1
0
mirror of https://github.com/musix-org/musix-oss synced 2024-12-24 11:13:18 +00:00
musix-oss/node_modules/google-gax/build/src/normalCalls/retries.js
2020-03-03 22:30:50 +02:00

132 lines
5.3 KiB
JavaScript

"use strict";
/**
* Copyright 2020 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
Object.defineProperty(exports, "__esModule", { value: true });
const status_1 = require("../status");
const googleError_1 = require("../googleError");
const timeout_1 = require("./timeout");
/**
* Creates a function equivalent to func, but that retries on certain
* exceptions.
*
* @private
*
* @param {GRPCCall} func - A function.
* @param {RetryOptions} retry - Configures the exceptions upon which the
* function eshould retry, and the parameters to the exponential backoff retry
* algorithm.
* @param {GRPCCallOtherArgs} otherArgs - the additional arguments to be passed to func.
* @return {SimpleCallbackFunction} A function that will retry.
*/
function retryable(func, retry, otherArgs) {
const delayMult = retry.backoffSettings.retryDelayMultiplier;
const maxDelay = retry.backoffSettings.maxRetryDelayMillis;
const timeoutMult = retry.backoffSettings.rpcTimeoutMultiplier;
const maxTimeout = retry.backoffSettings.maxRpcTimeoutMillis;
let delay = retry.backoffSettings.initialRetryDelayMillis;
let timeout = retry.backoffSettings.initialRpcTimeoutMillis;
/**
* Equivalent to ``func``, but retries upon transient failure.
*
* Retrying is done through an exponential backoff algorithm configured
* by the options in ``retry``.
* @param {RequestType} argument The request object.
* @param {APICallback} callback The callback.
* @return {GRPCCall}
*/
return (argument, callback) => {
let canceller;
let timeoutId;
let now = new Date();
let deadline;
if (retry.backoffSettings.totalTimeoutMillis) {
deadline = now.getTime() + retry.backoffSettings.totalTimeoutMillis;
}
let retries = 0;
const maxRetries = retry.backoffSettings.maxRetries;
// TODO: define A/B testing values for retry behaviors.
/** Repeat the API call as long as necessary. */
function repeat() {
timeoutId = null;
if (deadline && now.getTime() >= deadline) {
const error = new googleError_1.GoogleError('Retry total timeout exceeded before any response was received');
error.code = status_1.Status.DEADLINE_EXCEEDED;
callback(error);
return;
}
if (retries && retries >= maxRetries) {
const error = new googleError_1.GoogleError('Exceeded maximum number of retries before any ' +
'response was received');
error.code = status_1.Status.DEADLINE_EXCEEDED;
callback(error);
return;
}
retries++;
const toCall = timeout_1.addTimeoutArg(func, timeout, otherArgs);
canceller = toCall(argument, (err, response, next, rawResponse) => {
if (!err) {
callback(null, response, next, rawResponse);
return;
}
canceller = null;
if (retry.retryCodes.indexOf(err.code) < 0) {
err.note =
'Exception occurred in retry method that was ' +
'not classified as transient';
callback(err);
}
else {
const toSleep = Math.random() * delay;
timeoutId = setTimeout(() => {
now = new Date();
delay = Math.min(delay * delayMult, maxDelay);
const timeoutCal = timeout && timeoutMult ? timeout * timeoutMult : 0;
const rpcTimeout = maxTimeout ? maxTimeout : 0;
const newDeadline = deadline ? deadline - now.getTime() : 0;
timeout = Math.min(timeoutCal, rpcTimeout, newDeadline);
repeat();
}, toSleep);
}
});
}
if (maxRetries && deadline) {
const error = new googleError_1.GoogleError('Cannot set both totalTimeoutMillis and maxRetries ' +
'in backoffSettings.');
error.code = status_1.Status.INVALID_ARGUMENT;
callback(error);
}
else {
repeat();
}
return {
cancel() {
if (timeoutId) {
clearTimeout(timeoutId);
}
if (canceller) {
canceller.cancel();
}
else {
const error = new googleError_1.GoogleError('cancelled');
error.code = status_1.Status.CANCELLED;
callback(error);
}
},
};
};
}
exports.retryable = retryable;
//# sourceMappingURL=retries.js.map