Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions src/Illuminate/Foundation/Bus/Dispatchable.php
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*
Expand Down
21 changes: 21 additions & 0 deletions src/Illuminate/Foundation/Bus/PendingDispatch.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,13 @@ class PendingDispatch
*/
protected $afterResponse = false;

/**
* Indicates if the job dispatch should be deferred.
*
* @var bool
*/
protected $defer = false;

/**
* Create a new pending job dispatch.
*
Expand Down Expand Up @@ -163,6 +170,18 @@ public function afterResponse()
return $this;
}

/**
* Indicate that the job dispatch should be deferred.
*
* @return $this
*/
public function defer(): static
{
$this->defer = true;

return $this;
}

/**
* Determine if the job should be dispatched.
*
Expand Down Expand Up @@ -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);
}
Expand Down
8 changes: 8 additions & 0 deletions tests/Bus/BusPendingDispatchTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -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());
Expand Down
16 changes: 16 additions & 0 deletions tests/Integration/Queue/JobDispatchingTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -139,6 +140,21 @@ public function testUniqueJobLockIsReleasedForJobDispatchedAfterResponse()
$this->assertFalse(UniqueJob::$ran);
}

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[DeferredCallbackCollection::class]->invoke();
$this->runQueueWorkerCommand(['--once' => true]);
$this->assertTrue(Job::$ran);
}

public function testQueueMayBeNullForJobQueueingAndJobQueuedEvent()
{
Config::set('queue.default', 'database');
Expand Down
Loading