From a889940165a095ef36c14bed02478dae21f196a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Fastr=C3=A9?= Date: Thu, 16 Oct 2025 10:04:36 +0200 Subject: [PATCH] Trigger a PostTicketUpdateEvent asynchronously --- config/packages/messenger.yaml | 1 + ...eneratePostUpdateTicketEventSubscriber.php | 52 ++++++++++ .../src/Event/PostTicketUpdateEvent.php | 29 ++++++ .../PostTicketUpdateMessageHandler.php | 37 ++++++++ .../src/Messenger/PostTicketUpdateMessage.php | 27 ++++++ .../src/config/services.yaml | 6 ++ ...atePostUpdateTicketEventSubscriberTest.php | 58 ++++++++++++ .../PostTicketUpdateMessageHandlerTest.php | 94 +++++++++++++++++++ 8 files changed, 304 insertions(+) create mode 100644 src/Bundle/ChillTicketBundle/src/Event/EventSubscriber/GeneratePostUpdateTicketEventSubscriber.php create mode 100644 src/Bundle/ChillTicketBundle/src/Event/PostTicketUpdateEvent.php create mode 100644 src/Bundle/ChillTicketBundle/src/Messenger/Handler/PostTicketUpdateMessageHandler.php create mode 100644 src/Bundle/ChillTicketBundle/src/Messenger/PostTicketUpdateMessage.php create mode 100644 src/Bundle/ChillTicketBundle/tests/Event/EventSubscriber/GeneratePostUpdateTicketEventSubscriberTest.php create mode 100644 src/Bundle/ChillTicketBundle/tests/Messenger/Handler/PostTicketUpdateMessageHandlerTest.php diff --git a/config/packages/messenger.yaml b/config/packages/messenger.yaml index 4274aeec6..45802f50b 100644 --- a/config/packages/messenger.yaml +++ b/config/packages/messenger.yaml @@ -66,6 +66,7 @@ framework: 'Chill\MainBundle\Export\Messenger\ExportRequestGenerationMessage': priority 'Chill\MainBundle\Export\Messenger\RemoveExportGenerationMessage': async 'Chill\MainBundle\Notification\Email\NotificationEmailMessages\ScheduleDailyNotificationDigestMessage': async + 'Chill\TicketBundle\Messenger\PostTicketUpdateMessage': async # end of routes added by chill-bundles recipes # Route your messages to the transports # 'App\Message\YourMessage': async diff --git a/src/Bundle/ChillTicketBundle/src/Event/EventSubscriber/GeneratePostUpdateTicketEventSubscriber.php b/src/Bundle/ChillTicketBundle/src/Event/EventSubscriber/GeneratePostUpdateTicketEventSubscriber.php new file mode 100644 index 000000000..7b8889c1c --- /dev/null +++ b/src/Bundle/ChillTicketBundle/src/Event/EventSubscriber/GeneratePostUpdateTicketEventSubscriber.php @@ -0,0 +1,52 @@ + + */ + private array $toDispatch = []; + + public function __construct(private readonly MessageBusInterface $messageBus) {} + + public static function getSubscribedEvents(): array + { + return [ + TicketUpdateEvent::class => ['onTicketUpdate', 0], + KernelEvents::TERMINATE => ['onKernelTerminate', 8096], + ]; + } + + public function onTicketUpdate(TicketUpdateEvent $event): void + { + $this->toDispatch[] = new PostTicketUpdateMessage($event->ticket, $event->updateKind); + } + + public function onKernelTerminate(TerminateEvent $event): void + { + foreach ($this->toDispatch as $message) { + $this->messageBus->dispatch($message); + } + } +} diff --git a/src/Bundle/ChillTicketBundle/src/Event/PostTicketUpdateEvent.php b/src/Bundle/ChillTicketBundle/src/Event/PostTicketUpdateEvent.php new file mode 100644 index 000000000..d4e8fd738 --- /dev/null +++ b/src/Bundle/ChillTicketBundle/src/Event/PostTicketUpdateEvent.php @@ -0,0 +1,29 @@ +ticketRepository->find($event->ticketId); + + if (null === $ticket) { + throw new UnrecoverableMessageHandlingException('Ticket not found'); + } + + $this->eventDispatcher->dispatch(new PostTicketUpdateEvent($event->updateKind, $ticket)); + } +} diff --git a/src/Bundle/ChillTicketBundle/src/Messenger/PostTicketUpdateMessage.php b/src/Bundle/ChillTicketBundle/src/Messenger/PostTicketUpdateMessage.php new file mode 100644 index 000000000..ac6f9c2d5 --- /dev/null +++ b/src/Bundle/ChillTicketBundle/src/Messenger/PostTicketUpdateMessage.php @@ -0,0 +1,27 @@ +ticketId = $ticket->getId(); + } +} diff --git a/src/Bundle/ChillTicketBundle/src/config/services.yaml b/src/Bundle/ChillTicketBundle/src/config/services.yaml index 1089b574e..5e2b8e1b3 100644 --- a/src/Bundle/ChillTicketBundle/src/config/services.yaml +++ b/src/Bundle/ChillTicketBundle/src/config/services.yaml @@ -17,6 +17,9 @@ services: tags: - controller.service_arguments + Chill\TicketBundle\Event\EventSubscriber\: + resource: '../Event/EventSubscriber/' + Chill\TicketBundle\Repository\: resource: '../Repository/' @@ -35,6 +38,9 @@ services: Chill\TicketBundle\Menu\: resource: '../Menu/' + Chill\TicketBundle\Messenger\Handler\: + resource: '../Messenger/Handler' + Chill\TicketBundle\Validation\: resource: '../Validation/' diff --git a/src/Bundle/ChillTicketBundle/tests/Event/EventSubscriber/GeneratePostUpdateTicketEventSubscriberTest.php b/src/Bundle/ChillTicketBundle/tests/Event/EventSubscriber/GeneratePostUpdateTicketEventSubscriberTest.php new file mode 100644 index 000000000..e6a982906 --- /dev/null +++ b/src/Bundle/ChillTicketBundle/tests/Event/EventSubscriber/GeneratePostUpdateTicketEventSubscriberTest.php @@ -0,0 +1,58 @@ +getProperty('id'); + $idProperty->setValue($ticket, 1); + $event = new class (TicketUpdateKindEnum::UPDATE_MOTIVE, $ticket) extends TicketUpdateEvent {}; + + $messageBus = $this->prophesize(MessageBusInterface::class); + $messageBus->dispatch(Argument::that(fn ($arg) => $arg instanceof PostTicketUpdateMessage && TicketUpdateKindEnum::UPDATE_MOTIVE === $arg->updateKind && 1 === $arg->ticketId)) + ->will(fn ($args) => new Envelope($args[0])) + ->shouldBeCalled(); + + $eventSubscriber = new GeneratePostUpdateTicketEventSubscriber($messageBus->reveal()); + $eventSubscriber->onTicketUpdate($event); + + $kernel = $this->prophesize(KernelInterface::class); + $terminate = new TerminateEvent($kernel->reveal(), new Request(), new Response()); + $eventSubscriber->onKernelTerminate($terminate); + } +} diff --git a/src/Bundle/ChillTicketBundle/tests/Messenger/Handler/PostTicketUpdateMessageHandlerTest.php b/src/Bundle/ChillTicketBundle/tests/Messenger/Handler/PostTicketUpdateMessageHandlerTest.php new file mode 100644 index 000000000..de83dedb5 --- /dev/null +++ b/src/Bundle/ChillTicketBundle/tests/Messenger/Handler/PostTicketUpdateMessageHandlerTest.php @@ -0,0 +1,94 @@ +getProperty('id'); + $idProperty->setValue($ticket, 123); + + $message = new PostTicketUpdateMessage($ticket, TicketUpdateKindEnum::UPDATE_MOTIVE); + + // Mock repository to return the Ticket when searching by id + $ticketRepository = $this->prophesize(TicketRepositoryInterface::class); + $ticketRepository->find(123)->willReturn($ticket)->shouldBeCalledOnce(); + + // Expect the dispatcher to dispatch a PostTicketUpdateEvent with correct data + $eventDispatcher = $this->prophesize(EventDispatcherInterface::class); + $eventDispatcher + ->dispatch(Argument::that(function ($event) use ($ticket) { + return $event instanceof PostTicketUpdateEvent + && TicketUpdateKindEnum::UPDATE_MOTIVE === $event->updateKind + && $event->ticket === $ticket; + })) + ->will(function ($args) { return $args[0]; }) + ->shouldBeCalledOnce(); + + $handler = new PostTicketUpdateMessageHandler($eventDispatcher->reveal(), $ticketRepository->reveal()); + + // Act + $handler($message); + + // Assert: expectations asserted by Prophecy + self::assertTrue(true); + } + + public function testThrowsWhenTicketNotFound(): void + { + // Arrange: a Ticket with an ID for the message, but repository will return null + $ticket = new Ticket(); + $reflection = new \ReflectionClass(Ticket::class); + $idProperty = $reflection->getProperty('id'); + $idProperty->setValue($ticket, 999); + + $message = new PostTicketUpdateMessage($ticket, TicketUpdateKindEnum::UPDATE_MOTIVE); + + $ticketRepository = $this->prophesize(TicketRepositoryInterface::class); + $ticketRepository->find(999)->willReturn(null)->shouldBeCalledOnce(); + + $eventDispatcher = $this->prophesize(EventDispatcherInterface::class); + $eventDispatcher->dispatch(Argument::any())->shouldNotBeCalled(); + + $handler = new PostTicketUpdateMessageHandler($eventDispatcher->reveal(), $ticketRepository->reveal()); + + // Assert: exception is thrown + $this->expectException(UnrecoverableMessageHandlingException::class); + $this->expectExceptionMessage('Ticket not found'); + + // Act + $handler($message); + } +}