minio
Version:
S3 Compatible Cloud Storage client
75 lines (72 loc) • 10.6 kB
JavaScript
import { pipeline } from "stream";
import { promisify } from "util";
const pipelineAsync = promisify(pipeline);
export async function request(transport, opt, body = null) {
return new Promise((resolve, reject) => {
const requestObj = transport.request(opt, response => {
resolve(response);
});
requestObj.on('error', reject);
if (!body || Buffer.isBuffer(body) || typeof body === 'string') {
requestObj.end(body);
} else {
pipelineAsync(body, requestObj).catch(reject);
}
});
}
const MAX_RETRIES = 10;
const EXP_BACK_OFF_BASE_DELAY = 1000; // Base delay for exponential backoff
const ADDITIONAL_DELAY_FACTOR = 1.0; // to avoid synchronized retries
// Retryable error codes for HTTP ( ref: minio-go)
export const retryHttpCodes = {
408: true,
429: true,
499: true,
500: true,
502: true,
503: true,
504: true,
520: true
};
const isHttpRetryable = httpResCode => {
return retryHttpCodes[httpResCode] !== undefined;
};
const sleep = ms => {
return new Promise(resolve => setTimeout(resolve, ms));
};
const getExpBackOffDelay = retryCount => {
const backOffBy = EXP_BACK_OFF_BASE_DELAY * 2 ** retryCount;
const additionalDelay = Math.random() * backOffBy * ADDITIONAL_DELAY_FACTOR;
return backOffBy + additionalDelay;
};
export async function requestWithRetry(transport, opt, body = null, maxRetries = MAX_RETRIES) {
let attempt = 0;
let isRetryable = false;
while (attempt <= maxRetries) {
try {
const response = await request(transport, opt, body);
// Check if the HTTP status code is retryable
if (isHttpRetryable(response.statusCode)) {
isRetryable = true;
throw new Error(`Retryable HTTP status: ${response.statusCode}`); // trigger retry attempt with calculated delay
}
return response; // Success, return the raw response
} catch (err) {
if (isRetryable) {
attempt++;
isRetryable = false;
if (attempt > maxRetries) {
throw new Error(`Request failed after ${maxRetries} retries: ${err}`);
}
const delay = getExpBackOffDelay(attempt);
// eslint-disable-next-line no-console
console.warn(`${new Date().toLocaleString()} Retrying request (attempt ${attempt}/${maxRetries}) after ${delay}ms due to: ${err}`);
await sleep(delay);
} else {
throw err; // re-throw if any request, syntax errors
}
}
}
throw new Error(`${MAX_RETRIES} Retries exhausted, request failed.`);
}
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJwaXBlbGluZSIsInByb21pc2lmeSIsInBpcGVsaW5lQXN5bmMiLCJyZXF1ZXN0IiwidHJhbnNwb3J0Iiwib3B0IiwiYm9keSIsIlByb21pc2UiLCJyZXNvbHZlIiwicmVqZWN0IiwicmVxdWVzdE9iaiIsInJlc3BvbnNlIiwib24iLCJCdWZmZXIiLCJpc0J1ZmZlciIsImVuZCIsImNhdGNoIiwiTUFYX1JFVFJJRVMiLCJFWFBfQkFDS19PRkZfQkFTRV9ERUxBWSIsIkFERElUSU9OQUxfREVMQVlfRkFDVE9SIiwicmV0cnlIdHRwQ29kZXMiLCJpc0h0dHBSZXRyeWFibGUiLCJodHRwUmVzQ29kZSIsInVuZGVmaW5lZCIsInNsZWVwIiwibXMiLCJzZXRUaW1lb3V0IiwiZ2V0RXhwQmFja09mZkRlbGF5IiwicmV0cnlDb3VudCIsImJhY2tPZmZCeSIsImFkZGl0aW9uYWxEZWxheSIsIk1hdGgiLCJyYW5kb20iLCJyZXF1ZXN0V2l0aFJldHJ5IiwibWF4UmV0cmllcyIsImF0dGVtcHQiLCJpc1JldHJ5YWJsZSIsInN0YXR1c0NvZGUiLCJFcnJvciIsImVyciIsImRlbGF5IiwiY29uc29sZSIsIndhcm4iLCJEYXRlIiwidG9Mb2NhbGVTdHJpbmciXSwic291cmNlcyI6WyJyZXF1ZXN0LnRzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB0eXBlICogYXMgaHR0cCBmcm9tICdub2RlOmh0dHAnXG5pbXBvcnQgdHlwZSAqIGFzIGh0dHBzIGZyb20gJ25vZGU6aHR0cHMnXG5pbXBvcnQgdHlwZSAqIGFzIHN0cmVhbSBmcm9tICdub2RlOnN0cmVhbSdcbmltcG9ydCB7IHBpcGVsaW5lIH0gZnJvbSAnbm9kZTpzdHJlYW0nXG5pbXBvcnQgeyBwcm9taXNpZnkgfSBmcm9tICdub2RlOnV0aWwnXG5cbmltcG9ydCB0eXBlIHsgVHJhbnNwb3J0IH0gZnJvbSAnLi90eXBlLnRzJ1xuXG5jb25zdCBwaXBlbGluZUFzeW5jID0gcHJvbWlzaWZ5KHBpcGVsaW5lKVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gcmVxdWVzdChcbiAgdHJhbnNwb3J0OiBUcmFuc3BvcnQsXG4gIG9wdDogaHR0cHMuUmVxdWVzdE9wdGlvbnMsXG4gIGJvZHk6IEJ1ZmZlciB8IHN0cmluZyB8IHN0cmVhbS5SZWFkYWJsZSB8IG51bGwgPSBudWxsLFxuKTogUHJvbWlzZTxodHRwLkluY29taW5nTWVzc2FnZT4ge1xuICByZXR1cm4gbmV3IFByb21pc2U8aHR0cC5JbmNvbWluZ01lc3NhZ2U+KChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICBjb25zdCByZXF1ZXN0T2JqID0gdHJhbnNwb3J0LnJlcXVlc3Qob3B0LCAocmVzcG9uc2UpID0+IHtcbiAgICAgIHJlc29sdmUocmVzcG9uc2UpXG4gICAgfSlcblxuICAgIHJlcXVlc3RPYmoub24oJ2Vycm9yJywgcmVqZWN0KVxuXG4gICAgaWYgKCFib2R5IHx8IEJ1ZmZlci5pc0J1ZmZlcihib2R5KSB8fCB0eXBlb2YgYm9keSA9PT0gJ3N0cmluZycpIHtcbiAgICAgIHJlcXVlc3RPYmouZW5kKGJvZHkpXG4gICAgfSBlbHNlIHtcbiAgICAgIHBpcGVsaW5lQXN5bmMoYm9keSwgcmVxdWVzdE9iaikuY2F0Y2gocmVqZWN0KVxuICAgIH1cbiAgfSlcbn1cblxuY29uc3QgTUFYX1JFVFJJRVMgPSAxMFxuY29uc3QgRVhQX0JBQ0tfT0ZGX0JBU0VfREVMQVkgPSAxMDAwIC8vIEJhc2UgZGVsYXkgZm9yIGV4cG9uZW50aWFsIGJhY2tvZmZcbmNvbnN0IEFERElUSU9OQUxfREVMQVlfRkFDVE9SID0gMS4wIC8vIHRvIGF2b2lkIHN5bmNocm9uaXplZCByZXRyaWVzXG5cbi8vIFJldHJ5YWJsZSBlcnJvciBjb2RlcyBmb3IgSFRUUCAoIHJlZjogbWluaW8tZ28pXG5leHBvcnQgY29uc3QgcmV0cnlIdHRwQ29kZXM6IFJlY29yZDxzdHJpbmcsIGJvb2xlYW4+ID0ge1xuICA0MDg6IHRydWUsXG4gIDQyOTogdHJ1ZSxcbiAgNDk5OiB0cnVlLFxuICA1MDA6IHRydWUsXG4gIDUwMjogdHJ1ZSxcbiAgNTAzOiB0cnVlLFxuICA1MDQ6IHRydWUsXG4gIDUyMDogdHJ1ZSxcbn1cblxuY29uc3QgaXNIdHRwUmV0cnlhYmxlID0gKGh0dHBSZXNDb2RlOiBudW1iZXIpID0+IHtcbiAgcmV0dXJuIHJldHJ5SHR0cENvZGVzW2h0dHBSZXNDb2RlXSAhPT0gdW5kZWZpbmVkXG59XG5cbmNvbnN0IHNsZWVwID0gKG1zOiBudW1iZXIpID0+IHtcbiAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlKSA9PiBzZXRUaW1lb3V0KHJlc29sdmUsIG1zKSlcbn1cblxuY29uc3QgZ2V0RXhwQmFja09mZkRlbGF5ID0gKHJldHJ5Q291bnQ6IG51bWJlcikgPT4ge1xuICBjb25zdCBiYWNrT2ZmQnkgPSBFWFBfQkFDS19PRkZfQkFTRV9ERUxBWSAqIDIgKiogcmV0cnlDb3VudFxuICBjb25zdCBhZGRpdGlvbmFsRGVsYXkgPSBNYXRoLnJhbmRvbSgpICogYmFja09mZkJ5ICogQURESVRJT05BTF9ERUxBWV9GQUNUT1JcbiAgcmV0dXJuIGJhY2tPZmZCeSArIGFkZGl0aW9uYWxEZWxheVxufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gcmVxdWVzdFdpdGhSZXRyeShcbiAgdHJhbnNwb3J0OiBUcmFuc3BvcnQsXG4gIG9wdDogaHR0cHMuUmVxdWVzdE9wdGlvbnMsXG4gIGJvZHk6IEJ1ZmZlciB8IHN0cmluZyB8IHN0cmVhbS5SZWFkYWJsZSB8IG51bGwgPSBudWxsLFxuICBtYXhSZXRyaWVzOiBudW1iZXIgPSBNQVhfUkVUUklFUyxcbik6IFByb21pc2U8aHR0cC5JbmNvbWluZ01lc3NhZ2U+IHtcbiAgbGV0IGF0dGVtcHQgPSAwXG4gIGxldCBpc1JldHJ5YWJsZSA9IGZhbHNlXG4gIHdoaWxlIChhdHRlbXB0IDw9IG1heFJldHJpZXMpIHtcbiAgICB0cnkge1xuICAgICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCByZXF1ZXN0KHRyYW5zcG9ydCwgb3B0LCBib2R5KVxuICAgICAgLy8gQ2hlY2sgaWYgdGhlIEhUVFAgc3RhdHVzIGNvZGUgaXMgcmV0cnlhYmxlXG4gICAgICBpZiAoaXNIdHRwUmV0cnlhYmxlKHJlc3BvbnNlLnN0YXR1c0NvZGUgYXMgbnVtYmVyKSkge1xuICAgICAgICBpc1JldHJ5YWJsZSA9IHRydWVcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBSZXRyeWFibGUgSFRUUCBzdGF0dXM6ICR7cmVzcG9uc2Uuc3RhdHVzQ29kZX1gKSAvLyB0cmlnZ2VyIHJldHJ5IGF0dGVtcHQgd2l0aCBjYWxjdWxhdGVkIGRlbGF5XG4gICAgICB9XG5cbiAgICAgIHJldHVybiByZXNwb25zZSAvLyBTdWNjZXNzLCByZXR1cm4gdGhlIHJhdyByZXNwb25zZVxuICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgaWYgKGlzUmV0cnlhYmxlKSB7XG4gICAgICAgIGF0dGVtcHQrK1xuICAgICAgICBpc1JldHJ5YWJsZSA9IGZhbHNlXG5cbiAgICAgICAgaWYgKGF0dGVtcHQgPiBtYXhSZXRyaWVzKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBSZXF1ZXN0IGZhaWxlZCBhZnRlciAke21heFJldHJpZXN9IHJldHJpZXM6ICR7ZXJyfWApXG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgZGVsYXkgPSBnZXRFeHBCYWNrT2ZmRGVsYXkoYXR0ZW1wdClcbiAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLWNvbnNvbGVcbiAgICAgICAgY29uc29sZS53YXJuKFxuICAgICAgICAgIGAke25ldyBEYXRlKCkudG9Mb2NhbGVTdHJpbmcoKX0gUmV0cnlpbmcgcmVxdWVzdCAoYXR0ZW1wdCAke2F0dGVtcHR9LyR7bWF4UmV0cmllc30pIGFmdGVyICR7ZGVsYXl9bXMgZHVlIHRvOiAke2Vycn1gLFxuICAgICAgICApXG4gICAgICAgIGF3YWl0IHNsZWVwKGRlbGF5KVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhyb3cgZXJyIC8vIHJlLXRocm93IGlmIGFueSByZXF1ZXN0LCBzeW50YXggZXJyb3JzXG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgdGhyb3cgbmV3IEVycm9yKGAke01BWF9SRVRSSUVTfSBSZXRyaWVzIGV4aGF1c3RlZCwgcmVxdWVzdCBmYWlsZWQuYClcbn1cbiJdLCJtYXBwaW5ncyI6IkFBR0EsU0FBU0EsUUFBUTtBQUNqQixTQUFTQyxTQUFTO0FBSWxCLE1BQU1DLGFBQWEsR0FBR0QsU0FBUyxDQUFDRCxRQUFRLENBQUM7QUFFekMsT0FBTyxlQUFlRyxPQUFPQSxDQUMzQkMsU0FBb0IsRUFDcEJDLEdBQXlCLEVBQ3pCQyxJQUE4QyxHQUFHLElBQUksRUFDdEI7RUFDL0IsT0FBTyxJQUFJQyxPQUFPLENBQXVCLENBQUNDLE9BQU8sRUFBRUMsTUFBTSxLQUFLO0lBQzVELE1BQU1DLFVBQVUsR0FBR04sU0FBUyxDQUFDRCxPQUFPLENBQUNFLEdBQUcsRUFBR00sUUFBUSxJQUFLO01BQ3RESCxPQUFPLENBQUNHLFFBQVEsQ0FBQztJQUNuQixDQUFDLENBQUM7SUFFRkQsVUFBVSxDQUFDRSxFQUFFLENBQUMsT0FBTyxFQUFFSCxNQUFNLENBQUM7SUFFOUIsSUFBSSxDQUFDSCxJQUFJLElBQUlPLE1BQU0sQ0FBQ0MsUUFBUSxDQUFDUixJQUFJLENBQUMsSUFBSSxPQUFPQSxJQUFJLEtBQUssUUFBUSxFQUFFO01BQzlESSxVQUFVLENBQUNLLEdBQUcsQ0FBQ1QsSUFBSSxDQUFDO0lBQ3RCLENBQUMsTUFBTTtNQUNMSixhQUFhLENBQUNJLElBQUksRUFBRUksVUFBVSxDQUFDLENBQUNNLEtBQUssQ0FBQ1AsTUFBTSxDQUFDO0lBQy9DO0VBQ0YsQ0FBQyxDQUFDO0FBQ0o7QUFFQSxNQUFNUSxXQUFXLEdBQUcsRUFBRTtBQUN0QixNQUFNQyx1QkFBdUIsR0FBRyxJQUFJLEVBQUM7QUFDckMsTUFBTUMsdUJBQXVCLEdBQUcsR0FBRyxFQUFDOztBQUVwQztBQUNBLE9BQU8sTUFBTUMsY0FBdUMsR0FBRztFQUNyRCxHQUFHLEVBQUUsSUFBSTtFQUNULEdBQUcsRUFBRSxJQUFJ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