From 6ecff0f989f6615d9203c189fa2a7289c8942d37 Mon Sep 17 00:00:00 2001 From: Bram Ceulemans Date: Wed, 27 Aug 2025 19:06:52 +0100 Subject: [PATCH 1/6] Add defer method to PendingDispatch --- .../Foundation/Bus/PendingDispatch.php | 21 +++++++++++++++++++ tests/Bus/BusPendingDispatchTest.php | 8 +++++++ 2 files changed, 29 insertions(+) diff --git a/src/Illuminate/Foundation/Bus/PendingDispatch.php b/src/Illuminate/Foundation/Bus/PendingDispatch.php index 443eb5eddf5a..17ac395a2e09 100644 --- a/src/Illuminate/Foundation/Bus/PendingDispatch.php +++ b/src/Illuminate/Foundation/Bus/PendingDispatch.php @@ -27,6 +27,13 @@ class PendingDispatch */ protected $afterResponse = false; + /** + * Indicates if the job should be dispatched to the queue after the current request. + * + * @var bool + */ + protected $defer = true; + /** * Create a new pending job dispatch. * @@ -163,6 +170,18 @@ public function afterResponse() return $this; } + /** + * Indicate that the job should be dispatched to the queue after the current request. + * + * @return $this + */ + public function defer(): static + { + $this->defer = true; + + return $this; + } + /** * Determine if the job should be dispatched. * @@ -217,6 +236,8 @@ public function __destruct() return; } elseif ($this->afterResponse) { app(Dispatcher::class)->dispatchAfterResponse($this->job); + } elseif ($this->defer) { + defer(fn () => app(Dispatcher::class)->dispatch($this->job)); } else { app(Dispatcher::class)->dispatch($this->job); } diff --git a/tests/Bus/BusPendingDispatchTest.php b/tests/Bus/BusPendingDispatchTest.php index 99c4065cb5c5..7f6b8c665543 100644 --- a/tests/Bus/BusPendingDispatchTest.php +++ b/tests/Bus/BusPendingDispatchTest.php @@ -103,6 +103,14 @@ public function testAfterResponse() ); } + public function testDefer() + { + $this->pendingDispatch->defer(); + $this->assertTrue( + (new ReflectionClass($this->pendingDispatch))->getProperty('defer')->getValue($this->pendingDispatch) + ); + } + public function testGetJob() { $this->assertSame($this->job, $this->pendingDispatch->getJob()); From 27dfc990f0fb87e8f3b085874bbcb9a2404121af Mon Sep 17 00:00:00 2001 From: Bram Ceulemans Date: Wed, 27 Aug 2025 19:18:56 +0100 Subject: [PATCH 2/6] Add test for dispatch of deferred jobs --- src/Illuminate/Foundation/Bus/Dispatchable.php | 8 ++++++++ src/Illuminate/Foundation/Bus/PendingDispatch.php | 4 ++-- tests/Integration/Queue/JobDispatchingTest.php | 12 ++++++++++++ 3 files changed, 22 insertions(+), 2 deletions(-) diff --git a/src/Illuminate/Foundation/Bus/Dispatchable.php b/src/Illuminate/Foundation/Bus/Dispatchable.php index 1fef9872f833..391d83fc993b 100644 --- a/src/Illuminate/Foundation/Bus/Dispatchable.php +++ b/src/Illuminate/Foundation/Bus/Dispatchable.php @@ -87,6 +87,14 @@ public static function dispatchAfterResponse(...$arguments) return self::dispatch(...$arguments)->afterResponse(); } + /** + * Defer dispatching a command to its appropriate handler. + */ + public static function dispatchDefer(...$arguments) + { + return self::dispatch(...$arguments)->defer(); + } + /** * Set the jobs that should run if this job is successful. * diff --git a/src/Illuminate/Foundation/Bus/PendingDispatch.php b/src/Illuminate/Foundation/Bus/PendingDispatch.php index 17ac395a2e09..99c2953e1f67 100644 --- a/src/Illuminate/Foundation/Bus/PendingDispatch.php +++ b/src/Illuminate/Foundation/Bus/PendingDispatch.php @@ -28,7 +28,7 @@ class PendingDispatch protected $afterResponse = false; /** - * Indicates if the job should be dispatched to the queue after the current request. + * Indicates if the job dispatch should be deferred. * * @var bool */ @@ -171,7 +171,7 @@ public function afterResponse() } /** - * Indicate that the job should be dispatched to the queue after the current request. + * Indicate that the job dispatch should be deferred. * * @return $this */ diff --git a/tests/Integration/Queue/JobDispatchingTest.php b/tests/Integration/Queue/JobDispatchingTest.php index 441cb59dea97..e94e4f6b5044 100644 --- a/tests/Integration/Queue/JobDispatchingTest.php +++ b/tests/Integration/Queue/JobDispatchingTest.php @@ -10,6 +10,7 @@ use Illuminate\Queue\Events\JobQueued; use Illuminate\Queue\Events\JobQueueing; use Illuminate\Queue\InteractsWithQueue; +use Illuminate\Support\Defer\DeferredCallbackCollection; use Illuminate\Support\Facades\Bus; use Illuminate\Support\Facades\Config; use Orchestra\Testbench\Attributes\WithMigration; @@ -139,6 +140,17 @@ public function testUniqueJobLockIsReleasedForJobDispatchedAfterResponse() $this->assertFalse(UniqueJob::$ran); } + public function testDispatchDeferDelaysDispatchingUntilDeferredCallbacksAreRun() + { + $this->assertFalse(Job::$ran); + + Job::dispatchDefer('test'); + + $this->assertFalse(Job::$ran); + $this->app[DeferredCallbackCollection::class]->invoke(); + $this->assertTrue(Job::$ran); + } + public function testQueueMayBeNullForJobQueueingAndJobQueuedEvent() { Config::set('queue.default', 'database'); From d2316dc98905c5fedcb9acfb4169858507236886 Mon Sep 17 00:00:00 2001 From: Bram Ceulemans Date: Wed, 27 Aug 2025 19:19:56 +0100 Subject: [PATCH 3/6] Set defer to false by default --- src/Illuminate/Foundation/Bus/PendingDispatch.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Illuminate/Foundation/Bus/PendingDispatch.php b/src/Illuminate/Foundation/Bus/PendingDispatch.php index 99c2953e1f67..4ca29686843f 100644 --- a/src/Illuminate/Foundation/Bus/PendingDispatch.php +++ b/src/Illuminate/Foundation/Bus/PendingDispatch.php @@ -32,7 +32,7 @@ class PendingDispatch * * @var bool */ - protected $defer = true; + protected $defer = false; /** * Create a new pending job dispatch. From c7218d0837280c064cb8ddb4c6e7fd34a560442c Mon Sep 17 00:00:00 2001 From: Bram Ceulemans Date: Wed, 27 Aug 2025 19:31:43 +0100 Subject: [PATCH 4/6] Adjust test --- tests/Integration/Queue/JobDispatchingTest.php | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/tests/Integration/Queue/JobDispatchingTest.php b/tests/Integration/Queue/JobDispatchingTest.php index e94e4f6b5044..0e296fafd0c1 100644 --- a/tests/Integration/Queue/JobDispatchingTest.php +++ b/tests/Integration/Queue/JobDispatchingTest.php @@ -142,12 +142,14 @@ public function testUniqueJobLockIsReleasedForJobDispatchedAfterResponse() public function testDispatchDeferDelaysDispatchingUntilDeferredCallbacksAreRun() { - $this->assertFalse(Job::$ran); - Job::dispatchDefer('test'); $this->assertFalse(Job::$ran); - $this->app[DeferredCallbackCollection::class]->invoke(); + $this->runQueueWorkerCommand(['--stop-when-empty' => true]); + $this->assertFalse(Job::$ran); + + $this->app->get(DeferredCallbackCollection::class)->invoke(); + $this->runQueueWorkerCommand(['--stop-when-empty' => true]); $this->assertTrue(Job::$ran); } From df6349a2cfbcf9b4f38bab32d80530ab97ce358c Mon Sep 17 00:00:00 2001 From: Bram Ceulemans Date: Wed, 27 Aug 2025 19:34:07 +0100 Subject: [PATCH 5/6] Empty commit to trigger CI again From 37f036b05ddfbb8086e1264b24dd17cfc4b946fb Mon Sep 17 00:00:00 2001 From: Bram Ceulemans Date: Wed, 27 Aug 2025 19:46:13 +0100 Subject: [PATCH 6/6] WIP --- tests/Integration/Queue/JobDispatchingTest.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/Integration/Queue/JobDispatchingTest.php b/tests/Integration/Queue/JobDispatchingTest.php index 0e296fafd0c1..e1dcb04c3a43 100644 --- a/tests/Integration/Queue/JobDispatchingTest.php +++ b/tests/Integration/Queue/JobDispatchingTest.php @@ -144,12 +144,14 @@ public function testDispatchDeferDelaysDispatchingUntilDeferredCallbacksAreRun() { Job::dispatchDefer('test'); + $this->assertSame(1, $this->app[DeferredCallbackCollection::class]->count()); $this->assertFalse(Job::$ran); + $this->runQueueWorkerCommand(['--stop-when-empty' => true]); $this->assertFalse(Job::$ran); - $this->app->get(DeferredCallbackCollection::class)->invoke(); - $this->runQueueWorkerCommand(['--stop-when-empty' => true]); + $this->app[DeferredCallbackCollection::class]->invoke(); + $this->runQueueWorkerCommand(['--once' => true]); $this->assertTrue(Job::$ran); }