From 43a52c68e88134ff5a93cc93f2f401865e2bc722 Mon Sep 17 00:00:00 2001 From: Guicherd Date: Thu, 11 Jan 2024 17:13:41 +0100 Subject: [PATCH 1/4] feature #98 Total count JobExecution matched by query --- .../src/DoctrineDBALJobExecutionStorage.php | 71 ++++++++++++------- .../DoctrineDBALJobExecutionStorageTest.php | 1 + .../Storage/FilesystemJobExecutionStorage.php | 8 +++ .../QueryableJobExecutionStorageInterface.php | 5 ++ .../FilesystemJobExecutionStorageTest.php | 1 + 5 files changed, 62 insertions(+), 24 deletions(-) diff --git a/src/batch-doctrine-dbal/src/DoctrineDBALJobExecutionStorage.php b/src/batch-doctrine-dbal/src/DoctrineDBALJobExecutionStorage.php index b5bceb8e..8fee8005 100644 --- a/src/batch-doctrine-dbal/src/DoctrineDBALJobExecutionStorage.php +++ b/src/batch-doctrine-dbal/src/DoctrineDBALJobExecutionStorage.php @@ -7,6 +7,7 @@ use Doctrine\DBAL\Connection; use Doctrine\DBAL\Driver\Result; use Doctrine\DBAL\Exception as DBALException; +use Doctrine\DBAL\Query\QueryBuilder; use Doctrine\DBAL\Schema\Comparator; use Doctrine\DBAL\Schema\Schema; use Doctrine\DBAL\Types\Types; @@ -147,33 +148,11 @@ public function list(string $jobName): iterable public function query(Query $query): iterable { - $queryParameters = []; - $queryTypes = []; - $qb = $this->connection->createQueryBuilder(); $qb->select('*') ->from($this->table); - $names = $query->jobs(); - if (\count($names) > 0) { - $qb->andWhere($qb->expr()->in('job_name', ':jobNames')); - $queryParameters['jobNames'] = $names; - $queryTypes['jobNames'] = Connection::PARAM_STR_ARRAY; - } - - $ids = $query->ids(); - if (\count($ids) > 0) { - $qb->andWhere($qb->expr()->in('id', ':ids')); - $queryParameters['ids'] = $ids; - $queryTypes['ids'] = Connection::PARAM_STR_ARRAY; - } - - $statuses = $query->statuses(); - if (\count($statuses) > 0) { - $qb->andWhere($qb->expr()->in('status', ':statuses')); - $queryParameters['statuses'] = $statuses; - $queryTypes['statuses'] = Connection::PARAM_INT_ARRAY; - } + [$queryParameters, $queryTypes] = $this->addWheres($query, $qb); if ($query->startTime()) { $qb->andWhere($qb->expr()->isNotNull('start_time')); @@ -228,6 +207,18 @@ public function query(Query $query): iterable yield from $this->queryList($qb->getSQL(), $queryParameters, $queryTypes); } + public function count(Query $query): int + { + $qb = $this->connection->createQueryBuilder(); + $qb->select('count(*)') + ->from($this->table); + + /** @var int $result */ + $result = $this->connection->executeQuery($qb->getSQL(), ...$this->addWheres($query, $qb))->fetchOne(); + + return $result; + } + private function getSchema(): Schema { $schema = new Schema(); @@ -319,7 +310,7 @@ private function fetchRow(string $jobName, string $id): array /** * @phpstan-param array $parameters - * @phpstan-param array $types + * @phpstan-param array|int> $types * * @phpstan-return Generator */ @@ -357,4 +348,36 @@ private function getNormalizer(): JobExecutionRowNormalizer return $this->normalizer; } + + /** + * @return array|int>> + */ + private function addWheres(Query $query, QueryBuilder $qb): array + { + $queryParameters = []; + $queryTypes = []; + + $names = $query->jobs(); + if (\count($names) > 0) { + $qb->andWhere($qb->expr()->in('job_name', ':jobNames')); + $queryParameters['jobNames'] = $names; + $queryTypes['jobNames'] = Connection::PARAM_STR_ARRAY; + } + + $ids = $query->ids(); + if (\count($ids) > 0) { + $qb->andWhere($qb->expr()->in('id', ':ids')); + $queryParameters['ids'] = $ids; + $queryTypes['ids'] = Connection::PARAM_STR_ARRAY; + } + + $statuses = $query->statuses(); + if (\count($statuses) > 0) { + $qb->andWhere($qb->expr()->in('status', ':statuses')); + $queryParameters['statuses'] = $statuses; + $queryTypes['statuses'] = Connection::PARAM_INT_ARRAY; + } + + return [$queryParameters, $queryTypes]; + } } diff --git a/src/batch-doctrine-dbal/tests/DoctrineDBALJobExecutionStorageTest.php b/src/batch-doctrine-dbal/tests/DoctrineDBALJobExecutionStorageTest.php index 7ba5daca..bb5a6f85 100644 --- a/src/batch-doctrine-dbal/tests/DoctrineDBALJobExecutionStorageTest.php +++ b/src/batch-doctrine-dbal/tests/DoctrineDBALJobExecutionStorageTest.php @@ -282,6 +282,7 @@ public function testQuery(QueryBuilder $queryBuilder, array $expectedCouples): v $this->loadFixtures($storage); self::assertExecutions($expectedCouples, $storage->query($queryBuilder->getQuery())); + self::assertSame(\count($expectedCouples[0]), $storage->count($queryBuilder->getQuery())); } public function queries(): Generator diff --git a/src/batch/src/Storage/FilesystemJobExecutionStorage.php b/src/batch/src/Storage/FilesystemJobExecutionStorage.php index 51581b59..b16690ec 100644 --- a/src/batch/src/Storage/FilesystemJobExecutionStorage.php +++ b/src/batch/src/Storage/FilesystemJobExecutionStorage.php @@ -159,6 +159,14 @@ public function query(Query $query): iterable return \array_slice($candidates, $query->offset(), $query->limit()); } + public function count(Query $query): int + { + /** @var JobExecution[] $result */ + $result = $this->query($query); + + return \count($result); + } + private function buildFilePath(string $jobName, string $executionId): string { return \implode(DIRECTORY_SEPARATOR, [$this->directory, $jobName, $executionId]) . diff --git a/src/batch/src/Storage/QueryableJobExecutionStorageInterface.php b/src/batch/src/Storage/QueryableJobExecutionStorageInterface.php index 50f798f9..c4b1c90f 100644 --- a/src/batch/src/Storage/QueryableJobExecutionStorageInterface.php +++ b/src/batch/src/Storage/QueryableJobExecutionStorageInterface.php @@ -17,4 +17,9 @@ interface QueryableJobExecutionStorageInterface extends ListableJobExecutionStor * @return iterable|JobExecution[] */ public function query(Query $query): iterable; + + /** + * Execute query against stored job executions, and return count result. + */ + public function count(Query $query): int; } diff --git a/src/batch/tests/Storage/FilesystemJobExecutionStorageTest.php b/src/batch/tests/Storage/FilesystemJobExecutionStorageTest.php index bb945a9b..0a6d271d 100644 --- a/src/batch/tests/Storage/FilesystemJobExecutionStorageTest.php +++ b/src/batch/tests/Storage/FilesystemJobExecutionStorageTest.php @@ -150,6 +150,7 @@ public function testQueryWithProvider(QueryBuilder $query, array $expectedCouple ); self::assertExecutions($expectedCouples, $storage->query($query->getQuery())); + self::assertEquals(\count($expectedCouples), $storage->count($query->getQuery())); } public function query(): \Generator From f111263a7f9ef460a49c3e9be383ba6ba1704b49 Mon Sep 17 00:00:00 2001 From: Guicherd Date: Tue, 27 Feb 2024 12:28:15 +0100 Subject: [PATCH 2/4] #98 fix phpstan --- .../src/DoctrineDBALJobExecutionStorage.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/batch-doctrine-dbal/src/DoctrineDBALJobExecutionStorage.php b/src/batch-doctrine-dbal/src/DoctrineDBALJobExecutionStorage.php index 8fee8005..be6e0494 100644 --- a/src/batch-doctrine-dbal/src/DoctrineDBALJobExecutionStorage.php +++ b/src/batch-doctrine-dbal/src/DoctrineDBALJobExecutionStorage.php @@ -152,6 +152,10 @@ public function query(Query $query): iterable $qb->select('*') ->from($this->table); + /** + * @phpstan-var array> $queryParameters + * @phpstan-var array $queryTypes + */ [$queryParameters, $queryTypes] = $this->addWheres($query, $qb); if ($query->startTime()) { @@ -310,7 +314,7 @@ private function fetchRow(string $jobName, string $id): array /** * @phpstan-param array $parameters - * @phpstan-param array|int> $types + * @phpstan-param array $types * * @phpstan-return Generator */ From ac3efd1f161869cd17114b81420ea869357c105a Mon Sep 17 00:00:00 2001 From: Guicherd Date: Tue, 27 Feb 2024 15:11:49 +0100 Subject: [PATCH 3/4] #98 fix unit test --- .../tests/DoctrineDBALJobExecutionStorageTest.php | 2 +- .../tests/Storage/FilesystemJobExecutionStorageTest.php | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/batch-doctrine-dbal/tests/DoctrineDBALJobExecutionStorageTest.php b/src/batch-doctrine-dbal/tests/DoctrineDBALJobExecutionStorageTest.php index bb5a6f85..09f00733 100644 --- a/src/batch-doctrine-dbal/tests/DoctrineDBALJobExecutionStorageTest.php +++ b/src/batch-doctrine-dbal/tests/DoctrineDBALJobExecutionStorageTest.php @@ -282,7 +282,7 @@ public function testQuery(QueryBuilder $queryBuilder, array $expectedCouples): v $this->loadFixtures($storage); self::assertExecutions($expectedCouples, $storage->query($queryBuilder->getQuery())); - self::assertSame(\count($expectedCouples[0]), $storage->count($queryBuilder->getQuery())); + self::assertSame(\count($expectedCouples), $storage->count($queryBuilder->getQuery())); } public function queries(): Generator diff --git a/src/batch/tests/Storage/FilesystemJobExecutionStorageTest.php b/src/batch/tests/Storage/FilesystemJobExecutionStorageTest.php index 0a6d271d..6199608c 100644 --- a/src/batch/tests/Storage/FilesystemJobExecutionStorageTest.php +++ b/src/batch/tests/Storage/FilesystemJobExecutionStorageTest.php @@ -142,7 +142,7 @@ public function list(): \Generator /** * @dataProvider query */ - public function testQueryWithProvider(QueryBuilder $query, array $expectedCouples): void + public function testQueryWithProvider(QueryBuilder $query, array $expectedCouples, ?int $expectedCount = null): void { $storage = $this->createStorage( __DIR__ . '/fixtures/filesystem-job-execution', @@ -150,7 +150,8 @@ public function testQueryWithProvider(QueryBuilder $query, array $expectedCouple ); self::assertExecutions($expectedCouples, $storage->query($query->getQuery())); - self::assertEquals(\count($expectedCouples), $storage->count($query->getQuery())); + $expectedCount ??= count($expectedCouples); + self::assertEquals($expectedCount, $storage->count($query->getQuery())); } public function query(): \Generator From 9bf7a15cbac07abb011ae588ab5d357e57de70c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yann=20Eugon=C3=A9?= Date: Wed, 8 Jan 2025 12:09:34 +0100 Subject: [PATCH 4/4] Rebase branch --- .../src/DoctrineDBALJobExecutionStorage.php | 78 ++++++++++--------- .../FilesystemJobExecutionStorageTest.php | 5 +- 2 files changed, 44 insertions(+), 39 deletions(-) diff --git a/src/batch-doctrine-dbal/src/DoctrineDBALJobExecutionStorage.php b/src/batch-doctrine-dbal/src/DoctrineDBALJobExecutionStorage.php index be6e0494..5133e0c7 100644 --- a/src/batch-doctrine-dbal/src/DoctrineDBALJobExecutionStorage.php +++ b/src/batch-doctrine-dbal/src/DoctrineDBALJobExecutionStorage.php @@ -153,43 +153,11 @@ public function query(Query $query): iterable ->from($this->table); /** - * @phpstan-var array> $queryParameters - * @phpstan-var array $queryTypes + * @phpstan-var array $queryParameters + * @phpstan-var array $queryTypes */ [$queryParameters, $queryTypes] = $this->addWheres($query, $qb); - if ($query->startTime()) { - $qb->andWhere($qb->expr()->isNotNull('start_time')); - } - $startDateFrom = $query->startTime()?->getFrom(); - if ($startDateFrom) { - $qb->andWhere($qb->expr()->gte('start_time', ':startDateFrom')); - $queryParameters['startDateFrom'] = $startDateFrom; - $queryTypes['startDateFrom'] = Types::DATETIME_IMMUTABLE; - } - $startDateTo = $query->startTime()?->getTo(); - if ($startDateTo) { - $qb->andWhere($qb->expr()->lte('start_time', ':startDateTo')); - $queryParameters['startDateTo'] = $startDateTo; - $queryTypes['startDateTo'] = Types::DATETIME_IMMUTABLE; - } - - if ($query->endTime()) { - $qb->andWhere($qb->expr()->isNotNull('start_time')); - } - $endDateFrom = $query->endTime()?->getFrom(); - if ($endDateFrom) { - $qb->andWhere($qb->expr()->gte('end_time', ':endDateFrom')); - $queryParameters['endDateFrom'] = $endDateFrom; - $queryTypes['endDateFrom'] = Types::DATETIME_IMMUTABLE; - } - $endDateTo = $query->endTime()?->getTo(); - if ($endDateTo) { - $qb->andWhere($qb->expr()->lte('end_time', ':endDateTo')); - $queryParameters['endDateTo'] = $endDateTo; - $queryTypes['endDateTo'] = Types::DATETIME_IMMUTABLE; - } - switch ($query->sort()) { case Query::SORT_BY_START_ASC: $qb->orderBy('start_time', 'asc'); @@ -217,8 +185,14 @@ public function count(Query $query): int $qb->select('count(*)') ->from($this->table); + /** + * @phpstan-var array $queryParameters + * @phpstan-var array $queryTypes + */ + [$queryParameters, $queryTypes] = $this->addWheres($query, $qb); + /** @var int $result */ - $result = $this->connection->executeQuery($qb->getSQL(), ...$this->addWheres($query, $qb))->fetchOne(); + $result = $this->connection->executeQuery($qb->getSQL(), $queryParameters, $queryTypes)->fetchOne(); return $result; } @@ -354,7 +328,7 @@ private function getNormalizer(): JobExecutionRowNormalizer } /** - * @return array|int>> + * @return array{array, array} */ private function addWheres(Query $query, QueryBuilder $qb): array { @@ -382,6 +356,38 @@ private function addWheres(Query $query, QueryBuilder $qb): array $queryTypes['statuses'] = Connection::PARAM_INT_ARRAY; } + if ($query->startTime()) { + $qb->andWhere($qb->expr()->isNotNull('start_time')); + } + $startDateFrom = $query->startTime()?->getFrom(); + if ($startDateFrom) { + $qb->andWhere($qb->expr()->gte('start_time', ':startDateFrom')); + $queryParameters['startDateFrom'] = $startDateFrom; + $queryTypes['startDateFrom'] = Types::DATETIME_IMMUTABLE; + } + $startDateTo = $query->startTime()?->getTo(); + if ($startDateTo) { + $qb->andWhere($qb->expr()->lte('start_time', ':startDateTo')); + $queryParameters['startDateTo'] = $startDateTo; + $queryTypes['startDateTo'] = Types::DATETIME_IMMUTABLE; + } + + if ($query->endTime()) { + $qb->andWhere($qb->expr()->isNotNull('start_time')); + } + $endDateFrom = $query->endTime()?->getFrom(); + if ($endDateFrom) { + $qb->andWhere($qb->expr()->gte('end_time', ':endDateFrom')); + $queryParameters['endDateFrom'] = $endDateFrom; + $queryTypes['endDateFrom'] = Types::DATETIME_IMMUTABLE; + } + $endDateTo = $query->endTime()?->getTo(); + if ($endDateTo) { + $qb->andWhere($qb->expr()->lte('end_time', ':endDateTo')); + $queryParameters['endDateTo'] = $endDateTo; + $queryTypes['endDateTo'] = Types::DATETIME_IMMUTABLE; + } + return [$queryParameters, $queryTypes]; } } diff --git a/src/batch/tests/Storage/FilesystemJobExecutionStorageTest.php b/src/batch/tests/Storage/FilesystemJobExecutionStorageTest.php index 6199608c..0a6d271d 100644 --- a/src/batch/tests/Storage/FilesystemJobExecutionStorageTest.php +++ b/src/batch/tests/Storage/FilesystemJobExecutionStorageTest.php @@ -142,7 +142,7 @@ public function list(): \Generator /** * @dataProvider query */ - public function testQueryWithProvider(QueryBuilder $query, array $expectedCouples, ?int $expectedCount = null): void + public function testQueryWithProvider(QueryBuilder $query, array $expectedCouples): void { $storage = $this->createStorage( __DIR__ . '/fixtures/filesystem-job-execution', @@ -150,8 +150,7 @@ public function testQueryWithProvider(QueryBuilder $query, array $expectedCouple ); self::assertExecutions($expectedCouples, $storage->query($query->getQuery())); - $expectedCount ??= count($expectedCouples); - self::assertEquals($expectedCount, $storage->count($query->getQuery())); + self::assertEquals(\count($expectedCouples), $storage->count($query->getQuery())); } public function query(): \Generator