Skip to content

Commit 2479453

Browse files
committed
[Messenger] Dispatch events before & after each handler
1 parent b04d7b0 commit 2479453

File tree

8 files changed

+158
-0
lines changed

8 files changed

+158
-0
lines changed

src/Symfony/Bundle/FrameworkBundle/Resources/config/messenger.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,8 @@
8282
->abstract()
8383
->args([
8484
abstract_arg('bus handler resolver'),
85+
false,
86+
service('event_dispatcher'),
8587
])
8688
->tag('monolog.logger', ['channel' => 'messenger'])
8789
->call('setLogger', [service('logger')->ignoreOnInvalid()])

src/Symfony/Component/Messenger/CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
CHANGELOG
22
=========
33

4+
7.1
5+
---
6+
7+
* New events: `HandlerStartingEvent`, `HandlerSuccessEvent`, `HandlerFailureEvent`
8+
49
7.0
510
---
611

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Messenger\Event;
13+
14+
use Symfony\Component\Messenger\Envelope;
15+
use Symfony\Component\Messenger\Handler\HandlerDescriptor;
16+
17+
abstract class AbstractHandlerEvent
18+
{
19+
public function __construct(
20+
public readonly Envelope $envelope,
21+
public readonly HandlerDescriptor $handlerDescriptor,
22+
) {
23+
}
24+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Messenger\Event;
13+
14+
use Symfony\Component\Messenger\Envelope;
15+
use Symfony\Component\Messenger\Handler\HandlerDescriptor;
16+
17+
/**
18+
* Event dispatched after a handler fails.
19+
*/
20+
final class HandlerFailureEvent extends AbstractHandlerEvent
21+
{
22+
public function __construct(
23+
Envelope $envelope,
24+
HandlerDescriptor $handlerDescriptor,
25+
public readonly \Throwable $exception,
26+
) {
27+
parent::__construct($envelope, $handlerDescriptor);
28+
}
29+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Messenger\Event;
13+
14+
/**
15+
* Event dispatched before a handler is called.
16+
*/
17+
final class HandlerStartingEvent extends AbstractHandlerEvent
18+
{
19+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Messenger\Event;
13+
14+
/**
15+
* Event dispatched after a handler succeeds.
16+
*/
17+
final class HandlerSuccessEvent extends AbstractHandlerEvent
18+
{
19+
}

src/Symfony/Component/Messenger/Middleware/HandleMessageMiddleware.php

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,12 @@
1111

1212
namespace Symfony\Component\Messenger\Middleware;
1313

14+
use Psr\EventDispatcher\EventDispatcherInterface;
1415
use Psr\Log\LoggerAwareTrait;
1516
use Symfony\Component\Messenger\Envelope;
17+
use Symfony\Component\Messenger\Event\HandlerFailureEvent;
18+
use Symfony\Component\Messenger\Event\HandlerStartingEvent;
19+
use Symfony\Component\Messenger\Event\HandlerSuccessEvent;
1620
use Symfony\Component\Messenger\Exception\HandlerFailedException;
1721
use Symfony\Component\Messenger\Exception\LogicException;
1822
use Symfony\Component\Messenger\Exception\NoHandlerForMessageException;
@@ -35,6 +39,7 @@ class HandleMessageMiddleware implements MiddlewareInterface
3539
public function __construct(
3640
private HandlersLocatorInterface $handlersLocator,
3741
private bool $allowNoHandlers = false,
42+
private ?EventDispatcherInterface $eventDispatcher = null,
3843
) {
3944
}
4045

@@ -58,6 +63,10 @@ public function handle(Envelope $envelope, StackInterface $stack): Envelope
5863
continue;
5964
}
6065

66+
$this->eventDispatcher?->dispatch(new HandlerStartingEvent($envelope, $handlerDescriptor));
67+
68+
$e = null;
69+
6170
try {
6271
$handler = $handlerDescriptor->getHandler();
6372
$batchHandler = $handlerDescriptor->getBatchHandler();
@@ -97,6 +106,14 @@ public function handle(Envelope $envelope, StackInterface $stack): Envelope
97106
} catch (\Throwable $e) {
98107
$exceptions[$handlerDescriptor->getName()] = $e;
99108
}
109+
110+
if (null !== $this->eventDispatcher) {
111+
$event = (null !== $e)
112+
? new HandlerFailureEvent($envelope, $handlerDescriptor, $e)
113+
: new HandlerSuccessEvent($envelope, $handlerDescriptor);
114+
115+
$this->eventDispatcher->dispatch($event);
116+
}
100117
}
101118

102119
/** @var FlushBatchHandlersStamp $flushStamp */

src/Symfony/Component/Messenger/Tests/Middleware/HandleMessageMiddlewareTest.php

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,11 @@
1111

1212
namespace Symfony\Component\Messenger\Tests\Middleware;
1313

14+
use Psr\EventDispatcher\EventDispatcherInterface;
1415
use Symfony\Component\Messenger\Envelope;
16+
use Symfony\Component\Messenger\Event\HandlerFailureEvent;
17+
use Symfony\Component\Messenger\Event\HandlerStartingEvent;
18+
use Symfony\Component\Messenger\Event\HandlerSuccessEvent;
1519
use Symfony\Component\Messenger\Exception\HandlerFailedException;
1620
use Symfony\Component\Messenger\Exception\LogicException;
1721
use Symfony\Component\Messenger\Exception\NoHandlerForMessageException;
@@ -356,6 +360,45 @@ public function testHandlerArgumentsStampNamedArgument()
356360

357361
$middleware->handle($envelope, $this->getStackMock());
358362
}
363+
364+
public function testDispatchHandlerEvents()
365+
{
366+
$message = new DummyMessage('Hey');
367+
$envelope = new Envelope($message);
368+
369+
$successHandler = $this->createMock(HandleMessageMiddlewareTestCallable::class);
370+
$successHandler->expects($this->once())->method('__invoke');
371+
372+
$failureHandler = $this->createMock(HandleMessageMiddlewareTestCallable::class);
373+
$failureHandler->expects($this->once())->method('__invoke')->willThrowException(
374+
$exception = new \RuntimeException('Handler failed'),
375+
);
376+
377+
$handlersLocator = new HandlersLocator([
378+
DummyMessage::class => [
379+
$successHandlerDescriptor = new HandlerDescriptor($successHandler, ['alias' => 'successHandler']),
380+
$failureHandlerDescriptor = new HandlerDescriptor($failureHandler, ['alias' => 'failureHandler']),
381+
],
382+
]);
383+
384+
$dispatcher = $this->createMock(EventDispatcherInterface::class);
385+
386+
$handledStamp = new HandledStamp(null, $successHandlerDescriptor->getName());
387+
388+
$dispatcher->expects($this->exactly(4))
389+
->method('dispatch')
390+
->withConsecutive(
391+
[new HandlerStartingEvent($envelope, $successHandlerDescriptor)],
392+
[new HandlerSuccessEvent($envelope->with($handledStamp), $successHandlerDescriptor)],
393+
[new HandlerStartingEvent($envelope->with($handledStamp), $failureHandlerDescriptor)],
394+
[new HandlerFailureEvent($envelope->with($handledStamp), $failureHandlerDescriptor, $exception)],
395+
);
396+
397+
$middleware = new HandleMessageMiddleware($handlersLocator, eventDispatcher: $dispatcher);
398+
399+
$this->expectException(HandlerFailedException::class);
400+
$middleware->handle($envelope, new StackMiddleware());
401+
}
359402
}
360403

361404
class HandleMessageMiddlewareTestCallable

0 commit comments

Comments
 (0)