Revision 148 | Zur aktuellen Revision | Blame | Vergleich mit vorheriger | Letzte Änderung | Log anzeigen | RSS feed
<?phpnamespace Illuminate\Queue\Console;use Illuminate\Console\Command;use Illuminate\Contracts\Cache\Repository as Cache;use Illuminate\Contracts\Queue\Job;use Illuminate\Queue\Events\JobFailed;use Illuminate\Queue\Events\JobProcessed;use Illuminate\Queue\Events\JobProcessing;use Illuminate\Queue\Events\JobReleasedAfterException;use Illuminate\Queue\Worker;use Illuminate\Queue\WorkerOptions;use Illuminate\Support\Carbon;use Symfony\Component\Console\Attribute\AsCommand;use Symfony\Component\Console\Terminal;use function Termwind\terminal;#[AsCommand(name: 'queue:work')]class WorkCommand extends Command{/*** The console command name.** @var string*/protected $signature = 'queue:work{connection? : The name of the queue connection to work}{--name=default : The name of the worker}{--queue= : The names of the queues to work}{--daemon : Run the worker in daemon mode (Deprecated)}{--once : Only process the next job on the queue}{--stop-when-empty : Stop when the queue is empty}{--delay=0 : The number of seconds to delay failed jobs (Deprecated)}{--backoff=0 : The number of seconds to wait before retrying a job that encountered an uncaught exception}{--max-jobs=0 : The number of jobs to process before stopping}{--max-time=0 : The maximum number of seconds the worker should run}{--force : Force the worker to run even in maintenance mode}{--memory=128 : The memory limit in megabytes}{--sleep=3 : Number of seconds to sleep when no job is available}{--rest=0 : Number of seconds to rest between jobs}{--timeout=60 : The number of seconds a child process can run}{--tries=1 : Number of times to attempt a job before logging it failed}';/*** The name of the console command.** This name is used to identify the command during lazy loading.** @var string|null** @deprecated*/protected static $defaultName = 'queue:work';/*** The console command description.** @var string*/protected $description = 'Start processing jobs on the queue as a daemon';/*** The queue worker instance.** @var \Illuminate\Queue\Worker*/protected $worker;/*** The cache store implementation.** @var \Illuminate\Contracts\Cache\Repository*/protected $cache;/*** Holds the start time of the last processed job, if any.** @var float|null*/protected $latestStartedAt;/*** Create a new queue work command.** @param \Illuminate\Queue\Worker $worker* @param \Illuminate\Contracts\Cache\Repository $cache* @return void*/public function __construct(Worker $worker, Cache $cache){parent::__construct();$this->cache = $cache;$this->worker = $worker;}/*** Execute the console command.** @return int|null*/public function handle(){if ($this->downForMaintenance() && $this->option('once')) {return $this->worker->sleep($this->option('sleep'));}// We'll listen to the processed and failed events so we can write information// to the console as jobs are processed, which will let the developer watch// which jobs are coming through a queue and be informed on its progress.$this->listenForEvents();$connection = $this->argument('connection')?: $this->laravel['config']['queue.default'];// We need to get the right queue for the connection which is set in the queue// configuration file for the application. We will pull it based on the set// connection being run for the queue operation currently being executed.$queue = $this->getQueue($connection);if (Terminal::hasSttyAvailable()) {$this->components->info(sprintf('Processing jobs from the [%s] %s.', $queue, str('queue')->plural(explode(',', $queue))));}return $this->runWorker($connection, $queue);}/*** Run the worker instance.** @param string $connection* @param string $queue* @return int|null*/protected function runWorker($connection, $queue){return $this->worker->setName($this->option('name'))->setCache($this->cache)->{$this->option('once') ? 'runNextJob' : 'daemon'}($connection, $queue, $this->gatherWorkerOptions());}/*** Gather all of the queue worker options as a single object.** @return \Illuminate\Queue\WorkerOptions*/protected function gatherWorkerOptions(){return new WorkerOptions($this->option('name'),max($this->option('backoff'), $this->option('delay')),$this->option('memory'),$this->option('timeout'),$this->option('sleep'),$this->option('tries'),$this->option('force'),$this->option('stop-when-empty'),$this->option('max-jobs'),$this->option('max-time'),$this->option('rest'));}/*** Listen for the queue events in order to update the console output.** @return void*/protected function listenForEvents(){$this->laravel['events']->listen(JobProcessing::class, function ($event) {$this->writeOutput($event->job, 'starting');});$this->laravel['events']->listen(JobProcessed::class, function ($event) {$this->writeOutput($event->job, 'success');});$this->laravel['events']->listen(JobReleasedAfterException::class, function ($event) {$this->writeOutput($event->job, 'released_after_exception');});$this->laravel['events']->listen(JobFailed::class, function ($event) {$this->writeOutput($event->job, 'failed');$this->logFailedJob($event);});}/*** Write the status output for the queue worker.** @param \Illuminate\Contracts\Queue\Job $job* @param string $status* @return void*/protected function writeOutput(Job $job, $status){$this->output->write(sprintf(' <fg=gray>%s</> %s%s',$this->now()->format('Y-m-d H:i:s'),$job->resolveName(),$this->output->isVerbose()? sprintf(' <fg=gray>%s</>', $job->getJobId()): ''));if ($status == 'starting') {$this->latestStartedAt = microtime(true);$dots = max(terminal()->width() - mb_strlen($job->resolveName()) - ($this->output->isVerbose() ? (mb_strlen($job->getJobId()) + 1) : 0) - 33, 0);$this->output->write(' '.str_repeat('<fg=gray>.</>', $dots));return $this->output->writeln(' <fg=yellow;options=bold>RUNNING</>');}$runTime = number_format((microtime(true) - $this->latestStartedAt) * 1000, 2).'ms';$dots = max(terminal()->width() - mb_strlen($job->resolveName()) - ($this->output->isVerbose() ? (mb_strlen($job->getJobId()) + 1) : 0) - mb_strlen($runTime) - 31, 0);$this->output->write(' '.str_repeat('<fg=gray>.</>', $dots));$this->output->write(" <fg=gray>$runTime</>");$this->output->writeln(match ($status) {'success' => ' <fg=green;options=bold>DONE</>','released_after_exception' => ' <fg=yellow;options=bold>FAIL</>',default => ' <fg=red;options=bold>FAIL</>',});}/*** Get the current date / time.** @return \Illuminate\Support\Carbon*/protected function now(){$queueTimezone = $this->laravel['config']->get('queue.output_timezone');if ($queueTimezone &&$queueTimezone !== $this->laravel['config']->get('app.timezone')) {return Carbon::now()->setTimezone($queueTimezone);}return Carbon::now();}/*** Store a failed job event.** @param \Illuminate\Queue\Events\JobFailed $event* @return void*/protected function logFailedJob(JobFailed $event){$this->laravel['queue.failer']->log($event->connectionName,$event->job->getQueue(),$event->job->getRawBody(),$event->exception);}/*** Get the queue name for the worker.** @param string $connection* @return string*/protected function getQueue($connection){return $this->option('queue') ?: $this->laravel['config']->get("queue.connections.{$connection}.queue", 'default');}/*** Determine if the worker should run in maintenance mode.** @return bool*/protected function downForMaintenance(){return $this->option('force') ? false : $this->laravel->isDownForMaintenance();}}