|
|
@@ -3,13 +3,14 @@
|
|
|
namespace App\Commands;
|
|
|
|
|
|
use App\Service\Cron\CronJobInterface;
|
|
|
-use App\Service\Cron\IO\CommandLineIO;
|
|
|
+use App\Service\Cron\UI\ConsoleUI;
|
|
|
use App\Service\ServiceIterator\CronjobIterator;
|
|
|
use Psr\Log\LoggerInterface;
|
|
|
use RuntimeException;
|
|
|
use Symfony\Component\Console\Attribute\AsCommand;
|
|
|
use Symfony\Component\Console\Command\Command;
|
|
|
use Symfony\Component\Console\Command\LockableTrait;
|
|
|
+use Symfony\Component\Console\Helper\FormatterHelper;
|
|
|
use Symfony\Component\Console\Helper\ProgressBar;
|
|
|
use Symfony\Component\Console\Input\InputArgument;
|
|
|
use Symfony\Component\Console\Input\InputInterface;
|
|
|
@@ -17,6 +18,11 @@ use Symfony\Component\Console\Input\InputOption;
|
|
|
use Symfony\Component\Console\Output\OutputInterface;
|
|
|
use Symfony\Contracts\Service\Attribute\Required;
|
|
|
|
|
|
+/**
|
|
|
+ * CLI Command to run the cron-jobs
|
|
|
+ *
|
|
|
+ * @see ~/src/Service/Cron/Readme.md
|
|
|
+ */
|
|
|
#[AsCommand(
|
|
|
name: 'ot:cron',
|
|
|
description: 'Executes cron jobs'
|
|
|
@@ -27,34 +33,40 @@ class CronCommand extends Command
|
|
|
|
|
|
private const ACTION_LIST = 'list';
|
|
|
private const ACTION_RUN = 'run';
|
|
|
- private const ACTION_RUN_ALL = 'run-all';
|
|
|
- private const ACTIONS = [self::ACTION_LIST, self::ACTION_RUN, self::ACTION_RUN_ALL];
|
|
|
+ private const ACTION_RUN_ALL = 'all';
|
|
|
+
|
|
|
+ private const ACTIONS = [
|
|
|
+ self::ACTION_LIST => 'List registered jobs',
|
|
|
+ self::ACTION_RUN => 'Run the given job',
|
|
|
+ self::ACTION_RUN_ALL => 'Successively run all the registered cron jobs'
|
|
|
+ ];
|
|
|
|
|
|
- private InputInterface $input;
|
|
|
private OutputInterface $output;
|
|
|
- private bool $silent;
|
|
|
- private ProgressBar $progressBar;
|
|
|
private LoggerInterface $logger;
|
|
|
private CronjobIterator $cronjobIterator;
|
|
|
|
|
|
#[Required]
|
|
|
- public function setLoggerInterface(LoggerInterface $logger): void
|
|
|
- {
|
|
|
- $this->logger = $logger;
|
|
|
- }
|
|
|
-
|
|
|
+ public function setLoggerInterface(LoggerInterface $logger): void { $this->logger = $logger; }
|
|
|
#[Required]
|
|
|
- public function setCronjobIterator(CronjobIterator $cronjobIterator): void
|
|
|
- {
|
|
|
- $this->cronjobIterator = $cronjobIterator;
|
|
|
- }
|
|
|
+ public function setCronjobIterator(CronjobIterator $cronjobIterator): void { $this->cronjobIterator = $cronjobIterator; }
|
|
|
|
|
|
+ /**
|
|
|
+ * Configures the command
|
|
|
+ */
|
|
|
protected function configure(): void
|
|
|
{
|
|
|
$this->addArgument(
|
|
|
'action',
|
|
|
InputArgument::REQUIRED,
|
|
|
- 'Action to execute among : ' . implode(', ', self::ACTIONS)
|
|
|
+ 'Action to execute among : ' .
|
|
|
+ implode(
|
|
|
+ ', ',
|
|
|
+ array_map(
|
|
|
+ static function ($v, $k) { return "'" . $k . "' (" . $v . ")"; },
|
|
|
+ self::ACTIONS,
|
|
|
+ array_keys(self::ACTIONS)
|
|
|
+ )
|
|
|
+ )
|
|
|
);
|
|
|
$this->addArgument(
|
|
|
'jobs',
|
|
|
@@ -65,39 +77,37 @@ class CronCommand extends Command
|
|
|
'preview',
|
|
|
'p',
|
|
|
InputOption::VALUE_NONE,
|
|
|
- 'Only preview the operations instead of executing it'
|
|
|
+ 'Only preview the operations instead of executing them'
|
|
|
);
|
|
|
}
|
|
|
|
|
|
- protected function updateProgression(int $i, int $total): void
|
|
|
- {
|
|
|
- if (!$this->progressBar->getMaxSteps() !== $total) {
|
|
|
- $this->progressBar->setMaxSteps($total);
|
|
|
- }
|
|
|
- $this->progressBar->setProgress($i);
|
|
|
- }
|
|
|
-
|
|
|
+ /**
|
|
|
+ * Executes the command
|
|
|
+ *
|
|
|
+ * @param InputInterface $input
|
|
|
+ * @param OutputInterface $output
|
|
|
+ * @return int
|
|
|
+ */
|
|
|
final protected function execute(InputInterface $input, OutputInterface $output): int
|
|
|
{
|
|
|
- $this->input = $input;
|
|
|
$this->output = $output;
|
|
|
+ $formatter = $this->getHelper('formatter');
|
|
|
|
|
|
$action = $input->getArgument('action');
|
|
|
$jobNames = $input->getArgument('jobs');
|
|
|
$preview = $input->getOption('preview');
|
|
|
+ $jobs = [];
|
|
|
|
|
|
- if (!in_array($action, self::ACTIONS, true)) {
|
|
|
- $this->output->writeln('Error: unrecognized action');
|
|
|
+ if (!array_key_exists($action, self::ACTIONS)) {
|
|
|
+ $this->output->writeln($formatter->formatBlock('Error: unrecognized action', 'error'));
|
|
|
return Command::INVALID;
|
|
|
}
|
|
|
|
|
|
- if ($action === 'list') {
|
|
|
+ if ($action === self::ACTION_LIST) {
|
|
|
$this->listJobs();
|
|
|
return Command::SUCCESS;
|
|
|
}
|
|
|
|
|
|
- $jobs = [];
|
|
|
-
|
|
|
if ($action === self::ACTION_RUN_ALL) {
|
|
|
$jobs = $this->cronjobIterator->getAll();
|
|
|
}
|
|
|
@@ -114,6 +124,8 @@ class CronCommand extends Command
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ $this->logger->info('CronCommand will ' . ($preview ? 'preview' : 'execute') . ' ' . implode(', ', $jobs));
|
|
|
+
|
|
|
foreach ($jobs as $job) {
|
|
|
$this->runJob($job, $preview);
|
|
|
}
|
|
|
@@ -121,34 +133,52 @@ class CronCommand extends Command
|
|
|
return Command::SUCCESS;
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * List all available cron jobs
|
|
|
+ */
|
|
|
private function listJobs(): void {
|
|
|
$availableJobs = $this->cronjobIterator->getAll();
|
|
|
+
|
|
|
if (empty($availableJobs)) {
|
|
|
$this->output->writeln('No cronjob found');
|
|
|
- } else {
|
|
|
- $this->output->writeln('Available cron jobs : ');
|
|
|
- foreach ($this->cronjobIterator->getAll() as $job) {
|
|
|
- $this->output->writeln('* ' . $job->name());
|
|
|
- }
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ $this->output->writeln('Available cron jobs : ');
|
|
|
+ foreach ($this->cronjobIterator->getAll() as $job) {
|
|
|
+ $this->output->writeln('* ' . $job->name());
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * Run one Cronjob
|
|
|
+ *
|
|
|
+ * @param CronJobInterface $job
|
|
|
+ * @param bool $preview
|
|
|
+ * @return int
|
|
|
+ */
|
|
|
private function runJob(CronjobInterface $job, bool $preview = false): int
|
|
|
{
|
|
|
+ $formatter = $this->getHelper('formatter');
|
|
|
+
|
|
|
if (!$this->lock($job->name())) {
|
|
|
- $this->output->writeln('The command ' . $job->name() . ' is already running in another process. Abort.');
|
|
|
- return Command::SUCCESS;
|
|
|
+ $msg = 'The command ' . $job->name() . ' is already running in another process. Abort.';
|
|
|
+ $this->output->writeln($formatter->formatBlock($msg, 'error'));
|
|
|
+ $this->logger->error($msg);
|
|
|
+ return Command::FAILURE;
|
|
|
}
|
|
|
|
|
|
$t0 = microtime(true);
|
|
|
|
|
|
- $this->output->writeln("Started : " . $job->name());
|
|
|
+ $this->output->writeln(
|
|
|
+ $formatter->formatSection($job->name(),"Start")
|
|
|
+ );
|
|
|
if ($preview) {
|
|
|
$this->output->writeln('PREVIEW MODE');
|
|
|
}
|
|
|
|
|
|
- $io = new CommandLineIO($job->name(), $this->logger, $this->output);
|
|
|
- $job->setIO($io);
|
|
|
+ $ui = new ConsoleUI($this->output);
|
|
|
+ $job->setUI($ui);
|
|
|
|
|
|
try {
|
|
|
if ($preview) {
|
|
|
@@ -163,7 +193,10 @@ class CronCommand extends Command
|
|
|
}
|
|
|
|
|
|
$t1 = microtime(true);
|
|
|
- $this->output->writeln($job->name() . " has been successfully executed [" . ($t1 - $t0) . " sec.]");
|
|
|
+
|
|
|
+ $msg = "Job has been successfully executed [" . ($t1 - $t0) . " sec.]";
|
|
|
+ $this->output->writeln($formatter->formatSection($job->name(), $msg));
|
|
|
+ $this->logger->info($msg);
|
|
|
|
|
|
return Command::SUCCESS;
|
|
|
}
|