mirror of
https://github.com/abraunegg/onedrive
synced 2024-06-19 14:15:25 +02:00
* Handle curl exceptions and timeouts better with backoff/retry logic
This commit is contained in:
parent
cdad8631ec
commit
44576ea4ca
|
@ -5,6 +5,7 @@ import std.stdio, std.string, std.uni, std.uri, std.file;
|
|||
import std.array: split;
|
||||
import core.stdc.stdlib;
|
||||
import core.thread, std.conv, std.math;
|
||||
import std.algorithm.searching;
|
||||
import progress;
|
||||
import config;
|
||||
static import log;
|
||||
|
@ -629,8 +630,58 @@ final class OneDriveApi
|
|||
try {
|
||||
http.perform();
|
||||
} catch (CurlException e) {
|
||||
// Potentially Timeout was reached on handle error
|
||||
log.error("ERROR: There was a timeout in accessing the Microsoft OneDrive service - Internet connectivity issue?");
|
||||
// Parse and display error message received from OneDrive
|
||||
log.error("ERROR: OneDrive returned an error with the following message:");
|
||||
auto errorArray = splitLines(e.msg);
|
||||
string errorMessage = errorArray[0];
|
||||
|
||||
if (canFind(errorMessage, "Couldn't connect to server on handle")) {
|
||||
// This is a curl timeout
|
||||
log.error(" Error Message: There was a timeout in accessing the Microsoft OneDrive service - Internet connectivity issue?");
|
||||
// or 408 request timeout
|
||||
// https://github.com/abraunegg/onedrive/issues/694
|
||||
// Back off & retry with incremental delay
|
||||
int retryCount = 10000;
|
||||
int retryAttempts = 1;
|
||||
int backoffInterval = 1;
|
||||
int maxBackoffInterval = 3600;
|
||||
bool retrySucess = false;
|
||||
while (!retrySucess){
|
||||
backoffInterval++;
|
||||
log.vdebug(" Retry Attempt: ", retryAttempts);
|
||||
int thisBackOffInterval = retryAttempts*backoffInterval;
|
||||
if (thisBackOffInterval <= maxBackoffInterval) {
|
||||
Thread.sleep(dur!"seconds"(thisBackOffInterval));
|
||||
} else {
|
||||
Thread.sleep(dur!"seconds"(maxBackoffInterval));
|
||||
}
|
||||
try {
|
||||
http.perform();
|
||||
// no error from http.perform() on re-try
|
||||
log.log("Internet connectivity to Microsoft OneDrive service has been restored");
|
||||
retrySucess = true;
|
||||
} catch (CurlException e) {
|
||||
if (canFind(e.msg, "Couldn't connect to server on handle")) {
|
||||
log.error(" Error Message: There was a timeout in accessing the Microsoft OneDrive service - Internet connectivity issue?");
|
||||
// Increment & loop around
|
||||
retryAttempts++;
|
||||
}
|
||||
if (retryAttempts == retryCount) {
|
||||
// we have attempted to re-connect X number of times
|
||||
// false set this to true to break out of while loop
|
||||
retrySucess = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (retryAttempts >= retryCount) {
|
||||
log.error(" Error Message: Was unable to reconnect to the Microsoft OneDrive service after 10000 attempts lasting over 1.2 years!");
|
||||
throw new OneDriveException(408, "Request Timeout - HTTP 408 or Internet down?");
|
||||
}
|
||||
} else {
|
||||
// Some other error was returned
|
||||
log.error(" Error Message: ", errorMessage);
|
||||
}
|
||||
// return an empty JSON for handling
|
||||
return json;
|
||||
}
|
||||
|
||||
|
@ -665,6 +716,7 @@ final class OneDriveApi
|
|||
404 Not Found The requested resource doesn’t exist.
|
||||
405 Method Not Allowed The HTTP method in the request is not allowed on the resource.
|
||||
406 Not Acceptable This service doesn’t support the format requested in the Accept header.
|
||||
408 Request Time out Not expected from OneDrive, but can be used to handle Internet connection failures the same (fallback and try again)
|
||||
409 Conflict The current state conflicts with what the request expects. For example, the specified parent folder might not exist.
|
||||
410 Gone The requested resource is no longer available at the server.
|
||||
411 Length Required A Content-Length header is required on the request.
|
||||
|
@ -727,6 +779,12 @@ final class OneDriveApi
|
|||
log.vlog("OneDrive returned a 'HTTP 404 - Item not found' - gracefully handling error");
|
||||
break;
|
||||
|
||||
// 408 - Request Timeout
|
||||
case 408:
|
||||
// Request to connect to OneDrive service timed out
|
||||
log.vlog("Request Timeout - gracefully handling error");
|
||||
throw new OneDriveException(408, "Request Timeout - HTTP 408 or Internet down?");
|
||||
|
||||
// 409 - Conflict
|
||||
case 409:
|
||||
// Conflict handling .. how should we act? This only really gets triggered if we are using --local-first & we remove items.db as the DB thinks the file is not uploaded but it is
|
||||
|
|
|
@ -1453,9 +1453,11 @@ final class SyncEngine
|
|||
try {
|
||||
onedrive.downloadById(item.driveId, item.id, path, fileSize);
|
||||
} catch (OneDriveException e) {
|
||||
if (e.httpStatusCode == 429) {
|
||||
if ((e.httpStatusCode == 429) || (e.httpStatusCode == 408)) {
|
||||
// HTTP request returned status code 429 (Too Many Requests)
|
||||
// https://github.com/abraunegg/onedrive/issues/133
|
||||
// or 408 request timeout
|
||||
// https://github.com/abraunegg/onedrive/issues/694
|
||||
// Back off & retry with incremental delay
|
||||
int retryCount = 10;
|
||||
int retryAttempts = 1;
|
||||
|
@ -1467,7 +1469,7 @@ final class SyncEngine
|
|||
// successful download
|
||||
retryAttempts = retryCount;
|
||||
} catch (OneDriveException e) {
|
||||
if (e.httpStatusCode == 429) {
|
||||
if ((e.httpStatusCode == 429) || (e.httpStatusCode == 408)) {
|
||||
// Increment & loop around
|
||||
retryAttempts++;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue