Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 3abca64

Browse files
committed
feature #30707 [Messenger][DX] Allow stamps to be passed directly to MessageBusInterface::dispatch() (weaverryan)
This PR was merged into the 4.3-dev branch. Discussion ---------- [Messenger][DX] Allow stamps to be passed directly to MessageBusInterface::dispatch() | Q | A | ------------- | --- | Branch? | master | Bug fix? | no | New feature? | yes | BC breaks? | yes | Deprecations? | no | Tests pass? | yes | Fixed tickets | none | License | MIT | Doc PR | TODO Me again o/! This proposal is *purely* for DX. With `DelayStamp`, the proposal of QueueNameStamp and future things like `AmqpRoutingKeyStamp`, stamps are becoming more common for end users to use. This changes how it looks to use them: ```php // before $bus->dispatch(new Envelope(new SendSmsNotification('Hi!'), new DelayStamp(10), new QueueNameStamp('low'))); // after $bus->dispatch(new SendSmsNotification('Hi!'), [new DelayStamp(10), new QueueNameStamp('low')]); ``` It's definitely a BC break, which is allowed because the component is experimental, though it should be minimized. This BC break shouldn't be felt by most end users, as creating your own bus is an advanced use-case. Even if you decorated it, you'll get an obvious error. Commits ------- e861de7 Allow stamps to be passed directly to MessageBusInterface::dispatch()
2 parents e897e6c + e861de7 commit 3abca64

18 files changed

+115
-52
lines changed

src/Symfony/Component/Messenger/CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,12 @@ CHANGELOG
44
4.3.0
55
-----
66

7+
* [BC BREAK] The `Envelope::__construct()` signature changed:
8+
you can no longer pass an unlimited number of stamps as the second,
9+
third, fourth, arguments etc: stamps are now an array passed to the
10+
second argument.
11+
* [BC BREAK] The `MessageBusInterface::dispatch()` signature changed:
12+
a second argument `array $stamps = []` was added.
713
* [BC BREAK] The `TransportFactoryInterface::createTransport()` signature
814
changed: a required 3rd `SerializerInterface` argument was added.
915
* Added a new `SyncTransport` along with `ForceCallHandlersStamp` to

src/Symfony/Component/Messenger/Envelope.php

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,10 @@ final class Envelope
2626
private $message;
2727

2828
/**
29-
* @param object $message
29+
* @param object $message
30+
* @param StampInterface[] $stamps
3031
*/
31-
public function __construct($message, StampInterface ...$stamps)
32+
public function __construct($message, array $stamps = [])
3233
{
3334
if (!\is_object($message)) {
3435
throw new \TypeError(sprintf('Invalid argument provided to "%s()": expected object but got %s.', __METHOD__, \gettype($message)));
@@ -40,6 +41,19 @@ public function __construct($message, StampInterface ...$stamps)
4041
}
4142
}
4243

44+
/**
45+
* Makes sure the message is in an Envelope and adds the given stamps.
46+
*
47+
* @param object|Envelope $message
48+
* @param StampInterface[] $stamps
49+
*/
50+
public static function wrap($message, array $stamps = []): self
51+
{
52+
$envelope = $message instanceof self ? $message : new self($message);
53+
54+
return $envelope->with(...$stamps);
55+
}
56+
4357
/**
4458
* @return Envelope a new Envelope instance with additional stamp
4559
*/

src/Symfony/Component/Messenger/MessageBus.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,12 +52,12 @@ public function getIterator()
5252
/**
5353
* {@inheritdoc}
5454
*/
55-
public function dispatch($message): Envelope
55+
public function dispatch($message, array $stamps = []): Envelope
5656
{
5757
if (!\is_object($message)) {
5858
throw new \TypeError(sprintf('Invalid argument provided to "%s()": expected object, but got %s.', __METHOD__, \gettype($message)));
5959
}
60-
$envelope = $message instanceof Envelope ? $message : new Envelope($message);
60+
$envelope = Envelope::wrap($message, $stamps);
6161
$middlewareIterator = $this->middlewareAggregate->getIterator();
6262

6363
while ($middlewareIterator instanceof \IteratorAggregate) {

src/Symfony/Component/Messenger/MessageBusInterface.php

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111

1212
namespace Symfony\Component\Messenger;
1313

14+
use Symfony\Component\Messenger\Stamp\StampInterface;
15+
1416
/**
1517
* @author Samuel Roze <[email protected]>
1618
*
@@ -21,7 +23,8 @@ interface MessageBusInterface
2123
/**
2224
* Dispatches the given message.
2325
*
24-
* @param object|Envelope $message The message or the message pre-wrapped in an envelope
26+
* @param object|Envelope $message The message or the message pre-wrapped in an envelope
27+
* @param StampInterface[] $stamps
2528
*/
26-
public function dispatch($message): Envelope;
29+
public function dispatch($message, array $stamps = []): Envelope;
2730
}

src/Symfony/Component/Messenger/RoutableMessageBus.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ public function __construct(ContainerInterface $busLocator)
3737
$this->busLocator = $busLocator;
3838
}
3939

40-
public function dispatch($envelope): Envelope
40+
public function dispatch($envelope, array $stamps = []): Envelope
4141
{
4242
if (!$envelope instanceof Envelope) {
4343
throw new InvalidArgumentException('Messages passed to RoutableMessageBus::dispatch() must be inside an Envelope');
@@ -53,6 +53,6 @@ public function dispatch($envelope): Envelope
5353
throw new InvalidArgumentException(sprintf('Invalid bus name "%s" on BusNameStamp.', $busNameStamp->getBusName()));
5454
}
5555

56-
return $this->busLocator->get($busNameStamp->getBusName())->dispatch($envelope);
56+
return $this->busLocator->get($busNameStamp->getBusName())->dispatch($envelope, $stamps);
5757
}
5858
}

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

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ class EnvelopeTest extends TestCase
2626
public function testConstruct()
2727
{
2828
$receivedStamp = new ReceivedStamp();
29-
$envelope = new Envelope($dummy = new DummyMessage('dummy'), $receivedStamp);
29+
$envelope = new Envelope($dummy = new DummyMessage('dummy'), [$receivedStamp]);
3030

3131
$this->assertSame($dummy, $envelope->getMessage());
3232
$this->assertArrayHasKey(ReceivedStamp::class, $stamps = $envelope->all());
@@ -42,7 +42,7 @@ public function testWithReturnsNewInstance()
4242

4343
public function testWithoutAll()
4444
{
45-
$envelope = new Envelope(new DummyMessage('dummy'), new ReceivedStamp(), new ReceivedStamp(), new DelayStamp(5000));
45+
$envelope = new Envelope(new DummyMessage('dummy'), [new ReceivedStamp(), new ReceivedStamp(), new DelayStamp(5000)]);
4646

4747
$envelope = $envelope->withoutAll(ReceivedStamp::class);
4848

@@ -53,7 +53,7 @@ public function testWithoutAll()
5353
public function testLast()
5454
{
5555
$receivedStamp = new ReceivedStamp();
56-
$envelope = new Envelope($dummy = new DummyMessage('dummy'), $receivedStamp);
56+
$envelope = new Envelope($dummy = new DummyMessage('dummy'), [$receivedStamp]);
5757

5858
$this->assertSame($receivedStamp, $envelope->last(ReceivedStamp::class));
5959
$this->assertNull($envelope->last(ValidationStamp::class));
@@ -72,4 +72,23 @@ public function testAll()
7272
$this->assertArrayHasKey(ValidationStamp::class, $stamps);
7373
$this->assertSame($validationStamp, $stamps[ValidationStamp::class][0]);
7474
}
75+
76+
public function testWrapWithMessage()
77+
{
78+
$message = new \stdClass();
79+
$stamp = new ReceivedStamp();
80+
$envelope = Envelope::wrap($message, [$stamp]);
81+
82+
$this->assertSame($message, $envelope->getMessage());
83+
$this->assertSame([ReceivedStamp::class => [$stamp]], $envelope->all());
84+
}
85+
86+
public function testWrapWithEnvelope()
87+
{
88+
$envelope = new Envelope(new \stdClass(), [new DelayStamp(5)]);
89+
$envelope = Envelope::wrap($envelope, [new ReceivedStamp()]);
90+
91+
$this->assertCount(1, $envelope->all(DelayStamp::class));
92+
$this->assertCount(1, $envelope->all(ReceivedStamp::class));
93+
}
7594
}

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ public function testHandleReturnsHandledStampResult()
3131

3232
$query = new DummyMessage('Hello');
3333
$bus->expects($this->once())->method('dispatch')->willReturn(
34-
new Envelope($query, new HandledStamp('result', 'DummyHandler::__invoke'))
34+
new Envelope($query, [new HandledStamp('result', 'DummyHandler::__invoke')])
3535
);
3636

3737
$this->assertSame('result', $queryBus->query($query));
@@ -42,7 +42,7 @@ public function testHandleAcceptsEnvelopes()
4242
$bus = $this->createMock(MessageBus::class);
4343
$queryBus = new TestQueryBus($bus);
4444

45-
$envelope = new Envelope(new DummyMessage('Hello'), new HandledStamp('result', 'DummyHandler::__invoke'));
45+
$envelope = new Envelope(new DummyMessage('Hello'), [new HandledStamp('result', 'DummyHandler::__invoke')]);
4646
$bus->expects($this->once())->method('dispatch')->willReturn($envelope);
4747

4848
$this->assertSame('result', $queryBus->query($envelope));
@@ -74,7 +74,7 @@ public function testHandleThrowsOnMultipleHandledStamps()
7474

7575
$query = new DummyMessage('Hello');
7676
$bus->expects($this->once())->method('dispatch')->willReturn(
77-
new Envelope($query, new HandledStamp('first_result', 'FirstDummyHandler::__invoke'), new HandledStamp('second_result', 'SecondDummyHandler::__invoke', 'dummy_2'))
77+
new Envelope($query, [new HandledStamp('first_result', 'FirstDummyHandler::__invoke'), new HandledStamp('second_result', 'SecondDummyHandler::__invoke', 'dummy_2')])
7878
);
7979

8080
$queryBus->query($query);

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

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
use Symfony\Component\Messenger\MessageBus;
1717
use Symfony\Component\Messenger\MessageBusInterface;
1818
use Symfony\Component\Messenger\Middleware\MiddlewareInterface;
19+
use Symfony\Component\Messenger\Stamp\BusNameStamp;
20+
use Symfony\Component\Messenger\Stamp\DelayStamp;
1921
use Symfony\Component\Messenger\Stamp\ReceivedStamp;
2022
use Symfony\Component\Messenger\Tests\Fixtures\AnEnvelopeStamp;
2123
use Symfony\Component\Messenger\Tests\Fixtures\DummyMessage;
@@ -69,7 +71,7 @@ public function testItCallsMiddleware()
6971
public function testThatAMiddlewareCanAddSomeStampsToTheEnvelope()
7072
{
7173
$message = new DummyMessage('Hello');
72-
$envelope = new Envelope($message, new ReceivedStamp());
74+
$envelope = new Envelope($message, [new ReceivedStamp()]);
7375
$envelopeWithAnotherStamp = $envelope->with(new AnEnvelopeStamp());
7476

7577
$firstMiddleware = $this->getMockBuilder(MiddlewareInterface::class)->getMock();
@@ -107,10 +109,10 @@ public function testThatAMiddlewareCanAddSomeStampsToTheEnvelope()
107109
public function testThatAMiddlewareCanUpdateTheMessageWhileKeepingTheEnvelopeStamps()
108110
{
109111
$message = new DummyMessage('Hello');
110-
$envelope = new Envelope($message, ...$stamps = [new ReceivedStamp()]);
112+
$envelope = new Envelope($message, $stamps = [new ReceivedStamp()]);
111113

112114
$changedMessage = new DummyMessage('Changed');
113-
$expectedEnvelope = new Envelope($changedMessage, ...$stamps);
115+
$expectedEnvelope = new Envelope($changedMessage, $stamps);
114116

115117
$firstMiddleware = $this->getMockBuilder(MiddlewareInterface::class)->getMock();
116118
$firstMiddleware->expects($this->once())
@@ -134,4 +136,16 @@ public function testThatAMiddlewareCanUpdateTheMessageWhileKeepingTheEnvelopeSta
134136

135137
$bus->dispatch($envelope);
136138
}
139+
140+
public function testItAddsTheStamps()
141+
{
142+
$finalEnvelope = (new MessageBus())->dispatch(new \stdClass(), [new DelayStamp(5), new BusNameStamp('bar')]);
143+
$this->assertCount(2, $finalEnvelope->all());
144+
}
145+
146+
public function testItAddsTheStampsToEnvelope()
147+
{
148+
$finalEnvelope = (new MessageBus())->dispatch(new Envelope(new \stdClass()), [new DelayStamp(5), new BusNameStamp('bar')]);
149+
$this->assertCount(2, $finalEnvelope->all());
150+
}
137151
}

src/Symfony/Component/Messenger/Tests/Middleware/DispatchAfterCurrentBusMiddlewareTest.php

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,8 @@ public function testEventsInNewTransactionAreHandledAfterMainMessage()
4444
$messageBus = new MessageBus([
4545
$middleware,
4646
new DispatchingMiddleware($eventBus, [
47-
new Envelope($firstEvent, new DispatchAfterCurrentBusStamp()),
48-
new Envelope($secondEvent, new DispatchAfterCurrentBusStamp()),
47+
new Envelope($firstEvent, [new DispatchAfterCurrentBusStamp()]),
48+
new Envelope($secondEvent, [new DispatchAfterCurrentBusStamp()]),
4949
$thirdEvent, // Not in a new transaction
5050
]),
5151
$handlingMiddleware,
@@ -80,8 +80,8 @@ public function testThrowingEventsHandlingWontStopExecution()
8080
$messageBus = new MessageBus([
8181
$middleware,
8282
new DispatchingMiddleware($eventBus, [
83-
new Envelope($firstEvent, new DispatchAfterCurrentBusStamp()),
84-
new Envelope($secondEvent, new DispatchAfterCurrentBusStamp()),
83+
new Envelope($firstEvent, [new DispatchAfterCurrentBusStamp()]),
84+
new Envelope($secondEvent, [new DispatchAfterCurrentBusStamp()]),
8585
]),
8686
$handlingMiddleware,
8787
]);

src/Symfony/Component/Messenger/Tests/Middleware/SendMessageMiddlewareTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ public function testItSendsTheMessageToMultipleSenders()
8686

8787
public function testItSendsToOnlyOneSenderOnRedelivery()
8888
{
89-
$envelope = new Envelope(new DummyMessage('Hey'), new RedeliveryStamp(5, 'bar'));
89+
$envelope = new Envelope(new DummyMessage('Hey'), [new RedeliveryStamp(5, 'bar')]);
9090
// even with a ForceCallHandlersStamp, the next middleware won't be called
9191
$envelope = $envelope->with(new ForceCallHandlersStamp());
9292
$sender = $this->getMockBuilder(SenderInterface::class)->getMock();

src/Symfony/Component/Messenger/Tests/Retry/MultiplierRetryStrategyTest.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,15 +21,15 @@ class MultiplierRetryStrategyTest extends TestCase
2121
public function testIsRetryable()
2222
{
2323
$strategy = new MultiplierRetryStrategy(3);
24-
$envelope = new Envelope(new \stdClass(), new RedeliveryStamp(0, 'sender_alias'));
24+
$envelope = new Envelope(new \stdClass(), [new RedeliveryStamp(0, 'sender_alias')]);
2525

2626
$this->assertTrue($strategy->isRetryable($envelope));
2727
}
2828

2929
public function testIsNotRetryable()
3030
{
3131
$strategy = new MultiplierRetryStrategy(3);
32-
$envelope = new Envelope(new \stdClass(), new RedeliveryStamp(3, 'sender_alias'));
32+
$envelope = new Envelope(new \stdClass(), [new RedeliveryStamp(3, 'sender_alias')]);
3333

3434
$this->assertFalse($strategy->isRetryable($envelope));
3535
}
@@ -48,7 +48,7 @@ public function testIsRetryableWithNoStamp()
4848
public function testGetWaitTime(int $delay, int $multiplier, int $maxDelay, int $previousRetries, int $expectedDelay)
4949
{
5050
$strategy = new MultiplierRetryStrategy(10, $delay, $multiplier, $maxDelay);
51-
$envelope = new Envelope(new \stdClass(), new RedeliveryStamp($previousRetries, 'sender_alias'));
51+
$envelope = new Envelope(new \stdClass(), [new RedeliveryStamp($previousRetries, 'sender_alias')]);
5252

5353
$this->assertSame($expectedDelay, $strategy->getWaitingTime($envelope));
5454
}

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

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,13 @@
1818
use Symfony\Component\Messenger\MessageBusInterface;
1919
use Symfony\Component\Messenger\RoutableMessageBus;
2020
use Symfony\Component\Messenger\Stamp\BusNameStamp;
21+
use Symfony\Component\Messenger\Stamp\DelayStamp;
2122

2223
class RoutableMessageBusTest extends TestCase
2324
{
2425
public function testItRoutesToTheCorrectBus()
2526
{
26-
$envelope = new Envelope(new \stdClass(), new BusNameStamp('foo_bus'));
27+
$envelope = new Envelope(new \stdClass(), [new BusNameStamp('foo_bus')]);
2728

2829
$bus1 = $this->createMock(MessageBusInterface::class);
2930
$bus2 = $this->createMock(MessageBusInterface::class);
@@ -32,11 +33,12 @@ public function testItRoutesToTheCorrectBus()
3233
$container->expects($this->once())->method('has')->with('foo_bus')->willReturn(true);
3334
$container->expects($this->once())->method('get')->will($this->returnValue($bus2));
3435

36+
$stamp = new DelayStamp(5);
3537
$bus1->expects($this->never())->method('dispatch');
36-
$bus2->expects($this->once())->method('dispatch')->with($envelope)->willReturn($envelope);
38+
$bus2->expects($this->once())->method('dispatch')->with($envelope, [$stamp])->willReturn($envelope);
3739

3840
$routableBus = new RoutableMessageBus($container);
39-
$this->assertSame($envelope, $routableBus->dispatch($envelope));
41+
$this->assertSame($envelope, $routableBus->dispatch($envelope, [$stamp]));
4042
}
4143

4244
public function testItExceptionOnMissingStamp()
@@ -58,7 +60,7 @@ public function testItExceptionOnBusNotFound()
5860
$this->expectException(InvalidArgumentException::class);
5961
$this->expectExceptionMessage('Invalid bus name');
6062

61-
$envelope = new Envelope(new \stdClass(), new BusNameStamp('foo_bus'));
63+
$envelope = new Envelope(new \stdClass(), [new BusNameStamp('foo_bus')]);
6264

6365
$container = $this->createMock(ContainerInterface::class);
6466
$container->expects($this->once())->method('has')->willReturn(false);

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

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
use PHPUnit\Framework\TestCase;
1515
use Symfony\Component\Messenger\Envelope;
1616
use Symfony\Component\Messenger\MessageBusInterface;
17+
use Symfony\Component\Messenger\Stamp\DelayStamp;
1718
use Symfony\Component\Messenger\Tests\Fixtures\AnEnvelopeStamp;
1819
use Symfony\Component\Messenger\Tests\Fixtures\DummyMessage;
1920
use Symfony\Component\Messenger\TraceableMessageBus;
@@ -24,22 +25,25 @@ public function testItTracesDispatch()
2425
{
2526
$message = new DummyMessage('Hello');
2627

28+
$stamp = new DelayStamp(5);
2729
$bus = $this->getMockBuilder(MessageBusInterface::class)->getMock();
28-
$bus->expects($this->once())->method('dispatch')->with($message)->willReturn(new Envelope($message));
30+
$bus->expects($this->once())->method('dispatch')->with($message, [$stamp])->willReturn(new Envelope($message));
2931

3032
$traceableBus = new TraceableMessageBus($bus);
3133
$line = __LINE__ + 1;
32-
$traceableBus->dispatch($message);
34+
$traceableBus->dispatch($message, [$stamp]);
3335
$this->assertCount(1, $tracedMessages = $traceableBus->getDispatchedMessages());
34-
$this->assertArraySubset([
36+
$actualTracedMessage = $tracedMessages[0];
37+
unset($actualTracedMessage['callTime']); // don't check, too variable
38+
$this->assertEquals([
3539
'message' => $message,
36-
'stamps' => [],
40+
'stamps' => [[$stamp]],
3741
'caller' => [
3842
'name' => 'TraceableMessageBusTest.php',
3943
'file' => __FILE__,
4044
'line' => $line,
4145
],
42-
], $tracedMessages[0], true);
46+
], $actualTracedMessage);
4347
}
4448

4549
public function testItTracesDispatchWithEnvelope()
@@ -54,15 +58,17 @@ public function testItTracesDispatchWithEnvelope()
5458
$line = __LINE__ + 1;
5559
$traceableBus->dispatch($envelope);
5660
$this->assertCount(1, $tracedMessages = $traceableBus->getDispatchedMessages());
57-
$this->assertArraySubset([
61+
$actualTracedMessage = $tracedMessages[0];
62+
unset($actualTracedMessage['callTime']); // don't check, too variable
63+
$this->assertEquals([
5864
'message' => $message,
5965
'stamps' => [[$stamp]],
6066
'caller' => [
6167
'name' => 'TraceableMessageBusTest.php',
6268
'file' => __FILE__,
6369
'line' => $line,
6470
],
65-
], $tracedMessages[0], true);
71+
], $actualTracedMessage);
6672
}
6773

6874
public function testItTracesExceptions()
@@ -82,7 +88,9 @@ public function testItTracesExceptions()
8288
}
8389

8490
$this->assertCount(1, $tracedMessages = $traceableBus->getDispatchedMessages());
85-
$this->assertArraySubset([
91+
$actualTracedMessage = $tracedMessages[0];
92+
unset($actualTracedMessage['callTime']); // don't check, too variable
93+
$this->assertEquals([
8694
'message' => $message,
8795
'exception' => $exception,
8896
'stamps' => [],
@@ -91,6 +99,6 @@ public function testItTracesExceptions()
9199
'file' => __FILE__,
92100
'line' => $line,
93101
],
94-
], $tracedMessages[0], true);
102+
], $actualTracedMessage);
95103
}
96104
}

0 commit comments

Comments
 (0)