diff --git a/composer.json b/composer.json index c3d533b..a9fd684 100644 --- a/composer.json +++ b/composer.json @@ -16,7 +16,8 @@ "guzzlehttp/guzzle": "~6.0", "nannehuiges/jsend": "2.1.*", "monolog/monolog": "1.*", - "php-di/php-di": "^6.0" + "php-di/php-di": "^6.0", + "dragonmantank/cron-expression": "^2.3" }, "require": { "php": "^7.1" @@ -25,7 +26,8 @@ "guzzlehttp/guzzle": "~6.0 Used for rest api and other http communication", "nannehuiges/jsend": "2.1.* Used for rest api", "php-di/php-di": "^6.* Used for DI integration", - "ext-zmq": "when using ZMQ subpackage" + "ext-zmq": "when using ZMQ subpackage", + "dragonmantank/cron-expression": "^2.3 when using cron staff" }, "autoload": { "psr-4": { diff --git a/src/SAREhub/Commons/Time/CronTask.php b/src/SAREhub/Commons/Time/CronTask.php new file mode 100644 index 0000000..410679e --- /dev/null +++ b/src/SAREhub/Commons/Time/CronTask.php @@ -0,0 +1,78 @@ +cron = $cron; + $this->timeProvider = $timeProvider; + $this->taskToRun = $taskToRun; + $this->logger = new NullLogger(); + $this->updateNextRunDate(); + } + + public function __invoke() + { + $now = $this->timeProvider->now(); + $this->logger->debug("Invoked, current nextRunDate: {nextRunDate}", [ + "nextRunDate" => $this->nextRunDate->format(\DateTime::ATOM) + ]); + if ($now >= $this->nextRunDate->getTimestamp()) { + $this->logger->notice("Run task, current nextRunDate: {nextRunDate}", [ + "nextRunDate" => $this->nextRunDate->format(\DateTime::ATOM) + ]); + $this->taskToRun->run(); + $this->updateNextRunDate(); + $this->logger->notice("Task ended, current nextRunDate: {nextRunDate}", [ + "nextRunDate" => $this->nextRunDate->format(\DateTime::ATOM) + ]); + } + } + + private function updateNextRunDate(): void + { + $this->nextRunDate = $this->cron->getNextRunDate("@" . $this->timeProvider->now()); + } + + public function setLogger(LoggerInterface $logger) + { + $this->logger = $logger; + } +} diff --git a/src/SAREhub/Commons/Time/PeriodicTaskDefinition.php b/src/SAREhub/Commons/Time/PeriodicTaskDefinition.php new file mode 100644 index 0000000..b1a089e --- /dev/null +++ b/src/SAREhub/Commons/Time/PeriodicTaskDefinition.php @@ -0,0 +1,45 @@ +id = $id; + $this->interval = $interval; + $this->callback = $callback; + } + + public function getId(): string + { + return $this->id; + } + + public function getInterval(): int + { + return $this->interval; + } + + public function getCallback(): callable + { + return $this->callback; + } +} diff --git a/src/SAREhub/Commons/Time/TimerServicePeriodicTasksRegisterTask.php b/src/SAREhub/Commons/Time/TimerServicePeriodicTasksRegisterTask.php new file mode 100644 index 0000000..244be06 --- /dev/null +++ b/src/SAREhub/Commons/Time/TimerServicePeriodicTasksRegisterTask.php @@ -0,0 +1,38 @@ +service = $service; + $this->taskDefs = $taskDefs; + } + + public function run() + { + foreach ($this->taskDefs as $taskDef) { + $this->service->addPeriodicTask( + $taskDef->getId(), + $taskDef->getInterval(), + $taskDef->getCallback() + ); + } + } +} diff --git a/tests/SAREhub/Commons/Time/CronTaskTest.php b/tests/SAREhub/Commons/Time/CronTaskTest.php new file mode 100644 index 0000000..d2ca057 --- /dev/null +++ b/tests/SAREhub/Commons/Time/CronTaskTest.php @@ -0,0 +1,79 @@ +cron = CronExpression::factory("@hourly"); + $this->timeProvider = new TimeProvider(); + $this->timeProvider->freezeTime(); + $this->taskToRun = Mockery::mock(Task::class); + $this->task = new CronTask($this->cron, $this->timeProvider, $this->taskToRun); + } + + public function testRunWhenNowIsNextRunDate() + { + $currentNextRunDate = $this->cron->getNextRunDate("@" . $this->timeProvider->now()); + $this->timeProvider->freezeTime($currentNextRunDate->getTimestamp()); + + $this->taskToRun->expects("run")->with(); + + ($this->task)(); + } + + public function testRunWhenNowIsNotNextRunDate() + { + $currentNextRunDate = $this->cron->getNextRunDate("@" . $this->timeProvider->now()); + $this->timeProvider->freezeTime($currentNextRunDate->getTimestamp() - 1); + + $this->taskToRun->expects("run")->never(); + + ($this->task)(); + } + + public function testRunWhenAfterRunDate() + { + $currentNextRunDate = $this->cron->getNextRunDate("@" . $this->timeProvider->now()); + $this->timeProvider->freezeTime($currentNextRunDate->getTimestamp() + 1); + $this->taskToRun->expects("run")->once(); + ($this->task)(); + + $currentNextRunDate = $this->cron->getNextRunDate("@" . $this->timeProvider->now()); + $this->timeProvider->freezeTime($currentNextRunDate->getTimestamp() - 1); + $this->taskToRun->expects("run")->never(); + + ($this->task)(); + } +} diff --git a/tests/SAREhub/Commons/Time/TimerServicePeriodicTasksRegisterTaskTest.php b/tests/SAREhub/Commons/Time/TimerServicePeriodicTasksRegisterTaskTest.php new file mode 100644 index 0000000..14832ee --- /dev/null +++ b/tests/SAREhub/Commons/Time/TimerServicePeriodicTasksRegisterTaskTest.php @@ -0,0 +1,30 @@ +expects("addPeriodicTask")->with($id, $interval, $callback); + + $task->run(); + } +}