Skip to content

Commit 3dd8a7b

Browse files
vjikStyleCIBotviktorprogger
authored
Replace queue factory with queue providers (#222)
* Remove `@internal` from `QueueInterface` * queue provider * improve * `QueueProviderInterfaceProxy` * remove exceptions * config * Remove factory * fix tests * test `PrototypeQueueProvider` * test `FactoryQueueProvider` * test `CompositeQueueProvider` * Apply fixes from StyleCI * Improve `QueueFactoryQueueProvider` * Add `AdapterFactoryQueueProvider` * improve tests * Rename "channel-definitions" to "channels" * stubs phpdoc * phpdoc * Apply fixes from StyleCI * readme * fix cs * Update src/Command/ListenAllCommand.php Co-authored-by: Viktor Babanov <[email protected]> * Move `DEFAULT_CHANNEL_NAME` to `QueueInterface` * Apply fixes from StyleCI * Extract stubs to separate namespace * Fix `Queue` * fix exception * fix * Remove QueueFactoryQueueProvider * Fix docs * Fix config * Bugfixes * Apply fixes from StyleCI --------- Co-authored-by: StyleCI Bot <[email protected]> Co-authored-by: Viktor Babanov <[email protected]>
1 parent af0fb00 commit 3dd8a7b

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+838
-654
lines changed

README.md

Lines changed: 24 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -28,15 +28,15 @@ The package could be installed with [Composer](https://getcomposer.org):
2828
composer require yiisoft/queue
2929
```
3030

31-
## Ready for yiisoft/config
31+
## Ready for Yii Config
3232

3333
If you are using [yiisoft/config](https://github.com/yiisoft/config), you'll find out this package has some defaults
3434
in the [`common`](config/di.php) and [`params`](config/params.php) configurations saving your time. Things you should
3535
change to start working with the queue:
3636

3737
- Optionally: define default `\Yiisoft\Queue\Adapter\AdapterInterface` implementation.
38-
- And/or define channel-specific `AdapterInterface` implementations in the `channel-definitions` params key to be used
39-
with the [queue factory](#different-queue-channels).
38+
- And/or define channel-specific `AdapterInterface` implementations in the `channel` params key to be used
39+
with the [queue provider](#different-queue-channels).
4040
- Define [message handlers](docs/guide/worker.md#handler-format) in the `handlers` params key to be used with the `QueueWorker`.
4141
- Resolve other `\Yiisoft\Queue\Queue` dependencies (psr-compliant event dispatcher).
4242

@@ -159,15 +159,23 @@ $worker = new \Yiisoft\Queue\Worker\Worker(
159159

160160
## Different queue channels
161161

162-
Often we need to push to different queue channels with an only application. There is the `QueueFactory` class to make
163-
different `Queue` objects creation for different channels. With this factory channel-specific `Queue` creation is as
164-
simple as
162+
Often we need to push to different queue channels with an only application. There is the `QueueProviderInterface`
163+
interface that provides different `Queue` objects creation for different channels. With implementation of this interface
164+
channel-specific `Queue` creation is as simple as
165165

166166
```php
167-
$queue = $factory->get('channel-name');
167+
$queue = $provider->get('channel-name');
168168
```
169169

170-
The main usage strategy is with explicit definition of channel-specific adapters. Definitions are passed in
170+
Out of the box, there are four implementations of the `QueueProviderInterface`:
171+
172+
- `AdapterFactoryQueueProvider`
173+
- `PrototypeQueueProvider`
174+
- `CompositeQueueProvider`
175+
176+
### `AdapterFactoryQueueProvider`
177+
178+
Provider based on definition of channel-specific adapters. Definitions are passed in
171179
the `$definitions` constructor parameter of the factory, where keys are channel names and values are definitions
172180
for the [`Yiisoft\Factory\Factory`](https://github.com/yiisoft/factory). Below are some examples:
173181

@@ -186,19 +194,19 @@ use Yiisoft\Queue\Adapter\SynchronousAdapter;
186194

187195
For more information about a definition formats available see the [factory](https://github.com/yiisoft/factory) documentation.
188196

189-
Another queue factory usage strategy is implicit adapter creation via `withChannel()` method call. To use this approach
190-
you should pass some specific constructor parameters:
197+
### `PrototypeQueueProvider`
191198

192-
- `true` to the `$enableRuntimeChannelDefinition`
193-
- a default `AdapterInterface` implementation to the `$defaultAdapter`.
194-
195-
In this case `$factory->get('channel-name')` call will be converted
196-
to `$this->queue->withAdapter($this->defaultAdapter->withChannel($channel))`, when there is no explicit adapter definition
197-
in the `$definitions`.
199+
Queue provider that only changes the channel name of the base queue. It can be useful when your queues used the same
200+
adapter.
198201

199202
> Warning: This strategy is not recommended as it does not give you any protection against typos and mistakes
200203
> in channel names.
201204
205+
### `CompositeQueueProvider`
206+
207+
This provider allows you to combine multiple providers into one. It will try to get a queue from each provider in the
208+
order they are passed to the constructor. The first queue found will be returned.
209+
202210
## Console execution
203211

204212
The exact way of task execution depends on the adapter used. Most adapters can be run using

composer.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
"psr/log": "^2.0|^3.0",
4242
"symfony/console": "^5.4|^6.0",
4343
"yiisoft/definitions": "^1.0|^2.0|^3.0",
44+
"yiisoft/factory": "dev-strict",
4445
"yiisoft/friendly-exception": "^1.0",
4546
"yiisoft/injector": "^1.0"
4647
},
@@ -60,7 +61,8 @@
6061
},
6162
"autoload": {
6263
"psr-4": {
63-
"Yiisoft\\Queue\\": "src"
64+
"Yiisoft\\Queue\\": "src",
65+
"Yiisoft\\Queue\\Stubs\\": "stubs"
6466
}
6567
},
6668
"autoload-dev": {

config/di.php

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,16 +19,22 @@
1919
use Yiisoft\Queue\Middleware\Push\MiddlewareFactoryPush;
2020
use Yiisoft\Queue\Middleware\Push\MiddlewareFactoryPushInterface;
2121
use Yiisoft\Queue\Middleware\Push\PushMiddlewareDispatcher;
22+
use Yiisoft\Queue\Provider\AdapterFactoryQueueProvider;
23+
use Yiisoft\Queue\Provider\QueueProviderInterface;
2224
use Yiisoft\Queue\Queue;
23-
use Yiisoft\Queue\QueueFactory;
24-
use Yiisoft\Queue\QueueFactoryInterface;
2525
use Yiisoft\Queue\QueueInterface;
2626
use Yiisoft\Queue\Worker\Worker as QueueWorker;
2727
use Yiisoft\Queue\Worker\WorkerInterface;
2828

2929
/* @var array $params */
3030

3131
return [
32+
AdapterFactoryQueueProvider::class => [
33+
'__construct()' => [
34+
'definitions' => $params['yiisoft/queue']['channels'],
35+
],
36+
],
37+
QueueProviderInterface::class => AdapterFactoryQueueProvider::class,
3238
QueueWorker::class => [
3339
'class' => QueueWorker::class,
3440
'__construct()' => [$params['yiisoft/queue']['handlers']],
@@ -39,10 +45,6 @@
3945
? $container->get(SignalLoop::class)
4046
: $container->get(SimpleLoop::class);
4147
},
42-
QueueFactoryInterface::class => QueueFactory::class,
43-
QueueFactory::class => [
44-
'__construct()' => ['channelConfiguration' => $params['yiisoft/queue']['channel-definitions']],
45-
],
4648
QueueInterface::class => Queue::class,
4749
MiddlewareFactoryPushInterface::class => MiddlewareFactoryPush::class,
4850
MiddlewareFactoryConsumeInterface::class => MiddlewareFactoryConsume::class,
@@ -59,12 +61,12 @@
5961
MessageSerializerInterface::class => JsonMessageSerializer::class,
6062
RunCommand::class => [
6163
'__construct()' => [
62-
'channels' => array_keys($params['yiisoft/queue']['channel-definitions']),
64+
'channels' => array_keys($params['yiisoft/queue']['channels']),
6365
],
6466
],
6567
ListenAllCommand::class => [
6668
'__construct()' => [
67-
'channels' => array_keys($params['yiisoft/queue']['channel-definitions']),
69+
'channels' => array_keys($params['yiisoft/queue']['channels']),
6870
],
6971
],
7072
];

config/params.php

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,10 @@
77
use Yiisoft\Queue\Command\ListenCommand;
88
use Yiisoft\Queue\Command\RunCommand;
99
use Yiisoft\Queue\Debug\QueueCollector;
10-
use Yiisoft\Queue\Debug\QueueFactoryInterfaceProxy;
10+
use Yiisoft\Queue\Debug\QueueProviderInterfaceProxy;
1111
use Yiisoft\Queue\Debug\QueueWorkerInterfaceProxy;
12-
use Yiisoft\Queue\QueueFactoryInterface;
12+
use Yiisoft\Queue\Provider\QueueProviderInterface;
13+
use Yiisoft\Queue\QueueInterface;
1314
use Yiisoft\Queue\Worker\WorkerInterface;
1415

1516
return [
@@ -22,8 +23,8 @@
2223
],
2324
'yiisoft/queue' => [
2425
'handlers' => [],
25-
'channel-definitions' => [
26-
QueueFactoryInterface::DEFAULT_CHANNEL_NAME => AdapterInterface::class,
26+
'channels' => [
27+
QueueInterface::DEFAULT_CHANNEL_NAME => AdapterInterface::class,
2728
],
2829
'middlewares-push' => [],
2930
'middlewares-consume' => [],
@@ -34,7 +35,7 @@
3435
QueueCollector::class,
3536
],
3637
'trackedServices' => [
37-
QueueFactoryInterface::class => [QueueFactoryInterfaceProxy::class, QueueCollector::class],
38+
QueueProviderInterface::class => [QueueProviderInterfaceProxy::class, QueueCollector::class],
3839
WorkerInterface::class => [QueueWorkerInterfaceProxy::class, QueueCollector::class],
3940
],
4041
],

src/Adapter/SynchronousAdapter.php

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
use InvalidArgumentException;
88
use Yiisoft\Queue\Enum\JobStatus;
99
use Yiisoft\Queue\Message\MessageInterface;
10-
use Yiisoft\Queue\QueueFactory;
1110
use Yiisoft\Queue\QueueInterface;
1211
use Yiisoft\Queue\Worker\WorkerInterface;
1312
use Yiisoft\Queue\Message\IdEnvelope;
@@ -20,7 +19,7 @@ final class SynchronousAdapter implements AdapterInterface
2019
public function __construct(
2120
private WorkerInterface $worker,
2221
private QueueInterface $queue,
23-
private string $channel = QueueFactory::DEFAULT_CHANNEL_NAME,
22+
private string $channel = QueueInterface::DEFAULT_CHANNEL_NAME,
2423
) {
2524
}
2625

src/Command/ListenAllCommand.php

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
use Symfony\Component\Console\Input\InputOption;
1111
use Symfony\Component\Console\Output\OutputInterface;
1212
use Yiisoft\Queue\Cli\LoopInterface;
13-
use Yiisoft\Queue\QueueFactoryInterface;
13+
use Yiisoft\Queue\Provider\QueueProviderInterface;
1414

1515
final class ListenAllCommand extends Command
1616
{
@@ -20,8 +20,11 @@ final class ListenAllCommand extends Command
2020
'Listens all configured queues by default in case you\'re using yiisoft/config. ' .
2121
'Needs to be stopped manually.';
2222

23-
public function __construct(private QueueFactoryInterface $queueFactory, private LoopInterface $loop, private array $channels)
24-
{
23+
public function __construct(
24+
private readonly QueueProviderInterface $queueProvider,
25+
private readonly LoopInterface $loop,
26+
private readonly array $channels,
27+
) {
2528
parent::__construct();
2629
}
2730

@@ -45,7 +48,7 @@ public function configure(): void
4548
'm',
4649
InputOption::VALUE_REQUIRED,
4750
'Maximum number of messages to process in each channel before switching to another channel. ' .
48-
'Default is 0 (no limits).',
51+
'Default is 0 (no limits).',
4952
0,
5053
);
5154

@@ -57,17 +60,17 @@ protected function execute(InputInterface $input, OutputInterface $output): int
5760
$queues = [];
5861
/** @var string $channel */
5962
foreach ($input->getArgument('channel') as $channel) {
60-
$queues[] = $this->queueFactory->get($channel);
63+
$queues[] = $this->queueProvider->get($channel);
6164
}
6265

6366
while ($this->loop->canContinue()) {
6467
$hasMessages = false;
6568
foreach ($queues as $queue) {
66-
$hasMessages = $queue->run((int)$input->getOption('maximum')) > 0 || $hasMessages;
69+
$hasMessages = $queue->run((int) $input->getOption('maximum')) > 0 || $hasMessages;
6770
}
6871

6972
if (!$hasMessages) {
70-
$pauseSeconds = (int)$input->getOption('pause');
73+
$pauseSeconds = (int) $input->getOption('pause');
7174
if ($pauseSeconds < 0) {
7275
$pauseSeconds = 1;
7376
}

src/Command/ListenCommand.php

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,17 @@
88
use Symfony\Component\Console\Input\InputArgument;
99
use Symfony\Component\Console\Input\InputInterface;
1010
use Symfony\Component\Console\Output\OutputInterface;
11-
use Yiisoft\Queue\QueueFactory;
12-
use Yiisoft\Queue\QueueFactoryInterface;
11+
use Yiisoft\Queue\Provider\QueueProviderInterface;
12+
use Yiisoft\Queue\QueueInterface;
1313

1414
final class ListenCommand extends Command
1515
{
1616
protected static $defaultName = 'queue:listen';
1717
protected static $defaultDescription = 'Listens the queue and executes messages as they come. Needs to be stopped manually.';
1818

19-
public function __construct(private QueueFactoryInterface $queueFactory)
20-
{
19+
public function __construct(
20+
private readonly QueueProviderInterface $queueProvider
21+
) {
2122
parent::__construct();
2223
}
2324

@@ -27,13 +28,13 @@ public function configure(): void
2728
'channel',
2829
InputArgument::OPTIONAL,
2930
'Queue channel name to connect to',
30-
QueueFactory::DEFAULT_CHANNEL_NAME
31+
QueueInterface::DEFAULT_CHANNEL_NAME,
3132
);
3233
}
3334

3435
protected function execute(InputInterface $input, OutputInterface $output): int
3536
{
36-
$this->queueFactory
37+
$this->queueProvider
3738
->get($input->getArgument('channel'))
3839
->listen();
3940

src/Command/RunCommand.php

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,18 @@
99
use Symfony\Component\Console\Input\InputInterface;
1010
use Symfony\Component\Console\Input\InputOption;
1111
use Symfony\Component\Console\Output\OutputInterface;
12-
use Yiisoft\Queue\QueueFactoryInterface;
12+
use Yiisoft\Queue\Provider\QueueProviderInterface;
1313

1414
final class RunCommand extends Command
1515
{
1616
protected static $defaultName = 'queue:run';
1717
protected static $defaultDescription = 'Runs all the existing messages in the given queues. ' .
1818
'Exits once messages are over.';
1919

20-
public function __construct(private QueueFactoryInterface $queueFactory, private array $channels)
21-
{
20+
public function __construct(
21+
private readonly QueueProviderInterface $queueProvider,
22+
private readonly array $channels,
23+
) {
2224
parent::__construct();
2325
}
2426

@@ -45,7 +47,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int
4547
/** @var string $channel */
4648
foreach ($input->getArgument('channel') as $channel) {
4749
$output->write("Processing channel $channel... ");
48-
$count = $this->queueFactory
50+
$count = $this->queueProvider
4951
->get($channel)
5052
->run((int)$input->getOption('maximum'));
5153

src/Debug/QueueFactoryInterfaceProxy.php

Lines changed: 0 additions & 24 deletions
This file was deleted.
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Yiisoft\Queue\Debug;
6+
7+
use Yiisoft\Queue\Provider\QueueProviderInterface;
8+
use Yiisoft\Queue\QueueInterface;
9+
10+
final class QueueProviderInterfaceProxy implements QueueProviderInterface
11+
{
12+
public function __construct(
13+
private readonly QueueProviderInterface $queueProvider,
14+
private readonly QueueCollector $collector,
15+
) {
16+
}
17+
18+
public function get(string $channel): QueueInterface
19+
{
20+
$queue = $this->queueProvider->get($channel);
21+
return new QueueDecorator($queue, $this->collector);
22+
}
23+
24+
public function has(string $channel): bool
25+
{
26+
return $this->queueProvider->has($channel);
27+
}
28+
}

src/Exception/AdapterConfiguration/AdapterNotConfiguredException.php

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

77
use RuntimeException;
88
use Yiisoft\FriendlyException\FriendlyExceptionInterface;
9+
use Yiisoft\Queue\Provider\QueueProviderInterface;
910
use Yiisoft\Queue\Queue;
10-
use Yiisoft\Queue\QueueFactory;
1111

1212
class AdapterNotConfiguredException extends RuntimeException implements FriendlyExceptionInterface
1313
{
@@ -21,7 +21,7 @@ public function getName(): string
2121
public function getSolution(): ?string
2222
{
2323
$queueClass = Queue::class;
24-
$factoryClass = QueueFactory::class;
24+
$queueProviderInterface = QueueProviderInterface::class;
2525

2626
return <<<SOLUTION
2727
Adapter property must be set in the Queue object before you can use it.
@@ -32,7 +32,7 @@ public function getSolution(): ?string
3232
References:
3333
- $queueClass::\$adapter
3434
- $queueClass::withAdapter()
35-
- $factoryClass::get()
35+
- $queueProviderInterface
3636
SOLUTION;
3737
}
3838
}

0 commit comments

Comments
 (0)