Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for the reply-to header #36

Closed
cdion opened this issue Jan 6, 2016 · 1 comment
Closed

Support for the reply-to header #36

cdion opened this issue Jan 6, 2016 · 1 comment

Comments

@cdion
Copy link

cdion commented Jan 6, 2016

I'm trying to use this library to do RPC style calls over STOMP to RabbitMQ.

However, it appears that this library doesn't properly support the automatic subscriptions created by a SEND frame containing the reply-to header. I believe ActiveMQ also provides similar functionality in their STOMP adapter.

For a detailed overview of how this works in RabbitMQ see: https://www.rabbitmq.com/stomp.html, under the the heading: Temp Queue Destinations

Here is a brief description of the problem with an example:

I want to use STOMP to send a message from a client to a server, and receive a response from that server. The steps are:

  1. RPC server subscribes to receive messages from the client with this header:
{
  destination: '/queue/test'
}
  1. RPC client sends a message using the following header. The broker creates an exclusive, temporary, queue with an opaque name, and automatically subscribes the client to this queue.
{
  destination: '/queue/test',
  reply-to: '/temp-queue/test'
}
  1. The RPC server receives a message with the following headers:
{ subscription: '1',
  destination: '/queue/test',
  'message-id': 'T_1@@session-rZDaF8mwGFwIy8YjMERxuw@@1',
  redelivered: 'false',
  ack: 'T_1@@session-rZDaF8mwGFwIy8YjMERxuw@@1',
  receipt: '1',
  'reply-to': '/reply-queue/amq.gen-JKMuz5nr1sGWN0h_BzxGKw', // this is the temporary exclusive queue
  'content-length': 9 }
  1. RPC server does the RPC call and sends the reply to the client using the temp queue provided by the broker in the reply-to header in step 3:
{
  destination: '/reply-queue/amq.gen-JKMuz5nr1sGWN0h_BzxGKw'
}
  1. The client receives the reply, via the automatic subscription created by the broker in step 2, with the following headers:
{ subscription: '/temp-queue/test',
  destination: '/queue/amq.gen-UzS0B3cF65bo_a-ARv7uZg',
  'message-id': 'T_/temp-queue/test@@session-eBbX3tY5PqdlT4raf_3hvg@@2',
  redelivered: 'false',
  receipt: '2',
  'content-length': 14 }

At this point the node Client library is destroyed and raises the following error:

invalid subscription id /temp-queue/test

Because there is no registered subscription for that id in the client (it was registered automatically by the broker). This happens here:

https://github.com/gdaws/node-stomp/blob/master/lib/Client.js#L403-L410

I've tried manually creating a subscription with /temp-queue/test as the subscription id, but this is explicitly disallowed by the broker and results in a broker error that also destroys the client.

Would it be possible to change this library to support this use case? I'm not 100% sure what the API would look like.

One possibility would be to provide an onReply function in the options when calling Client#send. This could automatically register a subscription for the reply with the client, where subId === reply-to header. The handler can then be called once with the reply message, and the subscription removed automatically by the Client. This would be similar to the way message receipts work.

var options = {
 replyTo: '/temp-queue/test', // automatically adds reply-to to header, like receipts?
 onReply: function(message) {
    // handle the reply here
 }
}
client.send(headers, [options])

Open to ideas, and can probably help with a PR.

@gdaws
Copy link
Owner

gdaws commented Jan 11, 2016

The stompit library has supported RabbitMQ temp queue destinations since v0.22.0, but I agree with you that the library doesn't appear to support this feature, as the required method to use is undocumented and there's no relevant code example provided.

Automatic subscriptions created by a broker can be registered with the client by calling the Client#setImplicitSubscription method. This method should only be called once for each temporary queue destination you define. Automatic subscriptions cannot be cancelled and exist until the client disconnects.

In your example you would call this alternative subscription method once before or immediately after the first send, like for example:

client.setImplicitSubscription('/temp-queue/test', 'auto', function(error, message) {
    // find and call the reply callback
});

The second argument must have value of 'auto' to match the ack mode set by RabbitMQ.

When sending a request include the reply-to header in your send headers:

client.send({
  'destination': '/queue/test',
  'reply-to': '/temp-queue/test'
});

The stompit library cannot provide a request/response API useful for RPC. The problems of binding a reply callback to a request and how to encode/decode a request id in a message is for the user or another library to solve.

@gdaws gdaws closed this as completed Feb 7, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants