8000 [WIP] [Messenger] Locate exactly one handler by gquemener · Pull Request #40254 · symfony/symfony · GitHub
[go: up one dir, main page]

Skip to content

[WIP] [Messenger] Locate exactly one handler #40254

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?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\Exception;

class MultipleHandlersForMessageException extends LogicException
{
public function __construct(string $messageType)
{
parent::__construct(sprintf('Multiple handlers for message "%s"', $messageType));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<?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\Handler;

use Symfony\Component\Messenger\Envelope;
use Symfony\Component\Messenger\Exception\MultipleHandlersForMessageException;
use Symfony\Component\Messenger\Exception\NoHandlerForMessageException;

final class ExactlyOneHandlerLocator implements HandlersLocatorInterface
{
private $handlers;

public function __construct(array $handlers)
{
foreach ($handlers as $type => $h) {
if (\count($h) > 1) {
throw new MultipleHandlersForMessageException($type);
}
}

$this->handlers = $handlers;
}

public function getHandlers(Envelope $envelope): iterable
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this need a dock-block?

    /**
     * {@inheritdoc}
     *
     * @throws NoHandlerForMessageException When no handler is found class
     */

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, I'll fix all CS if this feature gets interest. Thanks for pointing it out 👍

{
$type = \get_class($envelope->getMessage());
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit pick: This variable is named $class is similar function. e.g. HandlersLocator.php line 69

if (!isset($this->handlers[$type])) {
throw new NoHandlerForMessageException($type);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't the error message include the message type, rather that the type/class name

throw new NoHandlerForMessageException($this->handlers[$type]);

Theory being the error message 'Multiple handlers for message "%s"', thus, does this mean $envelope->getMessage()?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this specific case, $type holds the message type and $this->handlers[$type] is not set.

Theory being the error message 'Multiple handlers for message "%s"', thus, does this mean $envelope->getMessage()?

I don't understand what you mean.

}

yield $this->handlers[$type][0];
}
}
8000
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
<?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\HandlerDescriptor;
use Symfony\Component\Messenger\Stamp\ReceivedStamp;
use Symfony\Component\Messenger\Tests\Fixtures\DummyMessage;
use Symfony\Component\Messenger\Handler\HandlersLocatorInterface;
use Symfony\Component\Messenger\Handler\ExactlyOneHandlerLocator;
use Symfony\Component\Messenger\Exception\MultipleHandlersForMessageException;
use Symfony\Bundle\FrameworkBundle\Tests\Fixtures\Messenger\SecondMessage;
use Symfony\Component\Messenger\Exception\NoHandlerForMessageException;

class ExactlyOneHandlerLocatorTest extends TestCase
{
public function testItIsAHandlerLocator(): void
{
$this->assertInstanceOf(HandlersLocatorInterface::class, new ExactlyOneHandlerLocator([]));
}

public function testItProvidesAHandler(): void
{
$handler1 = $this->createPartialMock(ExactlyOneHandlerLocatorTestCallable::class, ['__invoke']);
$handler2 = $this->createPartialMock(ExactlyOneHandlerLocatorTestCallable::class, ['__invoke']);

$locator = new ExactlyOneHandlerLocator([
DummyMessage::class => [$handler1],
SecondMessage::class => [$handler2],
]);

$this->assertSame([$handler1], iterator_to_array($locator->getHandlers(
new Envelope(new DummyMessage('Body'), [new ReceivedStamp('transportName')])
)));
}

public function testItThrowsAnExceptionWhenMultipleHandlersMatchesMessage()
{
$this->expectException(MultipleHandlersForMessageException::class);

new ExactlyOneHandlerLocator([
DummyMessage::class => [
$this->createPartialMock(ExactlyOneHandlerLocatorTestCallable::class, ['__invoke']),
$this->createPartialMock(ExactlyOneHandlerLocatorTestCallable::class, ['__invoke']),
],
]);
}

public function testItThrowsExceptionWhenNoHandlerMatchesMessage(): void
{
$this->expectException(NoHandlerForMessageException::class);

$locator = new ExactlyOneHandlerLocator([]);
iterator_to_array($locator->getHandlers(
new Envelope(new DummyMessage('Body'), [new ReceivedStamp('transportName')])
));
}
}

class ExactlyOneHandlerLocatorTestCallable
{
public function __invoke()
{
}
}
0