From 765e1ea04ba7ad61f09b78f669de6decf2be56a5 Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Fri, 10 Jan 2025 15:39:22 +0100 Subject: [PATCH] feat: add horizon server details to queue --- app/Console/Commands/HorizonManage.php | 16 ++++++++-- app/Jobs/ApplicationDeploymentJob.php | 5 +++- .../Project/Application/DeploymentNavbar.php | 1 + app/Providers/HorizonServiceProvider.php | 21 ++++++++++++- app/Repositories/CustomJobRepository.php | 10 +++++++ ...35244_add_horizon_job_details_to_queue.php | 30 +++++++++++++++++++ 6 files changed, 79 insertions(+), 4 deletions(-) create mode 100644 database/migrations/2025_01_10_135244_add_horizon_job_details_to_queue.php diff --git a/app/Console/Commands/HorizonManage.php b/app/Console/Commands/HorizonManage.php index 611b516b0..a03c41a7b 100644 --- a/app/Console/Commands/HorizonManage.php +++ b/app/Console/Commands/HorizonManage.php @@ -7,6 +7,7 @@ use Illuminate\Console\Command; use Illuminate\Support\Facades\Artisan; use Laravel\Horizon\Contracts\JobRepository; use Laravel\Horizon\Contracts\MetricsRepository; +use Laravel\Horizon\Repositories\RedisJobRepository; use function Laravel\Prompts\multiselect; use function Laravel\Prompts\select; @@ -14,7 +15,7 @@ use function Laravel\Prompts\table; class HorizonManage extends Command { - protected $signature = 'horizon:manage '; + protected $signature = 'horizon:manage'; protected $description = 'Manage horizon'; @@ -28,6 +29,7 @@ class HorizonManage extends Command 'workers' => 'Workers', 'failed' => 'Failed Jobs', 'failed-delete' => 'Failed Jobs - Delete', + 'purge-queues' => 'Purge Queues', ] ); @@ -102,11 +104,11 @@ class HorizonManage extends Command return; } - dump($runningJobs); foreach ($runningJobs as $runningJob) { $runningJobsTable[] = [ 'id' => $runningJob->id, 'name' => $runningJob->name, + 'reserved_at' => $runningJob->reserved_at ? now()->parse($runningJob->reserved_at)->format('Y-m-d H:i:s') : null, ]; } table($runningJobsTable); @@ -123,5 +125,15 @@ class HorizonManage extends Command } table($workersTable); } + + if ($action === 'purge-queues') { + $getQueues = app(CustomJobRepository::class)->getQueues(); + $queueName = select( + label: 'Which queue to purge?', + options: $getQueues, + ); + $redisJobRepository = app(RedisJobRepository::class); + $redisJobRepository->purge($queueName); + } } } diff --git a/app/Jobs/ApplicationDeploymentJob.php b/app/Jobs/ApplicationDeploymentJob.php index bd9149040..1b92f817b 100644 --- a/app/Jobs/ApplicationDeploymentJob.php +++ b/app/Jobs/ApplicationDeploymentJob.php @@ -237,6 +237,7 @@ class ApplicationDeploymentJob implements ShouldBeEncrypted, ShouldQueue { $this->application_deployment_queue->update([ 'status' => ApplicationDeploymentStatus::IN_PROGRESS->value, + 'horizon_job_worker' => gethostname(), ]); if ($this->server->isFunctional() === false) { $this->application_deployment_queue->addLogEntry('Server is not functional.'); @@ -2389,10 +2390,12 @@ COPY ./nginx.conf /etc/nginx/conf.d/default.conf"); queue_next_deployment($this->application); // If the deployment is cancelled by the user, don't update the status if ( - $this->application_deployment_queue->status !== ApplicationDeploymentStatus::CANCELLED_BY_USER->value && $this->application_deployment_queue->status !== ApplicationDeploymentStatus::FAILED->value + $this->application_deployment_queue->status !== ApplicationDeploymentStatus::CANCELLED_BY_USER->value && + $this->application_deployment_queue->status !== ApplicationDeploymentStatus::FAILED->value ) { $this->application_deployment_queue->update([ 'status' => $status, + 'horizon_job_status' => $status, ]); } if ($this->application_deployment_queue->status === ApplicationDeploymentStatus::FAILED->value) { diff --git a/app/Livewire/Project/Application/DeploymentNavbar.php b/app/Livewire/Project/Application/DeploymentNavbar.php index 6a6fa2482..8210a12a1 100644 --- a/app/Livewire/Project/Application/DeploymentNavbar.php +++ b/app/Livewire/Project/Application/DeploymentNavbar.php @@ -84,6 +84,7 @@ class DeploymentNavbar extends Component $this->application_deployment_queue->update([ 'current_process_id' => null, 'status' => ApplicationDeploymentStatus::CANCELLED_BY_USER->value, + 'horizon_job_status' => ApplicationDeploymentStatus::CANCELLED_BY_USER->value, ]); next_after_cancel($server); } diff --git a/app/Providers/HorizonServiceProvider.php b/app/Providers/HorizonServiceProvider.php index a3ca3fc98..e89528d4c 100644 --- a/app/Providers/HorizonServiceProvider.php +++ b/app/Providers/HorizonServiceProvider.php @@ -3,9 +3,12 @@ namespace App\Providers; use App\Contracts\CustomJobRepositoryInterface; +use App\Models\ApplicationDeploymentQueue; use App\Repositories\CustomJobRepository; +use Illuminate\Support\Facades\Event; use Illuminate\Support\ServiceProvider; use Laravel\Horizon\Contracts\JobRepository; +use Laravel\Horizon\Events\JobReserved; class HorizonServiceProvider extends ServiceProvider { @@ -23,6 +26,22 @@ class HorizonServiceProvider extends ServiceProvider */ public function boot(): void { - // + // Event::listen(function (JobReserved $event) { + // $payload = $event->payload->decoded; + // $jobName = $payload['displayName']; + // if ($jobName === 'App\Jobs\ApplicationDeploymentJob') { + // $tags = $payload['tags']; + + // $deploymentQueueId = collect($tags)->first(function ($tag) { + // return str_contains($tag, 'App\Models\ApplicationDeploymentQueue'); + // }); + // $deploymentQueueId = explode(':', $deploymentQueueId)[1]; + // $deploymentQueue = ApplicationDeploymentQueue::find($deploymentQueueId); + // $deploymentQueue->update([ + // 'horizon_job_status' => 'reserved', + // ]); + // } + // }); + } } diff --git a/app/Repositories/CustomJobRepository.php b/app/Repositories/CustomJobRepository.php index ef492e3ba..3d67cdd1a 100644 --- a/app/Repositories/CustomJobRepository.php +++ b/app/Repositories/CustomJobRepository.php @@ -68,4 +68,14 @@ class CustomJobRepository extends RedisJobRepository implements CustomJobReposit return $jobs; } + + public function getQueues(): array + { + $queues = $this->connection()->keys('queue:*'); + $queues = array_map(function ($queue) { + return explode(':', $queue)[2]; + }, $queues); + + return $queues; + } } diff --git a/database/migrations/2025_01_10_135244_add_horizon_job_details_to_queue.php b/database/migrations/2025_01_10_135244_add_horizon_job_details_to_queue.php new file mode 100644 index 000000000..e6d4693a7 --- /dev/null +++ b/database/migrations/2025_01_10_135244_add_horizon_job_details_to_queue.php @@ -0,0 +1,30 @@ +string('horizon_job_status')->nullable(); + $table->string('horizon_job_worker')->nullable(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('application_deployment_queues', function (Blueprint $table) { + $table->dropColumn('horizon_job_status'); + $table->dropColumn('horizon_job_worker'); + }); + } +};