Skip to content

Commit 59531a2

Browse files
committed
Move injector invocation into CallableFactory
1 parent e11d8a0 commit 59531a2

17 files changed

Lines changed: 65 additions & 91 deletions

docs/guide/en/configuration-manual.md

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ use Psr\Container\ContainerInterface;
1717
use Psr\Log\NullLogger;
1818
use Yiisoft\Queue\Cli\SimpleLoop;
1919
use Yiisoft\Queue\Message\Handler\HandlerResolver;
20-
use Yiisoft\Queue\Middleware\CallableFactory;
2120
use Yiisoft\Queue\Middleware\Consume\ConsumeMiddlewareDispatcher;
2221
use Yiisoft\Queue\Middleware\Consume\ConsumeMiddlewareFactory;
2322
use Yiisoft\Queue\Middleware\FailureHandling\FailureMiddlewareDispatcher;
@@ -39,20 +38,18 @@ $handlers = [
3938
DownloadFileMessage::TYPE => [FileDownloader::class, 'handle'],
4039
];
4140

42-
$callableFactory = new CallableFactory($container);
43-
4441
// Create middleware dispatchers
4542
$consumeMiddlewareDispatcher = new ConsumeMiddlewareDispatcher(
46-
new ConsumeMiddlewareFactory($container, $callableFactory),
43+
new ConsumeMiddlewareFactory($container),
4744
);
4845

4946
$failureMiddlewareDispatcher = new FailureMiddlewareDispatcher(
50-
new FailureMiddlewareFactory($container, $callableFactory),
47+
new FailureMiddlewareFactory($container),
5148
[],
5249
);
5350

5451
$pushMiddlewareConfig = new PushMiddlewareConfig(
55-
new PushMiddlewareFactory($container, $callableFactory),
52+
new PushMiddlewareFactory($container),
5653
);
5754

5855
// Create worker

src/Message/Handler/HandlerResolver.php

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,6 @@
66

77
use Psr\Container\ContainerExceptionInterface;
88
use Psr\Container\ContainerInterface;
9-
use Yiisoft\Injector\Injector;
10-
use Yiisoft\Queue\Message\MessageInterface;
119
use Yiisoft\Queue\Middleware\CallableFactory;
1210
use Yiisoft\Queue\Middleware\InvalidCallableConfigurationException;
1311

@@ -27,7 +25,6 @@ final class HandlerResolver
2725
*/
2826
private array $cache = [];
2927

30-
private readonly Injector $injector;
3128
private readonly CallableFactory $callableFactory;
3229

3330
/**
@@ -43,8 +40,7 @@ public function __construct(
4340
private readonly ContainerInterface $container,
4441
?ContainerInterface $callableDependencyContainer = null,
4542
) {
46-
$this->injector = new Injector($callableDependencyContainer ?? $this->container);
47-
$this->callableFactory = new CallableFactory($this->container);
43+
$this->callableFactory = new CallableFactory($this->container, $callableDependencyContainer);
4844
}
4945

5046
/**
@@ -136,10 +132,6 @@ private function createCallableHandler(string $messageType, mixed $definition):
136132
throw new InvalidHandlerConfigurationException($messageType, $exception->getMessage(), $exception);
137133
}
138134

139-
$callable = function (MessageInterface $message) use ($callable): void {
140-
$this->injector->invoke($callable, [$message]);
141-
};
142-
143135
return new CallableHandler($callable);
144136
}
145137
}

src/Middleware/CallableFactory.php

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,30 +8,50 @@
88
use Psr\Container\ContainerInterface;
99
use ReflectionException;
1010
use ReflectionMethod;
11+
use Yiisoft\Injector\Injector;
1112

1213
use function is_array;
1314
use function is_callable;
1415
use function is_object;
1516
use function is_string;
1617

1718
/**
18-
* @internal Create real callable listener from configuration.
19+
* @internal Create real callable listener from configuration, ready to be invoked with dependency injection.
1920
*/
2021
final class CallableFactory
2122
{
23+
private readonly Injector $injector;
24+
2225
public function __construct(
2326
private readonly ContainerInterface $container,
24-
) {}
27+
?ContainerInterface $dependencyContainer = null,
28+
) {
29+
$this->injector = new Injector($dependencyContainer ?? $container);
30+
}
2531

2632
/**
27-
* Create a real callable listener from definition.
33+
* Create a real callable listener from definition. Calling the returned callable invokes the resolved listener,
34+
* injecting its dependencies by type hinting.
2835
*
2936
* @param mixed $definition Definition to create listener from.
3037
*
3138
* @throws InvalidCallableConfigurationException Failed to create listener.
3239
* @throws ContainerExceptionInterface Error while retrieving the entry from container.
40+
*
41+
* @psalm-return callable(mixed...): mixed
3342
*/
3443
public function create(mixed $definition): callable
44+
{
45+
$callable = $this->resolve($definition);
46+
47+
return fn(mixed ...$params): mixed => $this->injector->invoke($callable, $params);
48+
}
49+
50+
/**
51+
* @throws InvalidCallableConfigurationException Failed to resolve listener.
52+
* @throws ContainerExceptionInterface Error while retrieving the entry from container.
53+
*/
54+
private function resolve(mixed $definition): callable
3555
{
3656
if ($definition === null) {
3757
throw new InvalidCallableConfigurationException();

src/Middleware/Consume/ConsumeMiddlewareFactory.php

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@
44

55
namespace Yiisoft\Queue\Middleware\Consume;
66

7-
use Psr\Container\ContainerInterface;
8-
use Yiisoft\Injector\Injector;
97
use Yiisoft\Queue\Middleware\InvalidMiddlewareDefinitionException;
108
use Yiisoft\Queue\Middleware\MiddlewareFactory;
119

@@ -60,20 +58,17 @@ protected function getInterfaceName(): string
6058

6159
protected function wrapMiddleware(callable $callback): ConsumeMiddlewareInterface
6260
{
63-
$container = $this->container;
64-
return new class ($callback, $container) implements ConsumeMiddlewareInterface {
61+
return new class ($callback) implements ConsumeMiddlewareInterface {
6562
private $callback;
6663

67-
public function __construct(
68-
callable $callback,
69-
private readonly ContainerInterface $container,
70-
) {
64+
public function __construct(callable $callback)
65+
{
7166
$this->callback = $callback;
7267
}
7368

7469
public function processConsume(ConsumeRequest $request, ConsumeHandlerInterface $handler): ConsumeRequest
7570
{
76-
$response = (new Injector($this->container))->invoke($this->callback, [$request, $handler]);
71+
$response = ($this->callback)($request, $handler);
7772
if ($response instanceof ConsumeRequest) {
7873
return $response;
7974
}

src/Middleware/FailureHandling/FailureMiddlewareFactory.php

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,7 @@
55
namespace Yiisoft\Queue\Middleware\FailureHandling;
66

77
use Psr\Container\ContainerExceptionInterface;
8-
use Psr\Container\ContainerInterface;
98
use Psr\Container\NotFoundExceptionInterface;
10-
use Yiisoft\Injector\Injector;
119
use Yiisoft\Queue\Middleware\InvalidMiddlewareDefinitionException;
1210
use Yiisoft\Queue\Middleware\MiddlewareFactory;
1311

@@ -64,20 +62,17 @@ protected function getInterfaceName(): string
6462

6563
protected function wrapMiddleware(callable $callback): FailureMiddlewareInterface
6664
{
67-
$container = $this->container;
68-
return new class ($callback, $container) implements FailureMiddlewareInterface {
65+
return new class ($callback) implements FailureMiddlewareInterface {
6966
private $callback;
7067

71-
public function __construct(
72-
callable $callback,
73-
private readonly ContainerInterface $container,
74-
) {
68+
public function __construct(callable $callback)
69+
{
7570
$this->callback = $callback;
7671
}
7772

7873
public function processFailure(FailureHandlingRequest $request, FailureHandlerInterface $handler): FailureHandlingRequest
7974
{
80-
$response = (new Injector($this->container))->invoke($this->callback, [$request, $handler]);
75+
$response = ($this->callback)($request, $handler);
8176
if ($response instanceof FailureHandlingRequest) {
8277
return $response;
8378
}

src/Middleware/MiddlewareFactory.php

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,19 @@
2121
*/
2222
abstract class MiddlewareFactory
2323
{
24+
private readonly CallableFactory $callableFactory;
25+
26+
/**
27+
* @param ContainerInterface $container Container used to resolve middleware.
28+
* @param ContainerInterface|null $callableDependencyContainer Container used to resolve callable middleware
29+
* dependencies. If not set, the main container is used.
30+
*/
2431
public function __construct(
2532
protected readonly ContainerInterface $container,
26-
private readonly CallableFactory $callableFactory,
27-
) {}
33+
?ContainerInterface $callableDependencyContainer = null,
34+
) {
35+
$this->callableFactory = new CallableFactory($container, $callableDependencyContainer);
36+
}
2837

2938
/**
3039
* @param callable|array|string $definition Middleware definition in one of the following formats:

src/Middleware/Push/PushMiddlewareFactory.php

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@
44

55
namespace Yiisoft\Queue\Middleware\Push;
66

7-
use Psr\Container\ContainerInterface;
8-
use Yiisoft\Injector\Injector;
97
use Yiisoft\Queue\Message\MessageInterface;
108
use Yiisoft\Queue\Middleware\InvalidMiddlewareDefinitionException;
119
use Yiisoft\Queue\Middleware\MiddlewareFactory;
@@ -68,19 +66,17 @@ protected function getInterfaceName(): string
6866

6967
protected function wrapMiddleware(callable $callback): PushMiddlewareInterface
7068
{
71-
return new class ($callback, $this->container) implements PushMiddlewareInterface {
69+
return new class ($callback) implements PushMiddlewareInterface {
7270
private $callback;
7371

74-
public function __construct(
75-
callable $callback,
76-
private readonly ContainerInterface $container,
77-
) {
72+
public function __construct(callable $callback)
73+
{
7874
$this->callback = $callback;
7975
}
8076

8177
public function processPush(MessageInterface $message, PushHandlerInterface $handler): MessageInterface
8278
{
83-
$response = (new Injector($this->container))->invoke($this->callback, [$message, $handler]);
79+
$response = ($this->callback)($message, $handler);
8480
if ($response instanceof MessageInterface) {
8581
return $response;
8682
}

tests/Benchmark/QueueBench.php

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
use Yiisoft\Queue\Message\GenericMessage;
1313
use Yiisoft\Queue\Message\Serializer\JsonMessageEncoder;
1414
use Yiisoft\Queue\Message\Serializer\MessageSerializer;
15-
use Yiisoft\Queue\Middleware\CallableFactory;
1615
use Yiisoft\Queue\Middleware\Consume\ConsumeMiddlewareDispatcher;
1716
use Yiisoft\Queue\Middleware\Consume\ConsumeMiddlewareFactory;
1817
use Yiisoft\Queue\Middleware\FailureHandling\FailureEnvelope;
@@ -39,14 +38,13 @@ final class QueueBench
3938
public function __construct()
4039
{
4140
$container = new SimpleContainer();
42-
$callableFactory = new CallableFactory($container);
4341
$logger = new NullLogger();
4442

4543
$worker = new Worker(
4644
$logger,
47-
new ConsumeMiddlewareDispatcher(new ConsumeMiddlewareFactory($container, $callableFactory)),
45+
new ConsumeMiddlewareDispatcher(new ConsumeMiddlewareFactory($container)),
4846
new FailureMiddlewareDispatcher(
49-
new FailureMiddlewareFactory($container, $callableFactory),
47+
new FailureMiddlewareFactory($container),
5048
[],
5149
),
5250
new HandlerResolver(
@@ -61,7 +59,7 @@ public function __construct()
6159

6260
$this->producer = new AsyncQueueProducer(
6361
$logger,
64-
new PushMiddlewareConfig(new PushMiddlewareFactory($container, $callableFactory)),
62+
new PushMiddlewareConfig(new PushMiddlewareFactory($container)),
6563
$this->adapter,
6664
);
6765
$this->consumer = new QueueConsumer($worker, new SimpleLoop(0), $logger, $this->adapter);

tests/Integration/MiddlewareTest.php

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
use Yiisoft\Test\Support\Log\SimpleLogger;
1313
use Yiisoft\Queue\Message\GenericMessage;
1414
use Yiisoft\Queue\Message\MessageInterface;
15-
use Yiisoft\Queue\Middleware\CallableFactory;
1615
use Yiisoft\Queue\Middleware\Consume\ConsumeMiddlewareDispatcher;
1716
use Yiisoft\Queue\Middleware\Consume\ConsumeMiddlewareFactory;
1817
use Yiisoft\Queue\Middleware\FailureHandling\FailureFinalHandler;
@@ -47,9 +46,6 @@ public function testFullStackPush(): void
4746
$pushMiddlewareConfig = new PushMiddlewareConfig(
4847
new PushMiddlewareFactory(
4948
$this->createMock(ContainerInterface::class),
50-
new CallableFactory(
51-
$this->createMock(ContainerInterface::class),
52-
),
5349
),
5450
[
5551
new TestMiddleware('common 1'),
@@ -85,21 +81,17 @@ public function testFullStackConsume(): void
8581
'common 2',
8682
];
8783
$container = new SimpleContainer();
88-
$callableFactory = new CallableFactory($container);
8984

9085
$consumeMiddlewareDispatcher = new ConsumeMiddlewareDispatcher(
9186
new ConsumeMiddlewareFactory(
9287
$this->createMock(ContainerInterface::class),
93-
new CallableFactory(
94-
$this->createMock(ContainerInterface::class),
95-
),
9688
),
9789
new TestMiddleware('common 1'),
9890
new TestMiddleware('common 2'),
9991
);
10092

10193
$failureMiddlewareDispatcher = new FailureMiddlewareDispatcher(
102-
new FailureMiddlewareFactory($container, $callableFactory),
94+
new FailureMiddlewareFactory($container),
10395
[],
10496
);
10597

@@ -125,7 +117,6 @@ public function testFullStackFailure(): void
125117
$queueCallback = static fn(MessageInterface $message): MessageInterface => $message;
126118
$queue = $this->createMock(QueueProducerInterface::class);
127119
$container = new SimpleContainer([SendAgainMiddleware::class => new SendAgainMiddleware('test-container', 1, $queue)]);
128-
$callableFactory = new CallableFactory($container);
129120

130121
$queue->expects(self::exactly(7))->method('push')->willReturnCallback($queueCallback);
131122
$queue->method('getQueueName')->willReturn('simple');
@@ -154,7 +145,7 @@ public function testFullStackFailure(): void
154145
],
155146
];
156147
$dispatcher = new FailureMiddlewareDispatcher(
157-
new FailureMiddlewareFactory($container, $callableFactory),
148+
new FailureMiddlewareFactory($container),
158149
$middlewares,
159150
);
160151

tests/TestCase.php

Lines changed: 3 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
use Yiisoft\Queue\Cli\LoopInterface;
1515
use Yiisoft\Queue\Cli\SimpleLoop;
1616
use Yiisoft\Queue\DefaultQueue;
17-
use Yiisoft\Queue\Middleware\CallableFactory;
1817
use Yiisoft\Queue\Middleware\Consume\ConsumeMiddlewareDispatcher;
1918
use Yiisoft\Queue\Middleware\Consume\ConsumeMiddlewareFactory;
2019
use Yiisoft\Queue\Middleware\FailureHandling\FailureMiddlewareDispatcher;
@@ -160,30 +159,21 @@ protected function getMessageHandlers(): array
160159
protected function getPushMiddlewareConfig(): PushMiddlewareConfig
161160
{
162161
return new PushMiddlewareConfig(
163-
new PushMiddlewareFactory(
164-
$this->getContainer(),
165-
new CallableFactory($this->getContainer()),
166-
),
162+
new PushMiddlewareFactory($this->getContainer()),
167163
);
168164
}
169165

170166
protected function getConsumeMiddlewareDispatcher(): ConsumeMiddlewareDispatcher
171167
{
172168
return new ConsumeMiddlewareDispatcher(
173-
new ConsumeMiddlewareFactory(
174-
$this->getContainer(),
175-
new CallableFactory($this->getContainer()),
176-
),
169+
new ConsumeMiddlewareFactory($this->getContainer()),
177170
);
178171
}
179172

180173
protected function getFailureMiddlewareDispatcher(): FailureMiddlewareDispatcher
181174
{
182175
return new FailureMiddlewareDispatcher(
183-
new FailureMiddlewareFactory(
184-
$this->getContainer(),
185-
new CallableFactory($this->getContainer()),
186-
),
176+
new FailureMiddlewareFactory($this->getContainer()),
187177
[],
188178
);
189179
}

0 commit comments

Comments
 (0)