Skip to content

Commit dd30d79

Browse files
committed
Rewrite channels doc
1 parent dd3ae30 commit dd30d79

File tree

1 file changed

+118
-89
lines changed

1 file changed

+118
-89
lines changed

docs/guide/en/channels.md

Lines changed: 118 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -4,80 +4,158 @@ A *queue channel* is a named queue configuration.
44

55
In practice, a channel is a string (for example, `yii-queue`, `emails`, `critical`) that selects which queue backend (adapter) messages are pushed to and which worker consumes them.
66

7+
At a high level:
8+
9+
- You configure one or more channels.
10+
- When producing messages, you either:
11+
- use `QueueInterface` directly (single/default channel), or
12+
- use `QueueProviderInterface` to get a queue for a specific channel.
13+
- When consuming messages, you run a worker command for a channel (or a set of channels).
14+
715
Having multiple channels is useful when you want to separate workloads, for example:
816

917
- **Different priorities**: `critical` vs `low`.
1018
- **Different message types**: `emails`, `reports`, `webhooks`.
11-
- **Different backends / connections**: fast Redis queue for short jobs and a different backend for long-running jobs.
19+
- **Different backends / connections**: fast Redis queue for short jobs and RabbitMQ backend for long-running jobs or inter-app communication.
1220

1321
The default channel name is `Yiisoft\Queue\QueueInterface::DEFAULT_CHANNEL` (`yii-queue`).
1422

15-
## How channels are used in the code
23+
## Quick start (yiisoft/config)
1624

17-
- A channel name is passed to `Yiisoft\Queue\Provider\QueueProviderInterface::get($channel)`.
18-
- The provider returns a `Yiisoft\Queue\QueueInterface` instance bound to that channel.
19-
- Internally, the provider creates an adapter instance and calls `AdapterInterface::withChannel($channel)`.
25+
When using [yiisoft/config](https://github.com/yiisoft/config), channel configuration is stored in params under `yiisoft/queue.channels`.
2026

21-
In other words, a channel is the key that lets the application select a particular adapter instance/configuration.
27+
### 1. Start with a single channel (default)
28+
29+
If you use only a single channel, you can inject `QueueInterface` directly.
2230

23-
## Choosing a channel at runtime
31+
#### 1.1 Configure an Adapter
2432

25-
### In CLI
33+
Adapter is what actually sends messages to a queue broker.
2634

27-
These built-in commands accept channel names:
35+
Minimal DI configuration example:
2836

29-
- `queue:listen [channel]` listens to a single channel (defaults to `yii-queue`).
30-
- `queue:run [channel1 [channel2 [...]]]` processes existing messages and exits.
31-
- `queue:listen-all [channel1 [channel2 [...]]]` iterates over multiple channels (meant mostly for development).
37+
```php
38+
use Yiisoft\Queue\Adapter\SynchronousAdapter;
39+
use Yiisoft\Queue\Adapter\AdapterInterface;
40+
41+
return [
42+
AdapterInterface::class => SynchronousAdapter::class,
43+
];
44+
```
45+
> `SynchronousAdapter` is for learning/testing only. For production, install a real adapter, see adapter list: [adapter-list](adapter-list.md).
46+
47+
#### 1.2. Configure a default channel
48+
49+
When you are using `yiisoft/config` and the default configs from this package are loaded, the default channel is already present in params (so you don't need to add anything). The snippet below shows what is shipped by default in [config/params.php](../../../config/params.php):
50+
51+
```php
52+
use Yiisoft\Queue\Adapter\AdapterInterface;
53+
use Yiisoft\Queue\QueueInterface;
54+
55+
return [
56+
'yiisoft/queue' => [
57+
'channels' => [
58+
QueueInterface::DEFAULT_CHANNEL => AdapterInterface::class,
59+
],
60+
],
61+
];
62+
```
3263

33-
Examples:
64+
Pushing a message via DI:
3465

35-
```sh
36-
yii queue:listen emails
37-
yii queue:run critical emails --maximum=100
38-
yii queue:listen-all critical emails --pause=1 --maximum=500
66+
```php
67+
use Yiisoft\Queue\QueueInterface;
68+
use Yiisoft\Queue\Message\Message;
69+
70+
final readonly class SendWelcomeEmail
71+
{
72+
public function __construct(private QueueInterface $queue)
73+
{
74+
}
75+
76+
public function run(string $email): void
77+
{
78+
$this->queue->push(new Message('send-email', ['to' => $email]));
79+
}
80+
}
3981
```
4082

41-
### In PHP code
83+
### 2. Multiple channels
4284

43-
When you have a `QueueProviderInterface`, request a queue by channel name:
85+
Add more channels to the `params.php`:
4486

4587
```php
46-
/** @var \Yiisoft\Queue\Provider\QueueProviderInterface $provider */
88+
use Yiisoft\Queue\QueueInterface;
4789

48-
$emailsQueue = $provider->get('emails');
49-
$emailsQueue->push(new \Yiisoft\Queue\Message\Message('send-email', ['to' => 'user@example.com']));
90+
return [
91+
'yiisoft/queue' => [
92+
'channels' => [
93+
QueueInterface::DEFAULT_CHANNEL => \Yiisoft\Queue\Adapter\AdapterInterface::class,
94+
'critical' => \Yiisoft\Queue\Adapter\AdapterInterface::class,
95+
'emails' => \Yiisoft\Queue\Adapter\AdapterInterface::class,
96+
],
97+
],
98+
];
5099
```
51100

52-
You can also check if a channel exists before trying to get it:
101+
If you have multiple channels, inject `QueueProviderInterface` and call `get('channel-name')`.
53102

54103
```php
55-
if ($provider->has('emails')) {
56-
$emailsQueue = $provider->get('emails');
104+
use Yiisoft\Queue\Provider\QueueProviderInterface;
105+
use Yiisoft\Queue\Message\Message;
106+
107+
final readonly class SendTransactionalEmail
108+
{
109+
public function __construct(private QueueProviderInterface $queueProvider)
110+
{
111+
}
112+
113+
public function run(string $email): void
114+
{
115+
$this->queueProvider
116+
->get('emails')
117+
->push(new Message('send-email', ['to' => $email]));
118+
}
57119
}
58120
```
59121

60122
`QueueProviderInterface` accepts both strings and `BackedEnum` values (they are normalized to a string channel name).
61123

124+
## Running workers (CLI)
125+
126+
To consume messages you run console commands such as `queue:run`, `queue:listen`, and `queue:listen-all`.
127+
See [Console commands](console-commands.md) for details.
128+
129+
## Advanced
130+
131+
### How channels are used in the code
132+
133+
- A channel name is passed to `Yiisoft\Queue\Provider\QueueProviderInterface::get($channel)`.
134+
- The provider returns a `Yiisoft\Queue\QueueInterface` instance that uses an adapter configured for that channel.
135+
- Internally, the provider creates an adapter instance and calls `AdapterInterface::withChannel($channel)`.
136+
137+
In other words, a channel is the key that lets the application select a particular adapter instance/configuration.
138+
139+
`QueueInterface::getChannel()` is available for introspection and higher-level logic (for example, selecting middleware pipelines per channel). The channel itself is stored in the adapter and `Queue` proxies it.
140+
141+
### Providers
142+
62143
`QueueProviderInterface::get()` may throw:
63144

64145
- `Yiisoft\Queue\Provider\ChannelNotFoundException`
65146
- `Yiisoft\Queue\Provider\InvalidQueueConfigException`
66147
- `Yiisoft\Queue\Provider\QueueProviderException`
67148

68-
## Providers
69-
70-
`QueueProviderInterface` is the component responsible for returning a `QueueInterface` instance bound to a particular channel.
71-
72149
Out of the box, this package provides three implementations:
73150

74151
- `Yiisoft\Queue\Provider\AdapterFactoryQueueProvider`
75152
- `Yiisoft\Queue\Provider\PrototypeQueueProvider`
76153
- `Yiisoft\Queue\Provider\CompositeQueueProvider`
77154

78-
### `AdapterFactoryQueueProvider`
155+
#### `AdapterFactoryQueueProvider` (default)
79156

80-
This provider creates channel-specific `QueueInterface` instances based on adapter definitions.
157+
`AdapterFactoryQueueProvider` is used by default when you use `yiisoft/config`.
158+
It creates `QueueInterface` instances based on adapter definitions indexed by channel name.
81159

82160
It uses [`yiisoft/factory`](https://github.com/yiisoft/factory) to resolve adapter definitions.
83161

@@ -86,7 +164,7 @@ This approach is recommended when you want:
86164
- Separate configuration per channel.
87165
- Stronger validation (unknown channels are not silently accepted).
88166

89-
### `PrototypeQueueProvider`
167+
#### `PrototypeQueueProvider`
90168

91169
This provider always returns a queue by taking a base queue + base adapter and only changing the channel name.
92170

@@ -105,7 +183,7 @@ $queueForEmails = $provider->get('emails');
105183
$queueForCritical = $provider->get('critical');
106184
```
107185

108-
### `CompositeQueueProvider`
186+
#### `CompositeQueueProvider`
109187

110188
This provider combines multiple providers into one.
111189

@@ -125,74 +203,25 @@ $provider = new CompositeQueueProvider(
125203
$queue = $provider->get('emails');
126204
```
127205

128-
## Configuration with yiisoft/config
129-
130-
When using [yiisoft/config](https://github.com/yiisoft/config), channel configuration is stored in params under `yiisoft/queue.channels`.
131-
132-
By default, `QueueProviderInterface` is bound to `AdapterFactoryQueueProvider`.
133-
That makes `yiisoft/queue.channels` a strict channel registry:
134-
135-
- `QueueProviderInterface::has($channel)` checks whether the channel exists in definitions.
136-
- `QueueProviderInterface::get($channel)` throws `ChannelNotFoundException` for unknown channels.
137-
138-
The same channel list is used by `queue:run` and `queue:listen-all` as the default set of channels to process.
139-
140-
It is a map:
141-
142-
- key: channel name
143-
- value: adapter definition that should be resolved for that channel
144-
145-
Minimal example (single channel):
146-
147-
```php
148-
use Yiisoft\Queue\Adapter\AdapterInterface;
149-
use Yiisoft\Queue\QueueInterface;
150-
151-
return [
152-
'yiisoft/queue' => [
153-
'channels' => [
154-
QueueInterface::DEFAULT_CHANNEL => AdapterInterface::class,
155-
],
156-
],
157-
];
158-
```
159-
160-
Multiple channels example:
161-
162-
```php
163-
use Yiisoft\Queue\QueueInterface;
164-
165-
return [
166-
'yiisoft/queue' => [
167-
'channels' => [
168-
QueueInterface::DEFAULT_CHANNEL => \Yiisoft\Queue\Adapter\AdapterInterface::class,
169-
'critical' => \Yiisoft\Queue\Adapter\AdapterInterface::class,
170-
'emails' => \Yiisoft\Queue\Adapter\AdapterInterface::class,
171-
],
172-
],
173-
];
174-
```
175-
176-
The exact adapter definitions depend on which queue adapter package you use (Redis, AMQP, etc.).
177-
178-
When using the default DI config from this package, the configured channel names are also used as the default channel list for `queue:run` and `queue:listen-all`.
179-
180-
## Manual configuration (without yiisoft/config)
206+
### Manual configuration (without yiisoft/config)
181207

182208
For multiple channels without `yiisoft/config`, you can create a provider manually.
183209

184210
`AdapterFactoryQueueProvider` accepts adapter definitions indexed by channel names and returns a `QueueInterface` for a channel on demand:
185211

212+
> In this example, `$worker`, `$queue` and `$container` are assumed to be created already.
213+
> See [Manual configuration](configuration-manual.md) for a full runnable setup.
214+
186215
```php
187216
use Yiisoft\Queue\Provider\AdapterFactoryQueueProvider;
188217
use Yiisoft\Queue\Adapter\SynchronousAdapter;
189218

190219
$definitions = [
191-
'channel1' => new SynchronousAdapter($worker, $queue),
192-
'channel2' => static fn (SynchronousAdapter $adapter) => $adapter->withChannel('channel2'),
220+
'channel1' => new SynchronousAdapter($worker, $queue, 'channel1'),
221+
'channel2' => new SynchronousAdapter($worker, $queue, 'channel2'),
193222
'channel3' => [
194223
'class' => SynchronousAdapter::class,
195-
'__constructor' => ['channel' => 'channel3'],
224+
'__construct()' => ['channel' => 'channel3'],
196225
],
197226
];
198227

0 commit comments

Comments
 (0)