diff --git a/src/Illuminate/Console/Scheduling/Schedule.php b/src/Illuminate/Console/Scheduling/Schedule.php index 01c2d17f9428..d787967b71e7 100644 --- a/src/Illuminate/Console/Scheduling/Schedule.php +++ b/src/Illuminate/Console/Scheduling/Schedule.php @@ -2,12 +2,17 @@ namespace Illuminate\Console\Scheduling; +use Closure; use DateTimeInterface; use Illuminate\Console\Application; use Illuminate\Container\Container; +use Illuminate\Contracts\Bus\Dispatcher; +use Illuminate\Contracts\Container\BindingResolutionException; use Illuminate\Contracts\Queue\ShouldQueue; +use Illuminate\Queue\CallQueuedClosure; use Illuminate\Support\ProcessUtils; use Illuminate\Support\Traits\Macroable; +use RuntimeException; class Schedule { @@ -34,6 +39,13 @@ class Schedule */ protected $schedulingMutex; + /** + * The job dispatcher implementation. + * + * @var \Illuminate\Contracts\Bus\Dispatcher + */ + protected $dispatcher; + /** * The timezone the date should be evaluated on. * @@ -51,6 +63,12 @@ public function __construct($timezone = null) { $this->timezone = $timezone; + if (! class_exists(Container::class)) { + throw new RuntimeException( + 'The container implementation is required to use the scheduler. Please install illuminate/container.' + ); + } + $container = Container::getInstance(); $this->eventMutex = $container->bound(EventMutex::class) @@ -107,18 +125,52 @@ public function command($command, array $parameters = []) public function job($job, $queue = null, $connection = null) { return $this->call(function () use ($job, $queue, $connection) { - $job = is_string($job) ? resolve($job) : $job; + $job = is_string($job) ? Container::getInstance()->make($job) : $job; if ($job instanceof ShouldQueue) { - dispatch($job) - ->onConnection($connection ?? $job->connection) - ->onQueue($queue ?? $job->queue); + $this->dispatchToQueue($job, $queue ?? $job->queue, $connection ?? $job->connection); } else { - dispatch_now($job); + $this->dispatchNow($job); } })->name(is_string($job) ? $job : get_class($job)); } + /** + * Dispatch the given job to the queue. + * + * @param object $job + * @param string|null $queue + * @param string|null $connection + * @return void + */ + protected function dispatchToQueue($job, $queue, $connection) + { + if ($job instanceof Closure) { + if (! class_exists(CallQueuedClosure::class)) { + throw new RuntimeException( + 'To enable support for closure jobs, please install illuminate/queue.' + ); + } + + $job = CallQueuedClosure::create($job); + } + + $this->getDispatcher()->dispatch( + $job->onConnection($connection)->onQueue($queue) + ); + } + + /** + * Dispatch the given job right now. + * + * @param object $job + * @return void + */ + protected function dispatchNow($job) + { + $this->getDispatcher()->dispatchNow($job); + } + /** * Add a new command event to the schedule. * @@ -209,4 +261,26 @@ public function useCache($store) return $this; } + + /** + * Get the job dispatcher, if available. + * + * @return \Illuminate\Contracts\Bus\Dispatcher + */ + protected function getDispatcher() + { + if ($this->dispatcher === null) { + try { + $this->dispatcher = Container::getInstance()->make(Dispatcher::class); + } catch (BindingResolutionException $e) { + throw new RuntimeException( + 'Unable to resolve the dispatcher from the service container. Please bind it or install illuminate/bus.', + $e->getCode(), + $e + ); + } + } + + return $this->dispatcher; + } } diff --git a/src/Illuminate/Console/composer.json b/src/Illuminate/Console/composer.json index f746b351fd7f..55f104571a7f 100755 --- a/src/Illuminate/Console/composer.json +++ b/src/Illuminate/Console/composer.json @@ -31,9 +31,12 @@ } }, "suggest": { - "dragonmantank/cron-expression": "Required to use scheduling component (^2.0).", + "dragonmantank/cron-expression": "Required to use scheduler (^2.0).", "guzzlehttp/guzzle": "Required to use the ping methods on schedules (^6.0|^7.0).", - "illuminate/filesystem": "Required to use the generator command (^6.0)" + "illuminate/bus": "Required to use the scheduled job dispatcher (^6.0)", + "illuminate/container": "Required to use the scheduler (^6.0)", + "illuminate/filesystem": "Required to use the generator command (^6.0)", + "illuminate/queue": "Required to use closures for scheduled jobs (^6.0)" }, "config": { "sort-packages": true diff --git a/src/Illuminate/Foundation/helpers.php b/src/Illuminate/Foundation/helpers.php index 805377da3c0e..e1a901bc80de 100644 --- a/src/Illuminate/Foundation/helpers.php +++ b/src/Illuminate/Foundation/helpers.php @@ -17,7 +17,6 @@ use Illuminate\Foundation\Mix; use Illuminate\Http\Exceptions\HttpResponseException; use Illuminate\Queue\CallQueuedClosure; -use Illuminate\Queue\SerializableClosure; use Illuminate\Support\Facades\Date; use Illuminate\Support\HtmlString; use Symfony\Component\Debug\Exception\FatalThrowableError; @@ -387,7 +386,7 @@ function decrypt($value, $unserialize = true) function dispatch($job) { if ($job instanceof Closure) { - $job = new CallQueuedClosure(new SerializableClosure($job)); + $job = CallQueuedClosure::create($job); } return new PendingDispatch($job); diff --git a/src/Illuminate/Queue/CallQueuedClosure.php b/src/Illuminate/Queue/CallQueuedClosure.php index c0f45004443c..53359dbe1d10 100644 --- a/src/Illuminate/Queue/CallQueuedClosure.php +++ b/src/Illuminate/Queue/CallQueuedClosure.php @@ -2,6 +2,7 @@ namespace Illuminate\Queue; +use Closure; use Illuminate\Bus\Queueable; use Illuminate\Contracts\Container\Container; use Illuminate\Contracts\Queue\ShouldQueue; @@ -37,6 +38,17 @@ public function __construct(SerializableClosure $closure) $this->closure = $closure; } + /** + * Create a new job instance. + * + * @param \Closure $closure + * @return self + */ + public static function create(Closure $job) + { + return new self(new SerializableClosure($job)); + } + /** * Execute the job. * diff --git a/tests/Integration/Console/JobSchedulingTest.php b/tests/Integration/Console/JobSchedulingTest.php index 1b54307f001f..7f2c51d52aaa 100644 --- a/tests/Integration/Console/JobSchedulingTest.php +++ b/tests/Integration/Console/JobSchedulingTest.php @@ -4,6 +4,7 @@ use Illuminate\Bus\Queueable; use Illuminate\Console\Scheduling\Schedule; +use Illuminate\Container\Container; use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Queue\InteractsWithQueue; use Illuminate\Support\Facades\Queue;