Skip to content

Commit 7088a74

Browse files
committed
[Messenger] Add middleware allowing just for a single handler
1 parent 0f653d8 commit 7088a74

File tree

5 files changed

+120
-1
lines changed

5 files changed

+120
-1
lines changed

src/Symfony/Bundle/FrameworkBundle/Resources/config/messenger.xml

+3
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,9 @@
2929
<service id="messenger.middleware.call_message_handler" class="Symfony\Component\Messenger\Middleware\HandleMessageMiddleware" abstract="true">
3030
<argument /> <!-- Bus handler resolver -->
3131
</service>
32+
<service id="messenger.middleware.allow_single_handler" class="Symfony\Component\Messenger\Middleware\AllowSingleHandlerMiddleware" abstract="true">
33+
<argument /> <!-- Bus handler resolver -->
34+
</service>
3235

3336
<service id="messenger.middleware.validation" class="Symfony\Component\Messenger\Middleware\ValidationMiddleware" abstract="true">
3437
<argument type="service" id="validator" />

src/Symfony/Component/Messenger/CHANGELOG.md

+2-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@ CHANGELOG
1919
* [BC BREAK] The `EncoderInterface` and `DecoderInterface` have been replaced by a unified `Symfony\Component\Messenger\Transport\Serialization\SerializerInterface`.
2020
* [BC BREAK] The locator passed to `ContainerHandlerLocator` should not prefix its keys by "handler." anymore
2121
* [BC BREAK] The `AbstractHandlerLocator::getHandler()` method uses `?callable` as return type
22-
22+
* Added `AllowSingleHandlerMiddleware` for message buses which behave like command buses.
23+
2324
4.1.0
2425
-----
2526

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
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+
namespace Symfony\Component\Messenger\Exception;
13+
14+
/**
15+
* @author Kamil Kokot <kamil@kokot.me>
16+
*/
17+
class MoreThanOneHandlerForMessageException extends \LogicException implements ExceptionInterface
18+
{
19+
}
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+
namespace Symfony\Component\Messenger\Middleware;
13+
14+
use Symfony\Component\Messenger\Exception\MoreThanOneHandlerForMessageException;
15+
use Symfony\Component\Messenger\Handler\ChainHandler;
16+
use Symfony\Component\Messenger\Handler\Locator\HandlerLocatorInterface;
17+
18+
/**
19+
* @author Kamil Kokot <kamil@kokot.me>
20+
*/
21+
class AllowSingleHandlerMiddleware implements MiddlewareInterface
22+
{
23+
private $messageHandlerResolver;
24+
25+
public function __construct(HandlerLocatorInterface $messageHandlerResolver)
26+
{
27+
$this->messageHandlerResolver = $messageHandlerResolver;
28+
}
29+
30+
/**
31+
* {@inheritdoc}
32+
*/
33+
public function handle($message, callable $next)
34+
{
35+
$handler = $this->messageHandlerResolver->resolve($message);
36+
37+
if ($handler instanceof ChainHandler) {
38+
throw new MoreThanOneHandlerForMessageException(sprintf('More than one handler for message "%s".', \get_class($message)));
39+
}
40+
41+
return $next($message);
42+
}
43+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
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+
namespace Symfony\Component\Messenger\Tests\Middleware;
13+
14+
use PHPUnit\Framework\TestCase;
15+
use Symfony\Component\Messenger\Handler\ChainHandler;
16+
use Symfony\Component\Messenger\Handler\Locator\HandlerLocator;
17+
use Symfony\Component\Messenger\Middleware\AllowSingleHandlerMiddleware;
18+
use Symfony\Component\Messenger\Tests\Fixtures\DummyMessage;
19+
20+
class AllowSingleHandlerMiddlewareTest extends TestCase
21+
{
22+
public function testItCallsNextMiddlewareAndReturnsItsResult(): void
23+
{
24+
$message = new DummyMessage('Hey');
25+
26+
$handler = $this->createPartialMock(\stdClass::class, array('__invoke'));
27+
$handler->method('__invoke')->willReturn('Hello');
28+
29+
$next = $this->createPartialMock(\stdClass::class, array('__invoke'));
30+
$next->expects($this->once())->method('__invoke')->with($message)->willReturn('Foo');
31+
32+
$middleware = new AllowSingleHandlerMiddleware(new HandlerLocator(array(
33+
DummyMessage::class => $handler,
34+
)));
35+
36+
$this->assertSame('Foo', $middleware->handle($message, $next));
37+
}
38+
39+
/**
40+
* @expectedException \Symfony\Component\Messenger\Exception\MoreThanOneHandlerForMessageException
41+
* @expectedExceptionMessage More than one handler for message "Symfony\Component\Messenger\Tests\Fixtures\DummyMessage".
42+
*/
43+
public function testItThrowsAnExceptionIfHandlerIsChainHandler(): void
44+
{
45+
$next = $this->createPartialMock(\stdClass::class, array('__invoke'));
46+
47+
$middleware = new AllowSingleHandlerMiddleware(new HandlerLocator([
48+
DummyMessage::class => new ChainHandler(array(new \stdClass(), new \stdClass())),
49+
]));
50+
51+
$middleware->handle(new DummyMessage('Hey'), $next);
52+
}
53+
}

0 commit comments

Comments
 (0)