@@ -558,6 +558,7 @@ public class ThePostJsonWithNetworkRetryAsyncMethod
558558 {
559559 ProjectToken = "test-api-key" ,
560560 MaxRetries = maxRetries ,
561+ FeatureFlagRequestMaxRetries = maxRetries ,
561562 InitialRetryDelay = TimeSpan . FromMilliseconds ( 1 ) ,
562563 MaxRetryDelay = TimeSpan . FromSeconds ( 30 )
563564 } ;
@@ -590,15 +591,74 @@ public async Task RetriesOnConnectionResetThenSucceeds()
590591 Assert . Equal ( 2 , handler . RequestCount ) ;
591592 }
592593
594+ [ Fact ]
595+ public async Task RetriesUntilSuccessAfterMultipleConnectionResetErrors ( )
596+ {
597+ var handler = new FakeRetryHttpMessageHandler ( ) ;
598+ handler . AddException ( new HttpRequestException ( "Connection reset" , new SocketException ( ( int ) SocketError . ConnectionReset ) ) ) ;
599+ handler . AddException ( new HttpRequestException ( "Connection reset" , new SocketException ( ( int ) SocketError . ConnectionReset ) ) ) ;
600+ handler . AddException ( new HttpRequestException ( "Connection reset" , new SocketException ( ( int ) SocketError . ConnectionReset ) ) ) ;
601+ handler . AddResponse ( HttpStatusCode . OK , new { flags = new { } } ) ;
602+ using var httpClient = CreateHttpClient ( handler ) ;
603+ var options = CreateOptions ( maxRetries : 3 ) ;
604+ var timeProvider = new FakeTimeProvider ( ) ;
605+
606+ var task = httpClient . PostJsonWithNetworkRetryAsync < FlagsApiResult > (
607+ FlagsUrl ,
608+ new { api_key = "test" , distinct_id = "user-1" } ,
609+ timeProvider ,
610+ options ,
611+ CancellationToken . None ) ;
612+
613+ for ( var i = 1 ; i <= 4 && ! task . IsCompleted ; i ++ )
614+ {
615+ await handler . WaitForRequestCountAsync ( i ) ;
616+ timeProvider . Advance ( TimeSpan . FromMilliseconds ( 50 ) ) ;
617+ }
618+
619+ var result = await task ;
620+
621+ Assert . NotNull ( result ) ;
622+ Assert . Equal ( 4 , handler . RequestCount ) ;
623+ }
624+
625+ [ Fact ]
626+ public async Task ThrowsAfterMaxRetriesWhenConnectionResetPersists ( )
627+ {
628+ var handler = new FakeRetryHttpMessageHandler ( ) ;
629+ handler . AddException ( new HttpRequestException ( "Connection reset" , new SocketException ( ( int ) SocketError . ConnectionReset ) ) ) ;
630+ handler . AddException ( new HttpRequestException ( "Connection reset" , new SocketException ( ( int ) SocketError . ConnectionReset ) ) ) ;
631+ handler . AddException ( new HttpRequestException ( "Connection reset" , new SocketException ( ( int ) SocketError . ConnectionReset ) ) ) ;
632+ handler . AddException ( new HttpRequestException ( "Connection reset" , new SocketException ( ( int ) SocketError . ConnectionReset ) ) ) ;
633+ using var httpClient = CreateHttpClient ( handler ) ;
634+ var options = CreateOptions ( maxRetries : 3 ) ;
635+ var timeProvider = new FakeTimeProvider ( ) ;
636+
637+ var task = httpClient . PostJsonWithNetworkRetryAsync < FlagsApiResult > (
638+ FlagsUrl ,
639+ new { api_key = "test" , distinct_id = "user-1" } ,
640+ timeProvider ,
641+ options ,
642+ CancellationToken . None ) ;
643+
644+ for ( var i = 1 ; i <= 4 && ! task . IsCompleted ; i ++ )
645+ {
646+ await handler . WaitForRequestCountAsync ( i ) ;
647+ timeProvider . Advance ( TimeSpan . FromMilliseconds ( 50 ) ) ;
648+ }
649+
650+ await Assert . ThrowsAsync < HttpRequestException > ( ( ) => task ) ;
651+ Assert . Equal ( 4 , handler . RequestCount ) ;
652+ }
653+
593654 [ Fact ]
594655 public async Task DoesNotRetryWhenFeatureFlagRequestMaxRetriesIsZero ( )
595656 {
596657 var handler = new FakeRetryHttpMessageHandler ( ) ;
597658 handler . AddException ( new HttpRequestException ( "Connection reset" , new SocketException ( ( int ) SocketError . ConnectionReset ) ) ) ;
598659 handler . AddResponse ( HttpStatusCode . OK , new { flags = new { } } ) ;
599660 using var httpClient = CreateHttpClient ( handler ) ;
600- var options = CreateOptions ( ) ;
601- options . FeatureFlagRequestMaxRetries = 0 ;
661+ var options = CreateOptions ( maxRetries : 0 ) ;
602662 var timeProvider = new FakeTimeProvider ( ) ;
603663
604664 await Assert . ThrowsAsync < HttpRequestException > ( ( ) =>
@@ -612,6 +672,31 @@ await Assert.ThrowsAsync<HttpRequestException>(() =>
612672 Assert . Equal ( 1 , handler . RequestCount ) ;
613673 }
614674
675+ #if NET8_0_OR_GREATER
676+ [ Fact ]
677+ public async Task DoesNotRetryOnUserCancellation ( )
678+ {
679+ var handler = new FakeRetryHttpMessageHandler ( ) ;
680+ using var cts = new CancellationTokenSource ( ) ;
681+ await cts . CancelAsync ( ) ;
682+ handler . AddException ( new TaskCanceledException ( "Operation was canceled." , null , cts . Token ) ) ;
683+ handler . AddResponse ( HttpStatusCode . OK , new { flags = new { } } ) ;
684+ using var httpClient = CreateHttpClient ( handler ) ;
685+ var options = CreateOptions ( ) ;
686+ var timeProvider = new FakeTimeProvider ( ) ;
687+
688+ await Assert . ThrowsAnyAsync < OperationCanceledException > ( ( ) =>
689+ httpClient . PostJsonWithNetworkRetryAsync < FlagsApiResult > (
690+ FlagsUrl ,
691+ new { api_key = "test" , distinct_id = "user-1" } ,
692+ timeProvider ,
693+ options ,
694+ cts . Token ) ) ;
695+
696+ Assert . Equal ( 1 , handler . RequestCount ) ;
697+ }
698+ #endif
699+
615700 [ Fact ]
616701 public async Task DoesNotRetryConnectionRefused ( )
617702 {
0 commit comments