Dispatching two events when a message is sent & handled

This commit is contained in:
Ryan Weaver 2019-03-22 12:10:25 -04:00
parent 6ff11858b1
commit a7ad1b4ccc
3 changed files with 80 additions and 2 deletions

View File

@ -0,0 +1,44 @@
<?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\Event;
use Symfony\Component\EventDispatcher\Event;
use Symfony\Component\Messenger\Envelope;
/**
* Event is dispatched before a message is sent to the transport.
*
* The event is *only* dispatched if the message will actually
* be sent to at least one transport. If the message is sent
* to multiple transports, the message is dispatched only one time.
*
* @author Ryan Weaver <ryan@symfonycasts.com>
*/
class SendMessageToTransportsEvent extends Event
{
private $envelope;
public function __construct(Envelope $envelope)
{
$this->envelope = $envelope;
}
public function getEnvelope(): Envelope
{
return $this->envelope;
}
public function setEnvelope(Envelope $envelope)
{
$this->envelope = $envelope;
}
}

View File

@ -13,7 +13,9 @@ namespace Symfony\Component\Messenger\Middleware;
use Psr\Log\LoggerAwareTrait;
use Psr\Log\NullLogger;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\Messenger\Envelope;
use Symfony\Component\Messenger\Event\SendMessageToTransportsEvent;
use Symfony\Component\Messenger\Stamp\ReceivedStamp;
use Symfony\Component\Messenger\Stamp\RedeliveryStamp;
use Symfony\Component\Messenger\Stamp\SentStamp;
@ -30,10 +32,12 @@ class SendMessageMiddleware implements MiddlewareInterface
use LoggerAwareTrait;
private $sendersLocator;
private $eventDispatcher;
public function __construct(SendersLocatorInterface $sendersLocator)
public function __construct(SendersLocatorInterface $sendersLocator, EventDispatcherInterface $eventDispatcher = null)
{
$this->sendersLocator = $sendersLocator;
$this->eventDispatcher = $eventDispatcher;
$this->logger = new NullLogger();
}
@ -58,7 +62,15 @@ class SendMessageMiddleware implements MiddlewareInterface
/** @var RedeliveryStamp|null $redeliveryStamp */
$redeliveryStamp = $envelope->last(RedeliveryStamp::class);
foreach ($this->sendersLocator->getSenders($envelope, $handle) as $alias => $sender) {
$senders = \iterator_to_array($this->sendersLocator->getSenders($envelope, $handle));
if (null !== $this->eventDispatcher && \count($senders) > 0) {
$event = new SendMessageToTransportsEvent($envelope);
$this->eventDispatcher->dispatch($event);
$envelope = $event->getEnvelope();
}
foreach ($senders as $alias => $sender) {
// on redelivery, only deliver to the given sender
if (null !== $redeliveryStamp && !$redeliveryStamp->shouldRedeliverToSender(\get_class($sender), $alias)) {
continue;

View File

@ -11,7 +11,9 @@
namespace Symfony\Component\Messenger\Tests\Middleware;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\Messenger\Envelope;
use Symfony\Component\Messenger\Event\SendMessageToTransportsEvent;
use Symfony\Component\Messenger\Middleware\SendMessageMiddleware;
use Symfony\Component\Messenger\Stamp\ReceivedStamp;
use Symfony\Component\Messenger\Stamp\RedeliveryStamp;
@ -202,4 +204,24 @@ class SendMessageMiddlewareTest extends MiddlewareTestCase
$this->assertNull($envelope->last(SentStamp::class), 'it does not add sent stamp for received messages');
}
public function testItDispatchesTheEventOnceTime()
{
$envelope = new Envelope(new DummyMessage('original envelope'));
$dispatcher = $this->createMock(EventDispatcherInterface::class);
$dispatcher->expects($this->once())
->method('dispatch')
->with(new SendMessageToTransportsEvent($envelope));
$sender1 = $this->getMockBuilder(SenderInterface::class)->getMock();
$sender2 = $this->getMockBuilder(SenderInterface::class)->getMock();
$middleware = new SendMessageMiddleware(new SendersLocator([DummyMessage::class => [$sender1, $sender2]]), $dispatcher);
$sender1->expects($this->once())->method('send')->willReturn($envelope);
$sender2->expects($this->once())->method('send')->willReturn($envelope);
$middleware->handle($envelope, $this->getStackMock(false));
}
}