Repository navigation
Pass the handler the message it was registered for, not the envelope - #352
Merged
KalimeroMK merged 1 commit intoNov 1, 2026
Merged
Conversation
A handler is registered for a message type, and the guide writes it with `assert($message instanceof SendEmailMessage)`. Nothing unwrapped an envelope on the way, so as soon as an adapter returned the message wrapped — an assigned id is the normal asynchronous path — the handler got the wrapper. With `zend.assertions=-1`, the production default, there is no error either: the properties read as `null` and the work is done against empty values. `ConsumeFinalHandler` now unwraps before calling the handler, carrying the envelope's meta over to the message. An envelope keeps the merged meta on itself while the message it wraps keeps its own, so unwrapping alone would lose the id, the delay and the failure counts. Unwrapping is the last step of the pipeline, so consume middleware still receive the envelope itself.
Reviewer's GuideThe final consume handler now unwraps adapter-created envelopes before invoking registered handlers, carries merged envelope metadata onto the underlying message, and leaves consume middleware envelope-aware; documentation, changelog, and regression tests cover the behavior. Sequence diagram for envelope unwrapping before message handlingsequenceDiagram
participant Adapter
participant Middleware as ConsumeMiddleware
participant FinalHandler as ConsumeFinalHandler
participant Handler
participant Envelope
participant Message
Adapter->>Middleware: handleConsume(request with Envelope)
Middleware->>FinalHandler: handleConsume(request with Envelope)
FinalHandler->>Envelope: getMessage()
Envelope-->>FinalHandler: Message
FinalHandler->>Envelope: getMeta()
Envelope-->>FinalHandler: merged metadata
FinalHandler->>Message: withMeta(merged metadata)
Message-->>FinalHandler: Message with metadata
FinalHandler->>Handler: handler(Message)
Handler-->>Handler: Read message payload and metadata
File-Level Changes
Possibly linked issues
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #352 +/- ##
============================================
+ Coverage 95.15% 95.26% +0.11%
- Complexity 395 396 +1
============================================
Files 59 59
Lines 1031 1034 +3
============================================
+ Hits 981 985 +4
+ Misses 50 49 -1 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
samdark
approved these changes
Nov 1, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What does this PR do?
A handler is registered for a message type, and the guide writes it that way
(
docs/guide/en/messages-and-handlers.md):Nothing unwrapped an envelope between the adapter and that handler, so an assigned id — the
normal asynchronous path — broke it:
With
zend.assertions=1:With
zend.assertions=-1, the production default, there is no error at all — the propertiesread as
nulland the work is done against empty values.DelayEnvelopeandFailureEnvelopebehave the same way.
Fix
ConsumeFinalHandlerunwraps before calling the handler, carrying the envelope's meta over tothe message:
The meta matters.
Envelope::__construct()keeps the merged meta on the envelope while$this->messagestays the innermost original, whose owngetMeta()never gets the envelope'skeys — so a plain
getMessage()would hand the handler a message withyii-id,yii-delayandyii-failuregone, andIdEnvelope::fromMessage($message)->getId()would start returningnullfor anything that logs or de-duplicates on the id. Carried over, those reads keep working.
Unwrapping is the last step of the pipeline, so consume middleware still receive the envelope
itself.
Envelope::getMessage()isfinaland already returns the innermost message — theconstructor flattens — so a stack of envelopes needs no loop here.
Two tests: the handler receives the message with the envelope's meta intact, and a consume
middleware still sees the envelope while the handler does not.
Note on #338
ConsumeFinalHandleris@internaland the change is one line, but #338 reworksWorkerand thepipeline around it. If that lands first, the same unwrap belongs wherever the final handler ends
up — happy to follow up either way.
Note on #342
InMemoryAdapterstores the unwrapped message, which is why the stub never showed this. Storingthe envelope there, as #342 asks, is safe once this is in.
Summary by Sourcery
Pass the registered message, with its envelope metadata preserved, to the final handler while retaining envelopes for consume middleware.
Bug Fixes:
Documentation:
Tests: