feature #28914 [Messenger] make Envelope first class citizen for middleware handlers (nicolas-grekas)

This PR was merged into the 4.2-dev branch.

Discussion
----------

[Messenger] make Envelope first class citizen for middleware handlers

| Q             | A
| ------------- | ---
| Branch?       | 4.2
| Bug fix?      | no
| New feature?  | no
| BC breaks?    | yes
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | -
| License       | MIT
| Doc PR        | -

This PR sits on top of #28909 so that only the 2nd commit should be reviewed for now, until I rebase it.
This idea has already been proposed and rejected in #27322.
Yet, now that I've reviewed in depth the component, I politely but strongly suggest to reconsider.
Middleware handlers are the central piece of the routing layer.
When `dispatch()` accepts `object|Envelope`, it's because it sits on the outer boundary of the component. `handle()` on the contrary plugs inside its core routing logic, so that it's very legitimate to require them to deal with `Envelope` objects. Yes, some middleware care only about the message inside. That's fine calling `getMessage()` for them.

Right now, we built a complex magic layer that acts as a band-aid *just* to save this call to `getMessage()`. For middleware that want the envelope, we require an additional interface that magically *changes* the expected argument. That's very fragile design: it breaks the `L` in `SOLID`...

Looking at the diff stat, this is most natural.

Commits
-------

ae46a436e7 [Messenger] make Envelope first class citizen for middleware handlers
This commit is contained in:
Samuel ROZE 2018-10-21 14:14:24 +01:00
commit f24794da31
31 changed files with 140 additions and 232 deletions

View File

@ -13,6 +13,7 @@ namespace Symfony\Bridge\Doctrine\Messenger;
use Doctrine\Common\Persistence\ManagerRegistry;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\Messenger\Envelope;
use Symfony\Component\Messenger\Middleware\MiddlewareInterface;
/**
@ -31,7 +32,10 @@ class DoctrineTransactionMiddleware implements MiddlewareInterface
$this->entityManagerName = $entityManagerName;
}
public function handle($message, callable $next): void
/**
* {@inheritdoc}
*/
public function handle(Envelope $envelope, callable $next): void
{
$entityManager = $this->managerRegistry->getManager($this->entityManagerName);
@ -41,7 +45,7 @@ class DoctrineTransactionMiddleware implements MiddlewareInterface
$entityManager->getConnection()->beginTransaction();
try {
$next($message);
$next($envelope);
$entityManager->flush();
$entityManager->getConnection()->commit();
} catch (\Throwable $exception) {

View File

@ -14,7 +14,6 @@ namespace Symfony\Component\Messenger\Asynchronous\Middleware;
use Symfony\Component\Messenger\Asynchronous\Routing\AbstractSenderLocator;
use Symfony\Component\Messenger\Asynchronous\Routing\SenderLocatorInterface;
use Symfony\Component\Messenger\Envelope;
use Symfony\Component\Messenger\EnvelopeAwareInterface;
use Symfony\Component\Messenger\Middleware\MiddlewareInterface;
use Symfony\Component\Messenger\Stamp\ReceivedStamp;
@ -22,7 +21,7 @@ use Symfony\Component\Messenger\Stamp\ReceivedStamp;
* @author Samuel Roze <samuel.roze@gmail.com>
* @author Tobias Schultze <http://tobion.de>
*/
class SendMessageMiddleware implements MiddlewareInterface, EnvelopeAwareInterface
class SendMessageMiddleware implements MiddlewareInterface
{
private $senderLocator;
private $messagesToSendAndHandleMapping;
@ -34,11 +33,9 @@ class SendMessageMiddleware implements MiddlewareInterface, EnvelopeAwareInterfa
}
/**
* @param Envelope $envelope
*
* {@inheritdoc}
*/
public function handle($envelope, callable $next): void
public function handle(Envelope $envelope, callable $next): void
{
if ($envelope->get(ReceivedStamp::class)) {
// It's a received message. Do not send it back:

View File

@ -7,6 +7,8 @@ CHANGELOG
* The component is not experimental anymore
* All the changes below are BC BREAKS
* `MessageBusInterface::dispatch()` and `MiddlewareInterface::handle()` now return `void`
* `MiddlewareInterface::handle()` now require an `Envelope` as first argument
* `EnvelopeAwareInterface` has been removed
* The signature of `Amqp*` classes changed to take a `Connection` as a first argument and an optional
`Serializer` as a second argument.
* `SenderLocator` has been renamed to `ContainerSenderLocator`

View File

@ -35,16 +35,6 @@ final class Envelope
}
}
/**
* Wrap a message into an envelope if not already wrapped.
*
* @param Envelope|object $message
*/
public static function wrap($message): self
{
return $message instanceof self ? $message : new self($message);
}
/**
* @return Envelope a new Envelope instance with additional stamp
*/
@ -59,15 +49,6 @@ final class Envelope
return $cloned;
}
public function withMessage($message): self
{
$cloned = clone $this;
$cloned->message = $message;
return $cloned;
}
public function get(string $stampFqcn): ?StampInterface
{
return $this->stamps[$stampFqcn] ?? null;
@ -88,15 +69,4 @@ final class Envelope
{
return $this->message;
}
/**
* @param object $target
*
* @return Envelope|object The original message or the envelope if the target supports it
* (i.e implements {@link EnvelopeAwareInterface}).
*/
public function getMessageFor($target)
{
return $target instanceof EnvelopeAwareInterface ? $this : $this->message;
}
}

View File

@ -1,21 +0,0 @@
<?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;
/**
* A Messenger protagonist aware of the message envelope and its content.
*
* @author Maxime Steinhausser <maxime.steinhausser@gmail.com>
*/
interface EnvelopeAwareInterface
{
}

View File

@ -44,34 +44,21 @@ class MessageBus implements MessageBusInterface
throw new InvalidArgumentException(sprintf('Invalid type for message argument. Expected object, but got "%s".', \gettype($message)));
}
\call_user_func($this->callableForNextMiddleware(0, Envelope::wrap($message)), $message);
$this->callableForNextMiddleware(0)($message instanceof Envelope ? $message : new Envelope($message));
}
private function callableForNextMiddleware(int $index, Envelope $currentEnvelope): callable
private function callableForNextMiddleware(int $index): callable
{
if (null === $this->indexedMiddlewareHandlers) {
$this->indexedMiddlewareHandlers = \is_array($this->middlewareHandlers) ? array_values($this->middlewareHandlers) : iterator_to_array($this->middlewareHandlers, false);
}
if (!isset($this->indexedMiddlewareHandlers[$index])) {
return function () {};
return static function () {};
}
$middleware = $this->indexedMiddlewareHandlers[$index];
return function ($message) use ($middleware, $index, $currentEnvelope) {
if ($message instanceof Envelope) {
$currentEnvelope = $message;
} else {
$message = $currentEnvelope->withMessage($message);
}
if (!$middleware instanceof EnvelopeAwareInterface) {
// Do not provide the envelope if the middleware cannot read it:
$message = $message->getMessage();
}
$middleware->handle($message, $this->callableForNextMiddleware($index + 1, $currentEnvelope));
return function (Envelope $envelope) use ($index) {
$this->indexedMiddlewareHandlers[$index]->handle($envelope, $this->callableForNextMiddleware($index + 1));
};
}
}

View File

@ -11,6 +11,7 @@
namespace Symfony\Component\Messenger\Middleware;
use Symfony\Component\Messenger\Envelope;
use Symfony\Component\Messenger\Exception\NoHandlerForMessageException;
/**
@ -18,10 +19,13 @@ use Symfony\Component\Messenger\Exception\NoHandlerForMessageException;
*/
class AllowNoHandlerMiddleware implements MiddlewareInterface
{
public function handle($message, callable $next): void
/**
* {@inheritdoc}
*/
public function handle(Envelope $envelope, callable $next): void
{
try {
$next($message);
$next($envelope);
} catch (NoHandlerForMessageException $e) {
// We allow not having a handler for this message.
}

View File

@ -12,7 +12,6 @@
namespace Symfony\Component\Messenger\Middleware\Enhancers;
use Symfony\Component\Messenger\Envelope;
use Symfony\Component\Messenger\EnvelopeAwareInterface;
use Symfony\Component\Messenger\Middleware\MiddlewareInterface;
/**
@ -20,7 +19,7 @@ use Symfony\Component\Messenger\Middleware\MiddlewareInterface;
*
* @author Maxime Steinhausser <maxime.steinhausser@gmail.com>
*/
class ActivationMiddlewareDecorator implements MiddlewareInterface, EnvelopeAwareInterface
class ActivationMiddlewareDecorator implements MiddlewareInterface
{
private $inner;
private $activated;
@ -35,12 +34,12 @@ class ActivationMiddlewareDecorator implements MiddlewareInterface, EnvelopeAwar
}
/**
* @param Envelope $envelope
* {@inheritdoc}
*/
public function handle($envelope, callable $next): void
public function handle(Envelope $envelope, callable $next): void
{
if (\is_callable($this->activated) ? ($this->activated)($envelope) : $this->activated) {
$this->inner->handle($envelope->getMessageFor($this->inner), $next);
$this->inner->handle($envelope, $next);
} else {
$next($envelope);
}

View File

@ -12,7 +12,6 @@
namespace Symfony\Component\Messenger\Middleware\Enhancers;
use Symfony\Component\Messenger\Envelope;
use Symfony\Component\Messenger\EnvelopeAwareInterface;
use Symfony\Component\Messenger\Middleware\MiddlewareInterface;
use Symfony\Component\Stopwatch\Stopwatch;
@ -21,7 +20,7 @@ use Symfony\Component\Stopwatch\Stopwatch;
*
* @author Maxime Steinhausser <maxime.steinhausser@gmail.com>
*/
class TraceableMiddleware implements MiddlewareInterface, EnvelopeAwareInterface
class TraceableMiddleware implements MiddlewareInterface
{
private $inner;
private $stopwatch;
@ -37,9 +36,9 @@ class TraceableMiddleware implements MiddlewareInterface, EnvelopeAwareInterface
}
/**
* @param Envelope $envelope
* {@inheritdoc}
*/
public function handle($envelope, callable $next): void
public function handle(Envelope $envelope, callable $next): void
{
$class = \get_class($this->inner);
$eventName = 'c' === $class[0] && 0 === strpos($class, "class@anonymous\0") ? get_parent_class($class).'@anonymous' : $class;
@ -51,9 +50,9 @@ class TraceableMiddleware implements MiddlewareInterface, EnvelopeAwareInterface
$this->stopwatch->start($eventName, $this->eventCategory);
try {
$this->inner->handle($envelope->getMessageFor($this->inner), function ($message) use ($next, $eventName) {
$this->inner->handle($envelope, function (Envelope $envelope) use ($next, $eventName) {
$this->stopwatch->stop($eventName);
$next($message);
$next($envelope);
$this->stopwatch->start($eventName, $this->eventCategory);
});
} finally {

View File

@ -11,6 +11,7 @@
namespace Symfony\Component\Messenger\Middleware;
use Symfony\Component\Messenger\Envelope;
use Symfony\Component\Messenger\Handler\Locator\HandlerLocatorInterface;
/**
@ -28,11 +29,12 @@ class HandleMessageMiddleware implements MiddlewareInterface
/**
* {@inheritdoc}
*/
public function handle($message, callable $next): void
public function handle(Envelope $envelope, callable $next): void
{
$message = $envelope->getMessage();
$handler = $this->messageHandlerResolver->resolve($message);
$handler($message);
$next($message);
$next($envelope);
}
}

View File

@ -12,6 +12,7 @@
namespace Symfony\Component\Messenger\Middleware;
use Psr\Log\LoggerInterface;
use Symfony\Component\Messenger\Envelope;
/**
* @author Samuel Roze <samuel.roze@gmail.com>
@ -28,12 +29,13 @@ class LoggingMiddleware implements MiddlewareInterface
/**
* {@inheritdoc}
*/
public function handle($message, callable $next): void
public function handle(Envelope $envelope, callable $next): void
{
$message = $envelope->getMessage();
$this->logger->debug('Starting handling message {class}', $this->createContext($message));
try {
$next($message);
$next($envelope);
} catch (\Throwable $e) {
$this->logger->warning('An exception occurred while handling message {class}', array_merge(
$this->createContext($message),

View File

@ -11,13 +11,23 @@
namespace Symfony\Component\Messenger\Middleware;
use Symfony\Component\Messenger\Envelope;
/**
* @author Samuel Roze <samuel.roze@gmail.com>
*/
interface MiddlewareInterface
{
/**
* @param object $message
* @param callable|NextInterface $next
*/
public function handle($message, callable $next): void;
public function handle(Envelope $envelope, callable $next): void;
}
/**
* @internal
*/
interface NextInterface
{
public function __invoke(Envelope $envelope): void;
}

View File

@ -12,7 +12,6 @@
namespace Symfony\Component\Messenger\Middleware;
use Symfony\Component\Messenger\Envelope;
use Symfony\Component\Messenger\EnvelopeAwareInterface;
use Symfony\Component\Messenger\Exception\ValidationFailedException;
use Symfony\Component\Messenger\Stamp\ValidationStamp;
use Symfony\Component\Validator\Validator\ValidatorInterface;
@ -20,7 +19,7 @@ use Symfony\Component\Validator\Validator\ValidatorInterface;
/**
* @author Tobias Nyholm <tobias.nyholm@gmail.com>
*/
class ValidationMiddleware implements MiddlewareInterface, EnvelopeAwareInterface
class ValidationMiddleware implements MiddlewareInterface
{
private $validator;
@ -30,9 +29,9 @@ class ValidationMiddleware implements MiddlewareInterface, EnvelopeAwareInterfac
}
/**
* @param Envelope $envelope
* {@inheritdoc}
*/
public function handle($envelope, callable $next): void
public function handle(Envelope $envelope, callable $next): void
{
$message = $envelope->getMessage();
$groups = null;

View File

@ -26,7 +26,7 @@ class SendMessageMiddlewareTest extends TestCase
public function testItSendsTheMessageToAssignedSender()
{
$message = new DummyMessage('Hey');
$envelope = Envelope::wrap($message);
$envelope = new Envelope($message);
$sender = $this->getMockBuilder(SenderInterface::class)->getMock();
$next = $this->createPartialMock(\stdClass::class, array('__invoke'));
@ -40,7 +40,7 @@ class SendMessageMiddlewareTest extends TestCase
public function testItSendsTheMessageToAssignedSenderWithPreWrappedMessage()
{
$envelope = Envelope::wrap(new DummyMessage('Hey'));
$envelope = new Envelope(new DummyMessage('Hey'));
$sender = $this->getMockBuilder(SenderInterface::class)->getMock();
$next = $this->createPartialMock(\stdClass::class, array('__invoke'));
@ -55,7 +55,7 @@ class SendMessageMiddlewareTest extends TestCase
public function testItAlsoCallsTheNextMiddlewareBasedOnTheMessageClass()
{
$message = new DummyMessage('Hey');
$envelope = Envelope::wrap($message);
$envelope = new Envelope($message);
$sender = $this->getMockBuilder(SenderInterface::class)->getMock();
$next = $this->createPartialMock(\stdClass::class, array('__invoke'));
@ -72,7 +72,7 @@ class SendMessageMiddlewareTest extends TestCase
public function testItAlsoCallsTheNextMiddlewareBasedOnTheMessageParentClass()
{
$message = new ChildDummyMessage('Hey');
$envelope = Envelope::wrap($message);
$envelope = new Envelope($message);
$sender = $this->getMockBuilder(SenderInterface::class)->getMock();
$next = $this->createPartialMock(\stdClass::class, array('__invoke'));
@ -89,7 +89,7 @@ class SendMessageMiddlewareTest extends TestCase
public function testItAlsoCallsTheNextMiddlewareBasedOnTheMessageInterface()
{
$message = new DummyMessage('Hey');
$envelope = Envelope::wrap($message);
$envelope = new Envelope($message);
$sender = $this->getMockBuilder(SenderInterface::class)->getMock();
$next = $this->createPartialMock(\stdClass::class, array('__invoke'));
@ -106,7 +106,7 @@ class SendMessageMiddlewareTest extends TestCase
public function testItAlsoCallsTheNextMiddlewareBasedOnWildcard()
{
$message = new DummyMessage('Hey');
$envelope = Envelope::wrap($message);
$envelope = new Envelope($message);
$sender = $this->getMockBuilder(SenderInterface::class)->getMock();
$next = $this->createPartialMock(\stdClass::class, array('__invoke'));
@ -123,7 +123,7 @@ class SendMessageMiddlewareTest extends TestCase
public function testItCallsTheNextMiddlewareWhenNoSenderForThisMessage()
{
$message = new DummyMessage('Hey');
$envelope = Envelope::wrap($message);
$envelope = new Envelope($message);
$next = $this->createPartialMock(\stdClass::class, array('__invoke'));
$middleware = new SendMessageMiddleware(new InMemorySenderLocator(null));
@ -135,7 +135,7 @@ class SendMessageMiddlewareTest extends TestCase
public function testItSkipsReceivedMessages()
{
$envelope = Envelope::wrap(new DummyMessage('Hey'))->with(new ReceivedStamp());
$envelope = (new Envelope(new DummyMessage('Hey')))->with(new ReceivedStamp());
$sender = $this->getMockBuilder(SenderInterface::class)->getMock();
$next = $this->createPartialMock(\stdClass::class, array('__invoke'));

View File

@ -670,7 +670,7 @@ class DummyReceiver implements ReceiverInterface
public function receive(callable $handler): void
{
for ($i = 0; $i < 3; ++$i) {
$handler(Envelope::wrap(new DummyMessage("Dummy $i")));
$handler(new Envelope(new DummyMessage("Dummy $i")));
}
}
@ -852,7 +852,7 @@ class HandlerOnUndefinedBus implements MessageSubscriberInterface
class UselessMiddleware implements MiddlewareInterface
{
public function handle($message, callable $next): void
public function handle(Envelope $message, callable $next): void
{
$next($message);
}

View File

@ -32,20 +32,9 @@ class EnvelopeTest extends TestCase
$this->assertSame($receivedStamp, $stamps[ReceivedStamp::class]);
}
public function testWrap()
{
$first = Envelope::wrap($dummy = new DummyMessage('dummy'));
$this->assertInstanceOf(Envelope::class, $first);
$this->assertSame($dummy, $first->getMessage());
$envelope = Envelope::wrap($first);
$this->assertSame($first, $envelope);
}
public function testWithReturnsNewInstance()
{
$envelope = Envelope::wrap($dummy = new DummyMessage('dummy'));
$envelope = new Envelope($dummy = new DummyMessage('dummy'));
$this->assertNotSame($envelope, $envelope->with(new ReceivedStamp()));
}
@ -61,7 +50,7 @@ class EnvelopeTest extends TestCase
public function testAll()
{
$envelope = Envelope::wrap($dummy = new DummyMessage('dummy'))
$envelope = (new Envelope($dummy = new DummyMessage('dummy')))
->with($receivedStamp = new ReceivedStamp())
->with($validationStamp = new ValidationStamp(array('foo')))
;

View File

@ -13,7 +13,6 @@ namespace Symfony\Component\Messenger\Tests;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Messenger\Envelope;
use Symfony\Component\Messenger\EnvelopeAwareInterface;
use Symfony\Component\Messenger\MessageBus;
use Symfony\Component\Messenger\MessageBusInterface;
use Symfony\Component\Messenger\Middleware\MiddlewareInterface;
@ -42,20 +41,21 @@ class MessageBusTest extends TestCase
public function testItCallsMiddleware()
{
$message = new DummyMessage('Hello');
$envelope = new Envelope($message);
$responseFromDepthMiddleware = 1234;
$firstMiddleware = $this->getMockBuilder(MiddlewareInterface::class)->getMock();
$firstMiddleware->expects($this->once())
->method('handle')
->with($message, $this->anything())
->will($this->returnCallback(function ($message, $next) {
$next($message);
->with($envelope, $this->anything())
->will($this->returnCallback(function ($envelope, $next) {
$next($envelope);
}));
$secondMiddleware = $this->getMockBuilder(MiddlewareInterface::class)->getMock();
$secondMiddleware->expects($this->once())
->method('handle')
->with($message, $this->anything())
->with($envelope, $this->anything())
;
$bus = new MessageBus(array(
@ -66,56 +66,29 @@ class MessageBusTest extends TestCase
$bus->dispatch($message);
}
public function testItKeepsTheEnvelopeEvenThroughAMiddlewareThatIsNotEnvelopeAware()
{
$message = new DummyMessage('Hello');
$envelope = new Envelope($message, new ReceivedStamp());
$firstMiddleware = $this->getMockBuilder(MiddlewareInterface::class)->getMock();
$firstMiddleware->expects($this->once())
->method('handle')
->with($message, $this->anything())
->will($this->returnCallback(function ($message, $next) {
$next($message);
}));
$secondMiddleware = $this->getMockBuilder(array(MiddlewareInterface::class, EnvelopeAwareInterface::class))->getMock();
$secondMiddleware->expects($this->once())
->method('handle')
->with($envelope, $this->anything())
;
$bus = new MessageBus(array(
$firstMiddleware,
$secondMiddleware,
));
$bus->dispatch($envelope);
}
public function testThatAMiddlewareCanAddSomeStampsToTheEnvelope()
{
$message = new DummyMessage('Hello');
$envelope = new Envelope($message, new ReceivedStamp());
$envelopeWithAnotherStamp = $envelope->with(new AnEnvelopeStamp());
$firstMiddleware = $this->getMockBuilder(array(MiddlewareInterface::class, EnvelopeAwareInterface::class))->getMock();
$firstMiddleware = $this->getMockBuilder(MiddlewareInterface::class)->getMock();
$firstMiddleware->expects($this->once())
->method('handle')
->with($envelope, $this->anything())
->will($this->returnCallback(function ($message, $next) {
$next($message->with(new AnEnvelopeStamp()));
->will($this->returnCallback(function ($envelope, $next) {
$next($envelope->with(new AnEnvelopeStamp()));
}));
$secondMiddleware = $this->getMockBuilder(MiddlewareInterface::class)->getMock();
$secondMiddleware->expects($this->once())
->method('handle')
->with($message, $this->anything())
->will($this->returnCallback(function ($message, $next) {
$next($message);
->with($envelopeWithAnotherStamp, $this->anything())
->will($this->returnCallback(function ($envelope, $next) {
$next($envelope);
}));
$thirdMiddleware = $this->getMockBuilder(array(MiddlewareInterface::class, EnvelopeAwareInterface::class))->getMock();
$thirdMiddleware = $this->getMockBuilder(MiddlewareInterface::class)->getMock();
$thirdMiddleware->expects($this->once())
->method('handle')
->with($envelopeWithAnotherStamp, $this->anything())
@ -141,12 +114,12 @@ class MessageBusTest extends TestCase
$firstMiddleware = $this->getMockBuilder(MiddlewareInterface::class)->getMock();
$firstMiddleware->expects($this->once())
->method('handle')
->with($message, $this->anything())
->will($this->returnCallback(function ($message, $next) use ($changedMessage) {
$next($changedMessage);
->with($envelope, $this->anything())
->will($this->returnCallback(function ($message, $next) use ($expectedEnvelope) {
$next($expectedEnvelope);
}));
$secondMiddleware = $this->getMockBuilder(array(MiddlewareInterface::class, EnvelopeAwareInterface::class))->getMock();
$secondMiddleware = $this->getMockBuilder(MiddlewareInterface::class)->getMock();
$secondMiddleware->expects($this->once())
->method('handle')
->with($expectedEnvelope, $this->anything())

View File

@ -12,6 +12,7 @@
namespace Symfony\Component\Messenger\Tests\Middleware;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Messenger\Envelope;
use Symfony\Component\Messenger\Exception\NoHandlerForMessageException;
use Symfony\Component\Messenger\Middleware\AllowNoHandlerMiddleware;
use Symfony\Component\Messenger\Tests\Fixtures\DummyMessage;
@ -21,12 +22,13 @@ class AllowNoHandlerMiddlewareTest extends TestCase
public function testItCallsNextMiddleware()
{
$message = new DummyMessage('Hey');
$envelope = new Envelope($message);
$next = $this->createPartialMock(\stdClass::class, array('__invoke'));
$next->expects($this->once())->method('__invoke')->with($message);
$next->expects($this->once())->method('__invoke')->with($envelope);
$middleware = new AllowNoHandlerMiddleware();
$middleware->handle($message, $next);
$middleware->handle($envelope, $next);
}
public function testItCatchesTheNoHandlerException()
@ -36,7 +38,7 @@ class AllowNoHandlerMiddlewareTest extends TestCase
$middleware = new AllowNoHandlerMiddleware();
$this->assertNull($middleware->handle(new DummyMessage('Hey'), $next));
$this->assertNull($middleware->handle(new Envelope(new DummyMessage('Hey')), $next));
}
/**
@ -49,6 +51,6 @@ class AllowNoHandlerMiddlewareTest extends TestCase
$next->expects($this->once())->method('__invoke')->will($this->throwException(new \RuntimeException('Something went wrong.')));
$middleware = new AllowNoHandlerMiddleware();
$middleware->handle(new DummyMessage('Hey'), $next);
$middleware->handle(new Envelope(new DummyMessage('Hey')), $next);
}
}

View File

@ -13,7 +13,6 @@ namespace Symfony\Component\Messenger\Tests\Middleware\Enhancers;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Messenger\Envelope;
use Symfony\Component\Messenger\EnvelopeAwareInterface;
use Symfony\Component\Messenger\Middleware\Enhancers\ActivationMiddlewareDecorator;
use Symfony\Component\Messenger\Middleware\MiddlewareInterface;
use Symfony\Component\Messenger\Tests\Fixtures\DummyMessage;
@ -26,13 +25,13 @@ class ActivationMiddlewareDecoratorTest extends TestCase
public function testExecuteMiddlewareOnActivated()
{
$message = new DummyMessage('Hello');
$envelope = Envelope::wrap($message);
$envelope = new Envelope($message);
$next = $this->createPartialMock(\stdClass::class, array('__invoke'));
$next->expects($this->never())->method('__invoke');
$middleware = $this->createMock(MiddlewareInterface::class);
$middleware->expects($this->once())->method('handle')->with($message, $next);
$middleware->expects($this->once())->method('handle')->with($envelope, $next);
$decorator = new ActivationMiddlewareDecorator($middleware, true);
@ -42,7 +41,7 @@ class ActivationMiddlewareDecoratorTest extends TestCase
public function testExecuteMiddlewareOnActivatedWithCallable()
{
$message = new DummyMessage('Hello');
$envelope = Envelope::wrap($message);
$envelope = new Envelope($message);
$activated = $this->createPartialMock(\stdClass::class, array('__invoke'));
$activated->expects($this->once())->method('__invoke')->with($envelope)->willReturn(true);
@ -51,25 +50,9 @@ class ActivationMiddlewareDecoratorTest extends TestCase
$next->expects($this->never())->method('__invoke');
$middleware = $this->createMock(MiddlewareInterface::class);
$middleware->expects($this->once())->method('handle')->with($message, $next);
$decorator = new ActivationMiddlewareDecorator($middleware, $activated);
$decorator->handle($envelope, $next);
}
public function testExecuteEnvelopeAwareMiddlewareWithEnvelope()
{
$message = new DummyMessage('Hello');
$envelope = Envelope::wrap($message);
$next = $this->createPartialMock(\stdClass::class, array('__invoke'));
$next->expects($this->never())->method('__invoke');
$middleware = $this->createMock(array(MiddlewareInterface::class, EnvelopeAwareInterface::class));
$middleware->expects($this->once())->method('handle')->with($envelope, $next);
$decorator = new ActivationMiddlewareDecorator($middleware, true);
$decorator = new ActivationMiddlewareDecorator($middleware, $activated);
$decorator->handle($envelope, $next);
}
@ -77,7 +60,7 @@ class ActivationMiddlewareDecoratorTest extends TestCase
public function testExecuteMiddlewareOnDeactivated()
{
$message = new DummyMessage('Hello');
$envelope = Envelope::wrap($message);
$envelope = new Envelope($message);
$next = $this->createPartialMock(\stdClass::class, array('__invoke'));
$next->expects($this->once())->method('__invoke')->with($envelope);

View File

@ -26,14 +26,14 @@ class TraceableMiddlewareTest extends TestCase
public function testHandle()
{
$busId = 'command_bus';
$envelope = Envelope::wrap($message = new DummyMessage('Hello'));
$envelope = new Envelope($message = new DummyMessage('Hello'));
$middleware = $this->getMockBuilder(MiddlewareInterface::class)->getMock();
$middleware->expects($this->once())
->method('handle')
->with($message, $this->anything())
->will($this->returnCallback(function ($message, callable $next) {
$next($message);
->with($envelope, $this->anything())
->will($this->returnCallback(function ($envelope, callable $next) {
$next($envelope);
}))
;
@ -41,7 +41,7 @@ class TraceableMiddlewareTest extends TestCase
$next
->expects($this->once())
->method('__invoke')
->with($message)
->with($envelope)
;
$stopwatch = $this->createMock(Stopwatch::class);
@ -67,14 +67,14 @@ class TraceableMiddlewareTest extends TestCase
public function testHandleWithException()
{
$busId = 'command_bus';
$envelope = Envelope::wrap($message = new DummyMessage('Hello'));
$envelope = new Envelope($message = new DummyMessage('Hello'));
$middleware = $this->getMockBuilder(MiddlewareInterface::class)->getMock();
$middleware->expects($this->once())
->method('handle')
->with($message, $this->anything())
->will($this->returnCallback(function ($message, callable $next) {
$next($message);
->with($envelope, $this->anything())
->will($this->returnCallback(function ($envelope, callable $next) {
$next($envelope);
}))
;

View File

@ -12,6 +12,7 @@
namespace Symfony\Component\Messenger\Tests\Middleware;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Messenger\Envelope;
use Symfony\Component\Messenger\Handler\Locator\HandlerLocator;
use Symfony\Component\Messenger\Middleware\HandleMessageMiddleware;
use Symfony\Component\Messenger\Tests\Fixtures\DummyMessage;
@ -21,6 +22,7 @@ class HandleMessageMiddlewareTest extends TestCase
public function testItCallsTheHandlerAndNextMiddleware()
{
$message = new DummyMessage('Hey');
$envelope = new Envelope($message);
$handler = $this->createPartialMock(\stdClass::class, array('__invoke'));
@ -31,8 +33,8 @@ class HandleMessageMiddlewareTest extends TestCase
)));
$handler->expects($this->once())->method('__invoke')->with($message);
$next->expects($this->once())->method('__invoke')->with($message);
$next->expects($this->once())->method('__invoke')->with($envelope);
$middleware->handle($message, $next);
$middleware->handle($envelope, $next);
}
}

View File

@ -13,6 +13,7 @@ namespace Symfony\Component\Messenger\Tests\Middleware;
use PHPUnit\Framework\TestCase;
use Psr\Log\LoggerInterface;
use Symfony\Component\Messenger\Envelope;
use Symfony\Component\Messenger\Middleware\LoggingMiddleware;
use Symfony\Component\Messenger\Tests\Fixtures\DummyMessage;
@ -21,6 +22,7 @@ class LoggingMiddlewareTest extends TestCase
public function testDebugLogAndNextMiddleware()
{
$message = new DummyMessage('Hey');
$envelope = new Envelope($message);
$logger = $this->createMock(LoggerInterface::class);
$logger
@ -31,10 +33,10 @@ class LoggingMiddlewareTest extends TestCase
$next
->expects($this->once())
->method('__invoke')
->with($message)
->with($envelope)
;
(new LoggingMiddleware($logger))->handle($message, $next);
(new LoggingMiddleware($logger))->handle($envelope, $next);
}
/**
@ -43,6 +45,7 @@ class LoggingMiddlewareTest extends TestCase
public function testWarningLogOnException()
{
$message = new DummyMessage('Hey');
$envelope = new Envelope($message);
$logger = $this->createMock(LoggerInterface::class);
$logger
@ -57,10 +60,10 @@ class LoggingMiddlewareTest extends TestCase
$next
->expects($this->once())
->method('__invoke')
->with($message)
->with($envelope)
->willThrowException(new \Exception())
;
(new LoggingMiddleware($logger))->handle($message, $next);
(new LoggingMiddleware($logger))->handle($envelope, $next);
}
}

View File

@ -24,7 +24,7 @@ class ValidationMiddlewareTest extends TestCase
public function testValidateAndNextMiddleware()
{
$message = new DummyMessage('Hey');
$envelope = Envelope::wrap($message);
$envelope = new Envelope($message);
$validator = $this->createMock(ValidatorInterface::class);
$validator
@ -45,7 +45,8 @@ class ValidationMiddlewareTest extends TestCase
public function testValidateWithStampAndNextMiddleware()
{
$envelope = Envelope::wrap($message = new DummyMessage('Hey'))->with(new ValidationStamp($groups = array('Default', 'Extra')));
$message = new DummyMessage('Hey');
$envelope = (new Envelope($message))->with(new ValidationStamp($groups = array('Default', 'Extra')));
$validator = $this->createMock(ValidatorInterface::class);
$validator
->expects($this->once())
@ -70,7 +71,7 @@ class ValidationMiddlewareTest extends TestCase
public function testValidationFailedException()
{
$message = new DummyMessage('Hey');
$envelope = Envelope::wrap($message);
$envelope = new Envelope($message);
$violationList = $this->createMock(ConstraintViolationListInterface::class);
$violationList

View File

@ -43,7 +43,8 @@ class TraceableMessageBusTest extends TestCase
public function testItTracesDispatchWithEnvelope()
{
$envelope = Envelope::wrap($message = new DummyMessage('Hello'))->with($stamp = new AnEnvelopeStamp());
$message = new DummyMessage('Hello');
$envelope = (new Envelope($message))->with($stamp = new AnEnvelopeStamp());
$bus = $this->getMockBuilder(MessageBusInterface::class)->getMock();

View File

@ -51,8 +51,8 @@ class AmqpExtIntegrationTest extends TestCase
$sender = new AmqpSender($connection, $serializer);
$receiver = new AmqpReceiver($connection, $serializer);
$sender->send($first = Envelope::wrap(new DummyMessage('First')));
$sender->send($second = Envelope::wrap(new DummyMessage('Second')));
$sender->send($first = new Envelope(new DummyMessage('First')));
$sender->send($second = new Envelope(new DummyMessage('Second')));
$receivedMessages = 0;
$receiver->receive(function (?Envelope $envelope) use ($receiver, &$receivedMessages, $first, $second) {
@ -75,7 +75,7 @@ class AmqpExtIntegrationTest extends TestCase
$connection->queue()->purge();
$sender = new AmqpSender($connection, $serializer);
$sender->send(Envelope::wrap(new DummyMessage('Hello')));
$sender->send(new Envelope(new DummyMessage('Hello')));
$amqpReadTimeout = 30;
$dsn = getenv('MESSENGER_AMQP_DSN').'?read_timeout='.$amqpReadTimeout;

View File

@ -25,7 +25,7 @@ class AmqpSenderTest extends TestCase
{
public function testItSendsTheEncodedMessage()
{
$envelope = Envelope::wrap(new DummyMessage('Oy'));
$envelope = new Envelope(new DummyMessage('Oy'));
$encoded = array('body' => '...', 'headers' => array('type' => DummyMessage::class));
$serializer = $this->getMockBuilder(SerializerInterface::class)->getMock();

View File

@ -44,7 +44,7 @@ class AmqpTransportTest extends TestCase
$amqpEnvelope->method('getBody')->willReturn('body');
$amqpEnvelope->method('getHeaders')->willReturn(array('my' => 'header'));
$serializer->method('decode')->with(array('body' => 'body', 'headers' => array('my' => 'header')))->willReturn(Envelope::wrap($decodedMessage));
$serializer->method('decode')->with(array('body' => 'body', 'headers' => array('my' => 'header')))->willReturn(new Envelope($decodedMessage));
$connection->method('get')->willReturn($amqpEnvelope);
$transport->receive(function (Envelope $envelope) use ($transport, $decodedMessage) {

View File

@ -26,7 +26,7 @@ class StopWhenMemoryUsageIsExceededReceiverTest extends TestCase
public function testReceiverStopsWhenMemoryLimitExceeded(int $memoryUsage, int $memoryLimit, bool $shouldStop)
{
$callable = function ($handler) {
$handler(Envelope::wrap(new DummyMessage('API')));
$handler(new Envelope(new DummyMessage('API')));
};
$decoratedReceiver = $this->getMockBuilder(CallbackReceiver::class)
@ -59,7 +59,7 @@ class StopWhenMemoryUsageIsExceededReceiverTest extends TestCase
public function testReceiverLogsMemoryExceededWhenLoggerIsGiven()
{
$callable = function ($handler) {
$handler(Envelope::wrap(new DummyMessage('API')));
$handler(new Envelope(new DummyMessage('API')));
};
$decoratedReceiver = $this->getMockBuilder(CallbackReceiver::class)

View File

@ -26,9 +26,9 @@ class StopWhenMessageCountIsExceededReceiverTest extends TestCase
public function testReceiverStopsWhenMaximumCountExceeded($max, $shouldStop)
{
$callable = function ($handler) {
$handler(Envelope::wrap(new DummyMessage('First message')));
$handler(Envelope::wrap(new DummyMessage('Second message')));
$handler(Envelope::wrap(new DummyMessage('Third message')));
$handler(new Envelope(new DummyMessage('First message')));
$handler(new Envelope(new DummyMessage('Second message')));
$handler(new Envelope(new DummyMessage('Third message')));
};
$decoratedReceiver = $this->getMockBuilder(CallbackReceiver::class)
@ -79,7 +79,7 @@ class StopWhenMessageCountIsExceededReceiverTest extends TestCase
public function testReceiverLogsMaximumCountExceededWhenLoggerIsGiven()
{
$callable = function ($handler) {
$handler(Envelope::wrap(new DummyMessage('First message')));
$handler(new Envelope(new DummyMessage('First message')));
};
$decoratedReceiver = $this->getMockBuilder(CallbackReceiver::class)

View File

@ -29,7 +29,7 @@ class SerializerTest extends TestCase
new SerializerComponent\Serializer(array(new ObjectNormalizer()), array('json' => new JsonEncoder()))
);
$envelope = Envelope::wrap(new DummyMessage('Hello'));
$envelope = new Envelope(new DummyMessage('Hello'));
$this->assertEquals($envelope, $serializer->decode($serializer->encode($envelope)));
}
@ -40,7 +40,7 @@ class SerializerTest extends TestCase
new SerializerComponent\Serializer(array(new ObjectNormalizer()), array('json' => new JsonEncoder()))
);
$envelope = Envelope::wrap(new DummyMessage('Hello'))
$envelope = (new Envelope(new DummyMessage('Hello')))
->with(new SerializerStamp(array(ObjectNormalizer::GROUPS => array('foo'))))
->with(new ValidationStamp(array('foo', 'bar')))
;
@ -54,7 +54,7 @@ class SerializerTest extends TestCase
new SerializerComponent\Serializer(array(new ObjectNormalizer()), array('json' => new JsonEncoder()))
);
$encoded = $serializer->encode(Envelope::wrap(new DummyMessage('Hello')));
$encoded = $serializer->encode(new Envelope(new DummyMessage('Hello')));
$this->assertArrayHasKey('body', $encoded);
$this->assertArrayHasKey('headers', $encoded);
@ -72,7 +72,7 @@ class SerializerTest extends TestCase
$encoder = new Serializer($serializer, 'csv', array('foo' => 'bar'));
$encoded = $encoder->encode(Envelope::wrap($message));
$encoded = $encoder->encode(new Envelope($message));
$decoded = $encoder->decode($encoded);
$this->assertSame('Yay', $encoded['body']);
@ -87,7 +87,7 @@ class SerializerTest extends TestCase
array()
);
$envelope = Envelope::wrap(new DummyMessage('Hello'))
$envelope = (new Envelope(new DummyMessage('Hello')))
->with($serializerStamp = new SerializerStamp(array(ObjectNormalizer::GROUPS => array('foo'))))
->with($validationStamp = new ValidationStamp(array('foo', 'bar')))
;

View File

@ -27,14 +27,14 @@ class WorkerTest extends TestCase
$ipaMessage = new DummyMessage('IPA');
$receiver = new CallbackReceiver(function ($handler) use ($apiMessage, $ipaMessage) {
$handler(Envelope::wrap($apiMessage));
$handler(Envelope::wrap($ipaMessage));
$handler(new Envelope($apiMessage));
$handler(new Envelope($ipaMessage));
});
$bus = $this->getMockBuilder(MessageBusInterface::class)->getMock();
$bus->expects($this->at(0))->method('dispatch')->with(Envelope::wrap($apiMessage)->with(new ReceivedStamp()));
$bus->expects($this->at(1))->method('dispatch')->with(Envelope::wrap($ipaMessage)->with(new ReceivedStamp()));
$bus->expects($this->at(0))->method('dispatch')->with((new Envelope($apiMessage))->with(new ReceivedStamp()));
$bus->expects($this->at(1))->method('dispatch')->with((new Envelope($ipaMessage))->with(new ReceivedStamp()));
$worker = new Worker($receiver, $bus);
$worker->run();
@ -42,7 +42,7 @@ class WorkerTest extends TestCase
public function testWorkerDoesNotWrapMessagesAlreadyWrappedWithReceivedMessage()
{
$envelop = Envelope::wrap(new DummyMessage('API'))->with(new ReceivedStamp());
$envelop = (new Envelope(new DummyMessage('API')))->with(new ReceivedStamp());
$receiver = new CallbackReceiver(function ($handler) use ($envelop) {
$handler($envelop);
});
@ -59,7 +59,7 @@ class WorkerTest extends TestCase
{
$receiver = new CallbackReceiver(function ($handler) {
try {
$handler(Envelope::wrap(new DummyMessage('Hello')));
$handler(new Envelope(new DummyMessage('Hello')));
$this->assertTrue(false, 'This should not be called because the exception is sent back to the generator.');
} catch (\InvalidArgumentException $e) {