write($output, 'Running loop...'); $this->waitNextMinute($output); $this->write($output, 'Starting loop...'); while (true) { $commands = $this->scheduleService->getPending(); $start = new DateTimeImmutable(); foreach ($commands as $command) { $this->runCommand($input, $output, $command); } $this->waitNextMinute($output, $start); } return self::SUCCESS; } protected function waitNextMinute(Console\Output\OutputInterface $output, ?DateTimeInterface $start = null): void { // wait for next minute if ($start === null) { $start = new DateTimeImmutable(); } $nextMinute = new DateTimeImmutable($start->format('Y-m-d H:i:00')); $nextMinute = $nextMinute->add(new \DateInterval('PT1M')); $this->logger->debug('Wait', [ 'start' => $start->format('Y-m-d H:i:s.u'), 'nextMinute' => $nextMinute->format('Y-m-d H:i:s.u'), ]); $diff = $nextMinute->getTimestamp() - $start->getTimestamp(); if ($diff > 0) { $this->logger->debug("Waiting {$diff} seconds..."); sleep($diff); } } protected function runCommand(Console\Input\InputInterface $input, Console\Output\OutputInterface $output, string $commandName): int { try { $command = $this->getApplication()->find($commandName); } catch (Console\Exception\CommandNotFoundException $exception) { $this->logger->warning($exception); } $cmd = new Console\Input\ArrayInput([ 'command' => $commandName ]); try { return $this->getApplication()->doRun($cmd, $output); } catch (Throwable $exception) { $this->logger->warning($exception); return self::FAILURE; } } protected function write(Console\Output\OutputInterface $output, string $message): void { $now = new DateTimeImmutable(); $output->writeln("[{$now->format('Y-m-d H:i:s e')}] {$message}"); } }