"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.request = request;
exports.requestWithRetry = requestWithRetry;
var _stream = require("stream");
var _util = require("util");
const pipelineAsync = (0, _util.promisify)(_stream.pipeline);
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 = 1;
const BASE_DELAY_MS = 100; // Base delay for exponential backoff
const MAX_DELAY_MS = 60000; // Max delay for exponential backoff

// Retryable error codes for HTTP ( ref: minio-go)
const retryHttpCodes = {
  408: true,
  429: true,
  499: true,
  500: true,
  502: true,
  503: true,
  504: true,
  520: true
};
exports.retryHttpCodes = retryHttpCodes;
const isHttpRetryable = httpResCode => {
  return retryHttpCodes[httpResCode] !== undefined;
};
const sleep = ms => {
  return new Promise(resolve => setTimeout(resolve, ms));
};
const getExpBackOffDelay = (retryCount, baseDelayMs, maximumDelayMs) => {
  const backOffBy = baseDelayMs * (1 << retryCount);
  const additionalDelay = Math.random() * backOffBy;
  return Math.min(backOffBy + additionalDelay, maximumDelayMs);
};
async function requestWithRetry(transport, opt, body = null, maxRetries = MAX_RETRIES, baseDelayMs = BASE_DELAY_MS, maximumDelayMs = MAX_DELAY_MS) {
  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, baseDelayMs, maximumDelayMs);
        // 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,[encoded data, 8496 characters]