ethers.js: Manage provider timeouts

Hi Richard,

Is it possible to manage timeouts from the provider? I currently use this code to create a “retry provider” for certain status codes. Is it possible to do the same for timeouts?

import { JsonRpcProvider } from "ethers/providers";
import { Networkish } from "ethers/utils";
import { ConnectionInfo, poll } from "ethers/utils/web";

export class RetryProvider extends JsonRpcProvider {
  public attempts: number;

  constructor(
    attempts: number,
    url?: ConnectionInfo | string,
    network?: Networkish
  ) {
    super(url, network);
    this.attempts = attempts;
  }

  public perform(method: string, params: any) {
    let attempts = 0;
    return poll(() => {
      attempts++;
      return super.perform(method, params).then(
        result => {
          return result;
        },
        (error: any) => {
          if (
            (error.statusCode === 429 || error.statusCode > 499) &&
            attempts < this.attempts
          ) {
            return Promise.resolve(undefined);
          } else {
            return Promise.reject(error);
          }
        }
      );
    });
  }
}

We deal with this in particular a fair bit:

2019-12-08 13:03:36 error: Error: timeout at Timeout._onTimeout (/var/app/current/node_modules/ethers/utils/web.js:54:20) at ontimeout (timers.js:436:11) at tryOnTimeout (timers.js:300:5) at listOnTimeout (timers.js:263:5) at Timer.processTimers (timers.js:223:10)

About this issue

  • Original URL
  • State: closed
  • Created 5 years ago
  • Comments: 15 (6 by maintainers)

Commits related to this issue

Most upvoted comments

I think the error now contains enough extra detail about what timed out that debugging should be much easier, so I’m going to close this. If not though, please feel free to re-open.

Thanks! 😃

The latest beta version should include a lot more details on timeouts now. Let me know if it helps you. It includes the URL and request body now…

@krzkaczor interesting, it seems that doing this gets around it:

try {
  await myContract.execute(address, callbackData, { gasLimit: 4000000 });
} catch (e) {
  if (
    e
      .toString()
      .toLowerCase()
      .includes("timeout")
  ) {
    await sleep(60 * 1000); // sleep for extra minute after timeout
  } else {
    throw e;
  }
}

I believe this is the hard-coded timeout you are referring to: https://github.com/ethers-io/ethers.js/blob/master/src.ts/utils/web.ts#L44

I also agree that we should be able to easily configure this when we create the provider.