Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Axios Timeout behaviour #138

Open
adrys-lab opened this issue Jan 18, 2021 · 6 comments
Open

Axios Timeout behaviour #138

adrys-lab opened this issue Jan 18, 2021 · 6 comments
Labels
enhancement New feature or request

Comments

@adrys-lab
Copy link

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 ?

@anmol098
Copy link

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

@adrys-lab
Copy link
Author

@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
Copy link
Author

adrys-lab commented Jan 19, 2021

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.

@JustinBeckwith
Copy link
Owner

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.

@jmurty
Copy link

jmurty commented Apr 12, 2021

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
);

@kvv002
Copy link

kvv002 commented Sep 15, 2021

Hi @JustinBeckwith , any update on this enhancement?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

5 participants