diff --git a/config/packages/messenger.yaml b/config/packages/messenger.yaml index 5504a1f..37d5c19 100644 --- a/config/packages/messenger.yaml +++ b/config/packages/messenger.yaml @@ -25,7 +25,9 @@ framework: Symfony\Component\Notifier\Message\ChatMessage: async Symfony\Component\Notifier\Message\SmsMessage: async App\Message\UpdateRdapServers: async - App\Message\SendNotifWatchListTrigger: async + App\Message\ProcessWatchListsTrigger: async + App\Message\ProcessWatchListTrigger: async + App\Message\ProcessDomainTrigger: async # Route your messages to the transports # 'App\Message\YourMessage': async diff --git a/src/Controller/DomainRefreshController.php b/src/Controller/DomainRefreshController.php index 51fefe9..b4d0030 100644 --- a/src/Controller/DomainRefreshController.php +++ b/src/Controller/DomainRefreshController.php @@ -3,40 +3,51 @@ namespace App\Controller; use App\Entity\Domain; +use App\Entity\WatchList; +use App\Message\ProcessDomainTrigger; use App\Repository\DomainRepository; use App\Service\RDAPService; use DateTimeImmutable; use Exception; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpKernel\Exception\TooManyRequestsHttpException; +use Symfony\Component\Messenger\Exception\ExceptionInterface; +use Symfony\Component\Messenger\MessageBusInterface; use Symfony\Component\RateLimiter\RateLimiterFactory; class DomainRefreshController extends AbstractController { - public function __construct(private readonly DomainRepository $domainRepository, - private readonly RDAPService $RDAPService, - private readonly RateLimiterFactory $authenticatedApiLimiter) + public function __construct(private readonly DomainRepository $domainRepository, + private readonly RDAPService $RDAPService, + private readonly RateLimiterFactory $authenticatedApiLimiter, + private readonly MessageBusInterface $bus) { } /** * @throws Exception + * @throws ExceptionInterface */ public function __invoke(string $ldhName,): ?Domain { /** @var Domain $domain */ $domain = $this->domainRepository->findOneBy(["ldhName" => $ldhName]); - if ($domain === null || - $domain->getUpdatedAt()->diff(new DateTimeImmutable('now'))->days >= 7) { + if ($domain !== null && $domain->getUpdatedAt()->diff(new DateTimeImmutable('now'))->days < 7) return $domain; + if ($this->container->getParameter('kernel.environment') !== 'dev') { $limiter = $this->authenticatedApiLimiter->create($this->getUser()->getUserIdentifier()); - if (false === $limiter->consume()->isAccepted()) { - throw new TooManyRequestsHttpException(); - } - - $domain = $this->RDAPService->registerDomain($ldhName); + if (false === $limiter->consume()->isAccepted()) throw new TooManyRequestsHttpException(); } + + $updatedAt = $domain->getUpdatedAt(); + $domain = $this->RDAPService->registerDomain($ldhName); + + /** @var WatchList $watchList */ + foreach ($domain->getWatchLists()->getIterator() as $watchList) { + $this->bus->dispatch(new ProcessDomainTrigger($watchList->getToken(), $domain->getLdhName(), $updatedAt)); + } + return $domain; } } \ No newline at end of file diff --git a/src/Message/ProcessDomainTrigger.php b/src/Message/ProcessDomainTrigger.php new file mode 100644 index 0000000..52fead6 --- /dev/null +++ b/src/Message/ProcessDomainTrigger.php @@ -0,0 +1,18 @@ +watchListRepository->findOneBy(["token" => $message->watchListToken]); + /** @var Domain $domain */ + $domain = $this->domainRepository->findOneBy(["ldhName" => $message->ldhName]); + + /** @var DomainEvent $event */ + foreach ($domain->getEvents()->filter(fn($event) => $message->updatedAt < $event->getDate()) as $event) { + $watchListTriggers = $watchList->getWatchListTriggers() + ->filter(fn($trigger) => $trigger->getEvent() === $event->getAction()); + + /** @var WatchListTrigger $watchListTrigger */ + foreach ($watchListTriggers->getIterator() as $watchListTrigger) { + + switch ($watchListTrigger->getAction()) { + case TriggerAction::SendEmail: + $this->sendEmailDomainUpdated($event, $watchList->getUser()); + } + } + } + } + + + /** + * @throws TransportExceptionInterface + */ + private function sendEmailDomainUpdated(DomainEvent $domainEvent, User $user): void + { + $email = (new TemplatedEmail()) + ->from($this->mailerSenderEmail) + ->to($user->getEmail()) + ->priority(Email::PRIORITY_HIGHEST) + ->subject('A domain name has been changed') + ->htmlTemplate('emails/domain_updated.html.twig') + ->locale('en') + ->context([ + "event" => $domainEvent + ]); + + $this->mailer->send($email); + } + +} diff --git a/src/MessageHandler/ProcessWatchListTriggerHandler.php b/src/MessageHandler/ProcessWatchListTriggerHandler.php new file mode 100644 index 0000000..cb9d35a --- /dev/null +++ b/src/MessageHandler/ProcessWatchListTriggerHandler.php @@ -0,0 +1,82 @@ +watchListRepository->findOneBy(["token" => $message->watchListToken]); + /** @var Domain $domain */ + foreach ($watchList->getDomains() + ->filter(fn($domain) => $domain->getUpdatedAt() + ->diff(new DateTimeImmutable('now'))->days >= 7) as $domain + ) { + $updatedAt = $domain->getUpdatedAt(); + + try { + $domain = $this->RDAPService->registerDomain($domain->getLdhName()); + } catch (Throwable) { + $this->sendEmailDomainUpdateError($domain, $watchList->getUser()); + continue; + } + + $this->bus->dispatch(new ProcessDomainTrigger($watchList->getToken(), $domain->getLdhName(), $updatedAt)); + } + } + + + /** + * @throws TransportExceptionInterface + */ + private function sendEmailDomainUpdateError(Domain $domain, User $user): void + { + $email = (new TemplatedEmail()) + ->from($this->mailerSenderEmail) + ->to($user->getEmail()) + ->subject('An error occurred while updating a domain name') + ->htmlTemplate('emails/errors/domain_update.html.twig') + ->locale('en') + ->context([ + "domain" => $domain + ]); + + $this->mailer->send($email); + } + +} diff --git a/src/MessageHandler/ProcessWatchListsTriggerHandler.php b/src/MessageHandler/ProcessWatchListsTriggerHandler.php new file mode 100644 index 0000000..99f62e3 --- /dev/null +++ b/src/MessageHandler/ProcessWatchListsTriggerHandler.php @@ -0,0 +1,35 @@ +watchListRepository->findAll() as $watchList) { + $this->bus->dispatch(new ProcessWatchListTrigger($watchList->getToken())); + } + } + +} diff --git a/src/MessageHandler/SendNotifWatchListTriggerHandler.php b/src/MessageHandler/SendNotifWatchListTriggerHandler.php deleted file mode 100644 index cb69555..0000000 --- a/src/MessageHandler/SendNotifWatchListTriggerHandler.php +++ /dev/null @@ -1,118 +0,0 @@ -watchListRepository->findAll() as $watchList) { - - /** @var Domain $domain */ - foreach ($watchList->getDomains() - ->filter(fn($domain) => $domain->getUpdatedAt() - ->diff(new DateTimeImmutable('now'))->days >= 7) as $domain - ) { - $updatedAt = $domain->getUpdatedAt(); - - try { - $domain = $this->RDAPService->registerDomain($domain->getLdhName()); - } catch (Throwable) { - $this->sendEmailDomainUpdateError($domain, $watchList->getUser()); - continue; - } - - /** @var DomainEvent $event */ - foreach ($domain->getEvents()->filter(fn($event) => $updatedAt < $event->getDate()) as $event) { - - $watchListTriggers = $watchList->getWatchListTriggers() - ->filter(fn($trigger) => $trigger->getEvent() === $event->getAction()); - - /** @var WatchListTrigger $watchListTrigger */ - foreach ($watchListTriggers->getIterator() as $watchListTrigger) { - - switch ($watchListTrigger->getAction()) { - case TriggerAction::SendEmail: - $this->sendEmailDomainUpdated($event, $watchList->getUser()); - } - } - } - } - - } - } - - /** - * @throws TransportExceptionInterface - */ - public function sendEmailDomainUpdateError(Domain $domain, User $user): Email - { - $email = (new TemplatedEmail()) - ->from($this->mailerSenderEmail) - ->to($user->getEmail()) - ->subject('An error occurred while updating a domain name') - ->htmlTemplate('emails/errors/domain_update.html.twig') - ->locale('en') - ->context([ - "domain" => $domain - ]); - - $this->mailer->send($email); - return $email; - } - - /** - * @throws TransportExceptionInterface - */ - public function sendEmailDomainUpdated(DomainEvent $domainEvent, User $user): Email - { - $email = (new TemplatedEmail()) - ->from($this->mailerSenderEmail) - ->to($user->getEmail()) - ->priority(Email::PRIORITY_HIGHEST) - ->subject('A domain name has been changed') - ->htmlTemplate('emails/domain_updated.html.twig') - ->locale('en') - ->context([ - "event" => $domainEvent - ]); - - $this->mailer->send($email); - return $email; - } - -} diff --git a/src/Scheduler/SendNotifWatchListTriggerSchedule.php b/src/Scheduler/SendNotifWatchListTriggerSchedule.php index c8df890..dddcb7f 100644 --- a/src/Scheduler/SendNotifWatchListTriggerSchedule.php +++ b/src/Scheduler/SendNotifWatchListTriggerSchedule.php @@ -2,7 +2,7 @@ namespace App\Scheduler; -use App\Message\SendNotifWatchListTrigger; +use App\Message\ProcessWatchListsTrigger; use Symfony\Component\Scheduler\Attribute\AsSchedule; use Symfony\Component\Scheduler\RecurringMessage; use Symfony\Component\Scheduler\Schedule; @@ -14,16 +14,16 @@ final readonly class SendNotifWatchListTriggerSchedule implements ScheduleProvid { public function __construct( private CacheInterface $cache, - ) { + ) + { } public function getSchedule(): Schedule { return (new Schedule()) ->add( - RecurringMessage::every('10 seconds', new SendNotifWatchListTrigger()), + RecurringMessage::every('10 seconds', new ProcessWatchListsTrigger()), ) - ->stateful($this->cache) - ; + ->stateful($this->cache); } }