[Messenger] collect all stamps added on Envelope as collections

This commit is contained in:
Nicolas Grekas 2018-11-09 17:32:17 +01:00
parent 99856a9b08
commit 2e9885922a
9 changed files with 43 additions and 44 deletions

View File

@ -33,6 +33,8 @@ CHANGELOG
* `ActivationMiddlewareDecorator` has been renamed `ActivationMiddleware` * `ActivationMiddlewareDecorator` has been renamed `ActivationMiddleware`
* `AllowNoHandlerMiddleware` has been removed in favor of a new constructor argument on `HandleMessageMiddleware` * `AllowNoHandlerMiddleware` has been removed in favor of a new constructor argument on `HandleMessageMiddleware`
* The `ContainerHandlerLocator`, `AbstractHandlerLocator`, `SenderLocator` and `AbstractSenderLocator` classes have been removed * The `ContainerHandlerLocator`, `AbstractHandlerLocator`, `SenderLocator` and `AbstractSenderLocator` classes have been removed
* `Envelope::all()` takes a new optional `$stampFqcn` argument and returns the stamps for the specified FQCN, or all stamps by their class name
* `Envelope::get()` has been renamed `Envelope::last()`
4.1.0 4.1.0
----- -----

View File

@ -36,7 +36,7 @@ final class Envelope
$this->message = $message; $this->message = $message;
foreach ($stamps as $stamp) { foreach ($stamps as $stamp) {
$this->stamps[\get_class($stamp)] = $stamp; $this->stamps[\get_class($stamp)][] = $stamp;
} }
} }
@ -48,22 +48,26 @@ final class Envelope
$cloned = clone $this; $cloned = clone $this;
foreach ($stamps as $stamp) { foreach ($stamps as $stamp) {
$cloned->stamps[\get_class($stamp)] = $stamp; $cloned->stamps[\get_class($stamp)][] = $stamp;
} }
return $cloned; return $cloned;
} }
public function get(string $stampFqcn): ?StampInterface public function last(string $stampFqcn): ?StampInterface
{ {
return $this->stamps[$stampFqcn] ?? null; return isset($this->stamps[$stampFqcn]) ? end($this->stamps[$stampFqcn]) : null;
} }
/** /**
* @return StampInterface[] indexed by fqcn * @return StampInterface[]|StampInterface[][] The stamps for the specified FQCN, or all stamps by their class name
*/ */
public function all(): array public function all(string $stampFqcn = null): array
{ {
if (null !== $stampFqcn) {
return $this->stamps[$stampFqcn] ?? array();
}
return $this->stamps; return $this->stamps;
} }

View File

@ -35,7 +35,7 @@ class SendMessageMiddleware implements MiddlewareInterface
*/ */
public function handle(Envelope $envelope, StackInterface $stack): Envelope public function handle(Envelope $envelope, StackInterface $stack): Envelope
{ {
if ($envelope->get(ReceivedStamp::class)) { if ($envelope->all(ReceivedStamp::class)) {
// it's a received message, do not send it back // it's a received message, do not send it back
return $stack->next()->handle($envelope, $stack); return $stack->next()->handle($envelope, $stack);
} }

View File

@ -38,7 +38,7 @@ class ValidationMiddleware implements MiddlewareInterface
$message = $envelope->getMessage(); $message = $envelope->getMessage();
$groups = null; $groups = null;
/** @var ValidationStamp|null $validationStamp */ /** @var ValidationStamp|null $validationStamp */
if ($validationStamp = $envelope->get(ValidationStamp::class)) { if ($validationStamp = $envelope->last(ValidationStamp::class)) {
$groups = $validationStamp->getGroups(); $groups = $validationStamp->getGroups();
} }

View File

@ -29,7 +29,7 @@ class EnvelopeTest extends TestCase
$this->assertSame($dummy, $envelope->getMessage()); $this->assertSame($dummy, $envelope->getMessage());
$this->assertArrayHasKey(ReceivedStamp::class, $stamps = $envelope->all()); $this->assertArrayHasKey(ReceivedStamp::class, $stamps = $envelope->all());
$this->assertSame($receivedStamp, $stamps[ReceivedStamp::class]); $this->assertSame($receivedStamp, $stamps[ReceivedStamp::class][0]);
} }
public function testWithReturnsNewInstance() public function testWithReturnsNewInstance()
@ -39,13 +39,13 @@ class EnvelopeTest extends TestCase
$this->assertNotSame($envelope, $envelope->with(new ReceivedStamp())); $this->assertNotSame($envelope, $envelope->with(new ReceivedStamp()));
} }
public function testGet() public function testGetLast()
{ {
$receivedStamp = new ReceivedStamp(); $receivedStamp = new ReceivedStamp();
$envelope = new Envelope($dummy = new DummyMessage('dummy'), $receivedStamp); $envelope = new Envelope($dummy = new DummyMessage('dummy'), $receivedStamp);
$this->assertSame($receivedStamp, $envelope->get(ReceivedStamp::class)); $this->assertSame($receivedStamp, $envelope->last(ReceivedStamp::class));
$this->assertNull($envelope->get(ValidationStamp::class)); $this->assertNull($envelope->last(ValidationStamp::class));
} }
public function testAll() public function testAll()
@ -57,8 +57,8 @@ class EnvelopeTest extends TestCase
$stamps = $envelope->all(); $stamps = $envelope->all();
$this->assertArrayHasKey(ReceivedStamp::class, $stamps); $this->assertArrayHasKey(ReceivedStamp::class, $stamps);
$this->assertSame($receivedStamp, $stamps[ReceivedStamp::class]); $this->assertSame($receivedStamp, $stamps[ReceivedStamp::class][0]);
$this->assertArrayHasKey(ValidationStamp::class, $stamps); $this->assertArrayHasKey(ValidationStamp::class, $stamps);
$this->assertSame($validationStamp, $stamps[ValidationStamp::class]); $this->assertSame($validationStamp, $stamps[ValidationStamp::class][0]);
} }
} }

View File

@ -56,7 +56,7 @@ class TraceableMessageBusTest extends TestCase
$this->assertCount(1, $tracedMessages = $traceableBus->getDispatchedMessages()); $this->assertCount(1, $tracedMessages = $traceableBus->getDispatchedMessages());
$this->assertArraySubset(array( $this->assertArraySubset(array(
'message' => $message, 'message' => $message,
'stamps' => array($stamp), 'stamps' => array(array($stamp)),
'caller' => array( 'caller' => array(
'name' => 'TraceableMessageBusTest.php', 'name' => 'TraceableMessageBusTest.php',
'file' => __FILE__, 'file' => __FILE__,

View File

@ -18,16 +18,13 @@ use Symfony\Component\Messenger\Stamp\ValidationStamp;
use Symfony\Component\Messenger\Tests\Fixtures\DummyMessage; use Symfony\Component\Messenger\Tests\Fixtures\DummyMessage;
use Symfony\Component\Messenger\Transport\Serialization\Serializer; use Symfony\Component\Messenger\Transport\Serialization\Serializer;
use Symfony\Component\Serializer as SerializerComponent; use Symfony\Component\Serializer as SerializerComponent;
use Symfony\Component\Serializer\Encoder\JsonEncoder;
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer; use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;
class SerializerTest extends TestCase class SerializerTest extends TestCase
{ {
public function testEncodedIsDecodable() public function testEncodedIsDecodable()
{ {
$serializer = new Serializer( $serializer = new Serializer();
new SerializerComponent\Serializer(array(new ObjectNormalizer()), array('json' => new JsonEncoder()))
);
$envelope = new Envelope(new DummyMessage('Hello')); $envelope = new Envelope(new DummyMessage('Hello'));
@ -36,9 +33,7 @@ class SerializerTest extends TestCase
public function testEncodedWithStampsIsDecodable() public function testEncodedWithStampsIsDecodable()
{ {
$serializer = new Serializer( $serializer = new Serializer();
new SerializerComponent\Serializer(array(new ObjectNormalizer()), array('json' => new JsonEncoder()))
);
$envelope = (new Envelope(new DummyMessage('Hello'))) $envelope = (new Envelope(new DummyMessage('Hello')))
->with(new SerializerStamp(array(ObjectNormalizer::GROUPS => array('foo')))) ->with(new SerializerStamp(array(ObjectNormalizer::GROUPS => array('foo'))))
@ -50,9 +45,7 @@ class SerializerTest extends TestCase
public function testEncodedIsHavingTheBodyAndTypeHeader() public function testEncodedIsHavingTheBodyAndTypeHeader()
{ {
$serializer = new Serializer( $serializer = new Serializer();
new SerializerComponent\Serializer(array(new ObjectNormalizer()), array('json' => new JsonEncoder()))
);
$encoded = $serializer->encode(new Envelope(new DummyMessage('Hello'))); $encoded = $serializer->encode(new Envelope(new DummyMessage('Hello')));
@ -81,11 +74,7 @@ class SerializerTest extends TestCase
public function testEncodedWithSymfonySerializerForStamps() public function testEncodedWithSymfonySerializerForStamps()
{ {
$serializer = new Serializer( $serializer = new Serializer();
new SerializerComponent\Serializer(array(new ObjectNormalizer()), array('json' => new JsonEncoder())),
'json',
array()
);
$envelope = (new Envelope(new DummyMessage('Hello'))) $envelope = (new Envelope(new DummyMessage('Hello')))
->with($serializerStamp = new SerializerStamp(array(ObjectNormalizer::GROUPS => array('foo')))) ->with($serializerStamp = new SerializerStamp(array(ObjectNormalizer::GROUPS => array('foo'))))
@ -102,7 +91,7 @@ class SerializerTest extends TestCase
$decoded = $serializer->decode($encoded); $decoded = $serializer->decode($encoded);
$this->assertEquals($serializerStamp, $decoded->get(SerializerStamp::class)); $this->assertEquals($serializerStamp, $decoded->last(SerializerStamp::class));
$this->assertEquals($validationStamp, $decoded->get(ValidationStamp::class)); $this->assertEquals($validationStamp, $decoded->last(ValidationStamp::class));
} }
} }

View File

@ -42,10 +42,11 @@ class WorkerTest extends TestCase
public function testWorkerDoesNotWrapMessagesAlreadyWrappedWithReceivedMessage() public function testWorkerDoesNotWrapMessagesAlreadyWrappedWithReceivedMessage()
{ {
$envelope = (new Envelope(new DummyMessage('API')))->with(new ReceivedStamp()); $envelope = new Envelope(new DummyMessage('API'));
$receiver = new CallbackReceiver(function ($handler) use ($envelope) { $receiver = new CallbackReceiver(function ($handler) use ($envelope) {
$handler($envelope); $handler($envelope);
}); });
$envelope = $envelope->with(new ReceivedStamp());
$bus = $this->getMockBuilder(MessageBusInterface::class)->getMock(); $bus = $this->getMockBuilder(MessageBusInterface::class)->getMock();
$bus->expects($this->at(0))->method('dispatch')->with($envelope)->willReturn($envelope); $bus->expects($this->at(0))->method('dispatch')->with($envelope)->willReturn($envelope);

View File

@ -17,6 +17,7 @@ use Symfony\Component\Messenger\Exception\LogicException;
use Symfony\Component\Messenger\Stamp\SerializerStamp; use Symfony\Component\Messenger\Stamp\SerializerStamp;
use Symfony\Component\Serializer\Encoder\JsonEncoder; use Symfony\Component\Serializer\Encoder\JsonEncoder;
use Symfony\Component\Serializer\Encoder\XmlEncoder; use Symfony\Component\Serializer\Encoder\XmlEncoder;
use Symfony\Component\Serializer\Normalizer\ArrayDenormalizer;
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer; use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;
use Symfony\Component\Serializer\Serializer as SymfonySerializer; use Symfony\Component\Serializer\Serializer as SymfonySerializer;
use Symfony\Component\Serializer\SerializerInterface as SymfonySerializerInterface; use Symfony\Component\Serializer\SerializerInterface as SymfonySerializerInterface;
@ -34,9 +35,9 @@ class Serializer implements SerializerInterface
private $format; private $format;
private $context; private $context;
public function __construct(SymfonySerializerInterface $serializer, string $format = 'json', array $context = array()) public function __construct(SymfonySerializerInterface $serializer = null, string $format = 'json', array $context = array())
{ {
$this->serializer = $serializer; $this->serializer = $serializer ?? self::create()->serializer;
$this->format = $format; $this->format = $format;
$this->context = $context; $this->context = $context;
} }
@ -48,7 +49,7 @@ class Serializer implements SerializerInterface
} }
$encoders = array(new XmlEncoder(), new JsonEncoder()); $encoders = array(new XmlEncoder(), new JsonEncoder());
$normalizers = array(new ObjectNormalizer()); $normalizers = array(new ArrayDenormalizer(), new ObjectNormalizer());
$serializer = new SymfonySerializer($normalizers, $encoders); $serializer = new SymfonySerializer($normalizers, $encoders);
return new self($serializer); return new self($serializer);
@ -70,9 +71,8 @@ class Serializer implements SerializerInterface
$stamps = $this->decodeStamps($encodedEnvelope); $stamps = $this->decodeStamps($encodedEnvelope);
$context = $this->context; $context = $this->context;
/** @var SerializerStamp|null $serializerStamp */ if (isset($stamps[SerializerStamp::class])) {
if ($serializerStamp = $stamps[SerializerStamp::class] ?? null) { $context = end($stamps[SerializerStamp::class])->getContext() + $context;
$context = $serializerStamp->getContext() + $context;
} }
$message = $this->serializer->deserialize($encodedEnvelope['body'], $encodedEnvelope['headers']['type'], $this->format, $context); $message = $this->serializer->deserialize($encodedEnvelope['body'], $encodedEnvelope['headers']['type'], $this->format, $context);
@ -87,7 +87,7 @@ class Serializer implements SerializerInterface
{ {
$context = $this->context; $context = $this->context;
/** @var SerializerStamp|null $serializerStamp */ /** @var SerializerStamp|null $serializerStamp */
if ($serializerStamp = $envelope->get(SerializerStamp::class)) { if ($serializerStamp = $envelope->last(SerializerStamp::class)) {
$context = $serializerStamp->getContext() + $context; $context = $serializerStamp->getContext() + $context;
} }
@ -107,7 +107,10 @@ class Serializer implements SerializerInterface
continue; continue;
} }
$stamps[] = $this->serializer->deserialize($value, substr($name, \strlen(self::STAMP_HEADER_PREFIX)), $this->format, $this->context); $stamps[] = $this->serializer->deserialize($value, substr($name, \strlen(self::STAMP_HEADER_PREFIX)).'[]', $this->format, $this->context);
}
if ($stamps) {
$stamps = array_merge(...$stamps);
} }
return $stamps; return $stamps;
@ -115,13 +118,13 @@ class Serializer implements SerializerInterface
private function encodeStamps(Envelope $envelope): array private function encodeStamps(Envelope $envelope): array
{ {
if (!$stamps = $envelope->all()) { if (!$allStamps = $envelope->all()) {
return array(); return array();
} }
$headers = array(); $headers = array();
foreach ($stamps as $stamp) { foreach ($allStamps as $class => $stamps) {
$headers[self::STAMP_HEADER_PREFIX.\get_class($stamp)] = $this->serializer->serialize($stamp, $this->format, $this->context); $headers[self::STAMP_HEADER_PREFIX.$class] = $this->serializer->serialize($stamps, $this->format, $this->context);
} }
return $headers; return $headers;