in sdk/src/azure/core/az_http_policy_retry.c [153:223]
AZ_NODISCARD az_result az_http_pipeline_policy_retry(
_az_http_policy* ref_policies,
void* ref_options,
az_http_request* ref_request,
az_http_response* ref_response)
{
az_http_policy_retry_options const* const retry_options
= (az_http_policy_retry_options const*)ref_options;
int32_t const max_retries = retry_options->max_retries;
int32_t const retry_delay_msec = retry_options->retry_delay_msec;
int32_t const max_retry_delay_msec = retry_options->max_retry_delay_msec;
_az_RETURN_IF_FAILED(_az_http_request_mark_retry_headers_start(ref_request));
az_context* const context = ref_request->_internal.context;
bool const should_log = _az_LOG_SHOULD_WRITE(AZ_LOG_HTTP_RETRY);
az_result result = AZ_OK;
int32_t attempt = 1;
while (true)
{
_az_RETURN_IF_FAILED(
az_http_response_init(ref_response, ref_response->_internal.http_response));
_az_RETURN_IF_FAILED(_az_http_request_remove_retry_headers(ref_request));
result = _az_http_pipeline_nextpolicy(ref_policies, ref_request, ref_response);
// Even HTTP 429, or 502 are expected to be AZ_OK, so the failed result is not retriable.
if (attempt > max_retries || az_result_failed(result))
{
return result;
}
int32_t retry_after_msec = -1;
bool should_retry = false;
az_http_response response_copy = *ref_response;
_az_RETURN_IF_FAILED(
_az_http_policy_retry_get_retry_after(&response_copy, &should_retry, &retry_after_msec));
if (!should_retry)
{
return result;
}
++attempt;
if (retry_after_msec < 0)
{ // there wasn't any kind of "retry-after" response header
retry_after_msec = _az_retry_calc_delay(attempt, retry_delay_msec, max_retry_delay_msec);
}
if (should_log)
{
_az_http_policy_retry_log(attempt, retry_after_msec);
}
_az_RETURN_IF_FAILED(az_platform_sleep_msec(retry_after_msec));
if (context != NULL)
{
int64_t clock = 0;
_az_RETURN_IF_FAILED(az_platform_clock_msec(&clock));
if (az_context_has_expired(context, clock))
{
return AZ_ERROR_CANCELED;
}
}
}
}