Skip to content

Commit ddab1e5

Browse files
committed
[Doctrine][Messenger] Prevents multiple TransportMessageIdStamp being stored in envelope
- Multiple TransportMessageIdStamps can heavily increase message size on multiple retries, to prevent that when message is fetched existing TransportMessageIdStamps are discarded before new one is added. - Replaces static calls to \PHPUnit\Framework\TestCase::expectException in DoctrineReceiverTest test with instance calls. Fixes: #49637
1 parent 6ba6441 commit ddab1e5

File tree

3 files changed

+85
-13
lines changed

3 files changed

+85
-13
lines changed

CHANGELOG-6.4.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@ in 6.4 minor versions.
77
To get the diff for a specific change, go to https://github.com/symfony/symfony/commit/XXX where XXX is the change hash
88
To get the diff between two versions, go to https://github.com/symfony/symfony/compare/v6.4.0...v6.4.1
99

10+
* 6.4.18 (2025-xx-xx)
11+
12+
* bug #49637 [Doctrine][Messenger] Prevents multiple `TransportMessageIdStamp` being stored in envelope (rtreffler)
13+
1014
* 6.4.17 (2024-12-31)
1115

1216
* bug #59304 [PropertyInfo] Remove ``@internal`` from `PropertyReadInfo` and `PropertyWriteInfo` (Dario Guarracino)
@@ -894,4 +898,3 @@ To get the diff between two versions, go to https://github.com/symfony/symfony/c
894898
* feature #43 Create PSR-7 messages using PSR-17 factories (ajgarlag)
895899
* feature #45 Fixed broken build (Nyholm)
896900
* feature #1 Initial support (dunglas)
897-

src/Symfony/Component/Messenger/Bridge/Doctrine/Tests/Transport/DoctrineReceiverTest.php

Lines changed: 75 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@
2828
use Symfony\Component\Messenger\Transport\Serialization\Serializer;
2929
use Symfony\Component\Serializer as SerializerComponent;
3030
use Symfony\Component\Serializer\Encoder\JsonEncoder;
31+
use Symfony\Component\Serializer\Normalizer\ArrayDenormalizer;
32+
use Symfony\Component\Serializer\Normalizer\DateTimeNormalizer;
3133
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;
3234

3335
class DoctrineReceiverTest extends TestCase
@@ -100,6 +102,23 @@ public function testOccursRetryableExceptionFromConnection()
100102
$receiver->get();
101103
}
102104

105+
public function testGetReplacesExistingTransportMessageIdStamps(): void
106+
{
107+
$serializer = $this->createSerializer();
108+
109+
$doctrineEnvelope = $this->createRetriedDoctrineEnvelope();
110+
$connection = $this->createMock(Connection::class);
111+
$connection->method('get')->willReturn($doctrineEnvelope);
112+
113+
$receiver = new DoctrineReceiver($connection, $serializer);
114+
$actualEnvelopes = $receiver->get();
115+
/** @var Envelope $actualEnvelope */
116+
$actualEnvelope = $actualEnvelopes[0];
117+
$messageIdStamps = $actualEnvelope->all(TransportMessageIdStamp::class);
118+
119+
$this->assertCount(1, $messageIdStamps);
120+
}
121+
103122
public function testAll()
104123
{
105124
$serializer = $this->createSerializer();
@@ -115,6 +134,24 @@ public function testAll()
115134
$this->assertEquals(new DummyMessage('Hi'), $actualEnvelopes[0]->getMessage());
116135
}
117136

137+
public function testAllReplacesExistingTransportMessageIdStamps(): void
138+
{
139+
$serializer = $this->createSerializer();
140+
141+
$doctrineEnvelope1 = $this->createRetriedDoctrineEnvelope();
142+
$doctrineEnvelope2 = $this->createRetriedDoctrineEnvelope();
143+
$connection = $this->createMock(Connection::class);
144+
$connection->method('findAll')->willReturn([$doctrineEnvelope1, $doctrineEnvelope2]);
145+
146+
$receiver = new DoctrineReceiver($connection, $serializer);
147+
$actualEnvelopes = $receiver->all();
148+
foreach ($actualEnvelopes as $actualEnvelope) {
149+
$messageIdStamps = $actualEnvelope->all(TransportMessageIdStamp::class);
150+
151+
$this->assertCount(1, $messageIdStamps);
152+
}
153+
}
154+
118155
public function testFind()
119156
{
120157
$serializer = $this->createSerializer();
@@ -128,6 +165,21 @@ public function testFind()
128165
$this->assertEquals(new DummyMessage('Hi'), $actualEnvelope->getMessage());
129166
}
130167

168+
public function testFindReplacesExistingTransportMessageIdStamps(): void
169+
{
170+
$serializer = $this->createSerializer();
171+
172+
$doctrineEnvelope = $this->createRetriedDoctrineEnvelope();
173+
$connection = $this->createMock(Connection::class);
174+
$connection->method('find')->with(3)->willReturn($doctrineEnvelope);
175+
176+
$receiver = new DoctrineReceiver($connection, $serializer);
177+
$actualEnvelope = $receiver->find(3);
178+
$messageIdStamps = $actualEnvelope->all(TransportMessageIdStamp::class);
179+
180+
$this->assertCount(1, $messageIdStamps);
181+
}
182+
131183
public function testAck()
132184
{
133185
$serializer = $this->createSerializer();
@@ -195,7 +247,7 @@ public function testAckThrowsRetryableExceptionAndRetriesFail()
195247
->with('1')
196248
->willThrowException($deadlockException);
197249

198-
self::expectException(TransportException::class);
250+
$this->expectException(TransportException::class);
199251
$receiver->ack($envelope);
200252
}
201253

@@ -215,7 +267,7 @@ public function testAckThrowsException()
215267
->with('1')
216268
->willThrowException($exception);
217269

218-
self::expectException($exception::class);
270+
$this->expectException($exception::class);
219271
$receiver->ack($envelope);
220272
}
221273

@@ -286,7 +338,7 @@ public function testRejectThrowsRetryableExceptionAndRetriesFail()
286338
->with('1')
287339
->willThrowException($deadlockException);
288340

289-
self::expectException(TransportException::class);
341+
$this->expectException(TransportException::class);
290342
$receiver->reject($envelope);
291343
}
292344

@@ -306,7 +358,7 @@ public function testRejectThrowsException()
306358
->with('1')
307359
->willThrowException($exception);
308360

309-
self::expectException($exception::class);
361+
$this->expectException($exception::class);
310362
$receiver->reject($envelope);
311363
}
312364

@@ -321,12 +373,27 @@ private function createDoctrineEnvelope(): array
321373
];
322374
}
323375

376+
private function createRetriedDoctrineEnvelope(): array
377+
{
378+
return [
379+
'id' => 3,
380+
'body' => '{"message": "Hi"}',
381+
'headers' => [
382+
'type' => DummyMessage::class,
383+
'X-Message-Stamp-Symfony\Component\Messenger\Stamp\BusNameStamp' => '[{"busName":"messenger.bus.default"}]',
384+
'X-Message-Stamp-Symfony\Component\Messenger\Stamp\TransportMessageIdStamp' => '[{"id":1},{"id":2}]',
385+
'X-Message-Stamp-Symfony\Component\Messenger\Stamp\ErrorDetailsStamp' => '[{"exceptionClass":"Symfony\\\\Component\\\\Messenger\\\\Exception\\\\RecoverableMessageHandlingException","exceptionCode":0,"exceptionMessage":"","flattenException":null}]',
386+
'X-Message-Stamp-Symfony\Component\Messenger\Stamp\DelayStamp' => '[{"delay":1000},{"delay":1000}]',
387+
'X-Message-Stamp-Symfony\Component\Messenger\Stamp\RedeliveryStamp' => '[{"retryCount":1,"redeliveredAt":"2025-01-05T13:58:25+00:00"},{"retryCount":2,"redeliveredAt":"2025-01-05T13:59:26+00:00"}]',
388+
'Content-Type' => 'application/json',
389+
],
390+
];
391+
}
392+
324393
private function createSerializer(): Serializer
325394
{
326-
$serializer = new Serializer(
327-
new SerializerComponent\Serializer([new ObjectNormalizer()], ['json' => new JsonEncoder()])
395+
return new Serializer(
396+
new SerializerComponent\Serializer([new DateTimeNormalizer(), new ArrayDenormalizer(), new ObjectNormalizer()], ['json' => new JsonEncoder()])
328397
);
329-
330-
return $serializer;
331398
}
332399
}

src/Symfony/Component/Messenger/Bridge/Doctrine/Transport/DoctrineReceiver.php

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -141,10 +141,12 @@ private function createEnvelopeFromData(array $data): Envelope
141141
throw $exception;
142142
}
143143

144-
return $envelope->with(
145-
new DoctrineReceivedStamp($data['id']),
146-
new TransportMessageIdStamp($data['id'])
147-
);
144+
return $envelope
145+
->withoutAll(TransportMessageIdStamp::class)
146+
->with(
147+
new DoctrineReceivedStamp($data['id']),
148+
new TransportMessageIdStamp($data['id'])
149+
);
148150
}
149151

150152
private function withRetryableExceptionRetry(callable $callable): void

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy