Skip to content

Commit c38a096

Browse files
committed
feature #44589 [Messenger] add SerializedMessageStamp (nikophil)
This PR was merged into the 6.1 branch. Discussion ---------- [Messenger] add SerializedMessageStamp | Q | A | ------------- | --- | Branch? | 6.1 | Bug fix? | no | New feature? | yes | Deprecations? | no | Tickets | Fix #43496 | License | MIT | Doc PR | (will be added if PR is accepted) This PR fixes #43496 When a message is sent for retry, we currently serialize it from the message POPO object whereas we already had the serialized representation of the message before deserializing it. This solution proposes to store the serialized message in a "not serializable" stamp when we receive the message. Then the serialized message will be used in `\Symfony\Component\Messenger\Transport\Serialization\Serializer::encode()`, if the message is retried, which prevents to serialize the message again. This has several advantages, mainly when we're dealing with big payloads: - it prevents the performance impact of serializing potential big objects - it prevents the need of a dedicated normalizer if the message comes from another system. Commits ------- 03bb8b9 [Messenger] add SerializedMessageStamp
2 parents cef3d5a + 03bb8b9 commit c38a096

File tree

5 files changed

+55
-3
lines changed

5 files changed

+55
-3
lines changed

src/Symfony/Component/Messenger/Bridge/Amqp/Tests/Transport/AmqpExtIntegrationTest.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,7 @@ public function testItReceivesSignals()
213213
$this->assertSame($expectedOutput.<<<'TXT'
214214
Get envelope with message: Symfony\Component\Messenger\Bridge\Amqp\Tests\Fixtures\DummyMessage
215215
with stamps: [
216+
"Symfony\\Component\\Messenger\\Stamp\\SerializedMessageStamp",
216217
"Symfony\\Component\\Messenger\\Bridge\\Amqp\\Transport\\AmqpReceivedStamp",
217218
"Symfony\\Component\\Messenger\\Stamp\\ReceivedStamp",
218219
"Symfony\\Component\\Messenger\\Stamp\\ConsumedByWorkerStamp",

src/Symfony/Component/Messenger/CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
CHANGELOG
22
=========
33

4+
6.1
5+
---
6+
7+
* Add `SerializedMessageStamp` to avoid serializing a message when a retry occurs.
8+
49
6.0
510
---
611

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Messenger\Stamp;
13+
14+
final class SerializedMessageStamp implements NonSendableStampInterface
15+
{
16+
public function __construct(private string $serializedMessage)
17+
{
18+
}
19+
20+
public function getSerializedMessage(): string
21+
{
22+
return $this->serializedMessage;
23+
}
24+
}

src/Symfony/Component/Messenger/Tests/Transport/Serialization/SerializerTest.php

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
use Symfony\Component\Messenger\Envelope;
1616
use Symfony\Component\Messenger\Exception\MessageDecodingFailedException;
1717
use Symfony\Component\Messenger\Stamp\NonSendableStampInterface;
18+
use Symfony\Component\Messenger\Stamp\SerializedMessageStamp;
1819
use Symfony\Component\Messenger\Stamp\SerializerStamp;
1920
use Symfony\Component\Messenger\Stamp\ValidationStamp;
2021
use Symfony\Component\Messenger\Tests\Fixtures\DummyMessage;
@@ -29,9 +30,10 @@ public function testEncodedIsDecodable()
2930
{
3031
$serializer = new Serializer();
3132

32-
$envelope = new Envelope(new DummyMessage('Hello'));
33+
$decodedEnvelope = $serializer->decode($serializer->encode(new Envelope(new DummyMessage('Hello'))));
3334

34-
$this->assertEquals($envelope, $serializer->decode($serializer->encode($envelope)));
35+
$this->assertEquals(new DummyMessage('Hello'), $decodedEnvelope->getMessage());
36+
$this->assertEquals(new SerializedMessageStamp('{"message":"Hello"}'), $decodedEnvelope->last(SerializedMessageStamp::class));
3537
}
3638

3739
public function testEncodedWithStampsIsDecodable()
@@ -41,11 +43,23 @@ public function testEncodedWithStampsIsDecodable()
4143
$envelope = (new Envelope(new DummyMessage('Hello')))
4244
->with(new SerializerStamp([ObjectNormalizer::GROUPS => ['foo']]))
4345
->with(new ValidationStamp(['foo', 'bar']))
46+
->with(new SerializedMessageStamp('{"message":"Hello"}'))
4447
;
4548

4649
$this->assertEquals($envelope, $serializer->decode($serializer->encode($envelope)));
4750
}
4851

52+
public function testSerializedMessageStampIsUsedForEncoding()
53+
{
54+
$serializer = new Serializer();
55+
56+
$encoded = $serializer->encode(
57+
new Envelope(new DummyMessage(''), [new SerializedMessageStamp('{"message":"Hello"}')])
58+
);
59+
60+
$this->assertSame('{"message":"Hello"}', $encoded['body'] ?? null);
61+
}
62+
4963
public function testEncodedIsHavingTheBodyAndTypeHeader()
5064
{
5165
$serializer = new Serializer();

src/Symfony/Component/Messenger/Transport/Serialization/Serializer.php

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
use Symfony\Component\Messenger\Exception\LogicException;
1616
use Symfony\Component\Messenger\Exception\MessageDecodingFailedException;
1717
use Symfony\Component\Messenger\Stamp\NonSendableStampInterface;
18+
use Symfony\Component\Messenger\Stamp\SerializedMessageStamp;
1819
use Symfony\Component\Messenger\Stamp\SerializerStamp;
1920
use Symfony\Component\Messenger\Stamp\StampInterface;
2021
use Symfony\Component\Serializer\Encoder\JsonEncoder;
@@ -71,6 +72,8 @@ public function decode(array $encodedEnvelope): Envelope
7172
}
7273

7374
$stamps = $this->decodeStamps($encodedEnvelope);
75+
$stamps[] = new SerializedMessageStamp($encodedEnvelope['body']);
76+
7477
$serializerStamp = $this->findFirstSerializerStamp($stamps);
7578

7679
$context = $this->context;
@@ -98,12 +101,17 @@ public function encode(Envelope $envelope): array
98101
$context = $serializerStamp->getContext() + $context;
99102
}
100103

104+
/** @var SerializedMessageStamp|null $serializedMessageStamp */
105+
$serializedMessageStamp = $envelope->last(SerializedMessageStamp::class);
106+
101107
$envelope = $envelope->withoutStampsOfType(NonSendableStampInterface::class);
102108

103109
$headers = ['type' => \get_class($envelope->getMessage())] + $this->encodeStamps($envelope) + $this->getContentTypeHeader();
104110

105111
return [
106-
'body' => $this->serializer->serialize($envelope->getMessage(), $this->format, $context),
112+
'body' => $serializedMessageStamp
113+
? $serializedMessageStamp->getSerializedMessage()
114+
: $this->serializer->serialize($envelope->getMessage(), $this->format, $context),
107115
'headers' => $headers,
108116
];
109117
}

0 commit comments

Comments
 (0)