10000 [Doctrine][Messenger] Prevents multiple TransportMessageIdStamp being… · symfony/doctrine-messenger@61646e2 · GitHub
[go: up one dir, main page]

Skip to content

Commit 61646e2

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: symfony/symfony#49637
1 parent c4afe70 commit 61646e2

File tree

2 files changed

+81
-12
lines changed

2 files changed

+81
-12
lines changed

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 8000 \ObjectNormalizer;
3234

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

105+
public function testGetReplacesExistingTransportMessageIdStamps()
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()
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()
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 6D40 +
$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
}

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)
0