I’m having problems to reconnect to a websocket after the stream is interrupted.
I do not know the root cause why ths stream of data is interrupted. My VPS server is up and running at all time, i have internet access to it, there is another program that runs at the same time and does not have network issues.
But for each packet received I increment my counter i, and if i has not changed for more than 20 seconds, then I try to reconnect. But any code attempts have failed so far, it just loops and tries to reconnect.
Nodejs running on decent linux server. Memory or CPU usage at the time of disconnect is fine. Disconnections have no pattern, sometimes runs for 2 days without problems, sometimes disconnect 4 times per day. When the stream stops, the only way to restart is to exit my code and run it again, and it works immediately, so no problem on server side.
My reconnect code that runs every 20 sec (which is the same as my initial connect code, except for the extra line: const WebSocket = require(‘ws’);
//catch broken stream, if i is not changing, close and reconnect and alert through Telegram
if (i == prev_i) {
ws.terminate();
setTimeout(function() {
console.log('waiting to reconnect');
const ws = new WebSocket('wss://streamer.cryptocompare.com/v2?api_key=6f56....fe10');
ws.on('open', function open() {
ws.send('{"action": "SubAdd","subs": ["0~coineal~BTC~USDT"]}');
});
}, 10000);
console.log("Reconnecting to stream");
var strMessage = "Reconnecting to stream"
var message = "chat_id=" + strChatId + "&text=" + strMessage
var request = require('request');
request.post({
headers: {'content-type' : 'application/x-www-form-urlencoded'},
url: Url,
body: message
}, function(error, response, body){
});
}
prev_i = i;
edit 5.5.2020:
as per suggestion below, I’ve modified my code above from
const ws = new WebSocket(...
to
ws = new WebSocket(...
Today the stream dropped for the first time since the change. Unfortunately, instead of trying to reconnect in a loop like before, the code execution stopped with the console messages in attached picture. Line 120 is the line that I modified.
2
Answers
I see one problem with your code: the
ws
variable is shadowed.When you do
ws.terminate()
your are terminating the socket held by thews
variable in the scope that is in effect around the block of code you quoted. However, in the code you pass tosetTimeout
to create a new socket you doconst ws = new WebSocket(...]
. When you do this, you declare a new variable in the scope created by the anonymous function you pass tosetTimeout
. This variable has the same name as the one in the outer scope but is different from the one in the outer scope. When you assign to it, the outer scopews
is not affected. So the new socket is created, opened and then your code forgets it. So yes, your code will try reconnecting again.Just dropping the
const
and usingws = new WebSocket(...)
should work. Obviously, for this to work thews
variable defined in the outer scope cannot be declared withconst ws
. It has to be declared withlet ws
, or, not as good,var ws
.I would also recommend generally using a linter like
eslint
configured with a sensible set of rules.eslint
has rules to report shadowed variables and prevent shadowing errors.I would furthermore recommend using something like PWS rather than try to roll your own reconnection code. There are all kinds of edge cases with reconnecting sockets.
Might I suggest using a protocol on top of websockets? This will give you more freedom from these errors and ensure quality of service. One such protocol is MQTT.