8000 Ensure the envelope is passed back and can be altered · sroze/symfony@599f32c · GitHub
[go: up one dir, main page]

Skip to content

Commit 599f32c

Browse files
committed
Ensure the envelope is passed back and can be altered
Ensure that the middlewares can also update the message within the envelope
1 parent 7c33cb2 commit 599f32c

File tree

3 files changed

+136
-5
lines changed

3 files changed

+136
-5
lines changed

src/Symfony/Component/Messenger/Envelope.php

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,15 @@ public function with(EnvelopeItemInterface $item): self
5757
return $cloned;
5858
}
5959

60+
public function withMessage($message): self
61+
{
62+
$cloned = clone $this;
63+
64+
$cloned->message = $message;
65+
66+
return $cloned;
67+
}
68+
6069
public function get(string $itemFqcn): ?EnvelopeItemInterface
6170
{
6271
return $this->items[$itemFqcn] ?? null;

src/Symfony/Component/Messenger/MessageBus.php

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -44,10 +44,10 @@ public function dispatch($message)
4444
throw new InvalidArgumentException(sprintf('Invalid type for message argument. Expected object, but got "%s".', \gettype($message)));
4545
}
4646

47-
return \call_user_func($this->callableForNextMiddleware(0), $message);
47+
return \call_user_func($this->callableForNextMiddleware(0, Envelope::wrap($message)), $message);
4848
}
4949

50-
private function callableForNextMiddleware(int $index): callable
50+
private function callableForNextMiddleware(int $index, Envelope $currentEnvelope): callable
5151
{
5252
if (null === $this->indexedMiddlewareHandlers) {
5353
$this->indexedMiddlewareHandlers = \is_array($this->middlewareHandlers) ? array_values($this->middlewareHandlers) : iterator_to_array($this->middlewareHandlers, false);
@@ -59,14 +59,19 @@ private function callableForNextMiddleware(int $index): callable
5959

6060
$middleware = $this->indexedMiddlewareHandlers[$index];
6161

62-
return function ($message) use ($middleware, $index) {
63-
$message = Envelope::wrap($message);
62+
return function ($message) use ($middleware, $index, $currentEnvelope) {
63+
if ($message instanceof Envelope) {
64+
$currentEnvelope = $message;
65+
} else {
66+
$message = $currentEnvelope->withMessage($message);
67+
}
68+
6469
if (!$middleware instanceof EnvelopeAwareInterface) {
6570
// Do not provide the envelope if the middleware cannot read it:
6671
$message = $message->getMessage();
6772
}
6873

69-
return $middleware->handle($message, $this->callableForNextMiddleware($index + 1));
74+
return $middleware->handle($message, $this->callableForNextMiddleware($index + 1, $currentEnvelope));
7075
};
7176
}
7277
}

src/Symfony/Component/Messenger/Tests/MessageBusTest.php

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@
1212
namespace Symfony\Component\Messenger\Tests;
1313

1414
use PHPUnit\Framework\TestCase;
15+
use Symfony\Component\Messenger\Asynchronous\Transport\ReceivedMessage;
16+
use Symfony\Component\Messenger\Envelope;
17+
use Symfony\Component\Messenger\EnvelopeAwareInterface;
18+
use Symfony\Component\Messenger\EnvelopeItemInterface;
1519
use Symfony\Component\Messenger\MessageBus;
1620
use Symfony\Component\Messenger\MessageBusInterface;
1721
use Symfony\Component\Messenger\Middleware\MiddlewareInterface;
@@ -61,4 +65,117 @@ public function testItCallsMiddlewareAndChainTheReturnValue()
6165

6266
$this->assertEquals($responseFromDepthMiddleware, $bus->dispatch($message));
6367
}
68+
69+
public function testItKeepsTheEnvelopeEvenThroughAMiddlewareThatIsNotEnvelopeAware()
70+
{
71+
$message = new DummyMessage('Hello');
72+
$envelope = new Envelope($message, array(new ReceivedMessage()));
73+
74+
$firstMiddleware = $this->getMockBuilder(MiddlewareInterface::class)->getMock();
75+
$firstMiddleware->expects($this->once())
76+
->method('handle')
77+
->with($message, $this->anything())
78+
->will($this->returnCallback(function ($message, $next) {
79+
return $next($message);
80+
}));
81+
82+
$secondMiddleware = $this->getMockBuilder(array(MiddlewareInterface::class, EnvelopeAwareInterface::class))->getMock();
83+
$secondMiddleware->expects($this->once())
84+
->method('handle')
85+
->with($envelope, $this->anything())
86+
;
87+
88+
$bus = new MessageBus(array(
89+
$firstMiddleware,
90+
$secondMiddleware,
91+
));
92+
93+
$bus->dispatch($envelope);
94+
}
95+
96+
public function testThatAMiddlewareCanAddSomeItemsToTheEnvelope()
97+
{
98+
$message = new DummyMessage('Hello');
99+
$envelope = new Envelope($message, array(new ReceivedMessage()));
100+
$envelopeWithAnotherItem = $envelope->with(new AnEnvelopeItem());
101+
102+
$firstMiddleware = $this->getMockBuilder(array(MiddlewareInterface::class, EnvelopeAwareInterface::class))->getMock();
103+
$firstMiddleware->expects($this->once())
104+
->method('handle')
105+
->with($envelope, $this->anything())
106+
->will($this->returnCallback(function ($message, $next) {
107+
return $next($message->with(new AnEnvelopeItem()));
108+
}));
109+
110+
$secondMiddleware = $this->getMockBuilder(MiddlewareInterface::class)->getMock();
111+
$secondMiddleware->expects($this->once())
112+
->method('handle')
113+
->with($message, $this->anything())
114+
->will($this->returnCallback(function ($message, $next) {
115+
return $next($message);
116+
}));
117+
118+
$thirdMiddleware = $this->getMockBuilder(array(MiddlewareInterface::class, EnvelopeAwareInterface::class))->getMock();
119+
$thirdMiddleware->expects($this->once())
120+
->method('handle')
121+
->with($envelopeWithAnotherItem, $this->anything())
122+
;
123+
124+
$bus = new MessageBus(array(
125+
$firstMiddleware,
126+
$secondMiddleware,
127+
$thirdMiddleware,
128+
));
129+
130+
$bus->dispatch($envelope);
131+
}
132+
133+
public function testThatAMiddlewareCanUpdateTheMessageWhileKeepingTheEnvelopeItems()
134+
{
135+
$message = new DummyMessage('Hello');
136+
$envelope = new Envelope($message, $items = array(new ReceivedMessage()));
137+
138+
$changedMessage = new DummyMessage('Changed');
139+
$expectedEnvelope = new Envelope($changedMessage, $items);
140+
141+
$firstMiddleware = $this->getMockBuilder(MiddlewareInterface::class)->getMock();
142+
$firstMiddleware->expects($this->once())
143+
->method('handle')
144+
->with($message, $this->anything())
145+
->will($this->returnCallback(function ($message, $next) use ($changedMessage) {
146+
return $next($changedMessage);
147+
}));
148+
149+
$secondMiddleware = $this->getMockBuilder(array(MiddlewareInterface::class, EnvelopeAwareInterface::class))->getMock();
150+
$secondMiddleware->expects($this->once())
151+
->method('handle')
152+
->with($expectedEnvelope, $this->anything())
153+
;
154+
155+
$bus = new MessageBus(array(
156+
$firstMiddleware,
157+
$secondMiddleware,
158+
));
159+
160+
$bus->dispatch($envelope);
161+
}
162+
}
163+
164+
class AnEnvelopeItem implements EnvelopeItemInterface
165+
{
166+
/**
167+
* {@inheritdoc}
168+
*/
169+
public function serialize()
170+
{
171+
return '';
172+
}
173+
174+
/**
175+
* {@inheritdoc}
176+
*/
177+
public function unserialize($serialized)
178+
{
179+
return new self();
180+
}
64181
}

0 commit comments

Comments
 (0)
0