Manejo de trabajos en cli por php en vez de cron
This commit is contained in:
@ -1,4 +1,4 @@
|
|||||||
FROM php:8.2-cli
|
FROM php:8.4-cli
|
||||||
|
|
||||||
ENV TZ "${TZ}"
|
ENV TZ "${TZ}"
|
||||||
ENV APP_NAME "${APP_NAME}"
|
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 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 \
|
RUN pecl install xdebug-3.4.2 \
|
||||||
&& docker-php-ext-enable xdebug \
|
&& docker-php-ext-enable xdebug
|
||||||
&& echo "#/bin/bash\nprintenv >> /etc/environment\ncron -f -L 11" > /root/entrypoint && chmod a+x /root/entrypoint
|
|
||||||
|
COPY --chmod=550 ./cli/entrypoint /root/entrypoint
|
||||||
|
|
||||||
COPY ./php-errors.ini /usr/local/etc/php/conf.d/docker-php-errors.ini
|
COPY ./php-errors.ini /usr/local/etc/php/conf.d/docker-php-errors.ini
|
||||||
|
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
"name": "incoviba/cli",
|
"name": "incoviba/cli",
|
||||||
"type": "project",
|
"type": "project",
|
||||||
"require": {
|
"require": {
|
||||||
|
"dragonmantank/cron-expression": "^3.4",
|
||||||
"guzzlehttp/guzzle": "^7.8",
|
"guzzlehttp/guzzle": "^7.8",
|
||||||
"monolog/monolog": "^3.5",
|
"monolog/monolog": "^3.5",
|
||||||
"php-di/php-di": "^7.0",
|
"php-di/php-di": "^7.0",
|
||||||
|
@ -7,3 +7,4 @@
|
|||||||
0 2 * * * /code/bin/incoviba money:uf >> /logs/commands 2>&1
|
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 * * * /code/bin/incoviba money:uf:update >> /logs/commands 2>&1
|
||||||
0 2 1 * * /code/bin/incoviba money:ipc >> /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
|
||||||
|
6
cli/entrypoint
Normal file
6
cli/entrypoint
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
#/usr/bin/bash
|
||||||
|
|
||||||
|
printenv >> /etc/environment
|
||||||
|
|
||||||
|
#cron -f -L 11
|
||||||
|
/code/bin/incoviba loop
|
2
cli/resources/commands/loop.php
Normal file
2
cli/resources/commands/loop.php
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
<?php
|
||||||
|
$app->add($app->getContainer()->get(Incoviba\Command\BaseLoop::class));
|
2
cli/resources/commands/queue.php
Normal file
2
cli/resources/commands/queue.php
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
<?php
|
||||||
|
$app->add($app->getContainer()->get(Incoviba\Command\Queue::class));
|
@ -13,6 +13,8 @@ return [
|
|||||||
'ventas:cuotas:hoy' => Incoviba\Command\Ventas\Cuotas\Hoy::class,
|
'ventas:cuotas:hoy' => Incoviba\Command\Ventas\Cuotas\Hoy::class,
|
||||||
'ventas:cuotas:pendientes' => Incoviba\Command\Ventas\Cuotas\Pendientes::class,
|
'ventas:cuotas:pendientes' => Incoviba\Command\Ventas\Cuotas\Pendientes::class,
|
||||||
'ventas:cuotas:vencer' => Incoviba\Command\Ventas\Cuotas\PorVencer::class,
|
'ventas:cuotas:vencer' => Incoviba\Command\Ventas\Cuotas\PorVencer::class,
|
||||||
|
'queue' => Incoviba\Command\Queue::class,
|
||||||
|
'loop' => Incoviba\Command\BaseLoop::class
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
63
cli/src/Command/BaseLoop.php
Normal file
63
cli/src/Command/BaseLoop.php
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
<?php
|
||||||
|
namespace Incoviba\Command;
|
||||||
|
|
||||||
|
use Throwable;
|
||||||
|
use DateTimeInterface;
|
||||||
|
use DateTimeImmutable;
|
||||||
|
use Psr\Log\LoggerInterface;
|
||||||
|
use Symfony\Component\Console;
|
||||||
|
use Incoviba\Service\Schedule;
|
||||||
|
|
||||||
|
#[Console\Attribute\AsCommand(
|
||||||
|
name: 'loop',
|
||||||
|
description: 'Run base loop',
|
||||||
|
)]
|
||||||
|
class BaseLoop extends Console\Command\Command
|
||||||
|
{
|
||||||
|
public function __construct(protected LoggerInterface $logger, protected Schedule $scheduleService, ?string $name = null)
|
||||||
|
{
|
||||||
|
parent::__construct($name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function execute(Console\Input\InputInterface $input, Console\Output\OutputInterface $output): int
|
||||||
|
{
|
||||||
|
$output->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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
26
cli/src/Command/Queue.php
Normal file
26
cli/src/Command/Queue.php
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
<?php
|
||||||
|
namespace Incoviba\Command;
|
||||||
|
|
||||||
|
use Symfony\Component\Console;
|
||||||
|
use Incoviba\Common\Alias\Command;
|
||||||
|
|
||||||
|
#[Console\Attribute\AsCommand(
|
||||||
|
name: 'queue',
|
||||||
|
description: 'Run queue'
|
||||||
|
)]
|
||||||
|
class Queue extends Command
|
||||||
|
{
|
||||||
|
public function execute(Console\Input\InputInterface $input, Console\Output\OutputInterface $output): int
|
||||||
|
{
|
||||||
|
$this->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;
|
||||||
|
}
|
||||||
|
}
|
60
cli/src/Service/Schedule.php
Normal file
60
cli/src/Service/Schedule.php
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
<?php
|
||||||
|
namespace Incoviba\Service;
|
||||||
|
|
||||||
|
use Cron\CronExpression;
|
||||||
|
use DateTimeInterface;
|
||||||
|
use DateTimeImmutable;
|
||||||
|
use Psr\Log\LoggerInterface;
|
||||||
|
|
||||||
|
class Schedule
|
||||||
|
{
|
||||||
|
public function __construct(protected LoggerInterface $logger) {}
|
||||||
|
|
||||||
|
protected string $filename = '/var/spool/cron/crontabs/root';
|
||||||
|
|
||||||
|
public function run(): array
|
||||||
|
{
|
||||||
|
$now = new DateTimeImmutable();
|
||||||
|
$schedule = $this->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 = '/^(?<minutes>(\d{1,2}|\*|\*\/\d{1,2})?) (?<hours>(\d{1,2}|\*|\*\/\d{1,2})?) (?<day_month>(\d{1,2}|\*|\*\/\d{1,2})?) (?<month>(\d{1,2}|\*|\*\/\d{1,2})?) (?<day_week>(\d{1,2}|\*|\*\/\d{1,2})?) (?<command>.*)$/';
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
@ -84,6 +84,7 @@ services:
|
|||||||
volumes:
|
volumes:
|
||||||
- ${CLI_PATH:-.}:/code
|
- ${CLI_PATH:-.}:/code
|
||||||
- ./logs/cli:/logs
|
- ./logs/cli:/logs
|
||||||
|
- ${CLI_PATH:-.}/crontab:/var/spool/cron/crontabs/root
|
||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
dbdata: {}
|
dbdata: {}
|
||||||
|
Reference in New Issue
Block a user