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

[Feature] Experimental retry with fallback provider #88

Closed
wants to merge 2 commits into from

Conversation

iturricf
Copy link
Contributor

This should be explicitly enabled in order to work.

Closes #86

@iturricf iturricf self-assigned this Jul 26, 2023
transactions: Array<TransactionResponse>;
}

export class MultiJsonRpcProvider extends ethers.providers.Provider {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can make the implementation more transparent by passing directly the arguments to the provider method.
Consider this implementation (very similar to resolveInAttempts):

  executeWithRetries (methodName: string) {
    let attemptsMade = 0;
    const that = this;
    return async function wrappedProviderMethod(...args) {
      const provider = that.nextProvider();
      attemptsMade++;
      try {
        await provider[methodName](...args);
      } catch (error) {
        if (attemptsMade >= that.maxRetries) {
          throw new Error(`Failed to execute ${methodName} after ${attemptsMade} attempts. Last error: ${error}`);
        }
        else {
         await sleep(500)
         return wrappedProviderMethod(...args);
        }
      }
    }
  }

This would allow you to replace all methods with something like this:

  getNetwork(...args: any[]) {
    return this.executeWithRetries('getNetwork', args);
  }

Which in my opinion has some advantages. Namely:

  • it's more clear to the developer that the class is not modifying the behaviour of any of the methods
  • if the signature of any of the methods change, we don't need to update the signature of our MultiJsonRpcProvider class
  • MultiJsonRpcProvider doesn't need to know nothing about the underlying providers types, which is easier to mantain in the long run. We could even remove the types added above this class. This is a HUGE advantage IMO
  • We reduce a lot of duplicated code (right now all methods of the calss that only call a provider have the same code to call resolveInAttempts, if we were to add a new param to resolveInAttempts we would need to add this in most of the module's code
  • The class only has code in one method, allowing you to very easily undertand and modify what the class does. The fact that all other methods just call one "factory" function makes it very declarative IMO
  • By using sleep, we simplify the code by not needing to manually create and resolve the promise

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a way to get the type of the arguments of a function? 🤔 That way we could replace the ...any[] for the actual signature of the getNetwork function

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, you can, but it can be bothersome. We should evaluate the provider API first and see whether it suits our purposes before diving into it.

toBlock?: BlockTag;
}

function _isFrozen(object: any): boolean {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I really really really don't like having all this code copied over from ethers 🥶

@@ -0,0 +1,606 @@
"use strict";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be redundant with proper tsconfig.json values.

@scnale scnale closed this Nov 30, 2023
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

Successfully merging this pull request may close these issues.

Generic Relayer - Retry with fallback provider
3 participants