From 7bc55116d2683586a37979f386134beb1ef94772 Mon Sep 17 00:00:00 2001 From: Moiseenko Date: Fri, 22 Sep 2023 17:41:52 +0400 Subject: [PATCH 01/48] First implementation --- .github/workflows/main.yml | 2 +- Makefile | 2 +- composer.json | 26 ++++----------- tests/TestCase.php | 2 +- tests/closure/ClosureTest.php | 10 +++++- tests/docker-compose.yml | 6 ++-- tests/docker/php/Dockerfile | 35 ++++++++++++++++++++ tests/docker/php/entrypoint.sh | 12 ------- tests/drivers/CliTestCase.php | 2 +- tests/drivers/TestCase.php | 2 +- tests/drivers/amqp_interop/QueueTest.php | 2 +- tests/drivers/db/TestCase.php | 2 +- tests/drivers/file/QueueTest.php | 2 +- tests/drivers/gearman/QueueTest.php | 2 +- tests/drivers/redis/QueueTest.php | 2 +- tests/drivers/sqs/FifoQueueTest.php | 2 +- tests/drivers/sqs/QueueTest.php | 2 +- tests/drivers/stomp/QueueTest.php | 2 +- tests/serializers/IgbinarySerializerTest.php | 2 +- 19 files changed, 69 insertions(+), 48 deletions(-) create mode 100644 tests/docker/php/Dockerfile diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index ffa601f0aa..9fa20c41e8 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -20,7 +20,7 @@ jobs: strategy: fail-fast: false matrix: - php: [ '5.6', '7.0', '7.1', '7.2', '7.3', '7.4', '8.0' ] + php: [ '8.1' ] steps: - name: Checkout uses: actions/checkout@v2 diff --git a/Makefile b/Makefile index ba996b739d..67079a8df3 100644 --- a/Makefile +++ b/Makefile @@ -7,7 +7,7 @@ build: ## Build an image from a docker-compose file. Params: {{ v=5.6 }}. Defa test: ## Run tests. Params: {{ v=5.6 }}. Default latest PHP 5.6 PHP_VERSION=$(filter-out $@,$(v)) docker-compose build --pull yii2-queue-php - PHP_VERSION=$(filter-out $@,$(v)) docker-compose run yii2-queue-php vendor/bin/phpunit --colors=always -v --debug + PHP_VERSION=$(filter-out $@,$(v)) docker-compose run yii2-queue-php vendor/bin/phpunit --colors=always make down down: ## Stop and remove containers, networks diff --git a/composer.json b/composer.json index 200893e77a..d870a85ef5 100644 --- a/composer.json +++ b/composer.json @@ -22,16 +22,15 @@ }, "require-dev": { "yiisoft/yii2-redis": "~2.0.0", - "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": "*", + "php-amqplib/php-amqplib": "^3.0.0", + "enqueue/amqp-lib": "^0.10.0", + "pda/pheanstalk": "3.2.1", + "opis/closure": "^3.6.0", "yiisoft/yii2-debug": "~2.1.0", "yiisoft/yii2-gii": "~2.2.0", - "phpunit/phpunit": "4.8.34", + "phpunit/phpunit": "^10.3.0", "aws/aws-sdk-php": ">=2.4", - "enqueue/stomp": "^0.8.39||^0.10.0", - "cweagans/composer-patches": "^1.7" + "enqueue/stomp": "^0.10.0" }, "suggest": { "ext-pcntl": "Need for process signals.", @@ -65,23 +64,12 @@ }, "config": { "allow-plugins": { - "yiisoft/yii2-composer": true, - "cweagans/composer-patches": true + "yiisoft/yii2-composer": 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": [ diff --git a/tests/TestCase.php b/tests/TestCase.php index acd2c1101b..6673faaf0c 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -12,6 +12,6 @@ * * @author Roman Zhuravlev */ -abstract class TestCase extends \PHPUnit_Framework_TestCase +abstract class TestCase extends \PHPUnit\Framework\TestCase { } diff --git a/tests/closure/ClosureTest.php b/tests/closure/ClosureTest.php index 3ff41ef3ca..a31301ac9d 100644 --- a/tests/closure/ClosureTest.php +++ b/tests/closure/ClosureTest.php @@ -21,6 +21,8 @@ class ClosureTest extends TestCase { public function testPush1() { + $this->markTestSkipped('Closure tests are disabled'); + $this->getQueue()->push(function () { $fileName = Yii::getAlias('@runtime/job-1.lock'); file_put_contents($fileName, ''); @@ -31,6 +33,8 @@ public function testPush1() public function testPush2() { + $this->markTestSkipped('Closure tests are disabled'); + $fileName = Yii::getAlias('@runtime/job-2.lock'); $this->getQueue()->push(function () use ($fileName) { file_put_contents($fileName, ''); @@ -41,6 +45,8 @@ public function testPush2() public function testPush3() { + $this->markTestSkipped('Closuretests are disabled'); + $job = new ClosureJob([ 'closure' => function () { $fileName = Yii::getAlias('@runtime/job-3.lock'); @@ -54,6 +60,8 @@ public function testPush3() public function testPush4() { + $this->markTestSkipped('Closure tests are disabled'); + $fileName = Yii::getAlias('@runtime/job-4.lock'); $job = new ClosureJob([ 'closure' => function () use ($fileName) { @@ -84,7 +92,7 @@ protected function getQueue() /** * @inheritdoc */ - protected function tearDown() + protected function tearDown(): void { foreach (glob(Yii::getAlias("@runtime/job-*.lock")) as $fileName) { unlink($fileName); diff --git a/tests/docker-compose.yml b/tests/docker-compose.yml index 2b7000c6ab..fe7da1d5c3 100644 --- a/tests/docker-compose.yml +++ b/tests/docker-compose.yml @@ -5,8 +5,10 @@ services: yii2-queue-php: container_name: yii2-queue-php build: - context: .. - dockerfile: tests/docker/php/${PHP_VERSION:-5.6}/Dockerfile + context: .. + dockerfile: tests/docker/php/Dockerfile + args: + PHP_VERSION: ${PHP_VERSION:-8.1} volumes: - ./runtime/.composer:/root/.composer - ..:/code diff --git a/tests/docker/php/Dockerfile b/tests/docker/php/Dockerfile new file mode 100644 index 0000000000..973f28667c --- /dev/null +++ b/tests/docker/php/Dockerfile @@ -0,0 +1,35 @@ +ARG PHP_VERSION + +FROM --platform=linux/amd64 php:${PHP_VERSION}-cli-alpine + +RUN echo https://dl-cdn.alpinelinux.org/alpine/edge/main >> /etc/apk/repositories \ + && echo https://dl-cdn.alpinelinux.org/alpine/edge/community >> /etc/apk/repositories \ + && echo https://dl-cdn.alpinelinux.org/alpine/edge/testing >> /etc/apk/repositories \ + && apk update + +RUN apk add git icu-dev libpq-dev gearman-dev libcrypto3 openssl-dev autoconf g++ make linux-headers + +RUN docker-php-ext-install pcntl bcmath pdo_mysql intl pdo_pgsql sockets +RUN pecl install igbinary +RUN docker-php-ext-enable igbinary + +# Official gearman package not supported PHP 8.1 now +RUN TMPDIR=$(mktemp -d) \ + && cd $TMPDIR \ + && git clone https://github.com/php/pecl-networking-gearman gearman \ + && cd ./gearman \ + && phpize \ + && ./configure \ + && make -j$(nproc) \ + && make install \ + && cd - \ + && rm -r $TMPDIR \ + && docker-php-ext-enable gearman + +COPY --from=composer:latest /usr/bin/composer /usr/local/bin/composer + +COPY . /code +WORKDIR /code + +ENTRYPOINT ["tests/docker/php/entrypoint.sh"] +CMD ["sleep", "infinity"] diff --git a/tests/docker/php/entrypoint.sh b/tests/docker/php/entrypoint.sh index 641ee5b4d9..b97e9934f9 100755 --- a/tests/docker/php/entrypoint.sh +++ b/tests/docker/php/entrypoint.sh @@ -6,22 +6,10 @@ flock tests/runtime/composer-install.lock composer install --prefer-dist --no-in tests/yii sqlite-migrate/up --interactive=0 -tests/docker/wait-for-it.sh mysql:3306 -t 180 tests/docker/php/mysql-lock.php tests/yii mysql-migrate/up --interactive=0 -tests/docker/wait-for-it.sh postgres:5432 -t 180 tests/docker/php/mysql-lock.php tests/yii pgsql-migrate/up --interactive=0 -tests/docker/wait-for-it.sh redis:6379 -t 180 - -tests/docker/wait-for-it.sh rabbitmq:5672 -t 180 - -tests/docker/wait-for-it.sh beanstalk:11300 -t 180 - -tests/docker/wait-for-it.sh gearmand:4730 -t 180 - -tests/docker/wait-for-it.sh activemq:61613 -t 180 - php --version set -x exec "$@" diff --git a/tests/drivers/CliTestCase.php b/tests/drivers/CliTestCase.php index 40870565d5..5d79a43992 100644 --- a/tests/drivers/CliTestCase.php +++ b/tests/drivers/CliTestCase.php @@ -84,7 +84,7 @@ static function (&$v) use ($replace) { /** * @inheritdoc */ - protected function tearDown() + protected function tearDown(): void { if (file_exists(PriorityJob::getFileName())) { unlink(PriorityJob::getFileName()); diff --git a/tests/drivers/TestCase.php b/tests/drivers/TestCase.php index 4d19592d4f..deec755bf3 100644 --- a/tests/drivers/TestCase.php +++ b/tests/drivers/TestCase.php @@ -68,7 +68,7 @@ protected function assertSimpleJobLaterDone(SimpleJob $job, $delay) /** * @inheritdoc */ - protected function tearDown() + protected function tearDown(): void { // Removes temp job files foreach (glob(Yii::getAlias("@runtime/job-*.lock")) as $fileName) { diff --git a/tests/drivers/amqp_interop/QueueTest.php b/tests/drivers/amqp_interop/QueueTest.php index 6f5d3f4f33..87ec023af0 100644 --- a/tests/drivers/amqp_interop/QueueTest.php +++ b/tests/drivers/amqp_interop/QueueTest.php @@ -183,7 +183,7 @@ protected function getQueue() return Yii::$app->amqpInteropQueue; } - protected function setUp() + protected function setUp(): void { if ('true' == getenv('EXCLUDE_AMQP_INTEROP')) { $this->markTestSkipped('Amqp tests are disabled for php 5.5'); diff --git a/tests/drivers/db/TestCase.php b/tests/drivers/db/TestCase.php index bc57ca7529..742efbbcc0 100644 --- a/tests/drivers/db/TestCase.php +++ b/tests/drivers/db/TestCase.php @@ -105,7 +105,7 @@ public function testRemove() $this->assertEquals(0, $actual); } - protected function tearDown() + protected function tearDown(): void { $this->getQueue()->db->createCommand() ->delete($this->getQueue()->tableName) diff --git a/tests/drivers/file/QueueTest.php b/tests/drivers/file/QueueTest.php index 1faea8006f..0eb28d42b9 100644 --- a/tests/drivers/file/QueueTest.php +++ b/tests/drivers/file/QueueTest.php @@ -95,7 +95,7 @@ protected function getQueue() return Yii::$app->fileQueue; } - protected function tearDown() + protected function tearDown(): void { foreach (glob(Yii::getAlias("@runtime/queue/*")) as $fileName) { unlink($fileName); diff --git a/tests/drivers/gearman/QueueTest.php b/tests/drivers/gearman/QueueTest.php index a68c42ed11..d4d5bd8bc6 100644 --- a/tests/drivers/gearman/QueueTest.php +++ b/tests/drivers/gearman/QueueTest.php @@ -69,7 +69,7 @@ protected function getQueue() return Yii::$app->gearmanQueue; } - public function setUp() + public function setUp(): void { if (!defined('GEARMAN_SUCCESS')) { $this->markTestSkipped('Gearman in not installed.'); diff --git a/tests/drivers/redis/QueueTest.php b/tests/drivers/redis/QueueTest.php index 8e6c462e9d..bb600a592d 100644 --- a/tests/drivers/redis/QueueTest.php +++ b/tests/drivers/redis/QueueTest.php @@ -95,7 +95,7 @@ protected function getQueue() return Yii::$app->redisQueue; } - protected function tearDown() + protected function tearDown(): void { $this->getQueue()->redis->flushdb(); parent::tearDown(); diff --git a/tests/drivers/sqs/FifoQueueTest.php b/tests/drivers/sqs/FifoQueueTest.php index 4cc4b8b556..ae58b517af 100644 --- a/tests/drivers/sqs/FifoQueueTest.php +++ b/tests/drivers/sqs/FifoQueueTest.php @@ -73,7 +73,7 @@ protected function getQueue() return Yii::$app->sqsFifoQueue; } - protected function setUp() + protected function setUp(): void { if (!getenv('AWS_SQS_FIFO_ENABLED')) { $this->markTestSkipped('AWS SQS FIFO tests are disabled'); diff --git a/tests/drivers/sqs/QueueTest.php b/tests/drivers/sqs/QueueTest.php index 8ef1e518ad..4de7f135de 100644 --- a/tests/drivers/sqs/QueueTest.php +++ b/tests/drivers/sqs/QueueTest.php @@ -75,7 +75,7 @@ protected function getQueue() return Yii::$app->sqsQueue; } - protected function setUp() + protected function setUp(): void { if (!getenv('AWS_SQS_ENABLED')) { $this->markTestSkipped('AWS SQS tests are disabled'); diff --git a/tests/drivers/stomp/QueueTest.php b/tests/drivers/stomp/QueueTest.php index c3aeb72762..f5bec5f823 100644 --- a/tests/drivers/stomp/QueueTest.php +++ b/tests/drivers/stomp/QueueTest.php @@ -44,7 +44,7 @@ protected function getQueue() } - protected function setUp() + protected function setUp(): void { if ('true' == getenv('EXCLUDE_STOMP')) { $this->markTestSkipped('Stomp tests are disabled for php 5.5'); diff --git a/tests/serializers/IgbinarySerializerTest.php b/tests/serializers/IgbinarySerializerTest.php index 8d851e12e5..f1e31c1f51 100644 --- a/tests/serializers/IgbinarySerializerTest.php +++ b/tests/serializers/IgbinarySerializerTest.php @@ -21,7 +21,7 @@ protected function createSerializer() return new IgbinarySerializer(); } - protected function setUp() + protected function setUp(): void { if (!extension_loaded('igbinary')) { $this->markTestSkipped('Igbinary extension is not loaded.'); From 8efd635e58bbf8d1788c947ac5b85d1cb46aa397 Mon Sep 17 00:00:00 2001 From: Moiseenko Date: Fri, 22 Sep 2023 18:47:06 +0400 Subject: [PATCH 02/48] Migrate phpunit config --- phpunit.xml.dist | 30 ++++++++++++++++-------------- tests/docker/php/entrypoint.sh | 4 ++-- 2 files changed, 18 insertions(+), 16 deletions(-) diff --git a/phpunit.xml.dist b/phpunit.xml.dist index d40b0c8eda..6b1875ea25 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -1,16 +1,18 @@ - - - - ./tests - ./tests/app - ./tests/docker - ./tests/runtime - - + + + + ./tests + ./tests/app + ./tests/docker + ./tests/runtime + + diff --git a/tests/docker/php/entrypoint.sh b/tests/docker/php/entrypoint.sh index b97e9934f9..7c7df3ce62 100755 --- a/tests/docker/php/entrypoint.sh +++ b/tests/docker/php/entrypoint.sh @@ -5,9 +5,9 @@ set -eu flock tests/runtime/composer-install.lock composer install --prefer-dist --no-interaction tests/yii sqlite-migrate/up --interactive=0 - +sleep 60 tests/docker/php/mysql-lock.php tests/yii mysql-migrate/up --interactive=0 - +sleep 60 tests/docker/php/mysql-lock.php tests/yii pgsql-migrate/up --interactive=0 php --version From c571f81daa5c03c81f89b10aaf5f735562514109 Mon Sep 17 00:00:00 2001 From: Moiseenko Date: Fri, 22 Sep 2023 19:13:15 +0400 Subject: [PATCH 03/48] Added return type hints and fixed unsupported phpunit methods --- tests/JobEventTest.php | 4 ++-- tests/closure/ClosureTest.php | 10 +++++----- tests/drivers/CliTestCase.php | 2 +- tests/drivers/TestCase.php | 8 ++++---- tests/drivers/amqp/QueueTest.php | 4 ++-- tests/drivers/amqp_interop/QueueTest.php | 18 +++++++++--------- tests/drivers/beanstalk/QueueTest.php | 16 ++++++++-------- tests/drivers/db/MysqlQueueTest.php | 2 +- tests/drivers/db/PgsqlQueueTest.php | 2 +- tests/drivers/db/SqliteQueueTest.php | 2 +- tests/drivers/db/TestCase.php | 16 ++++++++-------- tests/drivers/file/QueueTest.php | 18 +++++++++--------- tests/drivers/gearman/QueueTest.php | 10 +++++----- tests/drivers/redis/QueueTest.php | 16 ++++++++-------- tests/drivers/sqs/FifoQueueTest.php | 12 ++++++------ tests/drivers/sqs/QueueTest.php | 12 ++++++------ tests/drivers/stomp/QueueTest.php | 6 +++--- tests/drivers/sync/QueueTest.php | 6 +++--- tests/serializers/IgbinarySerializerTest.php | 2 +- tests/serializers/JsonSerializerTest.php | 9 ++++----- tests/serializers/PhpSerializerTest.php | 2 +- tests/serializers/TestCase.php | 6 +++--- 22 files changed, 91 insertions(+), 92 deletions(-) diff --git a/tests/JobEventTest.php b/tests/JobEventTest.php index 4cf46a7c92..574c2334b4 100644 --- a/tests/JobEventTest.php +++ b/tests/JobEventTest.php @@ -21,7 +21,7 @@ */ class JobEventTest extends TestCase { - public function testInvalidJob() + public function testInvalidJob(): void { $eventCounter = []; $eventHandler = function (JobEvent $event) use (&$eventCounter) { @@ -41,7 +41,7 @@ public function testInvalidJob() $this->assertArrayHasKey(Queue::EVENT_AFTER_ERROR, $eventCounter[$jobId]); } - public function testExecResult() + public function testExecResult(): void { $queue = new SyncQueue(['as closure' => ClosureBehavior::class]); $isTriggered = false; diff --git a/tests/closure/ClosureTest.php b/tests/closure/ClosureTest.php index a31301ac9d..6912fa33fb 100644 --- a/tests/closure/ClosureTest.php +++ b/tests/closure/ClosureTest.php @@ -19,7 +19,7 @@ */ class ClosureTest extends TestCase { - public function testPush1() + public function testPush1(): void { $this->markTestSkipped('Closure tests are disabled'); @@ -31,7 +31,7 @@ public function testPush1() $this->assertFileExists(Yii::getAlias('@runtime/job-1.lock')); } - public function testPush2() + public function testPush2(): void { $this->markTestSkipped('Closure tests are disabled'); @@ -43,7 +43,7 @@ public function testPush2() $this->assertFileExists($fileName); } - public function testPush3() + public function testPush3(): void { $this->markTestSkipped('Closuretests are disabled'); @@ -58,7 +58,7 @@ public function testPush3() $this->assertFileExists(Yii::getAlias('@runtime/job-3.lock')); } - public function testPush4() + public function testPush4(): void { $this->markTestSkipped('Closure tests are disabled'); @@ -76,7 +76,7 @@ public function testPush4() /** * @return Queue */ - protected function getQueue() + protected function getQueue(): Queue { if (!$this->_queue) { $this->_queue = new Queue([ diff --git a/tests/drivers/CliTestCase.php b/tests/drivers/CliTestCase.php index 5d79a43992..d821f25b30 100644 --- a/tests/drivers/CliTestCase.php +++ b/tests/drivers/CliTestCase.php @@ -26,7 +26,7 @@ abstract class CliTestCase extends TestCase /** * @param array $cmd */ - protected function runProcess($cmd) + protected function runProcess($cmd): void { $cmd = $this->prepareCmd($cmd); $process = new Process($cmd); diff --git a/tests/drivers/TestCase.php b/tests/drivers/TestCase.php index deec755bf3..cf68d175bd 100644 --- a/tests/drivers/TestCase.php +++ b/tests/drivers/TestCase.php @@ -21,12 +21,12 @@ abstract class TestCase extends \tests\TestCase /** * @return Queue */ - abstract protected function getQueue(); + abstract protected function getQueue(): Queue; /** * @return SimpleJob */ - protected function createSimpleJob() + protected function createSimpleJob(): SimpleJob { return new SimpleJob([ 'uid' => uniqid(), @@ -36,7 +36,7 @@ protected function createSimpleJob() /** * @param SimpleJob $job */ - protected function assertSimpleJobDone(SimpleJob $job) + protected function assertSimpleJobDone(SimpleJob $job): void { $timeout = 5000000; // 5 sec $step = 50000; @@ -51,7 +51,7 @@ protected function assertSimpleJobDone(SimpleJob $job) * @param SimpleJob $job * @param int $delay */ - protected function assertSimpleJobLaterDone(SimpleJob $job, $delay) + protected function assertSimpleJobLaterDone(SimpleJob $job, $delay): void { $time = time() + $delay; sleep($delay); diff --git a/tests/drivers/amqp/QueueTest.php b/tests/drivers/amqp/QueueTest.php index f363d45472..81c32aca63 100644 --- a/tests/drivers/amqp/QueueTest.php +++ b/tests/drivers/amqp/QueueTest.php @@ -21,12 +21,12 @@ class QueueTest extends CliTestCase /** * @return Queue */ - protected function getQueue() + protected function getQueue(): Queue { return Yii::$app->amqpQueue; } - public function testListen() + public function testListen(): void { $this->startProcess(['php', 'yii', 'queue/listen']); $job = $this->createSimpleJob(); diff --git a/tests/drivers/amqp_interop/QueueTest.php b/tests/drivers/amqp_interop/QueueTest.php index 87ec023af0..42b97fd35b 100644 --- a/tests/drivers/amqp_interop/QueueTest.php +++ b/tests/drivers/amqp_interop/QueueTest.php @@ -29,7 +29,7 @@ class QueueTest extends CliTestCase /** * Test working setter routing key */ - public function testNativeSettingRoutingKey() + public function testNativeSettingRoutingKey(): void { $uniqRoutingKey = Yii::$app->security->generateRandomString(12); $message = new InteropAmqpMessage(); @@ -41,7 +41,7 @@ public function testNativeSettingRoutingKey() /** * Sending a message to a queue using RoutingKey */ - public function testSendMessageWithRoutingKey() + public function testSendMessageWithRoutingKey(): void { $uniqKey = Yii::$app->security->generateRandomString(12); $receivedRoutingKey = null; @@ -71,7 +71,7 @@ public function testSendMessageWithRoutingKey() * Test push message with headers * @return void */ - public function testPushMessageWithHeaders() + public function testPushMessageWithHeaders(): void { $actualHeaders = []; $messageHeaders = [ @@ -111,7 +111,7 @@ public function testPushMessageWithHeaders() $this->assertEquals($expectedHeaders, $actualHeaders); } - public function testListen() + public function testListen(): void { $this->startProcess(['php', 'yii', 'queue/listen']); $job = $this->createSimpleJob(); @@ -120,7 +120,7 @@ public function testListen() $this->assertSimpleJobDone($job); } - public function testLater() + public function testLater(): void { $this->startProcess(['php', 'yii', 'queue/listen']); $job = $this->createSimpleJob(); @@ -129,7 +129,7 @@ public function testLater() $this->assertSimpleJobLaterDone($job, 2); } - public function testRetry() + public function testRetry(): void { $this->startProcess(['php', 'yii', 'queue/listen']); $job = new RetryJob(['uid' => uniqid()]); @@ -140,7 +140,7 @@ public function testRetry() $this->assertEquals('aa', file_get_contents($job->getFileName())); } - public function testPriority() + public function testPriority(): void { $this->getQueue()->priority(3)->push(new PriorityJob(['number' => 1])); $this->getQueue()->priority(1)->push(new PriorityJob(['number' => 5])); @@ -156,7 +156,7 @@ public function testPriority() /** * @requires extension pcntl */ - public function testSignals() + public function testSignals(): void { $signals = [ 1 => 129, // SIGHUP @@ -178,7 +178,7 @@ public function testSignals() /** * @return Queue */ - protected function getQueue() + protected function getQueue(): Queue { return Yii::$app->amqpInteropQueue; } diff --git a/tests/drivers/beanstalk/QueueTest.php b/tests/drivers/beanstalk/QueueTest.php index a78283ac4d..0b61d401d2 100644 --- a/tests/drivers/beanstalk/QueueTest.php +++ b/tests/drivers/beanstalk/QueueTest.php @@ -22,7 +22,7 @@ */ class QueueTest extends CliTestCase { - public function testRun() + public function testRun(): void { $job = $this->createSimpleJob(); $this->getQueue()->push($job); @@ -31,7 +31,7 @@ public function testRun() $this->assertSimpleJobDone($job); } - public function testStatus() + public function testStatus(): void { $job = $this->createSimpleJob(); $id = $this->getQueue()->push($job); @@ -43,7 +43,7 @@ public function testStatus() $this->assertTrue($isDone); } - public function testPriority() + public function testPriority(): void { $this->getQueue()->priority(100)->push(new PriorityJob(['number' => 1])); $this->getQueue()->priority(300)->push(new PriorityJob(['number' => 5])); @@ -55,7 +55,7 @@ public function testPriority() $this->assertEquals('12345', file_get_contents(PriorityJob::getFileName())); } - public function testListen() + public function testListen(): void { $this->startProcess(['php', 'yii', 'queue/listen', '1']); $job = $this->createSimpleJob(); @@ -64,7 +64,7 @@ public function testListen() $this->assertSimpleJobDone($job); } - public function testLater() + public function testLater(): void { $this->startProcess(['php', 'yii', 'queue/listen', '1']); $job = $this->createSimpleJob(); @@ -73,7 +73,7 @@ public function testLater() $this->assertSimpleJobLaterDone($job, 2); } - public function testRetry() + public function testRetry(): void { $this->startProcess(['php', 'yii', 'queue/listen', '1']); $job = new RetryJob(['uid' => uniqid()]); @@ -84,7 +84,7 @@ public function testRetry() $this->assertEquals('aa', file_get_contents($job->getFileName())); } - public function testRemove() + public function testRemove(): void { $id = $this->getQueue()->push($this->createSimpleJob()); $this->assertTrue($this->jobIsExists($id)); @@ -96,7 +96,7 @@ public function testRemove() /** * @return Queue */ - protected function getQueue() + protected function getQueue(): Queue { return Yii::$app->beanstalkQueue; } diff --git a/tests/drivers/db/MysqlQueueTest.php b/tests/drivers/db/MysqlQueueTest.php index 05e8702aca..f14049cfc0 100644 --- a/tests/drivers/db/MysqlQueueTest.php +++ b/tests/drivers/db/MysqlQueueTest.php @@ -20,7 +20,7 @@ class MysqlQueueTest extends TestCase /** * @return Queue */ - protected function getQueue() + protected function getQueue(): Queue { return Yii::$app->mysqlQueue; } diff --git a/tests/drivers/db/PgsqlQueueTest.php b/tests/drivers/db/PgsqlQueueTest.php index 3910d21694..65e6a5932a 100644 --- a/tests/drivers/db/PgsqlQueueTest.php +++ b/tests/drivers/db/PgsqlQueueTest.php @@ -20,7 +20,7 @@ class PgsqlQueueTest extends TestCase /** * @return Queue */ - protected function getQueue() + protected function getQueue(): Queue { return Yii::$app->pgsqlQueue; } diff --git a/tests/drivers/db/SqliteQueueTest.php b/tests/drivers/db/SqliteQueueTest.php index 762a9c3eda..db887c603c 100644 --- a/tests/drivers/db/SqliteQueueTest.php +++ b/tests/drivers/db/SqliteQueueTest.php @@ -20,7 +20,7 @@ class SqliteQueueTest extends TestCase /** * @return Queue */ - protected function getQueue() + protected function getQueue(): Queue { return Yii::$app->sqliteQueue; } diff --git a/tests/drivers/db/TestCase.php b/tests/drivers/db/TestCase.php index 742efbbcc0..d7064ea8ad 100644 --- a/tests/drivers/db/TestCase.php +++ b/tests/drivers/db/TestCase.php @@ -19,7 +19,7 @@ */ abstract class TestCase extends CliTestCase { - public function testRun() + public function testRun(): void { $job = $this->createSimpleJob(); $this->getQueue()->push($job); @@ -28,7 +28,7 @@ public function testRun() $this->assertSimpleJobDone($job); } - public function testStatus() + public function testStatus(): void { $job = $this->createSimpleJob(); $id = $this->getQueue()->push($job); @@ -40,7 +40,7 @@ public function testStatus() $this->assertTrue($isDone); } - public function testPriority() + public function testPriority(): void { $this->getQueue()->priority(100)->push(new PriorityJob(['number' => 1])); $this->getQueue()->priority(300)->push(new PriorityJob(['number' => 5])); @@ -52,7 +52,7 @@ public function testPriority() $this->assertEquals('12345', file_get_contents(PriorityJob::getFileName())); } - public function testListen() + public function testListen(): void { $this->startProcess(['php', 'yii', 'queue/listen', '1']); $job = $this->createSimpleJob(); @@ -61,7 +61,7 @@ public function testListen() $this->assertSimpleJobDone($job); } - public function testLater() + public function testLater(): void { $this->startProcess(['php', 'yii', 'queue/listen', '1']); $job = $this->createSimpleJob(); @@ -70,7 +70,7 @@ public function testLater() $this->assertSimpleJobLaterDone($job, 2); } - public function testRetry() + public function testRetry(): void { $this->startProcess(['php', 'yii', 'queue/listen', '1']); $job = new RetryJob(['uid' => uniqid()]); @@ -81,7 +81,7 @@ public function testRetry() $this->assertEquals('aa', file_get_contents($job->getFileName())); } - public function testClear() + public function testClear(): void { $this->getQueue()->push($this->createSimpleJob()); $this->runProcess(['php', 'yii', 'queue/clear', '--interactive=0']); @@ -93,7 +93,7 @@ public function testClear() $this->assertEquals(0, $actual); } - public function testRemove() + public function testRemove(): void { $id = $this->getQueue()->push($this->createSimpleJob()); $this->runProcess(['php', 'yii', 'queue/remove', $id]); diff --git a/tests/drivers/file/QueueTest.php b/tests/drivers/file/QueueTest.php index 0eb28d42b9..1a8b3ac880 100644 --- a/tests/drivers/file/QueueTest.php +++ b/tests/drivers/file/QueueTest.php @@ -19,7 +19,7 @@ */ class QueueTest extends CliTestCase { - public function testRun() + public function testRun(): void { $job = $this->createSimpleJob(); $this->getQueue()->push($job); @@ -28,7 +28,7 @@ public function testRun() $this->assertSimpleJobDone($job); } - public function testStatus() + public function testStatus(): void { $job = $this->createSimpleJob(); $id = $this->getQueue()->push($job); @@ -40,7 +40,7 @@ public function testStatus() $this->assertTrue($isDone); } - public function testListen() + public function testListen(): void { $this->startProcess(['php', 'yii', 'queue/listen', '1']); $job = $this->createSimpleJob(); @@ -49,7 +49,7 @@ public function testListen() $this->assertSimpleJobDone($job); } - public function testLater() + public function testLater(): void { $this->startProcess(['php', 'yii', 'queue/listen', '1']); $job = $this->createSimpleJob(); @@ -58,7 +58,7 @@ public function testLater() $this->assertSimpleJobLaterDone($job, 2); } - public function testRetry() + public function testRetry(): void { $this->startProcess(['php', 'yii', 'queue/listen', '1']); $job = new RetryJob(['uid' => uniqid()]); @@ -69,7 +69,7 @@ public function testRetry() $this->assertEquals('aa', file_get_contents($job->getFileName())); } - public function testClear() + public function testClear(): void { $this->getQueue()->push($this->createSimpleJob()); $this->assertNotEmpty(glob($this->getQueue()->path . '/job*.data')); @@ -78,19 +78,19 @@ public function testClear() $this->assertEmpty(glob($this->getQueue()->path . '/job*.data')); } - public function testRemove() + public function testRemove(): void { $id = $this->getQueue()->push($this->createSimpleJob()); $this->assertFileExists($this->getQueue()->path . "/job$id.data"); $this->runProcess(['php', 'yii', 'queue/remove', $id]); - $this->assertFileNotExists($this->getQueue()->path . "/job$id.data"); + $this->assertFileDoesNotExist($this->getQueue()->path . "/job$id.data"); } /** * @return Queue */ - protected function getQueue() + protected function getQueue(): Queue { return Yii::$app->fileQueue; } diff --git a/tests/drivers/gearman/QueueTest.php b/tests/drivers/gearman/QueueTest.php index d4d5bd8bc6..4bf65ffc09 100644 --- a/tests/drivers/gearman/QueueTest.php +++ b/tests/drivers/gearman/QueueTest.php @@ -19,7 +19,7 @@ */ class QueueTest extends CliTestCase { - public function testRun() + public function testRun(): void { $job = $this->createSimpleJob(); $this->getQueue()->push($job); @@ -28,7 +28,7 @@ public function testRun() $this->assertSimpleJobDone($job); } - public function testPriority() + public function testPriority(): void { $this->getQueue()->priority('high')->push(new PriorityJob(['number' => 1])); $this->getQueue()->priority('low')->push(new PriorityJob(['number' => 5])); @@ -40,7 +40,7 @@ public function testPriority() $this->assertEquals('12345', file_get_contents(PriorityJob::getFileName())); } - public function testStatus() + public function testStatus(): void { $job = $this->createSimpleJob(); $id = $this->getQueue()->push($job); @@ -52,7 +52,7 @@ public function testStatus() $this->assertTrue($isDone); } - public function testListen() + public function testListen(): void { $this->startProcess(['php', 'yii', 'queue/listen']); $job = $this->createSimpleJob(); @@ -64,7 +64,7 @@ public function testListen() /** * @return Queue */ - protected function getQueue() + protected function getQueue(): Queue { return Yii::$app->gearmanQueue; } diff --git a/tests/drivers/redis/QueueTest.php b/tests/drivers/redis/QueueTest.php index bb600a592d..e4d74262af 100644 --- a/tests/drivers/redis/QueueTest.php +++ b/tests/drivers/redis/QueueTest.php @@ -19,7 +19,7 @@ */ class QueueTest extends CliTestCase { - public function testRun() + public function testRun(): void { $job = $this->createSimpleJob(); $this->getQueue()->push($job); @@ -28,7 +28,7 @@ public function testRun() $this->assertSimpleJobDone($job); } - public function testStatus() + public function testStatus(): void { $job = $this->createSimpleJob(); $id = $this->getQueue()->push($job); @@ -40,7 +40,7 @@ public function testStatus() $this->assertTrue($isDone); } - public function testListen() + public function testListen(): void { $this->startProcess(['php', 'yii', 'queue/listen', '1']); $job = $this->createSimpleJob(); @@ -49,7 +49,7 @@ public function testListen() $this->assertSimpleJobDone($job); } - public function testLater() + public function testLater(): void { $this->startProcess(['php', 'yii', 'queue/listen', '1']); $job = $this->createSimpleJob(); @@ -58,7 +58,7 @@ public function testLater() $this->assertSimpleJobLaterDone($job, 2); } - public function testRetry() + public function testRetry(): void { $this->startProcess(['php', 'yii', 'queue/listen', '1']); $job = new RetryJob(['uid' => uniqid()]); @@ -69,7 +69,7 @@ public function testRetry() $this->assertEquals('aa', file_get_contents($job->getFileName())); } - public function testClear() + public function testClear(): void { $this->getQueue()->push($this->createSimpleJob()); $this->assertNotEmpty($this->getQueue()->redis->keys($this->getQueue()->channel . '.*')); @@ -78,7 +78,7 @@ public function testClear() $this->assertEmpty($this->getQueue()->redis->keys($this->getQueue()->channel . '.*')); } - public function testRemove() + public function testRemove(): void { $id = $this->getQueue()->push($this->createSimpleJob()); $this->assertTrue((bool) $this->getQueue()->redis->hexists($this->getQueue()->channel . '.messages', $id)); @@ -90,7 +90,7 @@ public function testRemove() /** * @return Queue */ - protected function getQueue() + protected function getQueue(): Queue { return Yii::$app->redisQueue; } diff --git a/tests/drivers/sqs/FifoQueueTest.php b/tests/drivers/sqs/FifoQueueTest.php index ae58b517af..dfd53f4357 100644 --- a/tests/drivers/sqs/FifoQueueTest.php +++ b/tests/drivers/sqs/FifoQueueTest.php @@ -17,7 +17,7 @@ */ class FifoQueueTest extends CliTestCase { - public function testRun() + public function testRun(): void { $job = $this->createSimpleJob(); $this->getQueue()->push($job); @@ -26,7 +26,7 @@ public function testRun() $this->assertSimpleJobDone($job); } - public function testListen() + public function testListen(): void { $this->startProcess(['php', 'yii', 'queue/listen', '1']); $job = $this->createSimpleJob(); @@ -35,7 +35,7 @@ public function testListen() $this->assertSimpleJobDone($job); } - public function testFifoQueueDoesNotSupportPerMessageDelays() + public function testFifoQueueDoesNotSupportPerMessageDelays(): void { $this->startProcess(['php', 'yii', 'queue/listen', '1']); $job = $this->createSimpleJob(); @@ -44,7 +44,7 @@ public function testFifoQueueDoesNotSupportPerMessageDelays() $this->getQueue()->delay(2)->push($job); } - public function testRetry() + public function testRetry(): void { $this->startProcess(['php', 'yii', 'queue/listen', '1']); $job = new RetryJob(['uid' => uniqid()]); @@ -55,7 +55,7 @@ public function testRetry() $this->assertEquals('aa', file_get_contents($job->getFileName())); } - public function testClear() + public function testClear(): void { if (!getenv('AWS_SQS_FIFO_CLEAR_TEST_ENABLED')) { $this->markTestSkipped(__METHOD__ . ' is disabled'); @@ -68,7 +68,7 @@ public function testClear() /** * @return Queue */ - protected function getQueue() + protected function getQueue(): Queue { return Yii::$app->sqsFifoQueue; } diff --git a/tests/drivers/sqs/QueueTest.php b/tests/drivers/sqs/QueueTest.php index 4de7f135de..d461d15159 100644 --- a/tests/drivers/sqs/QueueTest.php +++ b/tests/drivers/sqs/QueueTest.php @@ -19,7 +19,7 @@ */ class QueueTest extends CliTestCase { - public function testRun() + public function testRun(): void { $job = $this->createSimpleJob(); $this->getQueue()->push($job); @@ -28,7 +28,7 @@ public function testRun() $this->assertSimpleJobDone($job); } - public function testListen() + public function testListen(): void { $this->startProcess(['php', 'yii', 'queue/listen', '1']); $job = $this->createSimpleJob(); @@ -37,7 +37,7 @@ public function testListen() $this->assertSimpleJobDone($job); } - public function testLater() + public function testLater(): void { $this->startProcess(['php', 'yii', 'queue/listen', '1']); $job = $this->createSimpleJob(); @@ -46,7 +46,7 @@ public function testLater() $this->assertSimpleJobLaterDone($job, 2); } - public function testRetry() + public function testRetry(): void { $this->startProcess(['php', 'yii', 'queue/listen', '1']); $job = new RetryJob(['uid' => uniqid()]); @@ -57,7 +57,7 @@ public function testRetry() $this->assertEquals('aa', file_get_contents($job->getFileName())); } - public function testClear() + public function testClear(): void { if (!getenv('AWS_SQS_CLEAR_TEST_ENABLED')) { $this->markTestSkipped(__METHOD__ . ' is disabled'); @@ -70,7 +70,7 @@ public function testClear() /** * @return Queue */ - protected function getQueue() + protected function getQueue(): Queue { return Yii::$app->sqsQueue; } diff --git a/tests/drivers/stomp/QueueTest.php b/tests/drivers/stomp/QueueTest.php index f5bec5f823..c060afee0c 100644 --- a/tests/drivers/stomp/QueueTest.php +++ b/tests/drivers/stomp/QueueTest.php @@ -15,7 +15,7 @@ class QueueTest extends CliTestCase { - public function testListen() + public function testListen(): void { $this->startProcess(['php', 'yii', 'queue/listen']); $job = $this->createSimpleJob(); @@ -24,7 +24,7 @@ public function testListen() $this->assertSimpleJobDone($job); } - public function testRetry() + public function testRetry(): void { $this->startProcess(['php', 'yii', 'queue/listen']); $job = new RetryJob(['uid' => uniqid()]); @@ -38,7 +38,7 @@ public function testRetry() /** * @return Queue */ - protected function getQueue() + protected function getQueue(): Queue { return Yii::$app->stompQueue; } diff --git a/tests/drivers/sync/QueueTest.php b/tests/drivers/sync/QueueTest.php index 65a86e0db0..f873d9903b 100644 --- a/tests/drivers/sync/QueueTest.php +++ b/tests/drivers/sync/QueueTest.php @@ -21,12 +21,12 @@ class QueueTest extends TestCase /** * @return Queue */ - protected function getQueue() + protected function getQueue(): Queue { return Yii::$app->syncQueue; } - public function testRun() + public function testRun(): void { $job = $this->createSimpleJob(); $this->getQueue()->push($job); @@ -35,7 +35,7 @@ public function testRun() $this->assertSimpleJobDone($job); } - public function testStatus() + public function testStatus(): void { $job = $this->createSimpleJob(); $id = $this->getQueue()->push($job); diff --git a/tests/serializers/IgbinarySerializerTest.php b/tests/serializers/IgbinarySerializerTest.php index f1e31c1f51..5dfe47dc19 100644 --- a/tests/serializers/IgbinarySerializerTest.php +++ b/tests/serializers/IgbinarySerializerTest.php @@ -16,7 +16,7 @@ */ class IgbinarySerializerTest extends TestCase { - protected function createSerializer() + protected function createSerializer(): IgbinarySerializer { return new IgbinarySerializer(); } diff --git a/tests/serializers/JsonSerializerTest.php b/tests/serializers/JsonSerializerTest.php index c93067fdd2..b53e98b31c 100644 --- a/tests/serializers/JsonSerializerTest.php +++ b/tests/serializers/JsonSerializerTest.php @@ -8,6 +8,7 @@ namespace tests\serializers; use yii\queue\serializers\JsonSerializer; +use yii\queue\serializers\SerializerInterface; /** * Json Serializer Test. @@ -19,16 +20,14 @@ class JsonSerializerTest extends TestCase /** * @inheritdoc */ - protected function createSerializer() + protected function createSerializer(): SerializerInterface { return new JsonSerializer(); } - /** - * @expectedException \yii\base\InvalidConfigException - */ - public function testInvalidArrayKey() + public function testInvalidArrayKey(): void { + $this->expectException(\yii\base\InvalidConfigException::class); $this->createSerializer()->serialize([ 'class' => 'failed param', ]); diff --git a/tests/serializers/PhpSerializerTest.php b/tests/serializers/PhpSerializerTest.php index 6e2e5cbde8..c0cdaeae93 100644 --- a/tests/serializers/PhpSerializerTest.php +++ b/tests/serializers/PhpSerializerTest.php @@ -16,7 +16,7 @@ */ class PhpSerializerTest extends TestCase { - protected function createSerializer() + protected function createSerializer(): PhpSerializer { return new PhpSerializer(); } diff --git a/tests/serializers/TestCase.php b/tests/serializers/TestCase.php index 3fc1e938b4..9fc8ea54d0 100644 --- a/tests/serializers/TestCase.php +++ b/tests/serializers/TestCase.php @@ -21,13 +21,13 @@ abstract class TestCase extends \tests\TestCase /** * @return SerializerInterface */ - abstract protected function createSerializer(); + abstract protected function createSerializer(): SerializerInterface; /** * @dataProvider providerSerialize * @param mixed $expected */ - public function testSerialize($expected) + public function testSerialize($expected): void { $serializer = $this->createSerializer(); @@ -37,7 +37,7 @@ public function testSerialize($expected) $this->assertEquals($expected, $actual, "Payload: $serialized"); } - public function providerSerialize() + public static function providerSerialize(): array { return [ // Job object From d8659d5a5aa2d9259d95b8a20c590d6a28afa0c5 Mon Sep 17 00:00:00 2001 From: Moiseenko Date: Fri, 22 Sep 2023 20:43:57 +0400 Subject: [PATCH 04/48] opis/closure replaced to laravel/serializable-closure --- composer.json | 15 ++++++++------- tests/docker/php/entrypoint.sh | 4 ++-- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/composer.json b/composer.json index d870a85ef5..5e591dbc27 100644 --- a/composer.json +++ b/composer.json @@ -16,21 +16,22 @@ "docs": "https://github.com/yiisoft/yii2-queue/blob/master/docs/guide" }, "require": { - "php": ">=5.5.0", + "php": ">=8.0", "yiisoft/yii2": "~2.0.14", - "symfony/process": "^3.3||^4.0||^5.0||^6.0" + "symfony/process": "^6.3", + "laravel/serializable-closure": "^v1.3.0" }, "require-dev": { + "phpunit/phpunit": "^10.3.0", "yiisoft/yii2-redis": "~2.0.0", + "yiisoft/yii2-debug": "~2.1.0", + "yiisoft/yii2-gii": "~2.2.0", "php-amqplib/php-amqplib": "^3.0.0", "enqueue/amqp-lib": "^0.10.0", + "enqueue/stomp": "^0.10.0", "pda/pheanstalk": "3.2.1", "opis/closure": "^3.6.0", - "yiisoft/yii2-debug": "~2.1.0", - "yiisoft/yii2-gii": "~2.2.0", - "phpunit/phpunit": "^10.3.0", - "aws/aws-sdk-php": ">=2.4", - "enqueue/stomp": "^0.10.0" + "aws/aws-sdk-php": ">=2.4" }, "suggest": { "ext-pcntl": "Need for process signals.", diff --git a/tests/docker/php/entrypoint.sh b/tests/docker/php/entrypoint.sh index 7c7df3ce62..0e0f4e8dd5 100755 --- a/tests/docker/php/entrypoint.sh +++ b/tests/docker/php/entrypoint.sh @@ -5,9 +5,9 @@ set -eu flock tests/runtime/composer-install.lock composer install --prefer-dist --no-interaction tests/yii sqlite-migrate/up --interactive=0 -sleep 60 +sleep 30 tests/docker/php/mysql-lock.php tests/yii mysql-migrate/up --interactive=0 -sleep 60 +sleep 30 tests/docker/php/mysql-lock.php tests/yii pgsql-migrate/up --interactive=0 php --version From 08d53fd6d8bfa133f3cc839753d66fc30396589f Mon Sep 17 00:00:00 2001 From: Moiseenko Date: Thu, 28 Sep 2023 18:04:13 +0400 Subject: [PATCH 05/48] opis/closure replaced to laravel/serializable-closure --- Makefile | 8 ++++---- src/closure/Behavior.php | 14 +++++++++----- src/closure/Job.php | 16 +++++++++------- tests/closure/ClosureJob.php | 4 +++- tests/closure/ClosureTest.php | 8 -------- 5 files changed, 25 insertions(+), 25 deletions(-) diff --git a/Makefile b/Makefile index 67079a8df3..d6123044ef 100644 --- a/Makefile +++ b/Makefile @@ -1,11 +1,11 @@ help: ## Display help information @fgrep -h "##" $(MAKEFILE_LIST) | fgrep -v fgrep | sed -e 's/\\$$//' | sed -e 's/##//' -build: ## Build an image from a docker-compose file. Params: {{ v=5.6 }}. Default latest PHP 5.6 +build: ## Build an image from a docker-compose file. Params: {{ v=8.1 }}. Default latest PHP 8.1 @cp -n .env.example .env PHP_VERSION=$(filter-out $@,$(v)) docker-compose up -d --build -test: ## Run tests. Params: {{ v=5.6 }}. Default latest PHP 5.6 +test: ## Run tests. Params: {{ v=8.1 }}. Default latest PHP 8.1 PHP_VERSION=$(filter-out $@,$(v)) docker-compose build --pull yii2-queue-php PHP_VERSION=$(filter-out $@,$(v)) docker-compose run yii2-queue-php vendor/bin/phpunit --colors=always make down @@ -13,13 +13,13 @@ test: ## Run tests. Params: {{ v=5.6 }}. Default latest PHP 5.6 down: ## Stop and remove containers, networks docker-compose down -benchmark: ## Run benchmark. Params: {{ v=5.6 }}. Default latest PHP 5.6 +benchmark: ## Run benchmark. Params: {{ v=8.1 }}. Default latest PHP 8.1 PHP_VERSION=$(filter-out $@,$(v)) docker-compose build --pull yii2-queue-php PHP_VERSION=$(filter-out $@,$(v)) docker-compose run yii2-queue-php tests/yii benchmark/waiting make down sh: ## Enter the container with the application - docker exec -it yii2-queue-php bash + docker exec -it yii2-queue-php sh check-cs: docker-compose build php72 diff --git a/src/closure/Behavior.php b/src/closure/Behavior.php index 0efea4fe49..2e8518752f 100644 --- a/src/closure/Behavior.php +++ b/src/closure/Behavior.php @@ -7,7 +7,7 @@ namespace yii\queue\closure; -use function Opis\Closure\serialize as opis_serialize; +use Laravel\SerializableClosure\SerializableClosure; use yii\queue\PushEvent; use yii\queue\Queue; @@ -33,11 +33,10 @@ class Behavior extends \yii\base\Behavior */ public $owner; - /** * @inheritdoc */ - public function events() + public function events(): array { return [ Queue::EVENT_BEFORE_PUSH => 'beforePush', @@ -48,9 +47,14 @@ public function events() * Converts the closure to a job object. * @param PushEvent $event */ - public function beforePush(PushEvent $event) + public function beforePush(PushEvent $event): void { - $serialized = opis_serialize($event->job); + SerializableClosure::setSecretKey(uniqid('', true)); + $serialized = serialize( + new SerializableClosure(function () use ($event) { + return $event->job; + }) + ); $event->job = new Job(); $event->job->serialized = $serialized; } diff --git a/src/closure/Job.php b/src/closure/Job.php index 9ec2d15877..e9ea84896b 100644 --- a/src/closure/Job.php +++ b/src/closure/Job.php @@ -7,7 +7,7 @@ namespace yii\queue\closure; -use function Opis\Closure\unserialize as opis_unserialize; +use Laravel\SerializableClosure\Serializers\Native; use yii\queue\JobInterface; /** @@ -20,8 +20,7 @@ class Job implements JobInterface /** * @var string serialized closure */ - public $serialized; - + public string $serialized; /** * Unserializes and executes a closure. @@ -29,10 +28,13 @@ class Job implements JobInterface */ public function execute($queue) { - $unserialized = opis_unserialize($this->serialized); - if ($unserialized instanceof \Closure) { - return $unserialized(); + $closure = unserialize($this->serialized)->getClosure(); + $nativeClosure = $closure(); + + if ($nativeClosure instanceof Native) { + return $nativeClosure(); } - return $unserialized->execute($queue); + + return $nativeClosure->execute($queue); } } diff --git a/tests/closure/ClosureJob.php b/tests/closure/ClosureJob.php index f4f6cd81d0..5359cbed28 100644 --- a/tests/closure/ClosureJob.php +++ b/tests/closure/ClosureJob.php @@ -2,6 +2,8 @@ namespace tests\closure; +use Closure; +use Laravel\SerializableClosure\Serializers\Native; use yii\base\BaseObject; use yii\queue\JobInterface; @@ -13,7 +15,7 @@ class ClosureJob extends BaseObject implements JobInterface { /** - * @var \Closure + * @var Closure */ public $closure; diff --git a/tests/closure/ClosureTest.php b/tests/closure/ClosureTest.php index 6912fa33fb..0120d23dec 100644 --- a/tests/closure/ClosureTest.php +++ b/tests/closure/ClosureTest.php @@ -21,8 +21,6 @@ class ClosureTest extends TestCase { public function testPush1(): void { - $this->markTestSkipped('Closure tests are disabled'); - $this->getQueue()->push(function () { $fileName = Yii::getAlias('@runtime/job-1.lock'); file_put_contents($fileName, ''); @@ -33,8 +31,6 @@ public function testPush1(): void public function testPush2(): void { - $this->markTestSkipped('Closure tests are disabled'); - $fileName = Yii::getAlias('@runtime/job-2.lock'); $this->getQueue()->push(function () use ($fileName) { file_put_contents($fileName, ''); @@ -45,8 +41,6 @@ public function testPush2(): void public function testPush3(): void { - $this->markTestSkipped('Closuretests are disabled'); - $job = new ClosureJob([ 'closure' => function () { $fileName = Yii::getAlias('@runtime/job-3.lock'); @@ -60,8 +54,6 @@ public function testPush3(): void public function testPush4(): void { - $this->markTestSkipped('Closure tests are disabled'); - $fileName = Yii::getAlias('@runtime/job-4.lock'); $job = new ClosureJob([ 'closure' => function () use ($fileName) { From 33f7793129b10924b58c6da16eb7036e93d4ff82 Mon Sep 17 00:00:00 2001 From: Moiseenko Date: Thu, 28 Sep 2023 18:46:54 +0400 Subject: [PATCH 06/48] Added IDE helpers and more types hinting --- composer.json | 6 +-- src/RetryableJobInterface.php | 9 ++-- support/ide-helper.php | 62 ++++++++++++++++++++++++ tests/JobEventTest.php | 2 +- tests/app/PriorityJob.php | 4 +- tests/app/RetryJob.php | 6 +-- tests/app/SimpleJob.php | 4 +- tests/serializers/JsonSerializerTest.php | 3 +- tests/serializers/TestCase.php | 3 +- 9 files changed, 83 insertions(+), 16 deletions(-) create mode 100644 support/ide-helper.php diff --git a/composer.json b/composer.json index 5e591dbc27..cbbe39a06e 100644 --- a/composer.json +++ b/composer.json @@ -16,7 +16,7 @@ "docs": "https://github.com/yiisoft/yii2-queue/blob/master/docs/guide" }, "require": { - "php": ">=8.0", + "php": ">=8.1", "yiisoft/yii2": "~2.0.14", "symfony/process": "^6.3", "laravel/serializable-closure": "^v1.3.0" @@ -30,7 +30,6 @@ "enqueue/amqp-lib": "^0.10.0", "enqueue/stomp": "^0.10.0", "pda/pheanstalk": "3.2.1", - "opis/closure": "^3.6.0", "aws/aws-sdk-php": ">=2.4" }, "suggest": { @@ -65,7 +64,8 @@ }, "config": { "allow-plugins": { - "yiisoft/yii2-composer": true + "yiisoft/yii2-composer": true, + "php-http/discovery": true } }, "extra": { diff --git a/src/RetryableJobInterface.php b/src/RetryableJobInterface.php index 2a13fb7585..40dfe9ccff 100644 --- a/src/RetryableJobInterface.php +++ b/src/RetryableJobInterface.php @@ -7,6 +7,9 @@ namespace yii\queue; +use Exception; +use Throwable; + /** * Retryable Job Interface. * @@ -17,12 +20,12 @@ interface RetryableJobInterface extends JobInterface /** * @return int time to reserve in seconds */ - public function getTtr(); + public function getTtr(): int; /** * @param int $attempt number - * @param \Exception|\Throwable $error from last execute of the job + * @param Exception|Throwable $error from last execute of the job * @return bool */ - public function canRetry($attempt, $error); + public function canRetry(int $attempt, $error): bool; } diff --git a/support/ide-helper.php b/support/ide-helper.php new file mode 100644 index 0000000000..a41e9494ca --- /dev/null +++ b/support/ide-helper.php @@ -0,0 +1,62 @@ +on(Queue::EVENT_BEFORE_EXEC, $eventHandler); $queue->on(Queue::EVENT_AFTER_ERROR, $eventHandler); $queue->on(Queue::EVENT_AFTER_ERROR, function (ExecEvent $event) { - $this->assertTrue($event->error instanceof InvalidJobException); + $this->assertInstanceOf(InvalidJobException::class, $event->error); $this->assertFalse($event->retry); }); $jobId = $queue->push('message that cannot be unserialized'); diff --git a/tests/app/PriorityJob.php b/tests/app/PriorityJob.php index 2d8c2000f3..8cf6c681fc 100644 --- a/tests/app/PriorityJob.php +++ b/tests/app/PriorityJob.php @@ -18,14 +18,14 @@ */ class PriorityJob extends BaseObject implements JobInterface { - public $number; + public int $number; public function execute($queue) { file_put_contents(self::getFileName(), $this->number, FILE_APPEND); } - public static function getFileName() + public static function getFileName(): bool|string { return Yii::getAlias("@runtime/job-priority.log"); } diff --git a/tests/app/RetryJob.php b/tests/app/RetryJob.php index 8248d4c816..0830c5bc6b 100644 --- a/tests/app/RetryJob.php +++ b/tests/app/RetryJob.php @@ -26,17 +26,17 @@ public function execute($queue) throw new \Exception('Planned error.'); } - public function getFileName() + public function getFileName(): bool|string { return Yii::getAlias("@runtime/job-{$this->uid}.lock"); } - public function getTtr() + public function getTtr(): int { return 2; } - public function canRetry($attempt, $error) + public function canRetry($attempt, $error): bool { return $attempt < 2; } diff --git a/tests/app/SimpleJob.php b/tests/app/SimpleJob.php index 4647f4d5f0..1e0d54b10f 100644 --- a/tests/app/SimpleJob.php +++ b/tests/app/SimpleJob.php @@ -18,14 +18,14 @@ */ class SimpleJob extends BaseObject implements JobInterface { - public $uid; + public string $uid; public function execute($queue) { file_put_contents($this->getFileName(), ''); } - public function getFileName() + public function getFileName(): bool|string { return Yii::getAlias("@runtime/job-{$this->uid}.lock"); } diff --git a/tests/serializers/JsonSerializerTest.php b/tests/serializers/JsonSerializerTest.php index b53e98b31c..5a812cde5c 100644 --- a/tests/serializers/JsonSerializerTest.php +++ b/tests/serializers/JsonSerializerTest.php @@ -7,6 +7,7 @@ namespace tests\serializers; +use yii\base\InvalidConfigException; use yii\queue\serializers\JsonSerializer; use yii\queue\serializers\SerializerInterface; @@ -27,7 +28,7 @@ protected function createSerializer(): SerializerInterface public function testInvalidArrayKey(): void { - $this->expectException(\yii\base\InvalidConfigException::class); + $this->expectException(InvalidConfigException::class); $this->createSerializer()->serialize([ 'class' => 'failed param', ]); diff --git a/tests/serializers/TestCase.php b/tests/serializers/TestCase.php index 9fc8ea54d0..35976ee028 100644 --- a/tests/serializers/TestCase.php +++ b/tests/serializers/TestCase.php @@ -8,6 +8,7 @@ namespace tests\serializers; use tests\app\SimpleJob; +use tests\TestCase as BaseTestCase; use yii\base\BaseObject; use yii\queue\serializers\SerializerInterface; @@ -16,7 +17,7 @@ * * @author Roman Zhuravlev */ -abstract class TestCase extends \tests\TestCase +abstract class TestCase extends BaseTestCase { /** * @return SerializerInterface From a967c8f8bad6ec734610e942626308527c8a337f Mon Sep 17 00:00:00 2001 From: Moiseenko Date: Thu, 28 Sep 2023 18:51:34 +0400 Subject: [PATCH 07/48] Updated CI --- .gitattributes | 1 + .github/workflows/main.yml | 20 ++++++++++++++++++-- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/.gitattributes b/.gitattributes index 0e3c6ca146..dbebd6c75a 100644 --- a/.gitattributes +++ b/.gitattributes @@ -11,3 +11,4 @@ /.travis.yml export-ignore /Makefile export-ignore /phpunit.xml.dist export-ignore +/support export-ignore diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 9fa20c41e8..f61e5c0547 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -1,6 +1,22 @@ name: build -on: [push, workflow_dispatch, pull_request] +on: + pull_request: + paths-ignore: + - 'docs/**' + - 'README.md' + - 'CHANGELOG.md' + - '.gitignore' + - '.gitattributes' + + push: + branches: [ 'master' ] + paths-ignore: + - 'docs/**' + - 'README.md' + - 'CHANGELOG.md' + - '.gitignore' + - '.gitattributes' env: COMPOSE_PROJECT_NAME: yii2-queue @@ -20,7 +36,7 @@ jobs: strategy: fail-fast: false matrix: - php: [ '8.1' ] + php: [ '8.1', '8.2', '8.3' ] steps: - name: Checkout uses: actions/checkout@v2 From ec08b06bd775d580f8af5a5fd3eee8f7b227fc66 Mon Sep 17 00:00:00 2001 From: Moiseenko Date: Thu, 28 Sep 2023 18:54:41 +0400 Subject: [PATCH 08/48] Updated CI --- .editorconfig | 3 +++ .github/workflows/main.yml | 30 +++++++++++++++--------------- 2 files changed, 18 insertions(+), 15 deletions(-) diff --git a/.editorconfig b/.editorconfig index 61bd74c9e7..458e2d425a 100644 --- a/.editorconfig +++ b/.editorconfig @@ -16,3 +16,6 @@ trim_trailing_whitespace = false [Makefile] indent_style = tab + +[*.yml] +indent_size = 2 \ No newline at end of file diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index f61e5c0547..fff849efad 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -1,22 +1,22 @@ name: build on: - pull_request: - paths-ignore: - - 'docs/**' - - 'README.md' - - 'CHANGELOG.md' - - '.gitignore' - - '.gitattributes' + pull_request: + paths-ignore: + - 'docs/**' + - 'README.md' + - 'CHANGELOG.md' + - '.gitignore' + - '.gitattributes' - push: - branches: [ 'master' ] - paths-ignore: - - 'docs/**' - - 'README.md' - - 'CHANGELOG.md' - - '.gitignore' - - '.gitattributes' + push: + branches: [ 'master' ] + paths-ignore: + - 'docs/**' + - 'README.md' + - 'CHANGELOG.md' + - '.gitignore' + - '.gitattributes' env: COMPOSE_PROJECT_NAME: yii2-queue From 8a7b9c8b0e3428be0bbf10951251244a7a719515 Mon Sep 17 00:00:00 2001 From: Moiseenko Date: Thu, 28 Sep 2023 19:04:11 +0400 Subject: [PATCH 09/48] Updated CI --- .github/workflows/main.yml | 2 +- .gitignore | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index fff849efad..d6f9e5a6d7 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -36,7 +36,7 @@ jobs: strategy: fail-fast: false matrix: - php: [ '8.1', '8.2', '8.3' ] + php: [ '8.1', '8.2'] steps: - name: Checkout uses: actions/checkout@v2 diff --git a/.gitignore b/.gitignore index 6ccbccc58b..70455b22f1 100644 --- a/.gitignore +++ b/.gitignore @@ -19,3 +19,6 @@ composer.lock # Env variables .env + +# PHP Unit cache +.phpunit.result.cache From 891f54b20e66a1fac1ea55fd9db38f4b3e31d9f6 Mon Sep 17 00:00:00 2001 From: Moiseenko Date: Thu, 28 Sep 2023 19:18:45 +0400 Subject: [PATCH 10/48] Added more strict types --- tests/JobEventTest.php | 3 +++ tests/TestCase.php | 3 +++ tests/closure/ClosureJob.php | 3 ++- tests/closure/ClosureTest.php | 3 +++ tests/drivers/CliTestCase.php | 16 ++++++++++------ tests/drivers/TestCase.php | 3 +++ tests/drivers/sync/QueueTest.php | 3 +++ tests/serializers/IgbinarySerializerTest.php | 3 +++ tests/serializers/JsonSerializerTest.php | 3 +++ tests/serializers/PhpSerializerTest.php | 3 +++ tests/serializers/TestCase.php | 3 +++ 11 files changed, 39 insertions(+), 7 deletions(-) diff --git a/tests/JobEventTest.php b/tests/JobEventTest.php index 74286dfc8e..54fee05c58 100644 --- a/tests/JobEventTest.php +++ b/tests/JobEventTest.php @@ -1,4 +1,7 @@ prepareCmd($cmd); $process = new Process($cmd); @@ -43,7 +47,7 @@ protected function runProcess($cmd): void * @param array $cmd * @return Process */ - protected function startProcess($cmd) + protected function startProcess(array $cmd): Process { $process = new Process($this->prepareCmd($cmd)); $process->start(); @@ -59,9 +63,9 @@ protected function startProcess($cmd) * @param array $cmd * @return array */ - private function prepareCmd($cmd) + private function prepareCmd(array $cmd): array { - $class = new \ReflectionClass($this->getQueue()); + $class = new ReflectionClass($this->getQueue()); $method = $class->getMethod('getCommandId'); $method->setAccessible(true); @@ -74,7 +78,7 @@ private function prepareCmd($cmd) array_walk( $cmd, static function (&$v) use ($replace) { - $v = strtr($v, $replace); + $v = strtr((string)$v, $replace); } ); diff --git a/tests/drivers/TestCase.php b/tests/drivers/TestCase.php index cf68d175bd..e2ff40a08d 100644 --- a/tests/drivers/TestCase.php +++ b/tests/drivers/TestCase.php @@ -1,4 +1,7 @@ Date: Mon, 2 Oct 2023 14:16:51 +0400 Subject: [PATCH 11/48] Added more strict types --- src/Queue.php | 11 ++-- src/cli/Command.php | 2 +- src/cli/Queue.php | 2 +- src/closure/Behavior.php | 3 + src/closure/Job.php | 3 + src/drivers/amqp/Queue.php | 6 +- src/drivers/amqp_interop/Command.php | 7 ++- src/drivers/amqp_interop/Queue.php | 94 +++++++++++++++------------- src/drivers/beanstalk/Command.php | 2 +- src/drivers/beanstalk/Queue.php | 4 +- src/drivers/db/Command.php | 2 +- src/drivers/db/Queue.php | 6 +- src/drivers/file/Command.php | 2 +- src/drivers/file/Queue.php | 9 ++- src/drivers/gearman/Command.php | 2 +- src/drivers/redis/Command.php | 2 +- src/drivers/redis/Queue.php | 8 ++- src/drivers/sqs/Command.php | 2 +- src/drivers/sqs/Queue.php | 12 +--- src/drivers/stomp/Command.php | 2 +- src/drivers/stomp/Queue.php | 5 +- src/drivers/sync/Queue.php | 5 +- 22 files changed, 108 insertions(+), 83 deletions(-) diff --git a/src/Queue.php b/src/Queue.php index 2d61c82788..c6a7fd44eb 100644 --- a/src/Queue.php +++ b/src/Queue.php @@ -86,7 +86,7 @@ abstract class Queue extends Component /** * @inheritdoc */ - public function init() + public function init(): void { parent::init(); @@ -115,7 +115,7 @@ public function init() * @param int|mixed $value * @return $this */ - public function ttr($value) + public function ttr($value): static { $this->pushTtr = $value; return $this; @@ -127,7 +127,7 @@ public function ttr($value) * @param int|mixed $value * @return $this */ - public function delay($value) + public function delay($value): static { $this->pushDelay = $value; return $this; @@ -139,7 +139,7 @@ public function delay($value) * @param mixed $value * @return $this */ - public function priority($value) + public function priority($value): static { $this->pushPriority = $value; return $this; @@ -258,11 +258,10 @@ protected function handleMessage($id, $message, $ttr, $attempt) /** * Unserializes. * - * @param string $id of the job * @param string $serialized message * @return array pair of a job and error that */ - public function unserializeMessage($serialized) + public function unserializeMessage(string $serialized): array { try { $job = $this->serializer->unserialize($serialized); diff --git a/src/cli/Command.php b/src/cli/Command.php index 5a8758e4d5..456439a8d5 100644 --- a/src/cli/Command.php +++ b/src/cli/Command.php @@ -89,7 +89,7 @@ public function optionAliases() * @return bool * @since 2.0.2 */ - abstract protected function isWorkerAction($actionID); + abstract protected function isWorkerAction(string $actionID): bool; /** * @param string $actionID diff --git a/src/cli/Queue.php b/src/cli/Queue.php index ef513bc2f6..235a0a5df0 100644 --- a/src/cli/Queue.php +++ b/src/cli/Queue.php @@ -130,7 +130,7 @@ protected function runWorker(callable $handler) * @return int|null * @since 2.0.2 */ - public function getWorkerPid() + public function getWorkerPid(): ?int { return $this->_workerPid; } diff --git a/src/closure/Behavior.php b/src/closure/Behavior.php index 2e8518752f..a83f82bdf8 100644 --- a/src/closure/Behavior.php +++ b/src/closure/Behavior.php @@ -1,4 +1,7 @@ queue->listen(); } diff --git a/src/drivers/amqp_interop/Queue.php b/src/drivers/amqp_interop/Queue.php index 72809608f5..945cba4880 100644 --- a/src/drivers/amqp_interop/Queue.php +++ b/src/drivers/amqp_interop/Queue.php @@ -1,4 +1,7 @@ open(); $this->setupBroker(); @@ -344,7 +350,7 @@ public function listen() /** * @return AmqpContext */ - public function getContext() + public function getContext(): AmqpContext { $this->open(); diff --git a/src/drivers/beanstalk/Command.php b/src/drivers/beanstalk/Command.php index d9478cf71e..d407fb7335 100644 --- a/src/drivers/beanstalk/Command.php +++ b/src/drivers/beanstalk/Command.php @@ -40,7 +40,7 @@ public function actions() /** * @inheritdoc */ - protected function isWorkerAction($actionID) + protected function isWorkerAction($actionID): bool { return in_array($actionID, ['run', 'listen']); } diff --git a/src/drivers/beanstalk/Queue.php b/src/drivers/beanstalk/Queue.php index dadf161d49..c27a290658 100644 --- a/src/drivers/beanstalk/Queue.php +++ b/src/drivers/beanstalk/Queue.php @@ -1,4 +1,7 @@ db = Instance::ensure($this->db, Connection::class); diff --git a/src/drivers/file/Command.php b/src/drivers/file/Command.php index ae6685c31e..2999432bbc 100644 --- a/src/drivers/file/Command.php +++ b/src/drivers/file/Command.php @@ -40,7 +40,7 @@ public function actions() /** * @inheritdoc */ - protected function isWorkerAction($actionID) + protected function isWorkerAction($actionID): bool { return in_array($actionID, ['run', 'listen']); } diff --git a/src/drivers/file/Queue.php b/src/drivers/file/Queue.php index a054bf5579..f4194367a8 100644 --- a/src/drivers/file/Queue.php +++ b/src/drivers/file/Queue.php @@ -1,4 +1,7 @@ path = Yii::getAlias($this->path); diff --git a/src/drivers/gearman/Command.php b/src/drivers/gearman/Command.php index 02ffe427ac..8aea83ec8f 100644 --- a/src/drivers/gearman/Command.php +++ b/src/drivers/gearman/Command.php @@ -25,7 +25,7 @@ class Command extends CliCommand /** * @inheritdoc */ - protected function isWorkerAction($actionID) + protected function isWorkerAction($actionID): bool { return in_array($actionID, ['run', 'listen'], true); } diff --git a/src/drivers/redis/Command.php b/src/drivers/redis/Command.php index 146aa18d22..c74479c679 100644 --- a/src/drivers/redis/Command.php +++ b/src/drivers/redis/Command.php @@ -40,7 +40,7 @@ public function actions() /** * @inheritdoc */ - protected function isWorkerAction($actionID) + protected function isWorkerAction($actionID): bool { return in_array($actionID, ['run', 'listen'], true); } diff --git a/src/drivers/redis/Queue.php b/src/drivers/redis/Queue.php index aff79cfe0a..b5241ea96e 100644 --- a/src/drivers/redis/Queue.php +++ b/src/drivers/redis/Queue.php @@ -1,4 +1,7 @@ redis = Instance::ensure($this->redis, Connection::class); diff --git a/src/drivers/sqs/Command.php b/src/drivers/sqs/Command.php index 15474915b7..23cbdebccb 100644 --- a/src/drivers/sqs/Command.php +++ b/src/drivers/sqs/Command.php @@ -69,7 +69,7 @@ public function actionClear() /** * @inheritdoc */ - protected function isWorkerAction($actionID) + protected function isWorkerAction($actionID): bool { return in_array($actionID, ['run', 'listen']); } diff --git a/src/drivers/sqs/Queue.php b/src/drivers/sqs/Queue.php index 898ea019a7..896f6aa8e0 100644 --- a/src/drivers/sqs/Queue.php +++ b/src/drivers/sqs/Queue.php @@ -1,4 +1,7 @@ handle) { From 244d004890581a37a0f4dba8091a3d997b040981 Mon Sep 17 00:00:00 2001 From: Moiseenko Date: Mon, 2 Oct 2023 15:46:57 +0400 Subject: [PATCH 12/48] Added more strict types --- src/Queue.php | 2 +- src/drivers/amqp/Queue.php | 2 +- src/drivers/amqp_interop/Command.php | 1 - src/drivers/amqp_interop/Queue.php | 48 ++++++++++++------------ src/drivers/beanstalk/Command.php | 11 +++--- src/drivers/beanstalk/Queue.php | 2 +- src/drivers/db/Command.php | 12 +++--- src/drivers/db/Queue.php | 2 +- src/drivers/file/Command.php | 9 ++--- src/drivers/file/Queue.php | 6 +-- src/drivers/gearman/Command.php | 5 +-- src/drivers/gearman/Queue.php | 2 +- src/drivers/redis/Command.php | 16 ++++---- src/drivers/redis/Queue.php | 2 +- src/drivers/sqs/Command.php | 12 +++--- src/drivers/sqs/Queue.php | 2 +- src/drivers/stomp/Command.php | 6 +-- src/drivers/stomp/Queue.php | 2 +- src/drivers/sync/Queue.php | 2 +- tests/drivers/amqp_interop/QueueTest.php | 13 +------ 20 files changed, 73 insertions(+), 84 deletions(-) diff --git a/src/Queue.php b/src/Queue.php index c6a7fd44eb..c85624595d 100644 --- a/src/Queue.php +++ b/src/Queue.php @@ -327,5 +327,5 @@ public function isDone($id) * @param string $id of a job message * @return int status code */ - abstract public function status($id); + abstract public function status(string $id): int; } diff --git a/src/drivers/amqp/Queue.php b/src/drivers/amqp/Queue.php index c307c39ceb..20287b06eb 100644 --- a/src/drivers/amqp/Queue.php +++ b/src/drivers/amqp/Queue.php @@ -118,7 +118,7 @@ protected function pushMessage($message, $ttr, $delay, $priority) /** * @inheritdoc */ - public function status($id) + public function status($id): int { throw new NotSupportedException('Status is not supported in the driver.'); } diff --git a/src/drivers/amqp_interop/Command.php b/src/drivers/amqp_interop/Command.php index 44f77dcb9c..cf98696491 100644 --- a/src/drivers/amqp_interop/Command.php +++ b/src/drivers/amqp_interop/Command.php @@ -25,7 +25,6 @@ class Command extends CliCommand */ public $queue; - /** * @inheritdoc */ diff --git a/src/drivers/amqp_interop/Queue.php b/src/drivers/amqp_interop/Queue.php index 945cba4880..1acfb51112 100644 --- a/src/drivers/amqp_interop/Queue.php +++ b/src/drivers/amqp_interop/Queue.php @@ -48,9 +48,9 @@ class Queue extends CliQueue * 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 + * @var string|null */ - public string $dsn; + public ?string $dsn = null; /** * The message queue broker's host. * @@ -62,7 +62,7 @@ class Queue extends CliQueue * * @var string|null */ - public ?string $port; + public ?string $port = null; /** * This is RabbitMQ user which is used to login on the broker. * @@ -80,98 +80,98 @@ class Queue extends CliQueue * * @var string|null */ - public ?string $vhost; + public ?string $vhost = null; /** * The time PHP socket waits for an information while reading. In seconds. * * @var float|null */ - public ?float $readTimeout; + public ?float $readTimeout = null; /** * The time PHP socket waits for an information while witting. In seconds. * * @var float|null */ - public ?float $writeTimeout; + public ?float $writeTimeout = null; /** * The time RabbitMQ keeps the connection on idle. In seconds. * * @var float|null */ - public ?float $connectionTimeout; + public ?float $connectionTimeout = null; /** * The periods of time PHP pings the broker in order to prolong the connection timeout. In seconds. * * @var float|null */ - public ?float $heartbeat; + public ?float $heartbeat = 0; /** * PHP uses one shared connection if set true. * * @var bool|null */ - public ?bool $persisted; + public ?bool $persisted = null; /** * Send keep-alive packets for a socket connection * @var bool * @since 2.3.6 */ - public bool $keepalive; + public bool $keepalive = false; /** * The connection will be established as later as possible if set true. * * @var bool|null */ - public ?bool $lazy; + public ?bool $lazy = null; /** * 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 ?bool $qosGlobal; + public ?bool $qosGlobal = null; /** * Defines number of message pre-fetched in advance on a channel basis. * * @var int|null */ - public ?int $qosPrefetchSize; + public ?int $qosPrefetchSize = null; /** * Defines number of message pre-fetched in advance per consumer. * * @var int|null */ - public ?int $qosPrefetchCount; + public ?int $qosPrefetchCount = null; /** * Defines whether secure connection should be used or not. * * @var bool|null */ - public ?bool $sslOn; + public ?bool $sslOn = null; /** * Require verification of SSL certificate used. * * @var bool|null */ - public ?bool $sslVerify; + public ?bool $sslVerify = null; /** * 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 ?string $sslCacert; + public ?string $sslCacert = null; /** * Path to local certificate file on filesystem. * * @var string|null */ - public ?string $sslCert; + public ?string $sslCert = null; /** * Path to local private key file on filesystem in case of separate files for certificate (local_cert) and private key. * * @var string|null */ - public ?string $sslKey; + public ?string $sslKey = null; /** * The queue used to consume messages from. * @@ -223,7 +223,7 @@ class Queue extends CliQueue * * @var string|null */ - public ?string $routingKey; + public ?string $routingKey = null; /** * Defines the amqp interop transport being internally used. Currently supports lib, ext and bunny values. * @@ -247,16 +247,16 @@ class Queue extends CliQueue * ``` * * @var array - * @since 3.0.0 + * @since 2.3.6 */ public array $setMessageHeaders = []; /** * Amqp interop context. * - * @var AmqpContext + * @var AmqpContext|null */ - protected AmqpContext $context; + protected ?AmqpContext $context = null; /** * List of supported amqp interop drivers. * @@ -403,7 +403,7 @@ protected function pushMessage($payload, $ttr, $delay, $priority) /** * @inheritdoc */ - public function status($id) + public function status($id): int { throw new NotSupportedException('Status is not supported in the driver.'); } diff --git a/src/drivers/beanstalk/Command.php b/src/drivers/beanstalk/Command.php index d407fb7335..9237a49343 100644 --- a/src/drivers/beanstalk/Command.php +++ b/src/drivers/beanstalk/Command.php @@ -26,11 +26,10 @@ class Command extends CliCommand */ public $defaultAction = 'info'; - /** * @inheritdoc */ - public function actions() + public function actions(): array { return [ 'info' => InfoAction::class, @@ -51,7 +50,7 @@ protected function isWorkerAction($actionID): bool * * @return null|int exit code. */ - public function actionRun() + public function actionRun(): ?int { return $this->queue->run(false); } @@ -61,10 +60,10 @@ public function actionRun() * 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. + *@throws Exception when params are invalid. */ - public function actionListen($timeout = 3) + public function actionListen(int $timeout = 3): ?int { if (!is_numeric($timeout)) { throw new Exception('Timeout must be numeric.'); @@ -83,7 +82,7 @@ public function actionListen($timeout = 3) * @throws Exception when the job is not found. * @since 2.0.1 */ - public function actionRemove($id) + public function actionRemove(int $id): void { if (!$this->queue->remove($id)) { throw new Exception('The job is not found.'); diff --git a/src/drivers/beanstalk/Queue.php b/src/drivers/beanstalk/Queue.php index c27a290658..6291c51682 100644 --- a/src/drivers/beanstalk/Queue.php +++ b/src/drivers/beanstalk/Queue.php @@ -74,7 +74,7 @@ public function run($repeat, $timeout = 0) /** * @inheritdoc */ - public function status($id) + public function status($id): int { if (!is_numeric($id) || $id <= 0) { throw new InvalidArgumentException("Unknown message ID: $id."); diff --git a/src/drivers/db/Command.php b/src/drivers/db/Command.php index 60a71da830..5aec80b32c 100644 --- a/src/drivers/db/Command.php +++ b/src/drivers/db/Command.php @@ -30,7 +30,7 @@ class Command extends CliCommand /** * @inheritdoc */ - public function actions() + public function actions(): array { return [ 'info' => InfoAction::class, @@ -51,7 +51,7 @@ protected function isWorkerAction($actionID): bool * * @return null|int exit code. */ - public function actionRun() + public function actionRun(): ?int { return $this->queue->run(false); } @@ -61,10 +61,10 @@ public function actionRun() * 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. + *@throws Exception when params are invalid. */ - public function actionListen($timeout = 3) + public function actionListen(int $timeout = 3): ?int { if (!is_numeric($timeout)) { throw new Exception('Timeout must be numeric.'); @@ -81,7 +81,7 @@ public function actionListen($timeout = 3) * * @since 2.0.1 */ - public function actionClear() + public function actionClear(): void { if ($this->confirm('Are you sure?')) { $this->queue->clear(); @@ -95,7 +95,7 @@ public function actionClear() * @throws Exception when the job is not found. * @since 2.0.1 */ - public function actionRemove($id) + public function actionRemove(int $id): void { if (!$this->queue->remove($id)) { throw new Exception('The job is not found.'); diff --git a/src/drivers/db/Queue.php b/src/drivers/db/Queue.php index 151038dd9c..70f92d262a 100644 --- a/src/drivers/db/Queue.php +++ b/src/drivers/db/Queue.php @@ -98,7 +98,7 @@ public function run($repeat, $timeout = 0) /** * @inheritdoc */ - public function status($id) + public function status($id): int { $payload = (new Query()) ->from($this->tableName) diff --git a/src/drivers/file/Command.php b/src/drivers/file/Command.php index 2999432bbc..1700632d32 100644 --- a/src/drivers/file/Command.php +++ b/src/drivers/file/Command.php @@ -26,11 +26,10 @@ class Command extends CliCommand */ public $defaultAction = 'info'; - /** * @inheritdoc */ - public function actions() + public function actions(): array { return [ 'info' => InfoAction::class, @@ -51,7 +50,7 @@ protected function isWorkerAction($actionID): bool * * @return null|int exit code. */ - public function actionRun() + public function actionRun(): ?int { return $this->queue->run(false); } @@ -64,7 +63,7 @@ public function actionRun() * @throws Exception when params are invalid. * @return null|int exit code. */ - public function actionListen($timeout = 3) + public function actionListen(int $timeout = 3): ?int { if (!is_numeric($timeout)) { throw new Exception('Timeout must be numeric.'); @@ -81,7 +80,7 @@ public function actionListen($timeout = 3) * * @since 2.0.1 */ - public function actionClear() + public function actionClear(): void { if ($this->confirm('Are you sure?')) { $this->queue->clear(); diff --git a/src/drivers/file/Queue.php b/src/drivers/file/Queue.php index f4194367a8..7e64f20687 100644 --- a/src/drivers/file/Queue.php +++ b/src/drivers/file/Queue.php @@ -71,12 +71,12 @@ public function init(): void * @internal for worker command only. * @since 2.0.2 */ - public function run($repeat, $timeout = 0) + public function run(bool $repeat, int $timeout = 0): ?int { return $this->runWorker(function (callable $canContinue) use ($repeat, $timeout) { while ($canContinue()) { if (($payload = $this->reserve()) !== null) { - list($id, $message, $ttr, $attempt) = $payload; + [$id, $message, $ttr, $attempt] = $payload; if ($this->handleMessage($id, $message, $ttr, $attempt)) { $this->delete($payload); } @@ -92,7 +92,7 @@ public function run($repeat, $timeout = 0) /** * @inheritdoc */ - public function status($id) + public function status($id): int { if (!is_numeric($id) || $id <= 0) { throw new InvalidArgumentException("Unknown message ID: $id."); diff --git a/src/drivers/gearman/Command.php b/src/drivers/gearman/Command.php index 8aea83ec8f..4ed2950426 100644 --- a/src/drivers/gearman/Command.php +++ b/src/drivers/gearman/Command.php @@ -21,7 +21,6 @@ class Command extends CliCommand */ public $queue; - /** * @inheritdoc */ @@ -36,7 +35,7 @@ protected function isWorkerAction($actionID): bool * * @return null|int exit code. */ - public function actionRun() + public function actionRun(): ?int { return $this->queue->run(false); } @@ -47,7 +46,7 @@ public function actionRun() * * @return null|int exit code. */ - public function actionListen() + public function actionListen(): ?int { return $this->queue->run(true); } diff --git a/src/drivers/gearman/Queue.php b/src/drivers/gearman/Queue.php index 54fc4bbd2e..61db1a2979 100644 --- a/src/drivers/gearman/Queue.php +++ b/src/drivers/gearman/Queue.php @@ -75,7 +75,7 @@ protected function pushMessage($message, $ttr, $delay, $priority) /** * @inheritdoc */ - public function status($id) + public function status($id): int { $status = $this->getClient()->jobStatus($id); if ($status[0] && !$status[1]) { diff --git a/src/drivers/redis/Command.php b/src/drivers/redis/Command.php index c74479c679..278ab5cfdb 100644 --- a/src/drivers/redis/Command.php +++ b/src/drivers/redis/Command.php @@ -1,4 +1,7 @@ InfoAction::class, @@ -51,7 +53,7 @@ protected function isWorkerAction($actionID): bool * * @return null|int exit code. */ - public function actionRun() + public function actionRun(): ?int { return $this->queue->run(false); } @@ -61,10 +63,10 @@ public function actionRun() * 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. + * @throws Exception when params are invalid. */ - public function actionListen($timeout = 3) + public function actionListen(int $timeout = 3): ?int { if (!is_numeric($timeout)) { throw new Exception('Timeout must be numeric.'); @@ -81,7 +83,7 @@ public function actionListen($timeout = 3) * * @since 2.0.1 */ - public function actionClear() + public function actionClear(): void { if ($this->confirm('Are you sure?')) { $this->queue->clear(); @@ -95,7 +97,7 @@ public function actionClear() * @throws Exception when the job is not found. * @since 2.0.1 */ - public function actionRemove($id) + public function actionRemove(int $id): void { if (!$this->queue->remove($id)) { throw new Exception('The job is not found.'); diff --git a/src/drivers/redis/Queue.php b/src/drivers/redis/Queue.php index b5241ea96e..ac482dd613 100644 --- a/src/drivers/redis/Queue.php +++ b/src/drivers/redis/Queue.php @@ -73,7 +73,7 @@ public function run($repeat, $timeout = 0) /** * @inheritdoc */ - public function status($id) + public function status($id): int { if (!is_numeric($id) || $id <= 0) { throw new InvalidArgumentException("Unknown message ID: $id."); diff --git a/src/drivers/sqs/Command.php b/src/drivers/sqs/Command.php index 23cbdebccb..d8f5b53a54 100644 --- a/src/drivers/sqs/Command.php +++ b/src/drivers/sqs/Command.php @@ -1,4 +1,7 @@ queue->run(false); } @@ -40,10 +42,10 @@ public function actionRun() * 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. + * @throws Exception when params are invalid. */ - public function actionListen($timeout = 3) + public function actionListen(int $timeout = 3): ?int { if (!is_numeric($timeout)) { throw new Exception('Timeout must be numeric.'); @@ -58,7 +60,7 @@ public function actionListen($timeout = 3) /** * Clears the queue. */ - public function actionClear() + public function actionClear(): void { if ($this->confirm('Are you sure?')) { $this->queue->clear(); diff --git a/src/drivers/sqs/Queue.php b/src/drivers/sqs/Queue.php index 896f6aa8e0..219d53258d 100644 --- a/src/drivers/sqs/Queue.php +++ b/src/drivers/sqs/Queue.php @@ -158,7 +158,7 @@ public function clear() /** * @inheritdoc */ - public function status($id) + public function status($id): int { throw new NotSupportedException('Status is not supported in the driver.'); } diff --git a/src/drivers/stomp/Command.php b/src/drivers/stomp/Command.php index 22108f9ea4..1079d6daec 100644 --- a/src/drivers/stomp/Command.php +++ b/src/drivers/stomp/Command.php @@ -23,7 +23,6 @@ class Command extends CliCommand */ public $queue; - /** * @inheritdoc */ @@ -32,14 +31,13 @@ protected function isWorkerAction($actionID): bool 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() + public function actionRun(): ?int { return $this->queue->run(false); } @@ -52,7 +50,7 @@ public function actionRun() * @throws Exception when params are invalid. * @return null|int exit code. */ - public function actionListen($timeout = 3) + public function actionListen(int $timeout = 3): ?int { if (!is_numeric($timeout)) { throw new Exception('Timeout must be numeric.'); diff --git a/src/drivers/stomp/Queue.php b/src/drivers/stomp/Queue.php index 7f1900a6d5..42eb34f1c8 100644 --- a/src/drivers/stomp/Queue.php +++ b/src/drivers/stomp/Queue.php @@ -257,7 +257,7 @@ protected function close() * @inheritdoc * @throws NotSupportedException */ - public function status($id) + public function status($id): int { throw new NotSupportedException('Status is not supported in the driver.'); } diff --git a/src/drivers/sync/Queue.php b/src/drivers/sync/Queue.php index df1eae3d70..0caef050ca 100644 --- a/src/drivers/sync/Queue.php +++ b/src/drivers/sync/Queue.php @@ -86,7 +86,7 @@ protected function pushMessage($message, $ttr, $delay, $priority) /** * @inheritdoc */ - public function status($id) + public function status($id): int { if (!is_int($id) || $id <= 0 || $id > $this->pushedId) { throw new InvalidArgumentException("Unknown messages ID: $id."); diff --git a/tests/drivers/amqp_interop/QueueTest.php b/tests/drivers/amqp_interop/QueueTest.php index 42b97fd35b..571d17ab05 100644 --- a/tests/drivers/amqp_interop/QueueTest.php +++ b/tests/drivers/amqp_interop/QueueTest.php @@ -9,10 +9,10 @@ use Enqueue\AmqpLib\AmqpConnectionFactory; use Interop\Amqp\AmqpMessage; -use Interop\Amqp\Impl\AmqpMessage as InteropAmqpMessage; +use Interop\Amqp\AmqpQueue; use Interop\Amqp\AmqpTopic; use Interop\Amqp\Impl\AmqpBind; -use Interop\Amqp\AmqpQueue; +use Interop\Amqp\Impl\AmqpMessage as InteropAmqpMessage; use tests\app\PriorityJob; use tests\app\RetryJob; use tests\drivers\CliTestCase; @@ -183,15 +183,6 @@ protected function getQueue(): Queue return Yii::$app->amqpInteropQueue; } - protected function setUp(): void - { - if ('true' == getenv('EXCLUDE_AMQP_INTEROP')) { - $this->markTestSkipped('Amqp tests are disabled for php 5.5'); - } - - parent::setUp(); - } - /** * @param Queue $yiiQueue * @return mixed From b97c89c6c18213b2f4c02cc8d4a90604e0059623 Mon Sep 17 00:00:00 2001 From: Moiseenko Date: Mon, 2 Oct 2023 15:54:41 +0400 Subject: [PATCH 13/48] Removed deprecated AMQP driver --- src/drivers/amqp/Command.php | 43 -------- src/drivers/amqp/Queue.php | 169 ------------------------------- support/ide-helper.php | 2 - tests/app/config/main.php | 13 +-- tests/bootstrap.php | 1 - tests/drivers/amqp/QueueTest.php | 37 ------- tests/yii | 1 - 7 files changed, 2 insertions(+), 264 deletions(-) delete mode 100644 src/drivers/amqp/Command.php delete mode 100644 src/drivers/amqp/Queue.php delete mode 100644 tests/drivers/amqp/QueueTest.php diff --git a/src/drivers/amqp/Command.php b/src/drivers/amqp/Command.php deleted file mode 100644 index 311629430d..0000000000 --- a/src/drivers/amqp/Command.php +++ /dev/null @@ -1,43 +0,0 @@ - - */ -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(); - } -} diff --git a/src/drivers/amqp/Queue.php b/src/drivers/amqp/Queue.php deleted file mode 100644 index 20287b06eb..0000000000 --- a/src/drivers/amqp/Queue.php +++ /dev/null @@ -1,169 +0,0 @@ - - */ -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(): void - { - 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): int - { - 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(); - } -} diff --git a/support/ide-helper.php b/support/ide-helper.php index a41e9494ca..b98390aa97 100644 --- a/support/ide-helper.php +++ b/support/ide-helper.php @@ -3,7 +3,6 @@ declare(strict_types = 1); use yii\BaseYii; -use yii\queue\amqp\Queue as AmqpQueue; use yii\queue\amqp_interop\Queue as AmqpInteropQueue; use yii\queue\beanstalk\Queue as BeanstalkQueue; use yii\queue\file\Queue as FileQueue; @@ -31,7 +30,6 @@ class Yii extends BaseYii * Class BaseApplication * Used for properties that are identical for both WebApplication and ConsoleApplication * - * @property AmqpQueue $amqpQueue * @property AmqpInteropQueue $amqpInteropQueue * @property BeanstalkQueue $beanstalkQueue * @property FileQueue $fileQueue diff --git a/tests/app/config/main.php b/tests/app/config/main.php index 29b16b8f87..8da7675271 100644 --- a/tests/app/config/main.php +++ b/tests/app/config/main.php @@ -2,15 +2,14 @@ $config = [ 'id' => 'yii2-queue-app', 'basePath' => dirname(__DIR__), - 'vendorPath' => dirname(dirname(__DIR__)) . '/vendor', - 'runtimePath' => dirname(dirname(__DIR__)) . '/runtime', + 'vendorPath' => dirname(__DIR__, 2) . '/vendor', + 'runtimePath' => dirname(__DIR__, 2) . '/runtime', 'bootstrap' => [ 'fileQueue', 'mysqlQueue', 'sqliteQueue', 'pgsqlQueue', 'redisQueue', - 'amqpQueue', 'amqpInteropQueue', 'beanstalkQueue', 'stompQueue', @@ -81,14 +80,6 @@ 'redisQueue' => [ 'class' => \yii\queue\redis\Queue::class, ], - 'amqpQueue' => [ - 'class' => \yii\queue\amqp\Queue::class, - 'host' => getenv('RABBITMQ_HOST') ?: 'localhost', - 'user' => getenv('RABBITMQ_USER') ?: 'guest', - 'password' => getenv('RABBITMQ_PASSWORD') ?: 'guest', - 'queueName' => 'queue-basic', - 'exchangeName' => 'exchange-basic', - ], 'amqpInteropQueue' => [ 'class' => \yii\queue\amqp_interop\Queue::class, 'host' => getenv('RABBITMQ_HOST') ?: 'localhost', diff --git a/tests/bootstrap.php b/tests/bootstrap.php index 64cfda50f5..cff0639533 100644 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -8,7 +8,6 @@ require_once(__DIR__ . '/../vendor/yiisoft/yii2/Yii.php'); Yii::setAlias('@yii/queue', dirname(__DIR__) . '/src'); -Yii::setAlias('@yii/queue/amqp', dirname(__DIR__) . '/src/drivers/amqp'); Yii::setAlias('@yii/queue/amqp_interop', dirname(__DIR__) . '/src/drivers/amqp_interop'); Yii::setAlias('@yii/queue/beanstalk', dirname(__DIR__) . '/src/drivers/beanstalk'); Yii::setAlias('@yii/queue/db', dirname(__DIR__) . '/src/drivers/db'); diff --git a/tests/drivers/amqp/QueueTest.php b/tests/drivers/amqp/QueueTest.php deleted file mode 100644 index 81c32aca63..0000000000 --- a/tests/drivers/amqp/QueueTest.php +++ /dev/null @@ -1,37 +0,0 @@ - - */ -class QueueTest extends CliTestCase -{ - /** - * @return Queue - */ - protected function getQueue(): Queue - { - return Yii::$app->amqpQueue; - } - - public function testListen(): void - { - $this->startProcess(['php', 'yii', 'queue/listen']); - $job = $this->createSimpleJob(); - $this->getQueue()->push($job); - - $this->assertSimpleJobDone($job); - } -} diff --git a/tests/yii b/tests/yii index 8a69da60a6..c7c0732dea 100755 --- a/tests/yii +++ b/tests/yii @@ -9,7 +9,6 @@ require(__DIR__ . '/../vendor/autoload.php'); require(__DIR__ . '/../vendor/yiisoft/yii2/Yii.php'); Yii::setAlias('@yii/queue', dirname(__DIR__) . '/src'); -Yii::setAlias('@yii/queue/amqp', dirname(__DIR__) . '/src/drivers/amqp'); Yii::setAlias('@yii/queue/amqp_interop', dirname(__DIR__) . '/src/drivers/amqp_interop'); Yii::setAlias('@yii/queue/beanstalk', dirname(__DIR__) . '/src/drivers/beanstalk'); Yii::setAlias('@yii/queue/db', dirname(__DIR__) . '/src/drivers/db'); From 729d0576f42a3261671ba5d522d2756161b78393 Mon Sep 17 00:00:00 2001 From: Moiseenko Date: Mon, 2 Oct 2023 16:11:17 +0400 Subject: [PATCH 14/48] Added more strict types --- src/drivers/beanstalk/Command.php | 3 +++ src/drivers/beanstalk/InfoAction.php | 6 ++++-- src/drivers/beanstalk/Queue.php | 2 +- src/drivers/db/Command.php | 4 +++- src/drivers/db/InfoAction.php | 6 ++++-- src/drivers/db/Queue.php | 2 +- src/drivers/file/Command.php | 3 +++ src/drivers/file/InfoAction.php | 4 +++- src/drivers/file/Queue.php | 1 - src/drivers/gearman/Command.php | 3 +++ src/drivers/gearman/Queue.php | 12 +++++++----- src/drivers/redis/InfoAction.php | 4 +++- src/drivers/redis/Queue.php | 6 +++--- src/drivers/sqs/Queue.php | 2 +- src/drivers/stomp/Command.php | 3 +++ src/drivers/stomp/Queue.php | 9 ++++----- src/drivers/sync/Queue.php | 14 ++++++-------- 17 files changed, 52 insertions(+), 32 deletions(-) diff --git a/src/drivers/beanstalk/Command.php b/src/drivers/beanstalk/Command.php index 9237a49343..c05a4f6987 100644 --- a/src/drivers/beanstalk/Command.php +++ b/src/drivers/beanstalk/Command.php @@ -1,4 +1,7 @@ format('Statistical information about the tube:', Console::FG_GREEN)); diff --git a/src/drivers/beanstalk/Queue.php b/src/drivers/beanstalk/Queue.php index 6291c51682..6822c6ac13 100644 --- a/src/drivers/beanstalk/Queue.php +++ b/src/drivers/beanstalk/Queue.php @@ -50,7 +50,7 @@ class Queue extends CliQueue * @internal for worker command only. * @since 2.0.2 */ - public function run($repeat, $timeout = 0) + public function run(bool $repeat, int $timeout = 0): ?int { return $this->runWorker(function (callable $canContinue) use ($repeat, $timeout) { while ($canContinue()) { diff --git a/src/drivers/db/Command.php b/src/drivers/db/Command.php index 5aec80b32c..101016a239 100644 --- a/src/drivers/db/Command.php +++ b/src/drivers/db/Command.php @@ -1,4 +1,7 @@ format('Jobs', Console::FG_GREEN)); diff --git a/src/drivers/db/Queue.php b/src/drivers/db/Queue.php index 70f92d262a..e2247a7ee1 100644 --- a/src/drivers/db/Queue.php +++ b/src/drivers/db/Queue.php @@ -73,7 +73,7 @@ public function init(): void * @internal for worker command only * @since 2.0.2 */ - public function run($repeat, $timeout = 0) + public function run(bool $repeat, int $timeout = 0) { return $this->runWorker(function (callable $canContinue) use ($repeat, $timeout) { while ($canContinue()) { diff --git a/src/drivers/file/Command.php b/src/drivers/file/Command.php index 1700632d32..3c15d4ec3c 100644 --- a/src/drivers/file/Command.php +++ b/src/drivers/file/Command.php @@ -1,4 +1,7 @@ runWorker(function (callable $canContinue) use ($repeat) { $worker = new \GearmanWorker(); diff --git a/src/drivers/redis/InfoAction.php b/src/drivers/redis/InfoAction.php index 62d410a25a..f063f22db3 100644 --- a/src/drivers/redis/InfoAction.php +++ b/src/drivers/redis/InfoAction.php @@ -1,4 +1,7 @@ runWorker(function (callable $canContinue) use ($repeat, $timeout) { while ($canContinue()) { if (($payload = $this->reserve($timeout)) !== null) { - list($id, $message, $ttr, $attempt) = $payload; + [$id, $message, $ttr, $attempt] = $payload; if ($this->handleMessage($id, $message, $ttr, $attempt)) { $this->delete($id); } @@ -131,7 +131,7 @@ public function remove($id) * @param int $timeout timeout * @return array|null payload */ - protected function reserve($timeout) + protected function reserve(int $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)) { diff --git a/src/drivers/sqs/Queue.php b/src/drivers/sqs/Queue.php index 219d53258d..96307ef721 100644 --- a/src/drivers/sqs/Queue.php +++ b/src/drivers/sqs/Queue.php @@ -79,7 +79,7 @@ class Queue extends CliQueue * @return null|int exit code. * @internal for worker command only */ - public function run($repeat, $timeout = 0) + public function run(bool $repeat, int $timeout = 0): ?int { return $this->runWorker(function (callable $canContinue) use ($repeat, $timeout) { while ($canContinue()) { diff --git a/src/drivers/stomp/Command.php b/src/drivers/stomp/Command.php index 1079d6daec..c3c2e07c2c 100644 --- a/src/drivers/stomp/Command.php +++ b/src/drivers/stomp/Command.php @@ -1,4 +1,7 @@ runWorker(function (callable $canContinue) use ($repeat, $timeout) { $this->open(); diff --git a/src/drivers/sync/Queue.php b/src/drivers/sync/Queue.php index 0caef050ca..406ccf288d 100644 --- a/src/drivers/sync/Queue.php +++ b/src/drivers/sync/Queue.php @@ -25,25 +25,23 @@ class Queue extends BaseQueue /** * @var bool */ - public $handle = false; - + public bool $handle = false; /** * @var array of payloads */ - private $payloads = []; + private array $payloads = []; /** * @var int last pushed ID */ - private $pushedId = 0; + private int $pushedId = 0; /** * @var int started ID */ - private $startedId = 0; + private int $startedId = 0; /** * @var int last finished ID */ - private $finishedId = 0; - + private int $finishedId = 0; /** * @inheritdoc @@ -66,7 +64,7 @@ public function init(): void public function run() { while (($payload = array_shift($this->payloads)) !== null) { - list($ttr, $message) = $payload; + [$ttr, $message] = $payload; $this->startedId = $this->finishedId + 1; $this->handleMessage($this->startedId, $message, $ttr, 1); $this->finishedId = $this->startedId; From 055a2c2c26f3497814629fa04bf07ddccf695bec Mon Sep 17 00:00:00 2001 From: Moiseenko Date: Mon, 2 Oct 2023 17:16:04 +0400 Subject: [PATCH 15/48] Added more strict types --- src/Queue.php | 25 ++++++++++---------- src/cli/Action.php | 4 +++- src/cli/Command.php | 34 +++++++++++++++------------- src/cli/LoopInterface.php | 5 +++- src/cli/Queue.php | 13 ++++++----- src/cli/SignalLoop.php | 20 ++++++++-------- src/cli/VerboseBehavior.php | 6 +++-- src/cli/WorkerEvent.php | 7 ++++-- src/drivers/amqp_interop/Command.php | 2 +- src/drivers/beanstalk/Command.php | 2 +- src/drivers/db/Command.php | 2 +- src/drivers/file/Command.php | 2 +- src/drivers/file/Queue.php | 2 +- src/drivers/gearman/Command.php | 2 +- src/drivers/redis/Command.php | 2 +- src/drivers/sqs/Command.php | 2 +- src/drivers/stomp/Command.php | 2 +- 17 files changed, 73 insertions(+), 59 deletions(-) diff --git a/src/Queue.php b/src/Queue.php index c85624595d..1116127ee3 100644 --- a/src/Queue.php +++ b/src/Queue.php @@ -72,7 +72,7 @@ abstract class Queue extends Component /** * @var int default time to reserve a job */ - public $ttr = 300; + public int $ttr = 300; /** * @var int default attempt count */ @@ -82,7 +82,6 @@ abstract class Queue extends Component private $pushDelay; private $pushPriority; - /** * @inheritdoc */ @@ -149,9 +148,9 @@ public function priority($value): static * Pushes job into queue. * * @param JobInterface|mixed $job - * @return string|null id of a job message + * @return int|string|null id of a job message */ - public function push($job) + public function push($job): int|string|null { $event = new PushEvent([ 'job' => $job, @@ -227,7 +226,7 @@ public function getWorkerPid() */ protected function handleMessage($id, $message, $ttr, $attempt) { - list($job, $error) = $this->unserializeMessage($message); + [$job, $error] = $this->unserializeMessage($message); $event = new ExecEvent([ 'id' => $id, 'job' => $job, @@ -297,35 +296,35 @@ public function handleError(ExecEvent $event) } /** - * @param string $id of a job message + * @param int|string $id of a job message * @return bool */ - public function isWaiting($id) + public function isWaiting(int|string $id): bool { return $this->status($id) === self::STATUS_WAITING; } /** - * @param string $id of a job message + * @param int|string $id of a job message * @return bool */ - public function isReserved($id) + public function isReserved(int|string $id): bool { return $this->status($id) === self::STATUS_RESERVED; } /** - * @param string $id of a job message + * @param int|string $id of a job message * @return bool */ - public function isDone($id) + public function isDone(int|string $id): bool { return $this->status($id) === self::STATUS_DONE; } /** - * @param string $id of a job message + * @param string|int $id of a job message * @return int status code */ - abstract public function status(string $id): int; + abstract public function status(int|string $id): int; } diff --git a/src/cli/Action.php b/src/cli/Action.php index acfb6ce807..8dc85b6188 100644 --- a/src/cli/Action.php +++ b/src/cli/Action.php @@ -1,4 +1,7 @@ VerboseBehavior::class, ]; /** * @var bool isolate mode. It executes a job in a child process. */ - public $isolate = true; + public bool $isolate = true; /** * @var string path to php interpreter that uses to run child processes. * If it is undefined, PHP_BINARY will be used. @@ -56,11 +59,10 @@ abstract class Command extends Controller */ public $phpBinary; - /** * @inheritdoc */ - public function options($actionID) + public function options($actionID): array { $options = parent::options($actionID); if ($this->canVerbose($actionID)) { @@ -77,7 +79,7 @@ public function options($actionID) /** * @inheritdoc */ - public function optionAliases() + public function optionAliases(): array { return array_merge(parent::optionAliases(), [ 'v' => 'verbose', @@ -95,7 +97,7 @@ abstract protected function isWorkerAction(string $actionID): bool; * @param string $actionID * @return bool */ - protected function canVerbose($actionID) + protected function canVerbose(string $actionID): bool { return $actionID === 'exec' || $this->isWorkerAction($actionID); } @@ -104,7 +106,7 @@ protected function canVerbose($actionID) * @param string $actionID * @return bool */ - protected function canIsolate($actionID) + protected function canIsolate(string $actionID): bool { return $this->isWorkerAction($actionID); } @@ -123,7 +125,7 @@ public function beforeAction($action) $this->phpBinary = PHP_BINARY; } $this->queue->messageHandler = function ($id, $message, $ttr, $attempt) { - return $this->handleMessage($id, $message, $ttr, $attempt); + return $this->handleMessage($id, $message, (int)$ttr, (int)$attempt); }; } @@ -152,15 +154,15 @@ public function actionExec($id, $ttr, $attempt, $pid) /** * Handles message using child process. * - * @param string|null $id of a message + * @param int|string|null $id of a message * @param string $message - * @param int $ttr time to reserve + * @param int|null $ttr time to reserve * @param int $attempt number * @return bool * @throws * @see actionExec() */ - protected function handleMessage($id, $message, $ttr, $attempt) + protected function handleMessage(int|string|null $id, string $message, ?int $ttr, int $attempt) { // Child process command: php yii queue/exec "id" "ttr" "attempt" "pid" $cmd = [ @@ -196,7 +198,7 @@ protected function handleMessage($id, $message, $ttr, $attempt) } return $result === self::EXEC_DONE; } catch (ProcessRuntimeException $error) { - list($job) = $this->queue->unserializeMessage($message); + [$job] = $this->queue->unserializeMessage($message); return $this->queue->handleError(new ExecEvent([ 'id' => $id, 'job' => $job, diff --git a/src/cli/LoopInterface.php b/src/cli/LoopInterface.php index 746f35485f..9742362857 100644 --- a/src/cli/LoopInterface.php +++ b/src/cli/LoopInterface.php @@ -1,4 +1,7 @@ exitCode; } - $exitCode = null; try { call_user_func($handler, function () use ($loop, $event) { $this->trigger(self::EVENT_WORKER_LOOP, $event); diff --git a/src/cli/SignalLoop.php b/src/cli/SignalLoop.php index 3dbcd83dea..9b6dd4ae73 100644 --- a/src/cli/SignalLoop.php +++ b/src/cli/SignalLoop.php @@ -1,4 +1,7 @@ 'beforeExec', diff --git a/src/cli/WorkerEvent.php b/src/cli/WorkerEvent.php index e1ff4cbe2a..eb92a5af15 100644 --- a/src/cli/WorkerEvent.php +++ b/src/cli/WorkerEvent.php @@ -1,4 +1,7 @@ Date: Mon, 2 Oct 2023 20:09:43 +0400 Subject: [PATCH 16/48] Added more strict types --- src/ExecEvent.php | 5 ++++- src/InvalidJobException.php | 10 ++++++---- src/JobEvent.php | 14 +++++++++----- src/JobInterface.php | 5 ++++- src/LogBehavior.php | 8 +++++--- src/PushEvent.php | 5 ++++- src/Queue.php | 26 ++++++++++++++------------ src/RetryableJobInterface.php | 3 +++ src/closure/Job.php | 3 ++- tests/app/PriorityJob.php | 3 ++- tests/app/RetryJob.php | 3 ++- tests/app/SimpleJob.php | 3 ++- tests/app/benchmark/waiting/Job.php | 3 ++- tests/closure/ClosureJob.php | 3 ++- 14 files changed, 61 insertions(+), 33 deletions(-) diff --git a/src/ExecEvent.php b/src/ExecEvent.php index 0689a6ff12..75945cea71 100644 --- a/src/ExecEvent.php +++ b/src/ExecEvent.php @@ -1,4 +1,7 @@ serialized = $serialized; parent::__construct($message, $code, $previous); @@ -40,7 +42,7 @@ public function __construct($serialized, $message = '', $code = 0, Throwable $pr /** * @return string of serialized message that cannot be unserialized to a job */ - final public function getSerialized() + final public function getSerialized(): string { return $this->serialized; } diff --git a/src/JobEvent.php b/src/JobEvent.php index c6c0a041f2..8c56a1db66 100644 --- a/src/JobEvent.php +++ b/src/JobEvent.php @@ -1,4 +1,7 @@ 'afterPush', diff --git a/src/PushEvent.php b/src/PushEvent.php index b4a4949f24..ecf0733514 100644 --- a/src/PushEvent.php +++ b/src/PushEvent.php @@ -1,4 +1,7 @@ retry = $event->attempt < $this->attempts; if ($event->error instanceof InvalidJobException) { diff --git a/src/RetryableJobInterface.php b/src/RetryableJobInterface.php index 40dfe9ccff..08791db777 100644 --- a/src/RetryableJobInterface.php +++ b/src/RetryableJobInterface.php @@ -1,4 +1,7 @@ serialized)->getClosure(); $nativeClosure = $closure(); diff --git a/tests/app/PriorityJob.php b/tests/app/PriorityJob.php index 8cf6c681fc..4dc15dd287 100644 --- a/tests/app/PriorityJob.php +++ b/tests/app/PriorityJob.php @@ -10,6 +10,7 @@ use Yii; use yii\base\BaseObject; use yii\queue\JobInterface; +use yii\queue\Queue; /** * Priority Job. @@ -20,7 +21,7 @@ class PriorityJob extends BaseObject implements JobInterface { public int $number; - public function execute($queue) + public function execute(Queue $queue) { file_put_contents(self::getFileName(), $this->number, FILE_APPEND); } diff --git a/tests/app/RetryJob.php b/tests/app/RetryJob.php index 0830c5bc6b..2e60b66e9f 100644 --- a/tests/app/RetryJob.php +++ b/tests/app/RetryJob.php @@ -9,6 +9,7 @@ use Yii; use yii\base\BaseObject; +use yii\queue\Queue; use yii\queue\RetryableJobInterface; /** @@ -20,7 +21,7 @@ class RetryJob extends BaseObject implements RetryableJobInterface { public $uid; - public function execute($queue) + public function execute(Queue $queue) { file_put_contents($this->getFileName(), 'a', FILE_APPEND); throw new \Exception('Planned error.'); diff --git a/tests/app/SimpleJob.php b/tests/app/SimpleJob.php index 1e0d54b10f..72ba65eb96 100644 --- a/tests/app/SimpleJob.php +++ b/tests/app/SimpleJob.php @@ -10,6 +10,7 @@ use Yii; use yii\base\BaseObject; use yii\queue\JobInterface; +use yii\queue\Queue; /** * Simple Job. @@ -20,7 +21,7 @@ class SimpleJob extends BaseObject implements JobInterface { public string $uid; - public function execute($queue) + public function execute(Queue $queue) { file_put_contents($this->getFileName(), ''); } diff --git a/tests/app/benchmark/waiting/Job.php b/tests/app/benchmark/waiting/Job.php index 670c7cee92..e96c7219c7 100644 --- a/tests/app/benchmark/waiting/Job.php +++ b/tests/app/benchmark/waiting/Job.php @@ -9,6 +9,7 @@ use yii\base\BaseObject; use yii\queue\JobInterface; +use yii\queue\Queue; /** * The job calculates waiting time. @@ -22,7 +23,7 @@ class Job extends BaseObject implements JobInterface public $lockFileName; public $payload; - public function execute($queue) + public function execute(Queue $queue) { $waitingTime = microtime(true) - $this->pushedAt; if (file_exists($this->lockFileName)) { diff --git a/tests/closure/ClosureJob.php b/tests/closure/ClosureJob.php index 471d0c5266..a858c1080f 100644 --- a/tests/closure/ClosureJob.php +++ b/tests/closure/ClosureJob.php @@ -7,6 +7,7 @@ use Closure; use yii\base\BaseObject; use yii\queue\JobInterface; +use yii\queue\Queue; /** * Closure Job. @@ -20,7 +21,7 @@ class ClosureJob extends BaseObject implements JobInterface */ public $closure; - public function execute($queue) + public function execute(Queue $queue) { call_user_func($this->closure); } From 17f21bef6f7e2f81ee3993882f343fd1d25c5cce Mon Sep 17 00:00:00 2001 From: Moiseenko Date: Mon, 2 Oct 2023 20:17:29 +0400 Subject: [PATCH 17/48] Removed deprecated Job interface --- src/Job.php | 19 ------------------- 1 file changed, 19 deletions(-) delete mode 100644 src/Job.php diff --git a/src/Job.php b/src/Job.php deleted file mode 100644 index 45bab7ba9c..0000000000 --- a/src/Job.php +++ /dev/null @@ -1,19 +0,0 @@ - - */ -interface Job extends JobInterface -{ -} From f994f0fbe2947945ef7cc383f1dfe4ec0fabfd1b Mon Sep 17 00:00:00 2001 From: Moiseenko Date: Mon, 2 Oct 2023 20:45:47 +0400 Subject: [PATCH 18/48] Added more strict types --- src/debug/Panel.php | 4 +- src/debug/views/detail.php | 3 + src/debug/views/summary.php | 4 +- src/drivers/amqp_interop/Command.php | 3 +- src/drivers/beanstalk/Command.php | 3 +- src/drivers/db/Command.php | 3 +- .../db/migrations/M161119140200Queue.php | 10 ++-- .../db/migrations/M170307170300Later.php | 16 ++++-- .../db/migrations/M170509001400Retry.php | 10 ++-- .../db/migrations/M170601155600Priority.php | 16 ++++-- .../migrations/M211218163000JobQueueSize.php | 10 ++-- src/drivers/file/Command.php | 3 +- src/drivers/redis/Command.php | 3 +- src/drivers/sqs/Command.php | 3 +- src/drivers/stomp/Command.php | 3 +- src/gii/Generator.php | 4 +- src/gii/default/job.php | 5 +- src/gii/form.php | 3 + src/serializers/IgbinarySerializer.php | 3 + src/serializers/JsonSerializer.php | 3 + src/serializers/PhpSerializer.php | 3 + src/serializers/SerializerInterface.php | 3 + tests/app/PriorityJob.php | 3 + tests/app/RetryJob.php | 3 + tests/app/SimpleJob.php | 3 + tests/app/config/console.php | 14 +++-- tests/app/config/main.php | 56 ++++++++++++------- tests/bootstrap.php | 2 + tests/drivers/amqp_interop/QueueTest.php | 3 + tests/drivers/beanstalk/QueueTest.php | 3 + tests/drivers/db/MysqlQueueTest.php | 3 + tests/drivers/db/PgsqlQueueTest.php | 3 + tests/drivers/db/SqliteQueueTest.php | 3 + tests/drivers/db/TestCase.php | 3 + tests/drivers/file/QueueTest.php | 3 + tests/drivers/gearman/QueueTest.php | 3 + tests/drivers/redis/QueueTest.php | 3 + tests/drivers/sqs/FifoQueueTest.php | 3 + tests/drivers/sqs/QueueTest.php | 3 + tests/drivers/stomp/QueueTest.php | 4 +- 40 files changed, 179 insertions(+), 57 deletions(-) diff --git a/src/debug/Panel.php b/src/debug/Panel.php index 7cb0511391..11bee1130e 100644 --- a/src/debug/Panel.php +++ b/src/debug/Panel.php @@ -1,4 +1,7 @@ - diff --git a/src/drivers/amqp_interop/Command.php b/src/drivers/amqp_interop/Command.php index cf162d38da..e1bbe5ad9d 100644 --- a/src/drivers/amqp_interop/Command.php +++ b/src/drivers/amqp_interop/Command.php @@ -11,6 +11,7 @@ namespace yii\queue\amqp_interop; use yii\queue\cli\Command as CliCommand; +use yii\queue\cli\Queue as CliQueue; /** * Manages application amqp-queue. @@ -23,7 +24,7 @@ class Command extends CliCommand /** * @var Queue */ - public \yii\queue\cli\Queue $queue; + public CliQueue $queue; /** * @inheritdoc diff --git a/src/drivers/beanstalk/Command.php b/src/drivers/beanstalk/Command.php index d9936cc784..bcd843cefd 100644 --- a/src/drivers/beanstalk/Command.php +++ b/src/drivers/beanstalk/Command.php @@ -12,6 +12,7 @@ use yii\console\Exception; use yii\queue\cli\Command as CliCommand; +use yii\queue\cli\Queue as CliQueue; /** * Manages application beanstalk-queue. @@ -23,7 +24,7 @@ class Command extends CliCommand /** * @var Queue */ - public \yii\queue\cli\Queue $queue; + public CliQueue $queue; /** * @var string */ diff --git a/src/drivers/db/Command.php b/src/drivers/db/Command.php index 6a4f63ffc4..04047ce821 100644 --- a/src/drivers/db/Command.php +++ b/src/drivers/db/Command.php @@ -12,6 +12,7 @@ use yii\console\Exception; use yii\queue\cli\Command as CliCommand; +use yii\queue\cli\Queue as CliQueue; /** * Manages application db-queue. @@ -23,7 +24,7 @@ class Command extends CliCommand /** * @var Queue */ - public \yii\queue\cli\Queue $queue; + public CliQueue $queue; /** * @var string */ diff --git a/src/drivers/db/migrations/M161119140200Queue.php b/src/drivers/db/migrations/M161119140200Queue.php index 30dfa861c0..9db693284a 100644 --- a/src/drivers/db/migrations/M161119140200Queue.php +++ b/src/drivers/db/migrations/M161119140200Queue.php @@ -1,4 +1,7 @@ createTable($this->tableName, [ 'id' => $this->primaryKey(), @@ -35,7 +37,7 @@ public function up() $this->createIndex('started_at', $this->tableName, 'started_at'); } - public function down() + public function down(): void { $this->dropTable($this->tableName); } diff --git a/src/drivers/db/migrations/M170307170300Later.php b/src/drivers/db/migrations/M170307170300Later.php index 3d39d44044..0468806d64 100644 --- a/src/drivers/db/migrations/M170307170300Later.php +++ b/src/drivers/db/migrations/M170307170300Later.php @@ -1,4 +1,7 @@ addColumn($this->tableName, 'timeout', $this->integer()->defaultValue(0)->notNull()->after('created_at')); + $this->addColumn( + $this->tableName, + 'timeout', + $this->integer()->defaultValue(0)->notNull()->after('created_at') + ); } - public function down() + public function down(): void { $this->dropColumn($this->tableName, 'timeout'); } diff --git a/src/drivers/db/migrations/M170509001400Retry.php b/src/drivers/db/migrations/M170509001400Retry.php index 9b232b2542..1d642d293b 100644 --- a/src/drivers/db/migrations/M170509001400Retry.php +++ b/src/drivers/db/migrations/M170509001400Retry.php @@ -1,4 +1,7 @@ db->driverName !== 'sqlite') { $this->renameColumn($this->tableName, 'created_at', 'pushed_at'); @@ -48,7 +50,7 @@ public function up() } } - public function down() + public function down(): void { if ($this->db->driverName !== 'sqlite') { $this->renameColumn($this->tableName, 'done_at', 'finished_at'); diff --git a/src/drivers/db/migrations/M170601155600Priority.php b/src/drivers/db/migrations/M170601155600Priority.php index bfa98c6b13..cf8751e820 100644 --- a/src/drivers/db/migrations/M170601155600Priority.php +++ b/src/drivers/db/migrations/M170601155600Priority.php @@ -1,4 +1,7 @@ addColumn($this->tableName, 'priority', $this->integer()->unsigned()->notNull()->defaultValue(1024)->after('delay')); + $this->addColumn( + $this->tableName, + 'priority', + $this->integer()->unsigned()->notNull()->defaultValue(1024)->after('delay') + ); $this->createIndex('priority', $this->tableName, 'priority'); } - public function down() + public function down(): void { $this->dropIndex('priority', $this->tableName); $this->dropColumn($this->tableName, 'priority'); diff --git a/src/drivers/db/migrations/M211218163000JobQueueSize.php b/src/drivers/db/migrations/M211218163000JobQueueSize.php index 13fda75268..db9e259c60 100644 --- a/src/drivers/db/migrations/M211218163000JobQueueSize.php +++ b/src/drivers/db/migrations/M211218163000JobQueueSize.php @@ -1,4 +1,7 @@ db->driverName === 'mysql') { $this->alterColumn('{{%queue}}', 'job', 'LONGBLOB NOT NULL'); } } - public function down() + public function down(): void { if ($this->db->driverName === 'mysql') { $this->alterColumn('{{%queue}}', 'job', $this->binary()->notNull()); diff --git a/src/drivers/file/Command.php b/src/drivers/file/Command.php index 26e92648a1..a7dbe26834 100644 --- a/src/drivers/file/Command.php +++ b/src/drivers/file/Command.php @@ -12,6 +12,7 @@ use yii\console\Exception; use yii\queue\cli\Command as CliCommand; +use yii\queue\cli\Queue as CliQueue; /** * Manages application file-queue. @@ -23,7 +24,7 @@ class Command extends CliCommand /** * @var Queue */ - public \yii\queue\cli\Queue $queue; + public CliQueue $queue; /** * @var string */ diff --git a/src/drivers/redis/Command.php b/src/drivers/redis/Command.php index b5cbbc1574..380f7967fb 100644 --- a/src/drivers/redis/Command.php +++ b/src/drivers/redis/Command.php @@ -12,6 +12,7 @@ use yii\console\Exception; use yii\queue\cli\Command as CliCommand; +use yii\queue\cli\Queue as CliQueue; /** * Manages application redis-queue. @@ -23,7 +24,7 @@ class Command extends CliCommand /** * @var Queue */ - public \yii\queue\cli\Queue $queue; + public CliQueue $queue; /** * @var string */ diff --git a/src/drivers/sqs/Command.php b/src/drivers/sqs/Command.php index e4c6641166..5bd14c529a 100644 --- a/src/drivers/sqs/Command.php +++ b/src/drivers/sqs/Command.php @@ -12,6 +12,7 @@ use yii\console\Exception; use yii\queue\cli\Command as CliCommand; +use yii\queue\cli\Queue as CliQueue; /** * Manages application aws sqs-queue. @@ -24,7 +25,7 @@ class Command extends CliCommand /** * @var Queue */ - public \yii\queue\cli\Queue $queue; + public CliQueue $queue; /** * Runs all jobs from sqs. diff --git a/src/drivers/stomp/Command.php b/src/drivers/stomp/Command.php index b25620f626..076691a949 100644 --- a/src/drivers/stomp/Command.php +++ b/src/drivers/stomp/Command.php @@ -12,6 +12,7 @@ use yii\console\Exception; use yii\queue\cli\Command as CliCommand; +use yii\queue\cli\Queue as CliQueue; /** * Manages application stomp-queue. @@ -24,7 +25,7 @@ class Command extends CliCommand /** * @var Queue */ - public \yii\queue\cli\Queue $queue; + public CliQueue $queue; /** * @inheritdoc diff --git a/src/gii/Generator.php b/src/gii/Generator.php index 7bd1e8002d..a07fd4414e 100644 --- a/src/gii/Generator.php +++ b/src/gii/Generator.php @@ -1,4 +1,7 @@ [ 'mysql-migrate' => [ - 'class' => \yii\console\controllers\MigrateController::class, + 'class' => MigrateController::class, 'db' => 'mysql', 'migrationPath' => null, 'migrationNamespaces' => [ @@ -10,7 +16,7 @@ ], ], 'sqlite-migrate' => [ - 'class' => \yii\console\controllers\MigrateController::class, + 'class' => MigrateController::class, 'db' => 'sqlite', 'migrationPath' => null, 'migrationNamespaces' => [ @@ -18,13 +24,13 @@ ], ], 'pgsql-migrate' => [ - 'class' => \yii\console\controllers\MigrateController::class, + 'class' => MigrateController::class, 'db' => 'pgsql', 'migrationPath' => null, 'migrationNamespaces' => [ 'yii\queue\db\migrations', ], ], - 'benchmark' => \tests\app\benchmark\Controller::class, + 'benchmark' => Controller::class, ], ]; diff --git a/tests/app/config/main.php b/tests/app/config/main.php index 8da7675271..c908bfd037 100644 --- a/tests/app/config/main.php +++ b/tests/app/config/main.php @@ -1,4 +1,22 @@ 'yii2-queue-app', 'basePath' => dirname(__DIR__), @@ -16,13 +34,13 @@ ], 'components' => [ 'syncQueue' => [ - 'class' => \yii\queue\sync\Queue::class, + 'class' => SyncQueue::class, ], 'fileQueue' => [ - 'class' => \yii\queue\file\Queue::class, + 'class' => FileQueue::class, ], 'mysql' => [ - 'class' => \yii\db\Connection::class, + 'class' => Connection::class, 'dsn' => sprintf( 'mysql:host=%s;dbname=%s', getenv('MYSQL_HOST') ?: 'localhost', @@ -36,24 +54,24 @@ ], ], 'mysqlQueue' => [ - 'class' => \yii\queue\db\Queue::class, + 'class' => DbQueue::class, 'db' => 'mysql', 'mutex' => [ - 'class' => \yii\mutex\MysqlMutex::class, + 'class' => MysqlMutex::class, 'db' => 'mysql', ], ], 'sqlite' => [ - 'class' => \yii\db\Connection::class, + 'class' => Connection::class, 'dsn' => 'sqlite:@runtime/yii2_queue_test.db', ], 'sqliteQueue' => [ - 'class' => \yii\queue\db\Queue::class, + 'class' => DbQueue::class, 'db' => 'sqlite', - 'mutex' => \yii\mutex\FileMutex::class, + 'mutex' => FileMutex::class, ], 'pgsql' => [ - 'class' => \yii\db\Connection::class, + 'class' => Connection::class, 'dsn' => sprintf( 'pgsql:host=%s;dbname=%s', getenv('POSTGRES_HOST') ?: 'localhost', @@ -64,24 +82,24 @@ 'charset' => 'utf8', ], 'pgsqlQueue' => [ - 'class' => \yii\queue\db\Queue::class, + 'class' => DbQueue::class, 'db' => 'pgsql', 'mutex' => [ - 'class' => \yii\mutex\PgsqlMutex::class, + 'class' => PgsqlMutex::class, 'db' => 'pgsql', ], 'mutexTimeout' => 0, ], 'redis' => [ - 'class' => \yii\redis\Connection::class, + 'class' => RedisConnection::class, 'hostname' => getenv('REDIS_HOST') ?: 'localhost', 'database' => getenv('REDIS_DB') ?: 1, ], 'redisQueue' => [ - 'class' => \yii\queue\redis\Queue::class, + 'class' => RedisQueue::class, ], 'amqpInteropQueue' => [ - 'class' => \yii\queue\amqp_interop\Queue::class, + 'class' => AmqpInteropQueue::class, 'host' => getenv('RABBITMQ_HOST') ?: 'localhost', 'user' => getenv('RABBITMQ_USER') ?: 'guest', 'password' => getenv('RABBITMQ_PASSWORD') ?: 'guest', @@ -90,11 +108,11 @@ 'exchangeName' => 'exchange-interop', ], 'beanstalkQueue' => [ - 'class' => \yii\queue\beanstalk\Queue::class, + 'class' => BeanstalkQueue::class, 'host' => getenv('BEANSTALK_HOST') ?: 'localhost', ], 'stompQueue' => [ - 'class' => \yii\queue\stomp\Queue::class, + 'class' => StompQueue::class, 'host' => getenv('ACTIVEMQ_HOST') ?: 'localhost', ], ], @@ -103,7 +121,7 @@ if (defined('GEARMAN_SUCCESS')) { $config['bootstrap'][] = 'gearmanQueue'; $config['components']['gearmanQueue'] = [ - 'class' => \yii\queue\gearman\Queue::class, + 'class' => GearmanQueue::class, 'host' => getenv('GEARMAN_HOST') ?: 'localhost', ]; } @@ -111,7 +129,7 @@ if (getenv('AWS_SQS_ENABLED')) { $config['bootstrap'][] = 'sqsQueue'; $config['components']['sqsQueue'] = [ - 'class' => \yii\queue\sqs\Queue::class, + 'class' => SqsQueue::class, 'url' => getenv('AWS_SQS_URL'), 'key' => getenv('AWS_KEY'), 'secret' => getenv('AWS_SECRET'), @@ -122,7 +140,7 @@ if (getenv('AWS_SQS_FIFO_ENABLED')) { $config['bootstrap'][] = 'sqsFifoQueue'; $config['components']['sqsFifoQueue'] = [ - 'class' => \yii\queue\sqs\Queue::class, + 'class' => SqsQueue::class, 'url' => getenv('AWS_SQS_FIFO_URL'), 'key' => getenv('AWS_KEY'), 'secret' => getenv('AWS_SECRET'), diff --git a/tests/bootstrap.php b/tests/bootstrap.php index cff0639533..0b388ae229 100644 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -1,5 +1,7 @@ Date: Mon, 2 Oct 2023 20:51:06 +0400 Subject: [PATCH 19/48] Removed deprecated Serializer interface --- src/serializers/Serializer.php | 19 ------------------- 1 file changed, 19 deletions(-) delete mode 100644 src/serializers/Serializer.php diff --git a/src/serializers/Serializer.php b/src/serializers/Serializer.php deleted file mode 100644 index 119c7b8bef..0000000000 --- a/src/serializers/Serializer.php +++ /dev/null @@ -1,19 +0,0 @@ - - */ -interface Serializer extends SerializerInterface -{ -} From 7882b596a8a1d3222b2dc67b3e363363993b094b Mon Sep 17 00:00:00 2001 From: Moiseenko Date: Mon, 2 Oct 2023 21:05:12 +0400 Subject: [PATCH 20/48] Added more strict types --- src/serializers/IgbinarySerializer.php | 2 +- src/serializers/JsonSerializer.php | 3 +-- src/serializers/PhpSerializer.php | 2 +- src/serializers/SerializerInterface.php | 2 +- 4 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/serializers/IgbinarySerializer.php b/src/serializers/IgbinarySerializer.php index e93e2143d0..15fb9bda4a 100644 --- a/src/serializers/IgbinarySerializer.php +++ b/src/serializers/IgbinarySerializer.php @@ -25,7 +25,7 @@ class IgbinarySerializer extends BaseObject implements SerializerInterface /** * @inheritdoc */ - public function serialize($job) + public function serialize($job): string { return igbinary_serialize($job); } diff --git a/src/serializers/JsonSerializer.php b/src/serializers/JsonSerializer.php index 7bc6cf25bd..2500263db2 100644 --- a/src/serializers/JsonSerializer.php +++ b/src/serializers/JsonSerializer.php @@ -31,11 +31,10 @@ class JsonSerializer extends BaseObject implements SerializerInterface */ public $options = 0; - /** * @inheritdoc */ - public function serialize($job) + public function serialize($job): string { return Json::encode($this->toArray($job), $this->options); } diff --git a/src/serializers/PhpSerializer.php b/src/serializers/PhpSerializer.php index c768482207..d4fb4bc7c5 100644 --- a/src/serializers/PhpSerializer.php +++ b/src/serializers/PhpSerializer.php @@ -22,7 +22,7 @@ class PhpSerializer extends BaseObject implements SerializerInterface /** * @inheritdoc */ - public function serialize($job) + public function serialize($job): string { return serialize($job); } diff --git a/src/serializers/SerializerInterface.php b/src/serializers/SerializerInterface.php index 5b019e0f13..d34faad5b7 100644 --- a/src/serializers/SerializerInterface.php +++ b/src/serializers/SerializerInterface.php @@ -23,7 +23,7 @@ interface SerializerInterface * @param JobInterface|mixed $job * @return string */ - public function serialize($job); + public function serialize($job): string; /** * @param string $serialized From 9df1db4844fdcc7d25bb52e537db8b9d61ab2e5b Mon Sep 17 00:00:00 2001 From: Moiseenko Date: Mon, 2 Oct 2023 21:06:49 +0400 Subject: [PATCH 21/48] Removed deprecated RetryableJob interface --- src/RetryableJob.php | 19 ------------------- 1 file changed, 19 deletions(-) delete mode 100644 src/RetryableJob.php diff --git a/src/RetryableJob.php b/src/RetryableJob.php deleted file mode 100644 index 0641457b06..0000000000 --- a/src/RetryableJob.php +++ /dev/null @@ -1,19 +0,0 @@ - - */ -interface RetryableJob extends RetryableJobInterface -{ -} From f93677c2f2e5418cf0fa3a993d8aa0d797464a92 Mon Sep 17 00:00:00 2001 From: Moiseenko Date: Mon, 2 Oct 2023 21:09:57 +0400 Subject: [PATCH 22/48] Removed deprecated Signal class --- src/cli/Signal.php | 60 ---------------------------------------------- 1 file changed, 60 deletions(-) delete mode 100644 src/cli/Signal.php diff --git a/src/cli/Signal.php b/src/cli/Signal.php deleted file mode 100644 index cd3a8547f4..0000000000 --- a/src/cli/Signal.php +++ /dev/null @@ -1,60 +0,0 @@ - - */ -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; - } -} From 105d79cdadb09ecd9d9762ca25718592d2c19c58 Mon Sep 17 00:00:00 2001 From: Moiseenko Date: Mon, 2 Oct 2023 21:10:15 +0400 Subject: [PATCH 23/48] Removed deprecated Verbose class --- src/cli/Verbose.php | 19 ------------------- 1 file changed, 19 deletions(-) delete mode 100644 src/cli/Verbose.php diff --git a/src/cli/Verbose.php b/src/cli/Verbose.php deleted file mode 100644 index c17c9a0278..0000000000 --- a/src/cli/Verbose.php +++ /dev/null @@ -1,19 +0,0 @@ - - */ -class Verbose extends VerboseBehavior -{ -} From 1e8cd64f3db6c5f703f589e738a564df111eb8a2 Mon Sep 17 00:00:00 2001 From: Moiseenko Date: Mon, 2 Oct 2023 21:25:30 +0400 Subject: [PATCH 24/48] Added more strict types --- src/cli/Action.php | 2 +- src/drivers/beanstalk/InfoAction.php | 3 ++- src/drivers/db/InfoAction.php | 3 ++- src/drivers/file/InfoAction.php | 3 ++- src/drivers/redis/InfoAction.php | 3 ++- src/drivers/sqs/Queue.php | 26 +++++++++++++------------- support/ide-helper.php | 1 + 7 files changed, 23 insertions(+), 18 deletions(-) diff --git a/src/cli/Action.php b/src/cli/Action.php index 8dc85b6188..0b709914a7 100644 --- a/src/cli/Action.php +++ b/src/cli/Action.php @@ -24,7 +24,7 @@ abstract class Action extends BaseAction /** * @var Queue */ - public $queue; + public Queue $queue; /** * @var Command|ConsoleController */ diff --git a/src/drivers/beanstalk/InfoAction.php b/src/drivers/beanstalk/InfoAction.php index 31fa8725f0..c8951f2822 100644 --- a/src/drivers/beanstalk/InfoAction.php +++ b/src/drivers/beanstalk/InfoAction.php @@ -12,6 +12,7 @@ use yii\helpers\Console; use yii\queue\cli\Action; +use yii\queue\cli\Queue as CliQueue; /** * Info about queue status. @@ -23,7 +24,7 @@ class InfoAction extends Action /** * @var Queue */ - public $queue; + public CliQueue $queue; /** * Info about queue status. diff --git a/src/drivers/db/InfoAction.php b/src/drivers/db/InfoAction.php index 02b9ca6406..c0859e0432 100644 --- a/src/drivers/db/InfoAction.php +++ b/src/drivers/db/InfoAction.php @@ -13,6 +13,7 @@ use yii\db\Query; use yii\helpers\Console; use yii\queue\cli\Action; +use yii\queue\cli\Queue as CliQueue; /** * Info about queue status. @@ -24,7 +25,7 @@ class InfoAction extends Action /** * @var Queue */ - public $queue; + public CliQueue $queue; /** * Info about queue status. diff --git a/src/drivers/file/InfoAction.php b/src/drivers/file/InfoAction.php index 0edb6cfcc5..3a50d89dff 100644 --- a/src/drivers/file/InfoAction.php +++ b/src/drivers/file/InfoAction.php @@ -12,6 +12,7 @@ use yii\helpers\Console; use yii\queue\cli\Action; +use yii\queue\cli\Queue as CliQueue; /** * Info about queue status. @@ -23,7 +24,7 @@ class InfoAction extends Action /** * @var Queue */ - public $queue; + public CliQueue $queue; /** * Info about queue status. diff --git a/src/drivers/redis/InfoAction.php b/src/drivers/redis/InfoAction.php index f063f22db3..38a504e73f 100644 --- a/src/drivers/redis/InfoAction.php +++ b/src/drivers/redis/InfoAction.php @@ -12,6 +12,7 @@ use yii\helpers\Console; use yii\queue\cli\Action; +use yii\queue\cli\Queue as CliQueue; /** * Info about queue status. @@ -23,7 +24,7 @@ class InfoAction extends Action /** * @var Queue */ - public $queue; + public CliQueue $queue; /** * Info about queue status. diff --git a/src/drivers/sqs/Queue.php b/src/drivers/sqs/Queue.php index 96307ef721..e5e7134ede 100644 --- a/src/drivers/sqs/Queue.php +++ b/src/drivers/sqs/Queue.php @@ -28,33 +28,33 @@ class Queue extends CliQueue * The SQS url. * @var string */ - public $url; + public string $url; /** * aws access key. * @var string|null */ - public $key; + public ?string $key; /** * aws secret. * @var string|null */ - public $secret; + public ?string $secret; /** * region where queue is hosted. * @var string */ - public $region = ''; + public string $region = ''; /** * API version. * @var string */ - public $version = 'latest'; + public string $version = 'latest'; /** * Message Group ID for FIFO queues. * @var string * @since 2.2.1 */ - public $messageGroupId = 'default'; + public string $messageGroupId = 'default'; /** * @var string command class name * @inheritdoc @@ -69,7 +69,7 @@ class Queue extends CliQueue /** * @var SqsClient */ - private $_client; + private SqsClient $_client; /** * Listens queue and runs each job. @@ -104,7 +104,7 @@ public function run(bool $repeat, int $timeout = 0): ?int * @param int $timeout number of seconds for long polling. Must be between 0 and 20. * @return null|array payload. */ - protected function reserve($timeout) + protected function reserve(int $timeout): ?array { $response = $this->getClient()->receiveMessage([ 'QueueUrl' => $this->url, @@ -121,7 +121,7 @@ protected function reserve($timeout) $payload = reset($response['Messages']); $ttr = (int) $payload['MessageAttributes']['TTR']['StringValue']; - if ($ttr != $this->ttr) { + if ($ttr !== $this->ttr) { $this->getClient()->changeMessageVisibility([ 'QueueUrl' => $this->url, 'ReceiptHandle' => $payload['ReceiptHandle'], @@ -137,7 +137,7 @@ protected function reserve($timeout) * * @param array $payload */ - protected function delete($payload) + protected function delete(array $payload): void { $this->getClient()->deleteMessage([ 'QueueUrl' => $this->url, @@ -148,7 +148,7 @@ protected function delete($payload) /** * Clears the queue. */ - public function clear() + public function clear(): void { $this->getClient()->purgeQueue([ 'QueueUrl' => $this->url, @@ -209,9 +209,9 @@ protected function pushMessage($message, $ttr, $delay, $priority) } /** - * @return \Aws\Sqs\SqsClient + * @return SqsClient */ - protected function getClient() + protected function getClient(): SqsClient { if ($this->_client) { return $this->_client; diff --git a/support/ide-helper.php b/support/ide-helper.php index b98390aa97..9488fa7f77 100644 --- a/support/ide-helper.php +++ b/support/ide-helper.php @@ -38,6 +38,7 @@ class Yii extends BaseYii * @property StompQueue $stompQueue * @property SyncQueue $syncQueue * @property SqsQueue $sqsQueue + * @property SqsQueue $sqsFifoQueue */ abstract class BaseApplication extends yii\base\Application { From c06aba8e4d4243d41ddf980c39e952acdf03044a Mon Sep 17 00:00:00 2001 From: Moiseenko Date: Mon, 2 Oct 2023 21:38:25 +0400 Subject: [PATCH 25/48] Removed deprecated Dockerfile --- tests/docker/php/5.6/Dockerfile | 30 ------ tests/docker/php/7.0/Dockerfile | 39 ------- tests/docker/php/7.1/Dockerfile | 29 ------ tests/docker/php/7.2/Dockerfile | 29 ------ tests/docker/php/7.3/Dockerfile | 29 ------ tests/docker/php/7.4/Dockerfile | 18 ---- tests/docker/php/8.0/Dockerfile | 17 --- tests/docker/wait-for-it.sh | 178 -------------------------------- 8 files changed, 369 deletions(-) delete mode 100644 tests/docker/php/5.6/Dockerfile delete mode 100644 tests/docker/php/7.0/Dockerfile delete mode 100644 tests/docker/php/7.1/Dockerfile delete mode 100644 tests/docker/php/7.2/Dockerfile delete mode 100644 tests/docker/php/7.3/Dockerfile delete mode 100644 tests/docker/php/7.4/Dockerfile delete mode 100644 tests/docker/php/8.0/Dockerfile delete mode 100755 tests/docker/wait-for-it.sh diff --git a/tests/docker/php/5.6/Dockerfile b/tests/docker/php/5.6/Dockerfile deleted file mode 100644 index ef57421532..0000000000 --- a/tests/docker/php/5.6/Dockerfile +++ /dev/null @@ -1,30 +0,0 @@ -FROM amd64/php:5.6.40-cli-stretch - -RUN sed -i s/deb.debian.org/archive.debian.org/g /etc/apt/sources.list \ - && sed -i 's|security.debian.org|archive.debian.org|g' /etc/apt/sources.list \ - && sed -i '/stretch-updates/d' /etc/apt/sources.list - -RUN apt-get update -qq \ - && apt install -y ca-certificates \ - && sed -i '/^mozilla\/DST_Root_CA_X3.crt$/ s/^/!/' /etc/ca-certificates.conf \ - && update-ca-certificates \ - && rm -rf /var/lib/apt/lists/* - -RUN apt-get update \ - && apt-get install -y unzip curl zlib1g-dev libicu-dev libpq-dev libgearman-dev - -RUN docker-php-ext-install zip pcntl bcmath pdo_mysql intl pdo_pgsql - -RUN pecl install igbinary-2.0.8 gearman-1.1.2 \ - && docker-php-ext-enable gearman igbinary - -RUN rm -rf /var/lib/apt/lists/* - -COPY --from=cytopia/php-cs-fixer:2-php5.6 /usr/bin/php-cs-fixer /usr/local/bin/php-cs-fixer -COPY --from=composer:lts /usr/bin/composer /usr/local/bin/composer - -COPY . /code -WORKDIR /code - -ENTRYPOINT ["tests/docker/php/entrypoint.sh"] -CMD ["sleep", "infinity"] diff --git a/tests/docker/php/7.0/Dockerfile b/tests/docker/php/7.0/Dockerfile deleted file mode 100644 index 7c2902e468..0000000000 --- a/tests/docker/php/7.0/Dockerfile +++ /dev/null @@ -1,39 +0,0 @@ -FROM amd64/php:7.0.33-cli-stretch - -RUN sed -i s/deb.debian.org/archive.debian.org/g /etc/apt/sources.list \ - && sed -i 's|security.debian.org|archive.debian.org|g' /etc/apt/sources.list \ - && sed -i '/stretch-updates/d' /etc/apt/sources.list - -RUN apt update -qq \ - && apt install -y ca-certificates \ - && sed -i '/^mozilla\/DST_Root_CA_X3.crt$/ s/^/!/' /etc/ca-certificates.conf \ - && update-ca-certificates \ - && rm -rf /var/lib/apt/lists/* - -RUN apt-get update \ - && apt-get install -y unzip curl zlib1g-dev libicu-dev libpq-dev libgearman-dev - -RUN docker-php-ext-install zip pcntl bcmath pdo_mysql intl pdo_pgsql - -RUN pecl install igbinary \ - && docker-php-ext-enable igbinary - -RUN TMPDIR=$(mktemp -d) \ - && cd $TMPDIR \ - && curl -L https://github.com/wcgallego/pecl-gearman/archive/gearman-2.0.3.tar.gz | tar xzv --strip 1 \ - && phpize \ - && ./configure \ - && make -j$(nproc) \ - && make install \ - && cd - \ - && rm -r $TMPDIR \ - && docker-php-ext-enable gearman - -COPY --from=cytopia/php-cs-fixer:2-php7.0 /usr/bin/php-cs-fixer /usr/local/bin/php-cs-fixer -COPY --from=composer:lts /usr/bin/composer /usr/local/bin/composer - -COPY . /code -WORKDIR /code - -ENTRYPOINT ["tests/docker/php/entrypoint.sh"] -CMD ["sleep", "infinity"] diff --git a/tests/docker/php/7.1/Dockerfile b/tests/docker/php/7.1/Dockerfile deleted file mode 100644 index 7227164151..0000000000 --- a/tests/docker/php/7.1/Dockerfile +++ /dev/null @@ -1,29 +0,0 @@ -FROM php:7.1-cli - -RUN apt-get update \ - && apt-get install -y unzip curl zlib1g-dev libicu-dev libpq-dev libgearman-dev - -RUN docker-php-ext-install zip pcntl bcmath pdo_mysql intl pdo_pgsql - -RUN pecl install igbinary \ - && docker-php-ext-enable igbinary - -RUN TMPDIR=$(mktemp -d) \ - && cd $TMPDIR \ - && curl -L https://github.com/wcgallego/pecl-gearman/archive/gearman-2.0.3.tar.gz | tar xzv --strip 1 \ - && phpize \ - && ./configure \ - && make -j$(nproc) \ - && make install \ - && cd - \ - && rm -r $TMPDIR \ - && docker-php-ext-enable gearman - -COPY --from=cytopia/php-cs-fixer:2-php7.1 /usr/bin/php-cs-fixer /usr/local/bin/php-cs-fixer -COPY --from=composer:lts /usr/bin/composer /usr/local/bin/composer - -COPY . /code -WORKDIR /code - -ENTRYPOINT ["tests/docker/php/entrypoint.sh"] -CMD ["sleep", "infinity"] diff --git a/tests/docker/php/7.2/Dockerfile b/tests/docker/php/7.2/Dockerfile deleted file mode 100644 index c2ed7bdaeb..0000000000 --- a/tests/docker/php/7.2/Dockerfile +++ /dev/null @@ -1,29 +0,0 @@ -FROM php:7.2-cli - -RUN apt-get update \ - && apt-get install -y unzip libbz2-dev curl zlib1g-dev libicu-dev libpq-dev libgearman-dev - -RUN docker-php-ext-install zip pcntl bcmath pdo_mysql intl pdo_pgsql - -RUN pecl install igbinary \ - && docker-php-ext-enable igbinary - -RUN TMPDIR=$(mktemp -d) \ - && cd $TMPDIR \ - && curl -L https://github.com/wcgallego/pecl-gearman/archive/gearman-2.0.3.tar.gz | tar xzv --strip 1 \ - && phpize \ - && ./configure \ - && make -j$(nproc) \ - && make install \ - && cd - \ - && rm -r $TMPDIR \ - && docker-php-ext-enable gearman - -COPY --from=cytopia/php-cs-fixer:2-php7.2 /usr/bin/php-cs-fixer /usr/local/bin/php-cs-fixer -COPY --from=composer:latest /usr/bin/composer /usr/local/bin/composer - -COPY . /code -WORKDIR /code - -ENTRYPOINT ["tests/docker/php/entrypoint.sh"] -CMD ["sleep", "infinity"] diff --git a/tests/docker/php/7.3/Dockerfile b/tests/docker/php/7.3/Dockerfile deleted file mode 100644 index b5c0457912..0000000000 --- a/tests/docker/php/7.3/Dockerfile +++ /dev/null @@ -1,29 +0,0 @@ -FROM php:7.3-cli - -RUN apt-get update \ - && apt-get install -y unzip curl zlib1g-dev libzip-dev libicu-dev libpq-dev libgearman-dev - -RUN docker-php-ext-install zip pcntl bcmath pdo_mysql intl pdo_pgsql - -RUN pecl install igbinary \ - && docker-php-ext-enable igbinary - -RUN TMPDIR=$(mktemp -d) \ - && cd $TMPDIR \ - && curl -L https://github.com/wcgallego/pecl-gearman/archive/gearman-2.0.3.tar.gz | tar xzv --strip 1 \ - && phpize \ - && ./configure \ - && make -j$(nproc) \ - && make install \ - && cd - \ - && rm -r $TMPDIR \ - && docker-php-ext-enable gearman - -COPY --from=cytopia/php-cs-fixer:2-php7.3 /usr/bin/php-cs-fixer /usr/local/bin/php-cs-fixer -COPY --from=composer:latest /usr/bin/composer /usr/local/bin/composer - -COPY . /code -WORKDIR /code - -ENTRYPOINT ["tests/docker/php/entrypoint.sh"] -CMD ["sleep", "infinity"] diff --git a/tests/docker/php/7.4/Dockerfile b/tests/docker/php/7.4/Dockerfile deleted file mode 100644 index a60bebafe8..0000000000 --- a/tests/docker/php/7.4/Dockerfile +++ /dev/null @@ -1,18 +0,0 @@ -FROM php:7.4-cli - -RUN apt-get update \ - && apt-get install -y unzip curl zlib1g-dev libzip-dev libicu-dev libpq-dev libgearman-dev - -RUN docker-php-ext-install zip pcntl bcmath pdo_mysql intl pdo_pgsql - -RUN pecl install igbinary gearman \ - && docker-php-ext-enable igbinary gearman - -COPY --from=cytopia/php-cs-fixer:2-php7.4 /usr/bin/php-cs-fixer /usr/local/bin/php-cs-fixer -COPY --from=composer:latest /usr/bin/composer /usr/local/bin/composer - -COPY . /code -WORKDIR /code - -ENTRYPOINT ["tests/docker/php/entrypoint.sh"] -CMD ["sleep", "infinity"] diff --git a/tests/docker/php/8.0/Dockerfile b/tests/docker/php/8.0/Dockerfile deleted file mode 100644 index 8a349d5ad3..0000000000 --- a/tests/docker/php/8.0/Dockerfile +++ /dev/null @@ -1,17 +0,0 @@ -FROM --platform=linux/amd64 php:8.0.28-cli - -RUN apt-get update \ - && apt-get install -y unzip curl zlib1g-dev libzip-dev libicu-dev libpq-dev libgearman-dev - -RUN docker-php-ext-install zip pcntl bcmath pdo_mysql intl pdo_pgsql sockets -RUN pecl install igbinary gearman -RUN docker-php-ext-enable igbinary gearman - -COPY --from=composer:latest /usr/bin/composer /usr/local/bin/composer -COPY --from=cytopia/php-cs-fixer:latest /usr/bin/php-cs-fixer /usr/local/bin/php-cs-fixer - -COPY . /code -WORKDIR /code - -ENTRYPOINT ["tests/docker/php/entrypoint.sh"] -CMD ["sleep", "infinity"] diff --git a/tests/docker/wait-for-it.sh b/tests/docker/wait-for-it.sh deleted file mode 100755 index b444726abc..0000000000 --- a/tests/docker/wait-for-it.sh +++ /dev/null @@ -1,178 +0,0 @@ -#!/usr/bin/env bash -# Use this script to test if a given TCP host/port are available -# https://github.com/vishnubob/wait-for-it - -cmdname=$(basename $0) - -echoerr() { if [[ $QUIET -ne 1 ]]; then echo "$@" 1>&2; fi } - -usage() -{ - cat << USAGE >&2 -Usage: - $cmdname host:port [-s] [-t timeout] [-- command args] - -h HOST | --host=HOST Host or IP under test - -p PORT | --port=PORT TCP port under test - Alternatively, you specify the host and port as host:port - -s | --strict Only execute subcommand if the test succeeds - -q | --quiet Don't output any status messages - -t TIMEOUT | --timeout=TIMEOUT - Timeout in seconds, zero for no timeout - -- COMMAND ARGS Execute command with args after the test finishes -USAGE - exit 1 -} - -wait_for() -{ - if [[ $TIMEOUT -gt 0 ]]; then - echoerr "$cmdname: waiting $TIMEOUT seconds for $HOST:$PORT" - else - echoerr "$cmdname: waiting for $HOST:$PORT without a timeout" - fi - start_ts=$(date +%s) - while : - do - if [[ $ISBUSY -eq 1 ]]; then - nc -z $HOST $PORT - result=$? - else - (echo > /dev/tcp/$HOST/$PORT) >/dev/null 2>&1 - result=$? - fi - if [[ $result -eq 0 ]]; then - end_ts=$(date +%s) - echoerr "$cmdname: $HOST:$PORT is available after $((end_ts - start_ts)) seconds" - break - fi - sleep 1 - done - return $result -} - -wait_for_wrapper() -{ - # In order to support SIGINT during timeout: https://unix.stackexchange.com/a/57692 - if [[ $QUIET -eq 1 ]]; then - timeout $BUSYTIMEFLAG $TIMEOUT $0 --quiet --child --host=$HOST --port=$PORT --timeout=$TIMEOUT & - else - timeout $BUSYTIMEFLAG $TIMEOUT $0 --child --host=$HOST --port=$PORT --timeout=$TIMEOUT & - fi - PID=$! - trap "kill -INT -$PID" INT - wait $PID - RESULT=$? - if [[ $RESULT -ne 0 ]]; then - echoerr "$cmdname: timeout occurred after waiting $TIMEOUT seconds for $HOST:$PORT" - fi - return $RESULT -} - -# process arguments -while [[ $# -gt 0 ]] -do - case "$1" in - *:* ) - hostport=(${1//:/ }) - HOST=${hostport[0]} - PORT=${hostport[1]} - shift 1 - ;; - --child) - CHILD=1 - shift 1 - ;; - -q | --quiet) - QUIET=1 - shift 1 - ;; - -s | --strict) - STRICT=1 - shift 1 - ;; - -h) - HOST="$2" - if [[ $HOST == "" ]]; then break; fi - shift 2 - ;; - --host=*) - HOST="${1#*=}" - shift 1 - ;; - -p) - PORT="$2" - if [[ $PORT == "" ]]; then break; fi - shift 2 - ;; - --port=*) - PORT="${1#*=}" - shift 1 - ;; - -t) - TIMEOUT="$2" - if [[ $TIMEOUT == "" ]]; then break; fi - shift 2 - ;; - --timeout=*) - TIMEOUT="${1#*=}" - shift 1 - ;; - --) - shift - CLI=("$@") - break - ;; - --help) - usage - ;; - *) - echoerr "Unknown argument: $1" - usage - ;; - esac -done - -if [[ "$HOST" == "" || "$PORT" == "" ]]; then - echoerr "Error: you need to provide a host and port to test." - usage -fi - -TIMEOUT=${TIMEOUT:-15} -STRICT=${STRICT:-0} -CHILD=${CHILD:-0} -QUIET=${QUIET:-0} - -# check to see if timeout is from busybox? -# check to see if timeout is from busybox? -TIMEOUT_PATH=$(realpath $(which timeout)) -if [[ $TIMEOUT_PATH =~ "busybox" ]]; then - ISBUSY=1 - BUSYTIMEFLAG="-t" -else - ISBUSY=0 - BUSYTIMEFLAG="" -fi - -if [[ $CHILD -gt 0 ]]; then - wait_for - RESULT=$? - exit $RESULT -else - if [[ $TIMEOUT -gt 0 ]]; then - wait_for_wrapper - RESULT=$? - else - wait_for - RESULT=$? - fi -fi - -if [[ $CLI != "" ]]; then - if [[ $RESULT -ne 0 && $STRICT -eq 1 ]]; then - echoerr "$cmdname: strict mode, refusing to execute subprocess" - exit $RESULT - fi - exec "${CLI[@]}" -else - exit $RESULT -fi From bedfa60e565b5c5ac9644e48a2a9e7c7d1393981 Mon Sep 17 00:00:00 2001 From: Moiseenko Date: Mon, 2 Oct 2023 21:53:55 +0400 Subject: [PATCH 26/48] Cleaning --- support/ide-helper.php | 4 ++++ tests/docker/php/entrypoint.sh | 4 ++-- tests/drivers/TestCase.php | 2 +- tests/drivers/beanstalk/QueueTest.php | 10 +++++----- tests/drivers/stomp/QueueTest.php | 10 ---------- tests/drivers/sync/QueueTest.php | 2 +- 6 files changed, 13 insertions(+), 19 deletions(-) diff --git a/support/ide-helper.php b/support/ide-helper.php index 9488fa7f77..dd0a459e97 100644 --- a/support/ide-helper.php +++ b/support/ide-helper.php @@ -5,6 +5,7 @@ use yii\BaseYii; use yii\queue\amqp_interop\Queue as AmqpInteropQueue; use yii\queue\beanstalk\Queue as BeanstalkQueue; +use yii\queue\db\Queue as DbQueue; use yii\queue\file\Queue as FileQueue; use yii\queue\gearman\Queue as GearmanQueue; use yii\queue\redis\Queue as RedisQueue; @@ -39,6 +40,9 @@ class Yii extends BaseYii * @property SyncQueue $syncQueue * @property SqsQueue $sqsQueue * @property SqsQueue $sqsFifoQueue + * @property DbQueue $mysqlQueue + * @property DbQueue $pgsqlQueue + * @property DbQueue $sqliteQueue */ abstract class BaseApplication extends yii\base\Application { diff --git a/tests/docker/php/entrypoint.sh b/tests/docker/php/entrypoint.sh index 0e0f4e8dd5..2bcde08c9e 100755 --- a/tests/docker/php/entrypoint.sh +++ b/tests/docker/php/entrypoint.sh @@ -5,9 +5,9 @@ set -eu flock tests/runtime/composer-install.lock composer install --prefer-dist --no-interaction tests/yii sqlite-migrate/up --interactive=0 -sleep 30 +sleep 20 tests/docker/php/mysql-lock.php tests/yii mysql-migrate/up --interactive=0 -sleep 30 +sleep 20 tests/docker/php/mysql-lock.php tests/yii pgsql-migrate/up --interactive=0 php --version diff --git a/tests/drivers/TestCase.php b/tests/drivers/TestCase.php index e2ff40a08d..b21496e12e 100644 --- a/tests/drivers/TestCase.php +++ b/tests/drivers/TestCase.php @@ -10,8 +10,8 @@ namespace tests\drivers; -use Yii; use tests\app\SimpleJob; +use Yii; use yii\queue\Queue; /** diff --git a/tests/drivers/beanstalk/QueueTest.php b/tests/drivers/beanstalk/QueueTest.php index 53dba4398c..8ba5bbb7c5 100644 --- a/tests/drivers/beanstalk/QueueTest.php +++ b/tests/drivers/beanstalk/QueueTest.php @@ -105,22 +105,22 @@ protected function getQueue(): Queue } /** - * @param int $id of a job + * @param int|string|null $id of a job * @return bool * @throws */ - protected function jobIsExists($id) + protected function jobIsExists(int|string|null $id): bool { $connection = new Pheanstalk($this->getQueue()->host, $this->getQueue()->port); try { $connection->peek($id); return true; } catch (ServerException $e) { - if (strpos($e->getMessage(), 'NOT_FOUND') === 0) { + if (str_starts_with($e->getMessage(), 'NOT_FOUND')) { return false; - } else { - throw $e; } + + throw $e; } } } diff --git a/tests/drivers/stomp/QueueTest.php b/tests/drivers/stomp/QueueTest.php index d0f117c6ff..0bbe1121e1 100644 --- a/tests/drivers/stomp/QueueTest.php +++ b/tests/drivers/stomp/QueueTest.php @@ -45,14 +45,4 @@ protected function getQueue(): Queue return Yii::$app->stompQueue; } - - protected function setUp(): void - { - if ('true' == getenv('EXCLUDE_STOMP')) { - $this->markTestSkipped('Stomp tests are disabled for php 5.5'); - } - - parent::setUp(); - } - } diff --git a/tests/drivers/sync/QueueTest.php b/tests/drivers/sync/QueueTest.php index 4b832f722d..8b41db3432 100644 --- a/tests/drivers/sync/QueueTest.php +++ b/tests/drivers/sync/QueueTest.php @@ -10,8 +10,8 @@ namespace tests\drivers\sync; -use Yii; use tests\drivers\TestCase; +use Yii; use yii\queue\sync\Queue; /** From 711f008445ce1c338c3df1d445238decb69551ee Mon Sep 17 00:00:00 2001 From: Moiseenko Date: Tue, 3 Oct 2023 00:14:01 +0400 Subject: [PATCH 27/48] Added more strict types --- src/LogBehavior.php | 16 ++++++------ src/Queue.php | 8 +++--- src/cli/Action.php | 4 +-- src/cli/Command.php | 10 +++---- src/cli/Queue.php | 14 +++++----- src/cli/SignalLoop.php | 6 ++--- src/cli/VerboseBehavior.php | 20 +++++++------- src/drivers/amqp_interop/Queue.php | 37 +++++++++++++------------- src/drivers/beanstalk/Queue.php | 16 ++++++------ src/drivers/db/Queue.php | 16 ++++++------ src/drivers/file/Queue.php | 14 +++++----- src/drivers/gearman/Queue.php | 19 ++++++-------- src/drivers/redis/Queue.php | 12 ++++----- src/drivers/sqs/Queue.php | 10 +++---- src/drivers/stomp/Queue.php | 42 +++++++++++++++--------------- src/drivers/sync/Queue.php | 4 +-- tests/docker-compose.yml | 12 ++++----- tests/drivers/stomp/QueueTest.php | 2 +- 18 files changed, 129 insertions(+), 133 deletions(-) diff --git a/src/LogBehavior.php b/src/LogBehavior.php index 040f9c66d5..367cea414e 100644 --- a/src/LogBehavior.php +++ b/src/LogBehavior.php @@ -48,7 +48,7 @@ public function events(): array /** * @param PushEvent $event */ - public function afterPush(PushEvent $event) + public function afterPush(PushEvent $event): void { $title = $this->getJobTitle($event); Yii::info("$title is pushed.", Queue::class); @@ -57,7 +57,7 @@ public function afterPush(PushEvent $event) /** * @param ExecEvent $event */ - public function beforeExec(ExecEvent $event) + public function beforeExec(ExecEvent $event): void { $title = $this->getExecTitle($event); Yii::info("$title is started.", Queue::class); @@ -67,7 +67,7 @@ public function beforeExec(ExecEvent $event) /** * @param ExecEvent $event */ - public function afterExec(ExecEvent $event) + public function afterExec(ExecEvent $event): void { $title = $this->getExecTitle($event); Yii::endProfile($title, Queue::class); @@ -80,7 +80,7 @@ public function afterExec(ExecEvent $event) /** * @param ExecEvent $event */ - public function afterError(ExecEvent $event) + public function afterError(ExecEvent $event): void { $title = $this->getExecTitle($event); Yii::endProfile($title, Queue::class); @@ -94,7 +94,7 @@ public function afterError(ExecEvent $event) * @param cli\WorkerEvent $event * @since 2.0.2 */ - public function workerStart(cli\WorkerEvent $event) + public function workerStart(cli\WorkerEvent $event): void { $title = 'Worker ' . $event->sender->getWorkerPid(); Yii::info("$title is started.", Queue::class); @@ -108,7 +108,7 @@ public function workerStart(cli\WorkerEvent $event) * @param cli\WorkerEvent $event * @since 2.0.2 */ - public function workerStop(cli\WorkerEvent $event) + public function workerStop(cli\WorkerEvent $event): void { $title = 'Worker ' . $event->sender->getWorkerPid(); Yii::endProfile($title, Queue::class); @@ -123,7 +123,7 @@ public function workerStop(cli\WorkerEvent $event) * @return string * @since 2.0.2 */ - protected function getJobTitle(JobEvent $event) + protected function getJobTitle(JobEvent $event): string { $name = $event->job instanceof JobInterface ? get_class($event->job) : 'unknown job'; return "[$event->id] $name"; @@ -134,7 +134,7 @@ protected function getJobTitle(JobEvent $event) * @return string * @since 2.0.2 */ - protected function getExecTitle(ExecEvent $event) + protected function getExecTitle(ExecEvent $event): string { $title = $this->getJobTitle($event); $extra = "attempt: $event->attempt"; diff --git a/src/Queue.php b/src/Queue.php index b2623265ea..147cd61c69 100644 --- a/src/Queue.php +++ b/src/Queue.php @@ -201,20 +201,20 @@ public function push($job): int|string|null } /** - * @param string $message + * @param string $payload * @param int $ttr time to reserve in seconds * @param int $delay * @param mixed $priority - * @return string id of a job message + * @return string|int|null id of a job message */ - abstract protected function pushMessage($message, $ttr, $delay, $priority); + abstract protected function pushMessage(string $payload, int $ttr, int $delay, mixed $priority): int|string|null; /** * Uses for CLI drivers and gets process ID of a worker. * * @since 2.0.2 */ - public function getWorkerPid() + public function getWorkerPid(): ?int { return null; } diff --git a/src/cli/Action.php b/src/cli/Action.php index 0b709914a7..317171ebee 100644 --- a/src/cli/Action.php +++ b/src/cli/Action.php @@ -33,7 +33,7 @@ abstract class Action extends BaseAction /** * @inheritdoc */ - public function init() + public function init(): void { parent::init(); @@ -52,7 +52,7 @@ public function init() * @param string $string * @return string */ - protected function format($string) + protected function format(string $string) { return call_user_func_array([$this->controller, 'ansiFormat'], func_get_args()); } diff --git a/src/cli/Command.php b/src/cli/Command.php index 28d3ab6bc5..af335edd26 100644 --- a/src/cli/Command.php +++ b/src/cli/Command.php @@ -53,11 +53,11 @@ abstract class Command extends Controller */ public bool $isolate = true; /** - * @var string path to php interpreter that uses to run child processes. + * @var string|null 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; + public ?string $phpBinary = null; /** * @inheritdoc @@ -114,7 +114,7 @@ protected function canIsolate(string $actionID): bool /** * @inheritdoc */ - public function beforeAction($action) + public function beforeAction($action): bool { if ($this->canVerbose($action->id) && $this->verbose) { $this->queue->attachBehavior('verbose', ['command' => $this] + $this->verboseConfig); @@ -143,7 +143,7 @@ public function beforeAction($action) * @return int exit code * @internal It is used with isolate mode. */ - public function actionExec($id, $ttr, $attempt, $pid) + public function actionExec(?string $id, int $ttr, int $attempt, int $pid): int { if ($this->queue->execute($id, file_get_contents('php://stdin'), $ttr, $attempt, $pid ?: null)) { return self::EXEC_DONE; @@ -162,7 +162,7 @@ public function actionExec($id, $ttr, $attempt, $pid) * @throws * @see actionExec() */ - protected function handleMessage(int|string|null $id, string $message, ?int $ttr, int $attempt) + protected function handleMessage(int|string|null $id, string $message, ?int $ttr, int $attempt): bool { // Child process command: php yii queue/exec "id" "ttr" "attempt" "pid" $cmd = [ diff --git a/src/cli/Queue.php b/src/cli/Queue.php index e7f49cb48e..92f87e6df5 100644 --- a/src/cli/Queue.php +++ b/src/cli/Queue.php @@ -44,11 +44,11 @@ abstract class Queue extends BaseQueue implements BootstrapInterface * @var array|string * @since 2.0.2 */ - public $loopConfig = SignalLoop::class; + public string|array $loopConfig = SignalLoop::class; /** * @var string command class name */ - public $commandClass = Command::class; + public string $commandClass = Command::class; /** * @var array of additional options of command */ @@ -69,7 +69,7 @@ abstract class Queue extends BaseQueue implements BootstrapInterface * @return string command id * @throws */ - protected function getCommandId() + protected function getCommandId(): string { foreach (Yii::$app->getComponents(false) as $id => $component) { if ($component === $this) { @@ -82,7 +82,7 @@ protected function getCommandId() /** * @inheritdoc */ - public function bootstrap($app) + public function bootstrap($app): void { if ($app instanceof ConsoleApp) { $app->controllerMap[$this->getCommandId()] = [ @@ -99,7 +99,7 @@ public function bootstrap($app) * @return null|int exit code * @since 2.0.2 */ - protected function runWorker(callable $handler) + protected function runWorker(callable $handler): ?int { $this->_workerPid = getmypid(); /** @var LoopInterface $loop */ @@ -112,7 +112,7 @@ protected function runWorker(callable $handler) } try { - call_user_func($handler, function () use ($loop, $event) { + $handler(function () use ($loop, $event) { $this->trigger(self::EVENT_WORKER_LOOP, $event); return $event->exitCode === null && $loop->canContinue(); }); @@ -157,7 +157,7 @@ protected function handleMessage($id, $message, $ttr, $attempt) * @return bool * @internal for worker command only */ - public function execute($id, $message, $ttr, $attempt, $workerPid) + public function execute(string $id, string $message, int $ttr, int $attempt, ?int $workerPid): bool { $this->_workerPid = $workerPid; return parent::handleMessage($id, $message, $ttr, $attempt); diff --git a/src/cli/SignalLoop.php b/src/cli/SignalLoop.php index 9b6dd4ae73..46d8897ae6 100644 --- a/src/cli/SignalLoop.php +++ b/src/cli/SignalLoop.php @@ -74,17 +74,17 @@ public function init(): void parent::init(); if (extension_loaded('pcntl') && function_exists('pcntl_signal')) { foreach ($this->exitSignals as $signal) { - pcntl_signal($signal, function () { + pcntl_signal($signal, static function () { self::$exit = true; }); } foreach ($this->suspendSignals as $signal) { - pcntl_signal($signal, function () { + pcntl_signal($signal, static function () { self::$pause = true; }); } foreach ($this->resumeSignals as $signal) { - pcntl_signal($signal, function () { + pcntl_signal($signal, static function () { self::$pause = false; }); } diff --git a/src/cli/VerboseBehavior.php b/src/cli/VerboseBehavior.php index aa8c0f1388..e25d95b909 100644 --- a/src/cli/VerboseBehavior.php +++ b/src/cli/VerboseBehavior.php @@ -30,16 +30,16 @@ class VerboseBehavior extends Behavior /** * @var Controller */ - public $command; + public Controller $command; /** * @var float timestamp */ - private $jobStartedAt; + private float $jobStartedAt; /** * @var int timestamp */ - private $workerStartedAt; + private int $workerStartedAt; /** * @inheritdoc @@ -58,7 +58,7 @@ public function events(): array /** * @param ExecEvent $event */ - public function beforeExec(ExecEvent $event) + public function beforeExec(ExecEvent $event): void { $this->jobStartedAt = microtime(true); $this->command->stdout(date('Y-m-d H:i:s'), Console::FG_YELLOW); @@ -71,7 +71,7 @@ public function beforeExec(ExecEvent $event) /** * @param ExecEvent $event */ - public function afterExec(ExecEvent $event) + public function afterExec(ExecEvent $event): void { $this->command->stdout(date('Y-m-d H:i:s'), Console::FG_YELLOW); $this->command->stdout($this->jobTitle($event), Console::FG_GREY); @@ -86,7 +86,7 @@ public function afterExec(ExecEvent $event) /** * @param ExecEvent $event */ - public function afterError(ExecEvent $event) + public function afterError(ExecEvent $event): void { $this->command->stdout(date('Y-m-d H:i:s'), Console::FG_YELLOW); $this->command->stdout($this->jobTitle($event), Console::FG_GREY); @@ -112,7 +112,7 @@ public function afterError(ExecEvent $event) * @return string * @since 2.0.2 */ - protected function jobTitle(ExecEvent $event) + protected function jobTitle(ExecEvent $event): string { $name = $event->job instanceof JobInterface ? get_class($event->job) : 'unknown job'; $extra = "attempt: $event->attempt"; @@ -126,7 +126,7 @@ protected function jobTitle(ExecEvent $event) * @param WorkerEvent $event * @since 2.0.2 */ - public function workerStart(WorkerEvent $event) + public function workerStart(WorkerEvent $event): void { $this->workerStartedAt = time(); $this->command->stdout(date('Y-m-d H:i:s'), Console::FG_YELLOW); @@ -139,7 +139,7 @@ public function workerStart(WorkerEvent $event) * @param WorkerEvent $event * @since 2.0.2 */ - public function workerStop(WorkerEvent $event) + public function workerStop(WorkerEvent $event): void { $this->command->stdout(date('Y-m-d H:i:s'), Console::FG_YELLOW); $pid = $event->sender->getWorkerPid(); @@ -154,7 +154,7 @@ public function workerStop(WorkerEvent $event) * @return string * @since 2.0.2 */ - protected function formatDuration($value) + protected function formatDuration($value): string { $seconds = $value % 60; $value = ($value - $seconds) / 60; diff --git a/src/drivers/amqp_interop/Queue.php b/src/drivers/amqp_interop/Queue.php index 1acfb51112..0dbc80d5b8 100644 --- a/src/drivers/amqp_interop/Queue.php +++ b/src/drivers/amqp_interop/Queue.php @@ -235,7 +235,7 @@ class Queue extends CliQueue * * @var string command class name */ - public $commandClass = Command::class; + public string $commandClass = Command::class; /** * Headers to send along with the message @@ -360,7 +360,7 @@ public function getContext(): AmqpContext /** * @inheritdoc */ - protected function pushMessage($payload, $ttr, $delay, $priority) + protected function pushMessage(string $payload, int $ttr, int $delay, mixed $priority): int|string|null { $this->open(); $this->setupBroker(); @@ -417,19 +417,18 @@ protected function open() 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))); - } + $connectionClass = match ($this->driver) { + self::ENQUEUE_AMQP_LIB => AmqpLibConnectionFactory::class, + self::ENQUEUE_AMQP_EXT => AmqpExtConnectionFactory::class, + self::ENQUEUE_AMQP_BUNNY => AmqpBunnyConnectionFactory::class, + 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, @@ -455,7 +454,7 @@ protected function open() 'ssl_key' => $this->sslKey, ]; - $config = array_filter($config, function ($value) { + $config = array_filter($config, static function ($value) { return null !== $value; }); @@ -469,7 +468,7 @@ protected function open() } } - protected function setupBroker() + protected function setupBroker(): void { if ($this->setupBrokerDone) { return; @@ -493,7 +492,7 @@ protected function setupBroker() /** * Closes connection and channel. */ - protected function close() + protected function close(): void { if (!$this->context) { return; @@ -507,7 +506,7 @@ protected function close() /** * {@inheritdoc} */ - protected function redeliver(AmqpMessage $message) + protected function redeliver(AmqpMessage $message): void { $attempt = $message->getProperty(self::ATTEMPT, 1); diff --git a/src/drivers/beanstalk/Queue.php b/src/drivers/beanstalk/Queue.php index 6822c6ac13..35fe630683 100644 --- a/src/drivers/beanstalk/Queue.php +++ b/src/drivers/beanstalk/Queue.php @@ -27,19 +27,19 @@ class Queue extends CliQueue /** * @var string connection host */ - public $host = 'localhost'; + public string $host = 'localhost'; /** * @var int connection port */ - public $port = PheanstalkInterface::DEFAULT_PORT; + public int $port = PheanstalkInterface::DEFAULT_PORT; /** * @var string beanstalk tube */ - public $tube = 'queue'; + public string $tube = 'queue'; /** * @var string command class name */ - public $commandClass = Command::class; + public string $commandClass = Command::class; /** * Listens queue and runs each job. @@ -103,13 +103,13 @@ public function status($id): int * @return bool * @since 2.0.1 */ - public function remove($id) + public function remove($id): bool { try { $this->getPheanstalk()->delete(new Job($id, null)); return true; } catch (ServerException $e) { - if (strpos($e->getMessage(), 'NOT_FOUND') === 0) { + if (str_starts_with($e->getMessage(), 'NOT_FOUND')) { return false; } @@ -120,11 +120,11 @@ public function remove($id) /** * @inheritdoc */ - protected function pushMessage($message, $ttr, $delay, $priority) + protected function pushMessage(string $payload, int $ttr, int $delay, mixed $priority): int|string|null { return $this->getPheanstalk()->putInTube( $this->tube, - $message, + $payload, $priority ?: PheanstalkInterface::DEFAULT_PRIORITY, $delay, $ttr diff --git a/src/drivers/db/Queue.php b/src/drivers/db/Queue.php index e2247a7ee1..d361141519 100644 --- a/src/drivers/db/Queue.php +++ b/src/drivers/db/Queue.php @@ -36,23 +36,23 @@ class Queue extends CliQueue /** * @var int timeout */ - public $mutexTimeout = 3; + public int $mutexTimeout = 3; /** * @var string table name */ - public $tableName = '{{%queue}}'; + public string $tableName = '{{%queue}}'; /** * @var string */ - public $channel = 'queue'; + public string $channel = 'queue'; /** * @var bool ability to delete released messages from table */ - public $deleteReleased = true; + public bool $deleteReleased = true; /** * @var string command class name */ - public $commandClass = Command::class; + public string $commandClass = Command::class; /** * @inheritdoc @@ -129,7 +129,7 @@ public function status($id): int * * @since 2.0.1 */ - public function clear() + public function clear(): void { $this->db->createCommand() ->delete($this->tableName, ['channel' => $this->channel]) @@ -153,11 +153,11 @@ public function remove($id) /** * @inheritdoc */ - protected function pushMessage($message, $ttr, $delay, $priority) + protected function pushMessage(string $payload, int $ttr, int $delay, mixed $priority): int|string|null { $this->db->createCommand()->insert($this->tableName, [ 'channel' => $this->channel, - 'job' => $message, + 'job' => $payload, 'pushed_at' => time(), 'ttr' => $ttr, 'delay' => $delay, diff --git a/src/drivers/file/Queue.php b/src/drivers/file/Queue.php index ae492c7650..76326b47be 100644 --- a/src/drivers/file/Queue.php +++ b/src/drivers/file/Queue.php @@ -35,7 +35,7 @@ class Queue extends CliQueue /** * @var int|null */ - public $fileMode; + public ?int $fileMode = null; /** * @var callable */ @@ -47,7 +47,7 @@ class Queue extends CliQueue /** * @var string */ - public $commandClass = Command::class; + public string $commandClass = Command::class; /** * @inheritdoc @@ -109,7 +109,7 @@ public function status($id): int * * @since 2.0.1 */ - public function clear() + public function clear(): void { $this->touchIndex(function (&$data) { $data = []; @@ -210,7 +210,7 @@ protected function reserve() * * @param array $payload */ - protected function delete($payload) + protected function delete(array $payload): void { $id = $payload[0]; $this->touchIndex(function (&$data) use ($id) { @@ -227,19 +227,19 @@ protected function delete($payload) /** * @inheritdoc */ - protected function pushMessage($message, $ttr, $delay, $priority) + protected function pushMessage(string $payload, int $ttr, int $delay, mixed $priority): int|string|null { if ($priority !== null) { throw new NotSupportedException('Job priority is not supported in the driver.'); } - $this->touchIndex(function (&$data) use ($message, $ttr, $delay, &$id) { + $this->touchIndex(function (&$data) use ($payload, $ttr, $delay, &$id) { if (!isset($data['lastId'])) { $data['lastId'] = 0; } $id = ++$data['lastId']; $fileName = "$this->path/job$id.data"; - file_put_contents($fileName, $message); + file_put_contents($fileName, $payload); if ($this->fileMode !== null) { chmod($fileName, $this->fileMode); } diff --git a/src/drivers/gearman/Queue.php b/src/drivers/gearman/Queue.php index f0c9dce96d..e6f3dda759 100644 --- a/src/drivers/gearman/Queue.php +++ b/src/drivers/gearman/Queue.php @@ -26,7 +26,7 @@ class Queue extends CliQueue /** * @var string command class name */ - public $commandClass = Command::class; + public string $commandClass = Command::class; /** * Listens queue and runs each job. @@ -58,20 +58,17 @@ public function run(bool $repeat): ?int /** * @inheritdoc */ - protected function pushMessage($message, $ttr, $delay, $priority) + protected function pushMessage(string $payload, int $ttr, int $delay, mixed $priority): int|string|null { 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"); - } + return match ($priority) { + 'high' => $this->getClient()->doHighBackground($this->channel, "$ttr;$payload"), + 'low' => $this->getClient()->doLowBackground($this->channel, "$ttr;$payload"), + default => $this->getClient()->doBackground($this->channel, "$ttr;$payload"), + }; } /** @@ -94,7 +91,7 @@ public function status($id): int /** * @return \GearmanClient */ - protected function getClient() + protected function getClient(): \GearmanClient { if (!$this->_client) { $this->_client = new \GearmanClient(); diff --git a/src/drivers/redis/Queue.php b/src/drivers/redis/Queue.php index 58fdefad44..39f3d1a2e6 100644 --- a/src/drivers/redis/Queue.php +++ b/src/drivers/redis/Queue.php @@ -34,7 +34,7 @@ class Queue extends CliQueue /** * @var string command class name */ - public $commandClass = Command::class; + public string $commandClass = Command::class; /** * @inheritdoc @@ -95,7 +95,7 @@ public function status($id): int * * @since 2.0.1 */ - public function clear() + public function clear(): void { while (!$this->redis->set("$this->channel.moving_lock", true, 'NX')) { usleep(10000); @@ -161,7 +161,7 @@ protected function reserve(int $timeout) /** * @param string $from */ - protected function moveExpired($from) + protected function moveExpired($from): void { $now = time(); if ($expired = $this->redis->zrevrangebyscore($from, $now, '-inf')) { @@ -177,7 +177,7 @@ protected function moveExpired($from) * * @param int $id of a message */ - protected function delete($id) + protected function delete($id): void { $this->redis->zrem("$this->channel.reserved", $id); $this->redis->hdel("$this->channel.attempts", $id); @@ -187,14 +187,14 @@ protected function delete($id) /** * @inheritdoc */ - protected function pushMessage($message, $ttr, $delay, $priority) + protected function pushMessage(string $payload, int $ttr, int $delay, mixed $priority): int|string|null { 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"); + $this->redis->hset("$this->channel.messages", $id, "$ttr;$payload"); if (!$delay) { $this->redis->lpush("$this->channel.waiting", $id); } else { diff --git a/src/drivers/sqs/Queue.php b/src/drivers/sqs/Queue.php index e5e7134ede..b3d2a2797c 100644 --- a/src/drivers/sqs/Queue.php +++ b/src/drivers/sqs/Queue.php @@ -59,7 +59,7 @@ class Queue extends CliQueue * @var string command class name * @inheritdoc */ - public $commandClass = Command::class; + public string $commandClass = Command::class; /** * Json serializer by default. * @inheritdoc @@ -181,7 +181,7 @@ public function handle($id, $message, $ttr, $attempt) /** * @inheritdoc */ - protected function pushMessage($message, $ttr, $delay, $priority) + protected function pushMessage(string $payload, int $ttr, int $delay, mixed $priority): int|string|null { if ($priority) { throw new NotSupportedException('Priority is not supported in this driver'); @@ -189,7 +189,7 @@ protected function pushMessage($message, $ttr, $delay, $priority) $request = [ 'QueueUrl' => $this->url, - 'MessageBody' => $message, + 'MessageBody' => $payload, 'DelaySeconds' => $delay, 'MessageAttributes' => [ 'TTR' => [ @@ -199,9 +199,9 @@ protected function pushMessage($message, $ttr, $delay, $priority) ], ]; - if (substr($this->url, -5) === '.fifo') { + if (str_ends_with($this->url, '.fifo')) { $request['MessageGroupId'] = $this->messageGroupId; - $request['MessageDeduplicationId'] = hash('sha256', $message); + $request['MessageDeduplicationId'] = hash('sha256', $payload); } $response = $this->getClient()->sendMessage($request); diff --git a/src/drivers/stomp/Queue.php b/src/drivers/stomp/Queue.php index f0e754fd53..9cb6776c53 100644 --- a/src/drivers/stomp/Queue.php +++ b/src/drivers/stomp/Queue.php @@ -33,78 +33,78 @@ class Queue extends CliQueue * * @var string|null */ - public $host; + public ?string $host; /** * The message queue broker's port. * * @var string|null */ - public $port; + public ?string $port = null; /** * This is user which is used to login on the broker. * * @var string|null */ - public $user; + public ?string $user = null; /** * This is password which is used to login on the broker. * * @var string|null */ - public $password; + public ?string $password = null; /** - * Sets an fixed vhostname, which will be passed on connect as header['host']. + * Sets an fixed vhost name, which will be passed on connect as header['host']. * * @var string|null */ - public $vhost; + public ?string $vhost = null; /** * @var int */ - public $bufferSize; + public int $bufferSize = 1000; /** * @var int */ - public $connectionTimeout; + public int $connectionTimeout = 1; /** * Perform request synchronously. * @var bool */ - public $sync; + public bool $sync = false; /** * The connection will be established as later as possible if set true. * * @var bool|null */ - public $lazy; + public ?bool $lazy = true; /** * Defines whether secure connection should be used or not. * * @var bool|null */ - public $sslOn; + public ?bool $sslOn = false; /** * The queue used to consume messages from. * * @var string */ - public $queueName = 'stomp_queue'; + public string $queueName = 'stomp_queue'; /** * The property contains a command class which used in cli. * * @var string command class name */ - public $commandClass = Command::class; + public string $commandClass = Command::class; /** * Set the read timeout. * @var int */ - public $readTimeOut = 0; + public int $readTimeOut = 0; /** - * @var StompContext + * @var StompContext|null */ - protected $context; + protected ?StompContext $context = null; /** * @inheritdoc @@ -120,7 +120,7 @@ public function init(): void /** * Opens connection. */ - protected function open() + protected function open(): void { if ($this->context) { return; @@ -139,7 +139,7 @@ protected function open() 'ssl_on' => $this->sslOn, ]; - $config = array_filter($config, function ($value) { + $config = array_filter($config, static function ($value) { return null !== $value; }); @@ -213,12 +213,12 @@ protected function setMessageId(StompMessage $message) * @throws \Interop\Queue\Exception * @throws NotSupportedException */ - protected function pushMessage($message, $ttr, $delay, $priority) + protected function pushMessage(string $payload, int $ttr, int $delay, mixed $priority): int|string|null { $this->open(); $queue = $this->createQueue($this->queueName); - $message = $this->context->createMessage($message); + $message = $this->context->createMessage($payload); $message = $this->setMessageId($message); $message->setPersistent(true); $message->setProperty(self::ATTEMPT, 1); @@ -242,7 +242,7 @@ protected function pushMessage($message, $ttr, $delay, $priority) /** * Closes connection. */ - protected function close() + protected function close(): void { if (!$this->context) { return; diff --git a/src/drivers/sync/Queue.php b/src/drivers/sync/Queue.php index 406ccf288d..3c4b7b1a0f 100644 --- a/src/drivers/sync/Queue.php +++ b/src/drivers/sync/Queue.php @@ -75,9 +75,9 @@ public function run() /** * @inheritdoc */ - protected function pushMessage($message, $ttr, $delay, $priority) + protected function pushMessage(string $payload, int $ttr, int $delay, mixed $priority): int|string|null { - array_push($this->payloads, [$ttr, $message]); + $this->payloads[] = [$ttr, $payload]; return ++$this->pushedId; } diff --git a/tests/docker-compose.yml b/tests/docker-compose.yml index fe7da1d5c3..1f22950d3c 100644 --- a/tests/docker-compose.yml +++ b/tests/docker-compose.yml @@ -56,7 +56,7 @@ services: mysql: image: mysql:5.7 ports: - - 3307:3306 + - "3307:3306" environment: MYSQL_ALLOW_EMPTY_PASSWORD: 1 MYSQL_USER: yii2_queue_test @@ -69,7 +69,7 @@ services: postgres: image: postgres:10.4 ports: - - 5433:5432 + - "5433:5432" environment: POSTGRES_USER: yii2_queue_test POSTGRES_PASSWORD: yii2_queue_test @@ -81,7 +81,7 @@ services: redis: image: redis:4.0 ports: - - 6380:6379 + - "6380:6379" networks: net: {} @@ -98,7 +98,7 @@ services: beanstalk: image: schickling/beanstalkd ports: - - 11301:11300 + - "11301:11300" networks: net: {} @@ -106,7 +106,7 @@ services: gearmand: image: artefactual/gearmand ports: - - 4731:4730 + - "4731:4730" networks: net: {} @@ -114,7 +114,7 @@ services: activemq: image: webcenter/activemq ports: - - 61613:61613 + - "61613:61613" networks: net: {} diff --git a/tests/drivers/stomp/QueueTest.php b/tests/drivers/stomp/QueueTest.php index 0bbe1121e1..105b1aa4bd 100644 --- a/tests/drivers/stomp/QueueTest.php +++ b/tests/drivers/stomp/QueueTest.php @@ -29,7 +29,7 @@ public function testListen(): void public function testRetry(): void { $this->startProcess(['php', 'yii', 'queue/listen']); - $job = new RetryJob(['uid' => uniqid()]); + $job = new RetryJob(['uid' => uniqid('', true)]); $this->getQueue()->push($job); sleep(6); From b2034ebd826e3b9a3b93bd0a58a33d0f38c257e5 Mon Sep 17 00:00:00 2001 From: Moiseenko Date: Wed, 4 Oct 2023 18:11:53 +0400 Subject: [PATCH 28/48] Added code coverage driver --- phpunit.xml.dist | 5 +++++ tests/docker/php/Dockerfile | 4 ++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 6b1875ea25..413988cfae 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -15,4 +15,9 @@ ./tests/runtime + + + ./src + + diff --git a/tests/docker/php/Dockerfile b/tests/docker/php/Dockerfile index 973f28667c..63ee4c7a6f 100644 --- a/tests/docker/php/Dockerfile +++ b/tests/docker/php/Dockerfile @@ -10,8 +10,8 @@ RUN echo https://dl-cdn.alpinelinux.org/alpine/edge/main >> /etc/apk/repositorie RUN apk add git icu-dev libpq-dev gearman-dev libcrypto3 openssl-dev autoconf g++ make linux-headers RUN docker-php-ext-install pcntl bcmath pdo_mysql intl pdo_pgsql sockets -RUN pecl install igbinary -RUN docker-php-ext-enable igbinary +RUN pecl install igbinary pcov +RUN docker-php-ext-enable igbinary pcov # Official gearman package not supported PHP 8.1 now RUN TMPDIR=$(mktemp -d) \ From 495c32d6e4b17b616d2556a0dd827936791f1b75 Mon Sep 17 00:00:00 2001 From: Moiseenko Date: Wed, 4 Oct 2023 18:32:45 +0400 Subject: [PATCH 29/48] Added more strict types --- src/drivers/stomp/Queue.php | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/src/drivers/stomp/Queue.php b/src/drivers/stomp/Queue.php index 9cb6776c53..e04ec302c7 100644 --- a/src/drivers/stomp/Queue.php +++ b/src/drivers/stomp/Queue.php @@ -12,7 +12,11 @@ use Enqueue\Stomp\StompConnectionFactory; use Enqueue\Stomp\StompContext; +use Enqueue\Stomp\StompDestination; use Enqueue\Stomp\StompMessage; +use Interop\Queue\Exception as QueueException; +use Interop\Queue\Message; +use Interop\Queue\Queue as InteropQueue; use yii\base\Application as BaseApp; use yii\base\Event; use yii\base\NotSupportedException; @@ -163,7 +167,8 @@ public function run(bool $repeat, int $timeout = 0): ?int $consumer = $this->context->createConsumer($queue); while ($canContinue()) { - if ($message = ($this->readTimeOut > 0 ? $consumer->receive($this->readTimeOut) : $consumer->receiveNoWait())) { + $message = $this->readTimeOut > 0 ? $consumer->receive($this->readTimeOut) : $consumer->receiveNoWait(); + if ($message) { $messageId = $message->getMessageId(); if (!$messageId) { $message = $this->setMessageId($message); @@ -191,7 +196,7 @@ public function run(bool $repeat, int $timeout = 0): ?int break; } elseif ($timeout) { sleep($timeout); - $this->context->getStomp()->getConnection()->sendAlive(); + $this->context->getStomp()->getConnection()?->sendAlive(); } } }); @@ -200,9 +205,8 @@ public function run(bool $repeat, int $timeout = 0): ?int /** * @param StompMessage $message * @return StompMessage - * @throws \Interop\Queue\Exception */ - protected function setMessageId(StompMessage $message) + protected function setMessageId(Message $message): StompMessage { $message->setMessageId(uniqid('', true)); return $message; @@ -210,7 +214,7 @@ protected function setMessageId(StompMessage $message) /** * @inheritdoc - * @throws \Interop\Queue\Exception + * @throws QueueException * @throws NotSupportedException */ protected function pushMessage(string $payload, int $ttr, int $delay, mixed $priority): int|string|null @@ -263,13 +267,17 @@ public function status($id): int /** * @param StompMessage $message - * @throws \Interop\Queue\Exception + * @throws QueueException */ - protected function redeliver(StompMessage $message) + protected function redeliver(StompMessage $message): void { $attempt = $message->getProperty(self::ATTEMPT, 1); - $newMessage = $this->context->createMessage($message->getBody(), $message->getProperties(), $message->getHeaders()); + $newMessage = $this->context->createMessage( + $message->getBody(), + $message->getProperties(), + $message->getHeaders() + ); $newMessage->setProperty(self::ATTEMPT, ++$attempt); $this->context->createProducer()->send( @@ -279,10 +287,10 @@ protected function redeliver(StompMessage $message) } /** - * @param $name - * @return \Enqueue\Stomp\StompDestination + * @param string $name + * @return InteropQueue|StompDestination */ - private function createQueue($name) + private function createQueue(string $name): InteropQueue|StompDestination { $queue = $this->context->createQueue($name); $queue->setDurable(true); From 29068a715dc98baca743a9a9b37ad646748c715a Mon Sep 17 00:00:00 2001 From: Moiseenko Date: Wed, 4 Oct 2023 19:37:19 +0400 Subject: [PATCH 30/48] Added more strict types --- composer.json | 1 - src/cli/Action.php | 2 +- src/drivers/amqp_interop/Queue.php | 11 ++++++----- src/drivers/beanstalk/Queue.php | 7 ++++--- src/drivers/gearman/Command.php | 3 ++- src/drivers/gearman/Queue.php | 15 +++++++++------ src/drivers/redis/InfoAction.php | 2 +- src/drivers/redis/Queue.php | 14 +++++++------- src/drivers/sqs/Queue.php | 2 +- src/drivers/sync/Queue.php | 2 +- 10 files changed, 32 insertions(+), 27 deletions(-) diff --git a/composer.json b/composer.json index cbbe39a06e..acd7cb3be6 100644 --- a/composer.json +++ b/composer.json @@ -45,7 +45,6 @@ "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", diff --git a/src/cli/Action.php b/src/cli/Action.php index 317171ebee..4918c0b263 100644 --- a/src/cli/Action.php +++ b/src/cli/Action.php @@ -52,7 +52,7 @@ public function init(): void * @param string $string * @return string */ - protected function format(string $string) + protected function format(string $string): string { return call_user_func_array([$this->controller, 'ansiFormat'], func_get_args()); } diff --git a/src/drivers/amqp_interop/Queue.php b/src/drivers/amqp_interop/Queue.php index a78bd2a14e..cb6990258a 100644 --- a/src/drivers/amqp_interop/Queue.php +++ b/src/drivers/amqp_interop/Queue.php @@ -412,7 +412,7 @@ public function status($id): int /** * Opens connection and channel. */ - protected function open() + protected function open(): void { if ($this->context) { return; @@ -504,14 +504,15 @@ protected function close(): void $this->setupBrokerDone = false; } - /** - * {@inheritdoc} - */ protected function redeliver(AmqpMessage $message): void { $attempt = $message->getProperty(self::ATTEMPT, 1); - $newMessage = $this->context->createMessage($message->getBody(), $message->getProperties(), $message->getHeaders()); + $newMessage = $this->context->createMessage( + $message->getBody(), + $message->getProperties(), + $message->getHeaders() + ); $newMessage->setDeliveryMode($message->getDeliveryMode()); $newMessage->setProperty(self::ATTEMPT, ++$attempt); diff --git a/src/drivers/beanstalk/Queue.php b/src/drivers/beanstalk/Queue.php index df635a1b44..4a73810bb9 100644 --- a/src/drivers/beanstalk/Queue.php +++ b/src/drivers/beanstalk/Queue.php @@ -14,6 +14,7 @@ use Pheanstalk\Job; use Pheanstalk\Pheanstalk; use Pheanstalk\PheanstalkInterface; +use Pheanstalk\Response; use yii\base\InvalidArgumentException; use yii\queue\cli\Queue as CliQueue; @@ -105,7 +106,7 @@ public function status($id): int * @return bool * @since 2.0.1 */ - public function remove($id): bool + public function remove(int $id): bool { try { $this->getPheanstalk()->delete(new Job($id, null)); @@ -136,7 +137,7 @@ protected function pushMessage(string $payload, int $ttr, int $delay, mixed $pri /** * @return object tube statistics */ - public function getStatsTube() + public function getStatsTube(): object { return $this->getPheanstalk()->statsTube($this->tube); } @@ -144,7 +145,7 @@ public function getStatsTube() /** * @return Pheanstalk */ - protected function getPheanstalk() + protected function getPheanstalk(): Pheanstalk { if (!$this->_pheanstalk) { $this->_pheanstalk = new Pheanstalk($this->host, $this->port); diff --git a/src/drivers/gearman/Command.php b/src/drivers/gearman/Command.php index a8c894a4b5..745710d4b7 100644 --- a/src/drivers/gearman/Command.php +++ b/src/drivers/gearman/Command.php @@ -11,6 +11,7 @@ namespace yii\queue\gearman; use yii\queue\cli\Command as CliCommand; +use yii\queue\cli\Queue as CliQueue; /** * Manages application gearman-queue. @@ -22,7 +23,7 @@ class Command extends CliCommand /** * @var Queue */ - public \yii\queue\cli\Queue $queue; + public CliQueue $queue; /** * @inheritdoc diff --git a/src/drivers/gearman/Queue.php b/src/drivers/gearman/Queue.php index e6f3dda759..ca95bcdace 100644 --- a/src/drivers/gearman/Queue.php +++ b/src/drivers/gearman/Queue.php @@ -10,6 +10,9 @@ namespace yii\queue\gearman; +use GearmanClient; +use GearmanJob; +use GearmanWorker; use yii\base\NotSupportedException; use yii\queue\cli\Queue as CliQueue; @@ -39,10 +42,10 @@ class Queue extends CliQueue public function run(bool $repeat): ?int { return $this->runWorker(function (callable $canContinue) use ($repeat) { - $worker = new \GearmanWorker(); + $worker = new GearmanWorker(); $worker->addServer($this->host, $this->port); - $worker->addFunction($this->channel, function (\GearmanJob $payload) { - list($ttr, $message) = explode(';', $payload->workload(), 2); + $worker->addFunction($this->channel, function (GearmanJob $payload) { + [$ttr, $message] = explode(';', $payload->workload(), 2); $this->handleMessage($payload->handle(), $message, $ttr, 1); }); $worker->setTimeout($repeat ? 1000 : 1); @@ -89,12 +92,12 @@ public function status($id): int } /** - * @return \GearmanClient + * @return GearmanClient */ - protected function getClient(): \GearmanClient + protected function getClient(): GearmanClient { if (!$this->_client) { - $this->_client = new \GearmanClient(); + $this->_client = new GearmanClient(); $this->_client->addServer($this->host, $this->port); } return $this->_client; diff --git a/src/drivers/redis/InfoAction.php b/src/drivers/redis/InfoAction.php index 38a504e73f..385a097f26 100644 --- a/src/drivers/redis/InfoAction.php +++ b/src/drivers/redis/InfoAction.php @@ -29,7 +29,7 @@ class InfoAction extends Action /** * Info about queue status. */ - public function run() + public function run(): void { $prefix = $this->queue->channel; $waiting = $this->queue->redis->llen("$prefix.waiting"); diff --git a/src/drivers/redis/Queue.php b/src/drivers/redis/Queue.php index fe5b381bc5..7044cad1ab 100644 --- a/src/drivers/redis/Queue.php +++ b/src/drivers/redis/Queue.php @@ -26,7 +26,7 @@ class Queue extends CliQueue /** * @var Connection|array|string */ - public $redis = 'redis'; + public Connection|string|array $redis = 'redis'; /** * @var string */ @@ -110,7 +110,7 @@ public function clear(): void * @return bool * @since 2.0.1 */ - public function remove($id) + public function remove(int $id): bool { while (!$this->redis->set("$this->channel.moving_lock", true, 'NX', 'EX', 1)) { usleep(10000); @@ -131,7 +131,7 @@ public function remove($id) * @param int $timeout timeout * @return array|null payload */ - protected function reserve(int $timeout) + protected function reserve(int $timeout): ?array { // 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)) { @@ -155,7 +155,7 @@ protected function reserve(int $timeout) return null; } - list($ttr, $message) = explode(';', $payload, 2); + [$ttr, $message] = explode(';', $payload, 2); $this->redis->zadd("$this->channel.reserved", time() + $ttr, $id); $attempt = $this->redis->hincrby("$this->channel.attempts", $id, 1); @@ -165,7 +165,7 @@ protected function reserve(int $timeout) /** * @param string $from */ - protected function moveExpired($from): void + protected function moveExpired(string $from): void { $now = time(); if ($expired = $this->redis->zrevrangebyscore($from, $now, '-inf')) { @@ -179,9 +179,9 @@ protected function moveExpired($from): void /** * Deletes message by ID. * - * @param int $id of a message + * @param int|string $id of a message */ - protected function delete($id): void + protected function delete(int|string $id): void { $this->redis->zrem("$this->channel.reserved", $id); $this->redis->hdel("$this->channel.attempts", $id); diff --git a/src/drivers/sqs/Queue.php b/src/drivers/sqs/Queue.php index b3d2a2797c..38a477d4af 100644 --- a/src/drivers/sqs/Queue.php +++ b/src/drivers/sqs/Queue.php @@ -173,7 +173,7 @@ public function status($id): int * @return bool * @since 2.2.1 */ - public function handle($id, $message, $ttr, $attempt) + public function handle(string $id, string $message, int $ttr, int $attempt) { return $this->handleMessage($id, $message, $ttr, $attempt); } diff --git a/src/drivers/sync/Queue.php b/src/drivers/sync/Queue.php index 3c4b7b1a0f..d83d8eee58 100644 --- a/src/drivers/sync/Queue.php +++ b/src/drivers/sync/Queue.php @@ -61,7 +61,7 @@ public function init(): void /** * Runs all jobs from queue. */ - public function run() + public function run(): void { while (($payload = array_shift($this->payloads)) !== null) { [$ttr, $message] = $payload; From 43552648f12e4fe3a8ba190f0d15941adfe05f44 Mon Sep 17 00:00:00 2001 From: Moiseenko Date: Wed, 4 Oct 2023 19:49:11 +0400 Subject: [PATCH 31/48] Added codecov --- .github/workflows/main.yml | 10 ++++++++-- Makefile | 7 +------ 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index d6f9e5a6d7..d785cdb0cd 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -36,9 +36,15 @@ jobs: strategy: fail-fast: false matrix: - php: [ '8.1', '8.2'] + php: [ '8.1', '8.2' ] steps: - - name: Checkout + - name: Checkout. uses: actions/checkout@v2 + - name: PHP Unit tests for PHP ${{ matrix.php }} run: make test v=${{ matrix.php }} + + - name: Upload coverage to Codecov. + uses: codecov/codecov-action@v3 + with: + files: ./coverage.xml diff --git a/Makefile b/Makefile index d6123044ef..045d3f5ce8 100644 --- a/Makefile +++ b/Makefile @@ -7,7 +7,7 @@ build: ## Build an image from a docker-compose file. Params: {{ v=8.1 }}. Defa test: ## Run tests. Params: {{ v=8.1 }}. Default latest PHP 8.1 PHP_VERSION=$(filter-out $@,$(v)) docker-compose build --pull yii2-queue-php - PHP_VERSION=$(filter-out $@,$(v)) docker-compose run yii2-queue-php vendor/bin/phpunit --colors=always + PHP_VERSION=$(filter-out $@,$(v)) docker-compose run yii2-queue-php vendor/bin/phpunit --colors=always --coverage-clover=coverage.xml make down down: ## Stop and remove containers, networks @@ -21,11 +21,6 @@ benchmark: ## Run benchmark. Params: {{ v=8.1 }}. Default latest PHP 8.1 sh: ## Enter the container with the application docker exec -it yii2-queue-php sh -check-cs: - docker-compose build php72 - docker-compose run php72 php-cs-fixer fix --diff --dry-run - docker-compose down - clean: docker-compose down rm -rf tests/runtime/* From d6da3f414c999dd93f37bc80aee90c49182ecb4d Mon Sep 17 00:00:00 2001 From: Moiseenko Date: Wed, 4 Oct 2023 20:12:50 +0400 Subject: [PATCH 32/48] Added more strict types --- tests/app/benchmark/Controller.php | 13 ++++++++---- tests/app/benchmark/waiting/Action.php | 29 +++++++++++++------------- tests/app/benchmark/waiting/Job.php | 13 +++++++----- 3 files changed, 32 insertions(+), 23 deletions(-) diff --git a/tests/app/benchmark/Controller.php b/tests/app/benchmark/Controller.php index c5358b6774..265e2ad4f8 100644 --- a/tests/app/benchmark/Controller.php +++ b/tests/app/benchmark/Controller.php @@ -1,4 +1,7 @@ */ -class Controller extends \yii\console\Controller +class Controller extends ConsoleController { - private $startedAt; + private int $startedAt; - public function actions() + public function actions(): array { return [ 'waiting' => waiting\Action::class, @@ -26,7 +31,7 @@ public function actions() /** * @inheritdoc */ - public function beforeAction($action) + public function beforeAction($action): bool { $this->startedAt = time(); return parent::beforeAction($action); diff --git a/tests/app/benchmark/waiting/Action.php b/tests/app/benchmark/waiting/Action.php index d890905157..39b5836df6 100644 --- a/tests/app/benchmark/waiting/Action.php +++ b/tests/app/benchmark/waiting/Action.php @@ -1,4 +1,7 @@ */ -class Action extends \yii\base\Action +class Action extends BaseAction { /** * @var array */ - public $modes = [ + public array $modes = [ // Worker will be run in fast mode 'fast' => [ 'gearmanQueue' => ['gearman-queue/listen' ,'--isolate=0'], 'beanstalkQueue' => ['beanstalk-queue/listen' ,'--isolate=0'], 'redisQueue' => ['redis-queue/listen' ,'--isolate=0'], - 'amqpQueue' => ['amqp-queue/listen' ,'--isolate=0'], 'amqpInteropQueue' => ['amqp-interop-queue/listen' ,'--isolate=0'], 'mysqlQueue' => ['mysql-queue/listen', '1' ,'--isolate=0'], 'fileQueue' => ['file-queue/listen' , '1' ,'--isolate=0'], @@ -40,7 +43,6 @@ class Action extends \yii\base\Action 'gearmanQueue' => ['gearman-queue/listen' ,'--isolate=1'], 'beanstalkQueue' => ['beanstalk-queue/listen' ,'--isolate=1'], 'redisQueue' => ['redis-queue/listen' ,'--isolate=1'], - 'amqpQueue' => ['amqp-queue/listen' ,'--isolate=1'], 'amqpInteropQueue' => ['amqp-interop-queue/listen' ,'--isolate=1'], 'mysqlQueue' => ['mysql-queue/listen', '1' ,'--isolate=1'], 'fileQueue' => ['file-queue/listen' , '1' ,'--isolate=1'], @@ -50,7 +52,7 @@ class Action extends \yii\base\Action /** * @var Process[] */ - private $workers = []; + private array $workers = []; /** * Runs benchmark of job wait time. @@ -61,7 +63,7 @@ class Action extends \yii\base\Action * @param int $payloadSize additional job size * @throws */ - public function run($mode = 'fast', $jobCount = 1000, $workerCount = 10, $payloadSize = 0) + public function run(string $mode = 'fast', int $jobCount = 1000, int $workerCount = 10, int $payloadSize = 0): void { if (!isset($this->modes[$mode])) { throw new ConsoleException("Unknown mode: $mode."); @@ -100,7 +102,7 @@ public function run($mode = 'fast', $jobCount = 1000, $workerCount = 10, $payloa for ($i = 0; $i < $workerCount && $pushedCount < $jobCount; $i++) { $jobs[] = $job = new Job(); $job->resultFileName = $resultFileName; - $lockName = uniqid($queueName); + $lockName = uniqid($queueName, true); $job->lockFileName = Yii::getAlias("@runtime/$lockName.lock"); touch($job->lockFileName); $job->pushedAt = microtime(true); @@ -125,7 +127,7 @@ public function run($mode = 'fast', $jobCount = 1000, $workerCount = 10, $payloa } Console::endProgress(strtr( - 'MEDIAN = {median} s; AVG = {avg} s; MIN = {min} s; MAX = {max} s' . PHP_EOL, + 'COUNT = {count}; MEDIAN = {median} s; AVG = {avg} s; MIN = {min} s; MAX = {max} s' . PHP_EOL, $this->calcResult($resultFileName, 4) )); } finally { @@ -141,7 +143,7 @@ public function run($mode = 'fast', $jobCount = 1000, $workerCount = 10, $payloa * @param int $count * @param callable $callback */ - private function startWorkers($command, $count, callable $callback) + private function startWorkers(array $command, int $count, callable $callback): void { for ($i = 0; $i < $count; $i++) { $this->workers[] = $worker = new Process(array_merge(['php', 'tests/yii'], $command)); @@ -152,10 +154,9 @@ private function startWorkers($command, $count, callable $callback) /** * Stops started workers. */ - private function stopWorkers() + private function stopWorkers(): void { foreach ($this->workers as $worker) { - /** @var Process $worker */ $worker->stop(); } $this->workers = []; @@ -168,7 +169,7 @@ private function stopWorkers() * @param int $scale * @return array of aggregate results in seconds */ - private function calcResult($fileName, $scale = 4) + private function calcResult(string $fileName, int $scale): array { /** @var float[] $times */ $times = explode("\n", trim(file_get_contents($fileName))); @@ -181,8 +182,8 @@ private function calcResult($fileName, $scale = 4) $median = ($median + $times[$middleIndex - 1]) / 2; } $avg = array_sum($times) / $count; - $min = min($times); - $max = max($times); + $min = (float)min($times); + $max = (float)max($times); return [ '{count}' => $count, diff --git a/tests/app/benchmark/waiting/Job.php b/tests/app/benchmark/waiting/Job.php index e96c7219c7..0337ebe2b8 100644 --- a/tests/app/benchmark/waiting/Job.php +++ b/tests/app/benchmark/waiting/Job.php @@ -1,4 +1,7 @@ pushedAt; if (file_exists($this->lockFileName)) { From 7ceb8fc6d211aca04e19b1d53a0c05cbe844ce1e Mon Sep 17 00:00:00 2001 From: Moiseenko Date: Wed, 4 Oct 2023 20:13:11 +0400 Subject: [PATCH 33/48] Cleaning --- .gitattributes | 1 - .github/workflows/main.yml | 2 ++ README.md | 4 ++++ 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/.gitattributes b/.gitattributes index dbebd6c75a..d83ec3c592 100644 --- a/.gitattributes +++ b/.gitattributes @@ -8,7 +8,6 @@ /.gitattributes export-ignore /.gitignore export-ignore /.php_cs export-ignore -/.travis.yml export-ignore /Makefile export-ignore /phpunit.xml.dist export-ignore /support export-ignore diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index d785cdb0cd..36ec37335c 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -6,6 +6,7 @@ on: - 'docs/**' - 'README.md' - 'CHANGELOG.md' + - 'UPGRADE.md' - '.gitignore' - '.gitattributes' @@ -15,6 +16,7 @@ on: - 'docs/**' - 'README.md' - 'CHANGELOG.md' + - 'UPGRADE.md' - '.gitignore' - '.gitattributes' diff --git a/README.md b/README.md index 8b5fed3a63..a28bd8f40b 100644 --- a/README.md +++ b/README.md @@ -16,6 +16,10 @@ Documentation is at [docs/guide/README.md](docs/guide/README.md). [![Total Downloads](https://poser.pugx.org/yiisoft/yii2-queue/downloads.svg)](https://packagist.org/packages/yiisoft/yii2-queue) [![Build Status](https://github.com/yiisoft/yii2-queue/workflows/build/badge.svg)](https://github.com/yiisoft/yii2-queue/actions) +## Requirements + +- PHP 8.1 or higher. + Installation ------------ From 62f4959bd3cb0293eb9e65f484879f074e197921 Mon Sep 17 00:00:00 2001 From: Moiseenko Date: Wed, 4 Oct 2023 23:36:52 +0400 Subject: [PATCH 34/48] Cleaning --- .gitignore | 1 + Makefile | 4 ++++ composer.json | 5 ++++- psalm.xml | 20 ++++++++++++++++++++ tests/docker/php/Dockerfile | 8 ++++---- 5 files changed, 33 insertions(+), 5 deletions(-) create mode 100644 psalm.xml diff --git a/.gitignore b/.gitignore index 70455b22f1..71e20a2728 100644 --- a/.gitignore +++ b/.gitignore @@ -22,3 +22,4 @@ composer.lock # PHP Unit cache .phpunit.result.cache +.phpunit.cache diff --git a/Makefile b/Makefile index 045d3f5ce8..71c794b63c 100644 --- a/Makefile +++ b/Makefile @@ -21,6 +21,10 @@ benchmark: ## Run benchmark. Params: {{ v=8.1 }}. Default latest PHP 8.1 sh: ## Enter the container with the application docker exec -it yii2-queue-php sh +static-analyze: ## Run code static analyze. Params: {{ v=8.1 }}. Default latest PHP 8.1 + PHP_VERSION=$(filter-out $@,$(v)) docker-compose run yii2-queue-php vendor/bin/psalm --config=psalm.xml --shepherd --stats --php-version=$(v) + make down + clean: docker-compose down rm -rf tests/runtime/* diff --git a/composer.json b/composer.json index acd7cb3be6..ce9e76b5fe 100644 --- a/composer.json +++ b/composer.json @@ -28,9 +28,12 @@ "yiisoft/yii2-gii": "~2.2.0", "php-amqplib/php-amqplib": "^3.0.0", "enqueue/amqp-lib": "^0.10.0", + "enqueue/amqp-bunny": "^0.10.0", + "enqueue/amqp-ext": "^0.10.8", "enqueue/stomp": "^0.10.0", "pda/pheanstalk": "3.2.1", - "aws/aws-sdk-php": ">=2.4" + "aws/aws-sdk-php": ">=2.4", + "vimeo/psalm": "^5.8" }, "suggest": { "ext-pcntl": "Need for process signals.", diff --git a/psalm.xml b/psalm.xml new file mode 100644 index 0000000000..f6d5901c20 --- /dev/null +++ b/psalm.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + + diff --git a/tests/docker/php/Dockerfile b/tests/docker/php/Dockerfile index 63ee4c7a6f..c806cdb70f 100644 --- a/tests/docker/php/Dockerfile +++ b/tests/docker/php/Dockerfile @@ -7,11 +7,11 @@ RUN echo https://dl-cdn.alpinelinux.org/alpine/edge/main >> /etc/apk/repositorie && echo https://dl-cdn.alpinelinux.org/alpine/edge/testing >> /etc/apk/repositories \ && apk update -RUN apk add git icu-dev libpq-dev gearman-dev libcrypto3 openssl-dev autoconf g++ make linux-headers +RUN apk add git icu-dev libpq-dev gearman-dev libcrypto3 openssl-dev autoconf g++ make linux-headers rabbitmq-c-dev -RUN docker-php-ext-install pcntl bcmath pdo_mysql intl pdo_pgsql sockets -RUN pecl install igbinary pcov -RUN docker-php-ext-enable igbinary pcov +RUN docker-php-ext-install pcntl bcmath pdo_mysql intl pdo_pgsql sockets opcache +RUN pecl install igbinary pcov amqp-1.11.0 +RUN docker-php-ext-enable igbinary pcov amqp # Official gearman package not supported PHP 8.1 now RUN TMPDIR=$(mktemp -d) \ From 516f6e17bb2cee591833b28f4026c137f5f94a6a Mon Sep 17 00:00:00 2001 From: Moiseenko Date: Thu, 5 Oct 2023 00:11:02 +0400 Subject: [PATCH 35/48] Fixed static analysis --- .gitattributes | 1 + composer.json | 2 +- psalm.xml | 4 +++- src/Queue.php | 4 ++-- src/cli/Queue.php | 2 +- src/drivers/beanstalk/Queue.php | 4 ++-- src/drivers/db/Queue.php | 4 ++-- src/drivers/file/InfoAction.php | 20 ++++++++++---------- src/drivers/gearman/Queue.php | 2 +- src/drivers/redis/Queue.php | 2 +- 10 files changed, 24 insertions(+), 21 deletions(-) diff --git a/.gitattributes b/.gitattributes index d83ec3c592..6e08b1d559 100644 --- a/.gitattributes +++ b/.gitattributes @@ -11,3 +11,4 @@ /Makefile export-ignore /phpunit.xml.dist export-ignore /support export-ignore +/psalm.xml export-ignore diff --git a/composer.json b/composer.json index ce9e76b5fe..7bec3f66d2 100644 --- a/composer.json +++ b/composer.json @@ -33,7 +33,7 @@ "enqueue/stomp": "^0.10.0", "pda/pheanstalk": "3.2.1", "aws/aws-sdk-php": ">=2.4", - "vimeo/psalm": "^5.8" + "vimeo/psalm": "^5.10.0" }, "suggest": { "ext-pcntl": "Need for process signals.", diff --git a/psalm.xml b/psalm.xml index f6d5901c20..b18f9106ef 100644 --- a/psalm.xml +++ b/psalm.xml @@ -1,6 +1,6 @@ + + diff --git a/src/Queue.php b/src/Queue.php index d21d5ad7d6..0d6e9a7b8d 100644 --- a/src/Queue.php +++ b/src/Queue.php @@ -217,13 +217,13 @@ public function getWorkerPid(): ?int } /** - * @param string $id of a job message + * @param int|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) + protected function handleMessage(int|string $id, string $message, int $ttr, int $attempt): bool { [$job, $error] = $this->unserializeMessage($message); $event = new ExecEvent([ diff --git a/src/cli/Queue.php b/src/cli/Queue.php index 92f87e6df5..ae12b5d4f7 100644 --- a/src/cli/Queue.php +++ b/src/cli/Queue.php @@ -139,7 +139,7 @@ public function getWorkerPid(): ?int /** * @inheritdoc */ - protected function handleMessage($id, $message, $ttr, $attempt) + protected function handleMessage(int|string $id, string $message, int $ttr, int $attempt): bool { if ($this->messageHandler) { return call_user_func($this->messageHandler, $id, $message, $ttr, $attempt); diff --git a/src/drivers/beanstalk/Queue.php b/src/drivers/beanstalk/Queue.php index 4a73810bb9..42288abb58 100644 --- a/src/drivers/beanstalk/Queue.php +++ b/src/drivers/beanstalk/Queue.php @@ -62,8 +62,8 @@ public function run(bool $repeat, int $timeout = 0): ?int if ($this->handleMessage( $payload->getId(), $payload->getData(), - $info->ttr, - $info->reserves + (int)$info->ttr, + (int)$info->reserves )) { $this->getPheanstalk()->delete($payload); } diff --git a/src/drivers/db/Queue.php b/src/drivers/db/Queue.php index d361141519..aade95bda3 100644 --- a/src/drivers/db/Queue.php +++ b/src/drivers/db/Queue.php @@ -81,8 +81,8 @@ public function run(bool $repeat, int $timeout = 0) if ($this->handleMessage( $payload['id'], $payload['job'], - $payload['ttr'], - $payload['attempt'] + (int)$payload['ttr'], + (int)$payload['attempt'] )) { $this->release($payload); } diff --git a/src/drivers/file/InfoAction.php b/src/drivers/file/InfoAction.php index 3a50d89dff..cd4b649a45 100644 --- a/src/drivers/file/InfoAction.php +++ b/src/drivers/file/InfoAction.php @@ -29,27 +29,27 @@ class InfoAction extends Action /** * Info about queue status. */ - public function run() + public function run(): void { Console::output($this->format('Jobs', Console::FG_GREEN)); Console::stdout($this->format('- waiting: ', Console::FG_YELLOW)); - Console::output($this->getWaitingCount()); + Console::output((string)$this->getWaitingCount()); Console::stdout($this->format('- delayed: ', Console::FG_YELLOW)); - Console::output($this->getDelayedCount()); + Console::output((string)$this->getDelayedCount()); Console::stdout($this->format('- reserved: ', Console::FG_YELLOW)); - Console::output($this->getReservedCount()); + Console::output((string)$this->getReservedCount()); Console::stdout($this->format('- done: ', Console::FG_YELLOW)); - Console::output($this->getDoneCount()); + Console::output((string)$this->getDoneCount()); } /** * @return int */ - protected function getWaitingCount() + protected function getWaitingCount(): int { $data = $this->getIndexData(); return !empty($data['waiting']) ? count($data['waiting']) : 0; @@ -58,7 +58,7 @@ protected function getWaitingCount() /** * @return int */ - protected function getDelayedCount() + protected function getDelayedCount(): int { $data = $this->getIndexData(); return !empty($data['delayed']) ? count($data['delayed']) : 0; @@ -67,7 +67,7 @@ protected function getDelayedCount() /** * @return int */ - protected function getReservedCount() + protected function getReservedCount(): int { $data = $this->getIndexData(); return !empty($data['reserved']) ? count($data['reserved']) : 0; @@ -76,10 +76,10 @@ protected function getReservedCount() /** * @return int */ - protected function getDoneCount() + protected function getDoneCount(): int { $data = $this->getIndexData(); - $total = isset($data['lastId']) ? $data['lastId'] : 0; + $total = $data['lastId'] ?? 0; return $total - $this->getDelayedCount() - $this->getWaitingCount(); } diff --git a/src/drivers/gearman/Queue.php b/src/drivers/gearman/Queue.php index ca95bcdace..b9989d01e8 100644 --- a/src/drivers/gearman/Queue.php +++ b/src/drivers/gearman/Queue.php @@ -46,7 +46,7 @@ public function run(bool $repeat): ?int $worker->addServer($this->host, $this->port); $worker->addFunction($this->channel, function (GearmanJob $payload) { [$ttr, $message] = explode(';', $payload->workload(), 2); - $this->handleMessage($payload->handle(), $message, $ttr, 1); + $this->handleMessage($payload->handle(), $message, (int)$ttr, 1); }); $worker->setTimeout($repeat ? 1000 : 1); while ($canContinue()) { diff --git a/src/drivers/redis/Queue.php b/src/drivers/redis/Queue.php index 7044cad1ab..03327914d9 100644 --- a/src/drivers/redis/Queue.php +++ b/src/drivers/redis/Queue.php @@ -60,7 +60,7 @@ public function run(bool $repeat, int $timeout = 0): ?int while ($canContinue()) { if (($payload = $this->reserve($timeout)) !== null) { [$id, $message, $ttr, $attempt] = $payload; - if ($this->handleMessage($id, $message, $ttr, $attempt)) { + if ($this->handleMessage($id, $message, (int)$ttr, (int)$attempt)) { $this->delete($id); } } elseif (!$repeat) { From 5fe7c13f9106d9bab3160325f38ac039366866a1 Mon Sep 17 00:00:00 2001 From: Moiseenko Date: Thu, 5 Oct 2023 00:32:57 +0400 Subject: [PATCH 36/48] Fixed static analysis --- psalm.xml | 1 + src/Queue.php | 4 ++-- src/drivers/amqp_interop/Queue.php | 8 ++++++-- src/drivers/sqs/Queue.php | 2 +- 4 files changed, 10 insertions(+), 5 deletions(-) diff --git a/psalm.xml b/psalm.xml index b18f9106ef..846e8ffff1 100644 --- a/psalm.xml +++ b/psalm.xml @@ -14,6 +14,7 @@ + diff --git a/src/Queue.php b/src/Queue.php index 0d6e9a7b8d..88f03bf163 100644 --- a/src/Queue.php +++ b/src/Queue.php @@ -65,9 +65,9 @@ abstract class Queue extends Component */ public bool $strictJobType = true; /** - * @var SerializerInterface|array + * @var SerializerInterface|array|string */ - public $serializer = PhpSerializer::class; + public string|array|SerializerInterface $serializer = PhpSerializer::class; /** * @var int default time to reserve a job */ diff --git a/src/drivers/amqp_interop/Queue.php b/src/drivers/amqp_interop/Queue.php index cb6990258a..e25dbd47dd 100644 --- a/src/drivers/amqp_interop/Queue.php +++ b/src/drivers/amqp_interop/Queue.php @@ -349,9 +349,9 @@ public function listen(): void } /** - * @return AmqpContext + * @return AmqpContext|null */ - public function getContext(): AmqpContext + public function getContext(): ?AmqpContext { $this->open(); @@ -368,6 +368,7 @@ protected function pushMessage(string $payload, int $ttr, int $delay, mixed $pri $topic = $this->context->createTopic($this->exchangeName); + /** @var AmqpMessage $message */ $message = $this->context->createMessage($payload); $message->setDeliveryMode(AmqpMessage::DELIVERY_MODE_PERSISTENT); $message->setMessageId(uniqid('', true)); @@ -475,11 +476,13 @@ protected function setupBroker(): void return; } + /** @var AmqpQueue $queue */ $queue = $this->context->createQueue($this->queueName); $queue->setFlags($this->queueFlags); $queue->setArguments($this->queueOptionalArguments); $this->context->declareQueue($queue); + /** @var AmqpTopic $topic */ $topic = $this->context->createTopic($this->exchangeName); $topic->setType($this->exchangeType); $topic->setFlags($this->exchangeFlags); @@ -508,6 +511,7 @@ protected function redeliver(AmqpMessage $message): void { $attempt = $message->getProperty(self::ATTEMPT, 1); + /** @var AmqpMessage $newMessage */ $newMessage = $this->context->createMessage( $message->getBody(), $message->getProperties(), diff --git a/src/drivers/sqs/Queue.php b/src/drivers/sqs/Queue.php index 38a477d4af..1618d0e8e5 100644 --- a/src/drivers/sqs/Queue.php +++ b/src/drivers/sqs/Queue.php @@ -64,7 +64,7 @@ class Queue extends CliQueue * Json serializer by default. * @inheritdoc */ - public $serializer = JsonSerializer::class; + public string|array|\yii\queue\serializers\SerializerInterface $serializer = JsonSerializer::class; /** * @var SqsClient From a81acb9b04782a58ca4c40fed50daa6f6f38465b Mon Sep 17 00:00:00 2001 From: Moiseenko Date: Thu, 5 Oct 2023 01:04:24 +0400 Subject: [PATCH 37/48] Fixed static analysis --- Makefile | 2 +- psalm.xml | 3 ++- src/Queue.php | 4 ---- src/cli/Command.php | 1 - src/cli/Queue.php | 1 - tests/drivers/amqp_interop/QueueTest.php | 10 +++++++--- 6 files changed, 10 insertions(+), 11 deletions(-) diff --git a/Makefile b/Makefile index 71c794b63c..a864b24347 100644 --- a/Makefile +++ b/Makefile @@ -7,7 +7,7 @@ build: ## Build an image from a docker-compose file. Params: {{ v=8.1 }}. Defa test: ## Run tests. Params: {{ v=8.1 }}. Default latest PHP 8.1 PHP_VERSION=$(filter-out $@,$(v)) docker-compose build --pull yii2-queue-php - PHP_VERSION=$(filter-out $@,$(v)) docker-compose run yii2-queue-php vendor/bin/phpunit --colors=always --coverage-clover=coverage.xml + PHP_VERSION=$(filter-out $@,$(v)) docker-compose run yii2-queue-php vendor/bin/phpunit --colors=always --coverage-clover coverage.xml make down down: ## Stop and remove containers, networks diff --git a/psalm.xml b/psalm.xml index 846e8ffff1..3b35278eed 100644 --- a/psalm.xml +++ b/psalm.xml @@ -1,6 +1,6 @@ + diff --git a/src/Queue.php b/src/Queue.php index 88f03bf163..4eb67aad47 100644 --- a/src/Queue.php +++ b/src/Queue.php @@ -93,7 +93,6 @@ public function init(): void 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.'); } @@ -101,7 +100,6 @@ public function init(): void 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.'); } @@ -177,7 +175,6 @@ public function push($job): int|string|null 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.'); } @@ -185,7 +182,6 @@ public function push($job): int|string|null 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.'); } diff --git a/src/cli/Command.php b/src/cli/Command.php index af335edd26..ef993ba534 100644 --- a/src/cli/Command.php +++ b/src/cli/Command.php @@ -159,7 +159,6 @@ public function actionExec(?string $id, int $ttr, int $attempt, int $pid): int * @param int|null $ttr time to reserve * @param int $attempt number * @return bool - * @throws * @see actionExec() */ protected function handleMessage(int|string|null $id, string $message, ?int $ttr, int $attempt): bool diff --git a/src/cli/Queue.php b/src/cli/Queue.php index ae12b5d4f7..9ded70bc02 100644 --- a/src/cli/Queue.php +++ b/src/cli/Queue.php @@ -67,7 +67,6 @@ abstract class Queue extends BaseQueue implements BootstrapInterface /** * @return string command id - * @throws */ protected function getCommandId(): string { diff --git a/tests/drivers/amqp_interop/QueueTest.php b/tests/drivers/amqp_interop/QueueTest.php index 349d964df1..e4a13497c0 100644 --- a/tests/drivers/amqp_interop/QueueTest.php +++ b/tests/drivers/amqp_interop/QueueTest.php @@ -11,11 +11,14 @@ namespace tests\drivers\amqp_interop; use Enqueue\AmqpLib\AmqpConnectionFactory; +use Enqueue\AmqpLib\AmqpContext; use Interop\Amqp\AmqpMessage; use Interop\Amqp\AmqpQueue; use Interop\Amqp\AmqpTopic; use Interop\Amqp\Impl\AmqpBind; use Interop\Amqp\Impl\AmqpMessage as InteropAmqpMessage; +use Interop\Queue\Context; +use Interop\Queue\Exception\Exception; use tests\app\PriorityJob; use tests\app\RetryJob; use tests\drivers\CliTestCase; @@ -135,7 +138,7 @@ public function testLater(): void public function testRetry(): void { $this->startProcess(['php', 'yii', 'queue/listen']); - $job = new RetryJob(['uid' => uniqid()]); + $job = new RetryJob(['uid' => uniqid('', true)]); $this->getQueue()->push($job); sleep(6); @@ -188,9 +191,10 @@ protected function getQueue(): Queue /** * @param Queue $yiiQueue - * @return mixed + * @return Context|AmqpContext + * @throws Exception */ - private function getNativeAMQPContext($yiiQueue) + private function getNativeAMQPContext(Queue $yiiQueue): Context|AmqpContext { $factory = new AmqpConnectionFactory([ 'host' => $yiiQueue->host, From 03408131e7d6603f53e74c49ea13c7f3670a18e7 Mon Sep 17 00:00:00 2001 From: Moiseenko Date: Thu, 5 Oct 2023 15:27:53 +0400 Subject: [PATCH 38/48] Improve amqp driver --- src/drivers/amqp_interop/Queue.php | 23 ++++++--- tests/app/config/main.php | 1 + tests/drivers/amqp_interop/AmqpTestCase.php | 56 +++++++++++++++++++++ tests/drivers/amqp_interop/QueueTest.php | 13 ++--- 4 files changed, 77 insertions(+), 16 deletions(-) create mode 100644 tests/drivers/amqp_interop/AmqpTestCase.php diff --git a/src/drivers/amqp_interop/Queue.php b/src/drivers/amqp_interop/Queue.php index e25dbd47dd..7a696fa590 100644 --- a/src/drivers/amqp_interop/Queue.php +++ b/src/drivers/amqp_interop/Queue.php @@ -32,6 +32,7 @@ * Amqp Queue. * * @property-read AmqpContext $context + * @property-read AmqpQueue $queue * * @author Maksym Kotliar * @since 2.0.2 @@ -275,6 +276,12 @@ class Queue extends CliQueue * @var bool */ protected bool $setupBrokerDone = false; + /** + * Created AmqpQueue instance + * + * @var AmqpQueue + */ + protected AmqpQueue $queue; /** * @inheritdoc @@ -476,11 +483,10 @@ protected function setupBroker(): void return; } - /** @var AmqpQueue $queue */ - $queue = $this->context->createQueue($this->queueName); - $queue->setFlags($this->queueFlags); - $queue->setArguments($this->queueOptionalArguments); - $this->context->declareQueue($queue); + $this->queue = $this->createQueue(); + $this->queue->setFlags($this->queueFlags); + $this->queue->setArguments($this->queueOptionalArguments); + $this->context->declareQueue($this->queue); /** @var AmqpTopic $topic */ $topic = $this->context->createTopic($this->exchangeName); @@ -488,7 +494,7 @@ protected function setupBroker(): void $topic->setFlags($this->exchangeFlags); $this->context->declareTopic($topic); - $this->context->bind(new AmqpBind($queue, $topic, $this->routingKey)); + $this->context->bind(new AmqpBind($this->queue, $topic, $this->routingKey)); $this->setupBrokerDone = true; } @@ -525,4 +531,9 @@ protected function redeliver(AmqpMessage $message): void $newMessage ); } + + private function createQueue(): AmqpQueue + { + return $this->context->createQueue($this->queueName); + } } diff --git a/tests/app/config/main.php b/tests/app/config/main.php index c908bfd037..047508603f 100644 --- a/tests/app/config/main.php +++ b/tests/app/config/main.php @@ -103,6 +103,7 @@ 'host' => getenv('RABBITMQ_HOST') ?: 'localhost', 'user' => getenv('RABBITMQ_USER') ?: 'guest', 'password' => getenv('RABBITMQ_PASSWORD') ?: 'guest', + 'port' => getenv('RABBITMQ_PORT') ?: 5672, 'queueOptionalArguments' => ['x-max-priority' => 10], 'queueName' => 'queue-interop', 'exchangeName' => 'exchange-interop', diff --git a/tests/drivers/amqp_interop/AmqpTestCase.php b/tests/drivers/amqp_interop/AmqpTestCase.php new file mode 100644 index 0000000000..31b783c645 --- /dev/null +++ b/tests/drivers/amqp_interop/AmqpTestCase.php @@ -0,0 +1,56 @@ +purgeQueue(); + } + + /** + * @return Queue + */ + protected function getQueue(): Queue + { + $this->activeQueue = true; + + return Yii::$app->amqpInteropQueue; + } + + private function purgeQueue(): void + { + if ($this->activeQueue) { + $queue = $this->getQueue(); + + $connection = new AMQPStreamConnection( + $queue->host, + $queue->port, + $queue->user, + $queue->password + ); + $channel = $connection->channel(); + $channel->queue_bind($queue->queueName, $queue->exchangeName); + $channel->queue_purge($queue->queueName); + sleep(5); + } + } +} diff --git a/tests/drivers/amqp_interop/QueueTest.php b/tests/drivers/amqp_interop/QueueTest.php index e4a13497c0..8bdf826cb6 100644 --- a/tests/drivers/amqp_interop/QueueTest.php +++ b/tests/drivers/amqp_interop/QueueTest.php @@ -21,7 +21,6 @@ use Interop\Queue\Exception\Exception; use tests\app\PriorityJob; use tests\app\RetryJob; -use tests\drivers\CliTestCase; use Yii; use yii\queue\amqp_interop\Queue; @@ -30,13 +29,15 @@ * * @author Maksym Kotliar */ -class QueueTest extends CliTestCase +class QueueTest extends AmqpTestCase { /** * Test working setter routing key */ public function testNativeSettingRoutingKey(): void { + $this->activeQueue = false; + $uniqRoutingKey = Yii::$app->security->generateRandomString(12); $message = new InteropAmqpMessage(); $message->setRoutingKey($uniqRoutingKey); @@ -181,14 +182,6 @@ public function testSignals(): void } } - /** - * @return Queue - */ - protected function getQueue(): Queue - { - return Yii::$app->amqpInteropQueue; - } - /** * @param Queue $yiiQueue * @return Context|AmqpContext From 8f35468d3d40595c2a4c99e8dc10397478f63f81 Mon Sep 17 00:00:00 2001 From: Moiseenko Date: Thu, 5 Oct 2023 16:16:25 +0400 Subject: [PATCH 39/48] Improve static analyzes --- .github/workflows/static.yml | 32 ++++++++++++++++++++++++++++++++ src/PushEvent.php | 4 ++-- src/Queue.php | 35 ++++++++++------------------------- src/cli/Action.php | 2 +- src/cli/Queue.php | 4 +++- src/drivers/db/Command.php | 3 --- src/drivers/file/Command.php | 3 --- src/drivers/gearman/Queue.php | 1 + src/drivers/redis/Command.php | 3 --- src/drivers/redis/Queue.php | 2 +- src/drivers/stomp/Command.php | 3 --- 11 files changed, 50 insertions(+), 42 deletions(-) create mode 100644 .github/workflows/static.yml diff --git a/.github/workflows/static.yml b/.github/workflows/static.yml new file mode 100644 index 0000000000..377d5683b2 --- /dev/null +++ b/.github/workflows/static.yml @@ -0,0 +1,32 @@ +on: + pull_request: + paths-ignore: + - 'docs/**' + - 'README.md' + - 'CHANGELOG.md' + - 'UPGRADE.md' + - '.gitignore' + - '.gitattributes' + - 'phpunit.xml.dist' + + push: + branches: [ 'master' ] + paths-ignore: + - 'docs/**' + - 'README.md' + - 'CHANGELOG.md' + - 'UPGRADE.md' + - '.gitignore' + - '.gitattributes' + - 'phpunit.xml.dist' + +name: static analysis + +jobs: + psalm: + uses: yiisoft/actions/.github/workflows/psalm.yml@master + with: + os: >- + ['ubuntu-latest'] + php: >- + [ '8.1', '8.2' ] diff --git a/src/PushEvent.php b/src/PushEvent.php index ecf0733514..947e0a6bdb 100644 --- a/src/PushEvent.php +++ b/src/PushEvent.php @@ -22,7 +22,7 @@ class PushEvent extends JobEvent */ public int $delay; /** - * @var mixed + * @var int|string|null */ - public $priority; + public string|int|null $priority; } diff --git a/src/Queue.php b/src/Queue.php index 4eb67aad47..280d9918c2 100644 --- a/src/Queue.php +++ b/src/Queue.php @@ -77,9 +77,9 @@ abstract class Queue extends Component */ public int $attempts = 1; - private $pushTtr; - private $pushDelay; - private $pushPriority; + private ?int $pushTtr = null; + private ?int $pushDelay = null; + private int|string|null $pushPriority = null; /** * @inheritdoc @@ -90,16 +90,10 @@ public function init(): void $this->serializer = Instance::ensure($this->serializer, SerializerInterface::class); - if (!is_numeric($this->ttr)) { - throw new InvalidConfigException('Default TTR must be integer.'); - } 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.'); - } if ($this->attempts <= 0) { throw new InvalidConfigException('Default attempts count must be greater that zero.'); } @@ -108,10 +102,10 @@ public function init(): void /** * Sets TTR for job execute. * - * @param int|mixed $value + * @param int|null $value * @return $this */ - public function ttr($value): static + public function ttr(?int $value): static { $this->pushTtr = $value; return $this; @@ -120,10 +114,10 @@ public function ttr($value): static /** * Sets delay for later execute. * - * @param int|mixed $value + * @param int|null $value * @return $this */ - public function delay($value): static + public function delay(?int $value): static { $this->pushDelay = $value; return $this; @@ -132,10 +126,10 @@ public function delay($value): static /** * Sets job priority. * - * @param mixed $value + * @param int|string|null $value * @return $this */ - public function priority($value): static + public function priority(int|string|null $value): static { $this->pushPriority = $value; return $this; @@ -172,16 +166,10 @@ public function push($job): int|string|null throw new InvalidArgumentException('Job must be instance of JobInterface.'); } - if (!is_numeric($event->ttr)) { - throw new InvalidArgumentException('Job TTR must be integer.'); - } 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.'); - } if ($event->delay < 0) { throw new InvalidArgumentException('Job delay must be positive.'); } @@ -238,10 +226,7 @@ protected function handleMessage(int|string $id, string $message, int $ttr, int } try { $event->result = $event->job->execute($this); - } catch (\Exception $error) { - $event->error = $error; - return $this->handleError($event); - } catch (\Throwable $error) { + } catch (\Exception|\Throwable $error) { $event->error = $error; return $this->handleError($event); } diff --git a/src/cli/Action.php b/src/cli/Action.php index 4918c0b263..3ee72af88a 100644 --- a/src/cli/Action.php +++ b/src/cli/Action.php @@ -37,7 +37,7 @@ public function init(): void { parent::init(); - if (!$this->queue && ($this->controller instanceof Command)) { + if ($this->controller instanceof Command) { $this->queue = $this->controller->queue; } if (!($this->controller instanceof ConsoleController)) { diff --git a/src/cli/Queue.php b/src/cli/Queue.php index 9ded70bc02..5dc67a4ec2 100644 --- a/src/cli/Queue.php +++ b/src/cli/Queue.php @@ -63,13 +63,14 @@ abstract class Queue extends BaseQueue implements BootstrapInterface * @var int|null current process ID of a worker. * @since 2.0.2 */ - private $_workerPid; + private ?int $_workerPid = null; /** * @return string command id */ protected function getCommandId(): string { + /** @psalm-suppress UndefinedClass */ foreach (Yii::$app->getComponents(false) as $id => $component) { if ($component === $this) { return Inflector::camel2id($id); @@ -102,6 +103,7 @@ protected function runWorker(callable $handler): ?int { $this->_workerPid = getmypid(); /** @var LoopInterface $loop */ + /** @psalm-suppress UndefinedClass */ $loop = Yii::createObject($this->loopConfig, [$this]); $event = new WorkerEvent(['loop' => $loop]); diff --git a/src/drivers/db/Command.php b/src/drivers/db/Command.php index 04047ce821..7ce572a139 100644 --- a/src/drivers/db/Command.php +++ b/src/drivers/db/Command.php @@ -69,9 +69,6 @@ public function actionRun(): ?int */ public function actionListen(int $timeout = 3): ?int { - if (!is_numeric($timeout)) { - throw new Exception('Timeout must be numeric.'); - } if ($timeout < 1) { throw new Exception('Timeout must be greater than zero.'); } diff --git a/src/drivers/file/Command.php b/src/drivers/file/Command.php index a7dbe26834..b6b8bcd9f2 100644 --- a/src/drivers/file/Command.php +++ b/src/drivers/file/Command.php @@ -69,9 +69,6 @@ public function actionRun(): ?int */ public function actionListen(int $timeout = 3): ?int { - if (!is_numeric($timeout)) { - throw new Exception('Timeout must be numeric.'); - } if ($timeout < 1) { throw new Exception('Timeout must be greater than zero.'); } diff --git a/src/drivers/gearman/Queue.php b/src/drivers/gearman/Queue.php index b9989d01e8..90d276faac 100644 --- a/src/drivers/gearman/Queue.php +++ b/src/drivers/gearman/Queue.php @@ -84,6 +84,7 @@ public function status($id): int return self::STATUS_WAITING; } + /** @psalm-suppress RedundantCondition */ if ($status[0] && $status[1]) { return self::STATUS_RESERVED; } diff --git a/src/drivers/redis/Command.php b/src/drivers/redis/Command.php index 380f7967fb..8b6e862e17 100644 --- a/src/drivers/redis/Command.php +++ b/src/drivers/redis/Command.php @@ -69,9 +69,6 @@ public function actionRun(): ?int */ public function actionListen(int $timeout = 3): ?int { - if (!is_numeric($timeout)) { - throw new Exception('Timeout must be numeric.'); - } if ($timeout < 1) { throw new Exception('Timeout must be greater than zero.'); } diff --git a/src/drivers/redis/Queue.php b/src/drivers/redis/Queue.php index 03327914d9..5396227ae4 100644 --- a/src/drivers/redis/Queue.php +++ b/src/drivers/redis/Queue.php @@ -156,7 +156,7 @@ protected function reserve(int $timeout): ?array } [$ttr, $message] = explode(';', $payload, 2); - $this->redis->zadd("$this->channel.reserved", time() + $ttr, $id); + $this->redis->zadd("$this->channel.reserved", time() + (int)$ttr, $id); $attempt = $this->redis->hincrby("$this->channel.attempts", $id, 1); return [$id, $message, $ttr, $attempt]; diff --git a/src/drivers/stomp/Command.php b/src/drivers/stomp/Command.php index 076691a949..87e70bd256 100644 --- a/src/drivers/stomp/Command.php +++ b/src/drivers/stomp/Command.php @@ -56,9 +56,6 @@ public function actionRun(): ?int */ public function actionListen(int $timeout = 3): ?int { - if (!is_numeric($timeout)) { - throw new Exception('Timeout must be numeric.'); - } if ($timeout < 1) { throw new Exception('Timeout must be greater that zero.'); } From 20a10c908b2b83003f4f0064816528d25677af9d Mon Sep 17 00:00:00 2001 From: Moiseenko Date: Thu, 5 Oct 2023 16:29:55 +0400 Subject: [PATCH 40/48] Fixed CI --- .github/workflows/static.yml | 18 ++++++++++++------ psalm.xml | 1 + 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/.github/workflows/static.yml b/.github/workflows/static.yml index 377d5683b2..add09840c2 100644 --- a/.github/workflows/static.yml +++ b/.github/workflows/static.yml @@ -24,9 +24,15 @@ name: static analysis jobs: psalm: - uses: yiisoft/actions/.github/workflows/psalm.yml@master - with: - os: >- - ['ubuntu-latest'] - php: >- - [ '8.1', '8.2' ] + name: PHP ${{ matrix.php }} + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + php: [ '8.1', '8.2' ] + steps: + - name: Checkout. + uses: actions/checkout@v2 + + - name: Run static analyzes for PHP ${{ matrix.php }} + run: make static-analyze v=${{ matrix.php }} diff --git a/psalm.xml b/psalm.xml index 3b35278eed..8a030fcb1b 100644 --- a/psalm.xml +++ b/psalm.xml @@ -13,6 +13,7 @@ + From 868273ed5a8b2312819ddc1025a4e9c807457d34 Mon Sep 17 00:00:00 2001 From: Moiseenko Date: Thu, 5 Oct 2023 16:31:21 +0400 Subject: [PATCH 41/48] Fixed CI --- Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/Makefile b/Makefile index a864b24347..affed65dc0 100644 --- a/Makefile +++ b/Makefile @@ -22,6 +22,7 @@ sh: ## Enter the container with the application docker exec -it yii2-queue-php sh static-analyze: ## Run code static analyze. Params: {{ v=8.1 }}. Default latest PHP 8.1 + PHP_VERSION=$(filter-out $@,$(v)) docker-compose build --pull yii2-queue-php PHP_VERSION=$(filter-out $@,$(v)) docker-compose run yii2-queue-php vendor/bin/psalm --config=psalm.xml --shepherd --stats --php-version=$(v) make down From 82142da9390531b9c742afab742bd477e3f2d491 Mon Sep 17 00:00:00 2001 From: Moiseenko Date: Thu, 5 Oct 2023 16:37:27 +0400 Subject: [PATCH 42/48] Fixed CI --- .github/workflows/static.yml | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/.github/workflows/static.yml b/.github/workflows/static.yml index add09840c2..d9d868552c 100644 --- a/.github/workflows/static.yml +++ b/.github/workflows/static.yml @@ -22,6 +22,17 @@ on: name: static analysis +env: + COMPOSE_PROJECT_NAME: yii2-queue + COMPOSE_FILE: tests/docker-compose.yml + AWS_SQS_ENABLED: ${{ secrets.AWS_SQS_ENABLED }} + AWS_SQS_URL: ${{ secrets.AWS_SQS_URL }} + AWS_KEY: ${{ secrets.AWS_KEY }} + AWS_SECRET: ${{ secrets.AWS_SECRET }} + AWS_REGION: ${{ secrets.AWS_REGION }} + AWS_SQS_FIFO_ENABLED: ${{ secrets.AWS_SQS_FIFO_ENABLED }} + AWS_SQS_FIFO_URL: ${{ secrets.AWS_SQS_FIFO_URL }} + AWS_SQS_FIFO_MESSAGE_GROUP_ID: ${{ secrets.AWS_SQS_FIFO_MESSAGE_GROUP_ID }} jobs: psalm: name: PHP ${{ matrix.php }} From 178dec28b3b1597780f80002232f1cbf121bf041 Mon Sep 17 00:00:00 2001 From: Moiseenko Date: Tue, 10 Oct 2023 21:25:51 +0400 Subject: [PATCH 43/48] Improved test for AMQP driver --- Makefile | 2 +- phpunit.xml.dist | 2 + src/drivers/amqp_interop/Queue.php | 11 +- tests/docker/php/Dockerfile | 5 +- tests/drivers/TestCase.php | 4 +- tests/drivers/amqp_interop/AmqpTestCase.php | 103 ++++++++++-- tests/drivers/amqp_interop/QueueTest.php | 175 +++++++++----------- 7 files changed, 176 insertions(+), 126 deletions(-) diff --git a/Makefile b/Makefile index affed65dc0..138991334c 100644 --- a/Makefile +++ b/Makefile @@ -7,7 +7,7 @@ build: ## Build an image from a docker-compose file. Params: {{ v=8.1 }}. Defa test: ## Run tests. Params: {{ v=8.1 }}. Default latest PHP 8.1 PHP_VERSION=$(filter-out $@,$(v)) docker-compose build --pull yii2-queue-php - PHP_VERSION=$(filter-out $@,$(v)) docker-compose run yii2-queue-php vendor/bin/phpunit --colors=always --coverage-clover coverage.xml + PHP_VERSION=$(filter-out $@,$(v)) docker-compose run yii2-queue-php vendor/bin/phpunit --coverage-clover coverage.xml make down down: ## Stop and remove containers, networks diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 413988cfae..9527182802 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -6,6 +6,8 @@ stopOnFailure="false" xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/10.3/phpunit.xsd" cacheDirectory=".phpunit.cache" + displayDetailsOnIncompleteTests="true" + displayDetailsOnSkippedTests="true" > diff --git a/src/drivers/amqp_interop/Queue.php b/src/drivers/amqp_interop/Queue.php index 7a696fa590..c7f25b0c91 100644 --- a/src/drivers/amqp_interop/Queue.php +++ b/src/drivers/amqp_interop/Queue.php @@ -23,6 +23,7 @@ use Interop\Amqp\AmqpQueue; use Interop\Amqp\AmqpTopic; use Interop\Amqp\Impl\AmqpBind; +use Interop\Queue\Context; use yii\base\Application as BaseApp; use yii\base\Event; use yii\base\NotSupportedException; @@ -59,7 +60,7 @@ class Queue extends CliQueue * * @var string|null */ - public ?string $host; + public ?string $host = null; /** * The message queue broker's port. * @@ -71,13 +72,13 @@ class Queue extends CliQueue * * @var string|null */ - public ?string $user; + public ?string $user = null; /** * This is RabbitMQ password which is used to login on the broker. * * @var string|null */ - public ?string $password; + public ?string $password = null; /** * Virtual hosts provide logical grouping and separation of resources. * @@ -256,9 +257,9 @@ class Queue extends CliQueue /** * Amqp interop context. * - * @var AmqpContext|null + * @var AmqpContext|Context|null */ - protected ?AmqpContext $context = null; + protected AmqpContext|null|Context $context = null; /** * List of supported amqp interop drivers. * diff --git a/tests/docker/php/Dockerfile b/tests/docker/php/Dockerfile index c806cdb70f..da2ee33bb8 100644 --- a/tests/docker/php/Dockerfile +++ b/tests/docker/php/Dockerfile @@ -1,3 +1,4 @@ +# Important! Do not use this image in production! ARG PHP_VERSION FROM --platform=linux/amd64 php:${PHP_VERSION}-cli-alpine @@ -10,8 +11,8 @@ RUN echo https://dl-cdn.alpinelinux.org/alpine/edge/main >> /etc/apk/repositorie RUN apk add git icu-dev libpq-dev gearman-dev libcrypto3 openssl-dev autoconf g++ make linux-headers rabbitmq-c-dev RUN docker-php-ext-install pcntl bcmath pdo_mysql intl pdo_pgsql sockets opcache -RUN pecl install igbinary pcov amqp-1.11.0 -RUN docker-php-ext-enable igbinary pcov amqp +RUN pecl install igbinary pcov amqp-1.11.0 xdebug +RUN docker-php-ext-enable igbinary pcov amqp xdebug # Official gearman package not supported PHP 8.1 now RUN TMPDIR=$(mktemp -d) \ diff --git a/tests/drivers/TestCase.php b/tests/drivers/TestCase.php index b21496e12e..287447ca81 100644 --- a/tests/drivers/TestCase.php +++ b/tests/drivers/TestCase.php @@ -32,7 +32,7 @@ abstract protected function getQueue(): Queue; protected function createSimpleJob(): SimpleJob { return new SimpleJob([ - 'uid' => uniqid(), + 'uid' => uniqid('', true), ]); } @@ -54,7 +54,7 @@ protected function assertSimpleJobDone(SimpleJob $job): void * @param SimpleJob $job * @param int $delay */ - protected function assertSimpleJobLaterDone(SimpleJob $job, $delay): void + protected function assertSimpleJobLaterDone(SimpleJob $job, int $delay): void { $time = time() + $delay; sleep($delay); diff --git a/tests/drivers/amqp_interop/AmqpTestCase.php b/tests/drivers/amqp_interop/AmqpTestCase.php index 31b783c645..e8df7c9312 100644 --- a/tests/drivers/amqp_interop/AmqpTestCase.php +++ b/tests/drivers/amqp_interop/AmqpTestCase.php @@ -10,47 +10,116 @@ namespace tests\drivers\amqp_interop; +use Enqueue\AmqpLib\AmqpConnectionFactory; +use Enqueue\AmqpLib\AmqpContext; +use Interop\Amqp\AmqpDestination; +use Interop\Amqp\Impl\AmqpBind; +use Interop\Amqp\AmqpTopic; +use Interop\Queue\Context; +use Interop\Queue\Exception\Exception; use PhpAmqpLib\Connection\AMQPStreamConnection; use tests\drivers\CliTestCase; use Yii; +use yii\base\InvalidConfigException; use yii\queue\amqp_interop\Queue; abstract class AmqpTestCase extends CliTestCase { - public bool $activeQueue = false; + public ?string $queueName = null; + public ?string $exchangeName = null; + public ?string $routingKey = null; + public string $exchangeType = AmqpTopic::TYPE_DIRECT; + public int $flags = AmqpDestination::FLAG_DURABLE; protected function tearDown(): void { - parent::tearDown(); + $this->routingKey = null; + $this->exchangeName = null; + $this->queueName = null; $this->purgeQueue(); + + parent::tearDown(); } /** + * @param bool $createObject * @return Queue + * @throws InvalidConfigException */ - protected function getQueue(): Queue + protected function getQueue(bool $createObject = false): Queue { - $this->activeQueue = true; - + if ($createObject) { + /** @var Queue $object */ + $object = Yii::createObject(array_merge( + $this->getConnectionConfig(), + [ + 'class' => Queue::class, + 'password' => getenv('RABBITMQ_PASSWORD') ?: 'guest', + 'queueOptionalArguments' => ['x-max-priority' => 10], + 'queueName' => 'queue-interop', + 'exchangeName' => 'exchange-interop', + ] + )); + return $object; + } return Yii::$app->amqpInteropQueue; } + /** + * @return Context|AmqpContext + * @throws Exception + */ + protected function getAMQPContext(): Context|AmqpContext + { + $factory = new AmqpConnectionFactory(array_merge( + $this->getConnectionConfig(), + [ + 'pass' => getenv('RABBITMQ_PASSWORD') ?: 'guest', + ] + )); + $context = $factory->createContext(); + + $queue = $context->createQueue($this->queueName); + $queue->addFlag($this->flags); + $queue->setArguments(['x-max-priority' => 10]); + $context->declareQueue($queue); + + $topic = $context->createTopic($this->exchangeName); + $topic->setType($this->exchangeType); + $topic->addFlag($this->flags); + $context->declareTopic($topic); + + $context->bind(new AmqpBind($queue, $topic, $this->routingKey)); + + return $context; + } + + private function getAmqpConnection(): AMQPStreamConnection + { + return new AMQPStreamConnection( + getenv('RABBITMQ_HOST') ?: 'localhost', + getenv('RABBITMQ_PORT') ?: 5672, + getenv('RABBITMQ_USER') ?: 'guest', + getenv('RABBITMQ_PASSWORD') ?: 'guest' + ); + } + private function purgeQueue(): void { - if ($this->activeQueue) { - $queue = $this->getQueue(); - - $connection = new AMQPStreamConnection( - $queue->host, - $queue->port, - $queue->user, - $queue->password - ); + if (null !== $this->queueName) { + $connection = $this->getAmqpConnection(); $channel = $connection->channel(); - $channel->queue_bind($queue->queueName, $queue->exchangeName); - $channel->queue_purge($queue->queueName); - sleep(5); + $channel->queue_purge($this->queueName, true); } } + + private function getConnectionConfig(): array + { + return [ + 'host' => getenv('RABBITMQ_HOST') ?: 'localhost', + 'user' => getenv('RABBITMQ_USER') ?: 'guest', + 'port' => getenv('RABBITMQ_PORT') ?: 5672, + ]; + } } diff --git a/tests/drivers/amqp_interop/QueueTest.php b/tests/drivers/amqp_interop/QueueTest.php index 8bdf826cb6..211ade1371 100644 --- a/tests/drivers/amqp_interop/QueueTest.php +++ b/tests/drivers/amqp_interop/QueueTest.php @@ -10,15 +10,9 @@ namespace tests\drivers\amqp_interop; -use Enqueue\AmqpLib\AmqpConnectionFactory; -use Enqueue\AmqpLib\AmqpContext; +use Interop\Amqp\AmqpConsumer; use Interop\Amqp\AmqpMessage; -use Interop\Amqp\AmqpQueue; -use Interop\Amqp\AmqpTopic; -use Interop\Amqp\Impl\AmqpBind; use Interop\Amqp\Impl\AmqpMessage as InteropAmqpMessage; -use Interop\Queue\Context; -use Interop\Queue\Exception\Exception; use tests\app\PriorityJob; use tests\app\RetryJob; use Yii; @@ -36,7 +30,8 @@ class QueueTest extends AmqpTestCase */ public function testNativeSettingRoutingKey(): void { - $this->activeQueue = false; + $this->exchangeName = null; + $this->queueName = null; $uniqRoutingKey = Yii::$app->security->generateRandomString(12); $message = new InteropAmqpMessage(); @@ -45,79 +40,6 @@ public function testNativeSettingRoutingKey(): void $this->assertSame($uniqRoutingKey, $message->getRoutingKey()); } - /** - * Sending a message to a queue using RoutingKey - */ - public function testSendMessageWithRoutingKey(): void - { - $uniqKey = Yii::$app->security->generateRandomString(12); - $receivedRoutingKey = null; - - $yiiQueue = $this->getQueue(); - $yiiQueue->routingKey = $uniqKey; - $yiiQueue->push($this->createSimpleJob()); - - $context = $this->getNativeAMQPContext($yiiQueue); - - $queue = $context->createQueue($yiiQueue->queueName); - $consumer = $context->createConsumer($queue); - $callback = function (AmqpMessage $message) use (&$receivedRoutingKey) { - $receivedRoutingKey = $message->getRoutingKey(); - return true; - }; - $subscriptionConsumer = $context->createSubscriptionConsumer(); - $subscriptionConsumer->subscribe($consumer, $callback); - $subscriptionConsumer->consume(1000); - - sleep(3); - - $this->assertSame($yiiQueue->routingKey, $receivedRoutingKey); - } - - /** - * Test push message with headers - * @return void - */ - public function testPushMessageWithHeaders(): void - { - $actualHeaders = []; - $messageHeaders = [ - 'header-1' => 'header-value-1', - 'header-2' => 'header-value-2', - ]; - - $yiiQueue = $this->getQueue(); - $yiiQueue->setMessageHeaders = $messageHeaders; - $yiiQueue->push($this->createSimpleJob()); - - $context = $this->getNativeAMQPContext($yiiQueue); - - $queue = $context->createQueue($yiiQueue->queueName); - $consumer = $context->createConsumer($queue); - $callback = function (AmqpMessage $message) use (&$actualHeaders) { - /** - * This not mistake. In original package this function mixed up - * getHeaders() => getProperties() - */ - $actualHeaders = $message->getProperties(); - return true; - }; - $subscriptionConsumer = $context->createSubscriptionConsumer(); - $subscriptionConsumer->subscribe($consumer, $callback); - $subscriptionConsumer->consume(1000); - - sleep(3); - - $expectedHeaders = array_merge( - $messageHeaders, - [ - Queue::ATTEMPT => 1, - Queue::TTR => 300, - ] - ); - $this->assertEquals($expectedHeaders, $actualHeaders); - } - public function testListen(): void { $this->startProcess(['php', 'yii', 'queue/listen']); @@ -183,29 +105,84 @@ public function testSignals(): void } /** - * @param Queue $yiiQueue - * @return Context|AmqpContext - * @throws Exception + * Sending a message to a queue using RoutingKey + */ + public function testSendMessageWithRoutingKey(): void + { + $this->queueName = 'routing-key'; + $this->exchangeName = 'routing-key'; + $this->routingKey = Yii::$app->security->generateRandomString(10); + + $receivedRoutingKey = null; + + $queue = $this->getQueue(true); + $queue->exchangeName = $this->exchangeName; + $queue->queueName = $this->queueName; + $queue->routingKey = $this->routingKey; + $queue->push($this->createSimpleJob()); + + $context = $this->getAMQPContext(); + $consumer = $context->createConsumer( + $context->createQueue($this->queueName) + ); + $callback = function (AmqpMessage $message, AmqpConsumer $consumer) use (&$receivedRoutingKey) { + $receivedRoutingKey = $message->getRoutingKey(); + $consumer->acknowledge($message); + return true; + }; + $subscriptionConsumer = $context->createSubscriptionConsumer(); + $subscriptionConsumer->subscribe($consumer, $callback); + $subscriptionConsumer->consume(1000); + + $this->assertSame($this->routingKey, $receivedRoutingKey); + } + + /** + * Test push message with headers + * @return void */ - private function getNativeAMQPContext(Queue $yiiQueue): Context|AmqpContext + public function testPushMessageWithHeaders(): void { - $factory = new AmqpConnectionFactory([ - 'host' => $yiiQueue->host, - ]); - $context = $factory->createContext(); + $this->queueName = 'message-headers'; + $this->exchangeName = 'message-headers'; + + $actualHeaders = []; + $messageHeaders = [ + 'header-1' => 'header-value-1', + 'header-2' => 'header-value-2', + ]; - $queue = $context->createQueue($yiiQueue->queueName); - $queue->addFlag(AmqpQueue::FLAG_DURABLE); - $queue->setArguments(['x-max-priority' => 10]); - $context->declareQueue($queue); + $queue = $this->getQueue(true); + $queue->exchangeName = $this->exchangeName; + $queue->queueName = $this->queueName; + $queue->setMessageHeaders = $messageHeaders; + $queue->push($this->createSimpleJob()); - $topic = $context->createTopic($yiiQueue->exchangeName); - $topic->setType($yiiQueue->exchangeType); - $topic->addFlag(AmqpTopic::FLAG_DURABLE); - $context->declareTopic($topic); + $context = $this->getAMQPContext(); + $consumer = $context->createConsumer( + $context->createQueue($this->queueName) + ); + $callback = function (AmqpMessage $message, AmqpConsumer $consumer) use (&$actualHeaders) { + /** + * This not mistake. In original package this function mixed up + * getHeaders() => getProperties() + */ + $actualHeaders = $message->getProperties(); + $consumer->acknowledge($message); + return true; + }; + $subscriptionConsumer = $context->createSubscriptionConsumer(); + $subscriptionConsumer->subscribe($consumer, $callback); + $subscriptionConsumer->consume(1000); - $context->bind(new AmqpBind($queue, $topic, $yiiQueue->routingKey)); - return $context; + $expectedHeaders = array_merge( + $messageHeaders, + [ + Queue::ATTEMPT => 1, + Queue::TTR => 300, + ] + ); + $this->assertEquals($expectedHeaders, $actualHeaders); } } From 375419440c700480197925694bdc3201577bd031 Mon Sep 17 00:00:00 2001 From: Moiseenko Date: Thu, 12 Oct 2023 11:37:49 +0400 Subject: [PATCH 44/48] Change testsuite name --- phpunit.xml.dist | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 9527182802..5babaa3c2b 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -10,7 +10,7 @@ displayDetailsOnSkippedTests="true" > - + ./tests ./tests/app ./tests/docker From d40f76777ea1b5cb6aa9a0e2977815a21abeeb33 Mon Sep 17 00:00:00 2001 From: Moiseenko Date: Thu, 12 Oct 2023 12:00:06 +0400 Subject: [PATCH 45/48] Using constructor property promotion --- src/InvalidJobException.php | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/InvalidJobException.php b/src/InvalidJobException.php index 0d73b20f0f..a313dd5907 100644 --- a/src/InvalidJobException.php +++ b/src/InvalidJobException.php @@ -10,6 +10,7 @@ namespace yii\queue; +use Exception; use Throwable; /** @@ -20,22 +21,21 @@ * @author Roman Zhuravlev * @since 2.1.1 */ -class InvalidJobException extends \Exception +class InvalidJobException extends Exception { - /** - * @var string - */ - private string $serialized; - /** * @param string $serialized * @param string $message * @param int $code * @param Throwable|null $previous */ - public function __construct(string $serialized, $message = '', $code = 0, Throwable $previous = null) + public function __construct( + private string $serialized, + string $message = '', + int $code = 0, + Throwable $previous = null + ) { - $this->serialized = $serialized; parent::__construct($message, $code, $previous); } From 66d8518b4eb9277f9f030c9ae545aab7ea34ad9a Mon Sep 17 00:00:00 2001 From: Moiseenko Date: Thu, 12 Oct 2023 19:49:47 +0400 Subject: [PATCH 46/48] Improve SQS driver and fix tests --- .env.example | 9 ------- .github/workflows/main.yml | 8 ------ .github/workflows/static.yml | 8 ------ Makefile | 10 ++++++++ phpunit.xml.dist | 1 + psalm.xml | 1 - src/drivers/sqs/Command.php | 3 --- src/drivers/sqs/Queue.php | 17 ++++++------ tests/app/config/main.php | 40 ++++++++++++----------------- tests/docker-compose.yml | 32 ++++++++++++++++------- tests/drivers/sqs/FifoQueueTest.php | 18 +++---------- tests/drivers/sqs/QueueTest.php | 15 +---------- 12 files changed, 64 insertions(+), 98 deletions(-) diff --git a/.env.example b/.env.example index 545f0fa141..4ed48f603b 100644 --- a/.env.example +++ b/.env.example @@ -1,11 +1,2 @@ COMPOSE_PROJECT_NAME=yii2-queue COMPOSE_FILE=tests/docker-compose.yml - -AWS_SQS_ENABLED= -AWS_SQS_URL= -AWS_KEY= -AWS_SECRET= -AWS_REGION= -AWS_SQS_FIFO_ENABLED= -AWS_SQS_FIFO_URL= -AWS_SQS_FIFO_MESSAGE_GROUP_ID= diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 36ec37335c..8dadc45d9a 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -23,14 +23,6 @@ on: env: COMPOSE_PROJECT_NAME: yii2-queue COMPOSE_FILE: tests/docker-compose.yml - AWS_SQS_ENABLED: ${{ secrets.AWS_SQS_ENABLED }} - AWS_SQS_URL: ${{ secrets.AWS_SQS_URL }} - AWS_KEY: ${{ secrets.AWS_KEY }} - AWS_SECRET: ${{ secrets.AWS_SECRET }} - AWS_REGION: ${{ secrets.AWS_REGION }} - AWS_SQS_FIFO_ENABLED: ${{ secrets.AWS_SQS_FIFO_ENABLED }} - AWS_SQS_FIFO_URL: ${{ secrets.AWS_SQS_FIFO_URL }} - AWS_SQS_FIFO_MESSAGE_GROUP_ID: ${{ secrets.AWS_SQS_FIFO_MESSAGE_GROUP_ID }} jobs: phpunit: name: PHP ${{ matrix.php }} diff --git a/.github/workflows/static.yml b/.github/workflows/static.yml index d9d868552c..be42e8f9a2 100644 --- a/.github/workflows/static.yml +++ b/.github/workflows/static.yml @@ -25,14 +25,6 @@ name: static analysis env: COMPOSE_PROJECT_NAME: yii2-queue COMPOSE_FILE: tests/docker-compose.yml - AWS_SQS_ENABLED: ${{ secrets.AWS_SQS_ENABLED }} - AWS_SQS_URL: ${{ secrets.AWS_SQS_URL }} - AWS_KEY: ${{ secrets.AWS_KEY }} - AWS_SECRET: ${{ secrets.AWS_SECRET }} - AWS_REGION: ${{ secrets.AWS_REGION }} - AWS_SQS_FIFO_ENABLED: ${{ secrets.AWS_SQS_FIFO_ENABLED }} - AWS_SQS_FIFO_URL: ${{ secrets.AWS_SQS_FIFO_URL }} - AWS_SQS_FIFO_MESSAGE_GROUP_ID: ${{ secrets.AWS_SQS_FIFO_MESSAGE_GROUP_ID }} jobs: psalm: name: PHP ${{ matrix.php }} diff --git a/Makefile b/Makefile index 138991334c..860e68a78f 100644 --- a/Makefile +++ b/Makefile @@ -4,9 +4,13 @@ help: ## Display help information build: ## Build an image from a docker-compose file. Params: {{ v=8.1 }}. Default latest PHP 8.1 @cp -n .env.example .env PHP_VERSION=$(filter-out $@,$(v)) docker-compose up -d --build + make create-sqs-queue + make create-sqs-fifo-queue test: ## Run tests. Params: {{ v=8.1 }}. Default latest PHP 8.1 PHP_VERSION=$(filter-out $@,$(v)) docker-compose build --pull yii2-queue-php + make create-sqs-queue + make create-sqs-fifo-queue PHP_VERSION=$(filter-out $@,$(v)) docker-compose run yii2-queue-php vendor/bin/phpunit --coverage-clover coverage.xml make down @@ -35,3 +39,9 @@ clean: clean-all: clean sudo rm -rf tests/runtime/.composer* + +create-sqs-queue: ## Create SQS queue + docker exec -it yii2-queue-localstack awslocal sqs create-queue --queue-name yii2-queue + +create-sqs-fifo-queue: ## Create SQS FIFO queue + docker exec -it yii2-queue-localstack awslocal sqs create-queue --queue-name yii2-queue.fifo --attributes "FifoQueue=true" diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 5babaa3c2b..821636bb0d 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -8,6 +8,7 @@ cacheDirectory=".phpunit.cache" displayDetailsOnIncompleteTests="true" displayDetailsOnSkippedTests="true" + executionOrder="random" > diff --git a/psalm.xml b/psalm.xml index 8a030fcb1b..a4f56374a0 100644 --- a/psalm.xml +++ b/psalm.xml @@ -16,7 +16,6 @@ - diff --git a/src/drivers/sqs/Command.php b/src/drivers/sqs/Command.php index 5bd14c529a..3597e0af50 100644 --- a/src/drivers/sqs/Command.php +++ b/src/drivers/sqs/Command.php @@ -48,9 +48,6 @@ public function actionRun(): ?int */ public function actionListen(int $timeout = 3): ?int { - if (!is_numeric($timeout)) { - throw new Exception('Timeout must be numeric.'); - } if ($timeout < 1 || $timeout > 20) { throw new Exception('Timeout must be between 1 and 20'); } diff --git a/src/drivers/sqs/Queue.php b/src/drivers/sqs/Queue.php index 1618d0e8e5..21aad3237d 100644 --- a/src/drivers/sqs/Queue.php +++ b/src/drivers/sqs/Queue.php @@ -15,6 +15,7 @@ use yii\base\NotSupportedException; use yii\queue\cli\Queue as CliQueue; use yii\queue\serializers\JsonSerializer; +use yii\queue\serializers\SerializerInterface; /** * SQS Queue. @@ -64,12 +65,12 @@ class Queue extends CliQueue * Json serializer by default. * @inheritdoc */ - public string|array|\yii\queue\serializers\SerializerInterface $serializer = JsonSerializer::class; + public string|array|SerializerInterface $serializer = JsonSerializer::class; /** - * @var SqsClient + * @var SqsClient|null */ - private SqsClient $_client; + private ?SqsClient $client = null; /** * Listens queue and runs each job. @@ -173,7 +174,7 @@ public function status($id): int * @return bool * @since 2.2.1 */ - public function handle(string $id, string $message, int $ttr, int $attempt) + public function handle(string $id, string $message, int $ttr, int $attempt): bool { return $this->handleMessage($id, $message, $ttr, $attempt); } @@ -213,8 +214,8 @@ protected function pushMessage(string $payload, int $ttr, int $delay, mixed $pri */ protected function getClient(): SqsClient { - if ($this->_client) { - return $this->_client; + if (null !== $this->client) { + return $this->client; } if ($this->key !== null && $this->secret !== null) { @@ -228,11 +229,11 @@ protected function getClient(): SqsClient $credentials = CredentialProvider::defaultProvider(); } - $this->_client = new SqsClient([ + $this->client = new SqsClient([ 'credentials' => $credentials, 'region' => $this->region, 'version' => $this->version, ]); - return $this->_client; + return $this->client; } } diff --git a/tests/app/config/main.php b/tests/app/config/main.php index 047508603f..7b719c9462 100644 --- a/tests/app/config/main.php +++ b/tests/app/config/main.php @@ -31,6 +31,8 @@ 'amqpInteropQueue', 'beanstalkQueue', 'stompQueue', + 'sqsQueue', + 'sqsFifoQueue', ], 'components' => [ 'syncQueue' => [ @@ -116,6 +118,21 @@ 'class' => StompQueue::class, 'host' => getenv('ACTIVEMQ_HOST') ?: 'localhost', ], + 'sqsQueue' => [ + 'class' => SqsQueue::class, + 'url' => getenv('AWS_SQS_URL'), + 'key' => getenv('AWS_KEY'), + 'secret' => getenv('AWS_SECRET'), + 'region' => getenv('AWS_REGION'), + ], + 'sqsFifoQueue' => [ + 'class' => SqsQueue::class, + 'url' => getenv('AWS_SQS_FIFO_URL'), + 'key' => getenv('AWS_KEY'), + 'secret' => getenv('AWS_SECRET'), + 'region' => getenv('AWS_REGION'), + 'messageGroupId' => getenv('AWS_SQS_FIFO_MESSAGE_GROUP_ID'), + ], ], ]; @@ -127,27 +144,4 @@ ]; } -if (getenv('AWS_SQS_ENABLED')) { - $config['bootstrap'][] = 'sqsQueue'; - $config['components']['sqsQueue'] = [ - 'class' => SqsQueue::class, - 'url' => getenv('AWS_SQS_URL'), - 'key' => getenv('AWS_KEY'), - 'secret' => getenv('AWS_SECRET'), - 'region' => getenv('AWS_REGION'), - ]; -} - -if (getenv('AWS_SQS_FIFO_ENABLED')) { - $config['bootstrap'][] = 'sqsFifoQueue'; - $config['components']['sqsFifoQueue'] = [ - 'class' => SqsQueue::class, - 'url' => getenv('AWS_SQS_FIFO_URL'), - 'key' => getenv('AWS_KEY'), - 'secret' => getenv('AWS_SECRET'), - 'region' => getenv('AWS_REGION'), - 'messageGroupId' => getenv('AWS_SQS_FIFO_MESSAGE_GROUP_ID'), - ]; -} - return $config; diff --git a/tests/docker-compose.yml b/tests/docker-compose.yml index 1f22950d3c..84fd098128 100644 --- a/tests/docker-compose.yml +++ b/tests/docker-compose.yml @@ -32,15 +32,13 @@ services: BEANSTALK_HOST: beanstalk GEARMAN_HOST: gearmand COMPOSER_ALLOW_SUPERUSER: 1 - AWS_SQS_ENABLED: ${AWS_SQS_ENABLED} - AWS_KEY: ${AWS_KEY} - AWS_SECRET: ${AWS_SECRET} - AWS_REGION: ${AWS_REGION} - AWS_SQS_URL: ${AWS_SQS_URL} ACTIVEMQ_HOST: activemq - AWS_SQS_FIFO_ENABLED: ${AWS_SQS_FIFO_ENABLED} - AWS_SQS_FIFO_URL: ${AWS_SQS_FIFO_URL} - AWS_SQS_FIFO_MESSAGE_GROUP_ID: ${AWS_SQS_FIFO_MESSAGE_GROUP_ID} + AWS_KEY: ${AWS_KEY:-admin} + AWS_SECRET: ${AWS_SECRET:-admin} + AWS_REGION: ${AWS_REGION:-us-east-1} + AWS_SQS_URL: ${AWS_SQS_URL:-http://localstack:4566/000000000000/yii2-queue} + AWS_SQS_FIFO_URL: ${AWS_SQS_FIFO_URL:-http://localstack:4566/000000000000/yii2-queue.fifo} + AWS_SQS_FIFO_MESSAGE_GROUP_ID: ${AWS_SQS_FIFO_MESSAGE_GROUP_ID:-default} depends_on: - mysql - postgres @@ -49,6 +47,7 @@ services: - beanstalk - gearmand - activemq + - localstack networks: net: {} @@ -118,7 +117,22 @@ services: networks: net: {} + # https://hub.docker.com/r/localstack/localstack + localstack: + container_name: yii2-queue-localstack + image: localstack/localstack + restart: always + ports: + - "4566:4566" + environment: + AWS_DEFAULT_REGION: us-east-1 + AWS_ACCESS_KEY_ID: admin + AWS_SECRET_ACCESS_KEY: admin + SERVICES: sqs + DISABLE_CORS_CHECKS: 1 + networks: + net: {} + networks: net: name: yii2_queue_net - diff --git a/tests/drivers/sqs/FifoQueueTest.php b/tests/drivers/sqs/FifoQueueTest.php index bdf87582b3..5e59219b36 100644 --- a/tests/drivers/sqs/FifoQueueTest.php +++ b/tests/drivers/sqs/FifoQueueTest.php @@ -10,6 +10,7 @@ namespace tests\drivers\sqs; +use Aws\Sqs\Exception\SqsException; use tests\app\RetryJob; use tests\drivers\CliTestCase; use Yii; @@ -40,17 +41,17 @@ public function testListen(): void public function testFifoQueueDoesNotSupportPerMessageDelays(): void { + $this->expectException(SqsException::class); $this->startProcess(['php', 'yii', 'queue/listen', '1']); $job = $this->createSimpleJob(); - $this->setExpectedException('\Aws\Sqs\Exception\SqsException'); $this->getQueue()->delay(2)->push($job); } public function testRetry(): void { $this->startProcess(['php', 'yii', 'queue/listen', '1']); - $job = new RetryJob(['uid' => uniqid()]); + $job = new RetryJob(['uid' => uniqid('', true)]); $this->getQueue()->push($job); sleep(6); @@ -60,10 +61,6 @@ public function testRetry(): void public function testClear(): void { - if (!getenv('AWS_SQS_FIFO_CLEAR_TEST_ENABLED')) { - $this->markTestSkipped(__METHOD__ . ' is disabled'); - } - $this->getQueue()->push($this->createSimpleJob()); $this->runProcess(['php', 'yii', 'queue/clear', '--interactive=0']); } @@ -75,13 +72,4 @@ protected function getQueue(): Queue { return Yii::$app->sqsFifoQueue; } - - protected function setUp(): void - { - if (!getenv('AWS_SQS_FIFO_ENABLED')) { - $this->markTestSkipped('AWS SQS FIFO tests are disabled'); - } - - parent::setUp(); - } } diff --git a/tests/drivers/sqs/QueueTest.php b/tests/drivers/sqs/QueueTest.php index 253674326a..acfb14b36f 100644 --- a/tests/drivers/sqs/QueueTest.php +++ b/tests/drivers/sqs/QueueTest.php @@ -52,7 +52,7 @@ public function testLater(): void public function testRetry(): void { $this->startProcess(['php', 'yii', 'queue/listen', '1']); - $job = new RetryJob(['uid' => uniqid()]); + $job = new RetryJob(['uid' => uniqid('', true)]); $this->getQueue()->push($job); sleep(6); @@ -62,10 +62,6 @@ public function testRetry(): void public function testClear(): void { - if (!getenv('AWS_SQS_CLEAR_TEST_ENABLED')) { - $this->markTestSkipped(__METHOD__ . ' is disabled'); - } - $this->getQueue()->push($this->createSimpleJob()); $this->runProcess(['php', 'yii', 'queue/clear', '--interactive=0']); } @@ -77,13 +73,4 @@ protected function getQueue(): Queue { return Yii::$app->sqsQueue; } - - protected function setUp(): void - { - if (!getenv('AWS_SQS_ENABLED')) { - $this->markTestSkipped('AWS SQS tests are disabled'); - } - - parent::setUp(); - } } From 5d600e7255f031d35de1433b19f75e8e5c4469ad Mon Sep 17 00:00:00 2001 From: Moiseenko Date: Thu, 12 Oct 2023 20:00:05 +0400 Subject: [PATCH 47/48] Updated documentation for SQS driver --- docs/guide-ru/driver-sqs.md | 26 +++++++++- docs/guide-zh-CN/driver-sqs.md | 86 ++++++++++++++++++++++++++++++++++ 2 files changed, 111 insertions(+), 1 deletion(-) create mode 100644 docs/guide-zh-CN/driver-sqs.md diff --git a/docs/guide-ru/driver-sqs.md b/docs/guide-ru/driver-sqs.md index c7332a9dc5..f99aa818d7 100644 --- a/docs/guide-ru/driver-sqs.md +++ b/docs/guide-ru/driver-sqs.md @@ -10,7 +10,7 @@ ```php return [ 'bootstrap' => [ - 'queue', // The component registers own console commands + 'queue', // Компонент регистрирует собственные консольные команды ], 'components' => [ 'queue' => [ @@ -24,6 +24,30 @@ return [ ]; ``` +Пример настройки для FIFO очередей: + +```php +return [ + 'bootstrap' => [ + 'queue', // Компонент регистрирует собственные консольные команды + ], + 'components' => [ + 'queue' => [ + 'class' => \yii\queue\sqs\Queue::class, + 'url' => '', + 'key' => '', + 'secret' => '', + 'region' => '', + 'messageGroupId' => '', + ], + ], +]; +``` + +Идентификатор группы сообщений требуется SQS для очередей FIFO. Вы можете настроить свои собственные или использовать значение "default". + +Идентификатор дедупликации генерируется автоматически, поэтому независимо от того, активировали ли вы дедупликацию на основе содержимого в очереди SQS или нет, этот идентификатор будет использоваться. + Консоль ------- diff --git a/docs/guide-zh-CN/driver-sqs.md b/docs/guide-zh-CN/driver-sqs.md new file mode 100644 index 0000000000..504050415d --- /dev/null +++ b/docs/guide-zh-CN/driver-sqs.md @@ -0,0 +1,86 @@ +AWS SQS Driver +============ + +The driver uses AWS SQS to store queue data. + +You have to add `aws/aws-sdk-php` extension to your application in order to use it. + +Configuration example for standard queues: + +```php +return [ + 'bootstrap' => [ + 'queue', // The component registers own console commands + ], + 'components' => [ + 'queue' => [ + 'class' => \yii\queue\sqs\Queue::class, + 'url' => '', + 'key' => '', + 'secret' => '', + 'region' => '', + ], + ], +]; +``` + +Configuration example for FIFO queues: + +```php +return [ + 'bootstrap' => [ + 'queue', // The component registers own console commands + ], + 'components' => [ + 'queue' => [ + 'class' => \yii\queue\sqs\Queue::class, + 'url' => '', + 'key' => '', + 'secret' => '', + 'region' => '', + 'messageGroupId' => '', + ], + ], +]; +``` + +The message group ID is required by SQS for FIFO queues. You can configure your own or use the "default" value. + +The deduplication ID is generated automatically, so no matter if you have activated content-based deduplication in the SQS queue or not, this ID will be used. + +Console +------- + +Console command is used to execute tasks. + +```sh +yii queue/listen [timeout] +``` + +`listen` command launches a daemon which infinitely queries the queue. If there are new tasks +they're immediately obtained and executed. `timeout` parameter is number of seconds to wait a job. +It uses SQS "Long Polling" feature, that holds a connection between client and a queue. + +**Important:** `timeout` parameter for SQS driver must be in range between 0 and 20 seconds. + +This method is most efficient when command is properly daemonized via +[supervisor](worker.md#supervisor) or [systemd](worker.md#systemd). + +```sh +yii queue/run +``` + +`run` command obtains and executes tasks in a loop until queue is empty. Works well with +[cron](worker.md#cron). + +`run` and `listen` commands have options: + +- `--verbose`, `-v`: print executing statuses into console. +- `--isolate`: each task is executed in a separate child process. +- `--color`: highlighting for verbose mode. + +```sh +yii queue/clear +``` + +`clear` command clears a queue. From d20dbc37ca8ab9a145ad746f9c272f9897efaa2d Mon Sep 17 00:00:00 2001 From: Moiseenko Date: Thu, 12 Oct 2023 20:26:31 +0400 Subject: [PATCH 48/48] Fix CI --- Makefile | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/Makefile b/Makefile index 860e68a78f..7f260cc750 100644 --- a/Makefile +++ b/Makefile @@ -8,9 +8,7 @@ build: ## Build an image from a docker-compose file. Params: {{ v=8.1 }}. Defa make create-sqs-fifo-queue test: ## Run tests. Params: {{ v=8.1 }}. Default latest PHP 8.1 - PHP_VERSION=$(filter-out $@,$(v)) docker-compose build --pull yii2-queue-php - make create-sqs-queue - make create-sqs-fifo-queue + make build PHP_VERSION=$(filter-out $@,$(v)) docker-compose run yii2-queue-php vendor/bin/phpunit --coverage-clover coverage.xml make down @@ -41,7 +39,7 @@ clean-all: clean sudo rm -rf tests/runtime/.composer* create-sqs-queue: ## Create SQS queue - docker exec -it yii2-queue-localstack awslocal sqs create-queue --queue-name yii2-queue + docker exec yii2-queue-localstack sh -c "awslocal sqs create-queue --queue-name yii2-queue" create-sqs-fifo-queue: ## Create SQS FIFO queue - docker exec -it yii2-queue-localstack awslocal sqs create-queue --queue-name yii2-queue.fifo --attributes "FifoQueue=true" + docker exec yii2-queue-localstack sh -c 'awslocal sqs create-queue --queue-name yii2-queue.fifo --attributes "FifoQueue=true"'