From a07371eac5705ec042efdfdafec21c03b42a1c7a Mon Sep 17 00:00:00 2001 From: Roman Zipp Date: Sun, 23 Feb 2025 09:21:10 +0100 Subject: [PATCH 1/5] Fix route tests --- config/queue-monitor.php | 3 - src/Providers/QueueMonitorProvider.php | 99 +++++++++++++------------- tests/MonitorRetryTest.php | 13 ++-- tests/RoutesTest.php | 8 +++ 4 files changed, 64 insertions(+), 59 deletions(-) diff --git a/config/queue-monitor.php b/config/queue-monitor.php index 85e1ecb..a589cb2 100644 --- a/config/queue-monitor.php +++ b/config/queue-monitor.php @@ -13,9 +13,6 @@ */ 'model' => \romanzipp\QueueMonitor\Models\Monitor::class, - // Determined if the queued jobs should be monitored - 'monitor_queued_jobs' => true, - // Specify the max character length to use for storing exception backtraces. 'db_max_length_exception' => 4294967295, 'db_max_length_exception_message' => 65535, diff --git a/src/Providers/QueueMonitorProvider.php b/src/Providers/QueueMonitorProvider.php index 5a7446a..5ad5a43 100644 --- a/src/Providers/QueueMonitorProvider.php +++ b/src/Providers/QueueMonitorProvider.php @@ -2,11 +2,8 @@ namespace romanzipp\QueueMonitor\Providers; -use Illuminate\Queue\Events\JobExceptionOccurred; -use Illuminate\Queue\Events\JobFailed; -use Illuminate\Queue\Events\JobProcessed; -use Illuminate\Queue\Events\JobProcessing; -use Illuminate\Queue\Events\JobQueued; +use Illuminate\Config\Repository; +use Illuminate\Queue\Events as QueueEvents; use Illuminate\Queue\QueueManager; use Illuminate\Support\Facades\Event; use Illuminate\Support\Facades\Route; @@ -21,6 +18,15 @@ class QueueMonitorProvider extends ServiceProvider { public function boot(): void { + /** @var \Illuminate\Config\Repository $config */ + $config = $this->app['config']; + + /** @var \Illuminate\Events\Dispatcher $events */ + $events = $this->app['events']; + + /** @var \Illuminate\Queue\QueueManager $queueManager */ + $queueManager = $this->app->make(QueueManager::class); + if ($this->app->runningInConsole()) { $this->publishes([ __DIR__ . '/../../config/queue-monitor.php' => config_path('queue-monitor.php'), @@ -48,54 +54,45 @@ public function boot(): void ]); } - $this->loadViewsFrom( - __DIR__ . '/../../views', - 'queue-monitor' - ); + $this->loadViewsFrom(__DIR__ . '/../../views', 'queue-monitor'); - if (config('queue-monitor.ui.enabled')) { - Route::group($this->buildRouteGroupConfig(), function () { + if ($config->boolean('queue-monitor.ui.enabled', false)) { + Route::group(self::buildRouteGroupConfig($config), function () { $this->loadRoutesFrom(__DIR__ . '/../../routes/queue-monitor.php'); }); } - // listen to JobQueued event - if (config('queue-monitor.monitor_queued_jobs', true)) { - /** - * If the project uses Horizon, we will listen to the JobPushed event, - * because Horizon fires JobPushed event when the job is queued or retry the job again from its UI. - * - * @see https://laravel.com/docs/horizon - */ - if (class_exists('Laravel\Horizon\Events\JobPushed')) { - Event::listen('Laravel\Horizon\Events\JobPushed', function ($event) { - QueueMonitor::handleJobPushed($event); - }); - } else { - Event::listen(JobQueued::class, function (JobQueued $event) { - QueueMonitor::handleJobQueued($event); - }); - } + // Listen to queue job events + + /** + * If the project uses Horizon, we will listen to the JobPushed event, + * because Horizon fires JobPushed event when the job is queued or retry the job again from its UI. + * + * @see https://laravel.com/docs/horizon + */ + if (class_exists('Laravel\Horizon\Events\JobPushed')) { + $events->listen('Laravel\Horizon\Events\JobPushed', function ($event) { + QueueMonitor::handleJobPushed($event); + }); + } else { + $events->listen(QueueEvents\JobQueued::class, function (QueueEvents\JobQueued $event) { + QueueMonitor::handleJobQueued($event); + }); } - // listen to other job events - - /** @var QueueManager $manager */ - $manager = app(QueueManager::class); - - $manager->before(static function (JobProcessing $event) { + $queueManager->before(static function (QueueEvents\JobProcessing $event) { QueueMonitor::handleJobProcessing($event); }); - $manager->after(static function (JobProcessed $event) { + $queueManager->after(static function (QueueEvents\JobProcessed $event) { QueueMonitor::handleJobProcessed($event); }); - $manager->failing(static function (JobFailed $event) { + $queueManager->failing(static function (QueueEvents\JobFailed $event) { QueueMonitor::handleJobFailed($event); }); - $manager->exceptionOccurred(static function (JobExceptionOccurred $event) { + $queueManager->exceptionOccurred(static function (QueueEvents\JobExceptionOccurred $event) { QueueMonitor::handleJobExceptionOccurred($event); }); } @@ -103,29 +100,29 @@ public function boot(): void /** * @return array */ - private function buildRouteGroupConfig(): array + public static function buildRouteGroupConfig(Repository $config): array { - $config = config('queue-monitor.ui.route'); + $routeConfig = $config->array('queue-monitor.ui.route'); - if ( ! isset($config['middleware'])) { - $config['middleware'] = []; + if ( ! isset($routeConfig['middleware'])) { + $routeConfig['middleware'] = []; } - $config['middleware'][] = CheckQueueMonitorUiConfig::class; + $routeConfig['middleware'][] = CheckQueueMonitorUiConfig::class; - return $config; + return $routeConfig; } public function register(): void { - /** @phpstan-ignore-next-line */ - if ( ! $this->app->configurationIsCached()) { - $this->mergeConfigFrom( - __DIR__ . '/../../config/queue-monitor.php', - 'queue-monitor' - ); - } + /** @var \Illuminate\Config\Repository $config */ + $config = $this->app['config']; + + $this->mergeConfigFrom( + __DIR__ . '/../../config/queue-monitor.php', + 'queue-monitor' + ); - QueueMonitor::$model = config('queue-monitor.model') ?: Monitor::class; + QueueMonitor::$model = $config->get('queue-monitor.model') ?: Monitor::class; } } diff --git a/tests/MonitorRetryTest.php b/tests/MonitorRetryTest.php index da81fc7..28f568a 100644 --- a/tests/MonitorRetryTest.php +++ b/tests/MonitorRetryTest.php @@ -4,6 +4,7 @@ use Illuminate\Database\Eloquent\ModelNotFoundException; use romanzipp\QueueMonitor\Models\Monitor; +use romanzipp\QueueMonitor\Providers\QueueMonitorProvider; use romanzipp\QueueMonitor\Tests\Support\MonitoredFailingJob; use romanzipp\QueueMonitor\Tests\Support\MonitoredJob; use romanzipp\QueueMonitor\Tests\TestCases\DatabaseTestCase; @@ -20,6 +21,13 @@ public function setUp(): void ]); } + protected function defineRoutes($router) + { + $router->group(QueueMonitorProvider::buildRouteGroupConfig(config()), function () use (&$router) { + require __DIR__ . '/../routes/queue-monitor.php'; + }); + } + protected function tearDown(): void { MonitoredFailingJob::$count = 0; @@ -31,11 +39,6 @@ protected function tearDown(): void public function testRetryFailedMonitor(): void { - config([ - 'queue-monitor.ui.enabled' => true, - 'queue-monitor.ui.allow_retry' => true, - ]); - $this ->dispatch(new MonitoredFailingJob()) ->assertDispatched(MonitoredFailingJob::class) diff --git a/tests/RoutesTest.php b/tests/RoutesTest.php index f881f3a..889cfe4 100644 --- a/tests/RoutesTest.php +++ b/tests/RoutesTest.php @@ -4,6 +4,7 @@ use romanzipp\QueueMonitor\Enums\MonitorStatus; use romanzipp\QueueMonitor\Models\Monitor; +use romanzipp\QueueMonitor\Providers\QueueMonitorProvider; use romanzipp\QueueMonitor\Tests\TestCases\DatabaseTestCase; class RoutesTest extends DatabaseTestCase @@ -15,6 +16,13 @@ public function setUp(): void $this->withExceptionHandling(); } + protected function defineRoutes($router) + { + $router->group(QueueMonitorProvider::buildRouteGroupConfig(config()), function () use (&$router) { + require __DIR__ . '/../routes/queue-monitor.php'; + }); + } + /* *-------------------------------------------------------------------------- * Index From af3b4e78e4085eb3a53911edc311b0cfee8b51aa Mon Sep 17 00:00:00 2001 From: Roman Zipp Date: Sun, 23 Feb 2025 09:28:41 +0100 Subject: [PATCH 2/5] Increase php min --- .github/workflows/tests-postgres.yml | 2 +- .github/workflows/tests-sqlite.yml | 2 +- .github/workflows/tests.yml | 2 +- composer.json | 10 +++++----- src/Traits/IsMonitored.php | 4 ++-- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/.github/workflows/tests-postgres.yml b/.github/workflows/tests-postgres.yml index b4d2caf..31ae050 100644 --- a/.github/workflows/tests-postgres.yml +++ b/.github/workflows/tests-postgres.yml @@ -7,7 +7,7 @@ jobs: strategy: fail-fast: false matrix: - php: [ "8.0", "8.1", "8.2", "8.3", "8.4" ] + php: [ "8.3", "8.4" ] name: "PHP ${{ matrix.php }}" runs-on: ubuntu-latest diff --git a/.github/workflows/tests-sqlite.yml b/.github/workflows/tests-sqlite.yml index 822ab74..35c2bcf 100644 --- a/.github/workflows/tests-sqlite.yml +++ b/.github/workflows/tests-sqlite.yml @@ -7,7 +7,7 @@ jobs: strategy: fail-fast: false matrix: - php: [ "8.0", "8.1", "8.2", "8.3", "8.4" ] + php: [ "8.3", "8.4" ] name: "PHP ${{ matrix.php }}" runs-on: ubuntu-latest diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 6ce154a..97d4baf 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -7,7 +7,7 @@ jobs: strategy: fail-fast: false matrix: - php: [ "8.0", "8.1", "8.2", "8.3", "8.4" ] + php: [ "8.3", "8.4" ] name: "PHP ${{ matrix.php }}" runs-on: ubuntu-latest diff --git a/composer.json b/composer.json index 6f4f246..0483cd7 100644 --- a/composer.json +++ b/composer.json @@ -11,18 +11,18 @@ } ], "require": { - "php": "^8.0", + "php": "^8.3", "ext-json": "*", "ext-mbstring": "*", - "illuminate/database": ">=5.5", - "illuminate/queue": ">=5.5", - "illuminate/support": ">=5.5", + "illuminate/database": ">=11.0", + "illuminate/queue": ">=11.0", + "illuminate/support": ">=11.0", "nesbot/carbon": "^2.0|^3.0" }, "require-dev": { "doctrine/dbal": "^3.1|^4.2", "friendsofphp/php-cs-fixer": "^3.0", - "laravel/framework": ">=5.5", + "laravel/framework": ">=11.0", "mockery/mockery": "^1.3.2", "orchestra/testbench": ">=3.8", "phpstan/phpstan": "^0.12.99|^1.0|^2.1", diff --git a/src/Traits/IsMonitored.php b/src/Traits/IsMonitored.php index 4134f16..2255f09 100644 --- a/src/Traits/IsMonitored.php +++ b/src/Traits/IsMonitored.php @@ -15,14 +15,14 @@ trait IsMonitored * * @var int|null */ - private $progressLastUpdated; + private ?int $progressLastUpdated; /** * Internal variable used for tracking chunking progress. * * @var int */ - private $progressCurrentChunk = 0; + private ?int $progressCurrentChunk = 0; /** * Update progress. From 7aba92e02b20790722acba94aae171f509569165 Mon Sep 17 00:00:00 2001 From: Roman Zipp Date: Sun, 23 Feb 2025 09:31:16 +0100 Subject: [PATCH 3/5] Improve tests --- tests/MonitorRetryTest.php | 13 +++---------- tests/RoutesTest.php | 8 +++----- 2 files changed, 6 insertions(+), 15 deletions(-) diff --git a/tests/MonitorRetryTest.php b/tests/MonitorRetryTest.php index 28f568a..c30329b 100644 --- a/tests/MonitorRetryTest.php +++ b/tests/MonitorRetryTest.php @@ -4,7 +4,6 @@ use Illuminate\Database\Eloquent\ModelNotFoundException; use romanzipp\QueueMonitor\Models\Monitor; -use romanzipp\QueueMonitor\Providers\QueueMonitorProvider; use romanzipp\QueueMonitor\Tests\Support\MonitoredFailingJob; use romanzipp\QueueMonitor\Tests\Support\MonitoredJob; use romanzipp\QueueMonitor\Tests\TestCases\DatabaseTestCase; @@ -14,18 +13,12 @@ class MonitorRetryTest extends DatabaseTestCase public function setUp(): void { parent::setUp(); - - config([ - 'queue-monitor.ui.enabled' => true, - 'queue-monitor.ui.allow_retry' => true, - ]); } - protected function defineRoutes($router) + protected function defineEnvironment($app): void { - $router->group(QueueMonitorProvider::buildRouteGroupConfig(config()), function () use (&$router) { - require __DIR__ . '/../routes/queue-monitor.php'; - }); + $app['config']->set('queue-monitor.ui.enabled', true); + $app['config']->set('queue-monitor.ui.allow_retry', true); } protected function tearDown(): void diff --git a/tests/RoutesTest.php b/tests/RoutesTest.php index 889cfe4..fb966e1 100644 --- a/tests/RoutesTest.php +++ b/tests/RoutesTest.php @@ -4,7 +4,6 @@ use romanzipp\QueueMonitor\Enums\MonitorStatus; use romanzipp\QueueMonitor\Models\Monitor; -use romanzipp\QueueMonitor\Providers\QueueMonitorProvider; use romanzipp\QueueMonitor\Tests\TestCases\DatabaseTestCase; class RoutesTest extends DatabaseTestCase @@ -16,11 +15,10 @@ public function setUp(): void $this->withExceptionHandling(); } - protected function defineRoutes($router) + protected function defineEnvironment($app): void { - $router->group(QueueMonitorProvider::buildRouteGroupConfig(config()), function () use (&$router) { - require __DIR__ . '/../routes/queue-monitor.php'; - }); + $app['config']->set('queue-monitor.ui.enabled', true); + $app['config']->set('queue-monitor.ui.allow_retry', true); } /* From 08f38b160f29532a644a2f5eabcaa3b7d23a138c Mon Sep 17 00:00:00 2001 From: Roman Zipp Date: Wed, 19 Mar 2025 06:17:52 +0100 Subject: [PATCH 4/5] wip --- README.md | 4 +- src/Providers/QueueMonitorProvider.php | 20 +++++++++ src/Services/QueueMonitor.php | 57 ++++---------------------- src/Traits/IsMonitored.php | 2 +- 4 files changed, 33 insertions(+), 50 deletions(-) diff --git a/README.md b/README.md index 5f189de..d9e60da 100644 --- a/README.md +++ b/README.md @@ -56,9 +56,11 @@ use Illuminate\Queue\SerializesModels; use Illuminate\Queue\InteractsWithQueue; use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Foundation\Bus\Dispatchable; + use romanzipp\QueueMonitor\Traits\IsMonitored; // <--- +use romanzipp\QueueMonitor\Contracts\MonitoredJobContract; // <--- -class ExampleJob implements ShouldQueue +class ExampleJob implements ShouldQueue, MonitoredJobContract { use Dispatchable; use InteractsWithQueue; diff --git a/src/Providers/QueueMonitorProvider.php b/src/Providers/QueueMonitorProvider.php index 5ad5a43..4145de3 100644 --- a/src/Providers/QueueMonitorProvider.php +++ b/src/Providers/QueueMonitorProvider.php @@ -95,6 +95,26 @@ public function boot(): void $queueManager->exceptionOccurred(static function (QueueEvents\JobExceptionOccurred $event) { QueueMonitor::handleJobExceptionOccurred($event); }); + + + $this->app['events']->listen([ + QueueEvents\JobExceptionOccurred::class, + QueueEvents\JobFailed::class, + QueueEvents\JobPopped::class, + QueueEvents\JobPopping::class, + QueueEvents\JobProcessed::class, + QueueEvents\JobProcessing::class, + QueueEvents\JobQueued::class, + QueueEvents\JobQueueing::class, + QueueEvents\JobReleasedAfterException::class, + QueueEvents\JobRetryRequested::class, + QueueEvents\JobTimedOut::class, + QueueEvents\Looping::class, + QueueEvents\QueueBusy::class, + QueueEvents\WorkerStopping::class, + ], function ($event) { + #dump(get_class($event)); + }); } /** diff --git a/src/Services/QueueMonitor.php b/src/Services/QueueMonitor.php index 28c6676..3983339 100644 --- a/src/Services/QueueMonitor.php +++ b/src/Services/QueueMonitor.php @@ -5,11 +5,7 @@ use Illuminate\Container\Container; use Illuminate\Contracts\Encryption\Encrypter; use Illuminate\Contracts\Queue\Job as JobContract; -use Illuminate\Queue\Events\JobExceptionOccurred; -use Illuminate\Queue\Events\JobFailed; -use Illuminate\Queue\Events\JobProcessed; -use Illuminate\Queue\Events\JobProcessing; -use Illuminate\Queue\Events\JobQueued; +use Illuminate\Queue\Events as QueueEvents; use Illuminate\Support\Carbon; use romanzipp\QueueMonitor\Enums\MonitorStatus; use romanzipp\QueueMonitor\Models\Contracts\MonitorContract; @@ -17,7 +13,7 @@ class QueueMonitor { - private const TIMESTAMP_EXACT_FORMAT = 'Y-m-d H:i:s.u'; + private const string TIMESTAMP_EXACT_FORMAT = 'Y-m-d H:i:s.u'; public static string $model; @@ -31,14 +27,7 @@ public static function getModel(): MonitorContract return new self::$model(); } - /** - * Handle Job Queued. - * - * @param JobQueued $event - * - * @return void - */ - public static function handleJobQueued(JobQueued $event): void + public static function handleJobQueued(QueueEvents\JobQueued $event): void { self::jobQueued($event); } @@ -53,50 +42,22 @@ public static function handleJobPushed($event): void self::jobPushed($event); } - /** - * Handle Job Processing. - * - * @param JobProcessing $event - * - * @return void - */ - public static function handleJobProcessing(JobProcessing $event): void + public static function handleJobProcessing(QueueEvents\JobProcessing $event): void { self::jobStarted($event->job); } - /** - * Handle Job Processed. - * - * @param JobProcessed $event - * - * @return void - */ - public static function handleJobProcessed(JobProcessed $event): void + public static function handleJobProcessed(QueueEvents\JobProcessed $event): void { self::jobFinished($event->job, MonitorStatus::SUCCEEDED); } - /** - * Handle Job Failing. - * - * @param JobFailed $event - * - * @return void - */ - public static function handleJobFailed(JobFailed $event): void + public static function handleJobFailed(QueueEvents\JobFailed $event): void { self::jobFinished($event->job, MonitorStatus::FAILED, $event->exception); } - /** - * Handle Job Exception Occurred. - * - * @param JobExceptionOccurred $event - * - * @return void - */ - public static function handleJobExceptionOccurred(JobExceptionOccurred $event): void + public static function handleJobExceptionOccurred(QueueEvents\JobExceptionOccurred $event): void { self::jobFinished($event->job, MonitorStatus::FAILED, $event->exception); } @@ -120,11 +81,11 @@ public static function getJobId(JobContract $job): string /** * Start Queue Monitoring for Job. * - * @param JobQueued $event + * @param QueueEvents\JobQueued $event * * @return void */ - protected static function jobQueued(JobQueued $event): void + protected static function jobQueued(QueueEvents\JobQueued $event): void { if ( ! self::shouldBeMonitored($event->job)) { return; diff --git a/src/Traits/IsMonitored.php b/src/Traits/IsMonitored.php index 2255f09..a9d55b0 100644 --- a/src/Traits/IsMonitored.php +++ b/src/Traits/IsMonitored.php @@ -22,7 +22,7 @@ trait IsMonitored * * @var int */ - private ?int $progressCurrentChunk = 0; + private int $progressCurrentChunk = 0; /** * Update progress. From de5dabb1c325190c33af516eb3fb51029f11011d Mon Sep 17 00:00:00 2001 From: romanzipp Date: Wed, 19 Mar 2025 05:40:12 +0000 Subject: [PATCH 5/5] Fix styling --- src/Providers/QueueMonitorProvider.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Providers/QueueMonitorProvider.php b/src/Providers/QueueMonitorProvider.php index 4145de3..e1fe730 100644 --- a/src/Providers/QueueMonitorProvider.php +++ b/src/Providers/QueueMonitorProvider.php @@ -96,7 +96,6 @@ public function boot(): void QueueMonitor::handleJobExceptionOccurred($event); }); - $this->app['events']->listen([ QueueEvents\JobExceptionOccurred::class, QueueEvents\JobFailed::class, @@ -113,7 +112,7 @@ public function boot(): void QueueEvents\QueueBusy::class, QueueEvents\WorkerStopping::class, ], function ($event) { - #dump(get_class($event)); + // dump(get_class($event)); }); }