1<?php 2// Icinga Web 2 X.509 Module | (c) 2018 Icinga GmbH | GPLv2 3 4namespace Icinga\Module\X509; 5 6use Cron\CronExpression; 7use Icinga\Application\Logger; 8use React\EventLoop\Factory as Loop; 9 10class Scheduler 11{ 12 protected $loop; 13 14 public function __construct() 15 { 16 $this->loop = Loop::create(); 17 } 18 19 public function add($name, $cronSchedule, callable $callback) 20 { 21 if (! CronExpression::isValidExpression($cronSchedule)) { 22 throw new \RuntimeException('Invalid cron expression'); 23 } 24 25 $now = new \DateTime(); 26 27 $expression = CronExpression::factory($cronSchedule); 28 29 if ($expression->isDue($now)) { 30 $this->loop->futureTick($callback); 31 } 32 33 $nextRuns = $expression->getMultipleRunDates(2, $now); 34 35 $interval = $nextRuns[0]->getTimestamp() - $now->getTimestamp(); 36 37 $period = $nextRuns[1]->getTimestamp() - $nextRuns[0]->getTimestamp(); 38 39 Logger::info('Scheduling job %s to run at %s.', $name, $nextRuns[0]->format('Y-m-d H:i:s')); 40 41 $loop = function () use (&$loop, $name, $callback, $period) { 42 $callback(); 43 44 $nextRun = (new \DateTime()) 45 ->add(new \DateInterval("PT{$period}S")); 46 47 Logger::info('Scheduling job %s to run at %s.', $name, $nextRun->format('Y-m-d H:i:s')); 48 49 $this->loop->addTimer($period, $loop); 50 }; 51 52 $this->loop->addTimer($interval, $loop); 53 } 54 55 public function run() 56 { 57 $this->loop->run(); 58 } 59} 60