Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit88891d5

Browse files
feature#29166 [Messenger] Add handled & sent stamps (ogizanagi)
This PR was merged into the 4.2-dev branch.Discussion----------[Messenger] Add handled & sent stamps| Q | A| ------------- | ---| Branch? | 4.2 <!-- see below -->| Bug fix? | no| New feature? | yes <!-- don't forget to update src/**/CHANGELOG.md files -->| BC breaks? | no <!-- seehttps://symfony.com/bc -->| Deprecations? | no <!-- don't forget to update UPGRADE-*.md and src/**/CHANGELOG.md files -->| Tests pass? | yes <!-- please add some, will be required by reviewers -->| Fixed tickets | N/A <!-- #-prefixed issue number(s), if any -->| License | MIT| Doc PR |symfony/symfony-docs/issues/10661Based on#29159This new feature marks sent and handled messages, so middleware can act upon these and use the handler(s) result(s).This is also the base of a next PR (#29167), introducing a query bus built on top of the message bus.I'm not sure yet about the best way to determine the handlers and senders names/descriptions to store in the stamps:- Handlers are callable. I've just reused the [console text descriptor](https://github.com/nicolas-grekas/symfony/blob/1c1818b87675d077808dbf7e05da84c2e1ddc9f8/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/TextDescriptor.php#L457-L491) format for now.- ~~Sender are `SenderInterface` instances. `\get_class` is used for now, but a single message can be sent by multiple senders, including of the same class.~~ => Updated. Yielding the sender name if provided, the FQCN otherwise.~~Instead, what about allowing to yield names from locators, and fallback on the above strategies otherwise? So we'll use transport names from the config for senders, and pre-computed compile-time handlers descriptions?~~=> Done. For handlers, computing it at compile time might not be straightforward. Let's compute it lazily from `HandledStamp::fromCallable()`---### From previous conversations:> What about not adding HandledStamp on `null` returned from handlerIMHO, `null` still is a result. The stamps allows to identify a message as being handled regardless of the returned value, so makes sense on its own and keeping would require one less check for those wanting to consume it.> What about adding SentStamp?Makes sense to me and I think it was requested by@Nyholm before on Slack.So, included in this PR.> Should it target 4.2 or 4.3?Targeting 4.2, because of the removal of the handler result forwarding by middleware. A userland middleware could have used this result, typically a cache middleware. Which would now require extra boring code in userland. This will simplify it and allow users to create their query bus instance until 4.3.Commits-------2f5acf7 [Messenger] Add handled & sent stamps
2 parents100f205 +2f5acf7 commit88891d5

File tree

16 files changed

+325
-16
lines changed

16 files changed

+325
-16
lines changed

‎src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php‎

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1578,9 +1578,10 @@ private function registerMessengerConfiguration(array $config, ContainerBuilder
15781578
if ('*' !==$message && !class_exists($message) && !interface_exists($message,false)) {
15791579
thrownewLogicException(sprintf('Invalid Messenger routing configuration: class or interface "%s" not found.',$message));
15801580
}
1581-
$senders =array_map(function ($sender)use ($senderAliases) {
1582-
returnnewReference($senderAliases[$sender] ??$sender);
1583-
},$messageConfiguration['senders']);
1581+
$senders =array();
1582+
foreach ($messageConfiguration['senders']as$sender) {
1583+
$senders[$sender] =newReference($senderAliases[$sender] ??$sender);
1584+
}
15841585

15851586
$sendersId ='messenger.senders.'.$message;
15861587
$container->register($sendersId, RewindableGenerator::class)

‎src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php‎

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -569,7 +569,10 @@ public function testMessengerRouting()
569569
);
570570

571571
$this->assertSame($messageToSendAndHandleMapping,$senderLocatorDefinition->getArgument(1));
572-
$this->assertEquals(array(newReference('messenger.transport.amqp'),newReference('audit')),$container->getDefinition('messenger.senders.'.DummyMessage::class)->getArgument(0)[0]->getValues());
572+
$this->assertEquals(array(
573+
'amqp' =>newReference('messenger.transport.amqp'),
574+
'audit' =>newReference('audit'),
575+
),$container->getDefinition('messenger.senders.'.DummyMessage::class)->getArgument(0)[0]->getValues());
573576
}
574577

575578
/**

‎src/Symfony/Component/Messenger/CHANGELOG.md‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ CHANGELOG
44
4.2.0
55
-----
66

7+
* Added`HandledStamp` &`SentStamp` stamps
78
* All the changes below are BC BREAKS
89
* Senders and handlers subscribing to parent interfaces now receive*all* matching messages, wildcard included
910
*`MessageBusInterface::dispatch()`,`MiddlewareInterface::handle()` and`SenderInterface::send()` return`Envelope`

‎src/Symfony/Component/Messenger/Handler/HandlersLocator.php‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,9 @@ public function getHandlers(Envelope $envelope): iterable
4040
$seen =array();
4141

4242
foreach (self::listTypes($envelope)as$type) {
43-
foreach ($this->handlers[$type] ??array()as$handler) {
43+
foreach ($this->handlers[$type] ??array()as$alias =>$handler) {
4444
if (!\in_array($handler,$seen,true)) {
45-
yield$seen[] =$handler;
45+
yield$alias =>$seen[] =$handler;
4646
}
4747
}
4848
}

‎src/Symfony/Component/Messenger/Handler/HandlersLocatorInterface.php‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ interface HandlersLocatorInterface
2525
/**
2626
* Returns the handlers for the given message name.
2727
*
28-
* @return iterable|callable[]
28+
* @return iterable|callable[] Indexed by handler alias if available
2929
*/
3030
publicfunctiongetHandlers(Envelope$envelope):iterable;
3131
}

‎src/Symfony/Component/Messenger/Middleware/HandleMessageMiddleware.php‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
useSymfony\Component\Messenger\Envelope;
1515
useSymfony\Component\Messenger\Exception\NoHandlerForMessageException;
1616
useSymfony\Component\Messenger\Handler\HandlersLocatorInterface;
17+
useSymfony\Component\Messenger\Stamp\HandledStamp;
1718

1819
/**
1920
* @author Samuel Roze <samuel.roze@gmail.com>
@@ -40,8 +41,8 @@ public function handle(Envelope $envelope, StackInterface $stack): Envelope
4041
{
4142
$handler =null;
4243
$message =$envelope->getMessage();
43-
foreach ($this->handlersLocator->getHandlers($envelope)as$handler) {
44-
$handler($message);
44+
foreach ($this->handlersLocator->getHandlers($envelope)as$alias =>$handler) {
45+
$envelope =$envelope->with(HandledStamp::fromCallable($handler,$handler($message),\is_string($alias) ?$alias :null));
4546
}
4647
if (null ===$handler && !$this->allowNoHandlers) {
4748
thrownewNoHandlerForMessageException(sprintf('No handler for message "%s".',\get_class($envelope->getMessage())));

‎src/Symfony/Component/Messenger/Middleware/SendMessageMiddleware.php‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
useSymfony\Component\Messenger\Envelope;
1515
useSymfony\Component\Messenger\Stamp\ReceivedStamp;
16+
useSymfony\Component\Messenger\Stamp\SentStamp;
1617
useSymfony\Component\Messenger\Transport\Sender\SendersLocatorInterface;
1718

1819
/**
@@ -42,8 +43,8 @@ public function handle(Envelope $envelope, StackInterface $stack): Envelope
4243
$handle =false;
4344
$sender =null;
4445

45-
foreach ($this->sendersLocator->getSenders($envelope,$handle)as$sender) {
46-
$envelope =$sender->send($envelope);
46+
foreach ($this->sendersLocator->getSenders($envelope,$handle)as$alias =>$sender) {
47+
$envelope =$sender->send($envelope)->with(newSentStamp(\get_class($sender),\is_string($alias) ?$alias :null));
4748
}
4849

4950
if (null ===$sender ||$handle) {
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespaceSymfony\Component\Messenger\Stamp;
13+
14+
/**
15+
* Stamp identifying a message handled by the `HandleMessageMiddleware` middleware
16+
* and storing the handler returned value.
17+
*
18+
* @see \Symfony\Component\Messenger\Middleware\HandleMessageMiddleware
19+
*
20+
* @author Maxime Steinhausser <maxime.steinhausser@gmail.com>
21+
*
22+
* @experimental in 4.2
23+
*/
24+
finalclass HandledStampimplements StampInterface
25+
{
26+
private$result;
27+
private$callableName;
28+
private$handlerAlias;
29+
30+
/**
31+
* @param mixed $result The returned value of the message handler
32+
*/
33+
publicfunction__construct($result,string$callableName,string$handlerAlias =null)
34+
{
35+
$this->result =$result;
36+
$this->callableName =$callableName;
37+
$this->handlerAlias =$handlerAlias;
38+
}
39+
40+
/**
41+
* @param mixed $result The returned value of the message handler
42+
*/
43+
publicstaticfunctionfromCallable(callable$handler,$result,string$handlerAlias =null):self
44+
{
45+
if (\is_array($handler)) {
46+
if (\is_object($handler[0])) {
47+
returnnewself($result,\get_class($handler[0]).'::'.$handler[1],$handlerAlias);
48+
}
49+
50+
returnnewself($result,$handler[0].'::'.$handler[1],$handlerAlias);
51+
}
52+
53+
if (\is_string($handler)) {
54+
returnnewself($result,$handler,$handlerAlias);
55+
}
56+
57+
if ($handlerinstanceof \Closure) {
58+
$r =new \ReflectionFunction($handler);
59+
if (false !==strpos($r->name,'{closure}')) {
60+
returnnewself($result,'Closure',$handlerAlias);
61+
}
62+
if ($class =$r->getClosureScopeClass()) {
63+
returnnewself($result,$class->name.'::'.$r->name,$handlerAlias);
64+
}
65+
66+
returnnewself($result,$r->name,$handlerAlias);
67+
}
68+
69+
returnnewself($result,\get_class($handler).'::__invoke',$handlerAlias);
70+
}
71+
72+
/**
73+
* @return mixed
74+
*/
75+
publicfunctiongetResult()
76+
{
77+
return$this->result;
78+
}
79+
80+
publicfunctiongetCallableName():string
81+
{
82+
return$this->callableName;
83+
}
84+
85+
publicfunctiongetHandlerAlias(): ?string
86+
{
87+
return$this->handlerAlias;
88+
}
89+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespaceSymfony\Component\Messenger\Stamp;
13+
14+
/**
15+
* Marker stamp identifying a message sent by the `SendMessageMiddleware`.
16+
*
17+
* @see \Symfony\Component\Messenger\Middleware\SendMessageMiddleware
18+
*
19+
* @author Maxime Steinhausser <maxime.steinhausser@gmail.com>
20+
*
21+
* @experimental in 4.2
22+
*/
23+
finalclass SentStampimplements StampInterface
24+
{
25+
private$senderClass;
26+
private$senderAlias;
27+
28+
publicfunction__construct(string$senderClass,string$senderAlias =null)
29+
{
30+
$this->senderAlias =$senderAlias;
31+
$this->senderClass =$senderClass;
32+
}
33+
34+
publicfunctiongetSenderClass():string
35+
{
36+
return$this->senderClass;
37+
}
38+
39+
publicfunctiongetSenderAlias(): ?string
40+
{
41+
return$this->senderAlias;
42+
}
43+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespaceSymfony\Component\Messenger\Tests\Handler;
13+
14+
usePHPUnit\Framework\TestCase;
15+
useSymfony\Component\Messenger\Envelope;
16+
useSymfony\Component\Messenger\Handler\HandlersLocator;
17+
useSymfony\Component\Messenger\Tests\Fixtures\DummyMessage;
18+
19+
class HandlersLocatorTestextends TestCase
20+
{
21+
publicfunctiontestItYieldsProvidedAliasAsKey()
22+
{
23+
$handler =$this->createPartialMock(\stdClass::class,array('__invoke'));
24+
$locator =newHandlersLocator(array(
25+
DummyMessage::class =>array('dummy' =>$handler),
26+
));
27+
28+
$this->assertSame(array('dummy' =>$handler),iterator_to_array($locator->getHandlers(newEnvelope(newDummyMessage('a')))));
29+
}
30+
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp