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

how to auto-retry after waiting pre-defined time for response #164

Open
appukuttan-shailesh opened this issue Feb 26, 2021 · 10 comments
Open

Comments

@appukuttan-shailesh
Copy link

I am using axios to make a GET request in my reactjs app. Here is a code snippet of how I am currently making this call:

signal = axios.CancelToken.source();
...
...
...
  getList() {
    const url = baseUrl + "/projects";
    const config = {
      cancelToken: this.signal.token,
      headers: { Authorization: "Bearer " + this.context.auth[0].token },
    };
    axios
      .get(url, config)
      .then((res) => {
        console.log(res);
        this.setState({
          collab_list: res.data,
        });
      })
      .catch((err) => {
        console.log("Error: ", err.message);
      });
  }

What I find is that my GET requests work well most of the time, but around one out of 10 times they get stalled and remain in the pending state for a long time. During this time if I refresh the page, and redo the GET request, it works fine and returns a response immediately. This is an issue that I am facing since some time and could be a problem involving the targer server (over which I have no control).

So what I would like to do is the following (based on what I have found to work when doing manually):

  • Make the GET request as with the code snippet above
  • Wait upto 5 seconds for the repsonse.
  • If there is no response within 5 seconds, cancel the previous request, and initiate a fresh GET request.
  • Repeat this upto N times. Else fail.

So basically what I wish to do is retry, upto N times, if there is no repsonse within 5 seconds each time.

I know that axios-retry can trigger retry on error codes, but not sure if it can do "wait for X seconds for response, else retry". Is this doable? Thanks for any help.

@KevinDanikowski
Copy link

KevinDanikowski commented Feb 28, 2021

use retryDelay https://stackoverflow.com/questions/56074531/how-to-retry-5xx-requests-using-axios#answer-64076585 and add a timeout to the request (not axios-retry specific)

@appukuttan-shailesh
Copy link
Author

appukuttan-shailesh commented Mar 1, 2021

If I am not wrong, retryDelay specifically deals with the delay between two successive retries. In my case I am happy to have this delay set to 0 ms (the default value I believe). With the timeout bit, I am finding it doesn't work properly (as seems to be the case with many people apparently - see here).

@KevinDanikowski
Copy link

Here is my solution for using a different non-axios library for requests, you can use it here if you're having issues:

  const res = this.requestor(url, {
    ...options,
    timeout: timeout * 1000
  })
  // NOTE: this is done because got doesn't do the timeout correctly, should only be
  // necessary for certain clients as failsafe
  const callTimeout = setTimeout(() => res.cancel(), this.config.callTimeout);

  const response = await res;
  clearTimeout(callTimeout);

  return response;

@appukuttan-shailesh
Copy link
Author

Thanks for proposing an alternative solution @KevinDanikowski. I am going to try this out.

@KevinDanikowski
Copy link

@appukuttan-shailesh sounds good, I would recommend doing research into canceling axios calls, cancel() may not be the correct command.

@Vinayjinugu-gep
Copy link

I am looking for a solution for this problem, @appukuttan-shailesh did you find any good solution for the problem mentioned?

@appukuttan-shailesh
Copy link
Author

Not really. I think the target server performance improved and I stopped getting these issues. So didn't really pursue this further. But I don't think I had arrived at a proper axios based solution.

@KrayzeeKev
Copy link

I'm just after the very simple behaviour of "retry on timeout". I can't work out how to make this happen. If the network is flaky, some requests just die. Axios eventually times out. This is not a 50x error. It's a timeout. I want to try a few times before giving up. I know that in 99 times out of 100, the second request will succeed. It seems oddly difficult to achieve this. The source SPECIFICALLY excludes network timeouts. Which is different. I'm talking about client-side axios timeouts. eg:
const ax = axios.create();
axiosRetry(ax, { retries: 3 } )
await ax.get( { url, timeout: 2000 } )

I want it to start the get, in 2 seconds, fail that, try again, 2 seconds later try again, 2 seconds later fail

@KrayzeeKev
Copy link

Found my solution:
retryCondition: err => err.code === 'ECONNABORTED' || axiosRetry.isNetworkOrIdempotentRequestError(err)

@Waschnick
Copy link

Waschnick commented Sep 21, 2023

Sadly this does not work currently with axios 1.4.0 or 1.5.0 and axios-retry 3.8.0. The issue is that even if retryCondition is true, for a timeout it does not retry. It works for non-timeout erros.

          AxiosError: timeout of 2000ms exceeded
              at RedirectableRequest.handleRequestTimeout (/Users/sebastian.waschnick/Projekte/ueberseehub/effi-baufred-api/node_modules/axios/lib/adapters/http.js:630:16)
              at RedirectableRequest.emit (node:events:513:28)
              at Timeout.<anonymous> (/Users/sebastian.waschnick/Projekte/ueberseehub/effi-baufred-api/node_modules/follow-redirects/index.js:169:12)
              at listOnTimeout (node:internal/timers:564:17)
              at processTimers (node:internal/timers:507:7)

What did the magic trick for me: shouldResetTimeout: true It looks like otherwise it just does no retry on timeout, as the timeout is still 0 (it needs to be reset).

    axiosRetry(axios, {
      retries: 3,
      shouldResetTimeout: true,
      retryCondition: (e) => {
        return isNetworkOrIdempotentRequestError(e) || e?.code === 'ECONNABORTED';
      },
      onRetry: function onRetry(retryCount, error, requestConfig) {
        console.info(`Retry #${retryCount} to '${requestConfig.url}' because of ${error.message}`);
        return;
      },
    });

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

No branches or pull requests

5 participants