Skip to content

Commit

Permalink
Merge branch 'master' into refactor-handlers
Browse files Browse the repository at this point in the history
# Conflicts:
#	README.md
#	config/di.php
#	config/params.php
#	src/Middleware/FailureHandling/Implementation/ExponentialDelayMiddleware.php
#	src/Middleware/FailureHandling/Implementation/SendAgainMiddleware.php
#	src/Queue.php
#	src/Worker/Worker.php
#	tests/App/FakeHandler.php
#	tests/Integration/MessageConsumingTest.php
#	tests/Integration/MiddlewareTest.php
#	tests/TestCase.php
#	tests/Unit/QueueTest.php
#	tests/Unit/SynchronousAdapterTest.php
#	tests/Unit/WorkerTest.php
  • Loading branch information
xepozz committed Jan 13, 2024
2 parents dc2cd05 + 8498f59 commit 8297902
Show file tree
Hide file tree
Showing 115 changed files with 731 additions and 660 deletions.
14 changes: 7 additions & 7 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -10,22 +10,22 @@ down: ## Stop and remove containers, networks
docker-compose -f tests/docker/docker-compose.yml down

sh: ## Enter the container with the application
docker exec -it yii-queue-php sh
docker exec -it queue-php sh

test: ## Run tests. Params: {{ v=8.1 }}. Default latest PHP 8.1
PHP_VERSION=$(filter-out $@,$(v)) docker-compose -f tests/docker/docker-compose.yml build --pull yii-queue-php
PHP_VERSION=$(filter-out $@,$(v)) docker-compose -f tests/docker/docker-compose.yml run yii-queue-php vendor/bin/phpunit --debug
PHP_VERSION=$(filter-out $@,$(v)) docker-compose -f tests/docker/docker-compose.yml build --pull queue-php
PHP_VERSION=$(filter-out $@,$(v)) docker-compose -f tests/docker/docker-compose.yml run queue-php vendor/bin/phpunit --debug
make down

mutation-test: ## Run mutation tests. Params: {{ v=8.1 }}. Default latest PHP 8.1
PHP_VERSION=$(filter-out $@,$(v)) docker-compose -f tests/docker/docker-compose.yml build --pull yii-queue-php
PHP_VERSION=$(filter-out $@,$(v)) docker-compose -f tests/docker/docker-compose.yml run yii-queue-php php -dpcov.enabled=1 -dpcov.directory=. vendor/bin/roave-infection-static-analysis-plugin -j2 --ignore-msi-with-no-mutations --only-covered
PHP_VERSION=$(filter-out $@,$(v)) docker-compose -f tests/docker/docker-compose.yml build --pull queue-php
PHP_VERSION=$(filter-out $@,$(v)) docker-compose -f tests/docker/docker-compose.yml run queue-php php -dpcov.enabled=1 -dpcov.directory=. vendor/bin/roave-infection-static-analysis-plugin -j2 --ignore-msi-with-no-mutations --only-covered
make down

coverage: ## Run code coverage. Params: {{ v=8.1 }}. Default latest PHP 8.1
PHP_VERSION=$(filter-out $@,$(v)) docker-compose -f tests/docker/docker-compose.yml run yii-queue-php vendor/bin/phpunit --coverage-clover coverage.xml
PHP_VERSION=$(filter-out $@,$(v)) docker-compose -f tests/docker/docker-compose.yml run queue-php vendor/bin/phpunit --coverage-clover coverage.xml
make down

static-analyze: ## Run code static analyze. Params: {{ v=8.1 }}. Default latest PHP 8.1
PHP_VERSION=$(filter-out $@,$(v)) docker-compose -f tests/docker/docker-compose.yml run yii-queue-php vendor/bin/psalm --config=psalm.xml --shepherd --stats --php-version=$(v)
PHP_VERSION=$(filter-out $@,$(v)) docker-compose -f tests/docker/docker-compose.yml run queue-php vendor/bin/psalm --config=psalm.xml --shepherd --stats --php-version=$(v)
make down
46 changes: 23 additions & 23 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,14 @@ An extension for running tasks asynchronously via queues.

Documentation is at [docs/guide/README.md](docs/guide/README.md).

[![Latest Stable Version](https://poser.pugx.org/yiisoft/yii-queue/v/stable.svg)](https://packagist.org/packages/yiisoft/yii-queue)
[![Total Downloads](https://poser.pugx.org/yiisoft/yii-queue/downloads.svg)](https://packagist.org/packages/yiisoft/yii-queue)
[![Build status](https://github.com/yiisoft/yii-queue/workflows/build/badge.svg)](https://github.com/yiisoft/yii-queue/actions)
[![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/yiisoft/yii-queue/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/yiisoft/yii-queue/?branch=master)
[![Code Coverage](https://scrutinizer-ci.com/g/yiisoft/yii-queue/badges/coverage.png?b=master)](https://scrutinizer-ci.com/g/yiisoft/yii-queue/?branch=master)
[![Mutation testing badge](https://img.shields.io/endpoint?style=flat&url=https%3A%2F%2Fbadge-api.stryker-mutator.io%2Fgithub.com%2Fyiisoft%2Fyii-queue%2Fmaster)](https://dashboard.stryker-mutator.io/reports/github.com/yiisoft/yii-queue/master)
[![static analysis](https://github.com/yiisoft/yii-queue/workflows/static%20analysis/badge.svg)](https://github.com/yiisoft/yii-queue/actions?query=workflow%3A%22static+analysis%22)
[![type-coverage](https://shepherd.dev/github/yiisoft/yii-queue/coverage.svg)](https://shepherd.dev/github/yiisoft/yii-queue)
[![Latest Stable Version](https://poser.pugx.org/yiisoft/queue/v/stable.svg)](https://packagist.org/packages/yiisoft/queue)
[![Total Downloads](https://poser.pugx.org/yiisoft/queue/downloads.svg)](https://packagist.org/packages/yiisoft/queue)
[![Build status](https://github.com/yiisoft/queue/workflows/build/badge.svg)](https://github.com/yiisoft/queue/actions)
[![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/yiisoft/queue/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/yiisoft/queue/?branch=master)
[![Code Coverage](https://scrutinizer-ci.com/g/yiisoft/queue/badges/coverage.png?b=master)](https://scrutinizer-ci.com/g/yiisoft/queue/?branch=master)
[![Mutation testing badge](https://img.shields.io/endpoint?style=flat&url=https%3A%2F%2Fbadge-api.stryker-mutator.io%2Fgithub.com%2Fyiisoft%2Fqueue%2Fmaster)](https://dashboard.stryker-mutator.io/reports/github.com/yiisoft/queue/master)
[![static analysis](https://github.com/yiisoft/queue/workflows/static%20analysis/badge.svg)](https://github.com/yiisoft/queue/actions?query=workflow%3A%22static+analysis%22)
[![type-coverage](https://shepherd.dev/github/yiisoft/queue/coverage.svg)](https://shepherd.dev/github/yiisoft/queue)

## Installation

Expand All @@ -26,13 +26,13 @@ The preferred way to install this extension is through [composer](http://getcomp
Either run

```shell
composer require yiisoft/yii-queue
composer require yiisoft/queue
```

or add

```
"yiisoft/yii-queue": "~3.0"
"yiisoft/queue": "~3.0"
```

to the `require` section of your `composer.json` file.
Expand All @@ -42,11 +42,11 @@ to the `require` section of your `composer.json` file.
If you are using [yiisoft/config](https://github.com/yiisoft/config), you'll find out this package has some defaults
in the [`common`](config/di.php) and [`params`](config/params.php) configurations saving your time. Things you should
change to start working with the queue:
- Optionally: define default `\Yiisoft\Yii\Queue\Adapter\AdapterInterface` implementation.
- Optionally: define default `\Yiisoft\Queue\Adapter\AdapterInterface` implementation.
- And/or define channel-specific `AdapterInterface` implementations in the `channel-definitions` params key to be used
with the [queue factory](#different-queue-channels).
- Define [message handlers](docs/guide/worker.md#handler-format) in the `handlers` params key to be used with the `QueueWorker`.
- Resolve other `\Yiisoft\Yii\Queue\Queue` dependencies (psr-compliant event dispatcher).
- Resolve other `\Yiisoft\Queue\Queue` dependencies (psr-compliant event dispatcher).

## Differences to yii2-queue

Expand All @@ -58,8 +58,8 @@ Though, there are some key differences which are described in the "[migrating fr
Each queue task consists of two parts:

1. A message is a class implementing `MessageInterface`. For simple cases you can use the default implementation,
`Yiisoft\Yii\Queue\Message\Message`. For more complex cases you should implement the interface by your own.
2. A message handler is a callable called by a `Yiisoft\Yii\Queue\Worker\Worker`. The handler handles each queue message.
`Yiisoft\Queue\Message\Message`. For more complex cases you should implement the interface by your own.
2. A message handler is a callable called by a `Yiisoft\Queue\Worker\Worker`. The handler handles each queue message.

For example, if you need to download and save a file, your message may look like the following:

Expand All @@ -68,7 +68,7 @@ $data = [
'url' => $url,
'destinationFile' => $filename,
];
$message = new \Yiisoft\Yii\Queue\Message\Message(FileDownloader::class, $data);
$message = new \Yiisoft\Queue\Message\Message(FileDownloader::class, $data);
```

Then you should push it to the queue:
Expand All @@ -92,7 +92,7 @@ class FileDownloader implements MessageHandlerInterface
$this->absolutePath = $absolutePath;
}

public function handle(MessageInterface $message): MessageInterface
public function handle(\Yiisoft\Queue\Message\MessageInterface $downloadMessage): MessageInterface
{
$fileName = $message->getData()['destinationFile'];
$path = "$this->absolutePath/$fileName";
Expand All @@ -103,10 +103,10 @@ class FileDownloader implements MessageHandlerInterface
}
```

The last thing we should do is to create a configuration for the `Yiisoft\Yii\Queue\Worker\Worker`:
The last thing we should do is to create a configuration for the `Yiisoft\Queue\Worker\Worker`:

```php
$worker = new \Yiisoft\Yii\Queue\Worker\Worker(
$worker = new \Yiisoft\Queue\Worker\Worker(
$logger,
$injector,
$container
Expand Down Expand Up @@ -160,7 +160,7 @@ the `$definitions` constructor parameter of the factory, where keys are channel
for the [`Yiisoft\Factory\Factory`](https://github.com/yiisoft/factory). Below are some examples:

```php
use Yiisoft\Yii\Queue\Adapter\SynchronousAdapter;
use Yiisoft\Queue\Adapter\SynchronousAdapter;

[
'channel1' => new SynchronousAdapter(),
Expand Down Expand Up @@ -261,7 +261,7 @@ You have three places to define push middlewares:
1. `PushMiddlewareDispatcher`. You can pass it either to the constructor, or to the `withMiddlewares()` method, which
creates a completely new dispatcher object with only those middlewares, which are passed as arguments.
If you use [yiisoft/config](yiisoft/config), you can add middleware to the `middlewares-push` key of the
`yiisoft/yii-queue` array in the `params`.
`yiisoft/queue` array in the `params`.
2. Pass middlewares to either `Queue::withMiddlewares()` or `Queue::withMiddlewaresAdded()` methods. The difference is
that the former will completely replace an existing middleware stack, while the latter will add passed middlewares to
the end of the existing stack. These middlewares will be executed after the common ones, passed directly to the
Expand All @@ -274,15 +274,15 @@ along with them.

### Consume pipeline

You can set a middleware pipeline for a message when it will be consumed from a queue server. This is useful to collect metrics, modify message data, etc. In pair with a Push middleware you can deduplicate messages in the queue, calculate time from push to consume, handle errors (push to a queue again, redirect failed message to another queue, send a notification, etc.). Unless Push pipeline, you have only one place to define the middleware stack: in the `ConsumeMiddlewareDispatcher`, either in the constructor, or in the `withMiddlewares()` method. If you use [yiisoft/config](yiisoft/config), you can add middleware to the `middlewares-consume` key of the `yiisoft/yii-queue` array in the `params`.
You can set a middleware pipeline for a message when it will be consumed from a queue server. This is useful to collect metrics, modify message data, etc. In pair with a Push middleware you can deduplicate messages in the queue, calculate time from push to consume, handle errors (push to a queue again, redirect failed message to another queue, send a notification, etc.). Unless Push pipeline, you have only one place to define the middleware stack: in the `ConsumeMiddlewareDispatcher`, either in the constructor, or in the `withMiddlewares()` method. If you use [yiisoft/config](yiisoft/config), you can add middleware to the `middlewares-consume` key of the `yiisoft/queue` array in the `params`.

### Error handling pipeline

Often when some job is failing, we want to retry its execution a couple more times or redirect it to another queue channel. This can be done in `yiisoft/yii-queue` with Failure middleware pipeline. They are triggered each time message processing via the Consume middleware pipeline is interrupted with any `Throwable`. The key differences from the previous two pipelines:
Often when some job is failing, we want to retry its execution a couple more times or redirect it to another queue channel. This can be done in `yiisoft/queue` with Failure middleware pipeline. They are triggered each time message processing via the Consume middleware pipeline is interrupted with any `Throwable`. The key differences from the previous two pipelines:
- You should set up the middleware pipeline separately for each queue channel. That means, the format should be `['channel-name' => [FooMiddleware::class]]` instead of `[FooMiddleware::class]`, like for the other two pipelines. There is also a default key, which will be used for those channels without their own one: `FailureMiddlewareDispatcher::DEFAULT_PIPELINE`.
- The last middleware will throw the exception, which will come with the `FailureHandlingRequest` object. If you don't want the exception to be thrown, your middlewares should `return` a request without calling `$handler->handleFailure()`.

You can declare error handling middleware pipeline in the `FailureMiddlewareDispatcher`, either in the constructor, or in the `withMiddlewares()` method. If you use [yiisoft/config](yiisoft/config), you can add middleware to the `middlewares-fail` key of the `yiisoft/yii-queue` array in the `params`.
You can declare error handling middleware pipeline in the `FailureMiddlewareDispatcher`, either in the constructor, or in the `withMiddlewares()` method. If you use [yiisoft/config](yiisoft/config), you can add middleware to the `middlewares-fail` key of the `yiisoft/queue` array in the `params`.

See [error handling docs](docs/guide/error-handling.md) for details.

Expand Down
25 changes: 12 additions & 13 deletions composer.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "yiisoft/yii-queue",
"description": "Yii Queue Extension which supported DB, Redis, RabbitMQ, Beanstalk, SQS and Gearman",
"name": "yiisoft/queue",
"description": "Queue Extension which supported DB, Redis, RabbitMQ, Beanstalk, SQS and Gearman",
"type": "library",
"keywords": [
"yii",
Expand All @@ -16,46 +16,45 @@
],
"license": "BSD-3-Clause",
"support": {
"issues": "https://github.com/yiisoft/yii-queue/issues?state=open",
"issues": "https://github.com/yiisoft/queue/issues?state=open",
"forum": "https://www.yiiframework.com/forum/",
"wiki": "https://www.yiiframework.com/wiki/",
"irc": "ircs://irc.libera.chat:6697/yii",
"chat": "https://t.me/yii3en",
"source": "https://github.com/yiisoft/yii-queue"
"source": "https://github.com/yiisoft/queue"
},
"minimum-stability": "dev",
"prefer-stable": true,
"require": {
"php": "^8.0",
"psr/log": "^2.0|^3.0",
"psr/container": "^1.0|^2.0",
"yiisoft/yii-console": "^2.0",
"psr/log": "^2.0|^3.0",
"symfony/console": "^5.4|^6.0",
"yiisoft/definitions": "^1.0|^2.0|^3.0",
"yiisoft/friendly-exception": "^1.0",
"yiisoft/injector": "^1.0",
"symfony/console": "^5.4|^6.0"
"yiisoft/injector": "^1.0"
},
"require-dev": {
"maglnet/composer-require-checker": "^4.2",
"phpunit/phpunit": "^9.5",
"rector/rector": "^0.18.10",
"rector/rector": "^0.19.0",
"roave/infection-static-analysis-plugin": "^1.16",
"spatie/phpunit-watcher": "^1.23",
"yiisoft/yii-debug": "dev-master",
"vimeo/psalm": "^4.30|^5.8",
"yiisoft/test-support": "^3.0"
"yiisoft/test-support": "^3.0",
"yiisoft/yii-debug": "dev-master|dev-php80"
},
"suggest": {
"ext-pcntl": "Need for process signals"
},
"autoload": {
"psr-4": {
"Yiisoft\\Yii\\Queue\\": "src"
"Yiisoft\\Queue\\": "src"
}
},
"autoload-dev": {
"psr-4": {
"Yiisoft\\Yii\\Queue\\Tests\\": "tests"
"Yiisoft\\Queue\\Tests\\": "tests"
}
},
"extra": {
Expand Down
44 changes: 22 additions & 22 deletions config/di.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,24 +3,24 @@
declare(strict_types=1);

use Psr\Container\ContainerInterface;
use Yiisoft\Yii\Queue\Cli\LoopInterface;
use Yiisoft\Yii\Queue\Cli\SignalLoop;
use Yiisoft\Yii\Queue\Cli\SimpleLoop;
use Yiisoft\Yii\Queue\Middleware\Consume\ConsumeMiddlewareDispatcher;
use Yiisoft\Yii\Queue\Middleware\Consume\MiddlewareFactoryConsume;
use Yiisoft\Yii\Queue\Middleware\Consume\MiddlewareFactoryConsumeInterface;
use Yiisoft\Yii\Queue\Middleware\FailureHandling\FailureMiddlewareDispatcher;
use Yiisoft\Yii\Queue\Middleware\FailureHandling\MiddlewareFactoryFailure;
use Yiisoft\Yii\Queue\Middleware\FailureHandling\MiddlewareFactoryFailureInterface;
use Yiisoft\Yii\Queue\Middleware\Push\MiddlewareFactoryPush;
use Yiisoft\Yii\Queue\Middleware\Push\MiddlewareFactoryPushInterface;
use Yiisoft\Yii\Queue\Middleware\Push\PushMiddlewareDispatcher;
use Yiisoft\Yii\Queue\Queue;
use Yiisoft\Yii\Queue\QueueFactory;
use Yiisoft\Yii\Queue\QueueFactoryInterface;
use Yiisoft\Yii\Queue\QueueInterface;
use Yiisoft\Yii\Queue\Worker\Worker as QueueWorker;
use Yiisoft\Yii\Queue\Worker\WorkerInterface;
use Yiisoft\Queue\Cli\LoopInterface;
use Yiisoft\Queue\Cli\SignalLoop;
use Yiisoft\Queue\Cli\SimpleLoop;
use Yiisoft\Queue\Middleware\Consume\ConsumeMiddlewareDispatcher;
use Yiisoft\Queue\Middleware\Consume\MiddlewareFactoryConsume;
use Yiisoft\Queue\Middleware\Consume\MiddlewareFactoryConsumeInterface;
use Yiisoft\Queue\Middleware\FailureHandling\FailureMiddlewareDispatcher;
use Yiisoft\Queue\Middleware\FailureHandling\MiddlewareFactoryFailure;
use Yiisoft\Queue\Middleware\FailureHandling\MiddlewareFactoryFailureInterface;
use Yiisoft\Queue\Middleware\Push\MiddlewareFactoryPush;
use Yiisoft\Queue\Middleware\Push\MiddlewareFactoryPushInterface;
use Yiisoft\Queue\Middleware\Push\PushMiddlewareDispatcher;
use Yiisoft\Queue\Queue;
use Yiisoft\Queue\QueueFactory;
use Yiisoft\Queue\QueueFactoryInterface;
use Yiisoft\Queue\QueueInterface;
use Yiisoft\Queue\Worker\Worker as QueueWorker;
use Yiisoft\Queue\Worker\WorkerInterface;

/* @var array $params */

Expand All @@ -35,19 +35,19 @@
},
QueueFactoryInterface::class => QueueFactory::class,
QueueFactory::class => [
'__construct()' => ['channelConfiguration' => $params['yiisoft/yii-queue']['channel-definitions']],
'__construct()' => ['channelConfiguration' => $params['yiisoft/queue']['channel-definitions']],
],
QueueInterface::class => Queue::class,
MiddlewareFactoryPushInterface::class => MiddlewareFactoryPush::class,
MiddlewareFactoryConsumeInterface::class => MiddlewareFactoryConsume::class,
MiddlewareFactoryFailureInterface::class => MiddlewareFactoryFailure::class,
PushMiddlewareDispatcher::class => [
'__construct()' => ['middlewareDefinitions' => $params['yiisoft/yii-queue']['middlewares-push']],
'__construct()' => ['middlewareDefinitions' => $params['yiisoft/queue']['middlewares-push']],
],
ConsumeMiddlewareDispatcher::class => [
'__construct()' => ['middlewareDefinitions' => $params['yiisoft/yii-queue']['middlewares-consume']],
'__construct()' => ['middlewareDefinitions' => $params['yiisoft/queue']['middlewares-consume']],
],
FailureMiddlewareDispatcher::class => [
'__construct()' => ['middlewareDefinitions' => $params['yiisoft/yii-queue']['middlewares-fail']],
'__construct()' => ['middlewareDefinitions' => $params['yiisoft/queue']['middlewares-fail']],
],
];
16 changes: 8 additions & 8 deletions config/params.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@

declare(strict_types=1);

use Yiisoft\Yii\Queue\Command\ListenCommand;
use Yiisoft\Yii\Queue\Command\RunCommand;
use Yiisoft\Yii\Queue\Debug\QueueCollector;
use Yiisoft\Yii\Queue\Debug\QueueFactoryInterfaceProxy;
use Yiisoft\Yii\Queue\Debug\QueueWorkerInterfaceProxy;
use Yiisoft\Yii\Queue\QueueFactoryInterface;
use Yiisoft\Yii\Queue\Worker\WorkerInterface;
use Yiisoft\Queue\Command\ListenCommand;
use Yiisoft\Queue\Command\RunCommand;
use Yiisoft\Queue\Debug\QueueCollector;
use Yiisoft\Queue\Debug\QueueFactoryInterfaceProxy;
use Yiisoft\Queue\Debug\QueueWorkerInterfaceProxy;
use Yiisoft\Queue\QueueFactoryInterface;
use Yiisoft\Queue\Worker\WorkerInterface;

return [
'yiisoft/yii-console' => [
Expand All @@ -17,7 +17,7 @@
'queue:listen' => ListenCommand::class,
],
],
'yiisoft/yii-queue' => [
'yiisoft/queue' => [
'channel-definitions' => [],
'middlewares-push' => [],
'middlewares-consume' => [],
Expand Down
2 changes: 1 addition & 1 deletion docs/guide/adapter-list.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@ Queue Adapters
-------------

* [Synchronous](adapter-sync.md) - adapter for development and test environments
* [AMQP](https://github.com/yiisoft/yii-queue-amqp) - adapter over AMQP protocol via [amqplib](https://github.com/php-amqplib/php-amqplib)
* [AMQP](https://github.com/yiisoft/queue-amqp) - adapter over AMQP protocol via [amqplib](https://github.com/php-amqplib/php-amqplib)
Loading

0 comments on commit 8297902

Please sign in to comment.