From b124397613f52b2e9a2f23de7ccb6e5d2c9a7fdb Mon Sep 17 00:00:00 2001 From: Andras Bacsai <5845193+andrasbacsai@users.noreply.github.com> Date: Thu, 21 May 2026 19:19:43 +0200 Subject: [PATCH] fix(schedule): prevent duplicate SSL certificate regeneration Run RegenerateSslCertJob on one server only and add coverage to ensure scheduled production jobs use onOneServer. --- app/Console/Kernel.php | 2 +- tests/Feature/ScheduleOnOneServerTest.php | 38 +++++++++++++++++++++++ 2 files changed, 39 insertions(+), 1 deletion(-) create mode 100644 tests/Feature/ScheduleOnOneServerTest.php diff --git a/app/Console/Kernel.php b/app/Console/Kernel.php index 75ec31ae0..3ec59adb3 100644 --- a/app/Console/Kernel.php +++ b/app/Console/Kernel.php @@ -78,7 +78,7 @@ protected function schedule(Schedule $schedule): void // Scheduled Jobs (Backups & Tasks) $this->scheduleInstance->job(new ScheduledJobManager)->everyMinute()->onOneServer(); - $this->scheduleInstance->job(new RegenerateSslCertJob)->twiceDaily(); + $this->scheduleInstance->job(new RegenerateSslCertJob)->twiceDaily()->onOneServer(); $this->scheduleInstance->job(new CheckTraefikVersionJob)->weekly()->sundays()->at('00:00')->timezone($this->instanceTimezone)->onOneServer(); diff --git a/tests/Feature/ScheduleOnOneServerTest.php b/tests/Feature/ScheduleOnOneServerTest.php new file mode 100644 index 000000000..10758738c --- /dev/null +++ b/tests/Feature/ScheduleOnOneServerTest.php @@ -0,0 +1,38 @@ + InstanceSettings::query()->firstOrCreate(['id' => 0])); +}); + +it('schedules RegenerateSslCertJob with onOneServer to prevent multi-server double dispatch', function () { + $schedule = app(Schedule::class); + + $event = collect($schedule->events())->first( + fn ($e) => str_contains((string) $e->description, 'RegenerateSslCertJob') + ); + + expect($event)->not->toBeNull(); + expect($event->onOneServer)->toBeTrue(); +}); + +it('schedules every production job with onOneServer', function () { + $schedule = app(Schedule::class); + + $jobEvents = collect($schedule->events())->filter( + fn ($e) => str_contains((string) $e->description, 'App\\Jobs\\') + ); + + expect($jobEvents)->not->toBeEmpty(); + + $jobEvents->each(function ($event) { + expect($event->onOneServer)->toBeTrue( + "Scheduled job [{$event->description}] is missing ->onOneServer()" + ); + }); +});