XRPLF / xrpl.js

A JavaScript/TypeScript API for interacting with the XRP Ledger in Node.js and the browser
https://xrpl.org/
1.2k stars 511 forks source link

isConnected() returns true but ledger events are no longer emitted #689

Closed jnr101 closed 4 years ago

jnr101 commented 8 years ago

Hello

I have just started using nodejs so my coding might not be correct. Nevertheless I've tried to keep it as simple and short as possible to show the issue:

My little test program is as follows:

const {RippleAPI} = require('ripple-lib');

const api = new RippleAPI({
    server: 'wss://s1.ripple.com' // Public rippled server hosted by Ripple, Inc.
});

api.on('ledger', ledger => {
  console.log(ledger.ledgerVersion);
});

setInterval(function() {
  if (! api.isConnected()) {
    console.log('No connection! Try to (re)connect every 10 seconds..');
    api.connect().then(() => {
      console.log('Connected..');
    }).catch(console.error);
  } else {
    console.log('Still connected..');
  };
}, 10 * 1000);

What it is supposed to do, if the connection gets lost, then after 10 seconds it should try to reconnect. I test the program by starting it, and then at some moment in time I restart my router which causes an network-interrupt. I expect that 'isConnected()' will return false. However I am getting the following output:

No connection! Try to (re)connect every 10 seconds..
Connected..
Still connected..
18347372
18347373
Still connected..
18347374
18347375
Still connected..
18347376
18347377
18347378
Still connected..
Still connected..
Still connected..
Still connected..
Still connected..
Still connected..
Still connected..
Still connected..
Still connected..
Still connected..
Still connected..
Still connected..
Still connected..

So after ledger 18347378 I reboot the router. Yet it still thinks it's connected and I am not getting any new ledger...Bug?

--- Want to back this issue? **[Post a bounty on it!](https://www.bountysource.com/issues/29992200-isconnected-returns-true-but-ledger-events-are-no-longer-emitted?utm_campaign=plugin&utm_content=tracker%2F323756&utm_medium=issues&utm_source=github)** We accept bounties via [Bountysource](https://www.bountysource.com/?utm_campaign=plugin&utm_content=tracker%2F323756&utm_medium=issues&utm_source=github).
clark800 commented 8 years ago

I think what's happening is that the websocket connection is not being closed because the socket didn't actually close. See here: http://stackoverflow.com/a/438243

Note that RippleAPI will automatically try to reconnect if the socket is actually closed, so you wouldn't need the code above.

I don't know if there's any way to fix this completely. We could have a heartbeat check, but you would still have the same behavior until the next heartbeat. It might be worth doing though.

jnr101 commented 8 years ago

Currently I am using the next code to detect non-responsiveness (my 'main' code triggers at each newly returned ledger from api.on('ledger'..), the function below stands on its own)

/*****************************************************************************
 * Check every 3 minutes if connection is alive by checking logfiles updated
 * within 90 seconds.
 *****************************************************************************/

setInterval(function() {
  exec("echo $(( $(date +%s) - $(stat -c %Y logs/* | sort -u | tail -1) ))", function (err, stdout, stderr) {
    if (err) throw err;

    if (parseFloat(stdout) > 90) {
      console.log("[" + timestamp() + "] Timing out! Reconnecting..");
      api.disconnect().then(() => {
        console.log("[" + timestamp() + "] Disconnected..");
        api.connect().then(() => {
          console.log("[" + timestamp() + "] Connected..");
        });
      }).catch(console.error);
    };
  });
},  3 * 60 * 1000);

This is of course very specific to the implementation of my program. I have seen it being triggered so once in a while, so it's worth having a mechanism like this in my code, otherwise it would have stopped working - waiting indefinitely on the next ledger. If it would be beneficial to have a generic solution like a heartbeat, maybe, yes. It would benefit me I guess, but I also have this work-around in place..

intelliot commented 6 years ago

@jnr101 I know it's been a long time, but I like this idea. Would you like to propose a PR?

jnr101 commented 4 years ago

@intelliot Seems that #1101 has solved this issue using a heartbeat 👍:-) I will close this issue