Skip to content

support requeue header on nack - #102

Merged
jmglsn merged 1 commit into
stomp-php:masterfrom
gm-ghanover:feature/requeue
Nov 15, 2017
Merged

support requeue header on nack#102
jmglsn merged 1 commit into
stomp-php:masterfrom
gm-ghanover:feature/requeue

Conversation

@gm-ghanover

Copy link
Copy Markdown

as of rabbitmq 3.4, the NACK command supports the requeue header, necessary for DLX

Comment thread src/Protocol/Protocol.php Outdated
*
* @param \Stomp\Transport\Frame $frame
* @param string $transactionId
* @param bool $requeue

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please describe what this parameter is used for

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the requeue header on NACK will either requeue the message (default), or discard the message if false. if DLX is enabled for the queue, requeue=false will send the message to the deadletter exchange. see https://www.rabbitmq.com/dlx.html

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add a small note to the parameter doc, something like "Parameter are not available on all brokers".

@staabm

staabm commented Nov 8, 2017

Copy link
Copy Markdown
Member

DLX ?

@jmglsn

jmglsn commented Nov 8, 2017

Copy link
Copy Markdown
Member

The parameter needs to be part of the other protocol versions too, see failing tests here: https://travis-ci.org/stomp-php/stomp-php/jobs/298826443#L1335.

@staabm We need to check what should happen if this is set on the other protocols, they don't provide this functionality.
I would like to see an LogicException then.
In that case the default value must be null as true would not work.

@staabm

staabm commented Nov 8, 2017

Copy link
Copy Markdown
Member

We need to check what should happen if this is set on the other protocols, they don't provide this functionality.

in case the concept of "requeue" does only exist in certain protcols (or in certain msgqueues) we maybe should use a options array or a parameter object instead of a regular parameter.

@gm-ghanover

Copy link
Copy Markdown
Author

as far as i know, dead letter queue on activemq is handled via config in activemq.xml http://activemq.apache.org/message-redelivery-and-dlq-handling.html
i haven't tested on activemq, but i did test on older versions of rabbitmq (3.1.*), and the requeue header was ignored, as it wasn't added until 3.4

@jmglsn

jmglsn commented Nov 9, 2017

Copy link
Copy Markdown
Member

@staabm yes, we're ending up in many very specific parameters here. I think for the current version it would be ok just to add a new one. Next major release should reduce this again, I would like to use a parameter object then - it feels like a bigger change and might also reduce the parameters on other protocol functions.
For now I would add LogicException for any protocol that is not capable to cover this parameter. This makes sure that nobody uses the parameter and faces unreported data loss.
@gm-ghanover Thanks for checking this, would you like to add the exception for the other protocol implementations? Otherwise we could append this to your PR.

@gm-ghanover

Copy link
Copy Markdown
Author

Older versions of rabbitmq (and i assume activemq) that do not support the requeue header will go with their default behavior and requeue the message on NACK (unless otherwise configured at the service level), so I don't think there is any risk of data loss. The only issue that might arise is someone trying to use requeue=false on something which is not supported, and causing confusion when the message is not discarded (or sent to deadletter).

Throwing a LogicException on activemq could make sense to prevent that, but as far as I'm aware, there is no method for determining the version of rabbitmq that is in use, so there is no method to know if the header is supported or not.

@jmglsn jmglsn left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's a nice change, Thank you for your input!
If you like please add some small tests, otherwise we'll do this.

Please squash and we'll merge :)

Comment thread src/Protocol/Protocol.php Outdated
throw new StompException('Stomp Version 1.0 has no support for NACK Frames.');
}
$nack = $this->createFrame('NACK');
if ($requeue === false) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It should be possible to send requeue=>true too, when I read http://www.rabbitmq.com/amqp-0-9-1-reference.html#basic.nack.requeue it feels as if there is an way to configure the server to change the default behavior, not sure if this applies to the stomp plugin http://www.rabbitmq.com/stomp.html too.
But from my point of view it makes sense to allow true and false to be transmitted.
So the condition should be based on $requeue !== null.

Comment thread src/Protocol/Protocol.php Outdated
*
* @param \Stomp\Transport\Frame $frame
* @param string $transactionId
* @param bool $requeue

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add a small note to the parameter doc, something like "Parameter are not available on all brokers".

Comment thread src/StatefulStomp.php
* @return void
*/
public function nack(Frame $frame)
public function nack(Frame $frame, $requeue = null)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add the comment from Protocol here too.

{
if ($requeue !== null) {
throw new \LogicException(
'requeue header not supported by ActiveMQ. Please read ActiveMQ DLQ documentation.'

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why do you mention the docs here? is ActiveMQ DLQ a euqivalent feature as $requeue?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, though configured through activemq.xml, not something you can do individually with message headers.

Comment thread src/States/IStateful.php Outdated
* Not acknowledge consumption of a message from a subscription
*
* @param Frame $frame
* @param bool $requeue

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

here same doc, as requested above.

@gm-ghanover

Copy link
Copy Markdown
Author

i'll see what i can do about unit tests this weekend, but i don't have docker set up, so you may beat me to it.

@jmglsn

jmglsn commented Nov 14, 2017

Copy link
Copy Markdown
Member

Please squash your commits :)

@staabm

staabm commented Nov 14, 2017

Copy link
Copy Markdown
Member

Please squash your commits :)

@jmglsn in case you dont know. you can squash via github web ui

grafik

Comment thread src/Protocol/Protocol.php Outdated
*
* @param \Stomp\Transport\Frame $frame
* @param string $transactionId
* @param bool $requeue Requeue header supported on RabbitMQ >= 3.4

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shouldn't we implement it in the RabbitMq class then?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that would probably make more sense. should the base protocol then also throw the LogicException if $requeue !== null?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, I think so.

default $requeue to null

correct getNackFrame to match interface. I assume since Apoolo is built off ActiveMQ, it also doesn't support requeue header.

correct grammar in exception message

* requeue parameter doc
* handle requeue true or false

requeue unit tests

move requeue header processing to RabbitMQ

version check before creating frame
@jmglsn

jmglsn commented Nov 15, 2017

Copy link
Copy Markdown
Member

@staabm Was not sure about who is going to be author of those commits then, do you know that?

@staabm

staabm commented Nov 15, 2017

Copy link
Copy Markdown
Member

@jmglsn authorship will stay intact (not sure what happens in case you have commits of different users though).

I know it works when all commits are from the same user.

@jmglsn
jmglsn merged commit 8bde4a3 into stomp-php:master Nov 15, 2017
@jmglsn

jmglsn commented Nov 15, 2017

Copy link
Copy Markdown
Member

@gm-ghanover Thank you! Your change is included in https://github.com/stomp-php/stomp-php/releases/tag/4.3.1

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

Successfully merging this pull request may close these issues.

3 participants