zeromq.node icon indicating copy to clipboard operation
zeromq.node copied to clipboard

Support For multipart messages through XPUB/XSUB

Open esatterwhite opened this issue 10 years ago • 23 comments

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

esatterwhite avatar Mar 31 '15 04:03 esatterwhite

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'

ronkorving avatar Mar 31 '15 07:03 ronkorving

ZMQ_SNDMORE is 2

esatterwhite avatar Mar 31 '15 12:03 esatterwhite

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.

esatterwhite avatar Mar 31 '15 12:03 esatterwhite

why are you setting sockopt limits for xpub and xsub? Just curious

reqshark avatar Mar 31 '15 17:03 reqshark

so the proxy doesn't drop messages

esatterwhite avatar Mar 31 '15 18:03 esatterwhite

oh i've never had to set that it's never dropped messages for me

reqshark avatar Mar 31 '15 18:03 reqshark

either way i'll start looking into this issue today

reqshark avatar Mar 31 '15 18:03 reqshark

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.

kkoopa avatar Mar 31 '15 21:03 kkoopa

This was also somewhat of a duplicate of #274 which I opened a while back

esatterwhite avatar Apr 01 '15 03:04 esatterwhite

@esatterwhite, would you pls run:

$ pkg-config --modversion libzmq

and let me know what prints

reqshark avatar Apr 01 '15 19:04 reqshark

3.2.4

esatterwhite avatar Apr 01 '15 20:04 esatterwhite

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.

reqshark avatar Apr 01 '15 20:04 reqshark

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.

esatterwhite avatar Apr 01 '15 20:04 esatterwhite

fair enough.

keep the issue open, l'll dig further into this

reqshark avatar Apr 01 '15 20:04 reqshark

confirmed, same problem with 4.0.5

esatterwhite avatar Apr 01 '15 20:04 esatterwhite

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?

reqshark avatar Apr 02 '15 00:04 reqshark

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...

esatterwhite avatar Apr 02 '15 01:04 esatterwhite

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?

reqshark avatar Apr 02 '15 02:04 reqshark

I don't really know. How does, say, pyzmq handle this? Is there anything written about this in the zmq specification?

kkoopa avatar Apr 02 '15 16:04 kkoopa

I honestly have never used these features, so have no real thoughts on this. Sorry I can't be of more help.

ronkorving avatar Apr 03 '15 02:04 ronkorving

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?

esatterwhite avatar Apr 03 '15 02:04 esatterwhite

That sounds reasonable. PRs welcome.

kkoopa avatar Apr 03 '15 07:04 kkoopa

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));
});

brycekahle avatar Nov 01 '16 17:11 brycekahle