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

Websocket connection never cleaned up on connect() causing unrecoverable loop #1185

Closed nickewansmith closed 4 years ago

nickewansmith commented 4 years ago

It seems that if Connection _subscribeToLedger throws on connect() that Connection _ws is never cleaned up due to the cleanup code in connect() ->_ws.once('close') never actually being reached due to returning immediately on throw.

This can be reproduced in this way:

const RippleAPI = require('ripple-lib').RippleAPI;

const api = new RippleAPI({
  server: 'wss://s.altnet.rippletest.net:51233' 
});

const run = async () => {
  await api.connect();
  console.log('connected');
  await api.disconnect();
  console.log('disconnected');
  api.connection._subscribeToLedger = () => {
    throw new Error('Ripple Not Initialized');
  };
  setInterval(async () => {
    console.log('run interval connect');
    await api.connect().then(() => {
      console.log('interval connect success');
    }).catch((e) => {
      console.log(e, 'interval connect failure, stuck in loop, never connects');
      api.connection._subscribeToLedger = () => {};
    })
  }, 2500);
}

run()
  .catch((e) => {
    console.error('Caught', e);
  });
nickewansmith commented 4 years ago

Here is a proposed solution https://github.com/ripple/ripple-lib/pull/1186

FredKSchott commented 4 years ago

hey @nickewansmith, thanks for filing this! This logic is definitely tricky, so I want to make sure I understand your issue & the reproduction example and give some context:

Does that make sense? If I'm missing something / you are still seeing unexpected behavior, let me know.

nickewansmith commented 4 years ago

Hey, np @FredKSchott. What you've explained is correct, however, because the try/catch in question is run before the _ws.on('close') event gets a listener, calling _ws.close() in the disconnect() run in the catch never runs a cleanup listener for the close event, never cleaning up the connection and causing errors on each subsequent attempt to connect Websocket connection never cleaned up.

FredKSchott commented 4 years ago

Ah, you're right! Thanks for filling in that missing bit.

Okay, let's discuss solutions in #1186 since I think that PR is on the right track.