-
-
Notifications
You must be signed in to change notification settings - Fork 9.6k
[Messenger] No need for retry to require SentStamp #32053
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
[Messenger] No need for retry to require SentStamp #32053
Conversation
48f5d21
to
675eb85
Compare
675eb85
to
0034dee
Compare
@@ -150,7 +148,7 @@ private function handleMessage(Envelope $envelope, ReceiverInterface $receiver, | |||
|
|||
// add the delay and retry stamp info + remove ReceivedStamp | |||
$retryEnvelope = $envelope->with(new DelayStamp($delay)) | |||
->with(new RedeliveryStamp($retryCount, $this->getSenderClassOrAlias($envelope))) | |||
->with(new RedeliveryStamp($retryCount, $transportName)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The edge case I believe I was coding for (and maybe we decide it's not legitimate) is if you send on transport/sender A but receive on transport/receiver B. It's an odd case, but in that situation, we would (I think?) want to re-send to sender A, not receiver B. Thoughts?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In theory you could receive a message from transport B but route it to transport A for sending.
But in the end, senders and receivers are bound together by TransportInterface which requires implementing both. So if you do the above, you still have to implement sending part in transport B. So you could just use the same sender in transport B that you use in transport A if you need to cover retry going to transport A.
So to me that is an edge case that people can solve in custom transports. Nothing we should take care of by default. And in case we want to account for this later, the better and more explicit solution to me is to add a config option on the transport to configure the retry_transport
(similar to the failure_transport
).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is if you send on transport/sender A but receive on transport/receiver B
I also don't see how SentStamp should work for this case anyway. If a message comes from transport B, it cannot have the SentStamp pointing to transport A. If it was sent to transport B, it also has the SentStamp pointing to B (at least the last SentStamp) added by SendMessageMiddleware.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I also don't see how SentStamp should work for this case anyway
It would work like this:
A) Send a message on TransportA. The message now has a SentStamp for TransportA.
B) Receive message on TransportB. The message will, of course, still only have the SentStamp
for TransportA.
It's an edge case where, for example, you're using AMQP and send to TransportA, which has some routing & binding keys that ultimately put it in some queue "foo". Then, for whatever reason, you setup TransportB to receive from queue "foo". In this case, you will directly "receive" a message from TransportB that only has a SentStamp for TransportA.
But in the end, senders and receivers are bound together by TransportInterface which requires implementing both
I think that's not true... at least on a low, component level. I believe that, when routing, you can set the class to route to any service id that has the SenderInterface
, even if it's not defined as a transport (and doesn't define a TransportInterface
). I think the same is true for receiving messages: I think you can pass any service id to messenger:consume
.
Sorry to complicate things - this is what "possible" situation that was floating around when this was originally coded.
The tl;dr is this: the SentStamp
is the concrete way to mark exactly which sender sent a message so that we can definitely use the same sender during redelivery. But yes, we could add a retry_transport
option, which could act as an override for SentStamp/be used when that stamp is not available. Or, if the stamp is not available, we could "try" to redeliver to the "receiver" (and throw an exception if it doesn't implement SenderInterface
).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd prefer to not have the SentStamp logic. We agreed it tries to solve an edge case. To me that is something SF Messenger should not code against. It potentially breaks as much as it solves. For example, if I sent a Message to transport A, rename the transport to B and deploy again. Suddenly the retry of all existing messages in the queue breaks because it still tries to resend to A but A does not exist anymore. And with delayed messages of hours or days, this can easily happen.
How do we proceed now?
- accept the PR to remove SentStamp logic from retry in 4.3
- try to implement both the SentStamp logic and fallback to receiver
- as 2) but remove the SentStamp logic only in 4.4 to avoid potential bc break in 4.3
I'm in favor of 1).
2) would make the messenger behavior context dependent which I don't like at all.
This PR was merged into the 4.3 branch. Discussion ---------- [Messenger] No need for retry to require SentStamp | Q | A | ------------- | --- | Branch? | 4.3 | Bug fix? | yes | New feature? | no <!-- please update src/**/CHANGELOG.md files --> | BC breaks? | no <!-- see https://symfony.com/bc --> | Deprecations? | no <!-- please update UPGRADE-*.md and src/**/CHANGELOG.md files --> | Tests pass? | yes <!-- please add some, will be required by reviewers --> | Fixed tickets | | License | MIT | Doc PR | Fixes 2) in #32049 @weaverryan the SentStamp in the worker seems totally irrelevant. You always want to send messages back to the transport where they came from for retry. The only relevance I can potentially see is for the SyncTransport. Messages received async from worker might be routed to the SyncTransport. Using the SentStamp would redeliver the messages into the SyncTransport instead of the async. But that doesn't seem to have any use-case. I'm running the worker which handles the messages immediately. So basically there is no difference if they go to the Sync or Async transport from within the worker. Commits ------- 0034dee [Messenger] make retry logic work without SentStamp
Fixes 2) in #32049
@weaverryan the SentStamp in the worker seems totally irrelevant. You always want to send messages back to the transport where they came from for retry. The only relevance I can potentially see is for the SyncTransport. Messages received async from worker might be routed to the SyncTransport. Using the SentStamp would redeliver the messages into the SyncTransport instead of the async. But that doesn't seem to have any use-case. I'm running the worker which handles the messages immediately. So basically there is no difference if they go to the Sync or Async transport from within the worker.