Skip to content

Commit 2c72cd9

Browse files
authored
Fixing retry logic to not hit service when Retry-After header returned (#190)
1 parent 1bcf079 commit 2c72cd9

File tree

1 file changed

+24
-17
lines changed

1 file changed

+24
-17
lines changed

Source/HTTP/httpcall.cpp

+24-17
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,20 @@ bool http_call_should_retry(
244244
}
245245
if (call->traceCall) { HC_TRACE_INFORMATION(HTTPCLIENT, "HCHttpCallPerformExecute [ID %llu] delayBeforeRetry %lld ms", call->id, call->delayBeforeRetry.count()); }
246246

247+
// Remember result if there was an error and there was a Retry-After header
248+
if (call->retryAfterCacheId != 0 &&
249+
retryAfter.count() > 0 &&
250+
httpStatus > 400)
251+
{
252+
auto retryAfterTime = retryAfter + responseReceivedTime;
253+
http_retry_after_api_state state(retryAfterTime, httpStatus);
254+
auto httpSingleton = get_http_singleton(false);
255+
if (httpSingleton)
256+
{
257+
httpSingleton->set_retry_state(call->retryAfterCacheId, state);
258+
}
259+
}
260+
247261
if (remainingTimeBeforeTimeout < call->delayBeforeRetry + std::chrono::milliseconds(MIN_HTTP_TIMEOUT_IN_MS))
248262
{
249263
// Don't bother retrying when out of time
@@ -259,20 +273,6 @@ bool http_call_should_retry(
259273
}
260274
}
261275

262-
// Remember result if there was an error and there was a Retry-After header
263-
if (call->retryAfterCacheId != 0 &&
264-
retryAfter.count() > 0 &&
265-
httpStatus > 400)
266-
{
267-
auto retryAfterTime = retryAfter + responseReceivedTime;
268-
http_retry_after_api_state state(retryAfterTime, httpStatus);
269-
auto httpSingleton = get_http_singleton(false);
270-
if (httpSingleton)
271-
{
272-
httpSingleton->set_retry_state(call->retryAfterCacheId, state);
273-
}
274-
}
275-
276276
return true;
277277
}
278278

@@ -282,9 +282,12 @@ bool http_call_should_retry(
282282
bool should_fast_fail(
283283
_In_ http_retry_after_api_state apiState,
284284
_In_ HC_CALL* call,
285-
_In_ const chrono_clock_t::time_point& currentTime
285+
_In_ const chrono_clock_t::time_point& currentTime,
286+
_Out_ bool* clearState
286287
)
287288
{
289+
*clearState = false;
290+
288291
if (apiState.statusCode < 400)
289292
{
290293
return false;
@@ -293,6 +296,8 @@ bool should_fast_fail(
293296
std::chrono::milliseconds remainingTimeBeforeRetryAfterInMS = std::chrono::duration_cast<std::chrono::milliseconds>(apiState.retryAfterTime - currentTime);
294297
if (remainingTimeBeforeRetryAfterInMS.count() <= 0)
295298
{
299+
// Only clear the API cache when Retry-After time is up
300+
*clearState = true;
296301
return false;
297302
}
298303

@@ -339,13 +344,15 @@ void retry_http_call_until_done(
339344
http_retry_after_api_state apiState = httpSingleton->get_retry_state(retryContext->call->retryAfterCacheId);
340345
if (apiState.statusCode >= 400)
341346
{
342-
if (should_fast_fail(apiState, retryContext->call, requestStartTime))
347+
bool clearState = false;
348+
if (should_fast_fail(apiState, retryContext->call, requestStartTime, &clearState))
343349
{
344350
HCHttpCallResponseSetStatusCode(retryContext->call, apiState.statusCode);
345351
if (retryContext->call->traceCall) { HC_TRACE_INFORMATION(HTTPCLIENT, "HCHttpCallPerformExecute [ID %llu] Fast fail %d", retryContext->call->id, apiState.statusCode); }
346352
CompleteAsync(retryContext->outerAsyncBlock, S_OK, 0);
347353
}
348-
else
354+
355+
if( clearState )
349356
{
350357
httpSingleton->clear_retry_state(retryContext->call->retryAfterCacheId);
351358
}

0 commit comments

Comments
 (0)