[rabbitmq-discuss] pika and node.amqp interop
Dan Tenenbaum
dtenenba at fhcrc.org
Sat Jan 22 20:56:04 GMT 2011
On Sat, Jan 22, 2011 at 2:46 AM, Michael Bridgen <mikeb at rabbitmq.com> wrote:
> Hi Dan,
>
>
> I am new to rabbitmq. I got the python "getting started" examples to
>> work just fine.
>> I would like to be able to send messages between node.js (using
>> node.amqp) and python/pika.
>>
> >
>
>> I can successfully receive a message in node.js using this code:
>>
>> [receiver - node.js]
>> var sys = require('sys');
>> var amqp = require('./amqp');
>>
>> var connection = amqp.createConnection({ host: 'localhost' });
>>
>> // Wait for connection to become established.
>> connection.addListener('ready', function () {
>> // Create a queue and bind to all messages.
>> // Use the default 'amq.topic' exchange
>>
>> var q = connection.queue('my-queue');
>> // Catch all messages
>> q.bind('#');
>>
>> // Receive messages
>> q.subscribe(function (message) {
>> // Print messages to stdout
>> sys.puts(sys.inspect(message));
>> });
>> });
>>
>> [sender - python/pika]
>> #!/usr/bin/env python
>> import pika
>>
>> connection = pika.AsyncoreConnection(pika.ConnectionParameters(
>> host='localhost'))
>> channel = connection.channel()
>>
>>
>> channel.basic_publish(exchange='',
>> routing_key='my-queue',
>> body='Hello World!')
>> print " [x] Sent 'Hello World!'"
>> connection.close()
>>
>
> You should be aware that node-amqp, at least Ryan's original and most forks
> of it, make some unorthodox choices for parameter defaults and behaviour,
> which to be fair are probably inherited from the EventMachine AMQP client.
>
> In particular, the exchange that's published or bound to, if none is given,
> is "amq.topic". This is directly at odds with AMQP, for which an empty
> exchange name means the "default exchange" defined in the specification;
> that is, route directly to the queue named in the routing key.
>
> So your example above is working by coincidence -- you don't need to bind
> the queue in the node.js code, since your Python code is effectively sending
> straight to the queue. I.e., the node.js code sets up
>
> (amq.topic) --"#"--> [ | | my-queue | | ]
>
> but the message sent in the Python code actually follows
>
> (default) --"my-queue"--> [ | | my-queue | | ]
>
>
> But I can't go the other way. I'm not sure that the message sent by
>> node.js is going anywhere. I've looked at the unit tests for node.amqp
>> (they all pass) but there is something I am missing, probably to do with
>> exchanges or something. I'd like to do something like this:
>>
>> [sender - node.js]
>> var sys = require('sys');
>> var amqp = require('./amqp');
>>
>> var connection = amqp.createConnection({ host: 'localhost' });
>>
>> // Wait for connection to become established.
>> connection.addListener('ready', function () {
>> // Create a queue and bind to all messages.
>> // Use the default 'amq.topic' exchange
>> connection.publish("my-queue", {random_key:"this is my message"});
>> connection.end();
>> });
>>
>> [receiver - python/pika]
>> #!/usr/bin/env python
>> import pika
>> import sys
>>
>> connection = pika.AsyncoreConnection(pika.ConnectionParameters(
>> host='localhost'))
>> channel = connection.channel()
>>
>> print ' [*] Waiting for messages. To exit press CTRL+C'
>>
>> def callback(ch, method, properties, body):
>> print body,
>> sys.stdout.flush()
>> channel.basic_consume(callback,
>> queue='my-queue',
>> no_ack=True)
>>
>> pika.asyncore_loop()
>>
>
> This way around (presuming there's a restart in-between runs), node.js
> sends to amq.topic, but nothing is bound there, so the message is discarded.
>
> You might try binding the queue, in the Python, to the exchange
> "amq.topic". You should probably also declare it.
>
> If you actually don't want to use "amq.topic", and you probably don't if
> you can help it, you might declare your own exchange and use that.
>
>
OK, I am trying this approach, with the following sender:
var sys = require('sys');
var amqp = require('./amqp');
var connection = amqp.createConnection({ host: 'localhost' });
// Wait for connection to become established.
connection.addListener('ready', function () {
// Create a queue and bind to all messages.
// Use the default 'amq.topic' exchange
var exchange = connection.exchange("my-exchange");
exchange.publish("my-queue", {random_key:"this is my message"});
connection.end();
});
and receiver:
#!/usr/bin/env python
import pika
import sys
connection = pika.AsyncoreConnection(pika.ConnectionParameters(
host='localhost'))
channel = connection.channel()
result = channel.queue_declare('my-queue')
channel.exchange_declare(exchange='my-exchange')
channel.queue_bind(exchange='my-exchange', queue=result.queue)
print ' [*] Waiting for messages. To exit press CTRL+C'
def callback(ch, method, properties, body):
print body,
sys.stdout.flush()
channel.basic_consume(callback,
queue='my-queue',
no_ack=True)
pika.asyncore_loop()
When I run the receiver, I get:
% python receiver.py
Traceback (most recent call last):
File "receiver.py", line 9, in <module>
result = channel.queue_declare('my-queue')
File "build/bdist.macosx-10.6-universal/egg/pika/spec.py", line 3003, in
queue_declare
File "build/bdist.macosx-10.6-universal/egg/pika/channel.py", line 187, in
_rpc
File "build/bdist.macosx-10.6-universal/egg/pika/connection.py", line 325,
in _rpc
File "build/bdist.macosx-10.6-universal/egg/pika/connection.py", line 301,
in send_method
File "build/bdist.macosx-10.6-universal/egg/pika/connection.py", line 295,
in send_frame
File "build/bdist.macosx-10.6-universal/egg/pika/codec.py", line 74, in
marshal
File "build/bdist.macosx-10.6-universal/egg/pika/spec.py", line 673, in
encode
TypeError: unsupported operand type(s) for &: 'str' and 'long'
What am I doing wrong?
Thanks very much for your help.
Dan
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.rabbitmq.com/pipermail/rabbitmq-discuss/attachments/20110122/485c1949/attachment.htm>
More information about the rabbitmq-discuss
mailing list