using Polly; using Polly.CircuitBreaker; using Polly.Retry; namespace Kbx.Shared.Integrations; // Polly is intentionally limited to short-lived transient resilience. // Persistent retries are scheduled by Hangfire from durable integration state. public sealed class KbxPollyIntegrationPipeline { public ResiliencePipeline Build( int maxRetryAttempts, TimeSpan baseDelay, TimeSpan timeout, double failureRatio, TimeSpan samplingDuration, int minimumThroughput, TimeSpan breakDuration) { return new ResiliencePipelineBuilder() .AddCircuitBreaker(new CircuitBreakerStrategyOptions { ShouldHandle = static args => args.Outcome switch { { Exception: HttpRequestException } => PredicateResult.True(), { Result.FailureKind: KbxIntegrationFailureKind.Transient } => PredicateResult.True(), _ => PredicateResult.False(), }, FailureRatio = failureRatio, SamplingDuration = samplingDuration, MinimumThroughput = minimumThroughput, BreakDuration = breakDuration, }) .AddRetry(new RetryStrategyOptions { ShouldHandle = static args => args.Outcome switch { { Exception: HttpRequestException } => PredicateResult.True(), { Result.FailureKind: KbxIntegrationFailureKind.Transient } => PredicateResult.True(), _ => PredicateResult.False(), }, MaxRetryAttempts = maxRetryAttempts, Delay = baseDelay, BackoffType = DelayBackoffType.Exponential, UseJitter = true, }) .AddTimeout(timeout) .Build(); } }