diff --git a/CLI.Dockerfile b/CLI.Dockerfile index 87fcff6..66e5da3 100644 --- a/CLI.Dockerfile +++ b/CLI.Dockerfile @@ -1,4 +1,4 @@ -FROM php:8.2-cli +FROM php:8.4-cli ENV TZ "${TZ}" ENV APP_NAME "${APP_NAME}" @@ -6,9 +6,10 @@ ENV API_URL "${API_URL}" RUN apt-get update && apt-get install -y --no-install-recommends cron rsyslog nano && rm -r /var/lib/apt/lists/* -RUN pecl install xdebug-3.2.2 \ - && docker-php-ext-enable xdebug \ - && echo "#/bin/bash\nprintenv >> /etc/environment\ncron -f -L 11" > /root/entrypoint && chmod a+x /root/entrypoint +RUN pecl install xdebug-3.4.2 \ + && docker-php-ext-enable xdebug + +COPY --chmod=550 ./cli/entrypoint /root/entrypoint COPY ./php-errors.ini /usr/local/etc/php/conf.d/docker-php-errors.ini diff --git a/cli/composer.json b/cli/composer.json index fe8ae6b..34b7e40 100644 --- a/cli/composer.json +++ b/cli/composer.json @@ -2,6 +2,7 @@ "name": "incoviba/cli", "type": "project", "require": { + "dragonmantank/cron-expression": "^3.4", "guzzlehttp/guzzle": "^7.8", "monolog/monolog": "^3.5", "php-di/php-di": "^7.0", diff --git a/cli/crontab b/cli/crontab index 5f86424..fd4f307 100644 --- a/cli/crontab +++ b/cli/crontab @@ -7,3 +7,4 @@ 0 2 * * * /code/bin/incoviba money:uf >> /logs/commands 2>&1 0 2 * * * /code/bin/incoviba money:uf:update >> /logs/commands 2>&1 0 2 1 * * /code/bin/incoviba money:ipc >> /logs/commands 2>&1 +*/5 * * * * /code/bin/incoviba queue >> /logs/commands 2>&1 diff --git a/cli/entrypoint b/cli/entrypoint new file mode 100644 index 0000000..f3f1a0d --- /dev/null +++ b/cli/entrypoint @@ -0,0 +1,6 @@ +#/usr/bin/bash + +printenv >> /etc/environment + +#cron -f -L 11 +/code/bin/incoviba loop diff --git a/cli/resources/commands/loop.php b/cli/resources/commands/loop.php new file mode 100644 index 0000000..06cde58 --- /dev/null +++ b/cli/resources/commands/loop.php @@ -0,0 +1,2 @@ +add($app->getContainer()->get(Incoviba\Command\BaseLoop::class)); diff --git a/cli/resources/commands/queue.php b/cli/resources/commands/queue.php new file mode 100644 index 0000000..66df357 --- /dev/null +++ b/cli/resources/commands/queue.php @@ -0,0 +1,2 @@ +add($app->getContainer()->get(Incoviba\Command\Queue::class)); diff --git a/cli/setup/settings/commands.php b/cli/setup/settings/commands.php index f778b40..1cd1449 100644 --- a/cli/setup/settings/commands.php +++ b/cli/setup/settings/commands.php @@ -13,6 +13,8 @@ return [ 'ventas:cuotas:hoy' => Incoviba\Command\Ventas\Cuotas\Hoy::class, 'ventas:cuotas:pendientes' => Incoviba\Command\Ventas\Cuotas\Pendientes::class, 'ventas:cuotas:vencer' => Incoviba\Command\Ventas\Cuotas\PorVencer::class, + 'queue' => Incoviba\Command\Queue::class, + 'loop' => Incoviba\Command\BaseLoop::class ]; } ]; diff --git a/cli/src/Command/BaseLoop.php b/cli/src/Command/BaseLoop.php new file mode 100644 index 0000000..f51cc4e --- /dev/null +++ b/cli/src/Command/BaseLoop.php @@ -0,0 +1,63 @@ +writeln("Running Loop..."); + + // wait for next minute + $now = new DateTimeImmutable(); + $nextMinute = new DateTimeImmutable($now->format('Y-m-d H:i:00')); + $nextMinute->add(new \DateInterval('PT1M')); + $diff = $nextMinute->getTimestamp() - $now->getTimestamp(); + if ($diff > 0) { + $output->writeln("Waiting {$diff} seconds..."); + sleep($diff); + } + + $output->writeln('Starting loop...'); + while (true) { + $commands = $this->scheduleService->run(); + foreach ($commands as $command) { + $this->runCommand($input, $output, $command); + } + } + return self::SUCCESS; + } + 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; + } + } +} diff --git a/cli/src/Command/Queue.php b/cli/src/Command/Queue.php new file mode 100644 index 0000000..ff5b2f0 --- /dev/null +++ b/cli/src/Command/Queue.php @@ -0,0 +1,26 @@ +logger->debug("Running {$this->getName()}"); + $io = new Console\Style\SymfonyStyle($input, $output); + $io->title("Running Queue..."); + + $uri = '/api/queue/run'; + $output->writeln("GET {$uri}"); + $response = $this->client->get($uri); + $output->writeln("Response Code: {$response->getStatusCode()}"); + + return Console\Command\Command::SUCCESS; + } +} diff --git a/cli/src/Service/Schedule.php b/cli/src/Service/Schedule.php new file mode 100644 index 0000000..a04f1c3 --- /dev/null +++ b/cli/src/Service/Schedule.php @@ -0,0 +1,60 @@ +getCommandList(); + $commands = []; + foreach ($schedule as $line) { + $line = trim($line); + if ($line === '') { + continue; + } + $data = $this->parseCommandLine($line); + if ($this->processSchedule($now, $data)) { + $commands[] = $data['command']; + } + } + return $commands; + } + + protected function getCommandList(): array + { + if (!file_exists($this->filename)) { + return []; + } + return explode("\n", file_get_contents($this->filename)); + } + protected function parseCommandLine(string $line): array + { + $regex = '/^(?(\d{1,2}|\*|\*\/\d{1,2})?) (?(\d{1,2}|\*|\*\/\d{1,2})?) (?(\d{1,2}|\*|\*\/\d{1,2})?) (?(\d{1,2}|\*|\*\/\d{1,2})?) (?(\d{1,2}|\*|\*\/\d{1,2})?) (?.*)$/'; + preg_match_all($regex, $line, $matches); + + return [ + 'minutes' => $matches['minutes'][0], + 'hours' => $matches['hours'][0], + 'day_month' => $matches['day_month'][0], + 'month' => $matches['month'][0], + 'day_week' => $matches['day_week'][0], + 'command' => trim(str_replace(['/code/bin/incoviba', '>> /logs/commands 2>&1'], '', $matches['command'][0])), + ]; + } + protected function processSchedule(DateTimeInterface $now, array $schedule): bool + { + $cronLine = "{$schedule['minutes']} {$schedule['hours']} {$schedule['day_month']} {$schedule['month']} {$schedule['day_week']}"; + $cron = new CronExpression($cronLine); + return $cron->isDue($now); + } +} diff --git a/docker-compose.yml b/docker-compose.yml index 8223f8e..db7ed73 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -84,6 +84,7 @@ services: volumes: - ${CLI_PATH:-.}:/code - ./logs/cli:/logs + - ${CLI_PATH:-.}/crontab:/var/spool/cron/crontabs/root volumes: dbdata: {}