<?php
namespace App\EventSubscriber;
use App\Command\Impl\AbstractCronCommand;
use App\Entity\CronJob;
use App\Entity\CronLog;
use App\Exception\CommandRuntimeException;
use App\Service\CronJobService;
use App\Service\Utils\CommandLocker;
use App\Service\Utils\CommandUniquenessKeyGenerator;
use Doctrine\Persistence\ManagerRegistry;
use Exception;
use Psr\Log\LoggerInterface;
use Symfony\Component\Console\Command\LockableTrait;
use Symfony\Component\Console\ConsoleEvents;
use Symfony\Component\Console\Event\ConsoleCommandEvent;
use Symfony\Component\Console\Style\SymfonyStyle;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Session\SessionInterface;
use Symfony\Component\HttpKernel\Event\ResponseEvent;
use Symfony\Component\HttpKernel\KernelEvents;
/**
* Auto flushes objects before HTTP responses
*/
class CommandStartEventSubscriber implements EventSubscriberInterface
{
/** @var CronJobService $cronLogger The logger for commands */
private CronJobService $cronLogger;
/** @var SessionInterface $session */
private SessionInterface $session;
/** @var CommandLocker $commandLocker */
private CommandLocker $commandLocker;
/**
* @param CronJobService $cronLogger
* @param SessionInterface $session
* @param CommandLocker $commandLocker
*/
public function __construct(CronJobService $cronLogger, SessionInterface $session, CommandLocker $commandLocker)
{
$this->cronLogger = $cronLogger;
$this->session = $session;
$this->commandLocker = $commandLocker;
}
/** @inheritdoc */
public static function getSubscribedEvents()
{
return [
ConsoleEvents::COMMAND => ['commandStart', 1024]
];
}
public function commandStart(ConsoleCommandEvent $event): void
{
if ($event->getCommand() instanceof AbstractCronCommand) {
$this->session->set(CommandUniquenessKeyGenerator::generateForStartTime(), microtime(true));
$inputString = $event->getInput()->__toString();
$log = $this->cronLogger->openLog($event->getCommand(), $inputString);
$this->session->set(CommandUniquenessKeyGenerator::generate(), $log->getId());
if (false === $this->commandLocker->lockCommand($inputString)) {
throw new CommandRuntimeException('Command already running !', CronLog::SKIPPED);
}
$io = new SymfonyStyle($event->getInput(), $event->getOutput());
$io->info(sprintf('Command %s at %s', $inputString, (new \DateTime())->format('y-m-d H:i:s.u')));
}
}
}