I currently forced to create a new RabbitMQ connection every time a user loads a page on my website.
This is creating a new TCP connection every time. However, i'm trying to reduce the number of TCP connections i make to Rabbit with the NodeJS AMQP plug in. Here is what i have:
var ex_conn = get_connection(uri); //http:rabbitm.com
if(ex_conn == false) {
var tempConn = amqp.createConnection({
url: uri
});
connections.push({
host: uri,
obj: tempConn
});
}
else {
var tempConn = ex_conn.obj;
}
The issue i'm running into is that if i try to do:
tempConn.on('ready', function() {
});
Then the ready function does not get triggered. I'm assuming, that is because the ready call back was already defined and it is not going to be re triggered. What i'm looking to do is bind a new queue by doing:
tempConn.queu('', {});
Any thoughts on how to get around this issue is much appreciated.
thanks.
Related
With the following code i open a stream connection to the Binance crypto exchange:
let adress = 'wss://stream.binance.com:9443/ws/btcusdt#kline_1h';
const ws = new WebSocket(adress);
If i make this call for different crypto currencys then i have later a few streams open, i want to know how can i check the current open streams, is there something like a function or parameter where i can see for which currencys i have a open stream running?
because i also have the problem that it looks like streams are stopping sometimes and i dont have a good solution for checking which streams have stop and how to receonnect them. My idea is now to first find a way how to check which streams are running and then maybe if one streams is stop i will just send the connection request again.
In javascript there is a websocket events thing, so all you need is to
ws.onclose = function(event) {
ws = new WebSocket(adress);
//just reopen it
};
Or, for more safety, you can
ws.onclose = function(event) {
if (event.wasClean) {
ws = new WebSocket(adress);
} else {
console.log('Connection error!');
//or whatever u want
}
};
Sorry for this stupid styling, I'm newbie there
If you have your ws variable, then checking whether the websocket is open and alive is done with
if(ws && ws.readyState === 1){
// is opened
}
For other states of the websocket, see the docs.
If you want to receive push messages from the server, you need to keep the ws connection open. If not, you can close the ws after a query and reopen it then for another query. You should wait for the closed state ws.readyState === 3 before reopening.
If you need to keep all ws connections open, then you need a list of ws Objects. You push new objects to the list:
let ws_list = [] // global list of ws objects
let create_connection = function(url){
try{
ws_list.push(new WebSocket(url));
} catch(err){
console.log(err, url);
}
}
let do_something = function(){
for(let ws of ws_list){
// do something with the ws object
}
}
The setup
I am using the websockets/ws library to listen to a WSS feed. It works well, it's lightweight enough and it seems to be one of the fastest around (which is important).
I'm trying to differentiate between me programmatically closing the connection, and them closing it for whatever reason.
According to the docs, I can send a code (int) and a reason (string), both of which are sent to the on close event. But by all accounts, this functionality no longer exists.
Tests
Most codes throw a First argument must be a valid error code number error
Leaving it blank sends code = 1005 and an empty reason to the event
If I enter a code of 1005, I get the invalid error
If I enter a code of 1000, the event receives code = 1006 and still an empty reason (regardless of what I put)
^ tests are simple enough...
var WebSocket = require('ws');
var ws = new WebSocket(url);
ws.on('close', function(code, reason) {
console.log(code);
console.log(reason);
});
var code = 1234,
reason = 'whatever reason';
setTimeout(function() {
ws.close(code, reason);
}, 5000);
But...
I need to be able to tell if I've closed the connection, or if it was closed for another reason (connection lost, they closed it because of time limits, etc). Depending on the reason it was closed, I sometimes need to immediately reopen the connection, but only sometimes.
I can do something like...
_initWS(url) {
var ws = new WebSocket(url);
ws.on('open', function() {...});
ws.on('close', function(code, reason) {
ws = null; // Don't know if needed
ws = _initWS(url); // Reopen the connection, for ever and ever...
});
ws.on('message', funciton(msg) {...});
return ws;
}
var someFeed = _initWS(someURL);
... but since the code and reason are all but meaningless, this automatically restarts the connection regardless of why it was closed. This is great if the connection was lost or timed-out, but not so great if I want to close it programmatically...
someFeed.close(); // Connection immediately reopens, always and forever
Question(s)
How can I differentiate between different closes? I don't want to change the library code, because then I can't use npm install when I move my own code around. Can I override the close method within my own code?
Or is there an equally lightweight and lightning-fast library that has the functionality I'm looking for? I just need to be able to reliably send a unique code and/or reason, so I know when I'm trying to close it manually. I know that asking for recommendations is taboo, but there are too many libraries to test each one, and no benchmarks that I can find.
From the suggestion from #Bergi
_initWS(url) {
var ws = new WebSocket(url);
ws.didIClose = false; // This is the flag to set if I close it manually
ws.forceClose = function() {
ws.didIClose = true;
ws.close();
};
ws.on('open', function() {...});
ws.on('close', function(code, reason) {
if(!ws.didIClose) { // If I didn't close it, reopen
ws = null;
ws = _initWS(url);
}
});
ws.on('message', funciton(msg) {...});
return ws;
}
var someFeed = _initWS(someURL);
And then to use it...
someFeed.didIClose = true;
someFeed.close(); // Won't reopen the connection
Or, a bit cleaner...
someFeed.forceClose();
Edit #1
Modified solution to include the forceClose() method - requiring only one clean line of code to programmatically close it (instead of two).
How do I continuously check to see if there is an active connection to a specific url and port? I am able to preform the check initially on app launch by going with:
const net = require('net');
const testCon = new net.Socket();
testCon.connect('12.12.123.123:8000', function () {
// connected
});
testCon.on('disconnect', function () {
// not connected
});
How do I check if the connection is lost and reconnected. I didn't want to wrap it in a setInterval function. That seems hacky to me. There has to be a better way to accomplish this.
I had built interception calls in the socket.io file located under node_modules/socket.io/lib/client.js with version 1.3.7 (at least I think so, however I have to update to 1.4.5 because of other requirements). These changes allowed spoof information coming from the sender socket and they were done before continuing to send the data to the receiver socket.
Before (around 1.3.7), the method ran before sending a packet was the following:
Client.prototype.packet = function(packet, preEncoded, volatile){
var self = this;
var sockets = this.sockets[0]; //this helds the socket object
but now (1.4.5) socket.io changed its call to the following
Client.prototype.packet = function(packet, opts){
var sockets = this.sockets[0]; //gives undefined
I tried to look throughout the given objects but couldn't find the sockets of the receiver user.
Back in 1.3.7 I was able to effortlessly give properties to a socket object (e.g: socket.some-property = 1; in the .js file ran by nodejs in the root of the server) and later be able to get this some-property back in node_modules/client.js whenever the receiver got some packet so I could intercept the call but now it does not work and I would like to apply my old code to this new context in order for it all to function again.
var socketObject = {};
io.sockets.on('connection', function (client) {
socketObject[client.id] = {socket: client};
client.on('data', function (somedata) {
socketObject[client.id].data = someData;
});
client.on('disconnect', function() {
delete socketObject[client.id];
});
});
I have recently developed a web app using PeerJS, and am trying to add reconnect functionality.
Basically, my app works by someone creating a server that clients then connect to. The server person can control what the hosts are doing but its basic two way communication.
If a client disconnects they simply reconnect and it works normally. However if the server user refreshes the page, or their computer crashes then they need to be able to re-establish control over the clients.
The start of this is by regaining the original connection ID and peer api ID, which is fine and easy as they are stored in a database and assigned a unique ID the server user can use to query them. Then to enable the client to reconnect I do this upon close:
// connection is closed by the host involuntarily...
conn.on('close', function() {
// if the clients connection closes set up a reconnect request loop - when the host takes back control
// the client will auto reconnect...
connected = false;
conn = null;
var reconnect_timer = setInterval(function () {
console.log('reconnecting...'); // make a fancy animation here...
conn = peer.connect(connectionid, {metadata: JSON.stringify({'type':'hello','username':username})});
// upon connection
conn.on('open', function() { // if this fails need to provide an error message... DO THIS SOON
// run the connect function...
connected = true;
connect(conn);
});
// didnt connect yet
conn.on('error', function(err) {
connected = false;
});
if(connected === true) {
clearInterval(reconnect_timer);
}
}, 1000);
});
This appears to work, as on the server end the client looks like they have reconnected - the connect function has fired etc. However messages cant be sent between, and the client console says:
Error: Connection is not open. You should listen for the `open` event before sending messages.(…)
Where the 'open' event is shown as having been listened to above...
I hope this is clear - any help is appreciated :)
So in the end to create an auto reconnect script, I simply dealt with the client end of things, ensuring the server was set to the same api_key (for cloudservers) and key:
peer = new Peer(return_array.host_id, {key: return_array.api_key});
and then having the client, upon connection closing:
// connection is closed by the host involuntarily...
conn.on('close', function() {
// if the clients connection closes set up a reconnect request loop - when the host takes back control
// the client will auto reconnect...
peer.destroy(); // destroy the link
connected = false; // set the connected flag to false
conn = null; // destroy the conn
peer = null; // destroy the peer
// set a variable which means function calls to launchPeer will not overlap
var run_next = true;
// periodically attempt to reconnect
reconnect_timer = setInterval(function() {
if(connected===false && run_next===true) {
run_next = false; // stop this bit rerunning before launchPeer has finished...
if(launchPeer(false)===true) {
clearInterval(reconnect_timer);
} else run_next == true;
}
}, 1000);
});
Where launch peer will attempt to launch a new peer. To ensure continuity the new id from the client replaces the old id from the client and everything is a smooth takeover. The hardest part in the end was having the "setInterval" only fire once which is achieved (badly...) through use of boolean flags.
Thanks to anybody who read and thought how they could help :)