Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
194 changes: 106 additions & 88 deletions README.md

Large diffs are not rendered by default.

34 changes: 31 additions & 3 deletions docs/guide/en/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,38 @@

An extension for running tasks asynchronously via queues.

## Guides and concept explanations
## Getting started

- [Configuration with yiisoft/config](configuration-with-config.md)
- [Manual configuration](configuration-manual.md)

- [Usage basics](usage.md)
- [Migrating from `yii2-queue`](migrating-from-yii2-queue.md)
- [Errors and retryable jobs](error-handling.md)
- [Workers](worker.md)
- [Console commands](console-commands.md)

## Adapters

- [Adapter list](adapter-list.md)
- [Synchronous adapter](adapter-sync.md)

## Core concepts

- [Queue channels](channels.md)
- [Message handler](message-handler.md)
- [Envelopes](envelopes.md)
- [Loops](loops.md)

## Interoperability

- [Producing messages from external systems](producing-messages-from-external-systems.md)

## Reliability and visibility

- [Errors and retryable jobs](error-handling.md)
- [Failure handling pipeline](failure-handling-pipeline.md)
- [Job status](job-status.md)
- [Yii Debug integration](debug-integration.md)

## Migration from Yii2

- [Migrating from `yii2-queue`](migrating-from-yii2-queue.md)
118 changes: 118 additions & 0 deletions docs/guide/en/channels.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
# Queue channels

A *queue channel* is a named queue configuration.

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.

Having multiple channels is useful when you want to separate workloads, for example:

- **Different priorities**: `critical` vs `low`.
- **Different message types**: `emails`, `reports`, `webhooks`.
- **Different backends / connections**: fast Redis queue for short jobs and a different backend for long-running jobs.

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

## How channels are used in the code

- A channel name is passed to `Yiisoft\Queue\Provider\QueueProviderInterface::get($channel)`.
- The provider returns a `Yiisoft\Queue\QueueInterface` instance bound to that channel.
- Internally, the provider creates an adapter instance and calls `AdapterInterface::withChannel($channel)`.

In other words, a channel is the key that lets the application select a particular adapter instance/configuration.

## Choosing a channel at runtime

### In CLI

These built-in commands accept channel names:

- `queue:listen [channel]` listens to a single channel (defaults to `yii-queue`).
- `queue:run [channel1 [channel2 [...]]]` processes existing messages and exits.
- `queue:listen-all [channel1 [channel2 [...]]]` iterates over multiple channels (meant mostly for development).

Examples:

```sh
yii queue:listen emails
yii queue:run critical emails --maximum=100
yii queue:listen-all critical emails --pause=1 --maximum=500
```

### In PHP code

When you have a `QueueProviderInterface`, request a queue by channel name:

```php
/** @var \Yiisoft\Queue\Provider\QueueProviderInterface $provider */

$emailsQueue = $provider->get('emails');
$emailsQueue->push(new \Yiisoft\Queue\Message\Message('send-email', ['to' => 'user@example.com']));
```

## Configuration with yiisoft/config

When using [yiisoft/config](https://github.com/yiisoft/config), channel configuration is stored in params under `yiisoft/queue.channels`.

It is a map:

- key: channel name
- value: adapter definition that should be resolved for that channel

Minimal example (single channel):

```php
use Yiisoft\Queue\Adapter\AdapterInterface;
use Yiisoft\Queue\QueueInterface;

return [
'yiisoft/queue' => [
'channels' => [
QueueInterface::DEFAULT_CHANNEL => AdapterInterface::class,
],
],
];
```

Multiple channels example:

```php
use Yiisoft\Queue\QueueInterface;

return [
'yiisoft/queue' => [
'channels' => [
QueueInterface::DEFAULT_CHANNEL => \Yiisoft\Queue\Adapter\AdapterInterface::class,
'critical' => \Yiisoft\Queue\Adapter\AdapterInterface::class,
'emails' => \Yiisoft\Queue\Adapter\AdapterInterface::class,
],
],
];
```

The exact adapter definitions depend on which queue adapter package you use (Redis, AMQP, etc.).

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`.

## Manual configuration (without yiisoft/config)

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

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

```php
use Yiisoft\Queue\Provider\AdapterFactoryQueueProvider;

$definitions = [
'channel1' => new \Yiisoft\Queue\Adapter\SynchronousAdapter($worker, $queue),
'channel2' => static fn (\Yiisoft\Queue\Adapter\SynchronousAdapter $adapter) => $adapter->withChannel('channel2'),
];

$provider = new AdapterFactoryQueueProvider(
$queue,
$definitions,
$container,
);

$queueForChannel1 = $provider->get('channel1');
$queueForChannel2 = $provider->get('channel2');
```
116 changes: 116 additions & 0 deletions docs/guide/en/configuration-manual.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
# Manual Configuration (without [yiisoft/config](https://github.com/yiisoft/config))

This guide explains how to set up the queue component manually, without using [yiisoft/config](https://github.com/yiisoft/config).

## Basic setup

To use the queue, you need to create instances of the following classes:

1. **Adapter** - handles the actual queue backend (e.g., `SynchronousAdapter`, or an adapter from external packages like Redis, AMQP, etc.)
2. **Worker** - processes messages from the queue
3. **Queue** - the main entry point for pushing messages

### Example

```php
use Yiisoft\Queue\Adapter\SynchronousAdapter;
use Yiisoft\Queue\Queue;
use Yiisoft\Queue\Worker\Worker;
use Yiisoft\Queue\Middleware\Consume\ConsumeMiddlewareDispatcher;
use Yiisoft\Queue\Middleware\Consume\MiddlewareFactoryConsume;
use Yiisoft\Queue\Middleware\FailureHandling\FailureMiddlewareDispatcher;
use Yiisoft\Queue\Middleware\FailureHandling\MiddlewareFactoryFailure;
use Yiisoft\Queue\Middleware\Push\MiddlewareFactoryPush;
use Yiisoft\Queue\Middleware\Push\PushMiddlewareDispatcher;
use Psr\Container\ContainerInterface;

// You need a PSR-11 container for dependency injection
/** @var ContainerInterface $container */

// Define message handlers
$handlers = [
'file-download' => [FileDownloader::class, 'handle'],
FileDownloader::class => [FileDownloader::class, 'handle'],
];

// Create middleware dispatchers
$consumeMiddlewareDispatcher = new ConsumeMiddlewareDispatcher(
new MiddlewareFactoryConsume($container),
);

$failureMiddlewareDispatcher = new FailureMiddlewareDispatcher(
new MiddlewareFactoryFailure($container),
[],
);

$pushMiddlewareDispatcher = new PushMiddlewareDispatcher(
new MiddlewareFactoryPush($container),
);

// Create worker
$worker = new Worker(
$handlers,
$container->get(\Psr\Log\LoggerInterface::class),
$container->get(\Yiisoft\Injector\Injector::class),
$container,
$consumeMiddlewareDispatcher,
$failureMiddlewareDispatcher,
);

// Create queue with adapter
$queue = new Queue(
$worker,
$pushMiddlewareDispatcher,
$container->get(\Psr\EventDispatcher\EventDispatcherInterface::class),
new SynchronousAdapter($worker, /* queue instance will be set via withAdapter */),
);

// Now you can push messages
$message = new \Yiisoft\Queue\Message\Message('file-download', ['url' => 'https://example.com/file.pdf']);
$queue->push($message);
```

## Using Queue Provider

For multiple queue channels, use `AdapterFactoryQueueProvider`:

```php
use Yiisoft\Queue\Provider\AdapterFactoryQueueProvider;
use Yiisoft\Queue\Adapter\SynchronousAdapter;

$definitions = [
'channel1' => new SynchronousAdapter($worker, $queue),
'channel2' => static fn(SynchronousAdapter $adapter) => $adapter->withChannel('channel2'),
];

$provider = new AdapterFactoryQueueProvider(
$queue,
$definitions,
$container,
);

$queueForChannel1 = $provider->get('channel1');
$queueForChannel2 = $provider->get('channel2');
```

## Running the queue

### Processing existing messages

```php
$queue->run(); // Process all messages
$queue->run(10); // Process up to 10 messages
```

### Listening for new messages

```php
$queue->listen(); // Run indefinitely
```

## Next steps

- [Usage basics](usage.md) - learn how to create messages and handlers
- [Workers](worker.md) - understand handler formats
- [Error handling](error-handling.md) - configure retries and failure handling
- [Adapter list](adapter-list.md) - choose a production-ready adapter
45 changes: 45 additions & 0 deletions docs/guide/en/configuration-with-config.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# Configuration with [yiisoft/config](https://github.com/yiisoft/config)

If you are using [yiisoft/config](https://github.com/yiisoft/config) (i.e. installed with [yiisoft/app](https://github.com/yiisoft/app) or [yiisoft/app-api](https://github.com/yiisoft/app-api)), you'll find out this package has some defaults in the [`common`](../../../config/di.php) and [`params`](../../../config/params.php) configurations saving your time.

## Where to put the configuration

In [yiisoft/app](https://github.com/yiisoft/app)/[yiisoft/app-api](https://github.com/yiisoft/app-api) templates you typically add or adjust configuration in `config/params.php`.
If your project structure differs, put configuration into any params config file that is loaded by [yiisoft/config](https://github.com/yiisoft/config).

## What you need to configure

- Optionally: define default `\Yiisoft\Queue\Adapter\AdapterInterface` implementation.
- And/or define channel-specific `AdapterInterface` implementations in the `channels` params key. See more about channels [here](./channels.md).
- Define [message handlers](./message-handlers.md) in the `handlers` params key to be used with the `QueueWorker`.
- Resolve other `\Yiisoft\Queue\Queue` dependencies (psr-compliant event dispatcher).

## Minimal configuration example

```php
return [
'yiisoft/queue' => [
'handlers' => [
'handler-name' => [FooHandler::class, 'handle'],
],
],
];
```

## Full configuration example

```php
return [
'yiisoft/queue' => [
'handlers' => [
'handler-name' => [FooHandler::class, 'handle'],
],
'channels' => [
\Yiisoft\Queue\QueueInterface::DEFAULT_CHANNEL => \Yiisoft\Queue\Adapter\AdapterInterface::class,
],
'middlewares-push' => [],
'middlewares-consume' => [],
'middlewares-fail' => [],
],
];
```
45 changes: 45 additions & 0 deletions docs/guide/en/console-commands.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# Console commands

Yii Queue provides several console commands for processing queued jobs.

If you are using [yiisoft/config](https://github.com/yiisoft/config) and [yiisoft/yii-console](https://github.com/yiisoft/yii-console), the commands are registered automatically.

If you are using [symfony/console](https://github.com/symfony/console) directly, you should register the commands manually.

## 1. Run queued messages and exit

The command `queue:run` obtains and executes tasks until the queue is empty, then exits.

You can also narrow the scope of processed messages by specifying channel(s) and maximum number of messages to process:

- Specify one or more channels to process. Messages from other channels will be ignored. Default is all registered channels (in case of using [yiisoft/config](https://github.com/yiisoft/config) and [yiisoft/yii-console](https://github.com/yiisoft/yii-console), otherwise pass the default channel list to the command constructor).
- Use `--maximum` to limit the number of messages processed. When set, command will exit either when all the messages are processed or when the maximum count is reached.

The full command signature is:
```sh
yii queue:run [channel1 [channel2 [...]]] --maximum=100
```

## 2. Listen for queued messages and process them continuously

The following command launches a daemon, which infinitely consumes messages from a single channel of the queue. This command receives an optional `channel` argument to specify which channel to listen to, defaults to the default channel `yii-queue`.

```sh
yii queue:listen [channel]
```

## 3. Listen to multiple channels

The following command iterates through multiple channels and is meant to be used in development environment only, as it consumes a lot of CPU for iterating through channels. You can pass to it:

- `channel` argument(s). Specify one or more channels to process. Messages from other channels will be ignored. Default is all registered channels (in case of using [yiisoft/config](https://github.com/yiisoft/config) and [yiisoft/yii-console](https://github.com/yiisoft/yii-console), otherwise pass the default channel list to the command constructor).
- `--maximum` option to limit the number of messages processed before switching to another channel. E.g. you set `--maximum` to 500 and right now you have 1000 messages in `channel1`. This command will consume only 500 of them, then it will switch to `channel2` to see if there are any messages there. Defaults to `0` (no limit).
- `--pause` option to specify the number of seconds to pause between checking channels when no messages are found. Defaults to `1`.

The full command signature is:
```sh
yii queue:listen-all [channel1 [channel2 [...]]] --pause=1 --maximum=0
```

For long-running processes, graceful shutdown is controlled by `LoopInterface`. When `ext-pcntl` is available,
the default `SignalLoop` handles signals such as `SIGTERM`/`SIGINT`.
Loading
Loading