rabbit.js icon indicating copy to clipboard operation
rabbit.js copied to clipboard

Ability to ACK a single message

Open willyaranda opened this issue 11 years ago • 4 comments

When using a PUSH/WORKER scenario, if you receive a message on the Worker part, you can ack the worker socket to tell RabbitMQ that a message has been processed and can receive the next batch.

The pitfall is that if you configure the worker with a prefetch bigger than 1, you will always ack the first message received (that is saved always on the first position of the unacked array)

But, in a async environment, you may finish processing the second message received before the first one, but the ack will make the first one to be acked, not the message actually finished.

I would love to have a extended ack method that can accept the message payload (or a uniqueId) for acking that single message.

@squaremo , what do you think?

willyaranda avatar Oct 22 '14 10:10 willyaranda

Right, the WORKER socket assumes you're doing just one thing at a time, and scaling up by having more workers.

This discussion may be apposite: https://github.com/squaremo/rabbit.js/issues/48

The solution discussed there is to construct a future for each task, and pass that along with the payload to the next stage. Then you can iterate through the promises and ack things in order.

squaremo avatar Oct 27 '14 22:10 squaremo

I would love to have a extended ack method that can accept the message payload (or a uniqueId) for acking that single message.

Both of these are problematic: the first assumes no two payloads will ever be the same (uh-oh); the second requires some means of giving a buffer a unique ID, which is then required when acking it. I suppose it could be a property set on the buffer, but that seems kind of gross -- also, whatever you're passing it on to would have to know to tell you once it's done -- so you may as well give it a future or callback or whatever, rather than an ID.

squaremo avatar Nov 03 '14 21:11 squaremo

@squaremo I think messages received from your lib to Rabbit.JS internals has a deliveryTag (that is what you are using to ACK messages, based on https://github.com/squaremo/amqp.node/blob/master/lib/channel_model.js#L220-224 )

I think that you can send, along the message, the deliveryTag that message has. As I see [1] the readable.push method, I think this change will break the current API, as it allows only a Buffer or a String, and not an object, or two parameters.

[1] http://nodejs.org/api/stream.html#stream_readable_push_chunk_encoding

willyaranda avatar Nov 04 '14 10:11 willyaranda

I think that you can send, along the message, the deliveryTag that message has. As I see [1] the readable.push method, I think this change will break the current API, as it allows only a Buffer or a String

One can always set a property on the buffer or string -- it's JavaScript after all. But I don't like this solution, because the receiver has to know a very specific behaviour, which is to get the delivery tag from the buffer it's responding to, and somehow attach that to its answer. I'd rather there was a callback.

The library could help you out: maybe something like

var worker = rabbit.socker('WORKER');
worker.connect('jobs');
worker.on('data', function(job) {
  doSomethingAsync(job, worker.lastMessageAcker());
});

squaremo avatar Nov 09 '14 23:11 squaremo