Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
27 changes: 21 additions & 6 deletions src/Probe/Probe.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
namespace SchedulerBundle\Probe;

use DateTimeImmutable;
use Psr\Clock\ClockInterface;
use SchedulerBundle\SchedulerInterface;
use SchedulerBundle\Task\TaskInterface;
use SchedulerBundle\Worker\WorkerInterface;
Expand All @@ -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,
) {
}

Expand All @@ -26,29 +28,42 @@ 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();
}

/**
* {@inheritdoc}
*/
public function getFailedTasks(): int
{
return $this->worker->getFailedTasks()->count();
$failedTasks = $this->worker->getFailedTasks();

return $failedTasks->count();
}

/**
* {@inheritdoc}
*/
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();
}
}
15 changes: 12 additions & 3 deletions src/Scheduler.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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');
Expand Down Expand Up @@ -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);
Expand Down
35 changes: 27 additions & 8 deletions src/Worker/Worker.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

use DateTimeImmutable;
use Exception;
use Psr\Clock\ClockInterface;
use Psr\Log\LoggerInterface;
use Psr\Log\NullLogger;
use SchedulerBundle\Event\TaskExecutedEvent;
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -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);

Expand Down Expand Up @@ -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
Expand All @@ -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()
;
}
}