Subversion-Projekte lars-tiefland.laravel_shop

Revision

Revision 148 | Zur aktuellen Revision | Details | Vergleich mit vorheriger | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
148 lars 1
<?php
2
 
3
namespace Illuminate\Queue\Console;
4
 
5
use Illuminate\Console\Command;
6
use Illuminate\Contracts\Cache\Repository as Cache;
7
use Illuminate\Contracts\Queue\Job;
8
use Illuminate\Queue\Events\JobFailed;
9
use Illuminate\Queue\Events\JobProcessed;
10
use Illuminate\Queue\Events\JobProcessing;
11
use Illuminate\Queue\Events\JobReleasedAfterException;
12
use Illuminate\Queue\Worker;
13
use Illuminate\Queue\WorkerOptions;
14
use Illuminate\Support\Carbon;
15
use Symfony\Component\Console\Attribute\AsCommand;
16
use Symfony\Component\Console\Terminal;
17
use function Termwind\terminal;
18
 
19
#[AsCommand(name: 'queue:work')]
20
class WorkCommand extends Command
21
{
22
    /**
23
     * The console command name.
24
     *
25
     * @var string
26
     */
27
    protected $signature = 'queue:work
28
                            {connection? : The name of the queue connection to work}
29
                            {--name=default : The name of the worker}
30
                            {--queue= : The names of the queues to work}
31
                            {--daemon : Run the worker in daemon mode (Deprecated)}
32
                            {--once : Only process the next job on the queue}
33
                            {--stop-when-empty : Stop when the queue is empty}
34
                            {--delay=0 : The number of seconds to delay failed jobs (Deprecated)}
35
                            {--backoff=0 : The number of seconds to wait before retrying a job that encountered an uncaught exception}
36
                            {--max-jobs=0 : The number of jobs to process before stopping}
37
                            {--max-time=0 : The maximum number of seconds the worker should run}
38
                            {--force : Force the worker to run even in maintenance mode}
39
                            {--memory=128 : The memory limit in megabytes}
40
                            {--sleep=3 : Number of seconds to sleep when no job is available}
41
                            {--rest=0 : Number of seconds to rest between jobs}
42
                            {--timeout=60 : The number of seconds a child process can run}
43
                            {--tries=1 : Number of times to attempt a job before logging it failed}';
44
 
45
    /**
46
     * The name of the console command.
47
     *
48
     * This name is used to identify the command during lazy loading.
49
     *
50
     * @var string|null
51
     *
52
     * @deprecated
53
     */
54
    protected static $defaultName = 'queue:work';
55
 
56
    /**
57
     * The console command description.
58
     *
59
     * @var string
60
     */
61
    protected $description = 'Start processing jobs on the queue as a daemon';
62
 
63
    /**
64
     * The queue worker instance.
65
     *
66
     * @var \Illuminate\Queue\Worker
67
     */
68
    protected $worker;
69
 
70
    /**
71
     * The cache store implementation.
72
     *
73
     * @var \Illuminate\Contracts\Cache\Repository
74
     */
75
    protected $cache;
76
 
77
    /**
78
     * Holds the start time of the last processed job, if any.
79
     *
80
     * @var float|null
81
     */
82
    protected $latestStartedAt;
83
 
84
    /**
85
     * Create a new queue work command.
86
     *
87
     * @param  \Illuminate\Queue\Worker  $worker
88
     * @param  \Illuminate\Contracts\Cache\Repository  $cache
89
     * @return void
90
     */
91
    public function __construct(Worker $worker, Cache $cache)
92
    {
93
        parent::__construct();
94
 
95
        $this->cache = $cache;
96
        $this->worker = $worker;
97
    }
98
 
99
    /**
100
     * Execute the console command.
101
     *
102
     * @return int|null
103
     */
104
    public function handle()
105
    {
106
        if ($this->downForMaintenance() && $this->option('once')) {
107
            return $this->worker->sleep($this->option('sleep'));
108
        }
109
 
110
        // We'll listen to the processed and failed events so we can write information
111
        // to the console as jobs are processed, which will let the developer watch
112
        // which jobs are coming through a queue and be informed on its progress.
113
        $this->listenForEvents();
114
 
115
        $connection = $this->argument('connection')
116
                        ?: $this->laravel['config']['queue.default'];
117
 
118
        // We need to get the right queue for the connection which is set in the queue
119
        // configuration file for the application. We will pull it based on the set
120
        // connection being run for the queue operation currently being executed.
121
        $queue = $this->getQueue($connection);
122
 
123
        if (Terminal::hasSttyAvailable()) {
124
            $this->components->info(
125
                sprintf('Processing jobs from the [%s] %s.', $queue, str('queue')->plural(explode(',', $queue)))
126
            );
127
        }
128
 
129
        return $this->runWorker(
130
            $connection, $queue
131
        );
132
    }
133
 
134
    /**
135
     * Run the worker instance.
136
     *
137
     * @param  string  $connection
138
     * @param  string  $queue
139
     * @return int|null
140
     */
141
    protected function runWorker($connection, $queue)
142
    {
143
        return $this->worker
144
            ->setName($this->option('name'))
145
            ->setCache($this->cache)
146
            ->{$this->option('once') ? 'runNextJob' : 'daemon'}(
147
                $connection, $queue, $this->gatherWorkerOptions()
148
            );
149
    }
150
 
151
    /**
152
     * Gather all of the queue worker options as a single object.
153
     *
154
     * @return \Illuminate\Queue\WorkerOptions
155
     */
156
    protected function gatherWorkerOptions()
157
    {
158
        return new WorkerOptions(
159
            $this->option('name'),
160
            max($this->option('backoff'), $this->option('delay')),
161
            $this->option('memory'),
162
            $this->option('timeout'),
163
            $this->option('sleep'),
164
            $this->option('tries'),
165
            $this->option('force'),
166
            $this->option('stop-when-empty'),
167
            $this->option('max-jobs'),
168
            $this->option('max-time'),
169
            $this->option('rest')
170
        );
171
    }
172
 
173
    /**
174
     * Listen for the queue events in order to update the console output.
175
     *
176
     * @return void
177
     */
178
    protected function listenForEvents()
179
    {
180
        $this->laravel['events']->listen(JobProcessing::class, function ($event) {
181
            $this->writeOutput($event->job, 'starting');
182
        });
183
 
184
        $this->laravel['events']->listen(JobProcessed::class, function ($event) {
185
            $this->writeOutput($event->job, 'success');
186
        });
187
 
188
        $this->laravel['events']->listen(JobReleasedAfterException::class, function ($event) {
189
            $this->writeOutput($event->job, 'released_after_exception');
190
        });
191
 
192
        $this->laravel['events']->listen(JobFailed::class, function ($event) {
193
            $this->writeOutput($event->job, 'failed');
194
 
195
            $this->logFailedJob($event);
196
        });
197
    }
198
 
199
    /**
200
     * Write the status output for the queue worker.
201
     *
202
     * @param  \Illuminate\Contracts\Queue\Job  $job
203
     * @param  string  $status
204
     * @return void
205
     */
206
    protected function writeOutput(Job $job, $status)
207
    {
208
        $this->output->write(sprintf(
209
            '  <fg=gray>%s</> %s%s',
399 lars 210
            $this->now()->format('Y-m-d H:i:s'),
148 lars 211
            $job->resolveName(),
212
            $this->output->isVerbose()
213
                ? sprintf(' <fg=gray>%s</>', $job->getJobId())
214
                : ''
215
        ));
216
 
217
        if ($status == 'starting') {
218
            $this->latestStartedAt = microtime(true);
219
 
220
            $dots = max(terminal()->width() - mb_strlen($job->resolveName()) - (
221
                $this->output->isVerbose() ? (mb_strlen($job->getJobId()) + 1) : 0
222
            ) - 33, 0);
223
 
224
            $this->output->write(' '.str_repeat('<fg=gray>.</>', $dots));
225
 
226
            return $this->output->writeln(' <fg=yellow;options=bold>RUNNING</>');
227
        }
228
 
229
        $runTime = number_format((microtime(true) - $this->latestStartedAt) * 1000, 2).'ms';
230
 
231
        $dots = max(terminal()->width() - mb_strlen($job->resolveName()) - (
232
            $this->output->isVerbose() ? (mb_strlen($job->getJobId()) + 1) : 0
233
        ) - mb_strlen($runTime) - 31, 0);
234
 
235
        $this->output->write(' '.str_repeat('<fg=gray>.</>', $dots));
236
        $this->output->write(" <fg=gray>$runTime</>");
237
 
238
        $this->output->writeln(match ($status) {
239
            'success' => ' <fg=green;options=bold>DONE</>',
240
            'released_after_exception' => ' <fg=yellow;options=bold>FAIL</>',
241
            default => ' <fg=red;options=bold>FAIL</>',
242
        });
243
    }
244
 
245
    /**
399 lars 246
     * Get the current date / time.
247
     *
248
     * @return \Illuminate\Support\Carbon
249
     */
250
    protected function now()
251
    {
252
        $queueTimezone = $this->laravel['config']->get('queue.output_timezone');
253
 
254
        if ($queueTimezone &&
255
            $queueTimezone !== $this->laravel['config']->get('app.timezone')) {
256
            return Carbon::now()->setTimezone($queueTimezone);
257
        }
258
 
259
        return Carbon::now();
260
    }
261
 
262
    /**
148 lars 263
     * Store a failed job event.
264
     *
265
     * @param  \Illuminate\Queue\Events\JobFailed  $event
266
     * @return void
267
     */
268
    protected function logFailedJob(JobFailed $event)
269
    {
270
        $this->laravel['queue.failer']->log(
271
            $event->connectionName,
272
            $event->job->getQueue(),
273
            $event->job->getRawBody(),
274
            $event->exception
275
        );
276
    }
277
 
278
    /**
279
     * Get the queue name for the worker.
280
     *
281
     * @param  string  $connection
282
     * @return string
283
     */
284
    protected function getQueue($connection)
285
    {
286
        return $this->option('queue') ?: $this->laravel['config']->get(
287
            "queue.connections.{$connection}.queue", 'default'
288
        );
289
    }
290
 
291
    /**
292
     * Determine if the worker should run in maintenance mode.
293
     *
294
     * @return bool
295
     */
296
    protected function downForMaintenance()
297
    {
298
        return $this->option('force') ? false : $this->laravel->isDownForMaintenance();
299
    }
300
}