From f0b26e9c7b6ed4a1a60e21c60786034ff7103d7c Mon Sep 17 00:00:00 2001 From: Guillaume Loulier Date: Fri, 25 Nov 2022 17:17:18 +0100 Subject: [PATCH] feat(core): ClockInterface support started --- composer.json | 1 + src/Probe/Probe.php | 27 +++++++++++++++++++++------ src/Scheduler.php | 15 ++++++++++++--- src/Worker/Worker.php | 35 +++++++++++++++++++++++++++-------- 4 files changed, 61 insertions(+), 17 deletions(-) diff --git a/composer.json b/composer.json index 412ee504..ce1956f4 100644 --- a/composer.json +++ b/composer.json @@ -143,6 +143,7 @@ "phpstan/phpstan-symfony": "^1.2.19", "phpunit/phpunit": "^9.5.26", "psr/cache": "^1.0 || ^2.0 || ^3.0", + "psr/clock": "^1.0", "rector/rector": "0.15.10", "symfony/cache": "^5.4 || ^6.0", "symfony/dependency-injection": "^5.4 || ^6.0", diff --git a/src/Probe/Probe.php b/src/Probe/Probe.php index d266074f..cf1371c4 100644 --- a/src/Probe/Probe.php +++ b/src/Probe/Probe.php @@ -5,6 +5,7 @@ namespace SchedulerBundle\Probe; use DateTimeImmutable; +use Psr\Clock\ClockInterface; use SchedulerBundle\SchedulerInterface; use SchedulerBundle\Task\TaskInterface; use SchedulerBundle\Worker\WorkerInterface; @@ -17,7 +18,8 @@ final class Probe implements ProbeInterface { public function __construct( private SchedulerInterface $scheduler, - private WorkerInterface $worker + private WorkerInterface $worker, + private ?ClockInterface $clock = null, ) { } @@ -26,14 +28,23 @@ public function __construct( */ public function getExecutedTasks(): int { - return $this->scheduler->getTasks()->filter(filter: static function (TaskInterface $task): bool { + $tasks = $this->scheduler->getTasks(); + + $filteredTasks = $tasks->filter(filter: function (TaskInterface $task): bool { $lastExecutionDate = $task->getLastExecution(); if (!$lastExecutionDate instanceof DateTimeImmutable) { return false; } - return $lastExecutionDate->format(format: 'Y-m-d h:i') === (new DateTimeImmutable())->format(format: 'Y-m-d h:i'); - })->count(); + $currentDate = $this->clock instanceof ClockInterface + ? $this->clock->now()->format(format: 'Y-m-d h:i') + : (new DateTimeImmutable())->format(format: 'Y-m-d h:i') + ; + + return $lastExecutionDate->format(format: 'Y-m-d h:i') === $currentDate; + }); + + return $filteredTasks->count(); } /** @@ -41,7 +52,9 @@ public function getExecutedTasks(): int */ public function getFailedTasks(): int { - return $this->worker->getFailedTasks()->count(); + $failedTasks = $this->worker->getFailedTasks(); + + return $failedTasks->count(); } /** @@ -49,6 +62,8 @@ public function getFailedTasks(): int */ public function getScheduledTasks(): int { - return $this->scheduler->getTasks()->filter(filter: static fn (TaskInterface $task): bool => null !== $task->getScheduledAt())->count(); + $tasks = $this->scheduler->getTasks(); + + return $tasks->filter(filter: static fn (TaskInterface $task): bool => null !== $task->getScheduledAt())->count(); } } diff --git a/src/Scheduler.php b/src/Scheduler.php index c021e2d0..f8084746 100644 --- a/src/Scheduler.php +++ b/src/Scheduler.php @@ -10,6 +10,7 @@ use DateTimeImmutable; use DateTimeZone; use Exception; +use Psr\Clock\ClockInterface; use SchedulerBundle\Event\TaskExecutingEvent; use SchedulerBundle\Exception\InvalidArgumentException; use SchedulerBundle\Exception\TransportException; @@ -56,10 +57,14 @@ public function __construct( private TransportInterface $transport, private SchedulerMiddlewareStack $middlewareStack, private EventDispatcherInterface $eventDispatcher, - private ?MessageBusInterface $bus = null + private ?MessageBusInterface $bus = null, + private ?ClockInterface $clock = null ) { $this->timezone = new DateTimeZone(timezone: $timezone); - $this->initializationDate = new DateTimeImmutable(datetime: 'now', timezone: $this->timezone); + $this->initializationDate = $clock instanceof ClockInterface + ? $clock->now()->setTimezone(timezone: $this->timezone) + : new DateTimeImmutable(timezone: $this->timezone) + ; $this->minSynchronizationDelay = new DateInterval(duration: 'PT1S'); $this->maxSynchronizationDelay = new DateInterval(duration: 'P1D'); @@ -311,7 +316,11 @@ public function getPoolConfiguration(): SchedulerConfiguration */ private function getSynchronizedCurrentDate(): DateTimeImmutable { - $currentDate = new DateTimeImmutable(datetime: 'now', timezone: $this->timezone); + $currentDate = $this->clock instanceof ClockInterface + ? $this->clock->now()->setTimezone(timezone: $this->timezone) + : new DateTimeImmutable(datetime: 'now', timezone: $this->timezone) + ; + $currentDateIntervalWithInitialization = $this->initializationDate->diff(targetObject: $currentDate); $currentDateWithMinInterval = $currentDate->add(interval: $this->minSynchronizationDelay); diff --git a/src/Worker/Worker.php b/src/Worker/Worker.php index 06b64bac..09f4e026 100644 --- a/src/Worker/Worker.php +++ b/src/Worker/Worker.php @@ -6,6 +6,7 @@ use DateTimeImmutable; use Exception; +use Psr\Clock\ClockInterface; use Psr\Log\LoggerInterface; use Psr\Log\NullLogger; use SchedulerBundle\Event\TaskExecutedEvent; @@ -56,7 +57,8 @@ public function __construct( private WorkerMiddlewareStack $middlewareStack, private EventDispatcherInterface $eventDispatcher, private LockFactory $lockFactory, - ?LoggerInterface $logger = null + ?LoggerInterface $logger = null, + private ?ClockInterface $clock = null ) { $this->configuration = WorkerConfiguration::create(); $this->logger = $logger ?? new NullLogger(); @@ -292,15 +294,15 @@ protected function handleTask(TaskInterface $task, TaskListInterface $taskList): $this->configuration->setCurrentlyExecutedTask(task: $task); $this->eventDispatcher->dispatch(event: new WorkerRunningEvent(worker: $this)); $this->eventDispatcher->dispatch(event: new TaskExecutingEvent(task: $task, worker: $this, currentTasks: $taskList)); - $task->setArrivalTime(dateTimeImmutable: new DateTimeImmutable()); - $task->setExecutionStartTime(dateTimeImmutable: new DateTimeImmutable()); + $task->setArrivalTime(dateTimeImmutable: $this->getCurrentDateAsDatetimeImmutable()); + $task->setExecutionStartTime(dateTimeImmutable: $this->getCurrentDateAsDatetimeImmutable()); $this->taskExecutionTracker->startTracking(task: $task); $output = $runner->run(task: $task, worker: $this); $this->taskExecutionTracker->endTracking(task: $task); - $task->setExecutionEndTime(dateTimeImmutable: new DateTimeImmutable()); - $task->setLastExecution(dateTimeImmutable: new DateTimeImmutable()); + $task->setExecutionEndTime(dateTimeImmutable: $this->getCurrentDateAsDatetimeImmutable()); + $task->setLastExecution(dateTimeImmutable: $this->getCurrentDateAsDatetimeImmutable()); $this->defineTaskExecutionState(task: $task, output: $output); @@ -364,10 +366,19 @@ private function checkTaskState(TaskInterface $task): bool */ private function getSleepDuration(): int { - $nextMinute = new DateTimeImmutable(datetime: '+ 1 minute', timezone: $this->scheduler->getTimezone()); - $updatedNextExecutionDate = $nextMinute->setTime(hour: (int) $nextMinute->format('H'), minute: (int) $nextMinute->format('i')); + $schedulerTimezone = $this->scheduler->getTimezone(); - return (new DateTimeImmutable(datetime: 'now', timezone: $this->scheduler->getTimezone()))->diff(targetObject: $updatedNextExecutionDate)->s + $this->configuration->getSleepDurationDelay(); + $currentDatetimeMinusOneMinute = $this->clock instanceof ClockInterface + ? $this->clock->now()->setTimezone(timezone: $schedulerTimezone)->modify('-1 minute') + : new DateTimeImmutable(datetime: '+ 1 minute', timezone: $schedulerTimezone) + ; + + $updatedNextExecutionDate = $currentDatetimeMinusOneMinute->setTime( + hour: (int) $currentDatetimeMinusOneMinute->format('H'), + minute: (int) $currentDatetimeMinusOneMinute->format('i') + ); + + return (new DateTimeImmutable(datetime: 'now', timezone: $schedulerTimezone))->diff(targetObject: $updatedNextExecutionDate)->s + $this->configuration->getSleepDurationDelay(); } private function defineTaskExecutionState(TaskInterface $task, Output $output): void @@ -378,4 +389,12 @@ private function defineTaskExecutionState(TaskInterface $task, Output $output): $task->setExecutionState(executionState: Output::ERROR === $output->getType() ? TaskInterface::ERRORED : TaskInterface::SUCCEED); } + + private function getCurrentDateAsDatetimeImmutable(): DateTimeImmutable + { + return $this->clock instanceof ClockInterface + ? $this->clock->now() + : new DateTimeImmutable() + ; + } }