From 2a3f07e954a8909844d9d9a6defe357e66d81c33 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yann=20Eugon=C3=A9?= Date: Thu, 16 Apr 2026 17:22:39 +0200 Subject: [PATCH 1/2] Fix copy-paste bug: endTime filter was checking start_time IS NOT NULL instead of end_time --- src/batch-doctrine-dbal/src/DoctrineDBALJobExecutionStorage.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/batch-doctrine-dbal/src/DoctrineDBALJobExecutionStorage.php b/src/batch-doctrine-dbal/src/DoctrineDBALJobExecutionStorage.php index 76a0dbb1..3ae9a824 100644 --- a/src/batch-doctrine-dbal/src/DoctrineDBALJobExecutionStorage.php +++ b/src/batch-doctrine-dbal/src/DoctrineDBALJobExecutionStorage.php @@ -395,7 +395,7 @@ private function addWheres(Query $query, QueryBuilder $qb): array } if ($query->endTime() !== null) { - $qb->andWhere($qb->expr()->isNotNull('start_time')); + $qb->andWhere($qb->expr()->isNotNull('end_time')); } $endDateFrom = $query->endTime()?->getFrom(); if ($endDateFrom !== null) { From a4cd692427eaa1602bf5251e54f9220fcf669aed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yann=20Eugon=C3=A9?= Date: Thu, 16 Apr 2026 17:23:55 +0200 Subject: [PATCH 2/2] Make FilterUniqueProcessor implement InitializableInterface to reset state between job runs --- .../Item/Processor/FilterUniqueProcessor.php | 8 ++++++- .../Processor/FilterUniqueProcessorTest.php | 21 ++++++++++++------- 2 files changed, 20 insertions(+), 9 deletions(-) diff --git a/src/batch/src/Job/Item/Processor/FilterUniqueProcessor.php b/src/batch/src/Job/Item/Processor/FilterUniqueProcessor.php index dd2dc024..74bbb7cb 100644 --- a/src/batch/src/Job/Item/Processor/FilterUniqueProcessor.php +++ b/src/batch/src/Job/Item/Processor/FilterUniqueProcessor.php @@ -6,6 +6,7 @@ use Closure; use Yokai\Batch\Job\Item\Exception\SkipItemException; +use Yokai\Batch\Job\Item\InitializableInterface; use Yokai\Batch\Job\Item\ItemProcessorInterface; /** @@ -15,7 +16,7 @@ * it will use a {@see Closure} that will be called for each item * and that will be responsible for extracting an identifier from the item. */ -final class FilterUniqueProcessor implements ItemProcessorInterface +final class FilterUniqueProcessor implements ItemProcessorInterface, InitializableInterface { /** * @var array @@ -60,6 +61,11 @@ public static function withGetter(string $getter): self return new self(fn(object $item) => $item->$getter()); } + public function initialize(): void + { + $this->encountered = []; + } + public function process(mixed $item): mixed { $unique = (string)($this->extractUnique)($item); diff --git a/src/batch/tests/Job/Item/Processor/FilterUniqueProcessorTest.php b/src/batch/tests/Job/Item/Processor/FilterUniqueProcessorTest.php index c37fb955..a394bca3 100644 --- a/src/batch/tests/Job/Item/Processor/FilterUniqueProcessorTest.php +++ b/src/batch/tests/Job/Item/Processor/FilterUniqueProcessorTest.php @@ -19,16 +19,21 @@ public function test(callable $factory, array $items, array $expected): void /** @var FilterUniqueProcessor $processor */ $processor = $factory(); - $actual = []; - foreach ($items as $item) { - try { - $actual[] = $processor->process($item); - } catch (SkipItemException) { - //the item have be filtered and not won't be added to $actual + // test is done twice to prove initialize method resets state + foreach ([1, 2] as $unused) { + $processor->initialize(); + + $actual = []; + foreach ($items as $item) { + try { + $actual[] = $processor->process($item); + } catch (SkipItemException) { + //the item have be filtered and not won't be added to $actual + } } - } - self::assertSame($expected, $actual); + self::assertSame($expected, $actual); + } } public static function provider(): Generator