Subversion-Projekte lars-tiefland.laravel_shop

Revision

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

Revision Autor Zeilennr. Zeile
148 lars 1
<?php
2
 
3
namespace Illuminate\Queue;
4
 
5
use Closure;
6
use DateTimeInterface;
7
use Illuminate\Container\Container;
8
use Illuminate\Contracts\Encryption\Encrypter;
9
use Illuminate\Contracts\Queue\ShouldBeEncrypted;
10
use Illuminate\Queue\Events\JobQueued;
11
use Illuminate\Support\Arr;
12
use Illuminate\Support\InteractsWithTime;
13
use Illuminate\Support\Str;
14
 
15
abstract class Queue
16
{
17
    use InteractsWithTime;
18
 
19
    /**
20
     * The IoC container instance.
21
     *
22
     * @var \Illuminate\Container\Container
23
     */
24
    protected $container;
25
 
26
    /**
27
     * The connection name for the queue.
28
     *
29
     * @var string
30
     */
31
    protected $connectionName;
32
 
33
    /**
34
     * Indicates that jobs should be dispatched after all database transactions have committed.
35
     *
36
     * @return $this
37
     */
38
    protected $dispatchAfterCommit;
39
 
40
    /**
41
     * The create payload callbacks.
42
     *
43
     * @var callable[]
44
     */
45
    protected static $createPayloadCallbacks = [];
46
 
47
    /**
48
     * Push a new job onto the queue.
49
     *
50
     * @param  string  $queue
51
     * @param  string  $job
52
     * @param  mixed  $data
53
     * @return mixed
54
     */
55
    public function pushOn($queue, $job, $data = '')
56
    {
57
        return $this->push($job, $data, $queue);
58
    }
59
 
60
    /**
61
     * Push a new job onto a specific queue after (n) seconds.
62
     *
63
     * @param  string  $queue
64
     * @param  \DateTimeInterface|\DateInterval|int  $delay
65
     * @param  string  $job
66
     * @param  mixed  $data
67
     * @return mixed
68
     */
69
    public function laterOn($queue, $delay, $job, $data = '')
70
    {
71
        return $this->later($delay, $job, $data, $queue);
72
    }
73
 
74
    /**
75
     * Push an array of jobs onto the queue.
76
     *
77
     * @param  array  $jobs
78
     * @param  mixed  $data
79
     * @param  string|null  $queue
80
     * @return void
81
     */
82
    public function bulk($jobs, $data = '', $queue = null)
83
    {
84
        foreach ((array) $jobs as $job) {
85
            $this->push($job, $data, $queue);
86
        }
87
    }
88
 
89
    /**
90
     * Create a payload string from the given job and data.
91
     *
92
     * @param  \Closure|string|object  $job
93
     * @param  string  $queue
94
     * @param  mixed  $data
95
     * @return string
96
     *
97
     * @throws \Illuminate\Queue\InvalidPayloadException
98
     */
99
    protected function createPayload($job, $queue, $data = '')
100
    {
101
        if ($job instanceof Closure) {
102
            $job = CallQueuedClosure::create($job);
103
        }
104
 
105
        $payload = json_encode($this->createPayloadArray($job, $queue, $data), \JSON_UNESCAPED_UNICODE);
106
 
107
        if (json_last_error() !== JSON_ERROR_NONE) {
108
            throw new InvalidPayloadException(
109
                'Unable to JSON encode payload. Error code: '.json_last_error()
110
            );
111
        }
112
 
113
        return $payload;
114
    }
115
 
116
    /**
117
     * Create a payload array from the given job and data.
118
     *
119
     * @param  string|object  $job
120
     * @param  string  $queue
121
     * @param  mixed  $data
122
     * @return array
123
     */
124
    protected function createPayloadArray($job, $queue, $data = '')
125
    {
126
        return is_object($job)
127
                    ? $this->createObjectPayload($job, $queue)
128
                    : $this->createStringPayload($job, $queue, $data);
129
    }
130
 
131
    /**
132
     * Create a payload for an object-based queue handler.
133
     *
134
     * @param  object  $job
135
     * @param  string  $queue
136
     * @return array
137
     */
138
    protected function createObjectPayload($job, $queue)
139
    {
140
        $payload = $this->withCreatePayloadHooks($queue, [
141
            'uuid' => (string) Str::uuid(),
142
            'displayName' => $this->getDisplayName($job),
143
            'job' => 'Illuminate\Queue\CallQueuedHandler@call',
144
            'maxTries' => $job->tries ?? null,
145
            'maxExceptions' => $job->maxExceptions ?? null,
146
            'failOnTimeout' => $job->failOnTimeout ?? false,
147
            'backoff' => $this->getJobBackoff($job),
148
            'timeout' => $job->timeout ?? null,
149
            'retryUntil' => $this->getJobExpiration($job),
150
            'data' => [
151
                'commandName' => $job,
152
                'command' => $job,
153
            ],
154
        ]);
155
 
156
        $command = $this->jobShouldBeEncrypted($job) && $this->container->bound(Encrypter::class)
157
                    ? $this->container[Encrypter::class]->encrypt(serialize(clone $job))
158
                    : serialize(clone $job);
159
 
160
        return array_merge($payload, [
161
            'data' => array_merge($payload['data'], [
162
                'commandName' => get_class($job),
163
                'command' => $command,
164
            ]),
165
        ]);
166
    }
167
 
168
    /**
169
     * Get the display name for the given job.
170
     *
171
     * @param  object  $job
172
     * @return string
173
     */
174
    protected function getDisplayName($job)
175
    {
176
        return method_exists($job, 'displayName')
177
                        ? $job->displayName() : get_class($job);
178
    }
179
 
180
    /**
181
     * Get the backoff for an object-based queue handler.
182
     *
183
     * @param  mixed  $job
184
     * @return mixed
185
     */
186
    public function getJobBackoff($job)
187
    {
188
        if (! method_exists($job, 'backoff') && ! isset($job->backoff)) {
189
            return;
190
        }
191
 
192
        if (is_null($backoff = $job->backoff ?? $job->backoff())) {
193
            return;
194
        }
195
 
196
        return collect(Arr::wrap($backoff))
197
            ->map(function ($backoff) {
198
                return $backoff instanceof DateTimeInterface
199
                                ? $this->secondsUntil($backoff) : $backoff;
200
            })->implode(',');
201
    }
202
 
203
    /**
204
     * Get the expiration timestamp for an object-based queue handler.
205
     *
206
     * @param  mixed  $job
207
     * @return mixed
208
     */
209
    public function getJobExpiration($job)
210
    {
211
        if (! method_exists($job, 'retryUntil') && ! isset($job->retryUntil)) {
212
            return;
213
        }
214
 
215
        $expiration = $job->retryUntil ?? $job->retryUntil();
216
 
217
        return $expiration instanceof DateTimeInterface
218
                        ? $expiration->getTimestamp() : $expiration;
219
    }
220
 
221
    /**
222
     * Determine if the job should be encrypted.
223
     *
224
     * @param  object  $job
225
     * @return bool
226
     */
227
    protected function jobShouldBeEncrypted($job)
228
    {
229
        if ($job instanceof ShouldBeEncrypted) {
230
            return true;
231
        }
232
 
233
        return isset($job->shouldBeEncrypted) && $job->shouldBeEncrypted;
234
    }
235
 
236
    /**
237
     * Create a typical, string based queue payload array.
238
     *
239
     * @param  string  $job
240
     * @param  string  $queue
241
     * @param  mixed  $data
242
     * @return array
243
     */
244
    protected function createStringPayload($job, $queue, $data)
245
    {
246
        return $this->withCreatePayloadHooks($queue, [
247
            'uuid' => (string) Str::uuid(),
248
            'displayName' => is_string($job) ? explode('@', $job)[0] : null,
249
            'job' => $job,
250
            'maxTries' => null,
251
            'maxExceptions' => null,
252
            'failOnTimeout' => false,
253
            'backoff' => null,
254
            'timeout' => null,
255
            'data' => $data,
256
        ]);
257
    }
258
 
259
    /**
260
     * Register a callback to be executed when creating job payloads.
261
     *
262
     * @param  callable|null  $callback
263
     * @return void
264
     */
265
    public static function createPayloadUsing($callback)
266
    {
267
        if (is_null($callback)) {
268
            static::$createPayloadCallbacks = [];
269
        } else {
270
            static::$createPayloadCallbacks[] = $callback;
271
        }
272
    }
273
 
274
    /**
275
     * Create the given payload using any registered payload hooks.
276
     *
277
     * @param  string  $queue
278
     * @param  array  $payload
279
     * @return array
280
     */
281
    protected function withCreatePayloadHooks($queue, array $payload)
282
    {
283
        if (! empty(static::$createPayloadCallbacks)) {
284
            foreach (static::$createPayloadCallbacks as $callback) {
285
                $payload = array_merge($payload, $callback($this->getConnectionName(), $queue, $payload));
286
            }
287
        }
288
 
289
        return $payload;
290
    }
291
 
292
    /**
293
     * Enqueue a job using the given callback.
294
     *
295
     * @param  \Closure|string|object  $job
296
     * @param  string  $payload
297
     * @param  string  $queue
298
     * @param  \DateTimeInterface|\DateInterval|int|null  $delay
299
     * @param  callable  $callback
300
     * @return mixed
301
     */
302
    protected function enqueueUsing($job, $payload, $queue, $delay, $callback)
303
    {
304
        if ($this->shouldDispatchAfterCommit($job) &&
305
            $this->container->bound('db.transactions')) {
306
            return $this->container->make('db.transactions')->addCallback(
307
                function () use ($payload, $queue, $delay, $callback, $job) {
308
                    return tap($callback($payload, $queue, $delay), function ($jobId) use ($job) {
309
                        $this->raiseJobQueuedEvent($jobId, $job);
310
                    });
311
                }
312
            );
313
        }
314
 
315
        return tap($callback($payload, $queue, $delay), function ($jobId) use ($job) {
316
            $this->raiseJobQueuedEvent($jobId, $job);
317
        });
318
    }
319
 
320
    /**
321
     * Determine if the job should be dispatched after all database transactions have committed.
322
     *
323
     * @param  \Closure|string|object  $job
324
     * @return bool
325
     */
326
    protected function shouldDispatchAfterCommit($job)
327
    {
991 lars 328
        if (! $job instanceof Closure && is_object($job) && isset($job->afterCommit)) {
148 lars 329
            return $job->afterCommit;
330
        }
331
 
332
        if (isset($this->dispatchAfterCommit)) {
333
            return $this->dispatchAfterCommit;
334
        }
335
 
336
        return false;
337
    }
338
 
339
    /**
340
     * Raise the job queued event.
341
     *
342
     * @param  string|int|null  $jobId
343
     * @param  \Closure|string|object  $job
344
     * @return void
345
     */
346
    protected function raiseJobQueuedEvent($jobId, $job)
347
    {
348
        if ($this->container->bound('events')) {
349
            $this->container['events']->dispatch(new JobQueued($this->connectionName, $jobId, $job));
350
        }
351
    }
352
 
353
    /**
354
     * Get the connection name for the queue.
355
     *
356
     * @return string
357
     */
358
    public function getConnectionName()
359
    {
360
        return $this->connectionName;
361
    }
362
 
363
    /**
364
     * Set the connection name for the queue.
365
     *
366
     * @param  string  $name
367
     * @return $this
368
     */
369
    public function setConnectionName($name)
370
    {
371
        $this->connectionName = $name;
372
 
373
        return $this;
374
    }
375
 
376
    /**
377
     * Get the container instance being used by the connection.
378
     *
379
     * @return \Illuminate\Container\Container
380
     */
381
    public function getContainer()
382
    {
383
        return $this->container;
384
    }
385
 
386
    /**
387
     * Set the IoC container instance.
388
     *
389
     * @param  \Illuminate\Container\Container  $container
390
     * @return void
391
     */
392
    public function setContainer(Container $container)
393
    {
394
        $this->container = $container;
395
    }
396
}