Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
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 <!-- see https://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/10661 Based on #29159 This 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 handler IMHO, `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
- Loading branch information
Showing
16 changed files
with
325 additions
and
16 deletions.
There are no files selected for viewing
This file contains 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
This file contains 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
This file contains 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
This file contains 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
This file contains 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
This file contains 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
This file contains 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
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
<?php | ||
|
||
/* | ||
* This file is part of the Symfony package. | ||
* | ||
* (c) Fabien Potencier <fabien@symfony.com> | ||
* | ||
* For the full copyright and license information, please view the LICENSE | ||
* file that was distributed with this source code. | ||
*/ | ||
|
||
namespace Symfony\Component\Messenger\Stamp; | ||
|
||
/** | ||
* Stamp identifying a message handled by the `HandleMessageMiddleware` middleware | ||
* and storing the handler returned value. | ||
* | ||
* @see \Symfony\Component\Messenger\Middleware\HandleMessageMiddleware | ||
* | ||
* @author Maxime Steinhausser <maxime.steinhausser@gmail.com> | ||
* | ||
* @experimental in 4.2 | ||
*/ | ||
final class HandledStamp implements StampInterface | ||
{ | ||
private $result; | ||
private $callableName; | ||
private $handlerAlias; | ||
|
||
/** | ||
* @param mixed $result The returned value of the message handler | ||
*/ | ||
public function __construct($result, string $callableName, string $handlerAlias = null) | ||
{ | ||
$this->result = $result; | ||
$this->callableName = $callableName; | ||
$this->handlerAlias = $handlerAlias; | ||
} | ||
|
||
/** | ||
* @param mixed $result The returned value of the message handler | ||
*/ | ||
public static function fromCallable(callable $handler, $result, string $handlerAlias = null): self | ||
{ | ||
if (\is_array($handler)) { | ||
if (\is_object($handler[0])) { | ||
return new self($result, \get_class($handler[0]).'::'.$handler[1], $handlerAlias); | ||
} | ||
|
||
return new self($result, $handler[0].'::'.$handler[1], $handlerAlias); | ||
} | ||
|
||
if (\is_string($handler)) { | ||
return new self($result, $handler, $handlerAlias); | ||
} | ||
|
||
if ($handler instanceof \Closure) { | ||
$r = new \ReflectionFunction($handler); | ||
if (false !== strpos($r->name, '{closure}')) { | ||
return new self($result, 'Closure', $handlerAlias); | ||
} | ||
if ($class = $r->getClosureScopeClass()) { | ||
return new self($result, $class->name.'::'.$r->name, $handlerAlias); | ||
} | ||
|
||
return new self($result, $r->name, $handlerAlias); | ||
} | ||
|
||
return new self($result, \get_class($handler).'::__invoke', $handlerAlias); | ||
} | ||
|
||
/** | ||
* @return mixed | ||
*/ | ||
public function getResult() | ||
{ | ||
return $this->result; | ||
} | ||
|
||
public function getCallableName(): string | ||
{ | ||
return $this->callableName; | ||
} | ||
|
||
public function getHandlerAlias(): ?string | ||
{ | ||
return $this->handlerAlias; | ||
} | ||
} |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
<?php | ||
|
||
/* | ||
* This file is part of the Symfony package. | ||
* | ||
* (c) Fabien Potencier <fabien@symfony.com> | ||
* | ||
* For the full copyright and license information, please view the LICENSE | ||
* file that was distributed with this source code. | ||
*/ | ||
|
||
namespace Symfony\Component\Messenger\Stamp; | ||
|
||
/** | ||
* Marker stamp identifying a message sent by the `SendMessageMiddleware`. | ||
* | ||
* @see \Symfony\Component\Messenger\Middleware\SendMessageMiddleware | ||
* | ||
* @author Maxime Steinhausser <maxime.steinhausser@gmail.com> | ||
* | ||
* @experimental in 4.2 | ||
*/ | ||
final class SentStamp implements StampInterface | ||
{ | ||
private $senderClass; | ||
private $senderAlias; | ||
|
||
public function __construct(string $senderClass, string $senderAlias = null) | ||
{ | ||
$this->senderAlias = $senderAlias; | ||
$this->senderClass = $senderClass; | ||
} | ||
|
||
public function getSenderClass(): string | ||
{ | ||
return $this->senderClass; | ||
} | ||
|
||
public function getSenderAlias(): ?string | ||
{ | ||
return $this->senderAlias; | ||
} | ||
} |
30 changes: 30 additions & 0 deletions
30
src/Symfony/Component/Messenger/Tests/Handler/HandlersLocatorTest.php
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
<?php | ||
|
||
/* | ||
* This file is part of the Symfony package. | ||
* | ||
* (c) Fabien Potencier <fabien@symfony.com> | ||
* | ||
* For the full copyright and license information, please view the LICENSE | ||
* file that was distributed with this source code. | ||
*/ | ||
|
||
namespace Symfony\Component\Messenger\Tests\Handler; | ||
|
||
use PHPUnit\Framework\TestCase; | ||
use Symfony\Component\Messenger\Envelope; | ||
use Symfony\Component\Messenger\Handler\HandlersLocator; | ||
use Symfony\Component\Messenger\Tests\Fixtures\DummyMessage; | ||
|
||
class HandlersLocatorTest extends TestCase | ||
{ | ||
public function testItYieldsProvidedAliasAsKey() | ||
{ | ||
$handler = $this->createPartialMock(\stdClass::class, array('__invoke')); | ||
$locator = new HandlersLocator(array( | ||
DummyMessage::class => array('dummy' => $handler), | ||
)); | ||
|
||
$this->assertSame(array('dummy' => $handler), iterator_to_array($locator->getHandlers(new Envelope(new DummyMessage('a'))))); | ||
} | ||
} |
This file contains 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
This file contains 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
Oops, something went wrong.