WorkCommand.php 6.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  1. <?php
  2. namespace Illuminate\Queue\Console;
  3. use Illuminate\Queue\Worker;
  4. use Illuminate\Support\Carbon;
  5. use Illuminate\Console\Command;
  6. use Illuminate\Contracts\Queue\Job;
  7. use Illuminate\Queue\WorkerOptions;
  8. use Illuminate\Queue\Events\JobFailed;
  9. use Illuminate\Queue\Events\JobProcessed;
  10. use Illuminate\Queue\Events\JobProcessing;
  11. class WorkCommand extends Command
  12. {
  13. /**
  14. * The console command name.
  15. *
  16. * @var string
  17. */
  18. protected $signature = 'queue:work
  19. {connection? : The name of the queue connection to work}
  20. {--queue= : The names of the queues to work}
  21. {--daemon : Run the worker in daemon mode (Deprecated)}
  22. {--once : Only process the next job on the queue}
  23. {--delay=0 : The number of seconds to delay failed jobs}
  24. {--force : Force the worker to run even in maintenance mode}
  25. {--memory=128 : The memory limit in megabytes}
  26. {--sleep=3 : Number of seconds to sleep when no job is available}
  27. {--timeout=60 : The number of seconds a child process can run}
  28. {--tries=0 : Number of times to attempt a job before logging it failed}';
  29. /**
  30. * The console command description.
  31. *
  32. * @var string
  33. */
  34. protected $description = 'Start processing jobs on the queue as a daemon';
  35. /**
  36. * The queue worker instance.
  37. *
  38. * @var \Illuminate\Queue\Worker
  39. */
  40. protected $worker;
  41. /**
  42. * Create a new queue work command.
  43. *
  44. * @param \Illuminate\Queue\Worker $worker
  45. * @return void
  46. */
  47. public function __construct(Worker $worker)
  48. {
  49. parent::__construct();
  50. $this->worker = $worker;
  51. }
  52. /**
  53. * Execute the console command.
  54. *
  55. * @return void
  56. */
  57. public function handle()
  58. {
  59. if ($this->downForMaintenance() && $this->option('once')) {
  60. return $this->worker->sleep($this->option('sleep'));
  61. }
  62. // We'll listen to the processed and failed events so we can write information
  63. // to the console as jobs are processed, which will let the developer watch
  64. // which jobs are coming through a queue and be informed on its progress.
  65. $this->listenForEvents();
  66. $connection = $this->argument('connection')
  67. ?: $this->laravel['config']['queue.default'];
  68. // We need to get the right queue for the connection which is set in the queue
  69. // configuration file for the application. We will pull it based on the set
  70. // connection being run for the queue operation currently being executed.
  71. $queue = $this->getQueue($connection);
  72. $this->runWorker(
  73. $connection, $queue
  74. );
  75. }
  76. /**
  77. * Run the worker instance.
  78. *
  79. * @param string $connection
  80. * @param string $queue
  81. * @return array
  82. */
  83. protected function runWorker($connection, $queue)
  84. {
  85. $this->worker->setCache($this->laravel['cache']->driver());
  86. return $this->worker->{$this->option('once') ? 'runNextJob' : 'daemon'}(
  87. $connection, $queue, $this->gatherWorkerOptions()
  88. );
  89. }
  90. /**
  91. * Gather all of the queue worker options as a single object.
  92. *
  93. * @return \Illuminate\Queue\WorkerOptions
  94. */
  95. protected function gatherWorkerOptions()
  96. {
  97. return new WorkerOptions(
  98. $this->option('delay'), $this->option('memory'),
  99. $this->option('timeout'), $this->option('sleep'),
  100. $this->option('tries'), $this->option('force')
  101. );
  102. }
  103. /**
  104. * Listen for the queue events in order to update the console output.
  105. *
  106. * @return void
  107. */
  108. protected function listenForEvents()
  109. {
  110. $this->laravel['events']->listen(JobProcessing::class, function ($event) {
  111. $this->writeOutput($event->job, 'starting');
  112. });
  113. $this->laravel['events']->listen(JobProcessed::class, function ($event) {
  114. $this->writeOutput($event->job, 'success');
  115. });
  116. $this->laravel['events']->listen(JobFailed::class, function ($event) {
  117. $this->writeOutput($event->job, 'failed');
  118. $this->logFailedJob($event);
  119. });
  120. }
  121. /**
  122. * Write the status output for the queue worker.
  123. *
  124. * @param \Illuminate\Contracts\Queue\Job $job
  125. * @param string $status
  126. * @return void
  127. */
  128. protected function writeOutput(Job $job, $status)
  129. {
  130. switch ($status) {
  131. case 'starting':
  132. return $this->writeStatus($job, 'Processing', 'comment');
  133. case 'success':
  134. return $this->writeStatus($job, 'Processed', 'info');
  135. case 'failed':
  136. return $this->writeStatus($job, 'Failed', 'error');
  137. }
  138. }
  139. /**
  140. * Format the status output for the queue worker.
  141. *
  142. * @param \Illuminate\Contracts\Queue\Job $job
  143. * @param string $status
  144. * @param string $type
  145. * @return void
  146. */
  147. protected function writeStatus(Job $job, $status, $type)
  148. {
  149. $this->output->writeln(sprintf(
  150. "<{$type}>[%s][%s] %s</{$type}> %s",
  151. Carbon::now()->format('Y-m-d H:i:s'),
  152. $job->getJobId(),
  153. str_pad("{$status}:", 11), $job->resolveName()
  154. ));
  155. }
  156. /**
  157. * Store a failed job event.
  158. *
  159. * @param \Illuminate\Queue\Events\JobFailed $event
  160. * @return void
  161. */
  162. protected function logFailedJob(JobFailed $event)
  163. {
  164. $this->laravel['queue.failer']->log(
  165. $event->connectionName, $event->job->getQueue(),
  166. $event->job->getRawBody(), $event->exception
  167. );
  168. }
  169. /**
  170. * Get the queue name for the worker.
  171. *
  172. * @param string $connection
  173. * @return string
  174. */
  175. protected function getQueue($connection)
  176. {
  177. return $this->option('queue') ?: $this->laravel['config']->get(
  178. "queue.connections.{$connection}.queue", 'default'
  179. );
  180. }
  181. /**
  182. * Determine if the worker should run in maintenance mode.
  183. *
  184. * @return bool
  185. */
  186. protected function downForMaintenance()
  187. {
  188. return $this->option('force') ? false : $this->laravel->isDownForMaintenance();
  189. }
  190. }