startedAt = Date::now(); parent::__construct(); } /** * Execute the console command. * * @param \Illuminate\Console\Scheduling\Schedule $schedule * @param \Illuminate\Contracts\Events\Dispatcher $dispatcher * @param \Illuminate\Contracts\Cache\Repository $cache * @param \Illuminate\Contracts\Debug\ExceptionHandler $handler * @return void */ public function handle(Schedule $schedule, Dispatcher $dispatcher, Cache $cache, ExceptionHandler $handler) { $this->schedule = $schedule; $this->dispatcher = $dispatcher; $this->cache = $cache; $this->handler = $handler; $this->phpBinary = Application::phpBinary(); $this->clearInterruptSignal(); $this->newLine(); $events = $this->schedule->dueEvents($this->laravel); foreach ($events as $event) { if (! $event->filtersPass($this->laravel)) { $this->dispatcher->dispatch(new ScheduledTaskSkipped($event)); continue; } if ($event->onOneServer) { $this->runSingleServerEvent($event); } else { $this->runEvent($event); } $this->eventsRan = true; } if ($events->contains->isRepeatable()) { $this->repeatEvents($events->filter->isRepeatable()); } if (! $this->eventsRan) { $this->components->info('No scheduled commands are ready to run.'); } else { $this->newLine(); } } /** * Run the given single server event. * * @param \Illuminate\Console\Scheduling\Event $event * @return void */ protected function runSingleServerEvent($event) { if ($this->schedule->serverShouldRun($event, $this->startedAt)) { $this->runEvent($event); } else { $this->components->info(sprintf( 'Skipping [%s], as command already run on another server.', $event->getSummaryForDisplay() )); } } /** * Run the given event. * * @param \Illuminate\Console\Scheduling\Event $event * @return void */ protected function runEvent($event) { $summary = $event->getSummaryForDisplay(); $command = $event instanceof CallbackEvent ? $summary : trim(str_replace($this->phpBinary, '', $event->command)); $description = sprintf( '%s Running [%s]%s', Carbon::now()->format('Y-m-d H:i:s'), $command, $event->runInBackground ? ' in background' : '', ); $this->components->task($description, function () use ($event) { $this->dispatcher->dispatch(new ScheduledTaskStarting($event)); $start = microtime(true); try { $event->run($this->laravel); $this->dispatcher->dispatch(new ScheduledTaskFinished( $event, round(microtime(true) - $start, 2) )); $this->eventsRan = true; } catch (Throwable $e) { $this->dispatcher->dispatch(new ScheduledTaskFailed($event, $e)); $this->handler->report($e); } return $event->exitCode == 0; }); if (! $event instanceof CallbackEvent) { $this->components->bulletList([ $event->getSummaryForDisplay(), ]); } } /** * Run the given repeating events. * * @param \Illuminate\Support\Collection<\Illuminate\Console\Scheduling\Event> $events * @return void */ protected function repeatEvents($events) { $hasEnteredMaintenanceMode = false; while (Date::now()->lte($this->startedAt->endOfMinute())) { foreach ($events as $event) { if ($this->shouldInterrupt()) { return; } if (! $event->shouldRepeatNow()) { continue; } $hasEnteredMaintenanceMode = $hasEnteredMaintenanceMode || $this->laravel->isDownForMaintenance(); if ($hasEnteredMaintenanceMode && ! $event->runsInMaintenanceMode()) { continue; } if (! $event->filtersPass($this->laravel)) { $this->dispatcher->dispatch(new ScheduledTaskSkipped($event)); continue; } if ($event->onOneServer) { $this->runSingleServerEvent($event); } else { $this->runEvent($event); } $this->eventsRan = true; } Sleep::usleep(100000); } } /** * Determine if the schedule run should be interrupted. * * @return bool */ protected function shouldInterrupt() { return $this->cache->get('illuminate:schedule:interrupt', false); } /** * Ensure the interrupt signal is cleared. * * @return bool */ protected function clearInterruptSignal() { $this->cache->forget('illuminate:schedule:interrupt'); } }