Last active
July 27, 2020 07:43
-
-
Save Frenchcooc/7c042b4e0467d592c703dc822178449e to your computer and use it in GitHub Desktop.
Handling retries client-side for Google Apps Script add-ons
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Handle retries when calling Apps Script functions, | |
// from the client-side (i.e. a browser). | |
// | |
// @usage: | |
// - google.script.run.withRetry().myFunction() // Will retry "myFunction" 2 times | |
// - google.script.run.withRetry(5).myFunction() // Will retry "myFunction" 5 times | |
// | |
// /!\ Known caveats. The method withUserObject(object) is not supported. | |
if (google && google.script && google.script.run) { | |
google.script.run.withRetry = function (maxRetries) { | |
return new (function () { | |
this._successHandler = null; | |
this._failureHandler = null; | |
this.withSuccessHandler = function (callback) { | |
this._successHandler = callback; | |
return this; | |
}; | |
this.withFailureHandler = function (callback) { | |
this._failureHandler = callback; | |
return this; | |
}; | |
function _runWithRetry(backendFunction, nRetries, successHandler, failureHandler, _arguments) { | |
let _run = google.script.run; | |
let _totalRetries = isNaN(nRetries) ? 0 : nRetries; | |
let _maxRetries = typeof maxRetries === "number" ? maxRetries : 2; | |
if (!_run[backendFunction]) { | |
throw new Error(backendFunction + " is not defined"); | |
} | |
if (successHandler) { | |
_run = _run.withSuccessHandler(successHandler); | |
} | |
_run = _run.withFailureHandler(function (err) { | |
if (_totalRetries < _maxRetries) { | |
return _runWithRetry(backendFunction, _totalRetries + 1, successHandler, failureHandler, _arguments); | |
} | |
if (failureHandler) { | |
return failureHandler(err); | |
} | |
}); | |
const _maximumBackoff = 32 * 1000; | |
const _randomMilliseconds = Math.round(Math.random() * 1000); | |
const _backoffTime = Math.min(Math.pow(2, _totalRetries - 2) * 1000 + _randomMilliseconds, _maximumBackoff); | |
const _executionDelay = _totalRetries > 0 ? _backoffTime : 0; | |
window.setTimeout(function () { | |
_run[backendFunction].apply(null, _arguments); | |
}, _executionDelay); | |
} | |
this._run = function () { | |
_runWithRetry(this._backendFunction, 0, this._successHandler, this._failureHandler, arguments); | |
}; | |
const _backendFunctions = []; | |
for (let key in google.script.run) { | |
if (key.indexOf("with") === 0) { | |
continue; | |
} | |
_backendFunctions.push(key); | |
} | |
for (let i = 0; i < _backendFunctions.length; i++) { | |
const functionName = _backendFunctions[i]; | |
this[functionName] = new Function( | |
'this._backendFunction = "' + functionName + '"; this._run.apply(this, arguments)' | |
); | |
} | |
})(); | |
}; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment