From b4b6fcc53e3ba3f7b90b3ff09e5b50836013fe2e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yann=20Eugon=C3=A9?= Date: Wed, 15 Apr 2026 20:23:25 +0200 Subject: [PATCH] Add QueryableJobExecutionStorageInterface::purge --- .../src/DoctrineDBALJobExecutionStorage.php | 10 +++++++ .../DoctrineDBALJobExecutionStorageTest.php | 15 +++++++++++ .../Storage/FilesystemJobExecutionStorage.php | 7 +++++ .../QueryableJobExecutionStorageInterface.php | 6 +++++ .../FilesystemJobExecutionStorageTest.php | 26 +++++++++++++++++++ 5 files changed, 64 insertions(+) diff --git a/src/batch-doctrine-dbal/src/DoctrineDBALJobExecutionStorage.php b/src/batch-doctrine-dbal/src/DoctrineDBALJobExecutionStorage.php index 37663925..76a0dbb1 100644 --- a/src/batch-doctrine-dbal/src/DoctrineDBALJobExecutionStorage.php +++ b/src/batch-doctrine-dbal/src/DoctrineDBALJobExecutionStorage.php @@ -192,6 +192,16 @@ public function count(Query $query): int return $result; } + public function purge(Query $query): void + { + $qb = $this->connection->createQueryBuilder(); + $qb->delete($this->table); + + [$queryParameters, $queryTypes] = $this->addWheres($query, $qb); + + $this->connection->executeStatement($qb->getSQL(), $queryParameters, $queryTypes); + } + private function getSchema(): Schema { $schema = new Schema(); diff --git a/src/batch-doctrine-dbal/tests/DoctrineDBALJobExecutionStorageTest.php b/src/batch-doctrine-dbal/tests/DoctrineDBALJobExecutionStorageTest.php index 17ec0af9..88019772 100644 --- a/src/batch-doctrine-dbal/tests/DoctrineDBALJobExecutionStorageTest.php +++ b/src/batch-doctrine-dbal/tests/DoctrineDBALJobExecutionStorageTest.php @@ -427,6 +427,21 @@ public function testCountIgnoresLimit(): void self::assertSame(4, $storage->count($query)); } + public function testPurge(): void + { + $storage = $this->createStorage(); + $storage->setup(); + $this->loadFixtures($storage); + + // limit is ignored by purge — all "import" executions must be deleted (3 total) + $storage->purge((new QueryBuilder())->jobs(['import'])->limit(1, 0)->getQuery()); + + self::assertExecutions( + [['export', '123']], + $storage->query((new QueryBuilder())->getQuery()), + ); + } + public static function assertExecutionIds(array $ids, iterable $executions): void { $actualIds = []; diff --git a/src/batch/src/Storage/FilesystemJobExecutionStorage.php b/src/batch/src/Storage/FilesystemJobExecutionStorage.php index 86c242d7..93cf2625 100644 --- a/src/batch/src/Storage/FilesystemJobExecutionStorage.php +++ b/src/batch/src/Storage/FilesystemJobExecutionStorage.php @@ -115,6 +115,13 @@ public function count(Query $query): int return \count($jobExecutions); } + public function purge(Query $query): void + { + foreach ($this->rawQuery($query) as $execution) { + $this->remove($execution); + } + } + /** * @return list */ diff --git a/src/batch/src/Storage/QueryableJobExecutionStorageInterface.php b/src/batch/src/Storage/QueryableJobExecutionStorageInterface.php index a5734771..60a72c6a 100644 --- a/src/batch/src/Storage/QueryableJobExecutionStorageInterface.php +++ b/src/batch/src/Storage/QueryableJobExecutionStorageInterface.php @@ -23,4 +23,10 @@ public function query(Query $query): iterable; * Note: limit and offset from the query are ignored — all matching executions are counted. */ public function count(Query $query): int; + + /** + * Delete all job executions matching the given query. + * Note: limit and offset from the query are ignored — all matching executions are deleted. + */ + public function purge(Query $query): void; } diff --git a/src/batch/tests/Storage/FilesystemJobExecutionStorageTest.php b/src/batch/tests/Storage/FilesystemJobExecutionStorageTest.php index 58fe5af9..61723470 100644 --- a/src/batch/tests/Storage/FilesystemJobExecutionStorageTest.php +++ b/src/batch/tests/Storage/FilesystemJobExecutionStorageTest.php @@ -343,4 +343,30 @@ public function testRemoveFileNotWritable(): void $jobExecution = JobExecution::createRoot('123456789', 'export'); $this->createStorage(self::READONLY_STORAGE_DIR)->remove($jobExecution); } + + public function testPurge(): void + { + $storage = $this->createStorage( + self::STORAGE_DIR . '/purge', + new JsonJobExecutionSerializer(new InMemoryJobExecutionLoggerFactory()), + ); + + foreach (['20210920', '20210922'] as $id) { + $storage->store(JobExecution::createRoot($id, 'export')); + } + foreach (['20210910', '20210915', '20210920'] as $id) { + $storage->store(JobExecution::createRoot($id, 'list')); + } + + // limit is ignored by purge — all 3 "list" executions must be deleted + $storage->purge((new QueryBuilder())->jobs(['list'])->limit(1, 0)->getQuery()); + + self::assertExecutions( + [ + ['export', '20210920'], + ['export', '20210922'], + ], + $storage->query((new QueryBuilder())->getQuery()), + ); + } }