@@ -20,23 +20,29 @@ public RetryPolicy(OctoLogger log)
20
20
_log = log ;
21
21
}
22
22
23
- /// <summary>
24
- /// NEW: Minimal overload for HTTP calls that returns HttpResponseMessage so we can
25
- /// honor Retry-After and X-RateLimit-* headers for secondary rate limits.
26
- /// Usage: var resp = await _retryPolicy.HttpRetry(() => _httpClient.SendAsync(request));
27
- /// </summary>
23
+
28
24
public async Task < HttpResponseMessage > HttpRetry ( Func < Task < HttpResponseMessage > > func )
29
25
{
30
26
var policy = Policy
31
27
. HandleResult < HttpResponseMessage > ( r =>
32
28
{
33
29
var sc = ( int ) r . StatusCode ;
34
- if ( sc != 403 && sc != 429 ) return false ;
30
+ if ( sc is not 403 and not 429 )
31
+ {
32
+ return false ;
33
+ }
35
34
36
35
// Treat Retry-After or X-RateLimit-Remaining: 0 as secondary-rate limiting signals
37
- if ( r . Headers . RetryAfter != null ) return true ;
36
+ if ( r . Headers . RetryAfter != null )
37
+ {
38
+ return true ;
39
+ }
40
+
38
41
if ( r . Headers . TryGetValues ( "X-RateLimit-Remaining" , out var remain ) &&
39
- remain ? . FirstOrDefault ( ) == "0" ) return true ;
42
+ remain ? . FirstOrDefault ( ) == "0" )
43
+ {
44
+ return true ;
45
+ }
40
46
41
47
// Fallback: any 403/429 without headers still gets backoff per docs
42
48
return true ;
@@ -49,7 +55,10 @@ public async Task<HttpResponseMessage> HttpRetry(Func<Task<HttpResponseMessage>>
49
55
50
56
// 1) Honor Retry-After header
51
57
var ra = r . Headers . RetryAfter ? . Delta ;
52
- if ( ra . HasValue ) return ra . Value ;
58
+ if ( ra . HasValue )
59
+ {
60
+ return ra . Value ;
61
+ }
53
62
54
63
// 2) If remaining == 0, wait until reset
55
64
if ( r . Headers . TryGetValues ( "X-RateLimit-Remaining" , out var remainVals ) &&
@@ -59,7 +68,10 @@ public async Task<HttpResponseMessage> HttpRetry(Func<Task<HttpResponseMessage>>
59
68
{
60
69
var resetAt = DateTimeOffset . FromUnixTimeSeconds ( resetEpoch ) ;
61
70
var wait = resetAt - DateTimeOffset . UtcNow ;
62
- if ( wait > TimeSpan . Zero ) return wait ;
71
+ if ( wait > TimeSpan . Zero )
72
+ {
73
+ return wait ;
74
+ }
63
75
}
64
76
65
77
// 3) Otherwise: at least 1 minute, exponential thereafter (1,2,4,8,...)
@@ -78,7 +90,7 @@ public async Task<HttpResponseMessage> HttpRetry(Func<Task<HttpResponseMessage>>
78
90
$ "Retry-After={ r . Headers . RetryAfter ? . Delta ? . TotalSeconds } , " +
79
91
$ "X-RateLimit-Remaining={ TryHeader ( r , "X-RateLimit-Remaining" ) } , " +
80
92
$ "X-RateLimit-Reset={ TryHeader ( r , "X-RateLimit-Reset" ) } . " +
81
- $ "Body={ ( body ? . Length > 200 ? body . Substring ( 0 , 200 ) + "…" : body ) } ") ;
93
+ $ "Body={ ( body ? . Length > 200 ? body [ .. 200 ] + "…" : body ) } ") ;
82
94
} ) ;
83
95
84
96
var resp = await policy . ExecuteAsync ( func ) ;
0 commit comments