first commit
This commit is contained in:
224
vendor/yiisoft/yii2-queue/CHANGELOG.md
vendored
Normal file
224
vendor/yiisoft/yii2-queue/CHANGELOG.md
vendored
Normal file
@ -0,0 +1,224 @@
|
||||
Yii2 Queue Extension Change Log
|
||||
===============================
|
||||
|
||||
2.3.8 January 08, 2026
|
||||
----------------------
|
||||
|
||||
- Bug #522: Fix SQS driver type error with custom value passed to `queue/listen` (flaviovs)
|
||||
- Bug #528: Prevent multiple execution of aborted jobs (luke-)
|
||||
- Bug #538: Fix type hint for previous parameter in `InvalidJobException` class constructor in PHP `8.4` (implicitly marking parameter nullable) (terabytesoftw)
|
||||
- Enh #493: Pass environment variables to sub-processes (mgrechanik)
|
||||
- Enh #516: Ensure Redis driver messages are consumed at least once (soul11201)
|
||||
|
||||
|
||||
2.3.7 April 29, 2024
|
||||
--------------------
|
||||
|
||||
- Enh #509: Add StatisticsProviderInterface to get statistics from queue (kalmer)
|
||||
|
||||
|
||||
2.3.6 October 03, 2023
|
||||
----------------------
|
||||
|
||||
- Bug #373: Fixed error if payload in Redis is null (sanwv, magarzon)
|
||||
- Enh #372: Add ability to configure keepalive and heartbeat for AMQP and AMQP interop (vyachin)
|
||||
- Enh #464: Delete property `maxPriority` (skolkin-worker)
|
||||
- Enh #486: `SignalLoop::$exitSignals` now includes `SIGQUIT` (rhertogh)
|
||||
- Enh #487: Add ability to push message with headers for AMQP interop driver (s1lver)
|
||||
|
||||
|
||||
2.3.5 November 18, 2022
|
||||
-----------------------
|
||||
|
||||
- Enh #457: Upgraded `jeremeamia/superclosure` library to `opis/closure`, adding the possibility to have closures as properties of the jobs (mp1509)
|
||||
- Enh #459: Added the ability to sets of flags for the AMQP queue and exchange (s1lver)
|
||||
|
||||
|
||||
2.3.4 March 31, 2022
|
||||
--------------------
|
||||
|
||||
- Enh #449: Force db to use the index on the `reserved_at` column to unlock unfinished tasks in DB driver (erickskrauch)
|
||||
|
||||
|
||||
2.3.3 December 30, 2021
|
||||
-----------------------
|
||||
|
||||
- Enh #257: Increase MySQL db job size to more than 65KB (lourdas)
|
||||
- Enh #394: Added stack trace on error in verbose mode (germanow)
|
||||
- Enh #405: Change access modifier of `moveExpired` in DB drivers (matiosfree)
|
||||
- Enh #427: Added configurable AMQP `routingKey` options (alisin, s1lver)
|
||||
- Enh #430: Added configurable AMQP Exchange type (s1lver)
|
||||
- Enh #435: Added the ability to set optional arguments for the AMQP queue (s1lver)
|
||||
- Enh #445: Display memory peak usage when verbose output is enabled (nadar)
|
||||
|
||||
|
||||
2.3.2 May 05, 2021
|
||||
------------------
|
||||
|
||||
- Bug #414: Fixed PHP errors when PCNTL functions were disallowed (brandonkelly)
|
||||
|
||||
|
||||
2.3.1 December 23, 2020
|
||||
-----------------------
|
||||
|
||||
- Bug #380: Fixed amqp-interop queue/listen signal handling (tarinu)
|
||||
- Enh #388: `symfony/process 5.0` compatibility (leandrogehlen)
|
||||
|
||||
|
||||
2.3.0 June 04, 2019
|
||||
-------------------
|
||||
|
||||
- Enh #260: Added STOMP driver (versh23)
|
||||
|
||||
|
||||
2.2.1 May 21, 2019
|
||||
------------------
|
||||
|
||||
- Bug #220: Updated to the latest amqp-lib (alexkart)
|
||||
- Enh #293: Add `handle` method to `\yii\queue\sqs\Queue` that provides public access for `handleMessage` which can be
|
||||
useful for handling jobs by webhooks (alexkart)
|
||||
- Enh #332: Add AWS SQS FIFO support (kringkaste, alexkart)
|
||||
|
||||
|
||||
2.2.0 Mar 20, 2019
|
||||
------------------
|
||||
|
||||
- Bug #220: Fixed deadlock problem of DB driver (zhuravljov)
|
||||
- Bug #258: Worker in isolated mode fails if PHP_BINARY contains spaces (luke-)
|
||||
- Bug #267: Fixed symfony/process incompatibility (rob006)
|
||||
- Bug #269: Handling of broken messages that are not unserialized correctly (zhuravljov)
|
||||
- Bug #299: Queue config param validation (zhuravljov)
|
||||
- Enh #248: Reduce roundtrips to beanstalk server when removing job (SamMousa)
|
||||
- Enh #318: Added check result call function flock (evaldemar)
|
||||
- Enh: Job execution result is now forwarded to the event handler (zhuravljov)
|
||||
- Enh: `ErrorEvent` was marked as deprecated (zhuravljov)
|
||||
|
||||
2.1.0 May 24, 2018
|
||||
------------------
|
||||
|
||||
- Bug #126: Handles a fatal error of the job execution in isolate mode (zhuravljov)
|
||||
- Bug #207: Console params validation (zhuravljov)
|
||||
- Bug #210: Worker option to define php bin path to run child process (zhuravljov)
|
||||
- Bug #224: Invalid identifier "DELAY" (lar-dragon)
|
||||
- Enh #192: AWS SQS implementation (elitemaks, manoj-girnar)
|
||||
- Enh: Worker loop event (zhuravljov)
|
||||
|
||||
2.0.2 December 26, 2017
|
||||
-----------------------
|
||||
|
||||
- Bug #92: Resolve issue in debug panel (farmani-eigital)
|
||||
- Bug #99: Retry connecting after connection has timed out for redis driver (cebe)
|
||||
- Bug #180: Fixed info command of file driver (victorruan)
|
||||
- Enh #158: Add Amqp Interop driver (makasim)
|
||||
- Enh #185: Loop object instead of Signal helper (zhuravljov)
|
||||
- Enh #188: Configurable verbose mode (zhuravljov)
|
||||
- Enh: Start and stop events of a worker (zhuravljov)
|
||||
|
||||
2.0.1 November 13, 2017
|
||||
-----------------------
|
||||
|
||||
- Bug #98: Fixed timeout error handler (zhuravljov)
|
||||
- Bug #112: Queue command inside module (tsingsun)
|
||||
- Bug #118: Synchronized moving of delayed and reserved jobs to waiting list (zhuravljov)
|
||||
- Bug #155: Slave DB breaks listener (zhuravljov)
|
||||
- Enh #97: `Queue::status` is public method (zhuravljov)
|
||||
- Enh #116: Add Chinese Guide (kids-return)
|
||||
- Enh #122: Rename `Job` to `JobInterface` (zhuravljov)
|
||||
- Enh #137: All throwable errors caused by jobs are now caught (brandonkelly)
|
||||
- Enh #141: Clear and remove commands for File, DB, Beanstalk and Redis drivers (zhuravljov)
|
||||
- Enh #147: Igbinary job serializer (xutl)
|
||||
- Enh #148: Allow to change vhost setting for RabbitMQ (ischenko)
|
||||
- Enh #151: Compatibility with Yii 2.0.13 and PHP 7.2 (zhuravljov)
|
||||
- Enh #160: Benchmark of job wait time (zhuravljov)
|
||||
- Enh: Rename `cli\Verbose` behavior to `cli\VerboseBehavior` (zhuravljov)
|
||||
- Enh: Rename `serializers\Serializer` interface to `serializers\SerializerInterface` (zhuravljov)
|
||||
- Enh: Added `Signal::setExitFlag()` to stop `Queue::run()` loop manually (silverfire)
|
||||
|
||||
2.0.0 July 15, 2017
|
||||
-------------------
|
||||
|
||||
- Enh: The package is moved to yiisoft/yii2-queue (zhuravljov)
|
||||
|
||||
1.1.0 July 12, 2017
|
||||
-------------------
|
||||
|
||||
- Enh #50 Documentation about worker starting control (zhuravljov)
|
||||
- Enh #70: Durability for rabbitmq queues (mkubenka)
|
||||
- Enh: Detailed error about job type in message handling (zhuravljov)
|
||||
- Enh #60: Enhanced event handling (zhuravljov)
|
||||
- Enh: Job priority for DB driver (zhuravljov)
|
||||
- Enh: File mode options of file driver (zhuravljov)
|
||||
- Enh #47: Redis queue listen timeout (zhuravljov)
|
||||
- Enh #23: Retryable jobs (zhuravljov)
|
||||
|
||||
1.0.1 June 7, 2017
|
||||
------------------
|
||||
|
||||
- Enh #58: Deleting failed jobs from queue (zhuravljov)
|
||||
- Enh #55: Job priority (zhuravljov)
|
||||
|
||||
1.0.0 May 4, 2017
|
||||
-----------------
|
||||
|
||||
- Enh: Improvements of log behavior (zhuravljov)
|
||||
- Enh: File driver stat info (zhuravljov)
|
||||
- Enh: Beanstalk stat info (zhuravljov)
|
||||
- Enh: Colorized driver info actions (zhuravljov)
|
||||
- Enh: Colorized verbose mode (zhuravljov)
|
||||
- Enh: Improvements of debug panel (zhuravljov)
|
||||
- Enh: Queue job message statuses (zhuravljov)
|
||||
- Enh: Gii job generator (zhuravljov)
|
||||
- Enh: Enhanced gearman driver (zhuravljov)
|
||||
- Enh: Queue message identifiers (zhuravljov)
|
||||
- Enh: File queue (zhuravljov)
|
||||
|
||||
0.12.2 April 29, 2017
|
||||
---------------------
|
||||
|
||||
- Enh #10: Separate option that turn off isolate mode of job execute (zhuravljov)
|
||||
|
||||
0.12.1 April 20, 2017
|
||||
---------------------
|
||||
|
||||
- Bug #37: Fixed opening of a child process (zhuravljov)
|
||||
- Enh: Ability to push a closure (zhuravljov)
|
||||
- Enh: Before push event (zhuravljov)
|
||||
|
||||
0.12.0 April 14, 2017
|
||||
---------------------
|
||||
|
||||
- Enh #18: Executes a job in a child process (zhuravljov)
|
||||
- Bug #25: Enabled output buffer breaks output streams (luke-)
|
||||
- Enh: After push event (zhuravljov)
|
||||
|
||||
0.11.0 April 2, 2017
|
||||
--------------------
|
||||
|
||||
- Enh #21: Delayed jobs for redis queue (zhuravljov)
|
||||
- Enh: Info action for db and redis queue command (zhuravljov)
|
||||
|
||||
0.10.1 March 29, 2017
|
||||
---------------------
|
||||
|
||||
- Bug: Fixed db driver for pgsql (zhuravljov)
|
||||
- Bug #16: Timeout of queue reading lock for db driver (zhuravljov)
|
||||
- Enh: Minor code style enhancements (SilverFire)
|
||||
|
||||
0.10.0 March 22, 2017
|
||||
---------------------
|
||||
|
||||
- Enh #14: Json job serializer (zhuravljov)
|
||||
- Enh: Delayed running of a job (zhuravljov)
|
||||
|
||||
0.9.1 March 6, 2017
|
||||
-------------------
|
||||
|
||||
- Bug #13: Fixed reading of DB queue (zhuravljov)
|
||||
|
||||
0.9.0 March 6, 2017
|
||||
-------------------
|
||||
|
||||
- Enh: Signal handlers (zhuravljov)
|
||||
- Enh: Add exchange for AMQP driver (airani)
|
||||
- Enh: Beanstalk driver (zhuravljov)
|
||||
- Enh: Added English docs (samdark)
|
||||
29
vendor/yiisoft/yii2-queue/LICENSE.md
vendored
Normal file
29
vendor/yiisoft/yii2-queue/LICENSE.md
vendored
Normal file
@ -0,0 +1,29 @@
|
||||
Copyright © 2008 by Yii Software LLC (http://www.yiisoft.com)
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
* Neither the name of Yii Software LLC nor the names of its
|
||||
contributors may be used to endorse or promote products derived
|
||||
from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
97
vendor/yiisoft/yii2-queue/README.md
vendored
Normal file
97
vendor/yiisoft/yii2-queue/README.md
vendored
Normal file
@ -0,0 +1,97 @@
|
||||
<p align="center">
|
||||
<a href="https://github.com/yiisoft" target="_blank">
|
||||
<img src="https://avatars0.githubusercontent.com/u/993323" height="100px">
|
||||
</a>
|
||||
<h1 align="center">Yii2 Queue Extension</h1>
|
||||
<br>
|
||||
</p>
|
||||
|
||||
An extension for running tasks asynchronously via queues.
|
||||
|
||||
It supports queues based on **DB**, **Redis**, **RabbitMQ**, **AMQP**, **Beanstalk**, **ActiveMQ** and **Gearman**.
|
||||
|
||||
Documentation is at [docs/guide/README.md](docs/guide/README.md).
|
||||
|
||||
[](https://packagist.org/packages/yiisoft/yii2-queue)
|
||||
[](https://packagist.org/packages/yiisoft/yii2-queue)
|
||||
[](https://github.com/yiisoft/yii2-queue/actions)
|
||||
|
||||
Installation
|
||||
------------
|
||||
|
||||
The preferred way to install this extension is through [composer](https://getcomposer.org/download/):
|
||||
|
||||
```
|
||||
php composer.phar require --prefer-dist yiisoft/yii2-queue
|
||||
```
|
||||
|
||||
Basic Usage
|
||||
-----------
|
||||
|
||||
Each task which is sent to queue should be defined as a separate class.
|
||||
For example, if you need to download and save a file the class may look like the following:
|
||||
|
||||
```php
|
||||
class DownloadJob extends BaseObject implements \yii\queue\JobInterface
|
||||
{
|
||||
public $url;
|
||||
public $file;
|
||||
|
||||
public function execute($queue)
|
||||
{
|
||||
file_put_contents($this->file, file_get_contents($this->url));
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Here's how to send a task into the queue:
|
||||
|
||||
```php
|
||||
Yii::$app->queue->push(new DownloadJob([
|
||||
'url' => 'http://example.com/image.jpg',
|
||||
'file' => '/tmp/image.jpg',
|
||||
]));
|
||||
```
|
||||
To push a job into the queue that should run after 5 minutes:
|
||||
|
||||
```php
|
||||
Yii::$app->queue->delay(5 * 60)->push(new DownloadJob([
|
||||
'url' => 'http://example.com/image.jpg',
|
||||
'file' => '/tmp/image.jpg',
|
||||
]));
|
||||
```
|
||||
|
||||
The exact way a task is executed depends on the used driver. 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:
|
||||
|
||||
```sh
|
||||
yii queue/run
|
||||
```
|
||||
|
||||
This command launches a daemon which infinitely queries the queue:
|
||||
|
||||
```sh
|
||||
yii queue/listen
|
||||
```
|
||||
|
||||
See the documentation for more details about driver specific console commands and their options.
|
||||
|
||||
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 = Yii::$app->queue->push(new SomeJob());
|
||||
|
||||
// Check whether the job is waiting for execution.
|
||||
Yii::$app->queue->isWaiting($id);
|
||||
|
||||
// Check whether a worker got the job from the queue and executes it.
|
||||
Yii::$app->queue->isReserved($id);
|
||||
|
||||
// Check whether a worker has executed the job.
|
||||
Yii::$app->queue->isDone($id);
|
||||
```
|
||||
|
||||
For more details see [the guide](docs/guide/README.md).
|
||||
105
vendor/yiisoft/yii2-queue/UPGRADE.md
vendored
Normal file
105
vendor/yiisoft/yii2-queue/UPGRADE.md
vendored
Normal file
@ -0,0 +1,105 @@
|
||||
Upgrading Instructions
|
||||
======================
|
||||
|
||||
This file contains the upgrade notes. These notes highlight changes that could break your
|
||||
application when you upgrade the package from one version to another.
|
||||
|
||||
Upgrade to 2.3.6
|
||||
----------------
|
||||
|
||||
* The `maxPriority` property was removed from [amqp_interop](docs/guide/driver-amqp-interop.md).
|
||||
Use property `queueOptionalArguments` argument `x-max-priority`.
|
||||
|
||||
Upgrade to 2.1.1
|
||||
----------------
|
||||
|
||||
* `\yii\queue\ErrorEvent` has been deprecated and will be removed in `3.0`.
|
||||
Use `\yii\queue\ExecEvent` instead.
|
||||
|
||||
Upgrade from 2.0.1 to 2.0.2
|
||||
---------------------------
|
||||
|
||||
* The [Amqp driver](docs/guide/driver-amqp.md) has been deprecated and will be removed in `2.1`.
|
||||
It is advised to migrate to [Amqp Interop](docs/guide/driver-amqp-interop.md) instead.
|
||||
|
||||
* Added `\yii\queue\cli\Command::isWorkerAction()` abstract method. If you use your own console
|
||||
controllers to run queue listeners, you must implement it.
|
||||
|
||||
* `\yii\queue\cli\Signal` helper is deprecated and will be removed in `2.1`. The extension uses
|
||||
`\yii\queue\cli\SignalLoop` instead of the helper.
|
||||
|
||||
* If you use your own console controller to listen to a queue, you must upgrade it. See the native
|
||||
console controllers for how to upgrade.
|
||||
|
||||
Upgrade from 2.0.0 to 2.0.1
|
||||
---------------------------
|
||||
|
||||
* `yii\queue\cli\Verbose` behavior was renamed to `yii\queue\cli\VerboseBehavior`. The old class was
|
||||
marked as deprecated and will be removed in `2.1.0`.
|
||||
|
||||
* `Job`, `RetryableJob` and `Serializer` interfaces were renamed to `JobInterface`,
|
||||
`RetryableJobInterface` and `SerializerInterface`. The old names are declared as deprecated
|
||||
and will be removed in `2.1.0`.
|
||||
|
||||
Upgrade from 1.1.0 to 2.0.0
|
||||
---------------------------
|
||||
|
||||
* Code has been moved to yii namespace. Check and replace `zhuravljov\yii` to `yii` namespace for
|
||||
your project.
|
||||
|
||||
Upgrade from 1.0.0 to 1.1.0
|
||||
---------------------------
|
||||
|
||||
* Event `Queue::EVENT_AFTER_EXEC_ERROR` renamed to `Queue::EVENT_AFTER_ERROR`.
|
||||
|
||||
* Removed method `Queue::later()`. Use method chain `Yii::$app->queue->delay(60)->push()` instead.
|
||||
|
||||
* Changed table schema for DB driver. Apply migration.
|
||||
|
||||
|
||||
Upgrade from 0.x to 1.0.0
|
||||
-------------------------
|
||||
|
||||
* Some methods and constants were modified.
|
||||
|
||||
- Method `Job::run()` modified to `Job::execute($queue)`.
|
||||
- Const `Queue::EVENT_BEFORE_WORK` renamed to `Queue::EVENT_BEFORE_EXEC`.
|
||||
- Const `Queue::EVENT_AFTER_WORK` renamed to `Queue::EVENT_AFTER_EXEC`.
|
||||
- Const `Queue::EVENT_AFTER_ERROR` renamed to `Queue::EVENT_AFTER_EXEC_ERROR`.
|
||||
|
||||
* Method `Queue::sendMessage` renamed to `Queue::pushMessage`. Check it if you use it in your own
|
||||
custom drivers.
|
||||
|
||||
|
||||
Upgrade from 0.10.1
|
||||
-------------------
|
||||
|
||||
* Driver property was removed and this functionality was moved into queue classes. If you use public
|
||||
methods of `Yii::$app->queue->driver` you need to use the methods of `Yii::$app->queue`.
|
||||
|
||||
You also need to check your configs. For example, now the config for the db queue is:
|
||||
|
||||
```php
|
||||
'queue' => [
|
||||
'class' => \zhuravljov\yii\queue\db\Queue::class,
|
||||
'db' => 'db',
|
||||
'tableName' => '{{%queue}}',
|
||||
'channel' => 'default',
|
||||
'mutex' => \yii\mutex\MysqlMutex::class,
|
||||
],
|
||||
```
|
||||
|
||||
Instead of the old variant:
|
||||
|
||||
```php
|
||||
'queue' => [
|
||||
'class' => \zhuravljov\yii\queue\Queue::class,
|
||||
'driver' => [
|
||||
'class' => \yii\queue\db\Driver::class,
|
||||
'db' => 'db',
|
||||
'tableName' => '{{%queue}}'
|
||||
'channel' => 'default',
|
||||
'mutex' => \yii\mutex\MysqlMutex::class,
|
||||
],
|
||||
],
|
||||
```
|
||||
94
vendor/yiisoft/yii2-queue/composer.json
vendored
Normal file
94
vendor/yiisoft/yii2-queue/composer.json
vendored
Normal file
@ -0,0 +1,94 @@
|
||||
{
|
||||
"name": "yiisoft/yii2-queue",
|
||||
"description": "Yii2 Queue Extension which supports queues based on DB, Redis, RabbitMQ, Beanstalk, SQS, and Gearman",
|
||||
"type": "yii2-extension",
|
||||
"keywords": ["yii", "queue", "async", "gii", "db", "redis", "rabbitmq", "beanstalk", "gearman", "sqs"],
|
||||
"license": "BSD-3-Clause",
|
||||
"authors": [
|
||||
{
|
||||
"name": "Roman Zhuravlev",
|
||||
"email": "zhuravljov@gmail.com"
|
||||
}
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/yiisoft/yii2-queue/issues",
|
||||
"source": "https://github.com/yiisoft/yii2-queue",
|
||||
"docs": "https://github.com/yiisoft/yii2-queue/blob/master/docs/guide"
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.5.0",
|
||||
"yiisoft/yii2": "~2.0.14",
|
||||
"symfony/process": "^3.3||^4.0||^5.0||^6.0||^7.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"yiisoft/yii2-redis": "2.0.19",
|
||||
"php-amqplib/php-amqplib": "^2.8.0||^3.0.0",
|
||||
"enqueue/amqp-lib": "^0.8||^0.9.10||^0.10.0",
|
||||
"pda/pheanstalk": "~3.2.1",
|
||||
"opis/closure": "*",
|
||||
"yiisoft/yii2-debug": "~2.1.0",
|
||||
"yiisoft/yii2-gii": "~2.2.0",
|
||||
"phpunit/phpunit": "4.8.34",
|
||||
"aws/aws-sdk-php": ">=2.4",
|
||||
"enqueue/stomp": "^0.8.39||0.10.19",
|
||||
"cweagans/composer-patches": "^1.7"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-pcntl": "Need for process signals.",
|
||||
"yiisoft/yii2-redis": "Need for Redis queue.",
|
||||
"pda/pheanstalk": "Need for Beanstalk queue.",
|
||||
"php-amqplib/php-amqplib": "Need for AMQP queue.",
|
||||
"enqueue/amqp-lib": "Need for AMQP interop queue.",
|
||||
"ext-gearman": "Need for Gearman queue.",
|
||||
"aws/aws-sdk-php": "Need for aws SQS.",
|
||||
"enqueue/stomp": "Need for Stomp queue."
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"yii\\queue\\": "src",
|
||||
"yii\\queue\\amqp\\": "src/drivers/amqp",
|
||||
"yii\\queue\\amqp_interop\\": "src/drivers/amqp_interop",
|
||||
"yii\\queue\\beanstalk\\": "src/drivers/beanstalk",
|
||||
"yii\\queue\\db\\": "src/drivers/db",
|
||||
"yii\\queue\\file\\": "src/drivers/file",
|
||||
"yii\\queue\\gearman\\": "src/drivers/gearman",
|
||||
"yii\\queue\\redis\\": "src/drivers/redis",
|
||||
"yii\\queue\\sync\\": "src/drivers/sync",
|
||||
"yii\\queue\\sqs\\": "src/drivers/sqs",
|
||||
"yii\\queue\\stomp\\": "src/drivers/stomp"
|
||||
}
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": {
|
||||
"tests\\": "tests"
|
||||
}
|
||||
},
|
||||
"config": {
|
||||
"allow-plugins": {
|
||||
"yiisoft/yii2-composer": true,
|
||||
"cweagans/composer-patches": true,
|
||||
"php-http/discovery": true
|
||||
}
|
||||
},
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "2.x-dev"
|
||||
},
|
||||
"composer-exit-on-patch-failure": true,
|
||||
"patches": {
|
||||
"phpunit/phpunit-mock-objects": {
|
||||
"Fix PHP 7 and 8 compatibility": "https://yiisoft.github.io/phpunit-patches/phpunit_mock_objects.patch"
|
||||
},
|
||||
"phpunit/phpunit": {
|
||||
"Fix PHP 7 compatibility": "https://yiisoft.github.io/phpunit-patches/phpunit_php7.patch",
|
||||
"Fix PHP 8 compatibility": "https://yiisoft.github.io/phpunit-patches/phpunit_php8.patch"
|
||||
}
|
||||
}
|
||||
},
|
||||
"repositories": [
|
||||
{
|
||||
"type": "composer",
|
||||
"url": "https://asset-packagist.org"
|
||||
}
|
||||
]
|
||||
}
|
||||
42
vendor/yiisoft/yii2-queue/src/ExecEvent.php
vendored
Normal file
42
vendor/yiisoft/yii2-queue/src/ExecEvent.php
vendored
Normal file
@ -0,0 +1,42 @@
|
||||
<?php
|
||||
/**
|
||||
* @link https://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license https://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\queue;
|
||||
|
||||
/**
|
||||
* Exec Event.
|
||||
*
|
||||
* @author Roman Zhuravlev <zhuravljov@gmail.com>
|
||||
*/
|
||||
class ExecEvent extends JobEvent
|
||||
{
|
||||
/**
|
||||
* @var int attempt number.
|
||||
* @see Queue::EVENT_BEFORE_EXEC
|
||||
* @see Queue::EVENT_AFTER_EXEC
|
||||
* @see Queue::EVENT_AFTER_ERROR
|
||||
*/
|
||||
public $attempt;
|
||||
/**
|
||||
* @var mixed result of a job execution in case job is done.
|
||||
* @see Queue::EVENT_AFTER_EXEC
|
||||
* @since 2.1.1
|
||||
*/
|
||||
public $result;
|
||||
/**
|
||||
* @var null|\Exception|\Throwable
|
||||
* @see Queue::EVENT_AFTER_ERROR
|
||||
* @since 2.1.1
|
||||
*/
|
||||
public $error;
|
||||
/**
|
||||
* @var null|bool
|
||||
* @see Queue::EVENT_AFTER_ERROR
|
||||
* @since 2.1.1
|
||||
*/
|
||||
public $retry;
|
||||
}
|
||||
47
vendor/yiisoft/yii2-queue/src/InvalidJobException.php
vendored
Normal file
47
vendor/yiisoft/yii2-queue/src/InvalidJobException.php
vendored
Normal file
@ -0,0 +1,47 @@
|
||||
<?php
|
||||
/**
|
||||
* @link https://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license https://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\queue;
|
||||
|
||||
use Throwable;
|
||||
|
||||
/**
|
||||
* Invalid Job Exception.
|
||||
*
|
||||
* Throws when serialized message cannot be unserialized to a job.
|
||||
*
|
||||
* @author Roman Zhuravlev <zhuravljov@gmail.com>
|
||||
* @since 2.1.1
|
||||
*/
|
||||
class InvalidJobException extends \Exception
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $serialized;
|
||||
|
||||
|
||||
/**
|
||||
* @param string $serialized
|
||||
* @param string $message
|
||||
* @param int $code
|
||||
* @param Throwable|null $previous
|
||||
*/
|
||||
public function __construct($serialized, $message = '', $code = 0, $previous = null)
|
||||
{
|
||||
$this->serialized = $serialized;
|
||||
parent::__construct($message, $code, $previous);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string of serialized message that cannot be unserialized to a job
|
||||
*/
|
||||
final public function getSerialized()
|
||||
{
|
||||
return $this->serialized;
|
||||
}
|
||||
}
|
||||
19
vendor/yiisoft/yii2-queue/src/Job.php
vendored
Normal file
19
vendor/yiisoft/yii2-queue/src/Job.php
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
<?php
|
||||
/**
|
||||
* @link https://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license https://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\queue;
|
||||
|
||||
/**
|
||||
* Job Interface.
|
||||
*
|
||||
* @deprecated Will be removed in 3.0. Use JobInterface instead of Job.
|
||||
*
|
||||
* @author Roman Zhuravlev <zhuravljov@gmail.com>
|
||||
*/
|
||||
interface Job extends JobInterface
|
||||
{
|
||||
}
|
||||
36
vendor/yiisoft/yii2-queue/src/JobEvent.php
vendored
Normal file
36
vendor/yiisoft/yii2-queue/src/JobEvent.php
vendored
Normal file
@ -0,0 +1,36 @@
|
||||
<?php
|
||||
/**
|
||||
* @link https://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license https://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\queue;
|
||||
|
||||
use yii\base\Event;
|
||||
|
||||
/**
|
||||
* Job Event.
|
||||
*
|
||||
* @author Roman Zhuravlev <zhuravljov@gmail.com>
|
||||
*/
|
||||
abstract class JobEvent extends Event
|
||||
{
|
||||
/**
|
||||
* @var Queue
|
||||
* @inheritdoc
|
||||
*/
|
||||
public $sender;
|
||||
/**
|
||||
* @var string|null unique id of a job
|
||||
*/
|
||||
public $id;
|
||||
/**
|
||||
* @var JobInterface|null
|
||||
*/
|
||||
public $job;
|
||||
/**
|
||||
* @var int time to reserve in seconds of the job
|
||||
*/
|
||||
public $ttr;
|
||||
}
|
||||
22
vendor/yiisoft/yii2-queue/src/JobInterface.php
vendored
Normal file
22
vendor/yiisoft/yii2-queue/src/JobInterface.php
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
<?php
|
||||
/**
|
||||
* @link https://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license https://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\queue;
|
||||
|
||||
/**
|
||||
* Job Interface.
|
||||
*
|
||||
* @author Roman Zhuravlev <zhuravljov@gmail.com>
|
||||
*/
|
||||
interface JobInterface
|
||||
{
|
||||
/**
|
||||
* @param Queue $queue which pushed and is handling the job
|
||||
* @return void|mixed result of the job execution
|
||||
*/
|
||||
public function execute($queue);
|
||||
}
|
||||
144
vendor/yiisoft/yii2-queue/src/LogBehavior.php
vendored
Normal file
144
vendor/yiisoft/yii2-queue/src/LogBehavior.php
vendored
Normal file
@ -0,0 +1,144 @@
|
||||
<?php
|
||||
/**
|
||||
* @link https://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license https://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\queue;
|
||||
|
||||
use Yii;
|
||||
use yii\base\Behavior;
|
||||
|
||||
/**
|
||||
* Log Behavior.
|
||||
*
|
||||
* @author Roman Zhuravlev <zhuravljov@gmail.com>
|
||||
*/
|
||||
class LogBehavior extends Behavior
|
||||
{
|
||||
/**
|
||||
* @var Queue
|
||||
* @inheritdoc
|
||||
*/
|
||||
public $owner;
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
public $autoFlush = true;
|
||||
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function events()
|
||||
{
|
||||
return [
|
||||
Queue::EVENT_AFTER_PUSH => 'afterPush',
|
||||
Queue::EVENT_BEFORE_EXEC => 'beforeExec',
|
||||
Queue::EVENT_AFTER_EXEC => 'afterExec',
|
||||
Queue::EVENT_AFTER_ERROR => 'afterError',
|
||||
cli\Queue::EVENT_WORKER_START => 'workerStart',
|
||||
cli\Queue::EVENT_WORKER_STOP => 'workerStop',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param PushEvent $event
|
||||
*/
|
||||
public function afterPush(PushEvent $event)
|
||||
{
|
||||
$title = $this->getJobTitle($event);
|
||||
Yii::info("$title is pushed.", Queue::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ExecEvent $event
|
||||
*/
|
||||
public function beforeExec(ExecEvent $event)
|
||||
{
|
||||
$title = $this->getExecTitle($event);
|
||||
Yii::info("$title is started.", Queue::class);
|
||||
Yii::beginProfile($title, Queue::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ExecEvent $event
|
||||
*/
|
||||
public function afterExec(ExecEvent $event)
|
||||
{
|
||||
$title = $this->getExecTitle($event);
|
||||
Yii::endProfile($title, Queue::class);
|
||||
Yii::info("$title is finished.", Queue::class);
|
||||
if ($this->autoFlush) {
|
||||
Yii::getLogger()->flush(true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ExecEvent $event
|
||||
*/
|
||||
public function afterError(ExecEvent $event)
|
||||
{
|
||||
$title = $this->getExecTitle($event);
|
||||
Yii::endProfile($title, Queue::class);
|
||||
Yii::error("$title is finished with error: $event->error.", Queue::class);
|
||||
if ($this->autoFlush) {
|
||||
Yii::getLogger()->flush(true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param cli\WorkerEvent $event
|
||||
* @since 2.0.2
|
||||
*/
|
||||
public function workerStart(cli\WorkerEvent $event)
|
||||
{
|
||||
$title = 'Worker ' . $event->sender->getWorkerPid();
|
||||
Yii::info("$title is started.", Queue::class);
|
||||
Yii::beginProfile($title, Queue::class);
|
||||
if ($this->autoFlush) {
|
||||
Yii::getLogger()->flush(true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param cli\WorkerEvent $event
|
||||
* @since 2.0.2
|
||||
*/
|
||||
public function workerStop(cli\WorkerEvent $event)
|
||||
{
|
||||
$title = 'Worker ' . $event->sender->getWorkerPid();
|
||||
Yii::endProfile($title, Queue::class);
|
||||
Yii::info("$title is stopped.", Queue::class);
|
||||
if ($this->autoFlush) {
|
||||
Yii::getLogger()->flush(true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param JobEvent $event
|
||||
* @return string
|
||||
* @since 2.0.2
|
||||
*/
|
||||
protected function getJobTitle(JobEvent $event)
|
||||
{
|
||||
$name = $event->job instanceof JobInterface ? get_class($event->job) : 'unknown job';
|
||||
return "[$event->id] $name";
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ExecEvent $event
|
||||
* @return string
|
||||
* @since 2.0.2
|
||||
*/
|
||||
protected function getExecTitle(ExecEvent $event)
|
||||
{
|
||||
$title = $this->getJobTitle($event);
|
||||
$extra = "attempt: $event->attempt";
|
||||
if ($pid = $event->sender->getWorkerPid()) {
|
||||
$extra .= ", PID: $pid";
|
||||
}
|
||||
return "$title ($extra)";
|
||||
}
|
||||
}
|
||||
25
vendor/yiisoft/yii2-queue/src/PushEvent.php
vendored
Normal file
25
vendor/yiisoft/yii2-queue/src/PushEvent.php
vendored
Normal file
@ -0,0 +1,25 @@
|
||||
<?php
|
||||
/**
|
||||
* @link https://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license https://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\queue;
|
||||
|
||||
/**
|
||||
* Push Event.
|
||||
*
|
||||
* @author Roman Zhuravlev <zhuravljov@gmail.com>
|
||||
*/
|
||||
class PushEvent extends JobEvent
|
||||
{
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
public $delay;
|
||||
/**
|
||||
* @var mixed
|
||||
*/
|
||||
public $priority;
|
||||
}
|
||||
337
vendor/yiisoft/yii2-queue/src/Queue.php
vendored
Normal file
337
vendor/yiisoft/yii2-queue/src/Queue.php
vendored
Normal file
@ -0,0 +1,337 @@
|
||||
<?php
|
||||
/**
|
||||
* @link https://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license https://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\queue;
|
||||
|
||||
use Yii;
|
||||
use yii\base\Component;
|
||||
use yii\base\InvalidArgumentException;
|
||||
use yii\base\InvalidConfigException;
|
||||
use yii\di\Instance;
|
||||
use yii\helpers\VarDumper;
|
||||
use yii\queue\serializers\PhpSerializer;
|
||||
use yii\queue\serializers\SerializerInterface;
|
||||
|
||||
/**
|
||||
* Base Queue.
|
||||
*
|
||||
* @author Roman Zhuravlev <zhuravljov@gmail.com>
|
||||
*/
|
||||
abstract class Queue extends Component
|
||||
{
|
||||
/**
|
||||
* @event PushEvent
|
||||
*/
|
||||
const EVENT_BEFORE_PUSH = 'beforePush';
|
||||
/**
|
||||
* @event PushEvent
|
||||
*/
|
||||
const EVENT_AFTER_PUSH = 'afterPush';
|
||||
/**
|
||||
* @event ExecEvent
|
||||
*/
|
||||
const EVENT_BEFORE_EXEC = 'beforeExec';
|
||||
/**
|
||||
* @event ExecEvent
|
||||
*/
|
||||
const EVENT_AFTER_EXEC = 'afterExec';
|
||||
/**
|
||||
* @event ExecEvent
|
||||
*/
|
||||
const EVENT_AFTER_ERROR = 'afterError';
|
||||
/**
|
||||
* @see Queue::isWaiting()
|
||||
*/
|
||||
const STATUS_WAITING = 1;
|
||||
/**
|
||||
* @see Queue::isReserved()
|
||||
*/
|
||||
const STATUS_RESERVED = 2;
|
||||
/**
|
||||
* @see Queue::isDone()
|
||||
*/
|
||||
const STATUS_DONE = 3;
|
||||
|
||||
/**
|
||||
* @var bool whether to enable strict job type control.
|
||||
* Note that in order to enable type control, a pushing job must be [[JobInterface]] instance.
|
||||
* @since 2.0.1
|
||||
*/
|
||||
public $strictJobType = true;
|
||||
/**
|
||||
* @var SerializerInterface|array
|
||||
*/
|
||||
public $serializer = PhpSerializer::class;
|
||||
/**
|
||||
* @var int default time to reserve a job
|
||||
*/
|
||||
public $ttr = 300;
|
||||
/**
|
||||
* @var int default attempt count
|
||||
*/
|
||||
public $attempts = 1;
|
||||
|
||||
private $pushTtr;
|
||||
private $pushDelay;
|
||||
private $pushPriority;
|
||||
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function init()
|
||||
{
|
||||
parent::init();
|
||||
|
||||
$this->serializer = Instance::ensure($this->serializer, SerializerInterface::class);
|
||||
|
||||
if (!is_numeric($this->ttr)) {
|
||||
throw new InvalidConfigException('Default TTR must be integer.');
|
||||
}
|
||||
$this->ttr = (int) $this->ttr;
|
||||
if ($this->ttr <= 0) {
|
||||
throw new InvalidConfigException('Default TTR must be greater that zero.');
|
||||
}
|
||||
|
||||
if (!is_numeric($this->attempts)) {
|
||||
throw new InvalidConfigException('Default attempts count must be integer.');
|
||||
}
|
||||
$this->attempts = (int) $this->attempts;
|
||||
if ($this->attempts <= 0) {
|
||||
throw new InvalidConfigException('Default attempts count must be greater that zero.');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets TTR for job execute.
|
||||
*
|
||||
* @param int|mixed $value
|
||||
* @return $this
|
||||
*/
|
||||
public function ttr($value)
|
||||
{
|
||||
$this->pushTtr = $value;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets delay for later execute.
|
||||
*
|
||||
* @param int|mixed $value
|
||||
* @return $this
|
||||
*/
|
||||
public function delay($value)
|
||||
{
|
||||
$this->pushDelay = $value;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets job priority.
|
||||
*
|
||||
* @param mixed $value
|
||||
* @return $this
|
||||
*/
|
||||
public function priority($value)
|
||||
{
|
||||
$this->pushPriority = $value;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Pushes job into queue.
|
||||
*
|
||||
* @param JobInterface|mixed $job
|
||||
* @return string|null id of a job message
|
||||
*/
|
||||
public function push($job)
|
||||
{
|
||||
$event = new PushEvent([
|
||||
'job' => $job,
|
||||
'ttr' => $this->pushTtr ?: (
|
||||
$job instanceof RetryableJobInterface
|
||||
? $job->getTtr()
|
||||
: $this->ttr
|
||||
),
|
||||
'delay' => $this->pushDelay ?: 0,
|
||||
'priority' => $this->pushPriority,
|
||||
]);
|
||||
$this->pushTtr = null;
|
||||
$this->pushDelay = null;
|
||||
$this->pushPriority = null;
|
||||
|
||||
$this->trigger(self::EVENT_BEFORE_PUSH, $event);
|
||||
if ($event->handled) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if ($this->strictJobType && !($event->job instanceof JobInterface)) {
|
||||
throw new InvalidArgumentException('Job must be instance of JobInterface.');
|
||||
}
|
||||
|
||||
if (!is_numeric($event->ttr)) {
|
||||
throw new InvalidArgumentException('Job TTR must be integer.');
|
||||
}
|
||||
$event->ttr = (int) $event->ttr;
|
||||
if ($event->ttr <= 0) {
|
||||
throw new InvalidArgumentException('Job TTR must be greater that zero.');
|
||||
}
|
||||
|
||||
if (!is_numeric($event->delay)) {
|
||||
throw new InvalidArgumentException('Job delay must be integer.');
|
||||
}
|
||||
$event->delay = (int) $event->delay;
|
||||
if ($event->delay < 0) {
|
||||
throw new InvalidArgumentException('Job delay must be positive.');
|
||||
}
|
||||
|
||||
$message = $this->serializer->serialize($event->job);
|
||||
$event->id = $this->pushMessage($message, $event->ttr, $event->delay, $event->priority);
|
||||
$this->trigger(self::EVENT_AFTER_PUSH, $event);
|
||||
|
||||
return $event->id;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $message
|
||||
* @param int $ttr time to reserve in seconds
|
||||
* @param int $delay
|
||||
* @param mixed $priority
|
||||
* @return string id of a job message
|
||||
*/
|
||||
abstract protected function pushMessage($message, $ttr, $delay, $priority);
|
||||
|
||||
/**
|
||||
* Uses for CLI drivers and gets process ID of a worker.
|
||||
*
|
||||
* @since 2.0.2
|
||||
*/
|
||||
public function getWorkerPid()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $id of a job message
|
||||
* @param string $message
|
||||
* @param int $ttr time to reserve
|
||||
* @param int $attempt number
|
||||
* @return bool
|
||||
*/
|
||||
protected function handleMessage($id, $message, $ttr, $attempt)
|
||||
{
|
||||
list($job, $error) = $this->unserializeMessage($message);
|
||||
|
||||
// Handle aborted jobs without throwing an error.
|
||||
if ($attempt > 1 &&
|
||||
(($job instanceof RetryableJobInterface && !$job->canRetry($attempt - 1, $error))
|
||||
|| (!($job instanceof RetryableJobInterface) && $attempt > $this->attempts))) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$event = new ExecEvent([
|
||||
'id' => $id,
|
||||
'job' => $job,
|
||||
'ttr' => $ttr,
|
||||
'attempt' => $attempt,
|
||||
'error' => $error,
|
||||
]);
|
||||
$this->trigger(self::EVENT_BEFORE_EXEC, $event);
|
||||
if ($event->handled) {
|
||||
return true;
|
||||
}
|
||||
if ($event->error) {
|
||||
return $this->handleError($event);
|
||||
}
|
||||
try {
|
||||
$event->result = $event->job->execute($this);
|
||||
} catch (\Exception $error) {
|
||||
$event->error = $error;
|
||||
return $this->handleError($event);
|
||||
} catch (\Throwable $error) {
|
||||
$event->error = $error;
|
||||
return $this->handleError($event);
|
||||
}
|
||||
$this->trigger(self::EVENT_AFTER_EXEC, $event);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unserializes.
|
||||
*
|
||||
* @param string $id of the job
|
||||
* @param string $serialized message
|
||||
* @return array pair of a job and error that
|
||||
*/
|
||||
public function unserializeMessage($serialized)
|
||||
{
|
||||
try {
|
||||
$job = $this->serializer->unserialize($serialized);
|
||||
} catch (\Exception $e) {
|
||||
return [null, new InvalidJobException($serialized, $e->getMessage(), 0, $e)];
|
||||
}
|
||||
|
||||
if ($job instanceof JobInterface) {
|
||||
return [$job, null];
|
||||
}
|
||||
|
||||
return [null, new InvalidJobException($serialized, sprintf(
|
||||
'Job must be a JobInterface instance instead of %s.',
|
||||
VarDumper::dumpAsString($job)
|
||||
))];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ExecEvent $event
|
||||
* @return bool
|
||||
* @internal
|
||||
*/
|
||||
public function handleError(ExecEvent $event)
|
||||
{
|
||||
$event->retry = $event->attempt < $this->attempts;
|
||||
if ($event->error instanceof InvalidJobException) {
|
||||
$event->retry = false;
|
||||
} elseif ($event->job instanceof RetryableJobInterface) {
|
||||
$event->retry = $event->job->canRetry($event->attempt, $event->error);
|
||||
}
|
||||
$this->trigger(self::EVENT_AFTER_ERROR, $event);
|
||||
return !$event->retry;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $id of a job message
|
||||
* @return bool
|
||||
*/
|
||||
public function isWaiting($id)
|
||||
{
|
||||
return $this->status($id) === self::STATUS_WAITING;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $id of a job message
|
||||
* @return bool
|
||||
*/
|
||||
public function isReserved($id)
|
||||
{
|
||||
return $this->status($id) === self::STATUS_RESERVED;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $id of a job message
|
||||
* @return bool
|
||||
*/
|
||||
public function isDone($id)
|
||||
{
|
||||
return $this->status($id) === self::STATUS_DONE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $id of a job message
|
||||
* @return int status code
|
||||
*/
|
||||
abstract public function status($id);
|
||||
}
|
||||
19
vendor/yiisoft/yii2-queue/src/RetryableJob.php
vendored
Normal file
19
vendor/yiisoft/yii2-queue/src/RetryableJob.php
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
<?php
|
||||
/**
|
||||
* @link https://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license https://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\queue;
|
||||
|
||||
/**
|
||||
* Retryable Job Interface.
|
||||
*
|
||||
* @deprecated Will be removed in 3.0. Use RetryableJobInterface instead of RetryableJob.
|
||||
*
|
||||
* @author Roman Zhuravlev <zhuravljov@gmail.com>
|
||||
*/
|
||||
interface RetryableJob extends RetryableJobInterface
|
||||
{
|
||||
}
|
||||
28
vendor/yiisoft/yii2-queue/src/RetryableJobInterface.php
vendored
Normal file
28
vendor/yiisoft/yii2-queue/src/RetryableJobInterface.php
vendored
Normal file
@ -0,0 +1,28 @@
|
||||
<?php
|
||||
/**
|
||||
* @link https://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license https://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\queue;
|
||||
|
||||
/**
|
||||
* Retryable Job Interface.
|
||||
*
|
||||
* @author Roman Zhuravlev <zhuravljov@gmail.com>
|
||||
*/
|
||||
interface RetryableJobInterface extends JobInterface
|
||||
{
|
||||
/**
|
||||
* @return int time to reserve in seconds
|
||||
*/
|
||||
public function getTtr();
|
||||
|
||||
/**
|
||||
* @param int $attempt number
|
||||
* @param \Exception|\Throwable $error from last execute of the job
|
||||
* @return bool
|
||||
*/
|
||||
public function canRetry($attempt, $error);
|
||||
}
|
||||
57
vendor/yiisoft/yii2-queue/src/cli/Action.php
vendored
Normal file
57
vendor/yiisoft/yii2-queue/src/cli/Action.php
vendored
Normal file
@ -0,0 +1,57 @@
|
||||
<?php
|
||||
/**
|
||||
* @link https://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license https://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\queue\cli;
|
||||
|
||||
use yii\base\Action as BaseAction;
|
||||
use yii\base\InvalidConfigException;
|
||||
use yii\console\Controller as ConsoleController;
|
||||
|
||||
/**
|
||||
* Base Command Action.
|
||||
*
|
||||
* @author Roman Zhuravlev <zhuravljov@gmail.com>
|
||||
*/
|
||||
abstract class Action extends BaseAction
|
||||
{
|
||||
/**
|
||||
* @var Queue
|
||||
*/
|
||||
public $queue;
|
||||
/**
|
||||
* @var Command|ConsoleController
|
||||
*/
|
||||
public $controller;
|
||||
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function init()
|
||||
{
|
||||
parent::init();
|
||||
|
||||
if (!$this->queue && ($this->controller instanceof Command)) {
|
||||
$this->queue = $this->controller->queue;
|
||||
}
|
||||
if (!($this->controller instanceof ConsoleController)) {
|
||||
throw new InvalidConfigException('The controller must be console controller.');
|
||||
}
|
||||
if (!($this->queue instanceof Queue)) {
|
||||
throw new InvalidConfigException('The queue must be cli queue.');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $string
|
||||
* @return string
|
||||
*/
|
||||
protected function format($string)
|
||||
{
|
||||
return call_user_func_array([$this->controller, 'ansiFormat'], func_get_args());
|
||||
}
|
||||
}
|
||||
209
vendor/yiisoft/yii2-queue/src/cli/Command.php
vendored
Normal file
209
vendor/yiisoft/yii2-queue/src/cli/Command.php
vendored
Normal file
@ -0,0 +1,209 @@
|
||||
<?php
|
||||
/**
|
||||
* @link https://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license https://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\queue\cli;
|
||||
|
||||
use Symfony\Component\Process\Exception\ProcessFailedException;
|
||||
use Symfony\Component\Process\Exception\RuntimeException as ProcessRuntimeException;
|
||||
use Symfony\Component\Process\Process;
|
||||
use yii\console\Controller;
|
||||
use yii\queue\ExecEvent;
|
||||
|
||||
/**
|
||||
* Base Command.
|
||||
*
|
||||
* @author Roman Zhuravlev <zhuravljov@gmail.com>
|
||||
*/
|
||||
abstract class Command extends Controller
|
||||
{
|
||||
/**
|
||||
* The exit code of the exec action which is returned when job was done.
|
||||
*/
|
||||
const EXEC_DONE = 0;
|
||||
/**
|
||||
* The exit code of the exec action which is returned when job wasn't done and wanted next attempt.
|
||||
*/
|
||||
const EXEC_RETRY = 3;
|
||||
|
||||
/**
|
||||
* @var Queue
|
||||
*/
|
||||
public $queue;
|
||||
/**
|
||||
* @var bool verbose mode of a job execute. If enabled, execute result of each job
|
||||
* will be printed.
|
||||
*/
|
||||
public $verbose = false;
|
||||
/**
|
||||
* @var array additional options to the verbose behavior.
|
||||
* @since 2.0.2
|
||||
*/
|
||||
public $verboseConfig = [
|
||||
'class' => VerboseBehavior::class,
|
||||
];
|
||||
/**
|
||||
* @var bool isolate mode. It executes a job in a child process.
|
||||
*/
|
||||
public $isolate = true;
|
||||
/**
|
||||
* @var string path to php interpreter that uses to run child processes.
|
||||
* If it is undefined, PHP_BINARY will be used.
|
||||
* @since 2.0.3
|
||||
*/
|
||||
public $phpBinary;
|
||||
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function options($actionID)
|
||||
{
|
||||
$options = parent::options($actionID);
|
||||
if ($this->canVerbose($actionID)) {
|
||||
$options[] = 'verbose';
|
||||
}
|
||||
if ($this->canIsolate($actionID)) {
|
||||
$options[] = 'isolate';
|
||||
$options[] = 'phpBinary';
|
||||
}
|
||||
|
||||
return $options;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function optionAliases()
|
||||
{
|
||||
return array_merge(parent::optionAliases(), [
|
||||
'v' => 'verbose',
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $actionID
|
||||
* @return bool
|
||||
* @since 2.0.2
|
||||
*/
|
||||
abstract protected function isWorkerAction($actionID);
|
||||
|
||||
/**
|
||||
* @param string $actionID
|
||||
* @return bool
|
||||
*/
|
||||
protected function canVerbose($actionID)
|
||||
{
|
||||
return $actionID === 'exec' || $this->isWorkerAction($actionID);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $actionID
|
||||
* @return bool
|
||||
*/
|
||||
protected function canIsolate($actionID)
|
||||
{
|
||||
return $this->isWorkerAction($actionID);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function beforeAction($action)
|
||||
{
|
||||
if ($this->canVerbose($action->id) && $this->verbose) {
|
||||
$this->queue->attachBehavior('verbose', ['command' => $this] + $this->verboseConfig);
|
||||
}
|
||||
|
||||
if ($this->canIsolate($action->id) && $this->isolate) {
|
||||
if ($this->phpBinary === null) {
|
||||
$this->phpBinary = PHP_BINARY;
|
||||
}
|
||||
$this->queue->messageHandler = function ($id, $message, $ttr, $attempt) {
|
||||
return $this->handleMessage($id, $message, $ttr, $attempt);
|
||||
};
|
||||
}
|
||||
|
||||
return parent::beforeAction($action);
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes a job.
|
||||
* The command is internal, and used to isolate a job execution. Manual usage is not provided.
|
||||
*
|
||||
* @param string|null $id of a message
|
||||
* @param int $ttr time to reserve
|
||||
* @param int $attempt number
|
||||
* @param int $pid of a worker
|
||||
* @return int exit code
|
||||
* @internal It is used with isolate mode.
|
||||
*/
|
||||
public function actionExec($id, $ttr, $attempt, $pid)
|
||||
{
|
||||
if ($this->queue->execute($id, file_get_contents('php://stdin'), $ttr, $attempt, $pid ?: null)) {
|
||||
return self::EXEC_DONE;
|
||||
}
|
||||
return self::EXEC_RETRY;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles message using child process.
|
||||
*
|
||||
* @param string|null $id of a message
|
||||
* @param string $message
|
||||
* @param int $ttr time to reserve
|
||||
* @param int $attempt number
|
||||
* @return bool
|
||||
* @throws
|
||||
* @see actionExec()
|
||||
*/
|
||||
protected function handleMessage($id, $message, $ttr, $attempt)
|
||||
{
|
||||
// Child process command: php yii queue/exec "id" "ttr" "attempt" "pid"
|
||||
$cmd = [
|
||||
$this->phpBinary,
|
||||
$_SERVER['SCRIPT_FILENAME'],
|
||||
$this->uniqueId . '/exec',
|
||||
$id,
|
||||
$ttr,
|
||||
$attempt,
|
||||
$this->queue->getWorkerPid() ?: 0,
|
||||
];
|
||||
|
||||
foreach ($this->getPassedOptions() as $name) {
|
||||
if (in_array($name, $this->options('exec'), true)) {
|
||||
$cmd[] = '--' . $name . '=' . $this->$name;
|
||||
}
|
||||
}
|
||||
if (!in_array('color', $this->getPassedOptions(), true)) {
|
||||
$cmd[] = '--color=' . $this->isColorEnabled();
|
||||
}
|
||||
$env = isset($_ENV) ? $_ENV : null;
|
||||
$process = new Process($cmd, null, $env, $message, $ttr);
|
||||
try {
|
||||
$result = $process->run(function ($type, $buffer) {
|
||||
if ($type === Process::ERR) {
|
||||
$this->stderr($buffer);
|
||||
} else {
|
||||
$this->stdout($buffer);
|
||||
}
|
||||
});
|
||||
if (!in_array($result, [self::EXEC_DONE, self::EXEC_RETRY])) {
|
||||
throw new ProcessFailedException($process);
|
||||
}
|
||||
return $result === self::EXEC_DONE;
|
||||
} catch (ProcessRuntimeException $error) {
|
||||
list($job) = $this->queue->unserializeMessage($message);
|
||||
return $this->queue->handleError(new ExecEvent([
|
||||
'id' => $id,
|
||||
'job' => $job,
|
||||
'ttr' => $ttr,
|
||||
'attempt' => $attempt,
|
||||
'error' => $error,
|
||||
]));
|
||||
}
|
||||
}
|
||||
}
|
||||
63
vendor/yiisoft/yii2-queue/src/cli/InfoAction.php
vendored
Normal file
63
vendor/yiisoft/yii2-queue/src/cli/InfoAction.php
vendored
Normal file
@ -0,0 +1,63 @@
|
||||
<?php
|
||||
/**
|
||||
* @link https://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license https://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\queue\cli;
|
||||
|
||||
use yii\base\NotSupportedException;
|
||||
use yii\helpers\Console;
|
||||
use yii\queue\interfaces\DelayedCountInterface;
|
||||
use yii\queue\interfaces\DoneCountInterface;
|
||||
use yii\queue\interfaces\ReservedCountInterface;
|
||||
use yii\queue\interfaces\StatisticsProviderInterface;
|
||||
use yii\queue\interfaces\WaitingCountInterface;
|
||||
|
||||
/**
|
||||
* Info about queue status.
|
||||
*
|
||||
* @author Kalmer Kaurson <kalmerkaurson@gmail.com>
|
||||
*/
|
||||
class InfoAction extends Action
|
||||
{
|
||||
/**
|
||||
* @var Queue
|
||||
*/
|
||||
public $queue;
|
||||
|
||||
|
||||
/**
|
||||
* Info about queue status.
|
||||
*/
|
||||
public function run()
|
||||
{
|
||||
if (!($this->queue instanceof StatisticsProviderInterface)) {
|
||||
throw new NotSupportedException('Queue does not support ' . StatisticsProviderInterface::class);
|
||||
}
|
||||
|
||||
$this->controller->stdout('Jobs' . PHP_EOL, Console::FG_GREEN);
|
||||
$statisticsProvider = $this->queue->getStatisticsProvider();
|
||||
|
||||
if ($statisticsProvider instanceof WaitingCountInterface) {
|
||||
$this->controller->stdout('- waiting: ', Console::FG_YELLOW);
|
||||
$this->controller->stdout($statisticsProvider->getWaitingCount() . PHP_EOL);
|
||||
}
|
||||
|
||||
if ($statisticsProvider instanceof DelayedCountInterface) {
|
||||
$this->controller->stdout('- delayed: ', Console::FG_YELLOW);
|
||||
$this->controller->stdout($statisticsProvider->getDelayedCount() . PHP_EOL);
|
||||
}
|
||||
|
||||
if ($statisticsProvider instanceof ReservedCountInterface) {
|
||||
$this->controller->stdout('- reserved: ', Console::FG_YELLOW);
|
||||
$this->controller->stdout($statisticsProvider->getReservedCount() . PHP_EOL);
|
||||
}
|
||||
|
||||
if ($statisticsProvider instanceof DoneCountInterface) {
|
||||
$this->controller->stdout('- done: ', Console::FG_YELLOW);
|
||||
$this->controller->stdout($statisticsProvider->getDoneCount() . PHP_EOL);
|
||||
}
|
||||
}
|
||||
}
|
||||
22
vendor/yiisoft/yii2-queue/src/cli/LoopInterface.php
vendored
Normal file
22
vendor/yiisoft/yii2-queue/src/cli/LoopInterface.php
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
<?php
|
||||
/**
|
||||
* @link https://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license https://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\queue\cli;
|
||||
|
||||
/**
|
||||
* Loop Interface.
|
||||
*
|
||||
* @author Roman Zhuravlev <zhuravljov@gmail.com>
|
||||
* @since 2.0.2
|
||||
*/
|
||||
interface LoopInterface
|
||||
{
|
||||
/**
|
||||
* @return bool whether to continue listening of the queue.
|
||||
*/
|
||||
public function canContinue();
|
||||
}
|
||||
166
vendor/yiisoft/yii2-queue/src/cli/Queue.php
vendored
Normal file
166
vendor/yiisoft/yii2-queue/src/cli/Queue.php
vendored
Normal file
@ -0,0 +1,166 @@
|
||||
<?php
|
||||
/**
|
||||
* @link https://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license https://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\queue\cli;
|
||||
|
||||
use Yii;
|
||||
use yii\base\BootstrapInterface;
|
||||
use yii\base\InvalidConfigException;
|
||||
use yii\console\Application as ConsoleApp;
|
||||
use yii\helpers\Inflector;
|
||||
use yii\queue\Queue as BaseQueue;
|
||||
|
||||
/**
|
||||
* Queue with CLI.
|
||||
*
|
||||
* @property-read int|null $workerPid
|
||||
*
|
||||
* @author Roman Zhuravlev <zhuravljov@gmail.com>
|
||||
*/
|
||||
abstract class Queue extends BaseQueue implements BootstrapInterface
|
||||
{
|
||||
/**
|
||||
* @event WorkerEvent that is triggered when the worker is started.
|
||||
* @since 2.0.2
|
||||
*/
|
||||
const EVENT_WORKER_START = 'workerStart';
|
||||
/**
|
||||
* @event WorkerEvent that is triggered each iteration between requests to queue.
|
||||
* @since 2.0.3
|
||||
*/
|
||||
const EVENT_WORKER_LOOP = 'workerLoop';
|
||||
/**
|
||||
* @event WorkerEvent that is triggered when the worker is stopped.
|
||||
* @since 2.0.2
|
||||
*/
|
||||
const EVENT_WORKER_STOP = 'workerStop';
|
||||
|
||||
/**
|
||||
* @var array|string
|
||||
* @since 2.0.2
|
||||
*/
|
||||
public $loopConfig = SignalLoop::class;
|
||||
/**
|
||||
* @var string command class name
|
||||
*/
|
||||
public $commandClass = Command::class;
|
||||
/**
|
||||
* @var array of additional options of command
|
||||
*/
|
||||
public $commandOptions = [];
|
||||
/**
|
||||
* @var callable|null
|
||||
* @internal for worker command only
|
||||
*/
|
||||
public $messageHandler;
|
||||
|
||||
/**
|
||||
* @var int|null current process ID of a worker.
|
||||
* @since 2.0.2
|
||||
*/
|
||||
private $_workerPid;
|
||||
|
||||
|
||||
/**
|
||||
* @return string command id
|
||||
* @throws
|
||||
*/
|
||||
protected function getCommandId()
|
||||
{
|
||||
foreach (Yii::$app->getComponents(false) as $id => $component) {
|
||||
if ($component === $this) {
|
||||
return Inflector::camel2id($id);
|
||||
}
|
||||
}
|
||||
throw new InvalidConfigException('Queue must be an application component.');
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function bootstrap($app)
|
||||
{
|
||||
if ($app instanceof ConsoleApp) {
|
||||
$app->controllerMap[$this->getCommandId()] = [
|
||||
'class' => $this->commandClass,
|
||||
'queue' => $this,
|
||||
] + $this->commandOptions;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs worker.
|
||||
*
|
||||
* @param callable $handler
|
||||
* @return null|int exit code
|
||||
* @since 2.0.2
|
||||
*/
|
||||
protected function runWorker(callable $handler)
|
||||
{
|
||||
$this->_workerPid = getmypid();
|
||||
/** @var LoopInterface $loop */
|
||||
$loop = Yii::createObject($this->loopConfig, [$this]);
|
||||
|
||||
$event = new WorkerEvent(['loop' => $loop]);
|
||||
$this->trigger(self::EVENT_WORKER_START, $event);
|
||||
if ($event->exitCode !== null) {
|
||||
return $event->exitCode;
|
||||
}
|
||||
|
||||
$exitCode = null;
|
||||
try {
|
||||
call_user_func($handler, function () use ($loop, $event) {
|
||||
$this->trigger(self::EVENT_WORKER_LOOP, $event);
|
||||
return $event->exitCode === null && $loop->canContinue();
|
||||
});
|
||||
} finally {
|
||||
$this->trigger(self::EVENT_WORKER_STOP, $event);
|
||||
$this->_workerPid = null;
|
||||
}
|
||||
|
||||
return $event->exitCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets process ID of a worker.
|
||||
*
|
||||
* @inheritdoc
|
||||
* @return int|null
|
||||
* @since 2.0.2
|
||||
*/
|
||||
public function getWorkerPid()
|
||||
{
|
||||
return $this->_workerPid;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
protected function handleMessage($id, $message, $ttr, $attempt)
|
||||
{
|
||||
if ($this->messageHandler) {
|
||||
return call_user_func($this->messageHandler, $id, $message, $ttr, $attempt);
|
||||
}
|
||||
|
||||
return parent::handleMessage($id, $message, $ttr, $attempt);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $id of a message
|
||||
* @param string $message
|
||||
* @param int $ttr time to reserve
|
||||
* @param int $attempt number
|
||||
* @param int|null $workerPid of worker process
|
||||
* @return bool
|
||||
* @internal for worker command only
|
||||
*/
|
||||
public function execute($id, $message, $ttr, $attempt, $workerPid)
|
||||
{
|
||||
$this->_workerPid = $workerPid;
|
||||
return parent::handleMessage($id, $message, $ttr, $attempt);
|
||||
}
|
||||
}
|
||||
60
vendor/yiisoft/yii2-queue/src/cli/Signal.php
vendored
Normal file
60
vendor/yiisoft/yii2-queue/src/cli/Signal.php
vendored
Normal file
@ -0,0 +1,60 @@
|
||||
<?php
|
||||
/**
|
||||
* @link https://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license https://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\queue\cli;
|
||||
|
||||
/**
|
||||
* Process Signal Helper.
|
||||
*
|
||||
* @deprecated since 2.0.2 and will be removed in 3.0. Use SignalLoop instead.
|
||||
*
|
||||
* @author Roman Zhuravlev <zhuravljov@gmail.com>
|
||||
*/
|
||||
class Signal
|
||||
{
|
||||
private static $exit = false;
|
||||
|
||||
|
||||
/**
|
||||
* Checks exit signals
|
||||
* Used mainly by [[yii\queue\Queue]] to check, whether job execution
|
||||
* loop can be continued.
|
||||
* @return bool
|
||||
*/
|
||||
public static function isExit()
|
||||
{
|
||||
if (function_exists('pcntl_signal')) {
|
||||
// Installs a signal handler
|
||||
static $handled = false;
|
||||
if (!$handled) {
|
||||
foreach ([SIGTERM, SIGINT, SIGHUP] as $signal) {
|
||||
pcntl_signal($signal, function () {
|
||||
static::setExitFlag();
|
||||
});
|
||||
}
|
||||
$handled = true;
|
||||
}
|
||||
|
||||
// Checks signal
|
||||
if (!static::$exit) {
|
||||
pcntl_signal_dispatch();
|
||||
}
|
||||
}
|
||||
|
||||
return static::$exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets exit flag to `true`
|
||||
* Method can be used to simulate exit signal for methods that use
|
||||
* [[isExit()]] to check whether execution loop can be continued.
|
||||
*/
|
||||
public static function setExitFlag()
|
||||
{
|
||||
static::$exit = true;
|
||||
}
|
||||
}
|
||||
110
vendor/yiisoft/yii2-queue/src/cli/SignalLoop.php
vendored
Normal file
110
vendor/yiisoft/yii2-queue/src/cli/SignalLoop.php
vendored
Normal file
@ -0,0 +1,110 @@
|
||||
<?php
|
||||
/**
|
||||
* @link https://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license https://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\queue\cli;
|
||||
|
||||
use yii\base\BaseObject;
|
||||
|
||||
/**
|
||||
* Signal Loop.
|
||||
*
|
||||
* @author Roman Zhuravlev <zhuravljov@gmail.com>
|
||||
* @since 2.0.2
|
||||
*/
|
||||
class SignalLoop extends BaseObject implements LoopInterface
|
||||
{
|
||||
/**
|
||||
* @var array of signals to exit from listening of the queue.
|
||||
*/
|
||||
public $exitSignals = [
|
||||
15, // SIGTERM
|
||||
3, // SIGQUIT
|
||||
2, // SIGINT
|
||||
1, // SIGHUP
|
||||
];
|
||||
/**
|
||||
* @var array of signals to suspend listening of the queue.
|
||||
* For example: SIGTSTP
|
||||
*/
|
||||
public $suspendSignals = [];
|
||||
/**
|
||||
* @var array of signals to resume listening of the queue.
|
||||
* For example: SIGCONT
|
||||
*/
|
||||
public $resumeSignals = [];
|
||||
|
||||
/**
|
||||
* @var Queue
|
||||
*/
|
||||
protected $queue;
|
||||
|
||||
/**
|
||||
* @var bool status when exit signal was got.
|
||||
*/
|
||||
private static $exit = false;
|
||||
/**
|
||||
* @var bool status when suspend or resume signal was got.
|
||||
*/
|
||||
private static $pause = false;
|
||||
|
||||
|
||||
/**
|
||||
* @param Queue $queue
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function __construct($queue, array $config = [])
|
||||
{
|
||||
$this->queue = $queue;
|
||||
parent::__construct($config);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets signal handlers.
|
||||
*
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function init()
|
||||
{
|
||||
parent::init();
|
||||
if (extension_loaded('pcntl') && function_exists('pcntl_signal')) {
|
||||
foreach ($this->exitSignals as $signal) {
|
||||
pcntl_signal($signal, function () {
|
||||
self::$exit = true;
|
||||
});
|
||||
}
|
||||
foreach ($this->suspendSignals as $signal) {
|
||||
pcntl_signal($signal, function () {
|
||||
self::$pause = true;
|
||||
});
|
||||
}
|
||||
foreach ($this->resumeSignals as $signal) {
|
||||
pcntl_signal($signal, function () {
|
||||
self::$pause = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks signals state.
|
||||
*
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function canContinue()
|
||||
{
|
||||
if (extension_loaded('pcntl') && function_exists('pcntl_signal_dispatch')) {
|
||||
pcntl_signal_dispatch();
|
||||
// Wait for resume signal until loop is suspended
|
||||
while (self::$pause && !self::$exit) {
|
||||
usleep(10000);
|
||||
pcntl_signal_dispatch();
|
||||
}
|
||||
}
|
||||
|
||||
return !self::$exit;
|
||||
}
|
||||
}
|
||||
19
vendor/yiisoft/yii2-queue/src/cli/Verbose.php
vendored
Normal file
19
vendor/yiisoft/yii2-queue/src/cli/Verbose.php
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
<?php
|
||||
/**
|
||||
* @link https://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license https://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\queue\cli;
|
||||
|
||||
/**
|
||||
* Verbose Behavior.
|
||||
*
|
||||
* @deprecated Will be removed in 3.0. Use VerboseBehavior instead of Verbose.
|
||||
*
|
||||
* @author Roman Zhuravlev <zhuravljov@gmail.com>
|
||||
*/
|
||||
class Verbose extends VerboseBehavior
|
||||
{
|
||||
}
|
||||
170
vendor/yiisoft/yii2-queue/src/cli/VerboseBehavior.php
vendored
Normal file
170
vendor/yiisoft/yii2-queue/src/cli/VerboseBehavior.php
vendored
Normal file
@ -0,0 +1,170 @@
|
||||
<?php
|
||||
/**
|
||||
* @link https://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license https://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\queue\cli;
|
||||
|
||||
use yii\base\Behavior;
|
||||
use yii\console\Controller;
|
||||
use yii\helpers\Console;
|
||||
use yii\queue\ExecEvent;
|
||||
use yii\queue\JobInterface;
|
||||
|
||||
/**
|
||||
* Verbose Behavior.
|
||||
*
|
||||
* @author Roman Zhuravlev <zhuravljov@gmail.com>
|
||||
*/
|
||||
class VerboseBehavior extends Behavior
|
||||
{
|
||||
/**
|
||||
* @var Queue
|
||||
*/
|
||||
public $owner;
|
||||
/**
|
||||
* @var Controller
|
||||
*/
|
||||
public $command;
|
||||
|
||||
/**
|
||||
* @var float timestamp
|
||||
*/
|
||||
private $jobStartedAt;
|
||||
/**
|
||||
* @var int timestamp
|
||||
*/
|
||||
private $workerStartedAt;
|
||||
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function events()
|
||||
{
|
||||
return [
|
||||
Queue::EVENT_BEFORE_EXEC => 'beforeExec',
|
||||
Queue::EVENT_AFTER_EXEC => 'afterExec',
|
||||
Queue::EVENT_AFTER_ERROR => 'afterError',
|
||||
Queue::EVENT_WORKER_START => 'workerStart',
|
||||
Queue::EVENT_WORKER_STOP => 'workerStop',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ExecEvent $event
|
||||
*/
|
||||
public function beforeExec(ExecEvent $event)
|
||||
{
|
||||
$this->jobStartedAt = microtime(true);
|
||||
$this->command->stdout(date('Y-m-d H:i:s'), Console::FG_YELLOW);
|
||||
$this->command->stdout($this->jobTitle($event), Console::FG_GREY);
|
||||
$this->command->stdout(' - ', Console::FG_YELLOW);
|
||||
$this->command->stdout('Started', Console::FG_GREEN);
|
||||
$this->command->stdout(PHP_EOL);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ExecEvent $event
|
||||
*/
|
||||
public function afterExec(ExecEvent $event)
|
||||
{
|
||||
$this->command->stdout(date('Y-m-d H:i:s'), Console::FG_YELLOW);
|
||||
$this->command->stdout($this->jobTitle($event), Console::FG_GREY);
|
||||
$this->command->stdout(' - ', Console::FG_YELLOW);
|
||||
$this->command->stdout('Done', Console::FG_GREEN);
|
||||
$duration = number_format(round(microtime(true) - $this->jobStartedAt, 3), 3);
|
||||
$memory = round(memory_get_peak_usage(false)/1024/1024, 2);
|
||||
$this->command->stdout(" ($duration s, $memory MiB)", Console::FG_YELLOW);
|
||||
$this->command->stdout(PHP_EOL);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ExecEvent $event
|
||||
*/
|
||||
public function afterError(ExecEvent $event)
|
||||
{
|
||||
$this->command->stdout(date('Y-m-d H:i:s'), Console::FG_YELLOW);
|
||||
$this->command->stdout($this->jobTitle($event), Console::FG_GREY);
|
||||
$this->command->stdout(' - ', Console::FG_YELLOW);
|
||||
$this->command->stdout('Error', Console::BG_RED);
|
||||
if ($this->jobStartedAt) {
|
||||
$duration = number_format(round(microtime(true) - $this->jobStartedAt, 3), 3);
|
||||
$this->command->stdout(" ($duration s)", Console::FG_YELLOW);
|
||||
}
|
||||
$this->command->stdout(PHP_EOL);
|
||||
$this->command->stdout('> ' . get_class($event->error) . ': ', Console::FG_RED);
|
||||
$message = explode("\n", ltrim($event->error->getMessage()), 2)[0]; // First line
|
||||
$this->command->stdout($message, Console::FG_GREY);
|
||||
$this->command->stdout(PHP_EOL);
|
||||
$this->command->stdout('Stack trace:', Console::FG_GREY);
|
||||
$this->command->stdout(PHP_EOL);
|
||||
$this->command->stdout($event->error->getTraceAsString(), Console::FG_GREY);
|
||||
$this->command->stdout(PHP_EOL);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ExecEvent $event
|
||||
* @return string
|
||||
* @since 2.0.2
|
||||
*/
|
||||
protected function jobTitle(ExecEvent $event)
|
||||
{
|
||||
$name = $event->job instanceof JobInterface ? get_class($event->job) : 'unknown job';
|
||||
$extra = "attempt: $event->attempt";
|
||||
if ($pid = $event->sender->getWorkerPid()) {
|
||||
$extra .= ", pid: $pid";
|
||||
}
|
||||
return " [$event->id] $name ($extra)";
|
||||
}
|
||||
|
||||
/**
|
||||
* @param WorkerEvent $event
|
||||
* @since 2.0.2
|
||||
*/
|
||||
public function workerStart(WorkerEvent $event)
|
||||
{
|
||||
$this->workerStartedAt = time();
|
||||
$this->command->stdout(date('Y-m-d H:i:s'), Console::FG_YELLOW);
|
||||
$pid = $event->sender->getWorkerPid();
|
||||
$this->command->stdout(" [pid: $pid]", Console::FG_GREY);
|
||||
$this->command->stdout(" - Worker is started\n", Console::FG_GREEN);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param WorkerEvent $event
|
||||
* @since 2.0.2
|
||||
*/
|
||||
public function workerStop(WorkerEvent $event)
|
||||
{
|
||||
$this->command->stdout(date('Y-m-d H:i:s'), Console::FG_YELLOW);
|
||||
$pid = $event->sender->getWorkerPid();
|
||||
$this->command->stdout(" [pid: $pid]", Console::FG_GREY);
|
||||
$this->command->stdout(' - Worker is stopped ', Console::FG_GREEN);
|
||||
$duration = $this->formatDuration(time() - $this->workerStartedAt);
|
||||
$this->command->stdout("($duration)\n", Console::FG_YELLOW);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $value
|
||||
* @return string
|
||||
* @since 2.0.2
|
||||
*/
|
||||
protected function formatDuration($value)
|
||||
{
|
||||
$seconds = $value % 60;
|
||||
$value = ($value - $seconds) / 60;
|
||||
$minutes = $value % 60;
|
||||
$value = ($value - $minutes) / 60;
|
||||
$hours = $value % 24;
|
||||
$days = ($value - $hours) / 24;
|
||||
|
||||
if ($days > 0) {
|
||||
return sprintf('%d:%02d:%02d:%02d', $days, $hours, $minutes, $seconds);
|
||||
}
|
||||
|
||||
return sprintf('%d:%02d:%02d', $hours, $minutes, $seconds);
|
||||
}
|
||||
}
|
||||
33
vendor/yiisoft/yii2-queue/src/cli/WorkerEvent.php
vendored
Normal file
33
vendor/yiisoft/yii2-queue/src/cli/WorkerEvent.php
vendored
Normal file
@ -0,0 +1,33 @@
|
||||
<?php
|
||||
/**
|
||||
* @link https://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license https://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\queue\cli;
|
||||
|
||||
use yii\base\Event;
|
||||
|
||||
/**
|
||||
* Worker Event.
|
||||
*
|
||||
* @author Roman Zhuravlev <zhuravljov@gmail.com>
|
||||
* @since 2.0.2
|
||||
*/
|
||||
class WorkerEvent extends Event
|
||||
{
|
||||
/**
|
||||
* @var Queue
|
||||
* @inheritdoc
|
||||
*/
|
||||
public $sender;
|
||||
/**
|
||||
* @var LoopInterface
|
||||
*/
|
||||
public $loop;
|
||||
/**
|
||||
* @var null|int exit code
|
||||
*/
|
||||
public $exitCode;
|
||||
}
|
||||
57
vendor/yiisoft/yii2-queue/src/closure/Behavior.php
vendored
Normal file
57
vendor/yiisoft/yii2-queue/src/closure/Behavior.php
vendored
Normal file
@ -0,0 +1,57 @@
|
||||
<?php
|
||||
/**
|
||||
* @link https://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license https://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\queue\closure;
|
||||
|
||||
use function Opis\Closure\serialize as opis_serialize;
|
||||
use yii\queue\PushEvent;
|
||||
use yii\queue\Queue;
|
||||
|
||||
/**
|
||||
* Closure Behavior.
|
||||
*
|
||||
* If you use the behavior, you can push closures into queue. For example:
|
||||
*
|
||||
* ```php
|
||||
* $url = 'http://example.com/name.jpg';
|
||||
* $file = '/tmp/name.jpg';
|
||||
* Yii::$app->push(function () use ($url, $file) {
|
||||
* file_put_contents($file, file_get_contents($url));
|
||||
* });
|
||||
* ```
|
||||
*
|
||||
* @author Roman Zhuravlev <zhuravljov@gmail.com>
|
||||
*/
|
||||
class Behavior extends \yii\base\Behavior
|
||||
{
|
||||
/**
|
||||
* @var Queue
|
||||
*/
|
||||
public $owner;
|
||||
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function events()
|
||||
{
|
||||
return [
|
||||
Queue::EVENT_BEFORE_PUSH => 'beforePush',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the closure to a job object.
|
||||
* @param PushEvent $event
|
||||
*/
|
||||
public function beforePush(PushEvent $event)
|
||||
{
|
||||
$serialized = opis_serialize($event->job);
|
||||
$event->job = new Job();
|
||||
$event->job->serialized = $serialized;
|
||||
}
|
||||
}
|
||||
38
vendor/yiisoft/yii2-queue/src/closure/Job.php
vendored
Normal file
38
vendor/yiisoft/yii2-queue/src/closure/Job.php
vendored
Normal file
@ -0,0 +1,38 @@
|
||||
<?php
|
||||
/**
|
||||
* @link https://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license https://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\queue\closure;
|
||||
|
||||
use function Opis\Closure\unserialize as opis_unserialize;
|
||||
use yii\queue\JobInterface;
|
||||
|
||||
/**
|
||||
* Closure Job.
|
||||
*
|
||||
* @author Roman Zhuravlev <zhuravljov@gmail.com>
|
||||
*/
|
||||
class Job implements JobInterface
|
||||
{
|
||||
/**
|
||||
* @var string serialized closure
|
||||
*/
|
||||
public $serialized;
|
||||
|
||||
|
||||
/**
|
||||
* Unserializes and executes a closure.
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function execute($queue)
|
||||
{
|
||||
$unserialized = opis_unserialize($this->serialized);
|
||||
if ($unserialized instanceof \Closure) {
|
||||
return $unserialized();
|
||||
}
|
||||
return $unserialized->execute($queue);
|
||||
}
|
||||
}
|
||||
132
vendor/yiisoft/yii2-queue/src/debug/Panel.php
vendored
Normal file
132
vendor/yiisoft/yii2-queue/src/debug/Panel.php
vendored
Normal file
@ -0,0 +1,132 @@
|
||||
<?php
|
||||
/**
|
||||
* @link https://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license https://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\queue\debug;
|
||||
|
||||
use Yii;
|
||||
use yii\base\NotSupportedException;
|
||||
use yii\base\ViewContextInterface;
|
||||
use yii\helpers\VarDumper;
|
||||
use yii\queue\JobInterface;
|
||||
use yii\queue\PushEvent;
|
||||
use yii\queue\Queue;
|
||||
|
||||
/**
|
||||
* Debug Panel.
|
||||
*
|
||||
* @author Roman Zhuravlev <zhuravljov@gmail.com>
|
||||
*/
|
||||
class Panel extends \yii\debug\Panel implements ViewContextInterface
|
||||
{
|
||||
private $_jobs = [];
|
||||
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
return 'Queue';
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function init()
|
||||
{
|
||||
parent::init();
|
||||
PushEvent::on(Queue::class, Queue::EVENT_AFTER_PUSH, function (PushEvent $event) {
|
||||
$this->_jobs[] = $this->getPushData($event);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @param PushEvent $event
|
||||
* @return array
|
||||
*/
|
||||
protected function getPushData(PushEvent $event)
|
||||
{
|
||||
$data = [];
|
||||
foreach (Yii::$app->getComponents(false) as $id => $component) {
|
||||
if ($component === $event->sender) {
|
||||
$data['sender'] = $id;
|
||||
break;
|
||||
}
|
||||
}
|
||||
$data['id'] = $event->id;
|
||||
$data['ttr'] = $event->ttr;
|
||||
$data['delay'] = $event->delay;
|
||||
$data['priority'] = $event->priority;
|
||||
if ($event->job instanceof JobInterface) {
|
||||
$data['class'] = get_class($event->job);
|
||||
$data['properties'] = [];
|
||||
foreach (get_object_vars($event->job) as $property => $value) {
|
||||
$data['properties'][$property] = VarDumper::dumpAsString($value);
|
||||
}
|
||||
} else {
|
||||
$data['data'] = VarDumper::dumpAsString($event->job);
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function save()
|
||||
{
|
||||
return ['jobs' => $this->_jobs];
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function getViewPath()
|
||||
{
|
||||
return __DIR__ . '/views';
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function getSummary()
|
||||
{
|
||||
return Yii::$app->view->render('summary', [
|
||||
'url' => $this->getUrl(),
|
||||
'count' => isset($this->data['jobs']) ? count($this->data['jobs']) : 0,
|
||||
], $this);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function getDetail()
|
||||
{
|
||||
$jobs = isset($this->data['jobs']) ? $this->data['jobs'] : [];
|
||||
foreach ($jobs as &$job) {
|
||||
$job['status'] = 'unknown';
|
||||
/** @var Queue $queue */
|
||||
if ($queue = Yii::$app->get($job['sender'], false)) {
|
||||
try {
|
||||
if ($queue->isWaiting($job['id'])) {
|
||||
$job['status'] = 'waiting';
|
||||
} elseif ($queue->isReserved($job['id'])) {
|
||||
$job['status'] = 'reserved';
|
||||
} elseif ($queue->isDone($job['id'])) {
|
||||
$job['status'] = 'done';
|
||||
}
|
||||
} catch (NotSupportedException $e) {
|
||||
} catch (\Exception $e) {
|
||||
$job['status'] = $e->getMessage();
|
||||
}
|
||||
}
|
||||
}
|
||||
unset($job);
|
||||
|
||||
return Yii::$app->view->render('detail', compact('jobs'), $this);
|
||||
}
|
||||
}
|
||||
87
vendor/yiisoft/yii2-queue/src/debug/views/detail.php
vendored
Normal file
87
vendor/yiisoft/yii2-queue/src/debug/views/detail.php
vendored
Normal file
@ -0,0 +1,87 @@
|
||||
<?php
|
||||
/**
|
||||
* @var \yii\web\View $this
|
||||
* @var array $jobs
|
||||
*/
|
||||
use yii\helpers\Html;
|
||||
|
||||
$styles = [
|
||||
'unknown' => 'default',
|
||||
'waiting' => 'info',
|
||||
'reserved' => 'warning',
|
||||
'done' => 'success',
|
||||
];
|
||||
?>
|
||||
<h1>Pushed <?= count($jobs) ?> jobs</h1>
|
||||
|
||||
<?php foreach ($jobs as $job): ?>
|
||||
<div class="panel panel-<?= isset($styles[$job['status']]) ? $styles[$job['status']] : 'danger' ?>">
|
||||
<div class="panel-heading">
|
||||
<h3 class="panel-title">
|
||||
<?php if (is_string($job['id'])): ?>
|
||||
<?= Html::encode($job['id']) ?> -
|
||||
<?php endif; ?>
|
||||
<?= isset($job['class']) ? Html::encode($job['class']) : 'Mixed data' ?>
|
||||
</h3>
|
||||
</div>
|
||||
<table class="table">
|
||||
<tr>
|
||||
<th>Sender</th>
|
||||
<td><?= Html::encode($job['sender']) ?></td>
|
||||
</tr>
|
||||
<?php if (isset($job['id'])): ?>
|
||||
<tr>
|
||||
<th>ID</th>
|
||||
<td><?= Html::encode($job['id']) ?></td>
|
||||
</tr>
|
||||
<?php endif; ?>
|
||||
<tr>
|
||||
<th>TTR</th>
|
||||
<td><?= Html::encode($job['ttr']) ?></td>
|
||||
</tr>
|
||||
<?php if ($job['delay']): ?>
|
||||
<tr>
|
||||
<th>Delay</th>
|
||||
<td><?= Html::encode($job['delay']) ?></td>
|
||||
</tr>
|
||||
<?php endif; ?>
|
||||
<?php if (isset($job['priority'])): ?>
|
||||
<tr>
|
||||
<th>Priority</th>
|
||||
<td><?= Html::encode($job['priority']) ?></td>
|
||||
</tr>
|
||||
<?php endif; ?>
|
||||
<tr>
|
||||
<th>Status</th>
|
||||
<td><?= Html::encode($job['status']) ?></td>
|
||||
</tr>
|
||||
<?php if (isset($job['class'])): ?>
|
||||
<tr>
|
||||
<th>Class</th>
|
||||
<td><?= Html::encode($job['class']) ?></td>
|
||||
</tr>
|
||||
<?php foreach ($job['properties'] as $property => $value): ?>
|
||||
<tr>
|
||||
<th><?= Html::encode($property) ?></th>
|
||||
<td><?= Html::encode($value) ?></td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
<?php else: ?>
|
||||
<tr>
|
||||
<th>Data</th>
|
||||
<td><?= Html::encode($job['data']) ?></td>
|
||||
</tr>
|
||||
<?php endif; ?>
|
||||
</table>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
<?php
|
||||
$this->registerCss(
|
||||
<<<'CSS'
|
||||
|
||||
.panel > .table th {
|
||||
width: 25%;
|
||||
}
|
||||
|
||||
CSS
|
||||
);
|
||||
16
vendor/yiisoft/yii2-queue/src/debug/views/summary.php
vendored
Normal file
16
vendor/yiisoft/yii2-queue/src/debug/views/summary.php
vendored
Normal file
@ -0,0 +1,16 @@
|
||||
<?php
|
||||
/**
|
||||
* @var \yii\web\View $this
|
||||
* @var string $url
|
||||
* @var int $count
|
||||
*/
|
||||
?>
|
||||
<div class="yii-debug-toolbar__block">
|
||||
<a href="<?= $url ?>">
|
||||
Queue
|
||||
<span class="yii-debug-toolbar__label yii-debug-toolbar__label_<?= $count ? 'info' : 'default' ?>">
|
||||
<?= $count ?>
|
||||
</span>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
43
vendor/yiisoft/yii2-queue/src/drivers/amqp/Command.php
vendored
Normal file
43
vendor/yiisoft/yii2-queue/src/drivers/amqp/Command.php
vendored
Normal file
@ -0,0 +1,43 @@
|
||||
<?php
|
||||
/**
|
||||
* @link https://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license https://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\queue\amqp;
|
||||
|
||||
use yii\queue\cli\Command as CliCommand;
|
||||
|
||||
/**
|
||||
* Manages application amqp-queue.
|
||||
*
|
||||
* @deprecated since 2.0.2 and will be removed in 3.0. Consider using amqp_interop driver instead
|
||||
*
|
||||
* @author Roman Zhuravlev <zhuravljov@gmail.com>
|
||||
*/
|
||||
class Command extends CliCommand
|
||||
{
|
||||
/**
|
||||
* @var Queue
|
||||
*/
|
||||
public $queue;
|
||||
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
protected function isWorkerAction($actionID)
|
||||
{
|
||||
return $actionID === 'listen';
|
||||
}
|
||||
|
||||
/**
|
||||
* Listens amqp-queue and runs new jobs.
|
||||
* It can be used as daemon process.
|
||||
*/
|
||||
public function actionListen()
|
||||
{
|
||||
$this->queue->listen();
|
||||
}
|
||||
}
|
||||
167
vendor/yiisoft/yii2-queue/src/drivers/amqp/Queue.php
vendored
Normal file
167
vendor/yiisoft/yii2-queue/src/drivers/amqp/Queue.php
vendored
Normal file
@ -0,0 +1,167 @@
|
||||
<?php
|
||||
/**
|
||||
* @link https://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license https://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\queue\amqp;
|
||||
|
||||
use PhpAmqpLib\Channel\AMQPChannel;
|
||||
use PhpAmqpLib\Connection\AMQPStreamConnection;
|
||||
use PhpAmqpLib\Message\AMQPMessage;
|
||||
use yii\base\Application as BaseApp;
|
||||
use yii\base\Event;
|
||||
use yii\base\NotSupportedException;
|
||||
use yii\queue\cli\Queue as CliQueue;
|
||||
|
||||
/**
|
||||
* Amqp Queue.
|
||||
*
|
||||
* @deprecated since 2.0.2 and will be removed in 3.0. Consider using amqp_interop driver instead.
|
||||
*
|
||||
* @author Roman Zhuravlev <zhuravljov@gmail.com>
|
||||
*/
|
||||
class Queue extends CliQueue
|
||||
{
|
||||
public $host = 'localhost';
|
||||
public $port = 5672;
|
||||
public $user = 'guest';
|
||||
public $password = 'guest';
|
||||
public $queueName = 'queue';
|
||||
public $exchangeName = 'exchange';
|
||||
public $vhost = '/';
|
||||
/**
|
||||
* @var int The periods of time PHP pings the broker in order to prolong the connection timeout. In seconds.
|
||||
* @since 2.3.1
|
||||
*/
|
||||
public $heartbeat = 0;
|
||||
/**
|
||||
* Send keep-alive packets for a socket connection
|
||||
* @var bool
|
||||
* @since 2.3.6
|
||||
*/
|
||||
public $keepalive = false;
|
||||
/**
|
||||
* @var string command class name
|
||||
*/
|
||||
public $commandClass = Command::class;
|
||||
|
||||
/**
|
||||
* @var AMQPStreamConnection
|
||||
*/
|
||||
protected $connection;
|
||||
/**
|
||||
* @var AMQPChannel
|
||||
*/
|
||||
protected $channel;
|
||||
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function init()
|
||||
{
|
||||
parent::init();
|
||||
Event::on(BaseApp::class, BaseApp::EVENT_AFTER_REQUEST, function () {
|
||||
$this->close();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Listens amqp-queue and runs new jobs.
|
||||
*/
|
||||
public function listen()
|
||||
{
|
||||
$this->open();
|
||||
$callback = function (AMQPMessage $payload) {
|
||||
$id = $payload->get('message_id');
|
||||
list($ttr, $message) = explode(';', $payload->body, 2);
|
||||
if ($this->handleMessage($id, $message, $ttr, 1)) {
|
||||
$payload->delivery_info['channel']->basic_ack($payload->delivery_info['delivery_tag']);
|
||||
}
|
||||
};
|
||||
$this->channel->basic_qos(null, 1, null);
|
||||
$this->channel->basic_consume($this->queueName, '', false, false, false, false, $callback);
|
||||
while (count($this->channel->callbacks)) {
|
||||
$this->channel->wait();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
protected function pushMessage($message, $ttr, $delay, $priority)
|
||||
{
|
||||
if ($delay) {
|
||||
throw new NotSupportedException('Delayed work is not supported in the driver.');
|
||||
}
|
||||
if ($priority !== null) {
|
||||
throw new NotSupportedException('Job priority is not supported in the driver.');
|
||||
}
|
||||
|
||||
$this->open();
|
||||
$id = uniqid('', true);
|
||||
$this->channel->basic_publish(
|
||||
new AMQPMessage("$ttr;$message", [
|
||||
'delivery_mode' => AMQPMessage::DELIVERY_MODE_PERSISTENT,
|
||||
'message_id' => $id,
|
||||
]),
|
||||
$this->exchangeName
|
||||
);
|
||||
|
||||
return $id;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function status($id)
|
||||
{
|
||||
throw new NotSupportedException('Status is not supported in the driver.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens connection and channel.
|
||||
*/
|
||||
protected function open()
|
||||
{
|
||||
if ($this->channel) {
|
||||
return;
|
||||
}
|
||||
$this->connection = new AMQPStreamConnection(
|
||||
$this->host,
|
||||
$this->port,
|
||||
$this->user,
|
||||
$this->password,
|
||||
$this->vhost,
|
||||
false,
|
||||
'AMQPLAIN',
|
||||
null,
|
||||
'en_US',
|
||||
3.0,
|
||||
3.0,
|
||||
null,
|
||||
$this->keepalive,
|
||||
$this->heartbeat,
|
||||
0.0,
|
||||
null
|
||||
);
|
||||
$this->channel = $this->connection->channel();
|
||||
$this->channel->queue_declare($this->queueName, false, true, false, false);
|
||||
$this->channel->exchange_declare($this->exchangeName, 'direct', false, true, false);
|
||||
$this->channel->queue_bind($this->queueName, $this->exchangeName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes connection and channel.
|
||||
*/
|
||||
protected function close()
|
||||
{
|
||||
if (!$this->channel) {
|
||||
return;
|
||||
}
|
||||
$this->channel->close();
|
||||
$this->connection->close();
|
||||
}
|
||||
}
|
||||
42
vendor/yiisoft/yii2-queue/src/drivers/amqp_interop/Command.php
vendored
Normal file
42
vendor/yiisoft/yii2-queue/src/drivers/amqp_interop/Command.php
vendored
Normal file
@ -0,0 +1,42 @@
|
||||
<?php
|
||||
/**
|
||||
* @link https://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license https://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\queue\amqp_interop;
|
||||
|
||||
use yii\queue\cli\Command as CliCommand;
|
||||
|
||||
/**
|
||||
* Manages application amqp-queue.
|
||||
*
|
||||
* @author Maksym Kotliar <kotlyar.maksim@gmail.com>
|
||||
* @since 2.0.2
|
||||
*/
|
||||
class Command extends CliCommand
|
||||
{
|
||||
/**
|
||||
* @var Queue
|
||||
*/
|
||||
public $queue;
|
||||
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
protected function isWorkerAction($actionID)
|
||||
{
|
||||
return $actionID === 'listen';
|
||||
}
|
||||
|
||||
/**
|
||||
* Listens amqp-queue and runs new jobs.
|
||||
* It can be used as daemon process.
|
||||
*/
|
||||
public function actionListen()
|
||||
{
|
||||
$this->queue->listen();
|
||||
}
|
||||
}
|
||||
518
vendor/yiisoft/yii2-queue/src/drivers/amqp_interop/Queue.php
vendored
Normal file
518
vendor/yiisoft/yii2-queue/src/drivers/amqp_interop/Queue.php
vendored
Normal file
@ -0,0 +1,518 @@
|
||||
<?php
|
||||
/**
|
||||
* @link https://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license https://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\queue\amqp_interop;
|
||||
|
||||
use Enqueue\AmqpBunny\AmqpConnectionFactory as AmqpBunnyConnectionFactory;
|
||||
use Enqueue\AmqpExt\AmqpConnectionFactory as AmqpExtConnectionFactory;
|
||||
use Enqueue\AmqpLib\AmqpConnectionFactory as AmqpLibConnectionFactory;
|
||||
use Enqueue\AmqpTools\DelayStrategyAware;
|
||||
use Enqueue\AmqpTools\RabbitMqDlxDelayStrategy;
|
||||
use Interop\Amqp\AmqpConnectionFactory;
|
||||
use Interop\Amqp\AmqpConsumer;
|
||||
use Interop\Amqp\AmqpContext;
|
||||
use Interop\Amqp\AmqpDestination;
|
||||
use Interop\Amqp\AmqpMessage;
|
||||
use Interop\Amqp\AmqpQueue;
|
||||
use Interop\Amqp\AmqpTopic;
|
||||
use Interop\Amqp\Impl\AmqpBind;
|
||||
use yii\base\Application as BaseApp;
|
||||
use yii\base\Event;
|
||||
use yii\base\NotSupportedException;
|
||||
use yii\queue\cli\Queue as CliQueue;
|
||||
|
||||
/**
|
||||
* Amqp Queue.
|
||||
*
|
||||
* @property-read AmqpContext $context
|
||||
*
|
||||
* @author Maksym Kotliar <kotlyar.maksim@gmail.com>
|
||||
* @since 2.0.2
|
||||
*/
|
||||
class Queue extends CliQueue
|
||||
{
|
||||
const ATTEMPT = 'yii-attempt';
|
||||
const TTR = 'yii-ttr';
|
||||
const DELAY = 'yii-delay';
|
||||
const PRIORITY = 'yii-priority';
|
||||
const ENQUEUE_AMQP_LIB = 'enqueue/amqp-lib';
|
||||
const ENQUEUE_AMQP_EXT = 'enqueue/amqp-ext';
|
||||
const ENQUEUE_AMQP_BUNNY = 'enqueue/amqp-bunny';
|
||||
|
||||
/**
|
||||
* The connection to the broker could be configured as an array of options
|
||||
* or as a DSN string like amqp:, amqps:, amqps://user:pass@localhost:1000/vhost.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $dsn;
|
||||
/**
|
||||
* The message queue broker's host.
|
||||
*
|
||||
* @var string|null
|
||||
*/
|
||||
public $host;
|
||||
/**
|
||||
* The message queue broker's port.
|
||||
*
|
||||
* @var string|null
|
||||
*/
|
||||
public $port;
|
||||
/**
|
||||
* This is RabbitMQ user which is used to login on the broker.
|
||||
*
|
||||
* @var string|null
|
||||
*/
|
||||
public $user;
|
||||
/**
|
||||
* This is RabbitMQ password which is used to login on the broker.
|
||||
*
|
||||
* @var string|null
|
||||
*/
|
||||
public $password;
|
||||
/**
|
||||
* Virtual hosts provide logical grouping and separation of resources.
|
||||
*
|
||||
* @var string|null
|
||||
*/
|
||||
public $vhost;
|
||||
/**
|
||||
* The time PHP socket waits for an information while reading. In seconds.
|
||||
*
|
||||
* @var float|null
|
||||
*/
|
||||
public $readTimeout;
|
||||
/**
|
||||
* The time PHP socket waits for an information while witting. In seconds.
|
||||
*
|
||||
* @var float|null
|
||||
*/
|
||||
public $writeTimeout;
|
||||
/**
|
||||
* The time RabbitMQ keeps the connection on idle. In seconds.
|
||||
*
|
||||
* @var float|null
|
||||
*/
|
||||
public $connectionTimeout;
|
||||
/**
|
||||
* The periods of time PHP pings the broker in order to prolong the connection timeout. In seconds.
|
||||
*
|
||||
* @var float|null
|
||||
*/
|
||||
public $heartbeat;
|
||||
/**
|
||||
* PHP uses one shared connection if set true.
|
||||
*
|
||||
* @var bool|null
|
||||
*/
|
||||
public $persisted;
|
||||
/**
|
||||
* Send keep-alive packets for a socket connection
|
||||
* @var bool
|
||||
* @since 2.3.6
|
||||
*/
|
||||
public $keepalive;
|
||||
/**
|
||||
* The connection will be established as later as possible if set true.
|
||||
*
|
||||
* @var bool|null
|
||||
*/
|
||||
public $lazy;
|
||||
/**
|
||||
* If false prefetch_count option applied separately to each new consumer on the channel
|
||||
* If true prefetch_count option shared across all consumers on the channel.
|
||||
*
|
||||
* @var bool|null
|
||||
*/
|
||||
public $qosGlobal;
|
||||
/**
|
||||
* Defines number of message pre-fetched in advance on a channel basis.
|
||||
*
|
||||
* @var int|null
|
||||
*/
|
||||
public $qosPrefetchSize;
|
||||
/**
|
||||
* Defines number of message pre-fetched in advance per consumer.
|
||||
*
|
||||
* @var int|null
|
||||
*/
|
||||
public $qosPrefetchCount;
|
||||
/**
|
||||
* Defines whether secure connection should be used or not.
|
||||
*
|
||||
* @var bool|null
|
||||
*/
|
||||
public $sslOn;
|
||||
/**
|
||||
* Require verification of SSL certificate used.
|
||||
*
|
||||
* @var bool|null
|
||||
*/
|
||||
public $sslVerify;
|
||||
/**
|
||||
* Location of Certificate Authority file on local filesystem which should be used with the verify_peer context option to authenticate the identity of the remote peer.
|
||||
*
|
||||
* @var string|null
|
||||
*/
|
||||
public $sslCacert;
|
||||
/**
|
||||
* Path to local certificate file on filesystem.
|
||||
*
|
||||
* @var string|null
|
||||
*/
|
||||
public $sslCert;
|
||||
/**
|
||||
* Path to local private key file on filesystem in case of separate files for certificate (local_cert) and private key.
|
||||
*
|
||||
* @var string|null
|
||||
*/
|
||||
public $sslKey;
|
||||
/**
|
||||
* The queue used to consume messages from.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $queueName = 'interop_queue';
|
||||
/**
|
||||
* Setting optional arguments for the queue (key-value pairs)
|
||||
* ```php
|
||||
* [
|
||||
* 'x-expires' => 300000,
|
||||
* 'x-max-priority' => 10
|
||||
* ]
|
||||
* ```
|
||||
*
|
||||
* @var array
|
||||
* @since 2.3.3
|
||||
* @see https://www.rabbitmq.com/queues.html#optional-arguments
|
||||
*/
|
||||
public $queueOptionalArguments = [];
|
||||
/**
|
||||
* Set of flags for the queue
|
||||
* @var int
|
||||
* @since 2.3.5
|
||||
* @see AmqpDestination
|
||||
*/
|
||||
public $queueFlags = AmqpQueue::FLAG_DURABLE;
|
||||
/**
|
||||
* The exchange used to publish messages to.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $exchangeName = 'exchange';
|
||||
/**
|
||||
* The exchange type. Can take values: direct, fanout, topic, headers
|
||||
* @var string
|
||||
* @since 2.3.3
|
||||
*/
|
||||
public $exchangeType = AmqpTopic::TYPE_DIRECT;
|
||||
/**
|
||||
* Set of flags for the exchange
|
||||
* @var int
|
||||
* @since 2.3.5
|
||||
* @see AmqpDestination
|
||||
*/
|
||||
public $exchangeFlags = AmqpTopic::FLAG_DURABLE;
|
||||
/**
|
||||
* Routing key for publishing messages. Default is NULL.
|
||||
*
|
||||
* @var string|null
|
||||
*/
|
||||
public $routingKey;
|
||||
/**
|
||||
* Defines the amqp interop transport being internally used. Currently supports lib, ext and bunny values.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $driver = self::ENQUEUE_AMQP_LIB;
|
||||
/**
|
||||
* The property contains a command class which used in cli.
|
||||
*
|
||||
* @var string command class name
|
||||
*/
|
||||
public $commandClass = Command::class;
|
||||
/**
|
||||
* Headers to send along with the message
|
||||
* ```php
|
||||
* [
|
||||
* 'header-1' => 'header-value-1',
|
||||
* 'header-2' => 'header-value-2',
|
||||
* ]
|
||||
* ```
|
||||
*
|
||||
* @var array
|
||||
* @since 3.0.0
|
||||
*/
|
||||
public $setMessageHeaders = [];
|
||||
|
||||
/**
|
||||
* Amqp interop context.
|
||||
*
|
||||
* @var AmqpContext
|
||||
*/
|
||||
protected $context;
|
||||
/**
|
||||
* List of supported amqp interop drivers.
|
||||
*
|
||||
* @var string[]
|
||||
*/
|
||||
protected $supportedDrivers = [self::ENQUEUE_AMQP_LIB, self::ENQUEUE_AMQP_EXT, self::ENQUEUE_AMQP_BUNNY];
|
||||
/**
|
||||
* The property tells whether the setupBroker method was called or not.
|
||||
* Having it we can do broker setup only once per process.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $setupBrokerDone = false;
|
||||
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function init()
|
||||
{
|
||||
parent::init();
|
||||
Event::on(BaseApp::class, BaseApp::EVENT_AFTER_REQUEST, function () {
|
||||
$this->close();
|
||||
});
|
||||
|
||||
if (extension_loaded('pcntl') && function_exists('pcntl_signal') && PHP_MAJOR_VERSION >= 7) {
|
||||
// https://github.com/php-amqplib/php-amqplib#unix-signals
|
||||
$signals = [SIGTERM, SIGQUIT, SIGINT, SIGHUP];
|
||||
|
||||
foreach ($signals as $signal) {
|
||||
$oldHandler = null;
|
||||
// This got added in php 7.1 and might not exist on all supported versions
|
||||
if (function_exists('pcntl_signal_get_handler')) {
|
||||
$oldHandler = pcntl_signal_get_handler($signal);
|
||||
}
|
||||
|
||||
pcntl_signal($signal, static function ($signal) use ($oldHandler) {
|
||||
if ($oldHandler && is_callable($oldHandler)) {
|
||||
$oldHandler($signal);
|
||||
}
|
||||
|
||||
pcntl_signal($signal, SIG_DFL);
|
||||
posix_kill(posix_getpid(), $signal);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Listens amqp-queue and runs new jobs.
|
||||
*/
|
||||
public function listen()
|
||||
{
|
||||
$this->open();
|
||||
$this->setupBroker();
|
||||
|
||||
$queue = $this->context->createQueue($this->queueName);
|
||||
$consumer = $this->context->createConsumer($queue);
|
||||
|
||||
$callback = function (AmqpMessage $message, AmqpConsumer $consumer) {
|
||||
if ($message->isRedelivered()) {
|
||||
$consumer->acknowledge($message);
|
||||
|
||||
$this->redeliver($message);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
$ttr = $message->getProperty(self::TTR);
|
||||
$attempt = $message->getProperty(self::ATTEMPT, 1);
|
||||
|
||||
if ($this->handleMessage($message->getMessageId(), $message->getBody(), $ttr, $attempt)) {
|
||||
$consumer->acknowledge($message);
|
||||
} else {
|
||||
$consumer->acknowledge($message);
|
||||
|
||||
$this->redeliver($message);
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
$subscriptionConsumer = $this->context->createSubscriptionConsumer();
|
||||
$subscriptionConsumer->subscribe($consumer, $callback);
|
||||
$subscriptionConsumer->consume();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return AmqpContext
|
||||
*/
|
||||
public function getContext()
|
||||
{
|
||||
$this->open();
|
||||
|
||||
return $this->context;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
protected function pushMessage($payload, $ttr, $delay, $priority)
|
||||
{
|
||||
$this->open();
|
||||
$this->setupBroker();
|
||||
|
||||
$topic = $this->context->createTopic($this->exchangeName);
|
||||
|
||||
$message = $this->context->createMessage($payload);
|
||||
$message->setDeliveryMode(AmqpMessage::DELIVERY_MODE_PERSISTENT);
|
||||
$message->setMessageId(uniqid('', true));
|
||||
$message->setTimestamp(time());
|
||||
$message->setProperties(array_merge(
|
||||
$this->setMessageHeaders,
|
||||
[
|
||||
self::ATTEMPT => 1,
|
||||
self::TTR => $ttr,
|
||||
]
|
||||
));
|
||||
|
||||
$producer = $this->context->createProducer();
|
||||
|
||||
if ($delay) {
|
||||
$message->setProperty(self::DELAY, $delay);
|
||||
$producer->setDeliveryDelay($delay * 1000);
|
||||
}
|
||||
|
||||
if ($priority) {
|
||||
$message->setProperty(self::PRIORITY, $priority);
|
||||
$producer->setPriority($priority);
|
||||
}
|
||||
|
||||
if (null !== $this->routingKey) {
|
||||
$message->setRoutingKey($this->routingKey);
|
||||
}
|
||||
|
||||
$producer->send($topic, $message);
|
||||
|
||||
return $message->getMessageId();
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function status($id)
|
||||
{
|
||||
throw new NotSupportedException('Status is not supported in the driver.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens connection and channel.
|
||||
*/
|
||||
protected function open()
|
||||
{
|
||||
if ($this->context) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch ($this->driver) {
|
||||
case self::ENQUEUE_AMQP_LIB:
|
||||
$connectionClass = AmqpLibConnectionFactory::class;
|
||||
break;
|
||||
case self::ENQUEUE_AMQP_EXT:
|
||||
$connectionClass = AmqpExtConnectionFactory::class;
|
||||
break;
|
||||
case self::ENQUEUE_AMQP_BUNNY:
|
||||
$connectionClass = AmqpBunnyConnectionFactory::class;
|
||||
break;
|
||||
default:
|
||||
throw new \LogicException(sprintf('The given driver "%s" is not supported. Drivers supported are "%s"', $this->driver, implode('", "', $this->supportedDrivers)));
|
||||
}
|
||||
|
||||
$config = [
|
||||
'dsn' => $this->dsn,
|
||||
'host' => $this->host,
|
||||
'port' => $this->port,
|
||||
'user' => $this->user,
|
||||
'pass' => $this->password,
|
||||
'vhost' => $this->vhost,
|
||||
'read_timeout' => $this->readTimeout,
|
||||
'write_timeout' => $this->writeTimeout,
|
||||
'connection_timeout' => $this->connectionTimeout,
|
||||
'heartbeat' => $this->heartbeat,
|
||||
'persisted' => $this->persisted,
|
||||
'keepalive' => $this->keepalive,
|
||||
'lazy' => $this->lazy,
|
||||
'qos_global' => $this->qosGlobal,
|
||||
'qos_prefetch_size' => $this->qosPrefetchSize,
|
||||
'qos_prefetch_count' => $this->qosPrefetchCount,
|
||||
'ssl_on' => $this->sslOn,
|
||||
'ssl_verify' => $this->sslVerify,
|
||||
'ssl_cacert' => $this->sslCacert,
|
||||
'ssl_cert' => $this->sslCert,
|
||||
'ssl_key' => $this->sslKey,
|
||||
];
|
||||
|
||||
$config = array_filter($config, function ($value) {
|
||||
return null !== $value;
|
||||
});
|
||||
|
||||
/** @var AmqpConnectionFactory $factory */
|
||||
$factory = new $connectionClass($config);
|
||||
|
||||
$this->context = $factory->createContext();
|
||||
|
||||
if ($this->context instanceof DelayStrategyAware) {
|
||||
$this->context->setDelayStrategy(new RabbitMqDlxDelayStrategy());
|
||||
}
|
||||
}
|
||||
|
||||
protected function setupBroker()
|
||||
{
|
||||
if ($this->setupBrokerDone) {
|
||||
return;
|
||||
}
|
||||
|
||||
$queue = $this->context->createQueue($this->queueName);
|
||||
$queue->setFlags($this->queueFlags);
|
||||
$queue->setArguments($this->queueOptionalArguments);
|
||||
$this->context->declareQueue($queue);
|
||||
|
||||
$topic = $this->context->createTopic($this->exchangeName);
|
||||
$topic->setType($this->exchangeType);
|
||||
$topic->setFlags($this->exchangeFlags);
|
||||
$this->context->declareTopic($topic);
|
||||
|
||||
$this->context->bind(new AmqpBind($queue, $topic, $this->routingKey));
|
||||
|
||||
$this->setupBrokerDone = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes connection and channel.
|
||||
*/
|
||||
protected function close()
|
||||
{
|
||||
if (!$this->context) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->context->close();
|
||||
$this->context = null;
|
||||
$this->setupBrokerDone = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function redeliver(AmqpMessage $message)
|
||||
{
|
||||
$attempt = $message->getProperty(self::ATTEMPT, 1);
|
||||
|
||||
$newMessage = $this->context->createMessage($message->getBody(), $message->getProperties(), $message->getHeaders());
|
||||
$newMessage->setDeliveryMode($message->getDeliveryMode());
|
||||
$newMessage->setProperty(self::ATTEMPT, ++$attempt);
|
||||
|
||||
$this->context->createProducer()->send(
|
||||
$this->context->createQueue($this->queueName),
|
||||
$newMessage
|
||||
);
|
||||
}
|
||||
}
|
||||
92
vendor/yiisoft/yii2-queue/src/drivers/beanstalk/Command.php
vendored
Normal file
92
vendor/yiisoft/yii2-queue/src/drivers/beanstalk/Command.php
vendored
Normal file
@ -0,0 +1,92 @@
|
||||
<?php
|
||||
/**
|
||||
* @link https://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license https://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\queue\beanstalk;
|
||||
|
||||
use yii\console\Exception;
|
||||
use yii\queue\cli\Command as CliCommand;
|
||||
|
||||
/**
|
||||
* Manages application beanstalk-queue.
|
||||
*
|
||||
* @author Roman Zhuravlev <zhuravljov@gmail.com>
|
||||
*/
|
||||
class Command extends CliCommand
|
||||
{
|
||||
/**
|
||||
* @var Queue
|
||||
*/
|
||||
public $queue;
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $defaultAction = 'info';
|
||||
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function actions()
|
||||
{
|
||||
return [
|
||||
'info' => InfoAction::class,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
protected function isWorkerAction($actionID)
|
||||
{
|
||||
return in_array($actionID, ['run', 'listen']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs all jobs from beanstalk-queue.
|
||||
* It can be used as cron job.
|
||||
*
|
||||
* @return null|int exit code.
|
||||
*/
|
||||
public function actionRun()
|
||||
{
|
||||
return $this->queue->run(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Listens beanstalk-queue and runs new jobs.
|
||||
* It can be used as daemon process.
|
||||
*
|
||||
* @param int $timeout number of seconds to wait a job.
|
||||
* @throws Exception when params are invalid.
|
||||
* @return null|int exit code.
|
||||
*/
|
||||
public function actionListen($timeout = 3)
|
||||
{
|
||||
if (!is_numeric($timeout)) {
|
||||
throw new Exception('Timeout must be numeric.');
|
||||
}
|
||||
if ($timeout < 1) {
|
||||
throw new Exception('Timeout must be greater than zero.');
|
||||
}
|
||||
|
||||
return $this->queue->run(true, $timeout);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a job by id.
|
||||
*
|
||||
* @param int $id of the job.
|
||||
* @throws Exception when the job is not found.
|
||||
* @since 2.0.1
|
||||
*/
|
||||
public function actionRemove($id)
|
||||
{
|
||||
if (!$this->queue->remove($id)) {
|
||||
throw new Exception('The job is not found.');
|
||||
}
|
||||
}
|
||||
}
|
||||
38
vendor/yiisoft/yii2-queue/src/drivers/beanstalk/InfoAction.php
vendored
Normal file
38
vendor/yiisoft/yii2-queue/src/drivers/beanstalk/InfoAction.php
vendored
Normal file
@ -0,0 +1,38 @@
|
||||
<?php
|
||||
/**
|
||||
* @link https://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license https://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\queue\beanstalk;
|
||||
|
||||
use yii\helpers\Console;
|
||||
use yii\queue\cli\Action;
|
||||
|
||||
/**
|
||||
* Info about queue status.
|
||||
*
|
||||
* @author Roman Zhuravlev <zhuravljov@gmail.com>
|
||||
*/
|
||||
class InfoAction extends Action
|
||||
{
|
||||
/**
|
||||
* @var Queue
|
||||
*/
|
||||
public $queue;
|
||||
|
||||
|
||||
/**
|
||||
* Info about queue status.
|
||||
*/
|
||||
public function run()
|
||||
{
|
||||
Console::output($this->format('Statistical information about the tube:', Console::FG_GREEN));
|
||||
|
||||
foreach ($this->queue->getStatsTube() as $key => $value) {
|
||||
Console::stdout($this->format("- $key: ", Console::FG_YELLOW));
|
||||
Console::output($value);
|
||||
}
|
||||
}
|
||||
}
|
||||
154
vendor/yiisoft/yii2-queue/src/drivers/beanstalk/Queue.php
vendored
Normal file
154
vendor/yiisoft/yii2-queue/src/drivers/beanstalk/Queue.php
vendored
Normal file
@ -0,0 +1,154 @@
|
||||
<?php
|
||||
/**
|
||||
* @link https://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license https://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\queue\beanstalk;
|
||||
|
||||
use Pheanstalk\Exception\ServerException;
|
||||
use Pheanstalk\Job;
|
||||
use Pheanstalk\Pheanstalk;
|
||||
use Pheanstalk\PheanstalkInterface;
|
||||
use yii\base\InvalidArgumentException;
|
||||
use yii\queue\cli\Queue as CliQueue;
|
||||
|
||||
/**
|
||||
* Beanstalk Queue.
|
||||
*
|
||||
* @property-read object $statsTube Tube statistics.
|
||||
*
|
||||
* @author Roman Zhuravlev <zhuravljov@gmail.com>
|
||||
*/
|
||||
class Queue extends CliQueue
|
||||
{
|
||||
/**
|
||||
* @var string connection host
|
||||
*/
|
||||
public $host = 'localhost';
|
||||
/**
|
||||
* @var int connection port
|
||||
*/
|
||||
public $port = PheanstalkInterface::DEFAULT_PORT;
|
||||
/**
|
||||
* @var string beanstalk tube
|
||||
*/
|
||||
public $tube = 'queue';
|
||||
/**
|
||||
* @var string command class name
|
||||
*/
|
||||
public $commandClass = Command::class;
|
||||
|
||||
|
||||
/**
|
||||
* Listens queue and runs each job.
|
||||
*
|
||||
* @param bool $repeat whether to continue listening when queue is empty.
|
||||
* @param int $timeout number of seconds to wait for next message.
|
||||
* @return null|int exit code.
|
||||
* @internal for worker command only.
|
||||
* @since 2.0.2
|
||||
*/
|
||||
public function run($repeat, $timeout = 0)
|
||||
{
|
||||
return $this->runWorker(function (callable $canContinue) use ($repeat, $timeout) {
|
||||
while ($canContinue()) {
|
||||
if ($payload = $this->getPheanstalk()->reserveFromTube($this->tube, $timeout)) {
|
||||
$info = $this->getPheanstalk()->statsJob($payload);
|
||||
if ($this->handleMessage(
|
||||
$payload->getId(),
|
||||
$payload->getData(),
|
||||
$info->ttr,
|
||||
$info->reserves
|
||||
)) {
|
||||
$this->getPheanstalk()->delete($payload);
|
||||
}
|
||||
} elseif (!$repeat) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function status($id)
|
||||
{
|
||||
if (!is_numeric($id) || $id <= 0) {
|
||||
throw new InvalidArgumentException("Unknown message ID: $id.");
|
||||
}
|
||||
|
||||
try {
|
||||
$stats = $this->getPheanstalk()->statsJob($id);
|
||||
if ($stats['state'] === 'reserved') {
|
||||
return self::STATUS_RESERVED;
|
||||
}
|
||||
|
||||
return self::STATUS_WAITING;
|
||||
} catch (ServerException $e) {
|
||||
if ($e->getMessage() === 'Server reported NOT_FOUND') {
|
||||
return self::STATUS_DONE;
|
||||
}
|
||||
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a job by ID.
|
||||
*
|
||||
* @param int $id of a job
|
||||
* @return bool
|
||||
* @since 2.0.1
|
||||
*/
|
||||
public function remove($id)
|
||||
{
|
||||
try {
|
||||
$this->getPheanstalk()->delete(new Job($id, null));
|
||||
return true;
|
||||
} catch (ServerException $e) {
|
||||
if (strpos($e->getMessage(), 'NOT_FOUND') === 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
protected function pushMessage($message, $ttr, $delay, $priority)
|
||||
{
|
||||
return $this->getPheanstalk()->putInTube(
|
||||
$this->tube,
|
||||
$message,
|
||||
$priority ?: PheanstalkInterface::DEFAULT_PRIORITY,
|
||||
$delay,
|
||||
$ttr
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return object tube statistics
|
||||
*/
|
||||
public function getStatsTube()
|
||||
{
|
||||
return $this->getPheanstalk()->statsTube($this->tube);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Pheanstalk
|
||||
*/
|
||||
protected function getPheanstalk()
|
||||
{
|
||||
if (!$this->_pheanstalk) {
|
||||
$this->_pheanstalk = new Pheanstalk($this->host, $this->port);
|
||||
}
|
||||
return $this->_pheanstalk;
|
||||
}
|
||||
|
||||
private $_pheanstalk;
|
||||
}
|
||||
105
vendor/yiisoft/yii2-queue/src/drivers/db/Command.php
vendored
Normal file
105
vendor/yiisoft/yii2-queue/src/drivers/db/Command.php
vendored
Normal file
@ -0,0 +1,105 @@
|
||||
<?php
|
||||
/**
|
||||
* @link https://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license https://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\queue\db;
|
||||
|
||||
use yii\console\Exception;
|
||||
use yii\queue\cli\Command as CliCommand;
|
||||
use yii\queue\cli\InfoAction;
|
||||
|
||||
/**
|
||||
* Manages application db-queue.
|
||||
*
|
||||
* @author Roman Zhuravlev <zhuravljov@gmail.com>
|
||||
*/
|
||||
class Command extends CliCommand
|
||||
{
|
||||
/**
|
||||
* @var Queue
|
||||
*/
|
||||
public $queue;
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $defaultAction = 'info';
|
||||
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function actions()
|
||||
{
|
||||
return [
|
||||
'info' => InfoAction::class,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
protected function isWorkerAction($actionID)
|
||||
{
|
||||
return in_array($actionID, ['run', 'listen'], true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs all jobs from db-queue.
|
||||
* It can be used as cron job.
|
||||
*
|
||||
* @return null|int exit code.
|
||||
*/
|
||||
public function actionRun()
|
||||
{
|
||||
return $this->queue->run(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Listens db-queue and runs new jobs.
|
||||
* It can be used as daemon process.
|
||||
*
|
||||
* @param int $timeout number of seconds to sleep before next reading of the queue.
|
||||
* @throws Exception when params are invalid.
|
||||
* @return null|int exit code.
|
||||
*/
|
||||
public function actionListen($timeout = 3)
|
||||
{
|
||||
if (!is_numeric($timeout)) {
|
||||
throw new Exception('Timeout must be numeric.');
|
||||
}
|
||||
if ($timeout < 1) {
|
||||
throw new Exception('Timeout must be greater than zero.');
|
||||
}
|
||||
|
||||
return $this->queue->run(true, $timeout);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the queue.
|
||||
*
|
||||
* @since 2.0.1
|
||||
*/
|
||||
public function actionClear()
|
||||
{
|
||||
if ($this->confirm('Are you sure?')) {
|
||||
$this->queue->clear();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a job by id.
|
||||
*
|
||||
* @param int $id
|
||||
* @throws Exception when the job is not found.
|
||||
* @since 2.0.1
|
||||
*/
|
||||
public function actionRemove($id)
|
||||
{
|
||||
if (!$this->queue->remove($id)) {
|
||||
throw new Exception('The job is not found.');
|
||||
}
|
||||
}
|
||||
}
|
||||
95
vendor/yiisoft/yii2-queue/src/drivers/db/InfoAction.php
vendored
Normal file
95
vendor/yiisoft/yii2-queue/src/drivers/db/InfoAction.php
vendored
Normal file
@ -0,0 +1,95 @@
|
||||
<?php
|
||||
/**
|
||||
* @link https://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license https://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\queue\db;
|
||||
|
||||
use yii\db\Query;
|
||||
use yii\helpers\Console;
|
||||
use yii\queue\cli\Action;
|
||||
|
||||
/**
|
||||
* Info about queue status.
|
||||
*
|
||||
* @deprecated Will be removed in 3.0. Use yii\queue\cli\InfoAction instead.
|
||||
*
|
||||
* @author Roman Zhuravlev <zhuravljov@gmail.com>
|
||||
*/
|
||||
class InfoAction extends Action
|
||||
{
|
||||
/**
|
||||
* @var Queue
|
||||
*/
|
||||
public $queue;
|
||||
|
||||
|
||||
/**
|
||||
* Info about queue status.
|
||||
*/
|
||||
public function run()
|
||||
{
|
||||
Console::output($this->format('Jobs', Console::FG_GREEN));
|
||||
|
||||
Console::stdout($this->format('- waiting: ', Console::FG_YELLOW));
|
||||
Console::output($this->getWaiting()->count('*', $this->queue->db));
|
||||
|
||||
Console::stdout($this->format('- delayed: ', Console::FG_YELLOW));
|
||||
Console::output($this->getDelayed()->count('*', $this->queue->db));
|
||||
|
||||
Console::stdout($this->format('- reserved: ', Console::FG_YELLOW));
|
||||
Console::output($this->getReserved()->count('*', $this->queue->db));
|
||||
|
||||
Console::stdout($this->format('- done: ', Console::FG_YELLOW));
|
||||
Console::output($this->getDone()->count('*', $this->queue->db));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Query
|
||||
*/
|
||||
protected function getWaiting()
|
||||
{
|
||||
return (new Query())
|
||||
->from($this->queue->tableName)
|
||||
->andWhere(['channel' => $this->queue->channel])
|
||||
->andWhere(['reserved_at' => null])
|
||||
->andWhere(['delay' => 0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Query
|
||||
*/
|
||||
protected function getDelayed()
|
||||
{
|
||||
return (new Query())
|
||||
->from($this->queue->tableName)
|
||||
->andWhere(['channel' => $this->queue->channel])
|
||||
->andWhere(['reserved_at' => null])
|
||||
->andWhere(['>', 'delay', 0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Query
|
||||
*/
|
||||
protected function getReserved()
|
||||
{
|
||||
return (new Query())
|
||||
->from($this->queue->tableName)
|
||||
->andWhere(['channel' => $this->queue->channel])
|
||||
->andWhere('[[reserved_at]] is not null')
|
||||
->andWhere(['done_at' => null]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Query
|
||||
*/
|
||||
protected function getDone()
|
||||
{
|
||||
return (new Query())
|
||||
->from($this->queue->tableName)
|
||||
->andWhere(['channel' => $this->queue->channel])
|
||||
->andWhere('[[done_at]] is not null');
|
||||
}
|
||||
}
|
||||
271
vendor/yiisoft/yii2-queue/src/drivers/db/Queue.php
vendored
Normal file
271
vendor/yiisoft/yii2-queue/src/drivers/db/Queue.php
vendored
Normal file
@ -0,0 +1,271 @@
|
||||
<?php
|
||||
/**
|
||||
* @link https://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license https://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\queue\db;
|
||||
|
||||
use yii\base\Exception;
|
||||
use yii\base\InvalidArgumentException;
|
||||
use yii\db\Connection;
|
||||
use yii\db\Query;
|
||||
use yii\di\Instance;
|
||||
use yii\mutex\Mutex;
|
||||
use yii\queue\cli\Queue as CliQueue;
|
||||
use yii\queue\interfaces\StatisticsProviderInterface;
|
||||
|
||||
/**
|
||||
* Db Queue.
|
||||
*
|
||||
* @property-read StatisticsProvider $statisticsProvider
|
||||
*
|
||||
* @author Roman Zhuravlev <zhuravljov@gmail.com>
|
||||
*/
|
||||
class Queue extends CliQueue implements StatisticsProviderInterface
|
||||
{
|
||||
/**
|
||||
* @var Connection|array|string
|
||||
*/
|
||||
public $db = 'db';
|
||||
/**
|
||||
* @var Mutex|array|string
|
||||
*/
|
||||
public $mutex = 'mutex';
|
||||
/**
|
||||
* @var int timeout
|
||||
*/
|
||||
public $mutexTimeout = 3;
|
||||
/**
|
||||
* @var string table name
|
||||
*/
|
||||
public $tableName = '{{%queue}}';
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $channel = 'queue';
|
||||
/**
|
||||
* @var bool ability to delete released messages from table
|
||||
*/
|
||||
public $deleteReleased = true;
|
||||
/**
|
||||
* @var string command class name
|
||||
*/
|
||||
public $commandClass = Command::class;
|
||||
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function init()
|
||||
{
|
||||
parent::init();
|
||||
$this->db = Instance::ensure($this->db, Connection::class);
|
||||
$this->mutex = Instance::ensure($this->mutex, Mutex::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Listens queue and runs each job.
|
||||
*
|
||||
* @param bool $repeat whether to continue listening when queue is empty.
|
||||
* @param int $timeout number of seconds to sleep before next iteration.
|
||||
* @return null|int exit code.
|
||||
* @internal for worker command only
|
||||
* @since 2.0.2
|
||||
*/
|
||||
public function run($repeat, $timeout = 0)
|
||||
{
|
||||
return $this->runWorker(function (callable $canContinue) use ($repeat, $timeout) {
|
||||
while ($canContinue()) {
|
||||
if ($payload = $this->reserve()) {
|
||||
if ($this->handleMessage(
|
||||
$payload['id'],
|
||||
$payload['job'],
|
||||
$payload['ttr'],
|
||||
$payload['attempt']
|
||||
)) {
|
||||
$this->release($payload);
|
||||
}
|
||||
} elseif (!$repeat) {
|
||||
break;
|
||||
} elseif ($timeout) {
|
||||
sleep($timeout);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function status($id)
|
||||
{
|
||||
$payload = (new Query())
|
||||
->from($this->tableName)
|
||||
->where(['id' => $id])
|
||||
->one($this->db);
|
||||
|
||||
if (!$payload) {
|
||||
if ($this->deleteReleased) {
|
||||
return self::STATUS_DONE;
|
||||
}
|
||||
|
||||
throw new InvalidArgumentException("Unknown message ID: $id.");
|
||||
}
|
||||
|
||||
if (!$payload['reserved_at']) {
|
||||
return self::STATUS_WAITING;
|
||||
}
|
||||
|
||||
if (!$payload['done_at']) {
|
||||
return self::STATUS_RESERVED;
|
||||
}
|
||||
|
||||
return self::STATUS_DONE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the queue.
|
||||
*
|
||||
* @since 2.0.1
|
||||
*/
|
||||
public function clear()
|
||||
{
|
||||
$this->db->createCommand()
|
||||
->delete($this->tableName, ['channel' => $this->channel])
|
||||
->execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a job by ID.
|
||||
*
|
||||
* @param int $id of a job
|
||||
* @return bool
|
||||
* @since 2.0.1
|
||||
*/
|
||||
public function remove($id)
|
||||
{
|
||||
return (bool) $this->db->createCommand()
|
||||
->delete($this->tableName, ['channel' => $this->channel, 'id' => $id])
|
||||
->execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
protected function pushMessage($message, $ttr, $delay, $priority)
|
||||
{
|
||||
$this->db->createCommand()->insert($this->tableName, [
|
||||
'channel' => $this->channel,
|
||||
'job' => $message,
|
||||
'pushed_at' => time(),
|
||||
'ttr' => $ttr,
|
||||
'delay' => $delay,
|
||||
'priority' => $priority ?: 1024,
|
||||
])->execute();
|
||||
$tableSchema = $this->db->getTableSchema($this->tableName);
|
||||
return $this->db->getLastInsertID($tableSchema->sequenceName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes one message from waiting list and reserves it for handling.
|
||||
*
|
||||
* @return array|false payload
|
||||
* @throws Exception in case it hasn't waited the lock
|
||||
*/
|
||||
protected function reserve()
|
||||
{
|
||||
return $this->db->useMaster(function () {
|
||||
if (!$this->mutex->acquire(__CLASS__ . $this->channel, $this->mutexTimeout)) {
|
||||
throw new Exception('Has not waited the lock.');
|
||||
}
|
||||
|
||||
try {
|
||||
$this->moveExpired();
|
||||
|
||||
// Reserve one message
|
||||
$payload = (new Query())
|
||||
->from($this->tableName)
|
||||
->andWhere(['channel' => $this->channel, 'reserved_at' => null])
|
||||
->andWhere('[[pushed_at]] <= :time - [[delay]]', [':time' => time()])
|
||||
->orderBy(['priority' => SORT_ASC, 'id' => SORT_ASC])
|
||||
->limit(1)
|
||||
->one($this->db);
|
||||
if (is_array($payload)) {
|
||||
$payload['reserved_at'] = time();
|
||||
$payload['attempt'] = (int) $payload['attempt'] + 1;
|
||||
$this->db->createCommand()->update($this->tableName, [
|
||||
'reserved_at' => $payload['reserved_at'],
|
||||
'attempt' => $payload['attempt'],
|
||||
], [
|
||||
'id' => $payload['id'],
|
||||
])->execute();
|
||||
|
||||
// pgsql
|
||||
if (is_resource($payload['job'])) {
|
||||
$payload['job'] = stream_get_contents($payload['job']);
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
$this->mutex->release(__CLASS__ . $this->channel);
|
||||
}
|
||||
|
||||
return $payload;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @param array $payload
|
||||
*/
|
||||
protected function release($payload)
|
||||
{
|
||||
if ($this->deleteReleased) {
|
||||
$this->db->createCommand()->delete(
|
||||
$this->tableName,
|
||||
['id' => $payload['id']]
|
||||
)->execute();
|
||||
} else {
|
||||
$this->db->createCommand()->update(
|
||||
$this->tableName,
|
||||
['done_at' => time()],
|
||||
['id' => $payload['id']]
|
||||
)->execute();
|
||||
}
|
||||
}
|
||||
|
||||
protected $reserveTime;
|
||||
|
||||
/**
|
||||
* Moves expired messages into waiting list.
|
||||
*/
|
||||
protected function moveExpired()
|
||||
{
|
||||
if ($this->reserveTime !== time()) {
|
||||
$this->reserveTime = time();
|
||||
$this->db->createCommand()->update(
|
||||
$this->tableName,
|
||||
['reserved_at' => null],
|
||||
// `reserved_at IS NOT NULL` forces db to use index on column,
|
||||
// otherwise a full scan of the table will be performed
|
||||
'[[reserved_at]] is not null and [[reserved_at]] < :time - [[ttr]] and [[done_at]] is null',
|
||||
[':time' => $this->reserveTime]
|
||||
)->execute();
|
||||
}
|
||||
}
|
||||
|
||||
private $_statistcsProvider;
|
||||
|
||||
/**
|
||||
* @return StatisticsProvider
|
||||
*/
|
||||
public function getStatisticsProvider()
|
||||
{
|
||||
if (!$this->_statistcsProvider) {
|
||||
$this->_statistcsProvider = new StatisticsProvider($this);
|
||||
}
|
||||
return $this->_statistcsProvider;
|
||||
}
|
||||
}
|
||||
82
vendor/yiisoft/yii2-queue/src/drivers/db/StatisticsProvider.php
vendored
Normal file
82
vendor/yiisoft/yii2-queue/src/drivers/db/StatisticsProvider.php
vendored
Normal file
@ -0,0 +1,82 @@
|
||||
<?php
|
||||
/**
|
||||
* @link https://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license https://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\queue\db;
|
||||
|
||||
use yii\base\BaseObject;
|
||||
use yii\db\Query;
|
||||
use yii\queue\interfaces\DelayedCountInterface;
|
||||
use yii\queue\interfaces\DoneCountInterface;
|
||||
use yii\queue\interfaces\ReservedCountInterface;
|
||||
use yii\queue\interfaces\WaitingCountInterface;
|
||||
|
||||
/**
|
||||
* Statistics Provider
|
||||
*
|
||||
* @author Kalmer Kaurson <kalmerkaurson@gmail.com>
|
||||
*/
|
||||
class StatisticsProvider extends BaseObject implements DoneCountInterface, WaitingCountInterface, DelayedCountInterface, ReservedCountInterface
|
||||
{
|
||||
/**
|
||||
* @var Queue
|
||||
*/
|
||||
protected $queue;
|
||||
|
||||
|
||||
public function __construct(Queue $queue, $config = [])
|
||||
{
|
||||
$this->queue = $queue;
|
||||
parent::__construct($config);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function getWaitingCount()
|
||||
{
|
||||
return (new Query())
|
||||
->from($this->queue->tableName)
|
||||
->andWhere(['channel' => $this->queue->channel])
|
||||
->andWhere(['reserved_at' => null])
|
||||
->andWhere(['delay' => 0])->count('*', $this->queue->db);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function getDelayedCount()
|
||||
{
|
||||
return (new Query())
|
||||
->from($this->queue->tableName)
|
||||
->andWhere(['channel' => $this->queue->channel])
|
||||
->andWhere(['reserved_at' => null])
|
||||
->andWhere(['>', 'delay', 0])->count('*', $this->queue->db);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function getReservedCount()
|
||||
{
|
||||
return (new Query())
|
||||
->from($this->queue->tableName)
|
||||
->andWhere(['channel' => $this->queue->channel])
|
||||
->andWhere('[[reserved_at]] is not null')
|
||||
->andWhere(['done_at' => null])->count('*', $this->queue->db);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function getDoneCount()
|
||||
{
|
||||
return (new Query())
|
||||
->from($this->queue->tableName)
|
||||
->andWhere(['channel' => $this->queue->channel])
|
||||
->andWhere('[[done_at]] is not null')->count('*', $this->queue->db);
|
||||
}
|
||||
}
|
||||
42
vendor/yiisoft/yii2-queue/src/drivers/db/migrations/M161119140200Queue.php
vendored
Normal file
42
vendor/yiisoft/yii2-queue/src/drivers/db/migrations/M161119140200Queue.php
vendored
Normal file
@ -0,0 +1,42 @@
|
||||
<?php
|
||||
/**
|
||||
* @link https://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license https://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\queue\db\migrations;
|
||||
|
||||
use yii\db\Migration;
|
||||
|
||||
/**
|
||||
* Example of migration for queue message storage.
|
||||
*
|
||||
* @author Roman Zhuravlev <zhuravljov@gmail.com>
|
||||
*/
|
||||
class M161119140200Queue extends Migration
|
||||
{
|
||||
public $tableName = '{{%queue}}';
|
||||
public $tableOptions;
|
||||
|
||||
|
||||
public function up()
|
||||
{
|
||||
$this->createTable($this->tableName, [
|
||||
'id' => $this->primaryKey(),
|
||||
'channel' => $this->string()->notNull(),
|
||||
'job' => $this->binary()->notNull(),
|
||||
'created_at' => $this->integer()->notNull(),
|
||||
'started_at' => $this->integer(),
|
||||
'finished_at' => $this->integer(),
|
||||
], $this->tableOptions);
|
||||
|
||||
$this->createIndex('channel', $this->tableName, 'channel');
|
||||
$this->createIndex('started_at', $this->tableName, 'started_at');
|
||||
}
|
||||
|
||||
public function down()
|
||||
{
|
||||
$this->dropTable($this->tableName);
|
||||
}
|
||||
}
|
||||
31
vendor/yiisoft/yii2-queue/src/drivers/db/migrations/M170307170300Later.php
vendored
Normal file
31
vendor/yiisoft/yii2-queue/src/drivers/db/migrations/M170307170300Later.php
vendored
Normal file
@ -0,0 +1,31 @@
|
||||
<?php
|
||||
/**
|
||||
* @link https://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license https://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\queue\db\migrations;
|
||||
|
||||
use yii\db\Migration;
|
||||
|
||||
/**
|
||||
* Example of migration for queue message storage.
|
||||
*
|
||||
* @author Roman Zhuravlev <zhuravljov@gmail.com>
|
||||
*/
|
||||
class M170307170300Later extends Migration
|
||||
{
|
||||
public $tableName = '{{%queue}}';
|
||||
|
||||
|
||||
public function up()
|
||||
{
|
||||
$this->addColumn($this->tableName, 'timeout', $this->integer()->defaultValue(0)->notNull()->after('created_at'));
|
||||
}
|
||||
|
||||
public function down()
|
||||
{
|
||||
$this->dropColumn($this->tableName, 'timeout');
|
||||
}
|
||||
}
|
||||
77
vendor/yiisoft/yii2-queue/src/drivers/db/migrations/M170509001400Retry.php
vendored
Normal file
77
vendor/yiisoft/yii2-queue/src/drivers/db/migrations/M170509001400Retry.php
vendored
Normal file
@ -0,0 +1,77 @@
|
||||
<?php
|
||||
/**
|
||||
* @link https://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license https://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\queue\db\migrations;
|
||||
|
||||
use yii\db\Migration;
|
||||
|
||||
/**
|
||||
* Example of migration for queue message storage.
|
||||
*
|
||||
* @author Roman Zhuravlev <zhuravljov@gmail.com>
|
||||
*/
|
||||
class M170509001400Retry extends Migration
|
||||
{
|
||||
public $tableName = '{{%queue}}';
|
||||
|
||||
|
||||
public function up()
|
||||
{
|
||||
if ($this->db->driverName !== 'sqlite') {
|
||||
$this->renameColumn($this->tableName, 'created_at', 'pushed_at');
|
||||
$this->addColumn($this->tableName, 'ttr', $this->integer()->notNull()->after('pushed_at'));
|
||||
$this->renameColumn($this->tableName, 'timeout', 'delay');
|
||||
$this->dropIndex('started_at', $this->tableName);
|
||||
$this->renameColumn($this->tableName, 'started_at', 'reserved_at');
|
||||
$this->createIndex('reserved_at', $this->tableName, 'reserved_at');
|
||||
$this->addColumn($this->tableName, 'attempt', $this->integer()->after('reserved_at'));
|
||||
$this->renameColumn($this->tableName, 'finished_at', 'done_at');
|
||||
} else {
|
||||
$this->dropTable($this->tableName);
|
||||
$this->createTable($this->tableName, [
|
||||
'id' => $this->primaryKey(),
|
||||
'channel' => $this->string()->notNull(),
|
||||
'job' => $this->binary()->notNull(),
|
||||
'pushed_at' => $this->integer()->notNull(),
|
||||
'ttr' => $this->integer()->notNull(),
|
||||
'delay' => $this->integer()->notNull(),
|
||||
'reserved_at' => $this->integer(),
|
||||
'attempt' => $this->integer(),
|
||||
'done_at' => $this->integer(),
|
||||
]);
|
||||
$this->createIndex('channel', $this->tableName, 'channel');
|
||||
$this->createIndex('reserved_at', $this->tableName, 'reserved_at');
|
||||
}
|
||||
}
|
||||
|
||||
public function down()
|
||||
{
|
||||
if ($this->db->driverName !== 'sqlite') {
|
||||
$this->renameColumn($this->tableName, 'done_at', 'finished_at');
|
||||
$this->dropColumn($this->tableName, 'attempt');
|
||||
$this->dropIndex('reserved_at', $this->tableName);
|
||||
$this->renameColumn($this->tableName, 'reserved_at', 'started_at');
|
||||
$this->createIndex('started_at', $this->tableName, 'started_at');
|
||||
$this->renameColumn($this->tableName, 'delay', 'timeout');
|
||||
$this->dropColumn($this->tableName, 'ttr');
|
||||
$this->renameColumn($this->tableName, 'pushed_at', 'created_at');
|
||||
} else {
|
||||
$this->dropTable($this->tableName);
|
||||
$this->createTable($this->tableName, [
|
||||
'id' => $this->primaryKey(),
|
||||
'channel' => $this->string()->notNull(),
|
||||
'job' => $this->binary()->notNull(),
|
||||
'created_at' => $this->integer()->notNull(),
|
||||
'timeout' => $this->integer()->notNull(),
|
||||
'started_at' => $this->integer(),
|
||||
'finished_at' => $this->integer(),
|
||||
]);
|
||||
$this->createIndex('channel', $this->tableName, 'channel');
|
||||
$this->createIndex('started_at', $this->tableName, 'started_at');
|
||||
}
|
||||
}
|
||||
}
|
||||
33
vendor/yiisoft/yii2-queue/src/drivers/db/migrations/M170601155600Priority.php
vendored
Normal file
33
vendor/yiisoft/yii2-queue/src/drivers/db/migrations/M170601155600Priority.php
vendored
Normal file
@ -0,0 +1,33 @@
|
||||
<?php
|
||||
/**
|
||||
* @link https://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license https://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\queue\db\migrations;
|
||||
|
||||
use yii\db\Migration;
|
||||
|
||||
/**
|
||||
* Example of migration for queue message storage.
|
||||
*
|
||||
* @author Roman Zhuravlev <zhuravljov@gmail.com>
|
||||
*/
|
||||
class M170601155600Priority extends Migration
|
||||
{
|
||||
public $tableName = '{{%queue}}';
|
||||
|
||||
|
||||
public function up()
|
||||
{
|
||||
$this->addColumn($this->tableName, 'priority', $this->integer()->unsigned()->notNull()->defaultValue(1024)->after('delay'));
|
||||
$this->createIndex('priority', $this->tableName, 'priority');
|
||||
}
|
||||
|
||||
public function down()
|
||||
{
|
||||
$this->dropIndex('priority', $this->tableName);
|
||||
$this->dropColumn($this->tableName, 'priority');
|
||||
}
|
||||
}
|
||||
35
vendor/yiisoft/yii2-queue/src/drivers/db/migrations/M211218163000JobQueueSize.php
vendored
Normal file
35
vendor/yiisoft/yii2-queue/src/drivers/db/migrations/M211218163000JobQueueSize.php
vendored
Normal file
@ -0,0 +1,35 @@
|
||||
<?php
|
||||
/**
|
||||
* @link https://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license https://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\queue\db\migrations;
|
||||
|
||||
use yii\db\Migration;
|
||||
|
||||
/**
|
||||
* Example of migration for queue message storage.
|
||||
*
|
||||
* @author Roman Zhuravlev <zhuravljov@gmail.com>
|
||||
*/
|
||||
class M211218163000JobQueueSize extends Migration
|
||||
{
|
||||
public $tableName = '{{%queue}}';
|
||||
|
||||
|
||||
public function up()
|
||||
{
|
||||
if ($this->db->driverName === 'mysql') {
|
||||
$this->alterColumn($this->tableName, 'job', 'LONGBLOB NOT NULL');
|
||||
}
|
||||
}
|
||||
|
||||
public function down()
|
||||
{
|
||||
if ($this->db->driverName === 'mysql') {
|
||||
$this->alterColumn($this->tableName, 'job', $this->binary()->notNull());
|
||||
}
|
||||
}
|
||||
}
|
||||
105
vendor/yiisoft/yii2-queue/src/drivers/file/Command.php
vendored
Normal file
105
vendor/yiisoft/yii2-queue/src/drivers/file/Command.php
vendored
Normal file
@ -0,0 +1,105 @@
|
||||
<?php
|
||||
/**
|
||||
* @link https://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license https://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\queue\file;
|
||||
|
||||
use yii\console\Exception;
|
||||
use yii\queue\cli\Command as CliCommand;
|
||||
use yii\queue\cli\InfoAction;
|
||||
|
||||
/**
|
||||
* Manages application file-queue.
|
||||
*
|
||||
* @author Roman Zhuravlev <zhuravljov@gmail.com>
|
||||
*/
|
||||
class Command extends CliCommand
|
||||
{
|
||||
/**
|
||||
* @var Queue
|
||||
*/
|
||||
public $queue;
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $defaultAction = 'info';
|
||||
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function actions()
|
||||
{
|
||||
return [
|
||||
'info' => InfoAction::class,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
protected function isWorkerAction($actionID)
|
||||
{
|
||||
return in_array($actionID, ['run', 'listen']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs all jobs from file-queue.
|
||||
* It can be used as cron job.
|
||||
*
|
||||
* @return null|int exit code.
|
||||
*/
|
||||
public function actionRun()
|
||||
{
|
||||
return $this->queue->run(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Listens file-queue and runs new jobs.
|
||||
* It can be used as daemon process.
|
||||
*
|
||||
* @param int $timeout number of seconds to sleep before next reading of the queue.
|
||||
* @throws Exception when params are invalid.
|
||||
* @return null|int exit code.
|
||||
*/
|
||||
public function actionListen($timeout = 3)
|
||||
{
|
||||
if (!is_numeric($timeout)) {
|
||||
throw new Exception('Timeout must be numeric.');
|
||||
}
|
||||
if ($timeout < 1) {
|
||||
throw new Exception('Timeout must be greater than zero.');
|
||||
}
|
||||
|
||||
return $this->queue->run(true, $timeout);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the queue.
|
||||
*
|
||||
* @since 2.0.1
|
||||
*/
|
||||
public function actionClear()
|
||||
{
|
||||
if ($this->confirm('Are you sure?')) {
|
||||
$this->queue->clear();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a job by id.
|
||||
*
|
||||
* @param int $id
|
||||
* @throws Exception when the job is not found.
|
||||
* @since 2.0.1
|
||||
*/
|
||||
public function actionRemove($id)
|
||||
{
|
||||
if (!$this->queue->remove((int) $id)) {
|
||||
throw new Exception('The job is not found.');
|
||||
}
|
||||
}
|
||||
}
|
||||
99
vendor/yiisoft/yii2-queue/src/drivers/file/InfoAction.php
vendored
Normal file
99
vendor/yiisoft/yii2-queue/src/drivers/file/InfoAction.php
vendored
Normal file
@ -0,0 +1,99 @@
|
||||
<?php
|
||||
/**
|
||||
* @link https://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license https://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\queue\file;
|
||||
|
||||
use yii\helpers\Console;
|
||||
use yii\queue\cli\Action;
|
||||
|
||||
/**
|
||||
* Info about queue status.
|
||||
*
|
||||
* @deprecated Will be removed in 3.0. Use yii\queue\cli\InfoAction instead.
|
||||
*
|
||||
* @author Roman Zhuravlev <zhuravljov@gmail.com>
|
||||
*/
|
||||
class InfoAction extends Action
|
||||
{
|
||||
/**
|
||||
* @var Queue
|
||||
*/
|
||||
public $queue;
|
||||
|
||||
|
||||
/**
|
||||
* Info about queue status.
|
||||
*/
|
||||
public function run()
|
||||
{
|
||||
Console::output($this->format('Jobs', Console::FG_GREEN));
|
||||
|
||||
Console::stdout($this->format('- waiting: ', Console::FG_YELLOW));
|
||||
Console::output($this->getWaitingCount());
|
||||
|
||||
Console::stdout($this->format('- delayed: ', Console::FG_YELLOW));
|
||||
Console::output($this->getDelayedCount());
|
||||
|
||||
Console::stdout($this->format('- reserved: ', Console::FG_YELLOW));
|
||||
Console::output($this->getReservedCount());
|
||||
|
||||
Console::stdout($this->format('- done: ', Console::FG_YELLOW));
|
||||
Console::output($this->getDoneCount());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
protected function getWaitingCount()
|
||||
{
|
||||
$data = $this->getIndexData();
|
||||
return !empty($data['waiting']) ? count($data['waiting']) : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
protected function getDelayedCount()
|
||||
{
|
||||
$data = $this->getIndexData();
|
||||
return !empty($data['delayed']) ? count($data['delayed']) : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
protected function getReservedCount()
|
||||
{
|
||||
$data = $this->getIndexData();
|
||||
return !empty($data['reserved']) ? count($data['reserved']) : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
protected function getDoneCount()
|
||||
{
|
||||
$data = $this->getIndexData();
|
||||
$total = isset($data['lastId']) ? $data['lastId'] : 0;
|
||||
return $total - $this->getDelayedCount() - $this->getWaitingCount();
|
||||
}
|
||||
|
||||
protected function getIndexData()
|
||||
{
|
||||
static $data;
|
||||
if ($data === null) {
|
||||
$fileName = $this->queue->path . '/index.data';
|
||||
if (file_exists($fileName)) {
|
||||
$data = call_user_func($this->queue->indexDeserializer, file_get_contents($fileName));
|
||||
} else {
|
||||
$data = [];
|
||||
}
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
323
vendor/yiisoft/yii2-queue/src/drivers/file/Queue.php
vendored
Normal file
323
vendor/yiisoft/yii2-queue/src/drivers/file/Queue.php
vendored
Normal file
@ -0,0 +1,323 @@
|
||||
<?php
|
||||
/**
|
||||
* @link https://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license https://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\queue\file;
|
||||
|
||||
use Yii;
|
||||
use yii\base\InvalidArgumentException;
|
||||
use yii\base\InvalidConfigException;
|
||||
use yii\base\NotSupportedException;
|
||||
use yii\helpers\FileHelper;
|
||||
use yii\queue\cli\Queue as CliQueue;
|
||||
use yii\queue\interfaces\StatisticsProviderInterface;
|
||||
|
||||
/**
|
||||
* File Queue.
|
||||
*
|
||||
* @property-read StatisticsProvider $statisticsProvider
|
||||
*
|
||||
* @author Roman Zhuravlev <zhuravljov@gmail.com>
|
||||
*/
|
||||
class Queue extends CliQueue implements StatisticsProviderInterface
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $path = '@runtime/queue';
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
public $dirMode = 0755;
|
||||
/**
|
||||
* @var int|null
|
||||
*/
|
||||
public $fileMode;
|
||||
/**
|
||||
* @var callable
|
||||
*/
|
||||
public $indexSerializer = 'serialize';
|
||||
/**
|
||||
* @var callable
|
||||
*/
|
||||
public $indexDeserializer = 'unserialize';
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $commandClass = Command::class;
|
||||
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function init()
|
||||
{
|
||||
parent::init();
|
||||
$this->path = Yii::getAlias($this->path);
|
||||
if (!is_dir($this->path)) {
|
||||
FileHelper::createDirectory($this->path, $this->dirMode, true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Listens queue and runs each job.
|
||||
*
|
||||
* @param bool $repeat whether to continue listening when queue is empty.
|
||||
* @param int $timeout number of seconds to sleep before next iteration.
|
||||
* @return null|int exit code.
|
||||
* @internal for worker command only.
|
||||
* @since 2.0.2
|
||||
*/
|
||||
public function run($repeat, $timeout = 0)
|
||||
{
|
||||
return $this->runWorker(function (callable $canContinue) use ($repeat, $timeout) {
|
||||
while ($canContinue()) {
|
||||
if (($payload = $this->reserve()) !== null) {
|
||||
list($id, $message, $ttr, $attempt) = $payload;
|
||||
if ($this->handleMessage($id, $message, $ttr, $attempt)) {
|
||||
$this->delete($payload);
|
||||
}
|
||||
} elseif (!$repeat) {
|
||||
break;
|
||||
} elseif ($timeout) {
|
||||
sleep($timeout);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function status($id)
|
||||
{
|
||||
if (!is_numeric($id) || $id <= 0) {
|
||||
throw new InvalidArgumentException("Unknown message ID: $id.");
|
||||
}
|
||||
|
||||
if (file_exists("$this->path/job$id.data")) {
|
||||
return self::STATUS_WAITING;
|
||||
}
|
||||
|
||||
return self::STATUS_DONE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the queue.
|
||||
*
|
||||
* @since 2.0.1
|
||||
*/
|
||||
public function clear()
|
||||
{
|
||||
$this->touchIndex(function (&$data) {
|
||||
$data = [];
|
||||
foreach (glob("$this->path/job*.data") as $fileName) {
|
||||
unlink($fileName);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a job by ID.
|
||||
*
|
||||
* @param int $id of a job
|
||||
* @return bool
|
||||
* @since 2.0.1
|
||||
*/
|
||||
public function remove($id)
|
||||
{
|
||||
$removed = false;
|
||||
$this->touchIndex(function (&$data) use ($id, &$removed) {
|
||||
if (!empty($data['waiting'])) {
|
||||
foreach ($data['waiting'] as $key => $payload) {
|
||||
if ($payload[0] === $id) {
|
||||
unset($data['waiting'][$key]);
|
||||
$removed = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!$removed && !empty($data['delayed'])) {
|
||||
foreach ($data['delayed'] as $key => $payload) {
|
||||
if ($payload[0] === $id) {
|
||||
unset($data['delayed'][$key]);
|
||||
$removed = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!$removed && !empty($data['reserved'])) {
|
||||
foreach ($data['reserved'] as $key => $payload) {
|
||||
if ($payload[0] === $id) {
|
||||
unset($data['reserved'][$key]);
|
||||
$removed = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($removed) {
|
||||
unlink("$this->path/job$id.data");
|
||||
}
|
||||
});
|
||||
|
||||
return $removed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reserves message for execute.
|
||||
*
|
||||
* @return array|null payload
|
||||
*/
|
||||
protected function reserve()
|
||||
{
|
||||
$id = null;
|
||||
$ttr = null;
|
||||
$attempt = null;
|
||||
$this->touchIndex(function (&$data) use (&$id, &$ttr, &$attempt) {
|
||||
if (!empty($data['reserved'])) {
|
||||
foreach ($data['reserved'] as $key => $payload) {
|
||||
if ($payload[1] + $payload[3] < time()) {
|
||||
list($id, $ttr, $attempt, $time) = $payload;
|
||||
$data['reserved'][$key][2] = ++$attempt;
|
||||
$data['reserved'][$key][3] = time();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($data['delayed']) && $data['delayed'][0][2] <= time()) {
|
||||
list($id, $ttr, $time) = array_shift($data['delayed']);
|
||||
} elseif (!empty($data['waiting'])) {
|
||||
list($id, $ttr) = array_shift($data['waiting']);
|
||||
}
|
||||
if ($id) {
|
||||
$attempt = 1;
|
||||
$data['reserved']["job$id"] = [$id, $ttr, $attempt, time()];
|
||||
}
|
||||
});
|
||||
|
||||
if ($id) {
|
||||
return [$id, file_get_contents("$this->path/job$id.data"), $ttr, $attempt];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes reserved message.
|
||||
*
|
||||
* @param array $payload
|
||||
*/
|
||||
protected function delete($payload)
|
||||
{
|
||||
$id = $payload[0];
|
||||
$this->touchIndex(function (&$data) use ($id) {
|
||||
foreach ($data['reserved'] as $key => $payload) {
|
||||
if ($payload[0] === $id) {
|
||||
unset($data['reserved'][$key]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
unlink("$this->path/job$id.data");
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
protected function pushMessage($message, $ttr, $delay, $priority)
|
||||
{
|
||||
if ($priority !== null) {
|
||||
throw new NotSupportedException('Job priority is not supported in the driver.');
|
||||
}
|
||||
|
||||
$this->touchIndex(function (&$data) use ($message, $ttr, $delay, &$id) {
|
||||
if (!isset($data['lastId'])) {
|
||||
$data['lastId'] = 0;
|
||||
}
|
||||
$id = ++$data['lastId'];
|
||||
$fileName = "$this->path/job$id.data";
|
||||
file_put_contents($fileName, $message);
|
||||
if ($this->fileMode !== null) {
|
||||
chmod($fileName, $this->fileMode);
|
||||
}
|
||||
if (!$delay) {
|
||||
$data['waiting'][] = [$id, $ttr, 0];
|
||||
} else {
|
||||
$data['delayed'][] = [$id, $ttr, time() + $delay];
|
||||
usort($data['delayed'], function ($a, $b) {
|
||||
if ($a[2] < $b[2]) {
|
||||
return -1;
|
||||
}
|
||||
if ($a[2] > $b[2]) {
|
||||
return 1;
|
||||
}
|
||||
if ($a[0] < $b[0]) {
|
||||
return -1;
|
||||
}
|
||||
if ($a[0] > $b[0]) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
return $id;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param callable $callback
|
||||
* @throws InvalidConfigException
|
||||
*/
|
||||
private function touchIndex($callback)
|
||||
{
|
||||
$fileName = "$this->path/index.data";
|
||||
$isNew = !file_exists($fileName);
|
||||
touch($fileName);
|
||||
if ($isNew && $this->fileMode !== null) {
|
||||
chmod($fileName, $this->fileMode);
|
||||
}
|
||||
if (($file = fopen($fileName, 'rb+')) === false) {
|
||||
throw new InvalidConfigException("Unable to open index file: $fileName");
|
||||
}
|
||||
if (!flock($file, LOCK_EX)) {
|
||||
fclose($file);
|
||||
throw new InvalidConfigException("Unable to flock index file: $fileName");
|
||||
}
|
||||
$data = [];
|
||||
$content = stream_get_contents($file);
|
||||
if ($content !== '') {
|
||||
$data = call_user_func($this->indexDeserializer, $content);
|
||||
}
|
||||
try {
|
||||
$callback($data);
|
||||
$newContent = call_user_func($this->indexSerializer, $data);
|
||||
if ($newContent !== $content) {
|
||||
ftruncate($file, 0);
|
||||
rewind($file);
|
||||
fwrite($file, $newContent);
|
||||
fflush($file);
|
||||
}
|
||||
} finally {
|
||||
flock($file, LOCK_UN);
|
||||
fclose($file);
|
||||
}
|
||||
}
|
||||
|
||||
private $_statistcsProvider;
|
||||
|
||||
/**
|
||||
* @return StatisticsProvider
|
||||
*/
|
||||
public function getStatisticsProvider()
|
||||
{
|
||||
if (!$this->_statistcsProvider) {
|
||||
$this->_statistcsProvider = new StatisticsProvider($this);
|
||||
}
|
||||
return $this->_statistcsProvider;
|
||||
}
|
||||
}
|
||||
81
vendor/yiisoft/yii2-queue/src/drivers/file/StatisticsProvider.php
vendored
Normal file
81
vendor/yiisoft/yii2-queue/src/drivers/file/StatisticsProvider.php
vendored
Normal file
@ -0,0 +1,81 @@
|
||||
<?php
|
||||
/**
|
||||
* @link https://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license https://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\queue\file;
|
||||
|
||||
use yii\base\BaseObject;
|
||||
use yii\queue\interfaces\DelayedCountInterface;
|
||||
use yii\queue\interfaces\DoneCountInterface;
|
||||
use yii\queue\interfaces\ReservedCountInterface;
|
||||
use yii\queue\interfaces\WaitingCountInterface;
|
||||
|
||||
/**
|
||||
* Statistics Provider
|
||||
*
|
||||
* @author Kalmer Kaurson <kalmerkaurson@gmail.com>
|
||||
*/
|
||||
class StatisticsProvider extends BaseObject implements DoneCountInterface, WaitingCountInterface, DelayedCountInterface, ReservedCountInterface
|
||||
{
|
||||
/**
|
||||
* @var Queue
|
||||
*/
|
||||
protected $queue;
|
||||
|
||||
|
||||
public function __construct(Queue $queue, $config = [])
|
||||
{
|
||||
$this->queue = $queue;
|
||||
parent::__construct($config);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function getWaitingCount()
|
||||
{
|
||||
$data = $this->getIndexData();
|
||||
return !empty($data['waiting']) ? count($data['waiting']) : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function getDelayedCount()
|
||||
{
|
||||
$data = $this->getIndexData();
|
||||
return !empty($data['delayed']) ? count($data['delayed']) : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function getReservedCount()
|
||||
{
|
||||
$data = $this->getIndexData();
|
||||
return !empty($data['reserved']) ? count($data['reserved']) : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function getDoneCount()
|
||||
{
|
||||
$data = $this->getIndexData();
|
||||
$total = isset($data['lastId']) ? $data['lastId'] : 0;
|
||||
return $total - $this->getDelayedCount() - $this->getWaitingCount();
|
||||
}
|
||||
|
||||
protected function getIndexData()
|
||||
{
|
||||
$fileName = $this->queue->path . '/index.data';
|
||||
if (file_exists($fileName)) {
|
||||
return call_user_func($this->queue->indexDeserializer, file_get_contents($fileName));
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
}
|
||||
54
vendor/yiisoft/yii2-queue/src/drivers/gearman/Command.php
vendored
Normal file
54
vendor/yiisoft/yii2-queue/src/drivers/gearman/Command.php
vendored
Normal file
@ -0,0 +1,54 @@
|
||||
<?php
|
||||
/**
|
||||
* @link https://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license https://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\queue\gearman;
|
||||
|
||||
use yii\queue\cli\Command as CliCommand;
|
||||
|
||||
/**
|
||||
* Manages application gearman-queue.
|
||||
*
|
||||
* @author Roman Zhuravlev <zhuravljov@gmail.com>
|
||||
*/
|
||||
class Command extends CliCommand
|
||||
{
|
||||
/**
|
||||
* @var Queue
|
||||
*/
|
||||
public $queue;
|
||||
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
protected function isWorkerAction($actionID)
|
||||
{
|
||||
return in_array($actionID, ['run', 'listen'], true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs all jobs from gearman-queue.
|
||||
* It can be used as cron job.
|
||||
*
|
||||
* @return null|int exit code.
|
||||
*/
|
||||
public function actionRun()
|
||||
{
|
||||
return $this->queue->run(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Listens gearman-queue and runs new jobs.
|
||||
* It can be used as daemon process.
|
||||
*
|
||||
* @return null|int exit code.
|
||||
*/
|
||||
public function actionListen()
|
||||
{
|
||||
return $this->queue->run(true);
|
||||
}
|
||||
}
|
||||
105
vendor/yiisoft/yii2-queue/src/drivers/gearman/Queue.php
vendored
Normal file
105
vendor/yiisoft/yii2-queue/src/drivers/gearman/Queue.php
vendored
Normal file
@ -0,0 +1,105 @@
|
||||
<?php
|
||||
/**
|
||||
* @link https://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license https://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\queue\gearman;
|
||||
|
||||
use yii\base\NotSupportedException;
|
||||
use yii\queue\cli\Queue as CliQueue;
|
||||
|
||||
/**
|
||||
* Gearman Queue.
|
||||
*
|
||||
* @author Roman Zhuravlev <zhuravljov@gmail.com>
|
||||
*/
|
||||
class Queue extends CliQueue
|
||||
{
|
||||
public $host = 'localhost';
|
||||
public $port = 4730;
|
||||
public $channel = 'queue';
|
||||
/**
|
||||
* @var string command class name
|
||||
*/
|
||||
public $commandClass = Command::class;
|
||||
|
||||
|
||||
/**
|
||||
* Listens queue and runs each job.
|
||||
*
|
||||
* @param bool $repeat whether to continue listening when queue is empty.
|
||||
* @return null|int exit code.
|
||||
* @internal for worker command only.
|
||||
* @since 2.0.2
|
||||
*/
|
||||
public function run($repeat)
|
||||
{
|
||||
return $this->runWorker(function (callable $canContinue) use ($repeat) {
|
||||
$worker = new \GearmanWorker();
|
||||
$worker->addServer($this->host, $this->port);
|
||||
$worker->addFunction($this->channel, function (\GearmanJob $payload) {
|
||||
list($ttr, $message) = explode(';', $payload->workload(), 2);
|
||||
$this->handleMessage($payload->handle(), $message, $ttr, 1);
|
||||
});
|
||||
$worker->setTimeout($repeat ? 1000 : 1);
|
||||
while ($canContinue()) {
|
||||
$result = $worker->work();
|
||||
if (!$result && !$repeat) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
protected function pushMessage($message, $ttr, $delay, $priority)
|
||||
{
|
||||
if ($delay) {
|
||||
throw new NotSupportedException('Delayed work is not supported in the driver.');
|
||||
}
|
||||
|
||||
switch ($priority) {
|
||||
case 'high':
|
||||
return $this->getClient()->doHighBackground($this->channel, "$ttr;$message");
|
||||
case 'low':
|
||||
return $this->getClient()->doLowBackground($this->channel, "$ttr;$message");
|
||||
default:
|
||||
return $this->getClient()->doBackground($this->channel, "$ttr;$message");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function status($id)
|
||||
{
|
||||
$status = $this->getClient()->jobStatus($id);
|
||||
if ($status[0] && !$status[1]) {
|
||||
return self::STATUS_WAITING;
|
||||
}
|
||||
|
||||
if ($status[0] && $status[1]) {
|
||||
return self::STATUS_RESERVED;
|
||||
}
|
||||
|
||||
return self::STATUS_DONE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \GearmanClient
|
||||
*/
|
||||
protected function getClient()
|
||||
{
|
||||
if (!$this->_client) {
|
||||
$this->_client = new \GearmanClient();
|
||||
$this->_client->addServer($this->host, $this->port);
|
||||
}
|
||||
return $this->_client;
|
||||
}
|
||||
|
||||
private $_client;
|
||||
}
|
||||
105
vendor/yiisoft/yii2-queue/src/drivers/redis/Command.php
vendored
Normal file
105
vendor/yiisoft/yii2-queue/src/drivers/redis/Command.php
vendored
Normal file
@ -0,0 +1,105 @@
|
||||
<?php
|
||||
/**
|
||||
* @link https://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license https://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\queue\redis;
|
||||
|
||||
use yii\console\Exception;
|
||||
use yii\queue\cli\Command as CliCommand;
|
||||
use yii\queue\cli\InfoAction;
|
||||
|
||||
/**
|
||||
* Manages application redis-queue.
|
||||
*
|
||||
* @author Roman Zhuravlev <zhuravljov@gmail.com>
|
||||
*/
|
||||
class Command extends CliCommand
|
||||
{
|
||||
/**
|
||||
* @var Queue
|
||||
*/
|
||||
public $queue;
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $defaultAction = 'info';
|
||||
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function actions()
|
||||
{
|
||||
return [
|
||||
'info' => InfoAction::class,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
protected function isWorkerAction($actionID)
|
||||
{
|
||||
return in_array($actionID, ['run', 'listen'], true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs all jobs from redis-queue.
|
||||
* It can be used as cron job.
|
||||
*
|
||||
* @return null|int exit code.
|
||||
*/
|
||||
public function actionRun()
|
||||
{
|
||||
return $this->queue->run(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Listens redis-queue and runs new jobs.
|
||||
* It can be used as daemon process.
|
||||
*
|
||||
* @param int $timeout number of seconds to wait a job.
|
||||
* @throws Exception when params are invalid.
|
||||
* @return null|int exit code.
|
||||
*/
|
||||
public function actionListen($timeout = 3)
|
||||
{
|
||||
if (!is_numeric($timeout)) {
|
||||
throw new Exception('Timeout must be numeric.');
|
||||
}
|
||||
if ($timeout < 1) {
|
||||
throw new Exception('Timeout must be greater than zero.');
|
||||
}
|
||||
|
||||
return $this->queue->run(true, $timeout);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the queue.
|
||||
*
|
||||
* @since 2.0.1
|
||||
*/
|
||||
public function actionClear()
|
||||
{
|
||||
if ($this->confirm('Are you sure?')) {
|
||||
$this->queue->clear();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a job by id.
|
||||
*
|
||||
* @param int $id
|
||||
* @throws Exception when the job is not found.
|
||||
* @since 2.0.1
|
||||
*/
|
||||
public function actionRemove($id)
|
||||
{
|
||||
if (!$this->queue->remove($id)) {
|
||||
throw new Exception('The job is not found.');
|
||||
}
|
||||
}
|
||||
}
|
||||
54
vendor/yiisoft/yii2-queue/src/drivers/redis/InfoAction.php
vendored
Normal file
54
vendor/yiisoft/yii2-queue/src/drivers/redis/InfoAction.php
vendored
Normal file
@ -0,0 +1,54 @@
|
||||
<?php
|
||||
/**
|
||||
* @link https://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license https://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\queue\redis;
|
||||
|
||||
use yii\helpers\Console;
|
||||
use yii\queue\cli\Action;
|
||||
|
||||
/**
|
||||
* Info about queue status.
|
||||
*
|
||||
* @deprecated Will be removed in 3.0. Use yii\queue\cli\InfoAction instead.
|
||||
*
|
||||
* @author Roman Zhuravlev <zhuravljov@gmail.com>
|
||||
*/
|
||||
class InfoAction extends Action
|
||||
{
|
||||
/**
|
||||
* @var Queue
|
||||
*/
|
||||
public $queue;
|
||||
|
||||
|
||||
/**
|
||||
* Info about queue status.
|
||||
*/
|
||||
public function run()
|
||||
{
|
||||
$prefix = $this->queue->channel;
|
||||
$waiting = $this->queue->redis->llen("$prefix.waiting");
|
||||
$delayed = $this->queue->redis->zcount("$prefix.delayed", '-inf', '+inf');
|
||||
$reserved = $this->queue->redis->zcount("$prefix.reserved", '-inf', '+inf');
|
||||
$total = $this->queue->redis->get("$prefix.message_id");
|
||||
$done = $total - $waiting - $delayed - $reserved;
|
||||
|
||||
Console::output($this->format('Jobs', Console::FG_GREEN));
|
||||
|
||||
Console::stdout($this->format('- waiting: ', Console::FG_YELLOW));
|
||||
Console::output($waiting);
|
||||
|
||||
Console::stdout($this->format('- delayed: ', Console::FG_YELLOW));
|
||||
Console::output($delayed);
|
||||
|
||||
Console::stdout($this->format('- reserved: ', Console::FG_YELLOW));
|
||||
Console::output($reserved);
|
||||
|
||||
Console::stdout($this->format('- done: ', Console::FG_YELLOW));
|
||||
Console::output($done);
|
||||
}
|
||||
}
|
||||
224
vendor/yiisoft/yii2-queue/src/drivers/redis/Queue.php
vendored
Normal file
224
vendor/yiisoft/yii2-queue/src/drivers/redis/Queue.php
vendored
Normal file
@ -0,0 +1,224 @@
|
||||
<?php
|
||||
/**
|
||||
* @link https://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license https://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\queue\redis;
|
||||
|
||||
use yii\base\InvalidArgumentException;
|
||||
use yii\base\NotSupportedException;
|
||||
use yii\di\Instance;
|
||||
use yii\queue\cli\Queue as CliQueue;
|
||||
use yii\queue\interfaces\StatisticsProviderInterface;
|
||||
use yii\redis\Connection;
|
||||
|
||||
/**
|
||||
* Redis Queue.
|
||||
*
|
||||
* @property-read StatisticsProvider $statisticsProvider
|
||||
*
|
||||
* @author Roman Zhuravlev <zhuravljov@gmail.com>
|
||||
*/
|
||||
class Queue extends CliQueue implements StatisticsProviderInterface
|
||||
{
|
||||
/**
|
||||
* @var Connection|array|string
|
||||
*/
|
||||
public $redis = 'redis';
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $channel = 'queue';
|
||||
/**
|
||||
* @var string command class name
|
||||
*/
|
||||
public $commandClass = Command::class;
|
||||
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function init()
|
||||
{
|
||||
parent::init();
|
||||
$this->redis = Instance::ensure($this->redis, Connection::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Listens queue and runs each job.
|
||||
*
|
||||
* @param bool $repeat whether to continue listening when queue is empty.
|
||||
* @param int $timeout number of seconds to wait for next message.
|
||||
* @return null|int exit code.
|
||||
* @internal for worker command only.
|
||||
* @since 2.0.2
|
||||
*/
|
||||
public function run($repeat, $timeout = 0)
|
||||
{
|
||||
return $this->runWorker(function (callable $canContinue) use ($repeat, $timeout) {
|
||||
while ($canContinue()) {
|
||||
if (($payload = $this->reserve($timeout)) !== null) {
|
||||
list($id, $message, $ttr, $attempt) = $payload;
|
||||
if ($this->handleMessage($id, $message, $ttr, $attempt)) {
|
||||
$this->delete($id);
|
||||
}
|
||||
} elseif (!$repeat) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function status($id)
|
||||
{
|
||||
if (!is_numeric($id) || $id <= 0) {
|
||||
throw new InvalidArgumentException("Unknown message ID: $id.");
|
||||
}
|
||||
|
||||
if ($this->redis->hexists("$this->channel.attempts", $id)) {
|
||||
return self::STATUS_RESERVED;
|
||||
}
|
||||
|
||||
if ($this->redis->hexists("$this->channel.messages", $id)) {
|
||||
return self::STATUS_WAITING;
|
||||
}
|
||||
|
||||
return self::STATUS_DONE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the queue.
|
||||
*
|
||||
* @since 2.0.1
|
||||
*/
|
||||
public function clear()
|
||||
{
|
||||
while (!$this->redis->set("$this->channel.moving_lock", true, 'NX')) {
|
||||
usleep(10000);
|
||||
}
|
||||
$this->redis->executeCommand('DEL', $this->redis->keys("$this->channel.*"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a job by ID.
|
||||
*
|
||||
* @param int $id of a job
|
||||
* @return bool
|
||||
* @since 2.0.1
|
||||
*/
|
||||
public function remove($id)
|
||||
{
|
||||
while (!$this->redis->set("$this->channel.moving_lock", true, 'NX', 'EX', 1)) {
|
||||
usleep(10000);
|
||||
}
|
||||
if ($this->redis->hdel("$this->channel.messages", $id)) {
|
||||
$this->redis->zrem("$this->channel.delayed", $id);
|
||||
$this->redis->zrem("$this->channel.reserved", $id);
|
||||
$this->redis->lrem("$this->channel.waiting", 0, $id);
|
||||
$this->redis->hdel("$this->channel.attempts", $id);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $timeout timeout
|
||||
* @return array|null payload
|
||||
*/
|
||||
protected function reserve($timeout)
|
||||
{
|
||||
// Moves delayed and reserved jobs into waiting list with lock for one second
|
||||
if ($this->redis->set("$this->channel.moving_lock", true, 'NX', 'EX', 1)) {
|
||||
$this->moveExpired("$this->channel.delayed");
|
||||
$this->moveExpired("$this->channel.reserved");
|
||||
}
|
||||
|
||||
// Find a new waiting message
|
||||
$id = null;
|
||||
if (!$timeout) {
|
||||
$id = $this->redis->rpop("$this->channel.waiting");
|
||||
} elseif ($result = $this->redis->brpop("$this->channel.waiting", $timeout)) {
|
||||
$id = $result[1];
|
||||
}
|
||||
if (!$id) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$payload = $this->redis->hget("$this->channel.messages", $id);
|
||||
if (null === $payload) {
|
||||
return null;
|
||||
}
|
||||
|
||||
list($ttr, $message) = explode(';', $payload, 2);
|
||||
$this->redis->zadd("$this->channel.reserved", time() + $ttr, $id);
|
||||
$attempt = $this->redis->hincrby("$this->channel.attempts", $id, 1);
|
||||
|
||||
return [$id, $message, $ttr, $attempt];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $from
|
||||
*/
|
||||
protected function moveExpired($from)
|
||||
{
|
||||
$now = time();
|
||||
if ($expired = $this->redis->zrevrangebyscore($from, $now, '-inf')) {
|
||||
foreach ($expired as $id) {
|
||||
$this->redis->rpush("$this->channel.waiting", $id);
|
||||
}
|
||||
$this->redis->zremrangebyscore($from, '-inf', $now);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes message by ID.
|
||||
*
|
||||
* @param int $id of a message
|
||||
*/
|
||||
protected function delete($id)
|
||||
{
|
||||
$this->redis->zrem("$this->channel.reserved", $id);
|
||||
$this->redis->hdel("$this->channel.attempts", $id);
|
||||
$this->redis->hdel("$this->channel.messages", $id);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
protected function pushMessage($message, $ttr, $delay, $priority)
|
||||
{
|
||||
if ($priority !== null) {
|
||||
throw new NotSupportedException('Job priority is not supported in the driver.');
|
||||
}
|
||||
|
||||
$id = $this->redis->incr("$this->channel.message_id");
|
||||
$this->redis->hset("$this->channel.messages", $id, "$ttr;$message");
|
||||
if (!$delay) {
|
||||
$this->redis->lpush("$this->channel.waiting", $id);
|
||||
} else {
|
||||
$this->redis->zadd("$this->channel.delayed", time() + $delay, $id);
|
||||
}
|
||||
|
||||
return $id;
|
||||
}
|
||||
|
||||
private $_statistcsProvider;
|
||||
|
||||
/**
|
||||
* @return StatisticsProvider
|
||||
*/
|
||||
public function getStatisticsProvider()
|
||||
{
|
||||
if (!$this->_statistcsProvider) {
|
||||
$this->_statistcsProvider = new StatisticsProvider($this);
|
||||
}
|
||||
return $this->_statistcsProvider;
|
||||
}
|
||||
}
|
||||
74
vendor/yiisoft/yii2-queue/src/drivers/redis/StatisticsProvider.php
vendored
Normal file
74
vendor/yiisoft/yii2-queue/src/drivers/redis/StatisticsProvider.php
vendored
Normal file
@ -0,0 +1,74 @@
|
||||
<?php
|
||||
/**
|
||||
* @link https://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license https://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\queue\redis;
|
||||
|
||||
use yii\base\BaseObject;
|
||||
use yii\queue\interfaces\DelayedCountInterface;
|
||||
use yii\queue\interfaces\DoneCountInterface;
|
||||
use yii\queue\interfaces\ReservedCountInterface;
|
||||
use yii\queue\interfaces\WaitingCountInterface;
|
||||
|
||||
/**
|
||||
* Statistics Provider
|
||||
*
|
||||
* @author Kalmer Kaurson <kalmerkaurson@gmail.com>
|
||||
*/
|
||||
class StatisticsProvider extends BaseObject implements DoneCountInterface, WaitingCountInterface, DelayedCountInterface, ReservedCountInterface
|
||||
{
|
||||
/**
|
||||
* @var Queue
|
||||
*/
|
||||
protected $queue;
|
||||
|
||||
|
||||
public function __construct(Queue $queue, $config = [])
|
||||
{
|
||||
$this->queue = $queue;
|
||||
parent::__construct($config);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function getWaitingCount()
|
||||
{
|
||||
$prefix = $this->queue->channel;
|
||||
return $this->queue->redis->llen("$prefix.waiting");
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function getDelayedCount()
|
||||
{
|
||||
$prefix = $this->queue->channel;
|
||||
return $this->queue->redis->zcount("$prefix.delayed", '-inf', '+inf');
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function getReservedCount()
|
||||
{
|
||||
$prefix = $this->queue->channel;
|
||||
return $this->queue->redis->zcount("$prefix.reserved", '-inf', '+inf');
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function getDoneCount()
|
||||
{
|
||||
$prefix = $this->queue->channel;
|
||||
$waiting = $this->getWaitingCount();
|
||||
$delayed = $this->getDelayedCount();
|
||||
$reserved = $this->getReservedCount();
|
||||
$total = $this->queue->redis->get("$prefix.message_id");
|
||||
return $total - $waiting - $delayed - $reserved;
|
||||
}
|
||||
}
|
||||
78
vendor/yiisoft/yii2-queue/src/drivers/sqs/Command.php
vendored
Normal file
78
vendor/yiisoft/yii2-queue/src/drivers/sqs/Command.php
vendored
Normal file
@ -0,0 +1,78 @@
|
||||
<?php
|
||||
/**
|
||||
* @link https://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license https://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\queue\sqs;
|
||||
|
||||
use yii\console\Exception;
|
||||
use yii\queue\cli\Command as CliCommand;
|
||||
|
||||
/**
|
||||
* Manages application aws sqs-queue.
|
||||
*
|
||||
* @author Max Kozlovsky <kozlovskymaxim@gmail.com>
|
||||
* @author Manoj Malviya <manojm@girnarsoft.com>
|
||||
*/
|
||||
class Command extends CliCommand
|
||||
{
|
||||
/**
|
||||
* @var Queue
|
||||
*/
|
||||
public $queue;
|
||||
|
||||
|
||||
/**
|
||||
* Runs all jobs from sqs.
|
||||
* It can be used as cron job.
|
||||
*
|
||||
* @return null|int exit code.
|
||||
*/
|
||||
public function actionRun()
|
||||
{
|
||||
return $this->queue->run(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Listens sqs and runs new jobs.
|
||||
* It can be used as demon process.
|
||||
*
|
||||
* @param int $timeout number of seconds to sleep before next reading of the queue.
|
||||
* @throws Exception when params are invalid.
|
||||
* @return null|int exit code.
|
||||
*/
|
||||
public function actionListen($timeout = 3)
|
||||
{
|
||||
if (!is_numeric($timeout)) {
|
||||
throw new Exception('Timeout must be numeric.');
|
||||
}
|
||||
$timeout = (int) $timeout;
|
||||
|
||||
if ($timeout < 1 || $timeout > 20) {
|
||||
throw new Exception('Timeout must be between 1 and 20');
|
||||
}
|
||||
|
||||
return $this->queue->run(true, $timeout);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the queue.
|
||||
*/
|
||||
public function actionClear()
|
||||
{
|
||||
if ($this->confirm('Are you sure?')) {
|
||||
$this->queue->clear();
|
||||
$this->stdout("Queue has been cleared.\n");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
protected function isWorkerAction($actionID)
|
||||
{
|
||||
return in_array($actionID, ['run', 'listen']);
|
||||
}
|
||||
}
|
||||
244
vendor/yiisoft/yii2-queue/src/drivers/sqs/Queue.php
vendored
Normal file
244
vendor/yiisoft/yii2-queue/src/drivers/sqs/Queue.php
vendored
Normal file
@ -0,0 +1,244 @@
|
||||
<?php
|
||||
/**
|
||||
* @link https://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license https://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\queue\sqs;
|
||||
|
||||
use Aws\Credentials\CredentialProvider;
|
||||
use Aws\Sqs\SqsClient;
|
||||
use yii\base\NotSupportedException;
|
||||
use yii\queue\cli\Queue as CliQueue;
|
||||
use yii\queue\serializers\JsonSerializer;
|
||||
|
||||
/**
|
||||
* SQS Queue.
|
||||
*
|
||||
* @author Max Kozlovsky <kozlovskymaxim@gmail.com>
|
||||
* @author Manoj Malviya <manojm@girnarsoft.com>
|
||||
*/
|
||||
class Queue extends CliQueue
|
||||
{
|
||||
/**
|
||||
* The SQS url.
|
||||
* @var string
|
||||
*/
|
||||
public $url;
|
||||
/**
|
||||
* aws access key.
|
||||
* @var string|null
|
||||
*/
|
||||
public $key;
|
||||
/**
|
||||
* aws secret.
|
||||
* @var string|null
|
||||
*/
|
||||
public $secret;
|
||||
/**
|
||||
* region where queue is hosted.
|
||||
* @var string
|
||||
*/
|
||||
public $region = '';
|
||||
/**
|
||||
* API version.
|
||||
* @var string
|
||||
*/
|
||||
public $version = 'latest';
|
||||
/**
|
||||
* Message Group ID for FIFO queues.
|
||||
* @var string
|
||||
* @since 2.2.1
|
||||
*/
|
||||
public $messageGroupId = 'default';
|
||||
/**
|
||||
* @var string command class name
|
||||
* @inheritdoc
|
||||
*/
|
||||
public $commandClass = Command::class;
|
||||
/**
|
||||
* Json serializer by default.
|
||||
* @inheritdoc
|
||||
*/
|
||||
public $serializer = JsonSerializer::class;
|
||||
|
||||
/**
|
||||
* @var SqsClient
|
||||
*/
|
||||
private $_client;
|
||||
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function init()
|
||||
{
|
||||
parent::init();
|
||||
}
|
||||
|
||||
/**
|
||||
* Listens queue and runs each job.
|
||||
*
|
||||
* @param bool $repeat whether to continue listening when queue is empty.
|
||||
* @param int $timeout number of seconds to sleep before next iteration.
|
||||
* @return null|int exit code.
|
||||
* @internal for worker command only
|
||||
*/
|
||||
public function run($repeat, $timeout = 0)
|
||||
{
|
||||
return $this->runWorker(function (callable $canContinue) use ($repeat, $timeout) {
|
||||
while ($canContinue()) {
|
||||
if (($payload = $this->reserve($timeout)) !== null) {
|
||||
$id = $payload['MessageId'];
|
||||
$message = $payload['Body'];
|
||||
$ttr = (int) $payload['MessageAttributes']['TTR']['StringValue'];
|
||||
$attempt = (int) $payload['Attributes']['ApproximateReceiveCount'];
|
||||
if ($this->handleMessage($id, $message, $ttr, $attempt)) {
|
||||
$this->delete($payload);
|
||||
}
|
||||
} elseif (!$repeat) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a single message from SQS queue and sets the visibility to reserve message.
|
||||
*
|
||||
* @param int $timeout number of seconds for long polling. Must be between 0 and 20.
|
||||
* @return null|array payload.
|
||||
*/
|
||||
protected function reserve($timeout)
|
||||
{
|
||||
$response = $this->getClient()->receiveMessage([
|
||||
'QueueUrl' => $this->url,
|
||||
'AttributeNames' => ['ApproximateReceiveCount'],
|
||||
'MessageAttributeNames' => ['TTR'],
|
||||
'MaxNumberOfMessages' => 1,
|
||||
'VisibilityTimeout' => $this->ttr,
|
||||
'WaitTimeSeconds' => $timeout,
|
||||
]);
|
||||
if (!$response['Messages']) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$payload = reset($response['Messages']);
|
||||
|
||||
$ttr = (int) $payload['MessageAttributes']['TTR']['StringValue'];
|
||||
if ($ttr != $this->ttr) {
|
||||
$this->getClient()->changeMessageVisibility([
|
||||
'QueueUrl' => $this->url,
|
||||
'ReceiptHandle' => $payload['ReceiptHandle'],
|
||||
'VisibilityTimeout' => $ttr,
|
||||
]);
|
||||
}
|
||||
|
||||
return $payload;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes the message after successfully handling.
|
||||
*
|
||||
* @param array $payload
|
||||
*/
|
||||
protected function delete($payload)
|
||||
{
|
||||
$this->getClient()->deleteMessage([
|
||||
'QueueUrl' => $this->url,
|
||||
'ReceiptHandle' => $payload['ReceiptHandle'],
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the queue.
|
||||
*/
|
||||
public function clear()
|
||||
{
|
||||
$this->getClient()->purgeQueue([
|
||||
'QueueUrl' => $this->url,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function status($id)
|
||||
{
|
||||
throw new NotSupportedException('Status is not supported in the driver.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides public access for `handleMessage`
|
||||
*
|
||||
* @param $id string
|
||||
* @param $message string
|
||||
* @param $ttr int
|
||||
* @param $attempt int
|
||||
* @return bool
|
||||
* @since 2.2.1
|
||||
*/
|
||||
public function handle($id, $message, $ttr, $attempt)
|
||||
{
|
||||
return $this->handleMessage($id, $message, $ttr, $attempt);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
protected function pushMessage($message, $ttr, $delay, $priority)
|
||||
{
|
||||
if ($priority) {
|
||||
throw new NotSupportedException('Priority is not supported in this driver');
|
||||
}
|
||||
|
||||
$request = [
|
||||
'QueueUrl' => $this->url,
|
||||
'MessageBody' => $message,
|
||||
'DelaySeconds' => $delay,
|
||||
'MessageAttributes' => [
|
||||
'TTR' => [
|
||||
'DataType' => 'Number',
|
||||
'StringValue' => (string) $ttr,
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
if (substr($this->url, -5) === '.fifo') {
|
||||
$request['MessageGroupId'] = $this->messageGroupId;
|
||||
$request['MessageDeduplicationId'] = hash('sha256', $message);
|
||||
}
|
||||
|
||||
$response = $this->getClient()->sendMessage($request);
|
||||
return $response['MessageId'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Aws\Sqs\SqsClient
|
||||
*/
|
||||
protected function getClient()
|
||||
{
|
||||
if ($this->_client) {
|
||||
return $this->_client;
|
||||
}
|
||||
|
||||
if ($this->key !== null && $this->secret !== null) {
|
||||
$credentials = [
|
||||
'key' => $this->key,
|
||||
'secret' => $this->secret,
|
||||
];
|
||||
} else {
|
||||
// use default provider if no key and secret passed
|
||||
//see - https://docs.aws.amazon.com/aws-sdk-php/v3/guide/guide/credentials.html#credential-profiles
|
||||
$credentials = CredentialProvider::defaultProvider();
|
||||
}
|
||||
|
||||
$this->_client = new SqsClient([
|
||||
'credentials' => $credentials,
|
||||
'region' => $this->region,
|
||||
'version' => $this->version,
|
||||
]);
|
||||
return $this->_client;
|
||||
}
|
||||
}
|
||||
66
vendor/yiisoft/yii2-queue/src/drivers/stomp/Command.php
vendored
Normal file
66
vendor/yiisoft/yii2-queue/src/drivers/stomp/Command.php
vendored
Normal file
@ -0,0 +1,66 @@
|
||||
<?php
|
||||
/**
|
||||
* @link https://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license https://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\queue\stomp;
|
||||
|
||||
use yii\console\Exception;
|
||||
use yii\queue\cli\Command as CliCommand;
|
||||
|
||||
/**
|
||||
* Manages application stomp-queue.
|
||||
*
|
||||
* @author Sergey Vershinin <versh23@gmail.com>
|
||||
* @since 2.3.0
|
||||
*/
|
||||
class Command extends CliCommand
|
||||
{
|
||||
/**
|
||||
* @var Queue
|
||||
*/
|
||||
public $queue;
|
||||
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
protected function isWorkerAction($actionID)
|
||||
{
|
||||
return in_array($actionID, ['run', 'listen']);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Runs all jobs from stomp-queue.
|
||||
* It can be used as cron job.
|
||||
*
|
||||
* @return null|int exit code.
|
||||
*/
|
||||
public function actionRun()
|
||||
{
|
||||
return $this->queue->run(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Listens stomp-queue and runs new jobs.
|
||||
* It can be used as daemon process.
|
||||
*
|
||||
* @param int $timeout number of seconds to wait a job.
|
||||
* @throws Exception when params are invalid.
|
||||
* @return null|int exit code.
|
||||
*/
|
||||
public function actionListen($timeout = 3)
|
||||
{
|
||||
if (!is_numeric($timeout)) {
|
||||
throw new Exception('Timeout must be numeric.');
|
||||
}
|
||||
if ($timeout < 1) {
|
||||
throw new Exception('Timeout must be greater that zero.');
|
||||
}
|
||||
|
||||
return $this->queue->run(true, $timeout);
|
||||
}
|
||||
}
|
||||
292
vendor/yiisoft/yii2-queue/src/drivers/stomp/Queue.php
vendored
Normal file
292
vendor/yiisoft/yii2-queue/src/drivers/stomp/Queue.php
vendored
Normal file
@ -0,0 +1,292 @@
|
||||
<?php
|
||||
/**
|
||||
* @link https://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license https://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\queue\stomp;
|
||||
|
||||
use Enqueue\Stomp\StompConnectionFactory;
|
||||
use Enqueue\Stomp\StompContext;
|
||||
use Enqueue\Stomp\StompMessage;
|
||||
use yii\base\Application as BaseApp;
|
||||
use yii\base\Event;
|
||||
use yii\base\NotSupportedException;
|
||||
use yii\queue\cli\Queue as CliQueue;
|
||||
|
||||
/**
|
||||
* Stomp Queue.
|
||||
* @author Sergey Vershinin <versh23@gmail.com>
|
||||
* @since 2.3.0
|
||||
*/
|
||||
class Queue extends CliQueue
|
||||
{
|
||||
const ATTEMPT = 'yii-attempt';
|
||||
const TTR = 'yii-ttr';
|
||||
|
||||
/**
|
||||
* The message queue broker's host.
|
||||
*
|
||||
* @var string|null
|
||||
*/
|
||||
public $host;
|
||||
/**
|
||||
* The message queue broker's port.
|
||||
*
|
||||
* @var string|null
|
||||
*/
|
||||
public $port;
|
||||
/**
|
||||
* This is user which is used to login on the broker.
|
||||
*
|
||||
* @var string|null
|
||||
*/
|
||||
public $user;
|
||||
/**
|
||||
* This is password which is used to login on the broker.
|
||||
*
|
||||
* @var string|null
|
||||
*/
|
||||
public $password;
|
||||
/**
|
||||
* Sets an fixed vhostname, which will be passed on connect as header['host'].
|
||||
*
|
||||
* @var string|null
|
||||
*/
|
||||
public $vhost;
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
public $bufferSize;
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
public $connectionTimeout;
|
||||
/**
|
||||
* Perform request synchronously.
|
||||
* @var bool
|
||||
*/
|
||||
public $sync;
|
||||
/**
|
||||
* The connection will be established as later as possible if set true.
|
||||
*
|
||||
* @var bool|null
|
||||
*/
|
||||
public $lazy;
|
||||
/**
|
||||
* Defines whether secure connection should be used or not.
|
||||
*
|
||||
* @var bool|null
|
||||
*/
|
||||
public $sslOn;
|
||||
/**
|
||||
* The queue used to consume messages from.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $queueName = 'stomp_queue';
|
||||
/**
|
||||
* The property contains a command class which used in cli.
|
||||
*
|
||||
* @var string command class name
|
||||
*/
|
||||
public $commandClass = Command::class;
|
||||
/**
|
||||
* Set the read timeout.
|
||||
* @var int
|
||||
*/
|
||||
public $readTimeOut = 0;
|
||||
|
||||
/**
|
||||
* @var StompContext
|
||||
*/
|
||||
protected $context;
|
||||
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function init()
|
||||
{
|
||||
parent::init();
|
||||
Event::on(BaseApp::class, BaseApp::EVENT_AFTER_REQUEST, function () {
|
||||
$this->close();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens connection.
|
||||
*/
|
||||
protected function open()
|
||||
{
|
||||
if ($this->context) {
|
||||
return;
|
||||
}
|
||||
|
||||
$config = [
|
||||
'host' => $this->host,
|
||||
'port' => $this->port,
|
||||
'login' => $this->user,
|
||||
'password' => $this->password,
|
||||
'vhost' => $this->vhost,
|
||||
'buffer_size' => $this->bufferSize,
|
||||
'connection_timeout' => $this->connectionTimeout,
|
||||
'sync' => $this->sync,
|
||||
'lazy' => $this->lazy,
|
||||
'ssl_on' => $this->sslOn,
|
||||
];
|
||||
|
||||
$config = array_filter($config, function ($value) {
|
||||
return null !== $value;
|
||||
});
|
||||
|
||||
$factory = new StompConnectionFactory($config);
|
||||
|
||||
$this->context = $factory->createContext();
|
||||
}
|
||||
|
||||
/**
|
||||
* Listens queue and runs each job.
|
||||
*
|
||||
* @param $repeat
|
||||
* @param int $timeout
|
||||
* @return int|null
|
||||
*/
|
||||
public function run($repeat, $timeout = 0)
|
||||
{
|
||||
return $this->runWorker(function (callable $canContinue) use ($repeat, $timeout) {
|
||||
$this->open();
|
||||
$queue = $this->createQueue($this->queueName);
|
||||
$consumer = $this->context->createConsumer($queue);
|
||||
|
||||
while ($canContinue()) {
|
||||
if ($message = ($this->readTimeOut > 0 ? $consumer->receive($this->readTimeOut) : $consumer->receiveNoWait())) {
|
||||
$messageId = $message->getMessageId();
|
||||
if (!$messageId) {
|
||||
$message = $this->setMessageId($message);
|
||||
}
|
||||
|
||||
if ($message->isRedelivered()) {
|
||||
$consumer->acknowledge($message);
|
||||
|
||||
$this->redeliver($message);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
$ttr = $message->getProperty(self::TTR, $this->ttr);
|
||||
$attempt = $message->getProperty(self::ATTEMPT, 1);
|
||||
|
||||
if ($this->handleMessage($message->getMessageId(), $message->getBody(), $ttr, $attempt)) {
|
||||
$consumer->acknowledge($message);
|
||||
} else {
|
||||
$consumer->acknowledge($message);
|
||||
|
||||
$this->redeliver($message);
|
||||
}
|
||||
} elseif (!$repeat) {
|
||||
break;
|
||||
} elseif ($timeout) {
|
||||
sleep($timeout);
|
||||
$this->context->getStomp()->getConnection()->sendAlive();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @param StompMessage $message
|
||||
* @return StompMessage
|
||||
* @throws \Interop\Queue\Exception
|
||||
*/
|
||||
protected function setMessageId(StompMessage $message)
|
||||
{
|
||||
$message->setMessageId(uniqid('', true));
|
||||
return $message;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
* @throws \Interop\Queue\Exception
|
||||
* @throws NotSupportedException
|
||||
*/
|
||||
protected function pushMessage($message, $ttr, $delay, $priority)
|
||||
{
|
||||
$this->open();
|
||||
|
||||
$queue = $this->createQueue($this->queueName);
|
||||
$message = $this->context->createMessage($message);
|
||||
$message = $this->setMessageId($message);
|
||||
$message->setPersistent(true);
|
||||
$message->setProperty(self::ATTEMPT, 1);
|
||||
$message->setProperty(self::TTR, $ttr);
|
||||
|
||||
$producer = $this->context->createProducer();
|
||||
|
||||
if ($delay) {
|
||||
throw new NotSupportedException('Delayed work is not supported in the driver.');
|
||||
}
|
||||
|
||||
if ($priority) {
|
||||
throw new NotSupportedException('Job priority is not supported in the driver.');
|
||||
}
|
||||
|
||||
$producer->send($queue, $message);
|
||||
|
||||
return $message->getMessageId();
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes connection.
|
||||
*/
|
||||
protected function close()
|
||||
{
|
||||
if (!$this->context) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->context->close();
|
||||
$this->context = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
* @throws NotSupportedException
|
||||
*/
|
||||
public function status($id)
|
||||
{
|
||||
throw new NotSupportedException('Status is not supported in the driver.');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param StompMessage $message
|
||||
* @throws \Interop\Queue\Exception
|
||||
*/
|
||||
protected function redeliver(StompMessage $message)
|
||||
{
|
||||
$attempt = $message->getProperty(self::ATTEMPT, 1);
|
||||
|
||||
$newMessage = $this->context->createMessage($message->getBody(), $message->getProperties(), $message->getHeaders());
|
||||
$newMessage->setProperty(self::ATTEMPT, ++$attempt);
|
||||
|
||||
$this->context->createProducer()->send(
|
||||
$this->createQueue($this->queueName),
|
||||
$newMessage
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $name
|
||||
* @return \Enqueue\Stomp\StompDestination
|
||||
*/
|
||||
private function createQueue($name)
|
||||
{
|
||||
$queue = $this->context->createQueue($name);
|
||||
$queue->setDurable(true);
|
||||
$queue->setAutoDelete(false);
|
||||
$queue->setExclusive(false);
|
||||
|
||||
return $queue;
|
||||
}
|
||||
}
|
||||
102
vendor/yiisoft/yii2-queue/src/drivers/sync/Queue.php
vendored
Normal file
102
vendor/yiisoft/yii2-queue/src/drivers/sync/Queue.php
vendored
Normal file
@ -0,0 +1,102 @@
|
||||
<?php
|
||||
/**
|
||||
* @link https://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license https://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\queue\sync;
|
||||
|
||||
use Yii;
|
||||
use yii\base\Application;
|
||||
use yii\base\InvalidArgumentException;
|
||||
use yii\queue\Queue as BaseQueue;
|
||||
|
||||
/**
|
||||
* Sync Queue.
|
||||
*
|
||||
* @author Roman Zhuravlev <zhuravljov@gmail.com>
|
||||
*/
|
||||
class Queue extends BaseQueue
|
||||
{
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
public $handle = false;
|
||||
|
||||
/**
|
||||
* @var array of payloads
|
||||
*/
|
||||
private $payloads = [];
|
||||
/**
|
||||
* @var int last pushed ID
|
||||
*/
|
||||
private $pushedId = 0;
|
||||
/**
|
||||
* @var int started ID
|
||||
*/
|
||||
private $startedId = 0;
|
||||
/**
|
||||
* @var int last finished ID
|
||||
*/
|
||||
private $finishedId = 0;
|
||||
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function init()
|
||||
{
|
||||
parent::init();
|
||||
if ($this->handle) {
|
||||
Yii::$app->on(Application::EVENT_AFTER_REQUEST, function () {
|
||||
ob_start();
|
||||
$this->run();
|
||||
ob_end_clean();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs all jobs from queue.
|
||||
*/
|
||||
public function run()
|
||||
{
|
||||
while (($payload = array_shift($this->payloads)) !== null) {
|
||||
list($ttr, $message) = $payload;
|
||||
$this->startedId = $this->finishedId + 1;
|
||||
$this->handleMessage($this->startedId, $message, $ttr, 1);
|
||||
$this->finishedId = $this->startedId;
|
||||
$this->startedId = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
protected function pushMessage($message, $ttr, $delay, $priority)
|
||||
{
|
||||
array_push($this->payloads, [$ttr, $message]);
|
||||
return ++$this->pushedId;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function status($id)
|
||||
{
|
||||
if (!is_int($id) || $id <= 0 || $id > $this->pushedId) {
|
||||
throw new InvalidArgumentException("Unknown messages ID: $id.");
|
||||
}
|
||||
|
||||
if ($id <= $this->finishedId) {
|
||||
return self::STATUS_DONE;
|
||||
}
|
||||
|
||||
if ($id === $this->startedId) {
|
||||
return self::STATUS_RESERVED;
|
||||
}
|
||||
|
||||
return self::STATUS_WAITING;
|
||||
}
|
||||
}
|
||||
162
vendor/yiisoft/yii2-queue/src/gii/Generator.php
vendored
Normal file
162
vendor/yiisoft/yii2-queue/src/gii/Generator.php
vendored
Normal file
@ -0,0 +1,162 @@
|
||||
<?php
|
||||
/**
|
||||
* @link https://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license https://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\queue\gii;
|
||||
|
||||
use Yii;
|
||||
use yii\base\BaseObject;
|
||||
use yii\gii\CodeFile;
|
||||
use yii\queue\JobInterface;
|
||||
use yii\queue\RetryableJobInterface;
|
||||
|
||||
/**
|
||||
* This generator will generate a job.
|
||||
*
|
||||
* @author Roman Zhuravlev <zhuravljov@gmail.com>
|
||||
*/
|
||||
class Generator extends \yii\gii\Generator
|
||||
{
|
||||
public $jobClass;
|
||||
public $properties;
|
||||
public $retryable = false;
|
||||
public $ns = 'app\jobs';
|
||||
public $baseClass = BaseObject::class;
|
||||
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
return 'Job Generator';
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function getDescription()
|
||||
{
|
||||
return 'This generator generates a Job class for the queue.';
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return array_merge(parent::rules(), [
|
||||
[['jobClass', 'properties', 'ns', 'baseClass'], 'trim'],
|
||||
[['jobClass', 'ns', 'baseClass'], 'required'],
|
||||
['jobClass', 'match', 'pattern' => '/^\w+$/', 'message' => 'Only word characters are allowed.'],
|
||||
['jobClass', 'validateJobClass'],
|
||||
['properties', 'match', 'pattern' => '/^[a-z_][a-z0-9_,\\s]*$/i', 'message' => 'Must be valid class properties.'],
|
||||
['retryable', 'boolean'],
|
||||
['ns', 'validateNamespace'],
|
||||
['baseClass', 'validateClass'],
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function attributeLabels()
|
||||
{
|
||||
return array_merge(parent::attributeLabels(), [
|
||||
'jobClass' => 'Job Class',
|
||||
'properties' => 'Job Properties',
|
||||
'retryable' => 'Retryable Job',
|
||||
'ns' => 'Namespace',
|
||||
'baseClass' => 'Base Class',
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function hints()
|
||||
{
|
||||
return array_merge(parent::hints(), [
|
||||
'jobClass' => 'This is the name of the Job class to be generated, e.g., <code>SomeJob</code>.',
|
||||
'properties' => 'Job object property names. Separate multiple properties with commas or spaces, e.g., <code>prop1, prop2</code>.',
|
||||
'retryable' => 'Job object will implement <code>RetryableJobInterface</code> interface.',
|
||||
'ns' => 'This is the namespace of the Job class to be generated.',
|
||||
'baseClass' => 'This is the class that the new Job class will extend from.',
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function stickyAttributes()
|
||||
{
|
||||
return array_merge(parent::stickyAttributes(), ['ns', 'baseClass']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function requiredTemplates()
|
||||
{
|
||||
return ['job.php'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function generate()
|
||||
{
|
||||
$params = [];
|
||||
$params['jobClass'] = $this->jobClass;
|
||||
$params['ns'] = $this->ns;
|
||||
$params['baseClass'] = '\\' . ltrim($this->baseClass, '\\');
|
||||
$params['interfaces'] = [];
|
||||
if (!$this->retryable) {
|
||||
if (!is_a($this->baseClass, JobInterface::class, true)) {
|
||||
$params['interfaces'][] = '\\' . JobInterface::class;
|
||||
}
|
||||
} else {
|
||||
if (!is_a($this->baseClass, RetryableJobInterface::class, true)) {
|
||||
$params['interfaces'][] = '\\' . RetryableJobInterface::class;
|
||||
}
|
||||
}
|
||||
$params['properties'] = array_unique(preg_split('/[\s,]+/', $this->properties, -1, PREG_SPLIT_NO_EMPTY));
|
||||
|
||||
$jobFile = new CodeFile(
|
||||
Yii::getAlias('@' . str_replace('\\', '/', $this->ns)) . '/' . $this->jobClass . '.php',
|
||||
$this->render('job.php', $params)
|
||||
);
|
||||
|
||||
return [$jobFile];
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates the job class.
|
||||
*
|
||||
* @param string $attribute job attribute name.
|
||||
*/
|
||||
public function validateJobClass($attribute)
|
||||
{
|
||||
if ($this->isReservedKeyword($this->$attribute)) {
|
||||
$this->addError($attribute, 'Class name cannot be a reserved PHP keyword.');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates the namespace.
|
||||
*
|
||||
* @param string $attribute Namespace attribute name.
|
||||
*/
|
||||
public function validateNamespace($attribute)
|
||||
{
|
||||
$value = $this->$attribute;
|
||||
$value = ltrim($value, '\\');
|
||||
$path = Yii::getAlias('@' . str_replace('\\', '/', $value), false);
|
||||
if ($path === false) {
|
||||
$this->addError($attribute, 'Namespace must be associated with an existing directory.');
|
||||
}
|
||||
}
|
||||
}
|
||||
56
vendor/yiisoft/yii2-queue/src/gii/default/job.php
vendored
Normal file
56
vendor/yiisoft/yii2-queue/src/gii/default/job.php
vendored
Normal file
@ -0,0 +1,56 @@
|
||||
<?php
|
||||
/**
|
||||
* @var \yii\web\View $this
|
||||
* @var \yii\queue\gii\Generator $generator
|
||||
* @var string $jobClass
|
||||
* @var string $$ns
|
||||
* @var string $baseClass
|
||||
* @var string[] $interfaces
|
||||
* @var string[] $properties
|
||||
*/
|
||||
if ($interfaces) {
|
||||
$implements = 'implements ' . implode(', ', $interfaces);
|
||||
} else {
|
||||
$implements = '';
|
||||
}
|
||||
|
||||
echo "<?php\n";
|
||||
?>
|
||||
|
||||
namespace <?= $ns ?>;
|
||||
|
||||
/**
|
||||
* Class <?= $jobClass ?>.
|
||||
*/
|
||||
class <?= $jobClass ?> extends <?= $baseClass ?> <?= $implements ?>
|
||||
|
||||
{
|
||||
<?php foreach ($properties as $property): ?>
|
||||
public $<?= $property ?>;
|
||||
|
||||
<?php endforeach; ?>
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function execute($queue)
|
||||
{
|
||||
}
|
||||
<?php if ($generator->retryable): ?>
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function getTtr()
|
||||
{
|
||||
return 60;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function canRetry($attempt, $error)
|
||||
{
|
||||
return $attempt < 3;
|
||||
}
|
||||
<?php endif; ?>
|
||||
}
|
||||
12
vendor/yiisoft/yii2-queue/src/gii/form.php
vendored
Normal file
12
vendor/yiisoft/yii2-queue/src/gii/form.php
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
<?php
|
||||
/**
|
||||
* @var \yii\web\View $this
|
||||
* @var \yii\widgets\ActiveForm $form
|
||||
* @var \yii\queue\gii\Generator $generator
|
||||
*/
|
||||
?>
|
||||
<?= $form->field($generator, 'jobClass')->textInput(['autofocus' => true]) ?>
|
||||
<?= $form->field($generator, 'properties') ?>
|
||||
<?= $form->field($generator, 'retryable')->checkbox() ?>
|
||||
<?= $form->field($generator, 'ns') ?>
|
||||
<?= $form->field($generator, 'baseClass') ?>
|
||||
21
vendor/yiisoft/yii2-queue/src/interfaces/DelayedCountInterface.php
vendored
Normal file
21
vendor/yiisoft/yii2-queue/src/interfaces/DelayedCountInterface.php
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
<?php
|
||||
/**
|
||||
* @link https://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license https://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\queue\interfaces;
|
||||
|
||||
/**
|
||||
* Delayed Count Interface
|
||||
*
|
||||
* @author Kalmer Kaurson <kalmerkaurson@gmail.com>
|
||||
*/
|
||||
interface DelayedCountInterface
|
||||
{
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getDelayedCount();
|
||||
}
|
||||
21
vendor/yiisoft/yii2-queue/src/interfaces/DoneCountInterface.php
vendored
Normal file
21
vendor/yiisoft/yii2-queue/src/interfaces/DoneCountInterface.php
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
<?php
|
||||
/**
|
||||
* @link https://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license https://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\queue\interfaces;
|
||||
|
||||
/**
|
||||
* Done Count Interface
|
||||
*
|
||||
* @author Kalmer Kaurson <kalmerkaurson@gmail.com>
|
||||
*/
|
||||
interface DoneCountInterface
|
||||
{
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getDoneCount();
|
||||
}
|
||||
21
vendor/yiisoft/yii2-queue/src/interfaces/ReservedCountInterface.php
vendored
Normal file
21
vendor/yiisoft/yii2-queue/src/interfaces/ReservedCountInterface.php
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
<?php
|
||||
/**
|
||||
* @link https://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license https://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\queue\interfaces;
|
||||
|
||||
/**
|
||||
* Reserved Count Interface
|
||||
*
|
||||
* @author Kalmer Kaurson <kalmerkaurson@gmail.com>
|
||||
*/
|
||||
interface ReservedCountInterface
|
||||
{
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getReservedCount();
|
||||
}
|
||||
21
vendor/yiisoft/yii2-queue/src/interfaces/StatisticsProviderInterface.php
vendored
Normal file
21
vendor/yiisoft/yii2-queue/src/interfaces/StatisticsProviderInterface.php
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
<?php
|
||||
/**
|
||||
* @link https://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license https://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\queue\interfaces;
|
||||
|
||||
/**
|
||||
* Statistics Provider Interface
|
||||
*
|
||||
* @author Kalmer Kaurson <kalmerkaurson@gmail.com>
|
||||
*/
|
||||
interface StatisticsProviderInterface
|
||||
{
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getStatisticsProvider();
|
||||
}
|
||||
21
vendor/yiisoft/yii2-queue/src/interfaces/WaitingCountInterface.php
vendored
Normal file
21
vendor/yiisoft/yii2-queue/src/interfaces/WaitingCountInterface.php
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
<?php
|
||||
/**
|
||||
* @link https://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license https://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\queue\interfaces;
|
||||
|
||||
/**
|
||||
* Waiting Count Interface
|
||||
*
|
||||
* @author Kalmer Kaurson <kalmerkaurson@gmail.com>
|
||||
*/
|
||||
interface WaitingCountInterface
|
||||
{
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getWaitingCount();
|
||||
}
|
||||
37
vendor/yiisoft/yii2-queue/src/serializers/IgbinarySerializer.php
vendored
Normal file
37
vendor/yiisoft/yii2-queue/src/serializers/IgbinarySerializer.php
vendored
Normal file
@ -0,0 +1,37 @@
|
||||
<?php
|
||||
/**
|
||||
* @link https://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license https://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\queue\serializers;
|
||||
|
||||
use yii\base\BaseObject;
|
||||
|
||||
/**
|
||||
* Igbinary Serializer.
|
||||
*
|
||||
* It uses an alternative serializer available via PECL extension which produces
|
||||
* more compact data chunks significantly faster that native PHP one.
|
||||
*
|
||||
* @author xutl <xutongle@gmail.com>
|
||||
*/
|
||||
class IgbinarySerializer extends BaseObject implements SerializerInterface
|
||||
{
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function serialize($job)
|
||||
{
|
||||
return igbinary_serialize($job);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function unserialize($serialized)
|
||||
{
|
||||
return igbinary_unserialize($serialized);
|
||||
}
|
||||
}
|
||||
109
vendor/yiisoft/yii2-queue/src/serializers/JsonSerializer.php
vendored
Normal file
109
vendor/yiisoft/yii2-queue/src/serializers/JsonSerializer.php
vendored
Normal file
@ -0,0 +1,109 @@
|
||||
<?php
|
||||
/**
|
||||
* @link https://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license https://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\queue\serializers;
|
||||
|
||||
use Yii;
|
||||
use yii\base\BaseObject;
|
||||
use yii\base\InvalidConfigException;
|
||||
use yii\helpers\Json;
|
||||
|
||||
/**
|
||||
* Json Serializer.
|
||||
*
|
||||
* @author Roman Zhuravlev <zhuravljov@gmail.com>
|
||||
*/
|
||||
class JsonSerializer extends BaseObject implements SerializerInterface
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $classKey = 'class';
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
public $options = 0;
|
||||
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function serialize($job)
|
||||
{
|
||||
return Json::encode($this->toArray($job), $this->options);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function unserialize($serialized)
|
||||
{
|
||||
return $this->fromArray(Json::decode($serialized));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $data
|
||||
* @return array|mixed
|
||||
* @throws InvalidConfigException
|
||||
*/
|
||||
protected function toArray($data)
|
||||
{
|
||||
if (is_object($data)) {
|
||||
$result = [$this->classKey => get_class($data)];
|
||||
foreach (get_object_vars($data) as $property => $value) {
|
||||
if ($property === $this->classKey) {
|
||||
throw new InvalidConfigException("Object cannot contain $this->classKey property.");
|
||||
}
|
||||
$result[$property] = $this->toArray($value);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
if (is_array($data)) {
|
||||
$result = [];
|
||||
foreach ($data as $key => $value) {
|
||||
if ($key === $this->classKey) {
|
||||
throw new InvalidConfigException("Array cannot contain $this->classKey key.");
|
||||
}
|
||||
$result[$key] = $this->toArray($value);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $data
|
||||
* @return mixed
|
||||
*/
|
||||
protected function fromArray($data)
|
||||
{
|
||||
if (!is_array($data)) {
|
||||
return $data;
|
||||
}
|
||||
|
||||
if (!isset($data[$this->classKey])) {
|
||||
$result = [];
|
||||
foreach ($data as $key => $value) {
|
||||
$result[$key] = $this->fromArray($value);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
$config = ['class' => $data[$this->classKey]];
|
||||
unset($data[$this->classKey]);
|
||||
foreach ($data as $property => $value) {
|
||||
$config[$property] = $this->fromArray($value);
|
||||
}
|
||||
|
||||
return Yii::createObject($config);
|
||||
}
|
||||
}
|
||||
34
vendor/yiisoft/yii2-queue/src/serializers/PhpSerializer.php
vendored
Normal file
34
vendor/yiisoft/yii2-queue/src/serializers/PhpSerializer.php
vendored
Normal file
@ -0,0 +1,34 @@
|
||||
<?php
|
||||
/**
|
||||
* @link https://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license https://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\queue\serializers;
|
||||
|
||||
use yii\base\BaseObject;
|
||||
|
||||
/**
|
||||
* Php Serializer.
|
||||
*
|
||||
* @author Roman Zhuravlev <zhuravljov@gmail.com>
|
||||
*/
|
||||
class PhpSerializer extends BaseObject implements SerializerInterface
|
||||
{
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function serialize($job)
|
||||
{
|
||||
return serialize($job);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function unserialize($serialized)
|
||||
{
|
||||
return unserialize($serialized);
|
||||
}
|
||||
}
|
||||
19
vendor/yiisoft/yii2-queue/src/serializers/Serializer.php
vendored
Normal file
19
vendor/yiisoft/yii2-queue/src/serializers/Serializer.php
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
<?php
|
||||
/**
|
||||
* @link https://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license https://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\queue\serializers;
|
||||
|
||||
/**
|
||||
* Interface Serializer.
|
||||
*
|
||||
* @deprecated Will be removed in 3.0. Use SerializerInterface instead of Serializer.
|
||||
*
|
||||
* @author Roman Zhuravlev <zhuravljov@gmail.com>
|
||||
*/
|
||||
interface Serializer extends SerializerInterface
|
||||
{
|
||||
}
|
||||
30
vendor/yiisoft/yii2-queue/src/serializers/SerializerInterface.php
vendored
Normal file
30
vendor/yiisoft/yii2-queue/src/serializers/SerializerInterface.php
vendored
Normal file
@ -0,0 +1,30 @@
|
||||
<?php
|
||||
/**
|
||||
* @link https://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license https://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace yii\queue\serializers;
|
||||
|
||||
use yii\queue\JobInterface;
|
||||
|
||||
/**
|
||||
* Serializer Interface.
|
||||
*
|
||||
* @author Roman Zhuravlev <zhuravljov@gmail.com>
|
||||
*/
|
||||
interface SerializerInterface
|
||||
{
|
||||
/**
|
||||
* @param JobInterface|mixed $job
|
||||
* @return string
|
||||
*/
|
||||
public function serialize($job);
|
||||
|
||||
/**
|
||||
* @param string $serialized
|
||||
* @return JobInterface
|
||||
*/
|
||||
public function unserialize($serialized);
|
||||
}
|
||||
Reference in New Issue
Block a user