timezone = new DateTimeZone($_ENV['TZ'] ?? 'America/Santiago'); } protected DateTimeZone $timezone; public function execute(Console\Input\InputInterface $input, Console\Output\OutputInterface $output): int { $this->write($output, 'Running loop...'); $this->waitNextMinute($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->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('now', $this->timezone); } $nextMinute = new DateTimeImmutable($start->format('Y-m-d H:i:00'), $this->timezone); $nextMinute = $nextMinute->add(new \DateInterval('PT1M')); $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 { $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}"); } }