Web3.js: Improving of the error handling on reconnecting with a WebsocketProvider.

Created on 13 Apr 2019  路  15Comments  路  Source: ChainSafe/web3.js

Description

I was implementing simple connectivity check for websocket provider. I got it to work via error event listener, but even then it causes Infinitely reconnecting loop.

Expected behavior

Calling await web3.eth.net.isListening() should return true or false.

Actual behavior

If provider is not reachable it doesn't return anything and causes provider.on('error') event.

Steps to reproduce the behavior

  1. Import web3
  2. Create new instance of Web3 with provider address of wss://undefined
  3. Call await web3.eth.net.isListening()

...or use the gist below.

Error Logs

Gists

  1. Call await validateEndpointConnectivity()
  2. Note line 13 console.log('isListening', isListening) is never logged
  3. In console you'll get errors of reconnect attempts

https://gist.github.com/niklas-e/335fff457ee0352977e797a4f2e1c886

Versions

  • web3.js: 1.0.0-beta.50
  • nodejs: v10.15.3
  • browser: Chromium 73.0.3683.75
  • ethereum node: -
bug

All 15 comments

const isListening = await web3.eth.net.isListening()
console.log('isListening', isListening)

You need to implement it is using promises. like this:
web3.eth.net.isListening().then(console.log)

And I tested it and its working fine.

@princesinha19 that does not work in my environment. Would have been interesting if that worked, because awaiting promises work pretty much in the same way. Of course instead of then/catch you should use try...catch and return value.

@niklas-e Please check with promises. I think this error is due to async await only.

What do you mean? I already told you that it doesn't work. I tested it in my browser app and in addition in "clean" node.js stub.

Even though if it would be only async/await problem, it is a (probable) bug nevertheless.

I don't know why this is happening to you. But In my case, it is working properly. I am sure it's not a problem of web3.

web3.eth.net.isListening().then(function(result){
    console.log("Is Listening: ", result );
});

Result:-
screenshot

Did you try with unreachable endpoint, e.g. wss://non.existent.endpoint? Because that's when the error happens as mentioned in the repro steps. For me too it (await and then) does work perfectly when the endpoint is connected and listening.

Thanks for opening this issue! I'll test and fix this asap.

@niklas-e You implemented a reconnecting by your own right? I'm asking because Web3.js does have a reconnecting process already since some versions.

I've tested it with:

const checkConnection = () => {
  const web3 = new Web3(new Web3.providers.WebsocketProvider(`ws://127.0.0.1:8546`));
  web3.currentProvider.once('connect', () => { console.log('connected'); });
  web3.currentProvider.once('error', () => { console.log('error') });
};

checkConnection();

This should do the same as your code just without a Promise.

@nivida

@niklas-e You implemented a reconnecting by your own right? I'm asking because Web3.js does have a reconnecting process already since some versions.

Nope, I didn't implement custom reconnecting logic.

I've tested it with:

const checkConnection = () => {
  const web3 = new Web3(new Web3.providers.WebsocketProvider(`ws://127.0.0.1:8546`));
  web3.currentProvider.once('connect', () => { console.log('connected'); });
  web3.currentProvider.once('error', () => { console.log('error') });
};

checkConnection();

This should do the same as your code just without a Promise.

If that does do the same thing, I could implement the promise on those event listeners, because I do need the return value. I can try that later today.

My scenario is basically this:

  1. User can insert own endpoint
  2. Validate endpoint connectivity before saving the custom endpoint and setting it as current provider
  3. If the custom endpoint is unreachable, don't save it and inform user it's not reachable

Isn't it a bug either way if isListening crashes and doesn't return anything?

Yes, then you could use my example. No there isn't an issue with isListening I've tested it and it worked without a problem.

@nivida after all, I didn't have a chance to test this until now.

With the event listeners I end up in the same situation as with the isListening approach. On failed connections it will trigger infinite loop of reconnects. Though I can see this effect only on browser, because I'm not sure which error events it's emitting, so I cannot listen to them in node.js.

Is there a way to disable reconnection and/or destroy web3 or provider instance? I think it would be good enough solution for now.

image

I also tested more isListening and it just does not work on failed connections. I never get false as the return value, because it crashes. It doesn't even go to catch. Could you try to run the gist below as is. If it does work in your environment, I'm interested in what kind of env you have.

https://gist.github.com/niklas-e/64df35b43a389b549cf212794d71d5a5

@niklas-e Hmm this would explain a bug I've been chasing in one of my own products.
I'm using beta37 so this is probably just an edge case that wasn't being caught.
Good catch!
So it looks like this isn't bubbling up, ergo the catch is not being called.

I'll examine the code and get back with you if I see anything.

As for the comment earlier from @princesinha19 about using await vs promises. These are identical on the browser. async/await are just syntactic sugar, unless you're using es5 as a build target.

@nivida
https://github.com/ethereum/web3.js/blob/1.0/packages/web3-providers/src/providers/WebsocketProvider.js

line 60 is the cause of this. You're returning after a reconnect without bubbleing the error code and giving them a chance to override. For a connection refused you cannot know if this is a typo in the url or some other issue server side that will be resolved soon. I'd recommend you add auto-reconnect as an option to be passed into the constructor, instead of being the default.

Otherwise just don't auto-reconnect and let the user handle that condition in their own error handling code.

Was this page helpful?
0 / 5 - 0 ratings