Skip to content

Commit 79ee32a

Browse files
committed
feature #45418 [Messenger] Add HandlerArgumentsStamp (enumag)
This PR was merged into the 6.2 branch. Discussion ---------- [Messenger] Add HandlerArgumentsStamp | Q | A | ------------- | --- | Branch? | 6.2 | Bug fix? | no | New feature? | yes | Deprecations? | no | Tickets | Fix #31075 | License | MIT | Doc PR | symfony/symfony-docs#17174 As discussed in #31075 sometimes it's desirable for the messenger handler to receive additional argument than just the message itself. I understand the voiced concerns about passing the entire envelope but instead of that we could use the approach from this PR which doesn't add any additional arguments by default but is actually even more powerful since it gives the user full control what should be sent to the handler if desired. This is just a prototype of course. With #45377 in mind I used a readonly property from PHP 8.1 but of course such details can be easily adjusted. Let me know if such feature is wanted in Symfony. If yes then I'll add tests and a doc PR. Commits ------- d081267 Add HandlerArgumentsStamp
2 parents 0b328d0 + d081267 commit 79ee32a

File tree

3 files changed

+86
-2
lines changed

3 files changed

+86
-2
lines changed

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

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
use Symfony\Component\Messenger\Stamp\AckStamp;
2424
use Symfony\Component\Messenger\Stamp\FlushBatchHandlersStamp;
2525
use Symfony\Component\Messenger\Stamp\HandledStamp;
26+
use Symfony\Component\Messenger\Stamp\HandlerArgumentsStamp;
2627
use Symfony\Component\Messenger\Stamp\NoAutoAckStamp;
2728

2829
/**
@@ -78,7 +79,7 @@ public function handle(Envelope $envelope, StackInterface $stack): Envelope
7879
$ackStamp->ack($envelope, $e);
7980
});
8081

81-
$result = $handler($message, $ack);
82+
$result = $this->callHandler($handler, $message, $ack, $envelope->last(HandlerArgumentsStamp::class));
8283

8384
if (!\is_int($result) || 0 > $result) {
8485
throw new LogicException(sprintf('A handler implementing BatchHandlerInterface must return the size of the current batch as a positive integer, "%s" returned from "%s".', \is_int($result) ? $result : get_debug_type($result), get_debug_type($batchHandler)));
@@ -92,7 +93,7 @@ public function handle(Envelope $envelope, StackInterface $stack): Envelope
9293
$result = $ack->getResult();
9394
}
9495
} else {
95-
$result = $handler($message);
96+
$result = $this->callHandler($handler, $message, null, $envelope->last(HandlerArgumentsStamp::class));
9697
}
9798

9899
$handledStamp = HandledStamp::fromDescriptor($handlerDescriptor, $result);
@@ -142,4 +143,17 @@ private function messageHasAlreadyBeenHandled(Envelope $envelope, HandlerDescrip
142143

143144
return false;
144145
}
146+
147+
private function callHandler(callable $handler, object $message, ?Acknowledger $ack, ?HandlerArgumentsStamp $handlerArgumentsStamp): mixed
148+
{
149+
$arguments = [$message];
150+
if (null !== $ack) {
151+
$arguments[] = $ack;
152+
}
153+
if (null !== $handlerArgumentsStamp) {
154+
$arguments = [...$arguments, ...$handlerArgumentsStamp->getAdditionalArguments()];
155+
}
156+
157+
return $handler(...$arguments);
158+
}
145159
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
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\Stamp;
13+
14+
/**
15+
* @author Jáchym Toušek <enumag@gmail.com>
16+
*/
17+
final class HandlerArgumentsStamp implements NonSendableStampInterface
18+
{
19+
public function __construct(
20+
private array $additionalArguments,
21+
) {
22+
}
23+
24+
public function getAdditionalArguments()
25+
{
26+
return $this->additionalArguments;
27+
}
28+
}

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

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
use Symfony\Component\Messenger\Middleware\StackMiddleware;
2525
use Symfony\Component\Messenger\Stamp\AckStamp;
2626
use Symfony\Component\Messenger\Stamp\HandledStamp;
27+
use Symfony\Component\Messenger\Stamp\HandlerArgumentsStamp;
2728
use Symfony\Component\Messenger\Stamp\NoAutoAckStamp;
2829
use Symfony\Component\Messenger\Test\Middleware\MiddlewareTestCase;
2930
use Symfony\Component\Messenger\Tests\Fixtures\DummyMessage;
@@ -261,6 +262,40 @@ private function process(array $jobs): void
261262

262263
$this->assertSame([$message], $handler->processedMessages);
263264
}
265+
266+
public function testHandlerArgumentsStamp()
267+
{
268+
$message = new DummyMessage('Hey');
269+
$envelope = new Envelope($message);
270+
$envelope = $envelope->with(new HandlerArgumentsStamp(['additional argument']));
271+
272+
$handler = $this->createPartialMock(HandleMessageMiddlewareTestCallable::class, ['__invoke']);
273+
274+
$middleware = new HandleMessageMiddleware(new HandlersLocator([
275+
DummyMessage::class => [$handler],
276+
]));
277+
278+
$handler->expects($this->once())->method('__invoke')->with($message, 'additional argument');
279+
280+
$middleware->handle($envelope, $this->getStackMock());
281+
}
282+
283+
public function testHandlerArgumentsStampNamedArgument()
284+
{
285+
$message = new DummyMessage('Hey');
286+
$envelope = new Envelope($message);
287+
$envelope = $envelope->with(new HandlerArgumentsStamp(['namedArgument' => 'additional named argument']));
288+
289+
$handler = $this->createPartialMock(HandleMessageMiddlewareNamedArgumentTestCallable::class, ['__invoke']);
290+
291+
$middleware = new HandleMessageMiddleware(new HandlersLocator([
292+
DummyMessage::class => [$handler],
293+
]));
294+
295+
$handler->expects($this->once())->method('__invoke')->with($message, 'additional named argument');
296+
297+
$middleware->handle($envelope, $this->getStackMock());
298+
}
264299
}
265300

266301
class HandleMessageMiddlewareTestCallable
@@ -269,3 +304,10 @@ public function __invoke()
269304
{
270305
}
271306
}
307+
308+
class HandleMessageMiddlewareNamedArgumentTestCallable
309+
{
310+
public function __invoke(object $message, $namedArgument)
311+
{
312+
}
313+
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy