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

Support several RPC URLs #59

Merged
merged 13 commits into from
Aug 14, 2018

Conversation

fvictorio
Copy link

Closes #28.

This PR allows configuring several URLs in the HOME_RPC_URL and FOREIGN_RPC_URL environment variables.

To do this, two things were necessary: creating a new web3 provider that accepts several URLs (see HttpListProvider) and creating a RpcUrlsManager service that, given a function, will try it with each available URL until one of them works. This service also centralizes the access to the URLs, instead of having process.env.HOME_RPC_URLs all over the code.


To test this, I created a simple express app that acts as a proxy and logs each request. Then I started two proxy apps that redirect everything to the port 8545 and two other that redirect to the port 8546, where I had two parity nodes running. Then I configured the bridge to use two of the proxies as home URLs and the other two as foreign URLs. Finally, I killed and restarted the proxies in several combinations while sending transactions to check that everything was working.

The code for this express proxy is:

const proxy = require('express-http-proxy')
const app = require('express')()

const { PORT_FROM, PORT_TO } = process.env

app.use('/', proxy(() => {
  console.log('Request')
  return `http://localhost:${PORT_TO}`
}))

app.listen(PORT_FROM)

Then, in four different terminals, I did:

PORT_FROM=8555 PORT_TO=8545 node index.js
PORT_FROM=8565 PORT_TO=8545 node index.js
PORT_FROM=8556 PORT_TO=8546 node index.js
PORT_FROM=8566 PORT_TO=8546 node index.js

And in the .env file I used:

HOME_RPC_URL=http://localhost:8555,http://localhost:8565
FOREIGN_RPC_URL=http://localhost:8556,http://localhost:8566

Add a RpcUrlsManager that, given the (comma separated) lists of home
and foreign RPC URLs, parses them and exposes them.

This does not change the behavior of the system, since only the first
URL is used.
This way is more explicit that only one of several possible URLs is
being used. Besides, ideally the full list of URLs should be used
everywhere.
@ghost ghost assigned fvictorio Aug 2, 2018
@ghost ghost added the review label Aug 2, 2018
@fvictorio
Copy link
Author

Two more things:

First, there's something pending. Right now, if all URLs fail, the request (or web3 method) will fail. But the original issue says that it should wait and retry after a while. This is easy to add using retry-promise, but first let's check that everything is fine here, since this PR is hard enough to review as it is.

Second, I think the provider could be useful in other projects, so maybe it could be a separate project published in NPM and we could use it from there. Are you OK with that?

Copy link
Collaborator

@akolotov akolotov left a comment

Choose a reason for hiding this comment

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

I think the provider could be useful in other projects, so maybe it could be a separate project published in NPM and we could use it from there. Are you OK with that?

Currently I see that the functionality is too tied with 'home' and 'foreign' items. What exactly are you suggesting to move to a separate project?

Copy link
Collaborator

@akolotov akolotov left a comment

Choose a reason for hiding this comment

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

Is my understanding correct and you in are trying to start every time with the first URL in the list even if was found that it does not response? Will it impact performance if we are trying to handle hundreds of transactions?
Does it make sense to remember last successful URL in order to start from it rather than the first element of the URL list?

@fvictorio
Copy link
Author

fvictorio commented Aug 2, 2018

Currently I see that the functionality is too tied with 'home' and 'foreign' items. What exactly are you suggesting to move to a separate project?

Sorry, I was referring to the web3 provider. I think it's not tied to anything, so it should be usable in any project that could benefit from fallback URLs. I actually already moved it to its own repository, mainly for testing it, since doing that requires installing some very specific devDependencies. If you are OK with this idea, I can publish it in npm and update this PR to use it.

Is my understanding correct and you in are trying to start every time with the first URL in the list even if was found that it does not response? Will it impact performance if we are trying to handle hundreds of transactions?
Does it make sense to remember last successful URL in order to start from it rather than the first element of the URL list?

No, I think both the RpcUrlManager and the provider are using the last URL that worked. Let me know if you think that's not working.

@akolotov
Copy link
Collaborator

akolotov commented Aug 2, 2018

I actually already moved it to its own repository.

If it is an open repo, could you send a link?

@fvictorio
Copy link
Author

Sure, I just created the repo here and is published in npm. There are several things that could be done to improve it (support more node versions, support browser usage), but it can be used here as it is.

@akolotov
Copy link
Collaborator

@rstormsf please take a look at this PR. Thanks!

Copy link

@vbaranov vbaranov left a comment

Choose a reason for hiding this comment

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

@fvictorio
There are some minor comments for future improvements:

  1. first of all, npm package http-list-provider is not included to PR yet. HttpListProvider is defined inside current repo
  2. README.md with an example of usage is missing in suggested npm pakage
  3. Description of how to test the utility is missing
  4. It is better to add launch and stop of ganache-cli to test script (or at least mention, that ganache-cli should be launched before a test)

const currentIndex = this.currentIndex // eslint-disable-line prefer-destructuring

if (retries === this.urls.length) {
callback(new Error('Request failed for all urls'))

Choose a reason for hiding this comment

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

@fvictorio @akolotov what if for some reasons all of the RPC endpoints are not accessible in a short-term period, in this case, send method will fail here. What if to increase the level of service availability? I mean, to try to reach all RPC endpoints again. Introduce retriesOuter is equal, let's, say 3 - how many times send will try to reach all RPC endpoints. If all those tries will fail, then the method will fail. What do you think?

Copy link
Collaborator

Choose a reason for hiding this comment

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

Thanks @vbaranov for the comment! Actually it was requested in the original issue (#28) and @fvictorio said (#59 (comment)) that is will added later after the review of main part of changes.

Choose a reason for hiding this comment

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

oh, I see. Nevertheless, the rest looks good to me

@fvictorio
Copy link
Author

@vbaranov Thanks for the comments. I added a commit to use the provider as a dependency. I also added a README to the repo.

Regarding the retry, I think we should create a separate issue and do it in another PR. The worst case scenario (all URLs fail) is not worse than what we have now (the single URL fails), so I think it's safe to merge this.

Copy link
Collaborator

@akolotov akolotov left a comment

Choose a reason for hiding this comment

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

So, let's merge this PR.
And please open a new issue to introduce retry for the list of URLs.

@fvictorio
Copy link
Author

@vbaranov I'm going to merge this, but any other comments regarding this are welcome.

@fvictorio fvictorio merged commit c24917a into develop Aug 14, 2018
@fvictorio fvictorio deleted the #28-ability-to-configure-several-rpc-failover-urls branch August 14, 2018 13:23
@ghost ghost removed the review label Aug 14, 2018
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.

4 participants