33using Polly . Retry ;
44using System . Net ;
55using System . Text ;
6+ using TeaPie . Testing ;
67using ResiliencePipeline = Polly . ResiliencePipeline < System . Net . Http . HttpResponseMessage > ;
78using RetryStrategy = Polly . Retry . RetryStrategyOptions < System . Net . Http . HttpResponseMessage > ;
89
@@ -11,14 +12,21 @@ namespace TeaPie.Http.Retrying;
1112internal interface IResiliencePipelineProvider
1213{
1314 ResiliencePipeline GetResiliencePipeline (
14- string nameOfBaseStrategy , RetryStrategy ? explicitlyOverridenStrategy , IReadOnlyList < HttpStatusCode > statusCodes ) ;
15+ string nameOfBaseStrategy ,
16+ RetryStrategy ? explicitlyOverridenStrategy ,
17+ IReadOnlyList < HttpStatusCode > statusCodes ,
18+ string ? retryUntilTestPassTestName = null ) ;
1519}
1620
17- internal class ResiliencePipelineProvider ( IRetryStrategyRegistry registry , ILogger < ResiliencePipelineProvider > logger )
21+ internal class ResiliencePipelineProvider (
22+ IRetryStrategyRegistry registry ,
23+ ILogger < ResiliencePipelineProvider > logger ,
24+ ITester testExecutor )
1825 : IResiliencePipelineProvider
1926{
2027 private readonly IRetryStrategyRegistry _retryStrategyRegistry = registry ;
2128 private readonly ILogger < ResiliencePipelineProvider > _logger = logger ;
29+ private readonly ITester _testExecutor = testExecutor ;
2230
2331 public static readonly ResiliencePipeline DefaultResiliencePipeline =
2432 ResiliencePipeline . Empty ;
@@ -27,14 +35,19 @@ internal class ResiliencePipelineProvider(IRetryStrategyRegistry registry, ILogg
2735 new ( ) { { string . Empty , DefaultResiliencePipeline } } ;
2836
2937 public ResiliencePipeline < HttpResponseMessage > GetResiliencePipeline (
30- string nameOfBaseRetryStrategy , RetryStrategy ? overridRetryStrategy , IReadOnlyList < HttpStatusCode > statusCodes )
38+ string nameOfBaseRetryStrategy ,
39+ RetryStrategy ? overridRetryStrategy ,
40+ IReadOnlyList < HttpStatusCode > statusCodes ,
41+ string ? retryUntilTestPassTestName = null )
3142 {
3243 var isBaseRetryStrategyAltered = false ;
3344 CheckAndResolveBaseRetryStrategy ( nameOfBaseRetryStrategy , out var finalRetryStrategy , out var nameOfFinalStrategy ) ;
3445 ApplyExplicitOverridesIfAny (
3546 overridRetryStrategy , ref finalRetryStrategy , ref nameOfFinalStrategy , ref isBaseRetryStrategyAltered ) ;
3647 ApplyRetryUntilStatusCodesConditionIfAny (
3748 statusCodes , ref finalRetryStrategy , ref nameOfFinalStrategy , ref isBaseRetryStrategyAltered ) ;
49+ ApplyRetryUntilTestPassConditionIfAny (
50+ retryUntilTestPassTestName , ref finalRetryStrategy , ref nameOfFinalStrategy , ref isBaseRetryStrategyAltered ) ;
3851
3952 LogUsageOfRetryStrategy ( nameOfFinalStrategy , finalRetryStrategy , isBaseRetryStrategyAltered ) ;
4053
@@ -50,7 +63,25 @@ private void ApplyRetryUntilStatusCodesConditionIfAny(
5063 if ( statusCodes . Any ( ) )
5164 {
5265 nameOfFinalStrategy = GetRetryUntilStatusCodesStrategyName ( statusCodes , nameOfFinalStrategy ) ;
53- finalRetryStrategy = GetRetryStrategy ( statusCodes , finalRetryStrategy ) ;
66+ finalRetryStrategy = GetRetryStrategyWithCondition (
67+ response => ! statusCodes . Contains ( response . StatusCode ) ,
68+ finalRetryStrategy ) ;
69+ altered = true ;
70+ }
71+ }
72+
73+ private void ApplyRetryUntilTestPassConditionIfAny (
74+ string ? testName ,
75+ ref RetryStrategy finalRetryStrategy ,
76+ ref string nameOfFinalStrategy ,
77+ ref bool altered )
78+ {
79+ if ( ! string . IsNullOrEmpty ( testName ) )
80+ {
81+ nameOfFinalStrategy = $ "{ nameOfFinalStrategy } +{ RetryingDirectives . RetryUntilTestPassDirectiveFullName } :{ testName } ";
82+ finalRetryStrategy = GetRetryStrategyWithCondition (
83+ response => ! _testExecutor . ExecuteTestSync ( testName , response ) ,
84+ finalRetryStrategy ) ;
5485 altered = true ;
5586 }
5687 }
@@ -120,12 +151,14 @@ private static ResiliencePipeline BuildPipeline(RetryStrategy retryStrategy)
120151 . AddRetry ( retryStrategy )
121152 . Build ( ) ;
122153
123- private static RetryStrategy GetRetryStrategy ( IReadOnlyList < HttpStatusCode > statusCodes , RetryStrategy baseRetryStrategy )
154+ private static RetryStrategy GetRetryStrategyWithCondition (
155+ Func < HttpResponseMessage , bool > shouldRetryPredicate ,
156+ RetryStrategy baseRetryStrategy )
124157 {
125158 var retryStrategyWithCondition = new RetryStrategy ( )
126159 {
127160 ShouldHandle = new PredicateBuilder < HttpResponseMessage > ( )
128- . HandleResult ( response => ! statusCodes . Contains ( response . StatusCode ) )
161+ . HandleResult ( shouldRetryPredicate )
129162 } ;
130163
131164 return MergeRetryStrategies ( baseRetryStrategy , retryStrategyWithCondition ) ;
0 commit comments