| Clean Architecture Toolkit for .NET | |||||
|
Clean Architecture Toolkit is a clean, modular architecture foundation for .NET applications. It embraces SOLID principles and focuses on maintainability, testability, and scalability through clear boundaries and pluggable design. |
|
||||
|
| HOME | MODULE OVERVIEW | DEMO | |
|||||
Plans for Cat.Resilience
Retry and circuit breaker decorators for calls to other services and integrations.
Status: not started. This plan collects what we know. The open questions need an answer before the build.
Contents
The idea
Calls to other services and to external systems fail now and then. A retry fixes a short glitch. A circuit breaker stops hammering something that is down. Decorators can add both to a handler without touching its code.
What we already know
From the root readme:
- External integrations, like an email provider or a storage account, live in the infrastructure project. The core never calls them. It sends a query or a command, and a handler talks to the integration.
- A call to another service goes through the API gateway.
- A slow or unavailable service must not bring down the caller.
From the demo plan:
- The demo case is retry and circuit breaker on the payment call. Today
FakePaymentProviderruns inside Orders and always answers, so there is nothing to protect. The decided answer is a separateCat.Demo.PaymentServicethat can fail on purpose. See the payment provider decision in Demo.md. Aspire ServiceDefaultsalready adds the standard resilience handler to everyHttpClient: retries, timeouts and a circuit breaker.- That overlaps with the future
Cat.ResilienceandCat.Telemetrymodules on purpose. CAT is a toolbox, so the developer picks what to use. - The future module must work in projects that do not use Aspire, and must not depend on Aspire or on
ServiceDefaults. - The rule: a project with Aspire uses
ServiceDefaultsand does not need this module. The module exists for projects without Aspire. The only reason to use both is to extendServiceDefaults, and then the extension can live in the module.
From the Aspire plan:
- The
CatalogPriceProvidergets its retries from theHttpClienthandler.Cat.Api.Clienthas to work together with this module.
From the module conventions:
- Handlers of
Cat.Commands,Cat.QueriesandCat.ServiceRequestsrun through decorators fromCat.Decorators.
Decisions and open questions
Decided
| Topic | Decision |
|---|---|
| Place | Decorators on handlers that call other services and integrations. |
| Independence | The module works without Aspire and never references it. |
| Overlap | With Aspire, use ServiceDefaults and skip this module. The module exists for projects without Aspire. It may also hold extensions of ServiceDefaults. |
| Demo stand-in | The payment call in the demo goes to a separate, flaky Cat.Demo.PaymentService, so the module has something to show. |
Open
- Foundation. Build on Polly and
Microsoft.Extensions.Resilience, or write our own small policies? Polly is the standard, but it is a dependency. - What gets decorated. Query and command handlers in the infrastructure, which is where integrations live? Or service requests?
- Policy. One default, named policies, or a policy per handler type? Declared by attribute, registration or configuration?
- Retry safety. A retried command may run twice. Only queries and idempotent commands may be retried. How does a handler say it is safe?
- Failures. What is a failure: an exception, a failed
ICatResponse, or certain error codes only? A 404 should not be retried. - Double retry. The
HttpClienthandler retries, and this decorator retries on top. Three times three is nine calls. How do we avoid that? - State of the breaker. Per process, per handler or per target? Shared across instances is probably not needed.
- Fallback and timeout. In scope, or only retry and circuit breaker?
- Visibility. Log retries and breaker changes. Metrics and traces depend on
Cat.Telemetry. - Testing. Tests need to move time.
TimeProvidersupport is needed.
Questions before building
- The module is for projects without Aspire. May we depend on Polly for that?
- Do you want the decorators on handlers, on
HttpClient, or both? - How should a command say it is safe to retry?
- Which failures count: exceptions, failed responses, or specific error codes?
- How do we prevent retries on retries with the
ServiceDefaultshandler? Should the module detect it, or do we document it? - Do we need fallbacks and timeouts in the first version?
- Where do policies live: attributes, code or
appsettings? - Does the module tell
Cat.Telemetryabout every retry and break? - Does
Cat.Api.Clientuse this module internally, or stay with theHttpClienthandler?