8000 [Messenger] Add `NextInterface`, allowing to unstack the call stack · symfony/symfony@732be7f · GitHub
[go: up one dir, main page]

Skip to content

Commit 732be7f

Browse files
[Messenger] Add NextInterface, allowing to unstack the call stack
1 parent 5ae0e89 commit 732be7f

19 files changed

+203
-111
lines changed

src/Symfony/Bridge/Doctrine/Messenger/DoctrineTransactionMiddleware.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ public function handle(Envelope $envelope, callable $next): void
4545

4646
$entityManager->getConnection()->beginTransaction();
4747
try {
48-
$next($envelope);
48+
$next()->handle($envelope, $next);
4949
$entityManager->flush();
5050
$entityManager->getConnection()->commit();
5151
} catch (\Throwable $exception) {

src/Symfony/Component/Messenger/MessageBus.php

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
namespace Symfony\Component\Messenger;
1313

1414
use Symfony\Component\Messenger\Middleware\MiddlewareInterface;
15+
use Symfony\Component\Messenger\Middleware\NextMiddleware;
1516

1617
/**
1718
* @author Samuel Roze <samuel.roze@gmail.com>
@@ -64,13 +65,7 @@ public function dispatch($message): void
6465
if (!$middlewareIterator->valid()) {
6566
return;
6667
}
67-
$next = static function (Envelope $envelope) use ($middlewareIterator, &$next) {
68-
$middlewareIterator->next();
69-
70-
if ($middlewareIterator->valid()) {
71-
$middlewareIterator->current()->handle($envelope, $next);
72-
}
73-
};
68+
$next = new NextMiddleware($middlewareIterator);
7469

7570
$middlewareIterator->current()->handle($message instanceof Envelope ? $message : new Envelope($message), $next);
7671
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ public function handle(Envelope $envelope, callable $next): void
4040
if (\is_callable($this->activated) ? ($this->activated)($envelope) : $this->activated) {
4141
$this->inner->handle($envelope, $next);
4242
} else {
43-
$next($envelope);
43+
$next()->handle($envelope, $next);
4444
}
4545
}
4646
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ public function handle(Envelope $envelope, callable $next): void
3838
{
3939
if (null !== $handler = $this->messageHandlerLocator->getHandler($envelope)) {
4040
$handler($envelope->getMessage());
41-
$next($envelope);
41+
$next()->handle($envelope, $next);
4242
} elseif (!$this->allowNoHandlers) {
4343
throw new NoHandlerForMessageException(sprintf('No handler for message "%s".', \get_class($envelope->getMessage())));
4444
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ public function handle(Envelope $envelope, callable $next): void
3939
$this->logger->debug('Starting handling message {name}', $context);
4040

4141
try {
42-
$next($envelope);
42+
$next()->handle($envelope, $next);
4343
} catch (\Throwable $e) {
4444
$context['exception'] = $e;
4545
$this->logger->warning('An exception occurred while handling message {name}', $context);

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

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,3 @@ interface MiddlewareInterface
2323
*/
2424
public function handle(Envelope $envelope, callable $next): void;
2525
}
26-
27-
/**
28-
* @internal
29-
*/
30-
interface NextInterface
31-
{
32-
public function __invoke(Envelope $envelope): void;
33-
}
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\Middleware;
13+
14+
use Symfony\Component\Messenger\Envelope;
15+
16+
/**
17+
* @author Nicolas Grekas <p@tchwork.com>
18+
*/
19+
interface NextInterface
20+
{
21+
/**
22+
* Calls or returns the next middleware to process a message.
23+
*
24+
* @param Envelope|null When an envelope is passed, it should be forwarded to the next middleware's handle() method
25+
*
26+
* @return MiddlewareInterface The next middleware in the chain
27+
*/
28+
public function __invoke(Envelope $envelope = null): MiddlewareInterface;
29+
}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
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\Middleware;
13+
14+
use Symfony\Component\Messenger\Envelope;
15+
16+
/**
17+
* @author Nicolas Grekas <p@tchwork.com>
18+
*/
19+
class NextMiddleware implements MiddlewareInterface, NextInterface
20+
{
21+
private $middlewareIterator;
22+
23+
public function __construct(\Iterator $middlewareIterator = null)
24+
{
25+
$this->middlewareIterator = $middlewareIterator;
26+
}
27+
28+
public function __invoke(Envelope $envelope = null): MiddlewareInterface
29+
{
30+
if (null === $iterator = $this->middlewareIterator) {
31+
return $this;
32+
}
33+
$iterator->next();
34+
35+
if (!$iterator->valid()) {
36+
$this->middlewareIterator = null;
37+
38+
return $this;
39+
}
40+
$middleware = $iterator->current();
41+
42+
if (null !== $envelope) {
43+
$middleware->handle($envelope, $this);
44+
}
45+
46+
return $middleware;
47+
}
48+
49+
public function handle(Envelope $envelope, callable $next): void
50+
{
51+
// no-op
52+
}
53+
}

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ public function handle(Envelope $envelope, callable $next): void
3838
{
3939
if ($envelope->get(ReceivedStamp::class)) {
4040
// It's a received message. Do not send it back:
41-
$next($envelope);
41+
$next()->handle($envelope, $next);
4242

4343
return;
4444
}
@@ -54,6 +54,6 @@ public function handle(Envelope $envelope, callable $next): void
5454
}
5555
}
5656

57-
$next($envelope);
57+
$next()->handle($envelope, $next);
5858
}
5959
}

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

Lines changed: 48 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -49,15 +49,58 @@ public function handle(Envelope $envelope, callable $next): void
4949
$this->stopwatch->start($eventName, $this->eventCategory);
5050

5151
try {
52-
$this->inner->handle($envelope, function (Envelope $envelope) use ($next, $eventName) {
53-
$this->stopwatch->stop($eventName);
54-
$next($envelope);
55-
$this->stopwatch->start($eventName, $this->eventCategory);
56-
});
52+
$this->inner->handle($envelope, new TraceableInnerMiddleware($next, $this->stopwatch, $eventName, $this->eventCategory));
5753
} finally {
5854
if ($this->stopwatch->isStarted($eventName)) {
5955
$this->stopwatch->stop($eventName);
6056
}
6157
}
6258
}
6359
}
60+
61+
/* 17BE *
62+
* @internal
63+
*/
64+
class TraceableInnerMiddleware implements MiddlewareInterface, NextInterface
65+
{
66+
private $next;
67+
private $stopwatch;
68+
private $eventName;
69+
private $eventCategory;
70+
71+
public function __construct(callable $next, Stopwatch $stopwatch, string $eventName, string $eventCategory)
72+
{
73+
$this->next = $next;
74+
$this->stopwatch = $stopwatch;
75+
$this->eventName = $eventName;
76+
$this->eventCategory = $eventCategory;
77+
}
78+
79+
/**
80+
* {@inheritdoc}
81+
*/
82+
public function handle(Envelope $envelope, callable $next): void
83+
{
84+
$this->stopwatch->stop($this->eventName);
85+
if ($this === $next) {
86+
($this->next)()->handle($envelope, $this->next);
87+
} else {
88+
$next()->handle($envelope, $next);
89+
}
90+
$this->stopwatch->start($this->eventName, $this->eventCategory);
91+
}
92+
93+
/**
94+
* {@inheritdoc}
95+
*/
96+
public function __invoke(Envelope $envelope = null): MiddlewareInterface
97+
{
98+
if (null !== $envelope) {
99+
$this->stopwatch->stop($this->eventName);
100+
($this->next)()->handle($envelope, $this->next);
101+
$this->stopwatch->start($this->eventName, $this->eventCategory);
102+
}
103+
104+
return $this;
105+
}
106+
}

0 commit comments

Comments
 (0)
0