From 5349ac93b646007d65d6389c8045111131f23e5d Mon Sep 17 00:00:00 2001 From: lehaa22 <60298059+lehaa22@users.noreply.github.com> Date: Thu, 2 Nov 2023 10:57:55 +0500 Subject: [PATCH 01/22] fix 500 --- src/drivers/db/migrations/M211218163000JobQueueSize.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/drivers/db/migrations/M211218163000JobQueueSize.php b/src/drivers/db/migrations/M211218163000JobQueueSize.php index 13fda7526..a9d9fa54b 100644 --- a/src/drivers/db/migrations/M211218163000JobQueueSize.php +++ b/src/drivers/db/migrations/M211218163000JobQueueSize.php @@ -22,14 +22,14 @@ class M211218163000JobQueueSize extends Migration public function up() { if ($this->db->driverName === 'mysql') { - $this->alterColumn('{{%queue}}', 'job', 'LONGBLOB NOT NULL'); + $this->alterColumn($this->tableName, 'job', 'LONGBLOB NOT NULL'); } } public function down() { if ($this->db->driverName === 'mysql') { - $this->alterColumn('{{%queue}}', 'job', $this->binary()->notNull()); + $this->alterColumn($this->tableName, 'job', $this->binary()->notNull()); } } } From ab00a79323907710f44ff6c556662ee1a4e1cac0 Mon Sep 17 00:00:00 2001 From: Tim Kelty Date: Fri, 17 Nov 2023 05:18:37 -0500 Subject: [PATCH 02/22] Pass TTR StringValue as a string (#502) --- src/drivers/sqs/Queue.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/drivers/sqs/Queue.php b/src/drivers/sqs/Queue.php index 898ea019a..486c38147 100644 --- a/src/drivers/sqs/Queue.php +++ b/src/drivers/sqs/Queue.php @@ -200,7 +200,7 @@ protected function pushMessage($message, $ttr, $delay, $priority) 'MessageAttributes' => [ 'TTR' => [ 'DataType' => 'Number', - 'StringValue' => $ttr, + 'StringValue' => (string) $ttr, ], ], ]; From 68bac915195c534a4a20481c8479439b6d465c4c Mon Sep 17 00:00:00 2001 From: Moiseenko Date: Fri, 24 Nov 2023 20:46:49 +0300 Subject: [PATCH 03/22] Added PHP 8.3 to CI runners --- .github/workflows/main.yml | 2 +- .github/workflows/static.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 8dadc45d9..eb0b97723 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -30,7 +30,7 @@ jobs: strategy: fail-fast: false matrix: - php: [ '8.1', '8.2' ] + php: [ '8.1', '8.2', '8.3' ] steps: - name: Checkout. uses: actions/checkout@v2 diff --git a/.github/workflows/static.yml b/.github/workflows/static.yml index be42e8f9a..7e37c591d 100644 --- a/.github/workflows/static.yml +++ b/.github/workflows/static.yml @@ -32,7 +32,7 @@ jobs: strategy: fail-fast: false matrix: - php: [ '8.1', '8.2' ] + php: [ '8.1', '8.2', '8.3' ] steps: - name: Checkout. uses: actions/checkout@v2 From aa4b1678a99241d5ce5e954df5a1967298ce86f1 Mon Sep 17 00:00:00 2001 From: Andrew Ivchenkov Date: Fri, 5 Jan 2024 11:00:38 +0300 Subject: [PATCH 04/22] Added support for symfony/process:^7.0 (#508) --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 200893e77..0aca9187e 100644 --- a/composer.json +++ b/composer.json @@ -18,7 +18,7 @@ "require": { "php": ">=5.5.0", "yiisoft/yii2": "~2.0.14", - "symfony/process": "^3.3||^4.0||^5.0||^6.0" + "symfony/process": "^3.3||^4.0||^5.0||^6.0||^7.0" }, "require-dev": { "yiisoft/yii2-redis": "~2.0.0", From 9f839ba3934cb9f9770d9fa8c5f51585d59cbe75 Mon Sep 17 00:00:00 2001 From: EAMoiseenko Date: Sat, 6 Jan 2024 12:04:53 +0300 Subject: [PATCH 05/22] Fixed UndefinedVariable for psalm 5.18.0 --- src/drivers/file/Queue.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/drivers/file/Queue.php b/src/drivers/file/Queue.php index 5a7ee35b4..d4212de5e 100644 --- a/src/drivers/file/Queue.php +++ b/src/drivers/file/Queue.php @@ -257,6 +257,7 @@ protected function pushMessage(string $payload, int $ttr, int $delay, mixed $pri if ($priority !== null) { throw new NotSupportedException('Job priority is not supported in the driver.'); } + $id = 0; $this->touchIndex(function (array &$data) use ($payload, $ttr, $delay, &$id) { /** @var array{lastId: int, waiting: array, delayed: array} $data */ From 6df01d573f0e1b5405dc8e21338eba89382efe57 Mon Sep 17 00:00:00 2001 From: kalmerkaurson <56919431+kalmerkaurson@users.noreply.github.com> Date: Thu, 1 Feb 2024 10:15:03 +0200 Subject: [PATCH 06/22] Fix #509: Add StatisticsProviderInterface to get statistics from queue Co-authored-by: Kalmer Kaurson --- CHANGELOG.md | 2 +- src/cli/InfoAction.php | 63 ++++++ src/drivers/db/Command.php | 1 + src/drivers/db/InfoAction.php | 2 + src/drivers/db/Queue.php | 18 +- src/drivers/db/StatisticsProvider.php | 82 ++++++++ src/drivers/file/Command.php | 1 + src/drivers/file/InfoAction.php | 2 + src/drivers/file/Queue.php | 16 +- src/drivers/file/StatisticsProvider.php | 81 +++++++ src/drivers/redis/Command.php | 1 + src/drivers/redis/InfoAction.php | 2 + src/drivers/redis/Queue.php | 16 +- src/drivers/redis/StatisticsProvider.php | 74 +++++++ src/interfaces/DelayedCountInterface.php | 22 ++ src/interfaces/DoneCountInterface.php | 22 ++ src/interfaces/ReservedCountInterface.php | 22 ++ .../StatisticsProviderInterface.php | 22 ++ src/interfaces/WaitingCountInterface.php | 22 ++ tests/app/config/main.php | 3 + tests/cli/InfoActionTest.php | 198 ++++++++++++++++++ tests/cli/Queue.php | 47 +++++ .../cli/providers/BaseStatisticsProvider.php | 31 +++ tests/cli/providers/DelayedCountProvider.php | 27 +++ tests/cli/providers/DoneCountProvider.php | 27 +++ tests/cli/providers/ReservedCountProvider.php | 27 +++ tests/cli/providers/WaitingCountProvider.php | 27 +++ tests/docker-compose.yml | 6 +- tests/drivers/db/TestCase.php | 41 ++++ tests/drivers/file/QueueTest.php | 37 ++++ tests/drivers/redis/QueueTest.php | 37 ++++ 31 files changed, 973 insertions(+), 6 deletions(-) create mode 100644 src/cli/InfoAction.php create mode 100644 src/drivers/db/StatisticsProvider.php create mode 100644 src/drivers/file/StatisticsProvider.php create mode 100644 src/drivers/redis/StatisticsProvider.php create mode 100644 src/interfaces/DelayedCountInterface.php create mode 100644 src/interfaces/DoneCountInterface.php create mode 100644 src/interfaces/ReservedCountInterface.php create mode 100644 src/interfaces/StatisticsProviderInterface.php create mode 100644 src/interfaces/WaitingCountInterface.php create mode 100644 tests/cli/InfoActionTest.php create mode 100644 tests/cli/Queue.php create mode 100644 tests/cli/providers/BaseStatisticsProvider.php create mode 100644 tests/cli/providers/DelayedCountProvider.php create mode 100644 tests/cli/providers/DoneCountProvider.php create mode 100644 tests/cli/providers/ReservedCountProvider.php create mode 100644 tests/cli/providers/WaitingCountProvider.php diff --git a/CHANGELOG.md b/CHANGELOG.md index a4c06012b..416780e4e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,7 @@ Yii2 Queue Extension Change Log 2.3.7 under development ----------------------- - +- Enh #509: Add StatisticsProviderInterface to get statistics from queue (kalmer) - no changes in this release. diff --git a/src/cli/InfoAction.php b/src/cli/InfoAction.php new file mode 100644 index 000000000..f857ffe55 --- /dev/null +++ b/src/cli/InfoAction.php @@ -0,0 +1,63 @@ + + */ +class InfoAction extends Action +{ + /** + * @var Queue + */ + public $queue; + + + /** + * Info about queue status. + */ + public function run() + { + if (!($this->queue instanceof StatisticsProviderInterface)) { + throw new NotSupportedException('Queue does not support ' . StatisticsProviderInterface::class); + } + + $this->controller->stdout('Jobs' . PHP_EOL, Console::FG_GREEN); + $statisticsProvider = $this->queue->getStatisticsProvider(); + + if ($statisticsProvider instanceof WaitingCountInterface) { + $this->controller->stdout('- waiting: ', Console::FG_YELLOW); + $this->controller->stdout($statisticsProvider->getWaitingCount() . PHP_EOL); + } + + if ($statisticsProvider instanceof DelayedCountInterface) { + $this->controller->stdout('- delayed: ', Console::FG_YELLOW); + $this->controller->stdout($statisticsProvider->getDelayedCount() . PHP_EOL); + } + + if ($statisticsProvider instanceof ReservedCountInterface) { + $this->controller->stdout('- reserved: ', Console::FG_YELLOW); + $this->controller->stdout($statisticsProvider->getReservedCount() . PHP_EOL); + } + + if ($statisticsProvider instanceof DoneCountInterface) { + $this->controller->stdout('- done: ', Console::FG_YELLOW); + $this->controller->stdout($statisticsProvider->getDoneCount() . PHP_EOL); + } + } +} diff --git a/src/drivers/db/Command.php b/src/drivers/db/Command.php index a61e0787d..141fe9754 100644 --- a/src/drivers/db/Command.php +++ b/src/drivers/db/Command.php @@ -9,6 +9,7 @@ use yii\console\Exception; use yii\queue\cli\Command as CliCommand; +use yii\queue\cli\InfoAction; /** * Manages application db-queue. diff --git a/src/drivers/db/InfoAction.php b/src/drivers/db/InfoAction.php index 0510e0496..a91db6578 100644 --- a/src/drivers/db/InfoAction.php +++ b/src/drivers/db/InfoAction.php @@ -14,6 +14,8 @@ /** * Info about queue status. * + * @deprecated Will be removed in 3.0. Use yii\queue\cli\InfoAction instead. + * * @author Roman Zhuravlev */ class InfoAction extends Action diff --git a/src/drivers/db/Queue.php b/src/drivers/db/Queue.php index 93f3d98fb..1affd1cca 100644 --- a/src/drivers/db/Queue.php +++ b/src/drivers/db/Queue.php @@ -14,13 +14,14 @@ use yii\di\Instance; use yii\mutex\Mutex; use yii\queue\cli\Queue as CliQueue; +use yii\queue\interfaces\StatisticsProviderInterface; /** * Db Queue. * * @author Roman Zhuravlev */ -class Queue extends CliQueue +class Queue extends CliQueue implements StatisticsProviderInterface { /** * @var Connection|array|string @@ -233,6 +234,8 @@ protected function release($payload) } } + protected $reserveTime; + /** * Moves expired messages into waiting list. */ @@ -251,5 +254,16 @@ protected function moveExpired() } } - protected $reserveTime; + private $_statistcsProvider; + + /** + * @return StatisticsProvider + */ + public function getStatisticsProvider() + { + if (!$this->_statistcsProvider) { + $this->_statistcsProvider = new StatisticsProvider($this); + } + return $this->_statistcsProvider; + } } diff --git a/src/drivers/db/StatisticsProvider.php b/src/drivers/db/StatisticsProvider.php new file mode 100644 index 000000000..7df9c3c06 --- /dev/null +++ b/src/drivers/db/StatisticsProvider.php @@ -0,0 +1,82 @@ + + */ +class StatisticsProvider extends BaseObject implements DoneCountInterface, WaitingCountInterface, DelayedCountInterface, ReservedCountInterface +{ + /** + * @var Queue + */ + protected $queue; + + public function __construct(Queue $queue, $config = []) + { + $this->queue = $queue; + parent::__construct($config); + } + + /** + * @inheritdoc + */ + public function getWaitingCount() + { + return (new Query()) + ->from($this->queue->tableName) + ->andWhere(['channel' => $this->queue->channel]) + ->andWhere(['reserved_at' => null]) + ->andWhere(['delay' => 0])->count('*', $this->queue->db); + } + + /** + * @inheritdoc + */ + public function getDelayedCount() + { + return (new Query()) + ->from($this->queue->tableName) + ->andWhere(['channel' => $this->queue->channel]) + ->andWhere(['reserved_at' => null]) + ->andWhere(['>', 'delay', 0])->count('*', $this->queue->db); + } + + /** + * @inheritdoc + */ + public function getReservedCount() + { + return (new Query()) + ->from($this->queue->tableName) + ->andWhere(['channel' => $this->queue->channel]) + ->andWhere('[[reserved_at]] is not null') + ->andWhere(['done_at' => null])->count('*', $this->queue->db); + } + + /** + * @inheritdoc + */ + public function getDoneCount() + { + return (new Query()) + ->from($this->queue->tableName) + ->andWhere(['channel' => $this->queue->channel]) + ->andWhere('[[done_at]] is not null')->count('*', $this->queue->db); + } +} diff --git a/src/drivers/file/Command.php b/src/drivers/file/Command.php index ae6685c31..edfdd5dbd 100644 --- a/src/drivers/file/Command.php +++ b/src/drivers/file/Command.php @@ -9,6 +9,7 @@ use yii\console\Exception; use yii\queue\cli\Command as CliCommand; +use yii\queue\cli\InfoAction; /** * Manages application file-queue. diff --git a/src/drivers/file/InfoAction.php b/src/drivers/file/InfoAction.php index 9c996f2a3..6a168f7fb 100644 --- a/src/drivers/file/InfoAction.php +++ b/src/drivers/file/InfoAction.php @@ -13,6 +13,8 @@ /** * Info about queue status. * + * @deprecated Will be removed in 3.0. Use yii\queue\cli\InfoAction instead. + * * @author Roman Zhuravlev */ class InfoAction extends Action diff --git a/src/drivers/file/Queue.php b/src/drivers/file/Queue.php index a054bf557..c1e2fddc6 100644 --- a/src/drivers/file/Queue.php +++ b/src/drivers/file/Queue.php @@ -13,13 +13,14 @@ use yii\base\NotSupportedException; use yii\helpers\FileHelper; use yii\queue\cli\Queue as CliQueue; +use yii\queue\interfaces\StatisticsProviderInterface; /** * File Queue. * * @author Roman Zhuravlev */ -class Queue extends CliQueue +class Queue extends CliQueue implements StatisticsProviderInterface { /** * @var string @@ -304,4 +305,17 @@ private function touchIndex($callback) fclose($file); } } + + private $_statistcsProvider; + + /** + * @return StatisticsProvider + */ + public function getStatisticsProvider() + { + if (!$this->_statistcsProvider) { + $this->_statistcsProvider = new StatisticsProvider($this); + } + return $this->_statistcsProvider; + } } diff --git a/src/drivers/file/StatisticsProvider.php b/src/drivers/file/StatisticsProvider.php new file mode 100644 index 000000000..da0780ce8 --- /dev/null +++ b/src/drivers/file/StatisticsProvider.php @@ -0,0 +1,81 @@ + + */ +class StatisticsProvider extends BaseObject implements DoneCountInterface, WaitingCountInterface, DelayedCountInterface, ReservedCountInterface +{ + /** + * @var Queue + */ + protected $queue; + + public function __construct(Queue $queue, $config = []) + { + $this->queue = $queue; + parent::__construct($config); + } + + /** + * @inheritdoc + */ + public function getWaitingCount() + { + $data = $this->getIndexData(); + return !empty($data['waiting']) ? count($data['waiting']) : 0; + } + + /** + * @inheritdoc + */ + public function getDelayedCount() + { + $data = $this->getIndexData(); + return !empty($data['delayed']) ? count($data['delayed']) : 0; + } + + /** + * @inheritdoc + */ + public function getReservedCount() + { + $data = $this->getIndexData(); + return !empty($data['reserved']) ? count($data['reserved']) : 0; + } + + /** + * @inheritdoc + */ + public function getDoneCount() + { + $data = $this->getIndexData(); + $total = isset($data['lastId']) ? $data['lastId'] : 0; + return $total - $this->getDelayedCount() - $this->getWaitingCount(); + } + + protected function getIndexData() + { + $fileName = $this->queue->path . '/index.data'; + if (file_exists($fileName)) { + return call_user_func($this->queue->indexDeserializer, file_get_contents($fileName)); + } else { + return []; + } + } +} diff --git a/src/drivers/redis/Command.php b/src/drivers/redis/Command.php index 146aa18d2..0d152389c 100644 --- a/src/drivers/redis/Command.php +++ b/src/drivers/redis/Command.php @@ -9,6 +9,7 @@ use yii\console\Exception; use yii\queue\cli\Command as CliCommand; +use yii\queue\cli\InfoAction; /** * Manages application redis-queue. diff --git a/src/drivers/redis/InfoAction.php b/src/drivers/redis/InfoAction.php index 62d410a25..b9f1cd507 100644 --- a/src/drivers/redis/InfoAction.php +++ b/src/drivers/redis/InfoAction.php @@ -13,6 +13,8 @@ /** * Info about queue status. * + * @deprecated Will be removed in 3.0. Use yii\queue\cli\InfoAction instead. + * * @author Roman Zhuravlev */ class InfoAction extends Action diff --git a/src/drivers/redis/Queue.php b/src/drivers/redis/Queue.php index b56d1d07f..2babf2c92 100644 --- a/src/drivers/redis/Queue.php +++ b/src/drivers/redis/Queue.php @@ -11,6 +11,7 @@ use yii\base\NotSupportedException; use yii\di\Instance; use yii\queue\cli\Queue as CliQueue; +use yii\queue\interfaces\StatisticsProviderInterface; use yii\redis\Connection; /** @@ -18,7 +19,7 @@ * * @author Roman Zhuravlev */ -class Queue extends CliQueue +class Queue extends CliQueue implements StatisticsProviderInterface { /** * @var Connection|array|string @@ -205,4 +206,17 @@ protected function pushMessage($message, $ttr, $delay, $priority) return $id; } + + private $_statistcsProvider; + + /** + * @return StatisticsProvider + */ + public function getStatisticsProvider() + { + if (!$this->_statistcsProvider) { + $this->_statistcsProvider = new StatisticsProvider($this); + } + return $this->_statistcsProvider; + } } diff --git a/src/drivers/redis/StatisticsProvider.php b/src/drivers/redis/StatisticsProvider.php new file mode 100644 index 000000000..13824b4cb --- /dev/null +++ b/src/drivers/redis/StatisticsProvider.php @@ -0,0 +1,74 @@ + + */ +class StatisticsProvider extends BaseObject implements DoneCountInterface, WaitingCountInterface, DelayedCountInterface, ReservedCountInterface +{ + /** + * @var Queue + */ + protected $queue; + + public function __construct(Queue $queue, $config = []) + { + $this->queue = $queue; + parent::__construct($config); + } + + /** + * @inheritdoc + */ + public function getWaitingCount() + { + $prefix = $this->queue->channel; + return $this->queue->redis->llen("$prefix.waiting"); + } + + /** + * @inheritdoc + */ + public function getDelayedCount() + { + $prefix = $this->queue->channel; + return $this->queue->redis->zcount("$prefix.delayed", '-inf', '+inf'); + } + + /** + * @inheritdoc + */ + public function getReservedCount() + { + $prefix = $this->queue->channel; + return $this->queue->redis->zcount("$prefix.reserved", '-inf', '+inf'); + } + + /** + * @inheritdoc + */ + public function getDoneCount() + { + $prefix = $this->queue->channel; + $waiting = $this->getWaitingCount(); + $delayed = $this->getDelayedCount(); + $reserved = $this->getReservedCount(); + $total = $this->queue->redis->get("$prefix.message_id"); + return $total - $waiting - $delayed - $reserved; + } +} diff --git a/src/interfaces/DelayedCountInterface.php b/src/interfaces/DelayedCountInterface.php new file mode 100644 index 000000000..63ad9e8f1 --- /dev/null +++ b/src/interfaces/DelayedCountInterface.php @@ -0,0 +1,22 @@ + + */ +interface DelayedCountInterface +{ + /** + * @return int + */ + public function getDelayedCount(); +} diff --git a/src/interfaces/DoneCountInterface.php b/src/interfaces/DoneCountInterface.php new file mode 100644 index 000000000..be8f0c453 --- /dev/null +++ b/src/interfaces/DoneCountInterface.php @@ -0,0 +1,22 @@ + + */ +interface DoneCountInterface +{ + /** + * @return int + */ + public function getDoneCount(); +} diff --git a/src/interfaces/ReservedCountInterface.php b/src/interfaces/ReservedCountInterface.php new file mode 100644 index 000000000..78985f3ed --- /dev/null +++ b/src/interfaces/ReservedCountInterface.php @@ -0,0 +1,22 @@ + + */ +interface ReservedCountInterface +{ + /** + * @return int + */ + public function getReservedCount(); +} diff --git a/src/interfaces/StatisticsProviderInterface.php b/src/interfaces/StatisticsProviderInterface.php new file mode 100644 index 000000000..7ca7bfcca --- /dev/null +++ b/src/interfaces/StatisticsProviderInterface.php @@ -0,0 +1,22 @@ + + */ +interface StatisticsProviderInterface +{ + /** + * @return int + */ + public function getStatisticsProvider(); +} diff --git a/src/interfaces/WaitingCountInterface.php b/src/interfaces/WaitingCountInterface.php new file mode 100644 index 000000000..aa142a8ad --- /dev/null +++ b/src/interfaces/WaitingCountInterface.php @@ -0,0 +1,22 @@ + + */ +interface WaitingCountInterface +{ + /** + * @return int + */ + public function getWaitingCount(); +} diff --git a/tests/app/config/main.php b/tests/app/config/main.php index 29b16b8f8..a4cb30fd1 100644 --- a/tests/app/config/main.php +++ b/tests/app/config/main.php @@ -43,6 +43,7 @@ 'class' => \yii\mutex\MysqlMutex::class, 'db' => 'mysql', ], + 'deleteReleased' => false, ], 'sqlite' => [ 'class' => \yii\db\Connection::class, @@ -52,6 +53,7 @@ 'class' => \yii\queue\db\Queue::class, 'db' => 'sqlite', 'mutex' => \yii\mutex\FileMutex::class, + 'deleteReleased' => false, ], 'pgsql' => [ 'class' => \yii\db\Connection::class, @@ -72,6 +74,7 @@ 'db' => 'pgsql', ], 'mutexTimeout' => 0, + 'deleteReleased' => false, ], 'redis' => [ 'class' => \yii\redis\Connection::class, diff --git a/tests/cli/InfoActionTest.php b/tests/cli/InfoActionTest.php new file mode 100644 index 000000000..1756e374a --- /dev/null +++ b/tests/cli/InfoActionTest.php @@ -0,0 +1,198 @@ + + */ +class InfoActionTest extends TestCase +{ + public function testWaitingCount() + { + $controller = $this->getMockBuilder(Controller::class) + ->setConstructorArgs(['testController', new Module('testModule')]) + ->getMock() + ; + + $controller->expects(self::exactly(3)) + ->method('stdout') + ->withConsecutive( + [ + 'Jobs' . PHP_EOL, + Console::FG_GREEN, + ], + [ + '- waiting: ', + Console::FG_YELLOW, + ], + [ + 10 . PHP_EOL + ] + ) + ; + + $queue = $this->getMockBuilder(Queue::class)->getMock(); + + $provider = $this->getMockBuilder(WaitingCountProvider::class) + ->setConstructorArgs([$queue]) + ->getMock() + ; + $provider->expects(self::once()) + ->method('getWaitingCount') + ->willReturn(10) + ; + + $queue->method('getStatisticsProvider')->willReturn($provider); + + $action = (new InfoAction('infoAction', $controller, [ + 'queue' => $queue, + ])); + $action->run(); + } + + public function testDelayedCount() + { + $controller = $this->getMockBuilder(Controller::class) + ->setConstructorArgs(['testController', new Module('testModule')]) + ->getMock() + ; + + $controller->expects(self::exactly(3)) + ->method('stdout') + ->withConsecutive( + [ + 'Jobs' . PHP_EOL, + Console::FG_GREEN, + ], + [ + '- delayed: ', + Console::FG_YELLOW, + ], + [ + 10 . PHP_EOL + ] + ) + ; + + $queue = $this->getMockBuilder(Queue::class)->getMock(); + + $provider = $this->getMockBuilder(DelayedCountProvider::class) + ->setConstructorArgs([$queue]) + ->getMock() + ; + $provider->expects(self::once()) + ->method('getDelayedCount') + ->willReturn(10) + ; + + $queue->method('getStatisticsProvider')->willReturn($provider); + + $action = (new InfoAction('infoAction', $controller, [ + 'queue' => $queue, + ])); + $action->run(); + } + + public function testReservedCount() + { + $controller = $this->getMockBuilder(Controller::class) + ->setConstructorArgs(['testController', new Module('testModule')]) + ->getMock() + ; + + $controller->expects(self::exactly(3)) + ->method('stdout') + ->withConsecutive( + [ + 'Jobs' . PHP_EOL, + Console::FG_GREEN, + ], + [ + '- reserved: ', + Console::FG_YELLOW, + ], + [ + 10 . PHP_EOL + ] + ) + ; + + $queue = $this->getMockBuilder(Queue::class)->getMock(); + + $provider = $this->getMockBuilder(ReservedCountProvider::class) + ->setConstructorArgs([$queue]) + ->getMock() + ; + $provider->expects(self::once()) + ->method('getReservedCount') + ->willReturn(10) + ; + + $queue->method('getStatisticsProvider')->willReturn($provider); + + $action = (new InfoAction('infoAction', $controller, [ + 'queue' => $queue, + ])); + $action->run(); + } + + public function testDoneCount() + { + $controller = $this->getMockBuilder(Controller::class) + ->setConstructorArgs(['testController', new Module('testModule')]) + ->getMock() + ; + + $controller->expects(self::exactly(3)) + ->method('stdout') + ->withConsecutive( + [ + 'Jobs' . PHP_EOL, + Console::FG_GREEN, + ], + [ + '- done: ', + Console::FG_YELLOW, + ], + [ + 10 . PHP_EOL + ] + ) + ; + + $queue = $this->getMockBuilder(Queue::class)->getMock(); + + $provider = $this->getMockBuilder(DoneCountProvider::class) + ->setConstructorArgs([$queue]) + ->getMock() + ; + $provider->expects(self::once()) + ->method('getDoneCount') + ->willReturn(10) + ; + + $queue->method('getStatisticsProvider')->willReturn($provider); + + $action = (new InfoAction('infoAction', $controller, [ + 'queue' => $queue, + ])); + $action->run(); + } +} diff --git a/tests/cli/Queue.php b/tests/cli/Queue.php new file mode 100644 index 000000000..e7a6412d7 --- /dev/null +++ b/tests/cli/Queue.php @@ -0,0 +1,47 @@ + + */ +class Queue extends CliQueue implements StatisticsProviderInterface +{ + /** + * @inheritdoc + */ + public function status($id) + { + throw new NotSupportedException('"status" method is not supported.'); + } + /** + * @inheritdoc + */ + protected function pushMessage($message, $ttr, $delay, $priority) + { + throw new NotSupportedException('"pushMessage" method is not supported.'); + } + + /** + * @return StatisticsProvider + */ + public function getStatisticsProvider() + { + if (!$this->_statistcsProvider) { + $this->_statistcsProvider = new BaseStatisticsProvider($this); + } + return $this->_statistcsProvider; + } +} diff --git a/tests/cli/providers/BaseStatisticsProvider.php b/tests/cli/providers/BaseStatisticsProvider.php new file mode 100644 index 000000000..a403d52ca --- /dev/null +++ b/tests/cli/providers/BaseStatisticsProvider.php @@ -0,0 +1,31 @@ + + */ +class BaseStatisticsProvider extends BaseObject +{ + /** + * @var Queue + */ + protected $queue; + + public function __construct(Queue $queue, $config = []) + { + $this->queue = $queue; + parent::__construct($config); + } +} diff --git a/tests/cli/providers/DelayedCountProvider.php b/tests/cli/providers/DelayedCountProvider.php new file mode 100644 index 000000000..d15beab58 --- /dev/null +++ b/tests/cli/providers/DelayedCountProvider.php @@ -0,0 +1,27 @@ + + */ +class DelayedCountProvider extends BaseStatisticsProvider implements DelayedCountInterface +{ + /** + * @inheritdoc + */ + public function getDelayedCount() + { + return 10; + } +} diff --git a/tests/cli/providers/DoneCountProvider.php b/tests/cli/providers/DoneCountProvider.php new file mode 100644 index 000000000..0514aed66 --- /dev/null +++ b/tests/cli/providers/DoneCountProvider.php @@ -0,0 +1,27 @@ + + */ +class DoneCountProvider extends BaseStatisticsProvider implements DoneCountInterface +{ + /** + * @inheritdoc + */ + public function getDoneCount() + { + return 10; + } +} diff --git a/tests/cli/providers/ReservedCountProvider.php b/tests/cli/providers/ReservedCountProvider.php new file mode 100644 index 000000000..fbb894ac4 --- /dev/null +++ b/tests/cli/providers/ReservedCountProvider.php @@ -0,0 +1,27 @@ + + */ +class ReservedCountProvider extends BaseStatisticsProvider implements ReservedCountInterface +{ + /** + * @inheritdoc + */ + public function getReservedCount() + { + return 10; + } +} diff --git a/tests/cli/providers/WaitingCountProvider.php b/tests/cli/providers/WaitingCountProvider.php new file mode 100644 index 000000000..7a53b32dc --- /dev/null +++ b/tests/cli/providers/WaitingCountProvider.php @@ -0,0 +1,27 @@ + + */ +class WaitingCountProvider extends BaseStatisticsProvider implements WaitingCountInterface +{ + /** + * @inheritdoc + */ + public function getWaitingCount() + { + return 10; + } +} diff --git a/tests/docker-compose.yml b/tests/docker-compose.yml index 2b7000c6a..6e78de144 100644 --- a/tests/docker-compose.yml +++ b/tests/docker-compose.yml @@ -62,6 +62,10 @@ services: MYSQL_DATABASE: yii2_queue_test networks: net: {} + ulimits: + nofile: + soft: 262144 + hard: 262144 # https://hub.docker.com/_/postgres/ postgres: @@ -110,7 +114,7 @@ services: # https://hub.docker.com/r/webcenter/activemq/ activemq: - image: webcenter/activemq + image: islandora/activemq:3 ports: - 61613:61613 networks: diff --git a/tests/drivers/db/TestCase.php b/tests/drivers/db/TestCase.php index bc57ca752..181f95b85 100644 --- a/tests/drivers/db/TestCase.php +++ b/tests/drivers/db/TestCase.php @@ -10,6 +10,7 @@ use tests\app\PriorityJob; use tests\app\RetryJob; use tests\drivers\CliTestCase; +use Yii; use yii\db\Query; /** @@ -105,8 +106,48 @@ public function testRemove() $this->assertEquals(0, $actual); } + public function testWaitingCount() + { + $this->getQueue()->push($this->createSimpleJob()); + + $this->assertEquals(1, $this->getQueue()->getStatisticsProvider()->getWaitingCount()); + } + + public function testDelayedCount() + { + $this->getQueue()->delay(5)->push($this->createSimpleJob()); + + $this->assertEquals(1, $this->getQueue()->getStatisticsProvider()->getDelayedCount()); + } + + public function testReservedCount() + { + $this->getQueue()->messageHandler = function () { + $this->assertEquals(1, $this->getQueue()->getStatisticsProvider()->getReservedCount()); + }; + + $job = $this->createSimpleJob(); + $this->getQueue()->push($job); + $this->getQueue()->run(false); + } + + public function testDoneCount() + { + $this->getQueue()->messageHandler = function () { + return true; + }; + + $job = $this->createSimpleJob(); + $this->getQueue()->push($job); + $this->getQueue()->run(false); + + $this->assertEquals(1, $this->getQueue()->getStatisticsProvider()->getDoneCount()); + } + + protected function tearDown() { + $this->getQueue()->messageHandler = null; $this->getQueue()->db->createCommand() ->delete($this->getQueue()->tableName) ->execute(); diff --git a/tests/drivers/file/QueueTest.php b/tests/drivers/file/QueueTest.php index 1faea8006..42bc68050 100644 --- a/tests/drivers/file/QueueTest.php +++ b/tests/drivers/file/QueueTest.php @@ -87,6 +87,42 @@ public function testRemove() $this->assertFileNotExists($this->getQueue()->path . "/job$id.data"); } + public function testWaitingCount() + { + $this->getQueue()->push($this->createSimpleJob()); + + $this->assertEquals(1, $this->getQueue()->getStatisticsProvider()->getWaitingCount()); + } + + public function testDelayedCount() + { + $this->getQueue()->delay(5)->push($this->createSimpleJob()); + + $this->assertEquals(1, $this->getQueue()->getStatisticsProvider()->getDelayedCount()); + } + + public function testReservedCount() + { + $this->getQueue()->messageHandler = function () { + $this->assertEquals(1, $this->getQueue()->getStatisticsProvider()->getReservedCount()); + }; + + $job = $this->createSimpleJob(); + $this->getQueue()->push($job); + $this->getQueue()->run(false); + } + + public function testDoneCount() + { + $this->startProcess(['php', 'yii', 'queue/listen', '1']); + $job = $this->createSimpleJob(); + $this->getQueue()->push($job); + + $this->assertSimpleJobDone($job); + + $this->assertEquals(1, $this->getQueue()->getStatisticsProvider()->getDoneCount()); + } + /** * @return Queue */ @@ -97,6 +133,7 @@ protected function getQueue() protected function tearDown() { + $this->getQueue()->messageHandler = null; foreach (glob(Yii::getAlias("@runtime/queue/*")) as $fileName) { unlink($fileName); } diff --git a/tests/drivers/redis/QueueTest.php b/tests/drivers/redis/QueueTest.php index 8e6c462e9..8fbbf5a00 100644 --- a/tests/drivers/redis/QueueTest.php +++ b/tests/drivers/redis/QueueTest.php @@ -87,6 +87,42 @@ public function testRemove() $this->assertFalse((bool) $this->getQueue()->redis->hexists($this->getQueue()->channel . '.messages', $id)); } + public function testWaitingCount() + { + $this->getQueue()->push($this->createSimpleJob()); + + $this->assertEquals(1, $this->getQueue()->getStatisticsProvider()->getWaitingCount()); + } + + public function testDelayedCount() + { + $this->getQueue()->delay(5)->push($this->createSimpleJob()); + + $this->assertEquals(1, $this->getQueue()->getStatisticsProvider()->getDelayedCount()); + } + + public function testReservedCount() + { + $this->getQueue()->messageHandler = function () { + $this->assertEquals(1, $this->getQueue()->getStatisticsProvider()->getReservedCount()); + }; + + $job = $this->createSimpleJob(); + $this->getQueue()->push($job); + $this->getQueue()->run(false); + } + + public function testDoneCount() + { + $this->startProcess(['php', 'yii', 'queue/listen', '1']); + $job = $this->createSimpleJob(); + $this->getQueue()->push($job); + + $this->assertSimpleJobDone($job); + + $this->assertEquals(1, $this->getQueue()->getStatisticsProvider()->getDoneCount()); + } + /** * @return Queue */ @@ -97,6 +133,7 @@ protected function getQueue() protected function tearDown() { + $this->getQueue()->messageHandler = null; $this->getQueue()->redis->flushdb(); parent::tearDown(); } From 7bfb3d8720206270aec4a409ed2716e79fc058e0 Mon Sep 17 00:00:00 2001 From: coderltf <48883423+coderltf@users.noreply.github.com> Date: Thu, 25 Apr 2024 01:46:23 +0800 Subject: [PATCH 07/22] update translation in zh-CN (#512) --- docs/guide-zh-CN/retryable.md | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/docs/guide-zh-CN/retryable.md b/docs/guide-zh-CN/retryable.md index 738cb1916..34f139e98 100644 --- a/docs/guide-zh-CN/retryable.md +++ b/docs/guide-zh-CN/retryable.md @@ -1,10 +1,10 @@ 错误与重复执行 ========================= -在作业处理期间可以抛出异常。 当请求的服务和外部资源不可用时,由于代码编写的比较糟糕而导致的内部错误。 -在第二种情况下,可以在一段时间后重新尝试这个作业。 +作业的执行可能会失败。这可能是由于内部错误造成的,这些错误是由编写不当的代码导致的,应该首先修复。但是,它们也可能由于外部问题(例如服务或资源不可用)而失败。这可能会导致异常或超时。 +在后一种情况下,最好能够在一段时间后重试作业。有几种方法可以做到这一点。 -有几种方法可以做到这一点。 +>注意:下面描述的 ttr 功能需要安装 [PHP Process Control (pcntl)](https://www.php.net/manual/en/book.pcntl.php) 扩展,并且 worker 命令必须使用 --isolate 选项(默认启用)。 重试选项 ------------- @@ -21,7 +21,12 @@ ], ``` - `ttr` 选项设置了在队列中保留工作的时间。如果一份作业在这段时间没有执行,它将返回队列进行重试。 + `ttr` 选项设置了作业必须成功完成的秒数。因此,可能会发生两件事来使工作失败: + 1. 作业在`ttr`结束之前发生异常 + 2. 完成作业所需的时间将比 ttr 长(超时),工作线程停止作业执行 + +在这两种情况下,作业都将发送回队列进行重试。但请注意,在第一种情况下,即使作业在运行后立即停止,也不会立即重试,要等到`ttr`"用完"。也就是说,在将作业发送回队列之前,必须经过剩余的 ttr 秒数。 + `attempts` 选项设置了最大的尝试次数。如果尝试已经结束,作业作还没有完成,它将从队列中移除。 这种将全局设置队列中的所有作业,如果您需要为多个作业进行不同的设置可以使用, @@ -30,7 +35,7 @@ 重试作业接口 ---------------------- -Separate control of retry is implemented by `RetryableJobInterface` 接口。 示例: +为了更好地控制重试逻辑,作业可以实现 `RetryableJobInterface` 接口。 示例: ```php class SomeJob extends BaseObject implements RetryableJobInterface @@ -85,9 +90,9 @@ Yii::$app->queue->on(Queue::EVENT_AFTER_ERROR, function (ExecEvent $event) { 限制 ------------ -完全支持 [Beanstalk], [DB], [File] 和 [Redis] 驱动程序的重试工具。 -[Sync] 驱动不会重试失败的工作 [Gearman] 不支持重试。 -[RabbitMQ] 基本版支持,但重试编号无法得到。 +[Beanstalk], [DB], [File] 和 [Redis] 驱动程序实现了对可重试作业的完全支持。 +[Sync] 驱动不会重试失败的作业 [Gearman] 不支持重试作业。 +[RabbitMQ] 只有其基本的可重试支持,其中无法设置尝试次数。 [Beanstalk]: driver-beanstalk.md [DB]: driver-db.md @@ -95,4 +100,4 @@ Yii::$app->queue->on(Queue::EVENT_AFTER_ERROR, function (ExecEvent $event) { [Redis]: driver-redis.md [Sync]: driver-sync.md [Gearman]: driver-gearman.md -[RabbitMQ]: driver-amqp.md \ No newline at end of file +[RabbitMQ]: driver-amqp.md From 8481457c77a164257ffb43a85defc8eb08d028b9 Mon Sep 17 00:00:00 2001 From: Alexey Rogachev Date: Mon, 29 Apr 2024 14:36:13 +0500 Subject: [PATCH 08/22] Update `composer.json` (`allow-plugins` section) (#514) --- composer.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 0aca9187e..1664d4914 100644 --- a/composer.json +++ b/composer.json @@ -66,7 +66,8 @@ "config": { "allow-plugins": { "yiisoft/yii2-composer": true, - "cweagans/composer-patches": true + "cweagans/composer-patches": true, + "php-http/discovery": true } }, "extra": { From dbc9d4a7b2a6995cd19c3e334227482ef55e559b Mon Sep 17 00:00:00 2001 From: Alexey Rogachev Date: Mon, 29 Apr 2024 14:40:52 +0500 Subject: [PATCH 09/22] release version 2.3.7 --- CHANGELOG.md | 7 ++++--- src/drivers/db/Queue.php | 2 ++ src/drivers/db/StatisticsProvider.php | 2 +- src/drivers/file/Queue.php | 2 ++ src/drivers/file/StatisticsProvider.php | 2 +- src/drivers/redis/Queue.php | 2 ++ src/drivers/redis/StatisticsProvider.php | 2 +- src/interfaces/DelayedCountInterface.php | 1 - src/interfaces/DoneCountInterface.php | 1 - src/interfaces/ReservedCountInterface.php | 1 - src/interfaces/StatisticsProviderInterface.php | 1 - src/interfaces/WaitingCountInterface.php | 1 - 12 files changed, 13 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 416780e4e..2737967a1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,10 +1,11 @@ Yii2 Queue Extension Change Log =============================== -2.3.7 under development ------------------------ -- Enh #509: Add StatisticsProviderInterface to get statistics from queue (kalmer) +2.3.7 April 29, 2024 +-------------------- + - no changes in this release. +- Enh #509: Add StatisticsProviderInterface to get statistics from queue (kalmer) 2.3.6 October 03, 2023 diff --git a/src/drivers/db/Queue.php b/src/drivers/db/Queue.php index 1affd1cca..4d18266ad 100644 --- a/src/drivers/db/Queue.php +++ b/src/drivers/db/Queue.php @@ -19,6 +19,8 @@ /** * Db Queue. * + * @property-read StatisticsProvider $statisticsProvider + * * @author Roman Zhuravlev */ class Queue extends CliQueue implements StatisticsProviderInterface diff --git a/src/drivers/db/StatisticsProvider.php b/src/drivers/db/StatisticsProvider.php index 7df9c3c06..ff6020314 100644 --- a/src/drivers/db/StatisticsProvider.php +++ b/src/drivers/db/StatisticsProvider.php @@ -1,5 +1,4 @@ queue = $queue; diff --git a/src/drivers/file/Queue.php b/src/drivers/file/Queue.php index c1e2fddc6..d92c9eb13 100644 --- a/src/drivers/file/Queue.php +++ b/src/drivers/file/Queue.php @@ -18,6 +18,8 @@ /** * File Queue. * + * @property-read StatisticsProvider $statisticsProvider + * * @author Roman Zhuravlev */ class Queue extends CliQueue implements StatisticsProviderInterface diff --git a/src/drivers/file/StatisticsProvider.php b/src/drivers/file/StatisticsProvider.php index da0780ce8..cedc9520b 100644 --- a/src/drivers/file/StatisticsProvider.php +++ b/src/drivers/file/StatisticsProvider.php @@ -1,5 +1,4 @@ queue = $queue; diff --git a/src/drivers/redis/Queue.php b/src/drivers/redis/Queue.php index 2babf2c92..deabbb870 100644 --- a/src/drivers/redis/Queue.php +++ b/src/drivers/redis/Queue.php @@ -17,6 +17,8 @@ /** * Redis Queue. * + * @property-read StatisticsProvider $statisticsProvider + * * @author Roman Zhuravlev */ class Queue extends CliQueue implements StatisticsProviderInterface diff --git a/src/drivers/redis/StatisticsProvider.php b/src/drivers/redis/StatisticsProvider.php index 13824b4cb..78f21d2d3 100644 --- a/src/drivers/redis/StatisticsProvider.php +++ b/src/drivers/redis/StatisticsProvider.php @@ -1,5 +1,4 @@ queue = $queue; diff --git a/src/interfaces/DelayedCountInterface.php b/src/interfaces/DelayedCountInterface.php index 63ad9e8f1..41ea00532 100644 --- a/src/interfaces/DelayedCountInterface.php +++ b/src/interfaces/DelayedCountInterface.php @@ -1,5 +1,4 @@ Date: Mon, 29 Apr 2024 14:41:12 +0500 Subject: [PATCH 10/22] prepare for next release --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2737967a1..4ce504a73 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,12 @@ Yii2 Queue Extension Change Log =============================== +2.3.8 under development +----------------------- + +- no changes in this release. + + 2.3.7 April 29, 2024 -------------------- From caf3cb894e3b1163927573b5e25a93e4261b2069 Mon Sep 17 00:00:00 2001 From: Alexey Rogachev Date: Mon, 29 Apr 2024 14:49:53 +0500 Subject: [PATCH 11/22] Update CHANGELOG.md (#515) --- CHANGELOG.md | 1 - 1 file changed, 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4ce504a73..d7a0dd170 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,7 +10,6 @@ Yii2 Queue Extension Change Log 2.3.7 April 29, 2024 -------------------- -- no changes in this release. - Enh #509: Add StatisticsProviderInterface to get statistics from queue (kalmer) From 46b2eff9d89762fdf8af63ffa4fba72bf77a3457 Mon Sep 17 00:00:00 2001 From: Stefan Linke Date: Tue, 8 Oct 2024 16:25:38 +0000 Subject: [PATCH 12/22] Improve wording in package description (#518) --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 1664d4914..0197ca139 100644 --- a/composer.json +++ b/composer.json @@ -1,6 +1,6 @@ { "name": "yiisoft/yii2-queue", - "description": "Yii2 Queue Extension which supported DB, Redis, RabbitMQ, Beanstalk, SQS and Gearman", + "description": "Yii2 Queue Extension which supports queues based on DB, Redis, RabbitMQ, Beanstalk, SQS, and Gearman", "type": "yii2-extension", "keywords": ["yii", "queue", "async", "gii", "db", "redis", "rabbitmq", "beanstalk", "gearman", "sqs"], "license": "BSD-3-Clause", From 9dd5534e5396d45c33c35ce77423f59f6c01a4c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fl=C3=A1vio=20Veloso=20Soares?= Date: Thu, 20 Feb 2025 22:48:10 -0800 Subject: [PATCH 13/22] Fix #522: Fix SQS driver type error with custom value passed to `queue/listen` --- CHANGELOG.md | 2 +- src/drivers/sqs/Command.php | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d7a0dd170..652cce681 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,7 @@ Yii2 Queue Extension Change Log 2.3.8 under development ----------------------- -- no changes in this release. +- Bug #522: Fix SQS driver type error with custom value passed to `queue/listen` (flaviovs) 2.3.7 April 29, 2024 diff --git a/src/drivers/sqs/Command.php b/src/drivers/sqs/Command.php index 15474915b..d2b5e288b 100644 --- a/src/drivers/sqs/Command.php +++ b/src/drivers/sqs/Command.php @@ -48,6 +48,8 @@ public function actionListen($timeout = 3) if (!is_numeric($timeout)) { throw new Exception('Timeout must be numeric.'); } + $timeout = (int) $timeout; + if ($timeout < 1 || $timeout > 20) { throw new Exception('Timeout must be between 1 and 20'); } From 8f4c3504b75cf09b418080c2a13b55923a8c0701 Mon Sep 17 00:00:00 2001 From: Alexander Makarov Date: Fri, 21 Feb 2025 10:10:52 +0300 Subject: [PATCH 14/22] Fix tests (#524) --- Makefile | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/Makefile b/Makefile index ba996b739..0292d4b49 100644 --- a/Makefile +++ b/Makefile @@ -3,31 +3,31 @@ help: ## Display help information build: ## Build an image from a docker-compose file. Params: {{ v=5.6 }}. Default latest PHP 5.6 @cp -n .env.example .env - PHP_VERSION=$(filter-out $@,$(v)) docker-compose up -d --build + PHP_VERSION=$(filter-out $@,$(v)) docker compose up -d --build 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 build --pull yii2-queue-php + PHP_VERSION=$(filter-out $@,$(v)) docker compose run yii2-queue-php vendor/bin/phpunit --colors=always -v --debug make down down: ## Stop and remove containers, networks - docker-compose down + docker compose down benchmark: ## Run benchmark. 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 tests/yii benchmark/waiting + 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 check-cs: - docker-compose build php72 - docker-compose run php72 php-cs-fixer fix --diff --dry-run - docker-compose down + docker compose build php72 + docker compose run php72 php-cs-fixer fix --diff --dry-run + docker compose down clean: - docker-compose down + docker compose down rm -rf tests/runtime/* rm -f .php_cs.cache rm -rf composer.lock From d6372d8f2a8c5ad8c93200e547e15c3425293a55 Mon Sep 17 00:00:00 2001 From: soul11201 Date: Tue, 11 Mar 2025 22:00:59 +0800 Subject: [PATCH 15/22] Fix #516: Ensure Redis driver messages are consumed at least once --- CHANGELOG.md | 2 +- src/drivers/redis/Queue.php | 2 +- tests/drivers/redis/QueueTest.php | 50 ++++++++++++++++++++++++++ tests/drivers/redis/RedisCrashMock.php | 17 +++++++++ 4 files changed, 69 insertions(+), 2 deletions(-) create mode 100644 tests/drivers/redis/RedisCrashMock.php diff --git a/CHANGELOG.md b/CHANGELOG.md index 652cce681..4bdf0fc75 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,7 @@ Yii2 Queue Extension Change Log 2.3.8 under development ----------------------- - +- Enh #516: Ensure Redis driver messages are consumed at least once (soul11201) - Bug #522: Fix SQS driver type error with custom value passed to `queue/listen` (flaviovs) diff --git a/src/drivers/redis/Queue.php b/src/drivers/redis/Queue.php index deabbb870..1da823879 100644 --- a/src/drivers/redis/Queue.php +++ b/src/drivers/redis/Queue.php @@ -170,10 +170,10 @@ protected function moveExpired($from) { $now = time(); if ($expired = $this->redis->zrevrangebyscore($from, $now, '-inf')) { - $this->redis->zremrangebyscore($from, '-inf', $now); foreach ($expired as $id) { $this->redis->rpush("$this->channel.waiting", $id); } + $this->redis->zremrangebyscore($from, '-inf', $now); } } diff --git a/tests/drivers/redis/QueueTest.php b/tests/drivers/redis/QueueTest.php index 8fbbf5a00..92200fd63 100644 --- a/tests/drivers/redis/QueueTest.php +++ b/tests/drivers/redis/QueueTest.php @@ -10,6 +10,7 @@ use tests\app\RetryJob; use tests\drivers\CliTestCase; use Yii; +use yii\di\Instance; use yii\queue\redis\Queue; /** @@ -137,4 +138,53 @@ protected function tearDown() $this->getQueue()->redis->flushdb(); parent::tearDown(); } + + /** + * Verify that Redis data persists when process crashes during moveExpired. + * + * Steps: + * 1. Push a delayed job into queue + * 2. Wait for the job to expire + * 3. Mock Redis to simulate crash during moveExpired + * 4. Successfully process job after recovery + */ + public function testConsumeDelayedMessageAtLeastOnce() + { + $job = $this->createSimpleJob(); + $this->getQueue()->delay(1)->push($job); + // Expect a single message to be received. + $messageCount = 0; + $this->getQueue()->messageHandler = function () use(&$messageCount) { + $messageCount++; + }; + + // Ensure the delayed message can be consumed when more time passed than the delay is. + sleep(2); + + // Based on the implemention, emulate a crash when redis "rpush" + // command should be executed. + $mockRedis = Instance::ensure([ + 'class' => RedisCrashMock::class, + 'hostname' => getenv('REDIS_HOST') ?: 'localhost', + 'database' => getenv('REDIS_DB') ?: 1, + 'crashOnCommand' => 'rpush' // Crash when trying to move job to waiting queue. + ], 'yii\redis\Connection'); + + $queue = $this->getQueue(); + $old = $queue->redis; + $queue->redis = $mockRedis; + + try { + $queue->run(false); + } catch (\Exception $e) { + // Ignore exceptions. + } finally { + $queue->redis = $old; + } + + // Ensure the red lock is invalid. The red lock is valid for 1s. + sleep(2); + $this->getQueue()->run(false); + $this->assertEquals(1, $messageCount); + } } diff --git a/tests/drivers/redis/RedisCrashMock.php b/tests/drivers/redis/RedisCrashMock.php new file mode 100644 index 000000000..e463e08a9 --- /dev/null +++ b/tests/drivers/redis/RedisCrashMock.php @@ -0,0 +1,17 @@ +crashOnCommand) { + throw new \RuntimeException('Simulated Redis crash'); + } + return parent::executeCommand($name, $params); + } +} From 9858a7840c23d479b2cc114364788f8001dc7e4f Mon Sep 17 00:00:00 2001 From: EAMoiseenko Date: Mon, 12 May 2025 17:37:56 +0300 Subject: [PATCH 16/22] Fixed psalm issues --- composer.json | 4 ++-- psalm.xml | 4 ++++ src/JobEvent.php | 2 +- src/cli/VerboseBehavior.php | 1 - src/cli/WorkerEvent.php | 3 +-- src/closure/Behavior.php | 2 +- src/debug/Panel.php | 1 - src/drivers/amqp_interop/Command.php | 2 +- src/drivers/beanstalk/Command.php | 2 +- src/drivers/db/Command.php | 2 +- src/drivers/db/InfoAction.php | 2 +- src/drivers/file/Command.php | 2 +- src/drivers/file/InfoAction.php | 2 +- src/drivers/gearman/Command.php | 2 +- src/drivers/redis/Command.php | 2 +- src/drivers/redis/InfoAction.php | 2 +- src/drivers/sqs/Command.php | 2 +- src/drivers/stomp/Command.php | 2 +- tests/docker-compose.yml | 3 +-- 19 files changed, 21 insertions(+), 21 deletions(-) diff --git a/composer.json b/composer.json index 8b378d431..605c9b6cf 100644 --- a/composer.json +++ b/composer.json @@ -17,8 +17,8 @@ }, "require": { "php": ">=8.1", - "yiisoft/yii2": "~2.0.14", - "symfony/process": "^6.3||^7.0", + "yiisoft/yii2": "~2.0.50", + "symfony/process": "^7.0", "laravel/serializable-closure": "^v1.3.0" }, "require-dev": { diff --git a/psalm.xml b/psalm.xml index d92109732..e04d9b391 100644 --- a/psalm.xml +++ b/psalm.xml @@ -27,5 +27,9 @@ + + + + diff --git a/src/JobEvent.php b/src/JobEvent.php index fab622150..31968b09c 100644 --- a/src/JobEvent.php +++ b/src/JobEvent.php @@ -27,7 +27,7 @@ abstract class JobEvent extends Event /** * @var Queue * @inheritdoc - * @psalm-suppress PropertyNotSetInConstructor, NonInvariantDocblockPropertyType + * @psalm-suppress NonInvariantDocblockPropertyType */ public $sender; /** diff --git a/src/cli/VerboseBehavior.php b/src/cli/VerboseBehavior.php index e4dd27613..f9ea59a55 100644 --- a/src/cli/VerboseBehavior.php +++ b/src/cli/VerboseBehavior.php @@ -31,7 +31,6 @@ class VerboseBehavior extends Behavior public $owner; /** * @var Controller - * @psalm-suppress PropertyNotSetInConstructor */ public Controller $command; diff --git a/src/cli/WorkerEvent.php b/src/cli/WorkerEvent.php index 6dc4bf3c6..530c8ebd5 100644 --- a/src/cli/WorkerEvent.php +++ b/src/cli/WorkerEvent.php @@ -27,12 +27,11 @@ class WorkerEvent extends Event /** * @var Queue * @inheritdoc - * @psalm-suppress PropertyNotSetInConstructor, NonInvariantDocblockPropertyType + * @psalm-suppress NonInvariantDocblockPropertyType */ public $sender; /** * @var LoopInterface - * @psalm-suppress PropertyNotSetInConstructor */ public LoopInterface $loop; /** diff --git a/src/closure/Behavior.php b/src/closure/Behavior.php index 75b051181..f6a2b1dd4 100644 --- a/src/closure/Behavior.php +++ b/src/closure/Behavior.php @@ -33,7 +33,7 @@ class Behavior extends \yii\base\Behavior { /** * @var Queue - * @psalm-suppress PropertyNotSetInConstructor, NonInvariantDocblockPropertyType + * @psalm-suppress NonInvariantDocblockPropertyType */ public $owner; diff --git a/src/debug/Panel.php b/src/debug/Panel.php index 2dcabeb8d..0d63cfddd 100644 --- a/src/debug/Panel.php +++ b/src/debug/Panel.php @@ -24,7 +24,6 @@ * Debug Panel. * * @author Roman Zhuravlev - * @psalm-suppress PropertyNotSetInConstructor */ class Panel extends BasePanel implements ViewContextInterface { diff --git a/src/drivers/amqp_interop/Command.php b/src/drivers/amqp_interop/Command.php index 1dcd2b5cd..b24f1cc25 100644 --- a/src/drivers/amqp_interop/Command.php +++ b/src/drivers/amqp_interop/Command.php @@ -23,7 +23,7 @@ class Command extends CliCommand { /** * @var Queue - * @psalm-suppress PropertyNotSetInConstructor, NonInvariantDocblockPropertyType + * @psalm-suppress NonInvariantDocblockPropertyType */ public CliQueue $queue; diff --git a/src/drivers/beanstalk/Command.php b/src/drivers/beanstalk/Command.php index ebb54b4bf..2df4e720a 100644 --- a/src/drivers/beanstalk/Command.php +++ b/src/drivers/beanstalk/Command.php @@ -23,7 +23,7 @@ class Command extends CliCommand { /** * @var Queue - * @psalm-suppress PropertyNotSetInConstructor, NonInvariantPropertyType, NonInvariantDocblockPropertyType + * @psalm-suppress NonInvariantPropertyType, NonInvariantDocblockPropertyType */ public CliQueue $queue; /** diff --git a/src/drivers/db/Command.php b/src/drivers/db/Command.php index 798a2ca87..4978bdd7f 100644 --- a/src/drivers/db/Command.php +++ b/src/drivers/db/Command.php @@ -24,7 +24,7 @@ class Command extends CliCommand { /** * @var Queue - * @psalm-suppress PropertyNotSetInConstructor, NonInvariantDocblockPropertyType + * @psalm-suppress NonInvariantDocblockPropertyType */ public CliQueue $queue; /** diff --git a/src/drivers/db/InfoAction.php b/src/drivers/db/InfoAction.php index ecbe3d6cc..1280fa9a0 100644 --- a/src/drivers/db/InfoAction.php +++ b/src/drivers/db/InfoAction.php @@ -28,7 +28,7 @@ class InfoAction extends Action { /** * @var Queue - * @psalm-suppress PropertyNotSetInConstructor, NonInvariantDocblockPropertyType + * @psalm-suppress NonInvariantDocblockPropertyType */ public CliQueue $queue; diff --git a/src/drivers/file/Command.php b/src/drivers/file/Command.php index 0cce1f9a3..abe94f4d3 100644 --- a/src/drivers/file/Command.php +++ b/src/drivers/file/Command.php @@ -24,7 +24,7 @@ class Command extends CliCommand { /** * @var Queue - * @psalm-suppress PropertyNotSetInConstructor, NonInvariantDocblockPropertyType + * @psalm-suppress NonInvariantDocblockPropertyType */ public CliQueue $queue; /** diff --git a/src/drivers/file/InfoAction.php b/src/drivers/file/InfoAction.php index 8e9a89ce9..a2bc34d28 100644 --- a/src/drivers/file/InfoAction.php +++ b/src/drivers/file/InfoAction.php @@ -26,7 +26,7 @@ class InfoAction extends Action { /** * @var Queue - * @psalm-suppress NonInvariantDocblockPropertyType, PropertyNotSetInConstructor + * @psalm-suppress NonInvariantDocblockPropertyType */ public CliQueue $queue; diff --git a/src/drivers/gearman/Command.php b/src/drivers/gearman/Command.php index 3bf256cac..d21c191e4 100644 --- a/src/drivers/gearman/Command.php +++ b/src/drivers/gearman/Command.php @@ -22,7 +22,7 @@ class Command extends CliCommand { /** * @var Queue - * @psalm-suppress PropertyNotSetInConstructor, NonInvariantDocblockPropertyType + * @psalm-suppress NonInvariantDocblockPropertyType */ public CliQueue $queue; diff --git a/src/drivers/redis/Command.php b/src/drivers/redis/Command.php index b632a3489..50da9ac51 100644 --- a/src/drivers/redis/Command.php +++ b/src/drivers/redis/Command.php @@ -24,7 +24,7 @@ class Command extends CliCommand { /** * @var Queue - * @psalm-suppress PropertyNotSetInConstructor, NonInvariantDocblockPropertyType + * @psalm-suppress NonInvariantDocblockPropertyType */ public CliQueue $queue; /** diff --git a/src/drivers/redis/InfoAction.php b/src/drivers/redis/InfoAction.php index ec5755b45..97fe1fa1e 100644 --- a/src/drivers/redis/InfoAction.php +++ b/src/drivers/redis/InfoAction.php @@ -25,7 +25,7 @@ class InfoAction extends Action { /** * @var Queue - * @psalm-suppress PropertyNotSetInConstructor, NonInvariantDocblockPropertyType + * @psalm-suppress NonInvariantDocblockPropertyType */ public CliQueue $queue; diff --git a/src/drivers/sqs/Command.php b/src/drivers/sqs/Command.php index e5f90c490..9cb5850ad 100644 --- a/src/drivers/sqs/Command.php +++ b/src/drivers/sqs/Command.php @@ -24,7 +24,7 @@ class Command extends CliCommand { /** * @var Queue - * @psalm-suppress PropertyNotSetInConstructor, NonInvariantDocblockPropertyType + * @psalm-suppress NonInvariantDocblockPropertyType */ public CliQueue $queue; diff --git a/src/drivers/stomp/Command.php b/src/drivers/stomp/Command.php index 71bbfd9d1..974a0d1c3 100644 --- a/src/drivers/stomp/Command.php +++ b/src/drivers/stomp/Command.php @@ -24,7 +24,7 @@ class Command extends CliCommand { /** * @var Queue - * @psalm-suppress PropertyNotSetInConstructor, NonInvariantDocblockPropertyType + * @psalm-suppress NonInvariantDocblockPropertyType */ public CliQueue $queue; diff --git a/tests/docker-compose.yml b/tests/docker-compose.yml index 01426e342..67a6fd645 100644 --- a/tests/docker-compose.yml +++ b/tests/docker-compose.yml @@ -1,6 +1,5 @@ -version: "3.5" +--- services: - # https://hub.docker.com/_/php/ yii2-queue-php: container_name: yii2-queue-php From f5470142e27c5f6404bbafa58479071bf8f0474f Mon Sep 17 00:00:00 2001 From: EAMoiseenko Date: Sun, 18 May 2025 16:34:37 +0300 Subject: [PATCH 17/22] Fixed psalm issues --- .github/workflows/main.yml | 2 +- .github/workflows/static.yml | 2 +- Makefile | 8 +++--- composer.json | 2 +- src/cli/InfoAction.php | 11 +++++--- src/drivers/db/StatisticsProvider.php | 26 ++++++++++++------- src/drivers/file/StatisticsProvider.php | 18 +++++++------ src/drivers/redis/StatisticsProvider.php | 13 ++++++---- src/interfaces/DelayedCountInterface.php | 5 +++- src/interfaces/DoneCountInterface.php | 5 +++- src/interfaces/ReservedCountInterface.php | 5 +++- .../StatisticsProviderInterface.php | 3 +++ src/interfaces/WaitingCountInterface.php | 5 +++- src/serializers/JsonSerializer.php | 2 +- tests/docker-compose.yml | 2 +- tests/docker/php/Dockerfile | 2 +- 16 files changed, 71 insertions(+), 40 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index eb0b97723..53abb86e9 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -30,7 +30,7 @@ jobs: strategy: fail-fast: false matrix: - php: [ '8.1', '8.2', '8.3' ] + php: [ '8.2', '8.3', '8.4' ] steps: - name: Checkout. uses: actions/checkout@v2 diff --git a/.github/workflows/static.yml b/.github/workflows/static.yml index 7e37c591d..5126dc889 100644 --- a/.github/workflows/static.yml +++ b/.github/workflows/static.yml @@ -32,7 +32,7 @@ jobs: strategy: fail-fast: false matrix: - php: [ '8.1', '8.2', '8.3' ] + php: [ '8.2', '8.3', '8.4' ] steps: - name: Checkout. uses: actions/checkout@v2 diff --git a/Makefile b/Makefile index 6fb9191e5..c01e40b11 100644 --- a/Makefile +++ b/Makefile @@ -1,13 +1,13 @@ 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=8.1 }}. Default latest PHP 8.1 +build: ## Build an image from a docker-compose file. Params: {{ v=8.2 }}. Default latest PHP 8.2 @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 +test: ## Run tests. Params: {{ v=8.2 }}. Default latest PHP 8.2 make build PHP_VERSION=$(filter-out $@,$(v)) docker compose run yii2-queue-php vendor/bin/phpunit --coverage-clover coverage.xml make down @@ -15,7 +15,7 @@ test: ## Run tests. Params: {{ v=8.1 }}. Default latest PHP 8.1 down: ## Stop and remove containers, networks docker compose down -benchmark: ## Run benchmark. Params: {{ v=8.1 }}. Default latest PHP 8.1 +benchmark: ## Run benchmark. Params: {{ v=8.2 }}. Default latest PHP 8.2 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 @@ -23,7 +23,7 @@ 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 +static-analyze: ## Run code static analyze. Params: {{ v=8.2 }}. Default latest PHP 8.2 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 diff --git a/composer.json b/composer.json index 605c9b6cf..84f0a49f1 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.1", + "php": ">=8.2", "yiisoft/yii2": "~2.0.50", "symfony/process": "^7.0", "laravel/serializable-closure": "^v1.3.0" diff --git a/src/cli/InfoAction.php b/src/cli/InfoAction.php index f857ffe55..7f3ed669c 100644 --- a/src/cli/InfoAction.php +++ b/src/cli/InfoAction.php @@ -1,4 +1,7 @@ + * + * @property Controller $controller */ class InfoAction extends Action { /** * @var Queue */ - public $queue; - + public Queue $queue; /** * Info about queue status. */ - public function run() + public function run(): void { if (!($this->queue instanceof StatisticsProviderInterface)) { throw new NotSupportedException('Queue does not support ' . StatisticsProviderInterface::class); diff --git a/src/drivers/db/StatisticsProvider.php b/src/drivers/db/StatisticsProvider.php index ff6020314..50f05d5fb 100644 --- a/src/drivers/db/StatisticsProvider.php +++ b/src/drivers/db/StatisticsProvider.php @@ -1,4 +1,7 @@ from($this->queue->tableName) ->andWhere(['channel' => $this->queue->channel]) ->andWhere(['reserved_at' => null]) - ->andWhere(['delay' => 0])->count('*', $this->queue->db); + ->andWhere(['delay' => 0]) + ->count('*', $this->queue->db); } /** * @inheritdoc */ - public function getDelayedCount() + public function getDelayedCount(): int { return (new Query()) ->from($this->queue->tableName) ->andWhere(['channel' => $this->queue->channel]) ->andWhere(['reserved_at' => null]) - ->andWhere(['>', 'delay', 0])->count('*', $this->queue->db); + ->andWhere(['>', 'delay', 0]) + ->count('*', $this->queue->db); } /** * @inheritdoc */ - public function getReservedCount() + public function getReservedCount(): int { return (new Query()) ->from($this->queue->tableName) ->andWhere(['channel' => $this->queue->channel]) ->andWhere('[[reserved_at]] is not null') - ->andWhere(['done_at' => null])->count('*', $this->queue->db); + ->andWhere(['done_at' => null]) + ->count('*', $this->queue->db); } /** * @inheritdoc */ - public function getDoneCount() + public function getDoneCount(): int { return (new Query()) ->from($this->queue->tableName) ->andWhere(['channel' => $this->queue->channel]) - ->andWhere('[[done_at]] is not null')->count('*', $this->queue->db); + ->andWhere('[[done_at]] is not null') + ->count('*', $this->queue->db); } } diff --git a/src/drivers/file/StatisticsProvider.php b/src/drivers/file/StatisticsProvider.php index cedc9520b..33fdac820 100644 --- a/src/drivers/file/StatisticsProvider.php +++ b/src/drivers/file/StatisticsProvider.php @@ -1,4 +1,7 @@ getIndexData(); return !empty($data['waiting']) ? count($data['waiting']) : 0; @@ -44,7 +46,7 @@ public function getWaitingCount() /** * @inheritdoc */ - public function getDelayedCount() + public function getDelayedCount(): int { $data = $this->getIndexData(); return !empty($data['delayed']) ? count($data['delayed']) : 0; @@ -53,7 +55,7 @@ public function getDelayedCount() /** * @inheritdoc */ - public function getReservedCount() + public function getReservedCount(): int { $data = $this->getIndexData(); return !empty($data['reserved']) ? count($data['reserved']) : 0; @@ -62,7 +64,7 @@ public function getReservedCount() /** * @inheritdoc */ - public function getDoneCount() + public function getDoneCount(): int { $data = $this->getIndexData(); $total = isset($data['lastId']) ? $data['lastId'] : 0; @@ -74,8 +76,8 @@ protected function getIndexData() $fileName = $this->queue->path . '/index.data'; if (file_exists($fileName)) { return call_user_func($this->queue->indexDeserializer, file_get_contents($fileName)); - } else { - return []; } + + return []; } } diff --git a/src/drivers/redis/StatisticsProvider.php b/src/drivers/redis/StatisticsProvider.php index 78f21d2d3..23ddb4557 100644 --- a/src/drivers/redis/StatisticsProvider.php +++ b/src/drivers/redis/StatisticsProvider.php @@ -1,4 +1,7 @@ queue->channel; return $this->queue->redis->llen("$prefix.waiting"); @@ -44,7 +47,7 @@ public function getWaitingCount() /** * @inheritdoc */ - public function getDelayedCount() + public function getDelayedCount(): int { $prefix = $this->queue->channel; return $this->queue->redis->zcount("$prefix.delayed", '-inf', '+inf'); @@ -53,7 +56,7 @@ public function getDelayedCount() /** * @inheritdoc */ - public function getReservedCount() + public function getReservedCount(): int { $prefix = $this->queue->channel; return $this->queue->redis->zcount("$prefix.reserved", '-inf', '+inf'); @@ -62,7 +65,7 @@ public function getReservedCount() /** * @inheritdoc */ - public function getDoneCount() + public function getDoneCount(): int { $prefix = $this->queue->channel; $waiting = $this->getWaitingCount(); diff --git a/src/interfaces/DelayedCountInterface.php b/src/interfaces/DelayedCountInterface.php index 41ea00532..fcf19fd22 100644 --- a/src/interfaces/DelayedCountInterface.php +++ b/src/interfaces/DelayedCountInterface.php @@ -1,4 +1,7 @@ > /etc/apk/repositories \ && echo https://dl-cdn.alpinelinux.org/alpine/edge/community >> /etc/apk/repositories \ From f0264bc207c94ef26d6e6328a6dd7510a202a808 Mon Sep 17 00:00:00 2001 From: EAMoiseenko Date: Sun, 18 May 2025 17:02:44 +0300 Subject: [PATCH 18/22] Fixed psalm issues --- src/drivers/db/Queue.php | 13 ++++++----- src/drivers/db/StatisticsProvider.php | 22 ++++++++++++++----- src/drivers/file/Queue.php | 13 ++++++----- src/drivers/file/StatisticsProvider.php | 17 ++++++++++++-- src/drivers/redis/Queue.php | 13 ++++++----- src/drivers/redis/StatisticsProvider.php | 18 ++++++++++----- src/interfaces/StatisticsInterface.php | 18 +++++++++++++++ .../StatisticsProviderInterface.php | 4 ++-- 8 files changed, 84 insertions(+), 34 deletions(-) create mode 100644 src/interfaces/StatisticsInterface.php diff --git a/src/drivers/db/Queue.php b/src/drivers/db/Queue.php index 4007bbc9d..c26ad79b1 100644 --- a/src/drivers/db/Queue.php +++ b/src/drivers/db/Queue.php @@ -17,6 +17,7 @@ use yii\di\Instance; use yii\mutex\Mutex; use yii\queue\cli\Queue as CliQueue; +use yii\queue\interfaces\StatisticsInterface; use yii\queue\interfaces\StatisticsProviderInterface; /** @@ -285,16 +286,16 @@ private function getMutex(): Mutex return $mutex; } - private $_statistcsProvider; + private StatisticsInterface $_statisticsProvider; /** - * @return StatisticsProvider + * @return StatisticsInterface */ - public function getStatisticsProvider() + public function getStatisticsProvider(): StatisticsInterface { - if (!$this->_statistcsProvider) { - $this->_statistcsProvider = new StatisticsProvider($this); + if (!isset($this->_statisticsProvider)) { + $this->_statisticsProvider = new StatisticsProvider($this); } - return $this->_statistcsProvider; + return $this->_statisticsProvider; } } diff --git a/src/drivers/db/StatisticsProvider.php b/src/drivers/db/StatisticsProvider.php index 50f05d5fb..c5d0f3a9b 100644 --- a/src/drivers/db/StatisticsProvider.php +++ b/src/drivers/db/StatisticsProvider.php @@ -15,6 +15,7 @@ use yii\queue\interfaces\DelayedCountInterface; use yii\queue\interfaces\DoneCountInterface; use yii\queue\interfaces\ReservedCountInterface; +use yii\queue\interfaces\StatisticsInterface; use yii\queue\interfaces\WaitingCountInterface; /** @@ -22,14 +23,19 @@ * * @author Kalmer Kaurson */ -class StatisticsProvider extends BaseObject implements DoneCountInterface, WaitingCountInterface, DelayedCountInterface, ReservedCountInterface +class StatisticsProvider extends BaseObject implements + DoneCountInterface, + WaitingCountInterface, + DelayedCountInterface, + ReservedCountInterface, + StatisticsInterface { /** * @var Queue */ protected Queue $queue; - public function __construct(Queue $queue, $config = []) + public function __construct(Queue $queue, array $config = []) { $this->queue = $queue; parent::__construct($config); @@ -40,7 +46,8 @@ public function __construct(Queue $queue, $config = []) */ public function getWaitingCount(): int { - return (new Query()) + /** @psalm-var \yii\db\Connection $this->queue->db */ + return (int) (new Query()) ->from($this->queue->tableName) ->andWhere(['channel' => $this->queue->channel]) ->andWhere(['reserved_at' => null]) @@ -53,7 +60,8 @@ public function getWaitingCount(): int */ public function getDelayedCount(): int { - return (new Query()) + /** @psalm-var \yii\db\Connection $this->queue->db */ + return (int) (new Query()) ->from($this->queue->tableName) ->andWhere(['channel' => $this->queue->channel]) ->andWhere(['reserved_at' => null]) @@ -66,7 +74,8 @@ public function getDelayedCount(): int */ public function getReservedCount(): int { - return (new Query()) + /** @psalm-var \yii\db\Connection $this->queue->db */ + return (int) (new Query()) ->from($this->queue->tableName) ->andWhere(['channel' => $this->queue->channel]) ->andWhere('[[reserved_at]] is not null') @@ -79,7 +88,8 @@ public function getReservedCount(): int */ public function getDoneCount(): int { - return (new Query()) + /** @psalm-var \yii\db\Connection $this->queue->db */ + return (int) (new Query()) ->from($this->queue->tableName) ->andWhere(['channel' => $this->queue->channel]) ->andWhere('[[done_at]] is not null') diff --git a/src/drivers/file/Queue.php b/src/drivers/file/Queue.php index 805d3345a..2bfcade70 100644 --- a/src/drivers/file/Queue.php +++ b/src/drivers/file/Queue.php @@ -16,6 +16,7 @@ use yii\base\NotSupportedException; use yii\helpers\FileHelper; use yii\queue\cli\Queue as CliQueue; +use yii\queue\interfaces\StatisticsInterface; use yii\queue\interfaces\StatisticsProviderInterface; /** @@ -340,16 +341,16 @@ private function touchIndex(callable $callback): void } } - private $_statistcsProvider; + private StatisticsInterface $_statisticsProvider; /** - * @return StatisticsProvider + * @return StatisticsInterface */ - public function getStatisticsProvider() + public function getStatisticsProvider(): StatisticsInterface { - if (!$this->_statistcsProvider) { - $this->_statistcsProvider = new StatisticsProvider($this); + if (!isset($this->_statisticsProvider)) { + $this->_statisticsProvider = new StatisticsProvider($this); } - return $this->_statistcsProvider; + return $this->_statisticsProvider; } } diff --git a/src/drivers/file/StatisticsProvider.php b/src/drivers/file/StatisticsProvider.php index 33fdac820..27cc1a75f 100644 --- a/src/drivers/file/StatisticsProvider.php +++ b/src/drivers/file/StatisticsProvider.php @@ -14,6 +14,7 @@ use yii\queue\interfaces\DelayedCountInterface; use yii\queue\interfaces\DoneCountInterface; use yii\queue\interfaces\ReservedCountInterface; +use yii\queue\interfaces\StatisticsInterface; use yii\queue\interfaces\WaitingCountInterface; /** @@ -21,14 +22,19 @@ * * @author Kalmer Kaurson */ -class StatisticsProvider extends BaseObject implements DoneCountInterface, WaitingCountInterface, DelayedCountInterface, ReservedCountInterface +class StatisticsProvider extends BaseObject implements + DoneCountInterface, + WaitingCountInterface, + DelayedCountInterface, + ReservedCountInterface, + StatisticsInterface { /** * @var Queue */ protected Queue $queue; - public function __construct(Queue $queue, $config = []) + public function __construct(Queue $queue, array $config = []) { $this->queue = $queue; parent::__construct($config); @@ -39,6 +45,7 @@ public function __construct(Queue $queue, $config = []) */ public function getWaitingCount(): int { + /** @var array{waiting:array} $data */ $data = $this->getIndexData(); return !empty($data['waiting']) ? count($data['waiting']) : 0; } @@ -48,6 +55,7 @@ public function getWaitingCount(): int */ public function getDelayedCount(): int { + /** @var array{delayed:array} $data */ $data = $this->getIndexData(); return !empty($data['delayed']) ? count($data['delayed']) : 0; } @@ -57,6 +65,7 @@ public function getDelayedCount(): int */ public function getReservedCount(): int { + /** @var array{reserved:array} $data */ $data = $this->getIndexData(); return !empty($data['reserved']) ? count($data['reserved']) : 0; } @@ -66,11 +75,15 @@ public function getReservedCount(): int */ public function getDoneCount(): int { + /** @var array{lastId:int} $data */ $data = $this->getIndexData(); $total = isset($data['lastId']) ? $data['lastId'] : 0; return $total - $this->getDelayedCount() - $this->getWaitingCount(); } + /** + * @psalm-suppress MissingReturnType + */ protected function getIndexData() { $fileName = $this->queue->path . '/index.data'; diff --git a/src/drivers/redis/Queue.php b/src/drivers/redis/Queue.php index 0aa312498..48232e3c0 100644 --- a/src/drivers/redis/Queue.php +++ b/src/drivers/redis/Queue.php @@ -14,6 +14,7 @@ use yii\base\NotSupportedException; use yii\di\Instance; use yii\queue\cli\Queue as CliQueue; +use yii\queue\interfaces\StatisticsInterface; use yii\queue\interfaces\StatisticsProviderInterface; use yii\redis\Connection; @@ -225,16 +226,16 @@ protected function pushMessage(string $payload, int $ttr, int $delay, mixed $pri return $id; } - private $_statistcsProvider; + private StatisticsInterface $_statisticsProvider; /** - * @return StatisticsProvider + * @return StatisticsInterface */ - public function getStatisticsProvider() + public function getStatisticsProvider(): StatisticsInterface { - if (!$this->_statistcsProvider) { - $this->_statistcsProvider = new StatisticsProvider($this); + if (!isset($this->_statisticsProvider)) { + $this->_statisticsProvider = new StatisticsProvider($this); } - return $this->_statistcsProvider; + return $this->_statisticsProvider; } } diff --git a/src/drivers/redis/StatisticsProvider.php b/src/drivers/redis/StatisticsProvider.php index 23ddb4557..5df423f33 100644 --- a/src/drivers/redis/StatisticsProvider.php +++ b/src/drivers/redis/StatisticsProvider.php @@ -14,6 +14,7 @@ use yii\queue\interfaces\DelayedCountInterface; use yii\queue\interfaces\DoneCountInterface; use yii\queue\interfaces\ReservedCountInterface; +use yii\queue\interfaces\StatisticsInterface; use yii\queue\interfaces\WaitingCountInterface; /** @@ -21,7 +22,12 @@ * * @author Kalmer Kaurson */ -class StatisticsProvider extends BaseObject implements DoneCountInterface, WaitingCountInterface, DelayedCountInterface, ReservedCountInterface +class StatisticsProvider extends BaseObject implements + DoneCountInterface, + WaitingCountInterface, + DelayedCountInterface, + ReservedCountInterface, + StatisticsInterface { /** * @var Queue @@ -29,7 +35,7 @@ class StatisticsProvider extends BaseObject implements DoneCountInterface, Waiti protected Queue $queue; - public function __construct(Queue $queue, $config = []) + public function __construct(Queue $queue, array $config = []) { $this->queue = $queue; parent::__construct($config); @@ -41,7 +47,7 @@ public function __construct(Queue $queue, $config = []) public function getWaitingCount(): int { $prefix = $this->queue->channel; - return $this->queue->redis->llen("$prefix.waiting"); + return (int) $this->queue->redis->llen("$prefix.waiting"); } /** @@ -50,7 +56,7 @@ public function getWaitingCount(): int public function getDelayedCount(): int { $prefix = $this->queue->channel; - return $this->queue->redis->zcount("$prefix.delayed", '-inf', '+inf'); + return (int) $this->queue->redis->zcount("$prefix.delayed", '-inf', '+inf'); } /** @@ -59,7 +65,7 @@ public function getDelayedCount(): int public function getReservedCount(): int { $prefix = $this->queue->channel; - return $this->queue->redis->zcount("$prefix.reserved", '-inf', '+inf'); + return (int) $this->queue->redis->zcount("$prefix.reserved", '-inf', '+inf'); } /** @@ -71,7 +77,7 @@ public function getDoneCount(): int $waiting = $this->getWaitingCount(); $delayed = $this->getDelayedCount(); $reserved = $this->getReservedCount(); - $total = $this->queue->redis->get("$prefix.message_id"); + $total = (int) $this->queue->redis->get("$prefix.message_id"); return $total - $waiting - $delayed - $reserved; } } diff --git a/src/interfaces/StatisticsInterface.php b/src/interfaces/StatisticsInterface.php new file mode 100644 index 000000000..34cbfde77 --- /dev/null +++ b/src/interfaces/StatisticsInterface.php @@ -0,0 +1,18 @@ + Date: Sun, 18 May 2025 17:41:34 +0300 Subject: [PATCH 19/22] Fixed psalm issues --- composer.json | 2 +- psalm.xml | 9 ++++++ tests/cli/InfoActionTest.php | 29 +++++++++---------- tests/cli/Queue.php | 20 ++++++++----- .../cli/providers/BaseStatisticsProvider.php | 9 ++++-- tests/cli/providers/DelayedCountProvider.php | 4 ++- tests/cli/providers/DoneCountProvider.php | 4 ++- tests/cli/providers/ReservedCountProvider.php | 4 ++- tests/cli/providers/WaitingCountProvider.php | 4 ++- tests/drivers/redis/QueueTest.php | 18 ++++++------ tests/drivers/redis/RedisCrashMock.php | 3 ++ 11 files changed, 67 insertions(+), 39 deletions(-) diff --git a/composer.json b/composer.json index 84f0a49f1..be729e785 100644 --- a/composer.json +++ b/composer.json @@ -33,7 +33,7 @@ "enqueue/stomp": "^0.10.0", "pda/pheanstalk": "^5.0.0", "aws/aws-sdk-php": "3.285.0", - "vimeo/psalm": "^5.10.0" + "vimeo/psalm": "^6.0.0" }, "suggest": { "ext-pcntl": "Need for process signals.", diff --git a/psalm.xml b/psalm.xml index e04d9b391..a937de065 100644 --- a/psalm.xml +++ b/psalm.xml @@ -31,5 +31,14 @@ + + + + + + + + + diff --git a/tests/cli/InfoActionTest.php b/tests/cli/InfoActionTest.php index 1756e374a..26ad57f3a 100644 --- a/tests/cli/InfoActionTest.php +++ b/tests/cli/InfoActionTest.php @@ -1,4 +1,7 @@ getMockBuilder(Controller::class) ->setConstructorArgs(['testController', new Module('testModule')]) - ->getMock() - ; + ->getMock(); $controller->expects(self::exactly(3)) ->method('stdout') - ->withConsecutive( + ->with( [ 'Jobs' . PHP_EOL, Console::FG_GREEN, @@ -45,8 +47,7 @@ public function testWaitingCount() [ 10 . PHP_EOL ] - ) - ; + ); $queue = $this->getMockBuilder(Queue::class)->getMock(); @@ -67,7 +68,7 @@ public function testWaitingCount() $action->run(); } - public function testDelayedCount() + public function testDelayedCount(): void { $controller = $this->getMockBuilder(Controller::class) ->setConstructorArgs(['testController', new Module('testModule')]) @@ -76,7 +77,7 @@ public function testDelayedCount() $controller->expects(self::exactly(3)) ->method('stdout') - ->withConsecutive( + ->with( [ 'Jobs' . PHP_EOL, Console::FG_GREEN, @@ -110,7 +111,7 @@ public function testDelayedCount() $action->run(); } - public function testReservedCount() + public function testReservedCount(): void { $controller = $this->getMockBuilder(Controller::class) ->setConstructorArgs(['testController', new Module('testModule')]) @@ -119,7 +120,7 @@ public function testReservedCount() $controller->expects(self::exactly(3)) ->method('stdout') - ->withConsecutive( + ->with( [ 'Jobs' . PHP_EOL, Console::FG_GREEN, @@ -131,8 +132,7 @@ public function testReservedCount() [ 10 . PHP_EOL ] - ) - ; + ); $queue = $this->getMockBuilder(Queue::class)->getMock(); @@ -162,7 +162,7 @@ public function testDoneCount() $controller->expects(self::exactly(3)) ->method('stdout') - ->withConsecutive( + ->with( [ 'Jobs' . PHP_EOL, Console::FG_GREEN, @@ -174,8 +174,7 @@ public function testDoneCount() [ 10 . PHP_EOL ] - ) - ; + ); $queue = $this->getMockBuilder(Queue::class)->getMock(); diff --git a/tests/cli/Queue.php b/tests/cli/Queue.php index e7a6412d7..e7b5b981c 100644 --- a/tests/cli/Queue.php +++ b/tests/cli/Queue.php @@ -1,4 +1,7 @@ _statistcsProvider) { - $this->_statistcsProvider = new BaseStatisticsProvider($this); + if (!isset($this->_statisticsProvider)) { + $this->_statisticsProvider = new BaseStatisticsProvider($this); } - return $this->_statistcsProvider; + return $this->_statisticsProvider; } } diff --git a/tests/cli/providers/BaseStatisticsProvider.php b/tests/cli/providers/BaseStatisticsProvider.php index a403d52ca..3e7acce1a 100644 --- a/tests/cli/providers/BaseStatisticsProvider.php +++ b/tests/cli/providers/BaseStatisticsProvider.php @@ -1,5 +1,7 @@ */ -class BaseStatisticsProvider extends BaseObject +class BaseStatisticsProvider extends BaseObject implements StatisticsInterface { /** * @var Queue */ - protected $queue; + protected Queue $queue; - public function __construct(Queue $queue, $config = []) + public function __construct(Queue $queue, array $config = []) { $this->queue = $queue; parent::__construct($config); diff --git a/tests/cli/providers/DelayedCountProvider.php b/tests/cli/providers/DelayedCountProvider.php index d15beab58..17e7d6dcd 100644 --- a/tests/cli/providers/DelayedCountProvider.php +++ b/tests/cli/providers/DelayedCountProvider.php @@ -1,5 +1,7 @@ assertFalse((bool) $this->getQueue()->redis->hexists($this->getQueue()->channel . '.messages', $id)); } - public function testWaitingCount() + public function testWaitingCount(): void { $this->getQueue()->push($this->createSimpleJob()); $this->assertEquals(1, $this->getQueue()->getStatisticsProvider()->getWaitingCount()); } - public function testDelayedCount() + public function testDelayedCount(): void { $this->getQueue()->delay(5)->push($this->createSimpleJob()); $this->assertEquals(1, $this->getQueue()->getStatisticsProvider()->getDelayedCount()); } - public function testReservedCount() + public function testReservedCount(): void { $this->getQueue()->messageHandler = function () { $this->assertEquals(1, $this->getQueue()->getStatisticsProvider()->getReservedCount()); }; - $job = $this->createSimpleJob(); - $this->getQueue()->push($job); + $this->getQueue()->push($this->createSimpleJob()); $this->getQueue()->run(false); } - public function testDoneCount() + public function testDoneCount(): void { $this->startProcess(['php', 'yii', 'queue/listen', '1']); $job = $this->createSimpleJob(); @@ -151,13 +151,13 @@ protected function tearDown(): void * 3. Mock Redis to simulate crash during moveExpired * 4. Successfully process job after recovery */ - public function testConsumeDelayedMessageAtLeastOnce() + public function testConsumeDelayedMessageAtLeastOnce(): void { $job = $this->createSimpleJob(); $this->getQueue()->delay(1)->push($job); // Expect a single message to be received. $messageCount = 0; - $this->getQueue()->messageHandler = function () use(&$messageCount) { + $this->getQueue()->messageHandler = static function () use(&$messageCount) { $messageCount++; }; @@ -171,7 +171,7 @@ public function testConsumeDelayedMessageAtLeastOnce() 'hostname' => getenv('REDIS_HOST') ?: 'localhost', 'database' => getenv('REDIS_DB') ?: 1, 'crashOnCommand' => 'rpush' // Crash when trying to move job to waiting queue. - ], 'yii\redis\Connection'); + ], Connection::class); $queue = $this->getQueue(); $old = $queue->redis; diff --git a/tests/drivers/redis/RedisCrashMock.php b/tests/drivers/redis/RedisCrashMock.php index e463e08a9..b332d6abe 100644 --- a/tests/drivers/redis/RedisCrashMock.php +++ b/tests/drivers/redis/RedisCrashMock.php @@ -1,4 +1,7 @@ Date: Sun, 18 May 2025 18:04:04 +0300 Subject: [PATCH 20/22] Fixed psalm issues --- psalm.xml | 1 + tests/drivers/db/TestCase.php | 4 ++-- tests/drivers/file/QueueTest.php | 11 +++++------ 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/psalm.xml b/psalm.xml index a937de065..ec0f9676e 100644 --- a/psalm.xml +++ b/psalm.xml @@ -40,5 +40,6 @@ + diff --git a/tests/drivers/db/TestCase.php b/tests/drivers/db/TestCase.php index 6a6a8ebc5..4a9160bb9 100644 --- a/tests/drivers/db/TestCase.php +++ b/tests/drivers/db/TestCase.php @@ -136,8 +136,8 @@ public function testReservedCount(): void public function testDoneCount(): void { - $this->getQueue()->messageHandler = function () { - return true; + $this->getQueue()->messageHandler = static function () { + return null; }; $job = $this->createSimpleJob(); diff --git a/tests/drivers/file/QueueTest.php b/tests/drivers/file/QueueTest.php index d9d8cc228..13a62b015 100644 --- a/tests/drivers/file/QueueTest.php +++ b/tests/drivers/file/QueueTest.php @@ -90,32 +90,31 @@ public function testRemove(): void $this->assertFileDoesNotExist($this->getQueue()->path . "/job$id.data"); } - public function testWaitingCount() + public function testWaitingCount(): void { $this->getQueue()->push($this->createSimpleJob()); $this->assertEquals(1, $this->getQueue()->getStatisticsProvider()->getWaitingCount()); } - public function testDelayedCount() + public function testDelayedCount(): void { $this->getQueue()->delay(5)->push($this->createSimpleJob()); $this->assertEquals(1, $this->getQueue()->getStatisticsProvider()->getDelayedCount()); } - public function testReservedCount() + public function testReservedCount(): void { $this->getQueue()->messageHandler = function () { $this->assertEquals(1, $this->getQueue()->getStatisticsProvider()->getReservedCount()); }; - $job = $this->createSimpleJob(); - $this->getQueue()->push($job); + $this->getQueue()->push($this->createSimpleJob()); $this->getQueue()->run(false); } - public function testDoneCount() + public function testDoneCount(): void { $this->startProcess(['php', 'yii', 'queue/listen', '1']); $job = $this->createSimpleJob(); From 51ff720a1a150fa7bff357039948206195a56a0f Mon Sep 17 00:00:00 2001 From: EAMoiseenko Date: Mon, 19 May 2025 11:24:01 +0300 Subject: [PATCH 21/22] Fixed psalm issues --- tests/cli/InfoActionTest.php | 43 ++++++++++++------------------- tests/drivers/db/TestCase.php | 3 ++- tests/drivers/file/QueueTest.php | 1 + tests/drivers/redis/QueueTest.php | 2 ++ 4 files changed, 21 insertions(+), 28 deletions(-) diff --git a/tests/cli/InfoActionTest.php b/tests/cli/InfoActionTest.php index 26ad57f3a..de8a3b876 100644 --- a/tests/cli/InfoActionTest.php +++ b/tests/cli/InfoActionTest.php @@ -35,7 +35,7 @@ public function testWaitingCount(): void $controller->expects(self::exactly(3)) ->method('stdout') - ->with( + ->willReturnOnConsecutiveCalls( [ 'Jobs' . PHP_EOL, Console::FG_GREEN, @@ -53,12 +53,10 @@ public function testWaitingCount(): void $provider = $this->getMockBuilder(WaitingCountProvider::class) ->setConstructorArgs([$queue]) - ->getMock() - ; + ->getMock(); $provider->expects(self::once()) ->method('getWaitingCount') - ->willReturn(10) - ; + ->willReturn(10); $queue->method('getStatisticsProvider')->willReturn($provider); @@ -72,12 +70,11 @@ public function testDelayedCount(): void { $controller = $this->getMockBuilder(Controller::class) ->setConstructorArgs(['testController', new Module('testModule')]) - ->getMock() - ; + ->getMock(); $controller->expects(self::exactly(3)) ->method('stdout') - ->with( + ->willReturnOnConsecutiveCalls( [ 'Jobs' . PHP_EOL, Console::FG_GREEN, @@ -89,19 +86,16 @@ public function testDelayedCount(): void [ 10 . PHP_EOL ] - ) - ; + ); $queue = $this->getMockBuilder(Queue::class)->getMock(); $provider = $this->getMockBuilder(DelayedCountProvider::class) ->setConstructorArgs([$queue]) - ->getMock() - ; + ->getMock(); $provider->expects(self::once()) ->method('getDelayedCount') - ->willReturn(10) - ; + ->willReturn(10); $queue->method('getStatisticsProvider')->willReturn($provider); @@ -115,12 +109,11 @@ public function testReservedCount(): void { $controller = $this->getMockBuilder(Controller::class) ->setConstructorArgs(['testController', new Module('testModule')]) - ->getMock() - ; + ->getMock(); $controller->expects(self::exactly(3)) ->method('stdout') - ->with( + ->willReturnOnConsecutiveCalls( [ 'Jobs' . PHP_EOL, Console::FG_GREEN, @@ -142,8 +135,7 @@ public function testReservedCount(): void ; $provider->expects(self::once()) ->method('getReservedCount') - ->willReturn(10) - ; + ->willReturn(10); $queue->method('getStatisticsProvider')->willReturn($provider); @@ -153,16 +145,15 @@ public function testReservedCount(): void $action->run(); } - public function testDoneCount() + public function testDoneCount(): void { $controller = $this->getMockBuilder(Controller::class) ->setConstructorArgs(['testController', new Module('testModule')]) - ->getMock() - ; + ->getMock(); $controller->expects(self::exactly(3)) ->method('stdout') - ->with( + ->willReturnOnConsecutiveCalls( [ 'Jobs' . PHP_EOL, Console::FG_GREEN, @@ -180,12 +171,10 @@ public function testDoneCount() $provider = $this->getMockBuilder(DoneCountProvider::class) ->setConstructorArgs([$queue]) - ->getMock() - ; + ->getMock(); $provider->expects(self::once()) ->method('getDoneCount') - ->willReturn(10) - ; + ->willReturn(10); $queue->method('getStatisticsProvider')->willReturn($provider); diff --git a/tests/drivers/db/TestCase.php b/tests/drivers/db/TestCase.php index 4a9160bb9..57648e9a7 100644 --- a/tests/drivers/db/TestCase.php +++ b/tests/drivers/db/TestCase.php @@ -127,6 +127,7 @@ public function testReservedCount(): void { $this->getQueue()->messageHandler = function () { $this->assertEquals(1, $this->getQueue()->getStatisticsProvider()->getReservedCount()); + return true; }; $job = $this->createSimpleJob(); @@ -137,7 +138,7 @@ public function testReservedCount(): void public function testDoneCount(): void { $this->getQueue()->messageHandler = static function () { - return null; + return true; }; $job = $this->createSimpleJob(); diff --git a/tests/drivers/file/QueueTest.php b/tests/drivers/file/QueueTest.php index 13a62b015..cab469415 100644 --- a/tests/drivers/file/QueueTest.php +++ b/tests/drivers/file/QueueTest.php @@ -108,6 +108,7 @@ public function testReservedCount(): void { $this->getQueue()->messageHandler = function () { $this->assertEquals(1, $this->getQueue()->getStatisticsProvider()->getReservedCount()); + return true; }; $this->getQueue()->push($this->createSimpleJob()); diff --git a/tests/drivers/redis/QueueTest.php b/tests/drivers/redis/QueueTest.php index 137761e3c..6777c0a45 100644 --- a/tests/drivers/redis/QueueTest.php +++ b/tests/drivers/redis/QueueTest.php @@ -110,6 +110,7 @@ public function testReservedCount(): void { $this->getQueue()->messageHandler = function () { $this->assertEquals(1, $this->getQueue()->getStatisticsProvider()->getReservedCount()); + return true; }; $this->getQueue()->push($this->createSimpleJob()); @@ -159,6 +160,7 @@ public function testConsumeDelayedMessageAtLeastOnce(): void $messageCount = 0; $this->getQueue()->messageHandler = static function () use(&$messageCount) { $messageCount++; + return true; }; // Ensure the delayed message can be consumed when more time passed than the delay is. From 5cfd6151cd69f6c7f7af6eb0e8d27814b6360806 Mon Sep 17 00:00:00 2001 From: EAMoiseenko Date: Mon, 19 May 2025 12:16:42 +0300 Subject: [PATCH 22/22] Drop PHP 8.4 --- .github/workflows/main.yml | 2 +- README.md | 2 +- src/InvalidJobException.php | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 53abb86e9..9f2e1b2c8 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -30,7 +30,7 @@ jobs: strategy: fail-fast: false matrix: - php: [ '8.2', '8.3', '8.4' ] + php: [ '8.2', '8.3' ] steps: - name: Checkout. uses: actions/checkout@v2 diff --git a/README.md b/README.md index a28bd8f40..e336b02c2 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@ Documentation is at [docs/guide/README.md](docs/guide/README.md). ## Requirements -- PHP 8.1 or higher. +- PHP 8.2 or higher. Installation ------------ diff --git a/src/InvalidJobException.php b/src/InvalidJobException.php index ae345f1d2..eb7988fb3 100644 --- a/src/InvalidJobException.php +++ b/src/InvalidJobException.php @@ -33,7 +33,7 @@ public function __construct( private readonly string $serialized, string $message = '', int $code = 0, - Throwable $previous = null + ?Throwable $previous = null ) { parent::__construct($message, $code, $previous);