Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 4eb07c6

Browse files
committed
[Messenger] Fix processing batches
1 parent d4ab8c4 commit 4eb07c6

4 files changed

Lines changed: 68 additions & 6 deletions

File tree

src/Symfony/Component/Messenger/Handler/BatchHandlerTrait.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,10 @@ trait BatchHandlerTrait
2020

2121
public function flush(bool $force): void
2222
{
23+
if (!$force && !$this->shouldFlush()) {
24+
return;
25+
}
26+
2327
if ($jobs = $this->jobs) {
2428
$this->jobs = [];
2529
$this->process($jobs);

src/Symfony/Component/Messenger/Tests/Middleware/HandleMessageMiddlewareTest.php

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -323,6 +323,54 @@ private function process(array $jobs): void
323323
$this->assertSame([$message], $handler->processedMessages);
324324
}
325325

326+
public function testBatchHandlerFlushFalseDoesNotFlushPartialBatch()
327+
{
328+
$handler = new class implements BatchHandlerInterface {
329+
public array $processedMessages = [];
330+
331+
use BatchHandlerTrait;
332+
333+
public function __invoke(DummyMessage $message, ?Acknowledger $ack = null)
334+
{
335+
return $this->handle($message, $ack);
336+
}
337+
338+
private function getBatchSize(): int
339+
{
340+
return 3;
341+
}
342+
343+
private function process(array $jobs): void
344+
{
345+
$this->processedMessages = array_column($jobs, 0);
346+
347+
foreach ($jobs as [$job, $ack]) {
348+
$ack->ack($job);
349+
}
350+
}
351+
};
352+
353+
$middleware = new HandleMessageMiddleware(new HandlersLocator([
354+
DummyMessage::class => [new HandlerDescriptor($handler)],
355+
]));
356+
357+
$ack = static function () {};
358+
359+
$message = new DummyMessage('Hey');
360+
$envelope = $middleware->handle(new Envelope($message, [new AckStamp($ack)]), new StackMiddleware());
361+
362+
$this->assertEmpty($handler->processedMessages);
363+
$this->assertCount(1, $envelope->all(NoAutoAckStamp::class));
364+
365+
$handler->flush(false);
366+
367+
$this->assertEmpty($handler->processedMessages);
368+
369+
$handler->flush(true);
370+
371+
$this->assertSame([$message], $handler->processedMessages);
372+
}
373+
326374
public function testHandlerArgumentsStamp()
327375
{
328376
$message = new DummyMessage('Hey');

src/Symfony/Component/Messenger/Tests/WorkerTest.php

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -545,15 +545,15 @@ public function testFlushBatchOnIdle()
545545
static $i = 0;
546546
if (1 < ++$i) {
547547
$event->getWorker()->stop();
548-
$this->assertSame(1, $receiver->getAcknowledgeCount());
549-
} else {
550-
$this->assertSame(0, $receiver->getAcknowledgeCount());
551548
}
549+
$this->assertSame(0, $receiver->getAcknowledgeCount());
552550
});
553551

554552
$worker = new Worker([$receiver], $bus, $dispatcher, clock: new MockClock());
555553
$worker->run();
556554

555+
$this->assertSame(1, $receiver->getAcknowledgeCount());
556+
557557
$this->assertSame($expectedMessages, $handler->processedMessages);
558558
}
559559

@@ -619,7 +619,7 @@ public function dispatch(object $message, array $stamps = []): Envelope
619619
$unacks = $unacksProperty->getValue($worker);
620620
$dummyHandler = new DummyBatchHandler();
621621
$envelopeWithNoAutoAck = $envelope->with(new NoAutoAckStamp(new HandlerDescriptor($dummyHandler)));
622-
$unacks[$dummyHandler] = [$envelopeWithNoAutoAck, 'transport'];
622+
$unacks[$dummyHandler] = [$envelopeWithNoAutoAck, 'transport', false];
623623

624624
$worker->run();
625625

src/Symfony/Component/Messenger/Worker.php

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ private function handleMessage(Envelope $envelope, string $transportName): void
165165
if (!$acked && !$noAutoAckStamp) {
166166
$this->acks[] = [$transportName, $envelope, $e];
167167
} elseif ($noAutoAckStamp) {
168-
$this->unacks[$noAutoAckStamp->getHandlerDescriptor()->getBatchHandler()] = [$envelope->withoutAll(AckStamp::class), $transportName];
168+
$this->unacks[$noAutoAckStamp->getHandlerDescriptor()->getBatchHandler()] = [$envelope->withoutAll(AckStamp::class), $transportName, &$acked];
169169
}
170170

171171
$this->ack();
@@ -254,13 +254,23 @@ private function flush(bool $force): bool
254254
$this->unacks = new \SplObjectStorage();
255255

256256
foreach ($unacks as $batchHandler) {
257-
[$envelope, $transportName] = $unacks[$batchHandler];
257+
[$envelope, $transportName, $acked] = $unacks[$batchHandler];
258258
try {
259+
$e = null;
259260
$this->bus->dispatch($envelope->with(new FlushBatchHandlersStamp($force)));
260261
unset($unacks[$batchHandler], $batchHandler);
261262
} catch (\Throwable $e) {
262263
$envelope = $envelope->withoutAll(NoAutoAckStamp::class);
263264
$this->acks[] = [$transportName, $envelope, $e];
265+
continue;
266+
}
267+
268+
$noAutoAckStamp = $envelope->last(NoAutoAckStamp::class);
269+
270+
if (!$acked && !$noAutoAckStamp) {
271+
$this->acks[] = [$transportName, $envelope, $e];
272+
} elseif ($noAutoAckStamp) {
273+
$this->unacks[$noAutoAckStamp->getHandlerDescriptor()->getBatchHandler()] = [$envelope->withoutAll(AckStamp::class), $transportName, &$acked];
264274
}
265275
}
266276

0 commit comments

Comments
 (0)