write($output, 'Running loop...'); $this->waitNextTimeout($output); $this->write($output, 'Starting loop...'); while (true) { $commands = $this->scheduleService->getPending(); $start = new DateTimeImmutable('now', $this->timezone); foreach ($commands as $command) { $this->runCommand($input, $output, $command); } $this->waitNextTimeout($output, $start); } return self::SUCCESS; } protected function waitNextTimeout(Console\Output\OutputInterface $output, ?DateTimeInterface $start = null): void { // wait for next minute if ($start === null) { $start = new DateTimeImmutable('now', $this->timezone); } $nextTimeout = new DateTimeImmutable($start->format('Y-m-d H:i:00'), $this->timezone); $nextTimeout = $nextTimeout->add(new \DateInterval("PT{$this->timeout}S")); $diff = $nextTimeout->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); return self::FAILURE; } $cmd = new Console\Input\ArrayInput([ 'command' => $commandName ]); try { $this->logger->notice("Running commnand: {$commandName}"); 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('now', $this->timezone); $output->writeln("[{$now->format('Y-m-d H:i:s e')}] {$message}"); } }