retry-axios icon indicating copy to clipboard operation
retry-axios copied to clipboard

Axios Timeout behaviour

Open adrys-lab opened this issue 3 years ago • 6 comments

We did not find any information about how the timeout acts when retry behaviour comes up.

given

axios.post(path, body, {
    baseURL: ur;,
    timeout: 12000,
    raxConfig: {
      retry: 5,
      retryDelay: 500,
    },

is the timeout of 12sec apply for all the 5 retries ? so 12 sec for performing 5 possible requests ? or for each retry, the timeout is reset to 12sec ? being possibly 12sec * 5 attempts ?

can you please introduce this documentation in the main README ?

adrys-lab avatar Jan 18 '21 08:01 adrys-lab

@adrys-lab Use backoff : 'static' This will give static delay between retry. For the snippet you pasted. It will retry after 500ms

anmol098 avatar Jan 18 '21 12:01 anmol098

@anmol098 thanks for the backoff topic,

but i was talking about the general HTTP Timeout request when the server-side takes more than 12000 to respond.

My question is, if its a timeout for each retry, or by contrast, for ALL retries together.

adrys-lab avatar Jan 18 '21 15:01 adrys-lab

Is there a way to make the axios timeout NOT being reset to 0 for each retry ?

if we setup 10 seconds of timeout, we want to interpret it as a global value, so it is not used for each retry but for the whole request lifecycle.

adrys-lab avatar Jan 19 '21 09:01 adrys-lab

Yeah, there's no way to do that directly through retry-axios right now. The timeout is passed directly to Axios, and taken into account for each retry. You'd need to tune the retries variable to match the number you're looking for, otherwise you're going to get your timeout and the retry logic fighting with each other.

JustinBeckwith avatar Jan 19 '21 16:01 JustinBeckwith

Please consider adding a feature to restrict retries to the original request timeout. The competing axios-retry library has something along these lines under the shouldResetTimeout option.

In the meantime, I have implemented something workable but kludgy via a retriesStopAtTimeout option with following code, which I'll leave here in case it helps someone else:

const retryAxios = require("retry-axios");

const axiosClient = axios.create(config);

axiosClient.defaults.raxConfig = {
  instance: axiosClient,

  // Apply your default retry settings here..

  /**
   * HACK: Add and enforce option `retriesStopAtTimeout` which will prevent
   * retry requests after the original Axios timeout. For example, if the
   * timout was 2000, retry requests will only be sent within that 2 second
   * timeframe (though the final request may finish after that time)
   */
  retriesStopAtTimeout: true,
  shouldRetry: function enforceRetriesStopAtTimeout(err) {
    const raxConfig = retryAxios.getConfig(err);

    // Ensure max retries is always respected
    if (raxConfig.currentRetryAttempt >= raxConfig.retry) return false;

    // Respect 'retry-axios' decision not to retry
    if (!retryAxios.shouldRetryRequest(err)) {
      return false;
    }

    // Only abort retries at timeout cutoff if configured to do so
    if (!raxConfig.retriesStopAtTimeout) {
      return true;
    }

    // This delay calculation is adapted from 'retry-axios' index.ts
    let delay;
    if (raxConfig.backoffType === "linear") {
      delay = raxConfig.currentRetryAttempt * 1000;
    } else if (raxConfig.backoffType === "static") {
      delay = raxConfig.retryDelay;
    } else {
      delay = ((Math.pow(2, raxConfig.currentRetryAttempt) - 1) / 2) * 1000;
    }

    // Will the next retry request be sent before the retries cutoff?
    raxConfig.nextRetryAvailableTime =
      raxConfig.retriesStopAtTimeoutCutoff - Date.now() - delay;

    // Don't retry request if there is no time for it to complete
    if (raxConfig.nextRetryAvailableTime <= 0) {
      return false;
    }

    return true;
  },
};
retryAxios.attach(axiosClient);

/**
 * HACK: Store the cutoff time to apply if `retriesStopAtTimeout` is set
 * when the first request is sent.
 */
axiosClient.interceptors.request.use(
  function storeRetriesStopAtTimeoutCutoff(config) {
    const raxConfig = config.raxConfig || {};
    if (!raxConfig.retriesStopAtTimeoutCutoff) {
      raxConfig.retriesStopAtTimeoutCutoff = Date.now() + config.timeout;
    }
    return config;
  },
  undefined
);

jmurty avatar Apr 12 '21 11:04 jmurty

Hi @JustinBeckwith , any update on this enhancement?

kvv002 avatar Sep 15 '21 13:09 kvv002