From 03bb8b9045375867e74dbd686c0603bbb29199d3 Mon Sep 17 00:00:00 2001 From: Nicolas PHILIPPE Date: Mon, 13 Dec 2021 10:08:04 +0100 Subject: [PATCH] [Messenger] add SerializedMessageStamp --- .../Transport/AmqpExtIntegrationTest.php | 1 + src/Symfony/Component/Messenger/CHANGELOG.md | 5 ++++ .../Stamp/SerializedMessageStamp.php | 24 +++++++++++++++++++ .../Serialization/SerializerTest.php | 18 ++++++++++++-- .../Transport/Serialization/Serializer.php | 10 +++++++- 5 files changed, 55 insertions(+), 3 deletions(-) create mode 100644 src/Symfony/Component/Messenger/Stamp/SerializedMessageStamp.php diff --git a/src/Symfony/Component/Messenger/Bridge/Amqp/Tests/Transport/AmqpExtIntegrationTest.php b/src/Symfony/Component/Messenger/Bridge/Amqp/Tests/Transport/AmqpExtIntegrationTest.php index aa551e4e85080..8ca90a554c5b1 100644 --- a/src/Symfony/Component/Messenger/Bridge/Amqp/Tests/Transport/AmqpExtIntegrationTest.php +++ b/src/Symfony/Component/Messenger/Bridge/Amqp/Tests/Transport/AmqpExtIntegrationTest.php @@ -213,6 +213,7 @@ public function testItReceivesSignals() $this->assertSame($expectedOutput.<<<'TXT' Get envelope with message: Symfony\Component\Messenger\Bridge\Amqp\Tests\Fixtures\DummyMessage with stamps: [ + "Symfony\\Component\\Messenger\\Stamp\\SerializedMessageStamp", "Symfony\\Component\\Messenger\\Bridge\\Amqp\\Transport\\AmqpReceivedStamp", "Symfony\\Component\\Messenger\\Stamp\\ReceivedStamp", "Symfony\\Component\\Messenger\\Stamp\\ConsumedByWorkerStamp", diff --git a/src/Symfony/Component/Messenger/CHANGELOG.md b/src/Symfony/Component/Messenger/CHANGELOG.md index 22d9b6e80a3ce..14b38194898ff 100644 --- a/src/Symfony/Component/Messenger/CHANGELOG.md +++ b/src/Symfony/Component/Messenger/CHANGELOG.md @@ -1,6 +1,11 @@ CHANGELOG ========= +6.1 +--- + + * Add `SerializedMessageStamp` to avoid serializing a message when a retry occurs. + 6.0 --- diff --git a/src/Symfony/Component/Messenger/Stamp/SerializedMessageStamp.php b/src/Symfony/Component/Messenger/Stamp/SerializedMessageStamp.php new file mode 100644 index 0000000000000..3feffbc131861 --- /dev/null +++ b/src/Symfony/Component/Messenger/Stamp/SerializedMessageStamp.php @@ -0,0 +1,24 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Messenger\Stamp; + +final class SerializedMessageStamp implements NonSendableStampInterface +{ + public function __construct(private string $serializedMessage) + { + } + + public function getSerializedMessage(): string + { + return $this->serializedMessage; + } +} diff --git a/src/Symfony/Component/Messenger/Tests/Transport/Serialization/SerializerTest.php b/src/Symfony/Component/Messenger/Tests/Transport/Serialization/SerializerTest.php index 6f4d3bad313d1..712077d71ba54 100644 --- a/src/Symfony/Component/Messenger/Tests/Transport/Serialization/SerializerTest.php +++ b/src/Symfony/Component/Messenger/Tests/Transport/Serialization/SerializerTest.php @@ -15,6 +15,7 @@ use Symfony\Component\Messenger\Envelope; use Symfony\Component\Messenger\Exception\MessageDecodingFailedException; use Symfony\Component\Messenger\Stamp\NonSendableStampInterface; +use Symfony\Component\Messenger\Stamp\SerializedMessageStamp; use Symfony\Component\Messenger\Stamp\SerializerStamp; use Symfony\Component\Messenger\Stamp\ValidationStamp; use Symfony\Component\Messenger\Tests\Fixtures\DummyMessage; @@ -29,9 +30,10 @@ public function testEncodedIsDecodable() { $serializer = new Serializer(); - $envelope = new Envelope(new DummyMessage('Hello')); + $decodedEnvelope = $serializer->decode($serializer->encode(new Envelope(new DummyMessage('Hello')))); - $this->assertEquals($envelope, $serializer->decode($serializer->encode($envelope))); + $this->assertEquals(new DummyMessage('Hello'), $decodedEnvelope->getMessage()); + $this->assertEquals(new SerializedMessageStamp('{"message":"Hello"}'), $decodedEnvelope->last(SerializedMessageStamp::class)); } public function testEncodedWithStampsIsDecodable() @@ -41,11 +43,23 @@ public function testEncodedWithStampsIsDecodable() $envelope = (new Envelope(new DummyMessage('Hello'))) ->with(new SerializerStamp([ObjectNormalizer::GROUPS => ['foo']])) ->with(new ValidationStamp(['foo', 'bar'])) + ->with(new SerializedMessageStamp('{"message":"Hello"}')) ; $this->assertEquals($envelope, $serializer->decode($serializer->encode($envelope))); } + public function testSerializedMessageStampIsUsedForEncoding() + { + $serializer = new Serializer(); + + $encoded = $serializer->encode( + new Envelope(new DummyMessage(''), [new SerializedMessageStamp('{"message":"Hello"}')]) + ); + + $this->assertSame('{"message":"Hello"}', $encoded['body'] ?? null); + } + public function testEncodedIsHavingTheBodyAndTypeHeader() { $serializer = new Serializer(); diff --git a/src/Symfony/Component/Messenger/Transport/Serialization/Serializer.php b/src/Symfony/Component/Messenger/Transport/Serialization/Serializer.php index 30540321f639d..b3c8cb7c6ef3f 100644 --- a/src/Symfony/Component/Messenger/Transport/Serialization/Serializer.php +++ b/src/Symfony/Component/Messenger/Transport/Serialization/Serializer.php @@ -15,6 +15,7 @@ use Symfony\Component\Messenger\Exception\LogicException; use Symfony\Component\Messenger\Exception\MessageDecodingFailedException; use Symfony\Component\Messenger\Stamp\NonSendableStampInterface; +use Symfony\Component\Messenger\Stamp\SerializedMessageStamp; use Symfony\Component\Messenger\Stamp\SerializerStamp; use Symfony\Component\Messenger\Stamp\StampInterface; use Symfony\Component\Serializer\Encoder\JsonEncoder; @@ -71,6 +72,8 @@ public function decode(array $encodedEnvelope): Envelope } $stamps = $this->decodeStamps($encodedEnvelope); + $stamps[] = new SerializedMessageStamp($encodedEnvelope['body']); + $serializerStamp = $this->findFirstSerializerStamp($stamps); $context = $this->context; @@ -98,12 +101,17 @@ public function encode(Envelope $envelope): array $context = $serializerStamp->getContext() + $context; } + /** @var SerializedMessageStamp|null $serializedMessageStamp */ + $serializedMessageStamp = $envelope->last(SerializedMessageStamp::class); + $envelope = $envelope->withoutStampsOfType(NonSendableStampInterface::class); $headers = ['type' => \get_class($envelope->getMessage())] + $this->encodeStamps($envelope) + $this->getContentTypeHeader(); return [ - 'body' => $this->serializer->serialize($envelope->getMessage(), $this->format, $context), + 'body' => $serializedMessageStamp + ? $serializedMessageStamp->getSerializedMessage() + : $this->serializer->serialize($envelope->getMessage(), $this->format, $context), 'headers' => $headers, ]; }