<?php
namespace App\EventSubscriber;
use App\Event\ActionErrorEvent;
use App\Event\ActionFormEvent;
use App\Message\ProcessFormActionsMessage;
use App\Service\FormActionSetManager;
use Exception;
use Psr\Log\LoggerInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\Messenger\MessageBusInterface;
class ActionSubscriber implements EventSubscriberInterface
{
/** @var FormActionSetManager $formActionSetManager */
private $formActionSetManager;
/** @var MessageBusInterface $messageBus */
private $messageBus;
/** @var LoggerInterface $logger */
private $logger;
/** @var bool $asyncFormActions */
private $asyncFormActions;
/**
* @param FormActionSetManager $formActionSetManager
* @param MessageBusInterface $messageBus
* @param LoggerInterface $logger
* @param bool $asyncFormActions
*/
public function __construct(
FormActionSetManager $formActionSetManager,
MessageBusInterface $messageBus,
LoggerInterface $logger,
bool $asyncFormActions
) {
$this->formActionSetManager = $formActionSetManager;
$this->messageBus = $messageBus;
$this->logger = $logger;
$this->asyncFormActions = $asyncFormActions;
}
/**
* @return string[]
*/
public static function getSubscribedEvents(): array
{
return [
ActionErrorEvent::KEY => 'onActionError',
ActionFormEvent::KEY => 'onAppEventsForm'
];
}
/**
* Una acción que no ha podido completarse (hoy: un email sin destinatarios resolubles).
*
* Se registra con nivel error para que llegue a Sentry. Sin esto, un formulario cuyo
* email de confirmación no encuentra destinatario falla de forma completamente silenciosa.
*
* @param ActionErrorEvent $event
* @return void
*/
public function onActionError(ActionErrorEvent $event)
{
$action = $event->getAction();
$this->logger->error('La acción del formulario no ha podido completarse', [
'action' => $action->getId(),
'action_name' => $action->getName(),
'command' => $action->getCommand(),
'form' => $event->getForm()->getId(),
'form_lead' => $event->getFormLead()->getId(),
]);
}
/**
* Las acciones post-envío generan PDFs con Dompdf, calculan los promedios del anexo de
* indicadores sobre toda la campaña y envían por SMTP. Con ASYNC_FORM_ACTIONS=1 todo eso
* sale del request y lo procesa un worker de Messenger.
*
* El interruptor viene por variable de entorno y por defecto está apagado: así el código
* se puede desplegar sin activar el asíncrono, validar el worker en un entorno y activarlo
* después sin necesidad de otra release. Si no hay worker consumiendo la cola, los emails
* no llegan a salir, y eso tiene que ser una decisión explícita.
*
* @param ActionFormEvent $event
* @return void
* @throws Exception
*/
public function onAppEventsForm(ActionFormEvent $event)
{
if ($this->asyncFormActions) {
$this->messageBus->dispatch(new ProcessFormActionsMessage(
$event->getForm()->getId(),
$event->getFormLead()->getId(),
$event->getName()
));
return;
}
$this->formActionSetManager
->setForm($event->getForm())
->setLead($event->getFormLead())
->executeActionSets($event->getName())
;
}
}