loop = Loop::create(); } public function add($name, $cronSchedule, callable $callback) { if (! CronExpression::isValidExpression($cronSchedule)) { throw new \RuntimeException('Invalid cron expression'); } $now = new \DateTime(); $expression = new CronExpression($cronSchedule); if ($expression->isDue($now)) { $this->loop->futureTick($callback); } $nextRuns = $expression->getMultipleRunDates(2, $now); $interval = $nextRuns[0]->getTimestamp() - $now->getTimestamp(); $period = $nextRuns[1]->getTimestamp() - $nextRuns[0]->getTimestamp(); Logger::info('Scheduling job %s to run at %s.', $name, $nextRuns[0]->format('Y-m-d H:i:s')); $loop = function () use (&$loop, $name, $callback, $period) { $callback(); $nextRun = (new \DateTime()) ->add(new \DateInterval("PT{$period}S")); Logger::info('Scheduling job %s to run at %s.', $name, $nextRun->format('Y-m-d H:i:s')); $this->loop->addTimer($period, $loop); }; $this->loop->addTimer($interval, $loop); } public function run() { $this->loop->run(); } }