Skip to content

Commit

Permalink
feat(HTTP): Retry failed HTTP requests with exponential backoff
Browse files Browse the repository at this point in the history
  • Loading branch information
mariocynicys committed Sep 9, 2022
1 parent 31129ee commit e66076a
Showing 1 changed file with 36 additions and 4 deletions.
40 changes: 36 additions & 4 deletions packager/file/http_file.cc
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,10 @@ namespace {
constexpr const char* kBinaryContentType = "application/octet-stream";
constexpr const int kMinLogLevelForCurlDebugFunction = 2;

// The number of times to retry requesting the server before we give up.
constexpr const int kNumRequestErrorRetries = 5;
constexpr const int kFirstRetryDelayMilliseconds = 1000;

size_t CurlWriteCallback(char* buffer, size_t size, size_t nmemb, void* user) {
IoCache* cache = reinterpret_cast<IoCache*>(user);
size_t length = size * nmemb;
Expand Down Expand Up @@ -209,9 +213,6 @@ bool HttpFile::Open() {
}
// TODO: Try to connect initially so we can return connection error here.

// TODO: Implement retrying with exponential backoff, see
// "widevine_key_source.cc"

base::WorkerPool::PostTask(
FROM_HERE, base::Bind(&HttpFile::ThreadMain, base::Unretained(this)),
/* task_is_slow= */ true);
Expand Down Expand Up @@ -333,8 +334,39 @@ void HttpFile::SetupRequest() {

void HttpFile::ThreadMain() {
SetupRequest();
CURLcode res;
int64_t sleep_duration = kFirstRetryDelayMilliseconds;

// Try sending the request multiple times if it fails.
for (int i = 0; i < kNumRequestErrorRetries; ++i) {
res = curl_easy_perform(curl_.get());

if (res == CURLE_HTTP_RETURNED_ERROR) {
long res_code = 0;
curl_easy_getinfo(curl_.get(), CURLINFO_RESPONSE_CODE, &res_code);
if (res_code == 408 || res_code == 429 || res_code >= 500) {
// FIXME: Should we clear download_cache_ and upload_cache_ here??
// Retry.
} else {
// Exponential backoff won't help for this response code, Stop retrying.
break;
}
} else if (res == CURLE_OPERATION_TIMEDOUT) {
// Retry.
} else {
// Either the request was successful or exponential backoff won't help.
// Stop retrying.
break;
}

// Exponential backoff.
if (i != kNumRequestErrorRetries - 1) {
base::PlatformThread::Sleep(
base::TimeDelta::FromMilliseconds(sleep_duration));
sleep_duration *= 2;
}
}

CURLcode res = curl_easy_perform(curl_.get());
if (res != CURLE_OK) {
std::string error_message = curl_easy_strerror(res);
if (res == CURLE_HTTP_RETURNED_ERROR) {
Expand Down

0 comments on commit e66076a

Please sign in to comment.