I have multiple nodejs servers located at different locations and i need to create a IPC over tcp sockets and i am using ZeroMQ for that . I need something like request/response or pub/sub in a async way with affirmation that message is sent , but seeing the node-zeromq modules i found all the send methods are synchronous and there is no way to confirm the message the sent through a callback
In short ,
I need something like socket.send(message,function(err,res){;});
but i found this socket.send(message)
Anyone knows how to do this using ZeroMQ or any other way i could IPC reliablly and with a affirmation as response ?
UPDATE : Ive found https://github.com/visionmedia/axon , Axon and its req/rep send method has a callback , would be great if anyone can shed more light about this .Suggestions ?
You could use the request/reply pattern instead of the pub/sub pattern with ZMQ. I believe when you make a request, there is a callback to listen for the response, as opposed to pub.send()...
zeromq.node does yet not support reply callbacks for the send message.
There is an issue discussed for several years now on GitHub where people argue that it would be a sensible modification.
I followed the suggestion on another question since I would really like to use Promises in the higher levels and therefore need callbacks for the REQ/REP mechanism. I.e. the callback is invoked from the 'message' event handler:
var socket, onRepHandler, replyCallback, send;
socket = zmq.socket('req');
onRepHandler = function (reply) {
// HACK
// This handler is a workaround until zeromq.node supports
// direct callback for REQ/REP:
// https://github.com/JustinTulloss/zeromq.node/issues/48
if (replyCallback) {
replyCallback(reply);
}
replyCallback = undefined;
};
socket.on('message', onRepHandler(msg));
socket.connect(address);
// Send method with callback
send = function (msg, repcb) {
if (replyCallback) {
throw new Error('Cannot send request before receiving reply of preceding request!');
}
replyCallback = repcb;
socket.send(msg);
}
It feels like a questionable hack but I hope the zeromq.node library gets updated eventually.
Related
I'm using ws version 7.4.0 and I would want to display a console log or perfom operations between the moment where the client is sending a message to the server and before the server fire the on event message.
To represent it:
webserver.on('example', function callback(msg){console.log(msg);}); //act before the call of callback
client------server---[here]---callback
The only way I see right now would be to use a "root" function before the callback of all my events like this:
function callback(msg){console.log(msg);}
webserver.on('example', function root(msg) {console.log('example msg'); callback(msg);});
I don't know if this is a real and/or good solution I really wish to write a clean and organized application.
If someone could give me some advise or a real solution? Thank you.
You could make a wrapper for all of your callbacks like so:
function makeCallback(fn) {
return function(msg) {
if (!environment.prod) console.log(msg);
fn(msg)
};
}
var myCallback = makeCallback(function (msg) {
// something
});
webserver.on('example', myCallback);
Or I think the better solution is to stream the requets into your stdout although I don't know the implications of using this method.
And I want to address the naming of your websocket server. Even though a web socket server is technically a web server, it only responds to the websocket protocol and naming it webserver could be misleading, I would recommend using the naming like in their documents wss.
I am using Node.js for emitting event to socket via socket.emit(eventName[, ...args][, ack]).
On client side, an Arduino, I'm using the SocketIoClient.h library (link: https://github.com/timum-viw/socket.io-client).
So the server is sending an event and a callback function as
socket.emit("event",function(x){
console.log(x);
})
which is received on the client side in payload field as
clientSocket.on("event",event);
void event(const char * payload, size_t length);
How can I call this callback function from the client side, which is supposed to be present in the payload?
If I understood you correctly, you are trying to use the acknowledgement mechanism offered by Socket.IO (I inferred this from the tags of your question).
For more details, refer to
https://socket.io/docs/server-api/#socket-emit-eventname-args-ack
Acknowledgment for socket.io custom event
This mechanism is specific to the Socket.IO library and therefore can't be used if you are not using it on both the client and the server sides.
As an alternative, I would suggest to dedicate a specific event to the acknowledgement you wish to have. In other words, when your client receives your event "event", it will send a "received" event to the server as acknowledgement along with the data your callback should be called with.
For instance on your server you would have:
socket.on("received", function (x) {
console.log(x); //Will display "Yay! Got it!"
});
socket.emit("event");
and on the client something like
socket.on("event", function () {
socket.emit("received", "Yay! Got it!");
});
(I'm not familiar with the C library you use but the point is the underlying logic).
We need to update the client side UI to indicate that a message fails to deliver. How do I have Socket.IO JS client call a custom callback directly when the message fails to deliver? For example, something like:
socket.emit("event", data).onError(myCallback);
I know Socket.IO provides the Ack mechanism to confirm delivery success. Therefore, one can set up a timer with a handler which calls the failure callback, if the ack is not called after a certain amount of time. But this doesn't seem to be the best way to do.
Also there is the error event provided by Socket.IO, but it doesn't come with info regarding which emit caused the error.
Unfortunately there's no way to get errors from callbacks, the only way is to indeed create your own timeout:
var timeoutId = setTimeout(timeoutErrorFn, 500);
var acknCallbackFn = function(err, userData){
clearTimeout(timeoutId)
//manage UserData
}
socket.emit('getUserData', acknCallbackFn);
Source of the code
And there's another issue about this, open
So for the time being you have to stick with your manual setTimeout.
Challenge:
I would like to use SailsJS, and be able to join a room, by means of socket.io, and receive unsolicited messages from this room, not just when one enters or leaves the room but also receive objects.
So several clients connect to the server.
Afterwards broadcast (initiated from the server) messages/objects to every room and thus everey connected socket in this room.
I maybe could just send every connected socket a message, but dearly would like a example on how to do this with SailsJS 0.10, and a elegant method in the SailsJS 0.10 way.
I am looking at : https://github.com/balderdashy/sailsChat, but I think this is to close to the models themselves, with like e.g: autosubscribe: ['destroy', 'update']
In my opinion this should be more loosely coupled, and not so tied to the model itself.
Thanks in advance!
I.
The purpose of the SailsChat example is to demonstrate how Sails JS resourceful pubsub can take a lot of hassle out of socket messaging when you are mainly concerned with sending messages about models. The fact that you can make a full-featured chat app in Sails with very little back-end code is what makes it impressive. For situations where resourceful pubsub is not appropriate--or if you just plain don't want to use it--Sails exposes lower-level methods on the sails.sockets namespace. The docs are pretty clear on how they work.
To join a socket to an arbitrary room, do sails.sockets.join(<socket>, <roomName>), where <socket> is either a raw socket (probably from req.socket or a socket ID).
To broadcast a message to all sockets in a room, do sails.sockets.broadcast(<roomName>, <data>).
These and more methods are described in detail in the Sails JS documentation.
I'm just starting with SailsJS, and already a big fan.
I need to find out if this is also scalable with e.g. Heroku or other flavors of SAAS providers, but seems not that hard.
So just a follow up on what I did with SailsJS 0.10:
Server-side:
Made a controller with the following:
join: function (req, res) {
if (req.isSocket === true) {
sails.sockets.join(req.socket, 'mysecretroom');
return res.send(200, 'joined');
}
return res.send(200);
},
sendToRoom: function( req, res ) {
if (req.isSocket === true ) {
sails.sockets.broadcast('mysecretroom', 'messageevent', {message:'Listen very carefully, I'll shall say this only once..!'});
}
return res.send(200);
}
Client-side:
io.socket.on('messageevent', function (data) {
console.log(data);
})
+1 kudos #sgress454!
Thanks!
I have a very limited knowledge about node and nob-blocking IO so forgive me if my question is too naive.
In order to return needed information in response body, I need to
Make a call to 3rd party API
Wait for response
Add some modifications and return JSON response with the information I got from API.
My question is.. how can I wait for response? Or is it possible to send the information to the client only when I received response from API (as far as I know, connection should be bidirectional in this case which means I won't be able to do so using HTTP).
And yet another question. If one request waits for response from API, does this mean than other users will be forced to wait too (since node is single-threaded) until I increase numbers of threads/processes from 1 to N?
You pass a callback to the function which calls the service. If the service is a database, for example:
db.connect(host, callback);
And somewhere else in the code:
var callback = function(err, dbObject) {
// The connection was made, it's safe to handle the code here
console.log(dbObject.status);
res.json(jsonObject, 200)
};
Or you can use anonymous functions, so:
db.connect(host, function(err, dbObject) {
// The connection was made, it's safe to handle the code here
console.log(dbObject.status);
res.json(jsonObject, 200)
});
Between the call and the callback, node handles other clients / connections freely, "non-blocking".
This type of situation is exactly what node was designed to solve. Once you receive the request from your client, you can make a http request, which should take a callback parameter. This will call your callback function when the request is done, but node can do other work (including serving other clients) while you are waiting for the response. Once the request is done, you can have your code return the response to the client that is still waiting.
The amount of memory and CPU used by the node process will increase as additional clients connect to it, but only one process is needed to handle many simultaneous clients.
Node focuses on doing slow I/O asynchronously, so that the application code can start a task, and then have code start executing again after the I/O has completed.
An typical example might make it clear. We make a call to the FB API. When we get a response, we modify it and then send JSON to the user.
var express = require('express');
var fb = require('facebook-js');
app.get('/user', function(req, res){
fb.apiCall('GET', '/me/', {access_token: access_token}, function(error, response, body){ // access FB API
// when FB responds this part of the code will execute
if (error){
throw new Error('Error getting user information');
}
body.platform = 'Facebook' // modify the Facebook response, available as JSON in body
res.json(body); // send the response to client
});
});