Skip to content
Merged
6 changes: 3 additions & 3 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -88,9 +88,9 @@ jobs:
symfony-version: '7.0.*'
coverage-mode: 'xdebug'
- name: "Run tests with phpunit/phpunit"
env:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
run: |
vendor/bin/phpunit --testsuite=Code --coverage-clover coverage.xml
- name: "Upload coverage to Codecov"
uses: codecov/codecov-action@v1
uses: codecov/codecov-action@v5
env:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
32 changes: 32 additions & 0 deletions src/batch-doctrine-dbal/src/DoctrineDBALJobExecutionStorage.php
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,38 @@ public function query(Query $query): iterable
$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;
}

switch ($query->sort()) {
case Query::SORT_BY_START_ASC:
$qb->orderBy('start_time', 'asc');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -357,6 +357,53 @@ public function queries(): Generator
['import', '789'],
],
];
yield 'Filter start time lower boundary' => [
(new QueryBuilder())
->startTime(new \DateTimeImmutable('2019-07-01T13:00:01+0200'), null),
[
['import', '456'],
],
];
yield 'Filter start time upper boundary' => [
(new QueryBuilder())
->startTime(null, new \DateTimeImmutable('2019-06-30T22:00:00+0200')),
[
['import', '789'],
],
];
yield 'Filter start time boundaries' => [
(new QueryBuilder())
->startTime(
new \DateTimeImmutable('2019-07-01T13:00:01+0200'),
new \DateTimeImmutable('2019-07-01T17:29:29+0200'),
),
[
// none
],
];
yield 'Filter end time lower boundary' => [
(new QueryBuilder())
->endTime(new \DateTimeImmutable('2019-07-01T13:30:01+0200'), null),
[
['import', '456'],
],
];
yield 'Filter end time upper boundary' => [
(new QueryBuilder())
->endTime(null, new \DateTimeImmutable('2019-07-01T18:29:59+0200')),
[
['export', '123'],
],
];
yield 'Filter end time boundaries' => [
(new QueryBuilder())
->endTime(
new \DateTimeImmutable('2019-07-01T13:30:01+0200'),
new \DateTimeImmutable('2019-07-01T18:29:59+0200'),
),
[
],
];
}

public static function assertExecutionIds(array $ids, iterable $executions): void
Expand Down
20 changes: 20 additions & 0 deletions src/batch/src/Storage/FilesystemJobExecutionStorage.php
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,26 @@ public function query(Query $query): iterable
continue;
}

$startTime = $execution->getStartTime();
$startDateFrom = $query->startTime()?->getFrom();
if ($startDateFrom !== null && ($startTime === null || $startTime < $startDateFrom)) {
continue;
}
$startDateTo = $query->startTime()?->getTo();
if ($startDateTo !== null && ($startTime === null || $startTime > $startDateTo)) {
continue;
}

$endTime = $execution->getEndTime();
$endDateFrom = $query->endTime()?->getFrom();
if ($endDateFrom !== null && ($endTime === null || $endTime < $endDateFrom)) {
continue;
}
$endDateTo = $query->endTime()?->getTo();
if ($endDateTo !== null && ($endTime === null || $endTime > $endDateTo)) {
continue;
}

$candidates[] = $execution;
}

Expand Down
14 changes: 13 additions & 1 deletion src/batch/src/Storage/Query.php
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,11 @@ public function __construct(
* @var int[]
*/
private array $statuses,
private ?TimeFilter $startTime,
private ?TimeFilter $endTime,
private ?string $sort,
private int $limit,
private int $offset = 0,
private int $offset,
) {
}

Expand Down Expand Up @@ -63,6 +65,16 @@ public function statuses(): array
return $this->statuses;
}

public function startTime(): ?TimeFilter
{
return $this->startTime;
}

public function endTime(): ?TimeFilter
{
return $this->endTime;
}

public function sort(): ?string
{
return $this->sort;
Expand Down
58 changes: 57 additions & 1 deletion src/batch/src/Storage/QueryBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

namespace Yokai\Batch\Storage;

use DateTimeInterface;
use Yokai\Batch\BatchStatus;
use Yokai\Batch\Exception\UnexpectedValueException;

Expand All @@ -16,6 +17,8 @@
* ->ids(['123', '456'])
* ->jobs(['export', 'import'])
* ->statuses([BatchStatus::RUNNING, BatchStatus::COMPLETED])
* ->startTime(new \DateTimeImmutable('2023-07-07 15:18'), new \DateTime('2023-07-07 16:30'))
* ->endTime(new \DateTimeImmutable('2023-07-07 15:18'), new \DateTime('2023-07-07 16:30'))
* ->sort(Query::SORT_BY_END_DESC)
* ->limit(6, 12)
* ->getQuery();
Expand All @@ -26,6 +29,8 @@
* $builder->ids(['123', '456']);
* $builder->jobs(['export', 'import']);
* $builder->statuses([BatchStatus::RUNNING, BatchStatus::COMPLETED]);
* $builder->startTime(new \DateTimeImmutable('2023-07-07 15:18'), new \DateTime('2023-07-07 16:30'));
* $builder->endTime(new \DateTimeImmutable('2023-07-07 15:18'), new \DateTime('2023-07-07 16:30'));
* $builder->sort(Query::SORT_BY_END_DESC);
* $builder->limit(6, 12);
* $builder->getQuery();
Expand Down Expand Up @@ -63,6 +68,10 @@ final class QueryBuilder
*/
private array $statuses = [];

private ?TimeFilter $startTime = null;

private ?TimeFilter $endTime = null;

private ?string $sortBy = null;

private int $limit = 10;
Expand Down Expand Up @@ -126,6 +135,44 @@ public function statuses(array $statuses): self
return $this;
}

/**
* Filter executions that started in a frame.
* Both frame boundaries are optional.
* Calling this method with both null boundaries result in removing the filter.
*
* @param DateTimeInterface|null $from Beginning of the time frame
* @param DateTimeInterface|null $to End of the time frame
*/
public function startTime(?DateTimeInterface $from, ?DateTimeInterface $to): self
{
if ($from === null && $to === null) {
$this->startTime = null;
} else {
$this->startTime = new TimeFilter($from, $to);
}

return $this;
}

/**
* Filter executions that ended in a frame.
* Both frame boundaries are optional.
* Calling this method with both null boundaries result in removing the filter.
*
* @param DateTimeInterface|null $from Beginning of the time frame
* @param DateTimeInterface|null $to End of the time frame
*/
public function endTime(?DateTimeInterface $from, ?DateTimeInterface $to): self
{
if ($from === null && $to === null) {
$this->endTime = null;
} else {
$this->endTime = new TimeFilter($from, $to);
}

return $this;
}

/**
* Sort executions.
*
Expand Down Expand Up @@ -165,6 +212,15 @@ public function limit(int $limit, int $offset): self
*/
public function getQuery(): Query
{
return new Query($this->jobNames, $this->ids, $this->statuses, $this->sortBy, $this->limit, $this->offset);
return new Query(
$this->jobNames,
$this->ids,
$this->statuses,
$this->startTime,
$this->endTime,
$this->sortBy,
$this->limit,
$this->offset
);
}
}
33 changes: 33 additions & 0 deletions src/batch/src/Storage/TimeFilter.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?php

declare(strict_types=1);

namespace Yokai\Batch\Storage;

use DateTimeInterface;
use Yokai\Batch\Exception\UnexpectedValueException;

/**
* DTO with optional time boundaries.
*/
final class TimeFilter
{
public function __construct(
private ?DateTimeInterface $from,
private ?DateTimeInterface $to,
) {
if ($from !== null && $to !== null && $from > $to) {
throw new UnexpectedValueException('TimeFilter expect "from" boundary to be lower than "to" boundary.');
}
}

public function getFrom(): ?DateTimeInterface
{
return $this->from;
}

public function getTo(): ?DateTimeInterface
{
return $this->to;
}
}
56 changes: 56 additions & 0 deletions src/batch/tests/Storage/FilesystemJobExecutionStorageTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,62 @@ public function query(): \Generator
['list', '20210910'],
],
];
yield 'Filter start time lower boundary' => [
(new QueryBuilder())
->startTime(new \DateTimeImmutable('2021-09-20T10:35:48+0200'), null),
[
['export', '20210920'],
['export', '20210922'],
['list', '20210920'],
],
];
yield 'Filter start time upper boundary' => [
(new QueryBuilder())
->startTime(null, new \DateTimeImmutable('2021-09-20T10:35:50+0200')),
[
['export', '20210920'],
['list', '20210910'],
['list', '20210915'],
],
];
yield 'Filter start time boundaries' => [
(new QueryBuilder())
->startTime(
new \DateTimeImmutable('2021-09-20T10:35:48+0200'),
new \DateTimeImmutable('2021-09-20T10:35:50+0200'),
),
[
['export', '20210920'],
],
];
yield 'Filter end time lower boundary' => [
(new QueryBuilder())
->endTime(new \DateTimeImmutable('2021-09-20T10:35:48+0200'), null),
[
['export', '20210920'],
['export', '20210922'],
['list', '20210920'],
],
];
yield 'Filter end time upper boundary' => [
(new QueryBuilder())
->endTime(null, new \DateTimeImmutable('2021-09-20T10:35:50+0200')),
[
['export', '20210920'],
['list', '20210910'],
['list', '20210915'],
],
];
yield 'Filter end time boundaries' => [
(new QueryBuilder())
->endTime(
new \DateTimeImmutable('2021-09-20T10:35:48+0200'),
new \DateTimeImmutable('2021-09-20T10:35:50+0200'),
),
[
['export', '20210920'],
],
];
}

public function testRetrieveFilePathNotFound(): void
Expand Down
Loading
Loading