Skip to content

Commit

Permalink
Remove payloads, enhance docs (yiisoft#68)
Browse files Browse the repository at this point in the history
Co-authored-by: Alexander Makarov <[email protected]>
  • Loading branch information
viktorprogger and samdark authored Nov 2, 2020
1 parent e05b43d commit 0d5a7ac
Show file tree
Hide file tree
Showing 46 changed files with 847 additions and 765 deletions.
145 changes: 68 additions & 77 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,7 @@ Documentation is at [docs/guide/README.md](docs/guide/README.md).
[![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)

Installation
------------
## Installation

The preferred way to install this extension is through [composer](http://getcomposer.org/download/).

Expand All @@ -35,50 +34,36 @@ or add

to the `require` section of your `composer.json` file.

Basic Usage
-----------
## Differences to yii2-queue

If you have experience with `yiisoft/yii2-queue`, you will find out that this package is similar.
Though, there are some key differences which are described in the "[migrating from yii2-queue](docs/guide/migrating-from-yii2-queue.md)" article.

## Basic Usage

Each queue task consists of two parts:
1. Data payload. It is a class implementing `PayloadInterface`.
2. Payload handler. It is a callable called by a `WorkerInterface` which handles every queue message.

For example, if you need to download and save a file, the payload may look like the following:
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.

```php
class DownloadJob implements Yiisoft\Yii\Queue\Payload\PayloadInterface
{
public const NAME = 'file-download';
For example, if you need to download and save a file, your message may look like the following:

public string $url;
public string $fileName;

public function __construct(string $url, string $fileName)
{
$this->url = $url;
$this->fileName = $fileName;
}

public function getName(): string
{
return self::NAME;
}
```php
$data = [
'url' => $url,
'destinationFile' => $filename,
];
$message = new \Yiisoft\Yii\Queue\Message\Message('file-download', $data);
```

public function getData(): array
{
return [
'destinationFile' => $this->fileName,
'url' => $this->url
];
}
Then you should push it to the queue:

public function getMeta(): array
{
return [];
}
}
```php
$queue->push($message);
```

And its handler may look like the following:
Its handler may look like the following:

```php
class FileDownloader
Expand All @@ -92,16 +77,17 @@ class FileDownloader

public function handle(\Yiisoft\Yii\Queue\Message\MessageInterface $downloadMessage): void
{
$fileName = $downloadMessage->getPayloadData()['destinationFile'];
$fileName = $downloadMessage->getData()['destinationFile'];
$path = "$this->absolutePath/$fileName";
file_put_contents($path, file_get_contents($downloadMessage->getPayloadData()['url']));
file_put_contents($path, file_get_contents($downloadMessage->getData()['url']));
}
}
```

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

```php
$handlers = [DownloadJob::NAME => [new FileDownloader('/path/to/save/files'), 'handle']];
$handlers = ['file-download' => [new FileDownloader('/path/to/save/files'), 'handle']];
$worker = new \Yiisoft\Yii\Queue\Worker\Worker(
$handlers, // Here it is
$dispatcher,
Expand All @@ -111,45 +97,67 @@ $worker = new \Yiisoft\Yii\Queue\Worker\Worker(
);
```

Here's how to send a task into the queue:
There is the way to run all the messages that are already in the queue, and then exit:

```php
$queue->push(
new DownloadJob('http://example.com/image.jpg', 'new-image-name.jpg')
);
$queue->run(); // this will execute all the existing messages
$queue->run(10); // while this will execute only 10 messages as a maximum before exit
```

If you don't want your script to exit immediately, you can use the `listen` method:

```php
$queue->listen();
```

You can also check the status of a pushed message (the queue driver you are using must support this feature):

```php
$queue->push($message);
$id = $message->getId();

// Get status of the job
$status = $queue->status($id);

To push a job into the queue that should run after 5 minutes:
// Check whether the job is waiting for execution.
$status->isWaiting();

// Check whether a worker got the job from the queue and executes it.
$status->isReserved();

// Check whether a worker has executed the job.
$status->isDone();
```

## Driver behaviors

Some of queue drivers support different behaviors like delayed execution and prioritized queues.

**Important:** Not every driver supports all the behaviors. See concrete driver documentation to find out if
it supports the behavior you want to use. Driver will throw a `BehaviorNotSupportedException` if it does not support
some behaviors attached to the message you are trying to push to the queue.

### Delay behavior

To be sure message will be read from queue not earlier then 5 seconds since it will be pushed to the queue, you can use `DelayBehavior`:

```php
$queue->push(
new class('http://example.com/image.jpg', '/tmp/image.jpg') extends DownloadJob
implements \Yiisoft\Yii\Queue\Payload\DelayablePayloadInterface {

public function getDelay(): int
{
return 5 * 60;
}
}
);
$message->attachBehavior(new DelayBehavior(5));
$queue->push($message);
```

**Important:** Not every driver (such as synchronous driver) supports delayed execution.
## Console execution

The exact way a task is executed depends on the used driver. Most drivers can be run using
The exact way of task execution depends on the driver used. Most drivers can be run using
console commands, which the component automatically registers in your application.

This command obtains and executes tasks in a loop until the queue is empty:
The following command obtains and executes tasks in a loop until the queue is empty:

```sh
yii queue/run
```

This command launches a daemon which infinitely queries the queue:
The following command launches a daemon which infinitely queries the queue:

```sh
yii queue/listen
Expand All @@ -159,21 +167,4 @@ See the documentation for more details about driver specific console commands an

The component also has the ability to track the status of a job which was pushed into queue.

```php
// Push a job into the queue and get a message ID.
$id = $queue->push(new SomeJob());

// Get status of the job
$status = $queue->status($id);

// Check whether the job is waiting for execution.
$status->isWaiting();

// Check whether a worker got the job from the queue and executes it.
$status->isReserved($id);

// Check whether a worker has executed the job.
$status->isDone($id);
```

For more details see [the guide](docs/guide/README.md).
3 changes: 3 additions & 0 deletions config/common.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
use Yiisoft\Yii\Queue\Cli\LoopInterface;
use Yiisoft\Yii\Queue\Cli\SignalLoop;
use Yiisoft\Yii\Queue\Cli\SimpleLoop;
use Yiisoft\Yii\Queue\Driver\BehaviorChecker;
use Yiisoft\Yii\Queue\Driver\BehaviorCheckerInterface;
use Yiisoft\Yii\Queue\Worker\Worker as QueueWorker;
use Yiisoft\Yii\Queue\Worker\WorkerInterface;

Expand All @@ -20,4 +22,5 @@
? $container->get(SignalLoop::class)
: $container->get(SimpleLoop::class);
},
BehaviorCheckerInterface::class => BehaviorChecker::class,
];
10 changes: 0 additions & 10 deletions config/events-console.php

This file was deleted.

15 changes: 5 additions & 10 deletions docs/guide/README.md
Original file line number Diff line number Diff line change
@@ -1,17 +1,12 @@
Yii Queue extension
====================
# Yii Queue extension

An extension for running tasks asynchronously via queues.

Introduction
------------
## Guides and concept explanations

* [Usage basics](usage.md)
* [Migrating from `yii2-queue`](migrating-from-yii2-queue.md)
* [Message behaviors](behaviors.md)
* [Errors and retryable jobs](retryable.md)
* [Workers](worker.md)

Queue Drivers
-------------

* [Synchronous](driver-sync.md)
* [AMQP](https://github.com/yiisoft/yii-queue-amqp)
* [Driver list](driver-list.md)
42 changes: 42 additions & 0 deletions docs/guide/behaviors.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# Message behaviors

`Behaviors` are classes designed to tell queue [drivers] about some specific message behavior: e.g. when you want
to delay message consuming or set message priority. There are some predefined behaviors with which some
default [drivers] can work.

***Important!* Not every driver can work with all the behaviors. Below you will find a matrix displaying compatibility
of drivers and behaviors.**

## Default behaviors

### DelayBehavior

This behavior specifies amount of seconds the message can be consumed after.

This code means the message can be consumed after 5 seconds since it was pushed to the queue server:

```php
$message->attachBehavior(new DelayBehavior(5));
```

### PriorityBehavior

This behavior sets a relative order for message consuming. The higher the priority, the earlier a message will be consumed.

Example:

```php
$message->attachBehavior(new PriorityBehavior(100));
```

## Compatibility matrix

| | DelayBehavior | PriorityBehavior
|---------------------|---------------------------|-----------------
| [SynchronousDriver] | ❌ | ❌
| [Amqp] | yiisoft/yii-queue-amqp#11 | ❌


[drivers]: (driver-list.md)
[SynchronousDriver]: (driver-sync.md)
[Amqp]: (https://github.com/yiisoft/yii-queue-amqp)
5 changes: 5 additions & 0 deletions docs/guide/driver-list.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Queue Drivers
-------------

* [Synchronous](driver-sync.md) - driver for development and test environments
* [AMQP](https://github.com/yiisoft/yii-queue-amqp) - driver over AMQP protocol via [amqplib](https://github.com/php-amqplib/php-amqplib)
7 changes: 3 additions & 4 deletions docs/guide/driver-sync.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
Synchronous Driver
==================

Runs tasks synchronously in the same process.
It could be used when developing and debugging an application.
Run tasks synchronously in the same process. It could be used when developing and debugging an application.

Configuration example:

```php
$eventDisptacher = $DIContainer->get(\Psr\EventDispatcher\EventDispatcherInterface::class);
$eventDispatcher = $DIContainer->get(\Psr\EventDispatcher\EventDispatcherInterface::class);
$logger = $DIContainer->get(\Psr\Log\LoggerInterface::class);

$worker = $DIContainer->get(\Yiisoft\Yii\Queue\Worker\WorkerInterface::class);
Expand All @@ -16,7 +15,7 @@ $driver = new Yiisoft\Yii\Queue\Driver\SynchronousDriver($loop, $worker);

$queue = new Yiisoft\Yii\Queue\Queue(
$driver,
$eventDisptacher,
$eventDispatcher,
$worker,
$loop,
$logger
Expand Down
33 changes: 33 additions & 0 deletions docs/guide/migrating-from-yii2-queue.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# Migrating from yii2-queue

This package is similar to [yiisoft/yii2-queue] but with improved design and code style. The new package less coupled
and more structured than the old one allowing better maintenance.

## Drivers

- Individual drivers are now separate packages. This means each driver must be `require`d with composer in order to
be available in your application.
- Driver may be any class which implements `DriverInterface`. This means you can replace one driver with another without
changing any code in your app. For example, you can use `db` driver in development while using `amqp` in production,
then you may seamlessly switch to `redis` if needed. This also means you can write your own driver implementation
if necessary.

## Jobs (Messages and Handlers)

There was a concept in [yiisoft/yii2-queue] called `Job`: you had to push it to the queue, and it was executed after
being consumed. In the new package it is divided into two different concepts: a message and a handler.

- A `Message` is a class implementing `MessageInterface`. It contains 3 types of data:
- Name. Worker uses it to find the right handler for a message.
- Data. Any serializable data which should be used by the message handler.
- Behaviors. Message behaviors used by drivers. For example, priority setting, message delaying, etc. [See more](behaviors.md).

All the message data is fully serializable (that means message `data` must be serializable too). It allows you to
freely choose where and how to send and process jobs. Both can be implemented in a single application, or
separated into multiple applications, or you can do sending/processing only leaving part of the job to another
system including non-PHP ones. It is fairly popular to process heavy jobs with Go.

- A `Handler` is called by a `Worker` when a message comes. Default `Worker` finds a corresponding message handler
by the message name. [See more](worker.md#handler-format).

[yiisoft/yii2-queue]: (https://github.com/yiisoft/yii2-queue)
Loading

0 comments on commit 0d5a7ac

Please sign in to comment.