feat(resilience): add CSharpEssentials.Resilience package with modular policy system#36
Conversation
9c622d7 to
c0a1833
Compare
|
The architecture is solid — Must fix
Worth looking at Timeout tests use real
The circuit breaker The |
|
@senrecep thanks for the thorough review. Here's what I addressed:
README.MD API_REFERENCE.md §8 — added a deprecation note to the old Http resilience methods pointing to §9. SKILL.md — added a "When to use / When NOT to use" section and a key types reference table.
Timeout test flakiness — valid concern. Current tests use 1s timeout with 10s delay, which passes reliably on any CI. Deterministic testing via All tests passing (90/90). |
|
Good start overall — the struct design is clean and the Polly v8 pipeline ordering in Blocking: silent behavioral regression in The old implementation applied a default 30-second timeout when none was provided: // old
TimeSpan effectiveTimeout = timeout ?? TimeSpan.FromSeconds(30);The new one only adds a timeout if the caller explicitly passes one: // new
if (timeout.HasValue)
policy = policy.WithTimeout(timeout.Value);This is a silent change — callers who relied on the implicit timeout now get no timeout at all. That's a production risk. Either restore the default or document that it's an intentional breaking change. Blocking: breaking API change without a version bump
Everything else looks reasonable. Fix these two and it's good to go. |
|
@senrecep addressed both blocking issues: Default 30s timeout — restored. Backward-compatible return types — the old No Also added All tests passing (93 Resilience + 92 Http). |
|
Architecture is solid and the Result-first direction is correct —
README and API_REFERENCE list this error code, but no
Neither FallbackAction = async args => Outcome.FromResult(
await Result.TryAsync(() => fallbackAsync(args.Context.CancellationToken), HandleException))Same fix applies to the non-generic variant.
Delegate chain examples don't compile SKILL.md, README, and API_REFERENCE all show this pattern: await (() => _db.GetUser(id)).WithRetry(3).WithTimeout(TimeSpan.FromSeconds(5)).ExecuteAsync();There are no While you're at it
|
…eption support, fix docs
|
@senrecep addressed all four issues:
Delegate chain examples don't compile — removed the broken All tests passing (93/93). |
|
Getting close — the core logic is solid. Three more things before this ships: Quick Start examples don't compile Every policy.ExecuteAsync(() => _db.GetUser(id)) // ❌The method only accepts policy.ExecuteAsync(_ => _db.GetUser(id)) // ✅
var pipeline = _pipeline ?? ResiliencePipeline.Empty;One note: the |
|
@senrecep three more fixes: Quick Start examples don't compile — every
Note on All tests passing (93/93). |
|
Almost there. The fix was applied to // Lines ~77, ~98, ~117 — parameterless lambda, won't compile
.ExecuteAsync(() => _db.GetUser(id)) // ❌
.ExecuteAsync(_ => _db.GetUser(id)) // ✅
// Line ~97 — int passed to TimeSpan? parameter, won't compile
.WithCircuitBreaker(samplingDuration: 10) // ❌
.WithCircuitBreaker(minimumThroughput: 10) // ✅Everything else looks good to me. |
|
Fixed the remaining broken examples in Readme.MD — 3 ExecuteAsync(() => ...) → _ => ... and 1 samplingDuration: 10 → minimumThroughput: 10. All docs should compile clean now. |
What
CSharpEssentials.Resiliencepackage providing modular resilience policies: Retry, Timeout, Circuit Breaker, and Fallback.ResiliencePolicyandResiliencePolicy<T>base classes for composable policy chains with configurable options (ResilienceOptions).ResilienceFuncExtensionsandResilienceResultExtensionsfor fluent integration withResult<T>,Task<Result<T>>, andValueTask<Result<T>>pipelines.CSharpEssentials.Httpto consume the new Resilience package, removing inline resilience logic fromHttpClientResilienceExtensions..well-known/agent-skills/forcsharpessentials-resilience.Directory.Packages.props, CI workflows, andAPI_REFERENCE.md.Why
Resilience patterns (retry, timeout, circuit breaker, fallback) are critical for production-ready HTTP and service communication but are typically scattered across codebases as ad-hoc implementations. Centralizing these into a dedicated, composable package enables:
Result<T>functional pipelines without breaking the ROP flow.Impact
Resultextensions (Map,Bind,Then).CSharpEssentials.Httpretains its public API surface; the refactor is purely internal.Validation
dotnet build CSharpEssentials.slnx -nologodotnet test --filter CSharpEssentials.Tests.Resilience -nologo --no-builddotnet test --filter CSharpEssentials.Tests.Http -nologo --no-build