diff --git a/app/Jobs/RevalidateUnusableS3StoragesJob.php b/app/Jobs/RevalidateUnusableS3StoragesJob.php index 2240b457fb..b02d440dea 100644 --- a/app/Jobs/RevalidateUnusableS3StoragesJob.php +++ b/app/Jobs/RevalidateUnusableS3StoragesJob.php @@ -26,6 +26,11 @@ class RevalidateUnusableS3StoragesJob implements ShouldBeEncrypted, ShouldBeUniq public $timeout = 1800; + /** + * Releases the unique lock of a killed worker after one run, instead of after the queue retry_after. + */ + public int $uniqueFor = 1800; + /** * Stay well below $timeout, because a single unreachable endpoint can take a while to fail. */ diff --git a/tests/Feature/RevalidateUnusableS3StoragesJobUniqueLockTest.php b/tests/Feature/RevalidateUnusableS3StoragesJobUniqueLockTest.php new file mode 100644 index 0000000000..da93f0c0b6 --- /dev/null +++ b/tests/Feature/RevalidateUnusableS3StoragesJobUniqueLockTest.php @@ -0,0 +1,25 @@ +set('cache.default', 'array'); + Queue::fake(); +}); + +it('does not queue a second revalidation while the unique lock is held', function () { + RevalidateUnusableS3StoragesJob::dispatch(); + $this->travel(29)->minutes(); + RevalidateUnusableS3StoragesJob::dispatch(); + + Queue::assertPushed(RevalidateUnusableS3StoragesJob::class, 1); +}); + +it('queues the revalidation again after a lock left by a killed worker expires', function () { + RevalidateUnusableS3StoragesJob::dispatch(); + $this->travel(31)->minutes(); + RevalidateUnusableS3StoragesJob::dispatch(); + + Queue::assertPushed(RevalidateUnusableS3StoragesJob::class, 2); +});