Support For multipart messages through XPUB/XSUB
This relates to #275. When trying to send multipart messages and XPUB/XSUB proxy, the proxy is forwarding message part where the binding is expecting an integer, and crashes.
problem can be reproduced with this snippet
TypeError: Second argument should be an integer
at Socket._flush (/home/esatterwhite/dev/js/zmq-275/node_modules/zmq/lib/index.js:524:19)
at Socket.send (/home/esatterwhite/dev/js/zmq-275/node_modules/zmq/lib/index.js:463:14)
at emit (events.js:106:17)
at Socket._flush (/home/esatterwhite/dev/js/zmq-275/node_modules/zmq/lib/index.js:510:19)
at _zmq.onReady (/home/esatterwhite/dev/js/zmq-275/node_modules/zmq/lib/index.js:193:12)
pub sub: there was an un expected error: Second argument should be an integer
So what is it, if not an integer? zmq.ZMQ_SNDMORE should already be an integer.
> var zmq = require('./');
undefined
> zmq.ZMQ_SNDMORE
2
> typeof zmq.ZMQ_SNDMORE
'number'
ZMQ_SNDMORE is 2
That isn't the problem. I've said it 3 times, The XPUB socket is trying to forward the additional parts of the message to _zmq.send
If I add a console.log to line 524, just before the actual send
console.log(this.type, args[0].toString(), args[1].toString() );
it outputs this
xpub test monday
copy the gist and try it.
why are you setting sockopt limits for xpub and xsub? Just curious
so the proxy doesn't drop messages
oh i've never had to set that it's never dropped messages for me
either way i'll start looking into this issue today
On a side note: If I remember correctly, the high water mark options don't do anything in this implementation, due to that polling loop that does the multiplexing. zeromq.node never blocks, even if the zmq specs say it should.
This was also somewhat of a duplicate of #274 which I opened a while back
@esatterwhite, would you pls run:
$ pkg-config --modversion libzmq
and let me know what prints
3.2.4
zmq 4.0 added support for multipart messages via the xpub / xsub socket types.
you said this in https://github.com/JustinTulloss/zeromq.node/issues/274 and I agree.
I think without 4+ you'll have trouble with multipart message support.
I was using 4.0 on my work computer where I found the problem. It's the same behavior, it was sending the second part of the message to _zmq.send rather than the flag.
I'll update this computer to 4+ and see if that corrects it, but It looks like their is a bug in zeromq.node either way.
fair enough.
keep the issue open, l'll dig further into this
confirmed, same problem with 4.0.5
looks like you're dropping messages in the xsub's onmessage callback.
I forked your gist and made the following adjustment to illustrate exactly where the message loss is:
https://gist.github.com/reqshark/38bb0d1c301025374d98#file-proxy-js-L42-L47
are we good to close this?
ah, ok. its not dropping messages. the messages are delivered in a single event rather than being forwarded as they are sent during the xpub <>xsub forwarding.
So am I reading the code right? zeromq.node is consolidating the message parts and sending them all at the end?
If I change the proxy to do xpub.send.call( xpub, arguments ) that works, but It seems like a bit of a work around. It looks like the xpub socket should deal with upstream multi parts in libzmq
I'm just trying to understand where the problem is. it seems like in the case of multipart messages through xpub/xsub, that the parts have to be consolidated, exploded one too many times...
I'm just trying to understand where the problem is.
I dont think there is a problem. if anything your use case is a good argument to enhance our JS proxy method, assuming the native zmq_proxy() operation does the same.
@ronkorving, @kkoopa what do you guys think?
I don't really know. How does, say, pyzmq handle this? Is there anything written about this in the zmq specification?
I honestly have never used these features, so have no real thoughts on this. Sorry I can't be of more help.
zmq.node and pyzmq do pretty much the same thing with multi-part messages. They collect all of the parts internally into an array before handing it off to the consumer. However, pyzmq's implementation was put in place before xpub/xsub, and both were implemented before there was multi-part message support for the socket types.
The primary use case for the xpub/xsub pairing is a dumb proxy. I don't think that it makes sense for the xsub socket to collect all of the parts before firing the message event, Instead it seems more intuitive for the message parts to be sent as they come, as it looks like xpub and xsub sockets in libzmq take care of consolidating the parts internally.
The zmq spec doesn't say much about how these types should handle multi-part messages, and the fact that the functionality for it didn't land until 4.0, it probably wasn't really thought out. There aren't any examples of it in the zquide either.
perhaps, at the least, could there be an option in zeromq.node to forward message parts on the xsub type as the come?
That sounds reasonable. PRs welcome.
I believe the problem is the message event spreads the multipart message into multiple arguments, whereas send expects an array for multipart messages. I solved it by doing the following:
xsub.on('message', function() {
xpub.send(Array.prototype.slice.call(arguments));
});