<?php
namespace App\EventSubscriber;
use App\Command\Impl\AbstractCronCommand;
use App\Entity\CronLog;
use App\Exception\CommandRuntimeException;
use App\Service\CronJobService;
use App\Service\Utils\CommandLocker;
use App\Service\Utils\CommandUniquenessKeyGenerator;
use App\Service\Utils\FlushService;
use Psr\Log\LoggerInterface;
use Symfony\Component\Console\ConsoleEvents;
use Symfony\Component\Console\Event\ConsoleTerminateEvent;
use Symfony\Component\Console\Style\SymfonyStyle;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\Session\SessionInterface;
/**
* Auto flushes objects before HTTP responses
*/
class CommandTerminateEventSubscriber implements EventSubscriberInterface
{
/** @var CronJobService $cronJobService The logger for commands */
private CronJobService $cronJobService;
/** @var FlushService $flushService */
private FlushService $flushService;
/** @var SessionInterface $session */
private SessionInterface $session;
private CommandLocker $commandLocker;
/**
* @param LoggerInterface $logger
* @param CronJobService $cronJobService
* @param FlushService $flushService
* @param SessionInterface $session
* @param CommandLocker $commandLocker
*/
public function __construct(CronJobService $cronJobService, FlushService $flushService, SessionInterface $session, CommandLocker $commandLocker)
{
$this->cronJobService = $cronJobService;
$this->flushService = $flushService;
$this->session = $session;
$this->commandLocker = $commandLocker;
}
/** @inheritdoc */
public static function getSubscribedEvents()
{
return [
ConsoleEvents::TERMINATE => ['commandTerminate', 1024]
];
}
public function commandTerminate(ConsoleTerminateEvent $event): void
{
if ($event->getCommand() instanceof AbstractCronCommand) {
$io = new SymfonyStyle($event->getInput(), $event->getOutput());
$exitCode = $event->getExitCode();
$flushed = $this->flushService->flushForCommand($event);
if ($flushed === false) {
$event->setExitCode(98);
$io->error("Error when flushing.");
}
$uniquenessKey = CommandUniquenessKeyGenerator::generate();
$log = $this->cronJobService->findById($this->session->get($uniquenessKey, -1));
if ($log === null) {
$io->error(sprintf("Cannot find log with key %s", $uniquenessKey));
throw new CommandRuntimeException();
} else {
$this->cronJobService->closeLog($log, match ($exitCode) {
0 => CronLog::SUCCESS,
CronLog::SKIPPED => Cronlog::SKIPPED,
CronLog::INTERRUPTED => Cronlog::INTERRUPTED,
default => CronLog::FAILURE
});
}
$uniquenessKeyTime = CommandUniquenessKeyGenerator::generateForStartTime();
$startTime = $this->session->get($uniquenessKeyTime);
if (is_null($startTime)) {
$io->error(sprintf("Cannot find the start time with key %s", $uniquenessKeyTime));
throw new CommandRuntimeException();
}
$io->info('Total execution time : ' . number_format((microtime(true) - $startTime), 2) . ' seconds.');
$this->commandLocker->releaseCommand();
}
}
}