Subversion-Projekte lars-tiefland.laravel_shop

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
148 lars 1
<?php
2
 
3
namespace Illuminate\Bus;
4
 
5
use Carbon\CarbonImmutable;
6
use Closure;
7
use Illuminate\Contracts\Queue\Factory as QueueFactory;
8
use Illuminate\Contracts\Support\Arrayable;
9
use Illuminate\Queue\CallQueuedClosure;
10
use Illuminate\Support\Arr;
11
use Illuminate\Support\Collection;
12
use JsonSerializable;
13
use Throwable;
14
 
15
class Batch implements Arrayable, JsonSerializable
16
{
17
    /**
18
     * The queue factory implementation.
19
     *
20
     * @var \Illuminate\Contracts\Queue\Factory
21
     */
22
    protected $queue;
23
 
24
    /**
25
     * The repository implementation.
26
     *
27
     * @var \Illuminate\Bus\BatchRepository
28
     */
29
    protected $repository;
30
 
31
    /**
32
     * The batch ID.
33
     *
34
     * @var string
35
     */
36
    public $id;
37
 
38
    /**
39
     * The batch name.
40
     *
41
     * @var string
42
     */
43
    public $name;
44
 
45
    /**
46
     * The total number of jobs that belong to the batch.
47
     *
48
     * @var int
49
     */
50
    public $totalJobs;
51
 
52
    /**
53
     * The total number of jobs that are still pending.
54
     *
55
     * @var int
56
     */
57
    public $pendingJobs;
58
 
59
    /**
60
     * The total number of jobs that have failed.
61
     *
62
     * @var int
63
     */
64
    public $failedJobs;
65
 
66
    /**
67
     * The IDs of the jobs that have failed.
68
     *
69
     * @var array
70
     */
71
    public $failedJobIds;
72
 
73
    /**
74
     * The batch options.
75
     *
76
     * @var array
77
     */
78
    public $options;
79
 
80
    /**
81
     * The date indicating when the batch was created.
82
     *
83
     * @var \Carbon\CarbonImmutable
84
     */
85
    public $createdAt;
86
 
87
    /**
88
     * The date indicating when the batch was cancelled.
89
     *
90
     * @var \Carbon\CarbonImmutable|null
91
     */
92
    public $cancelledAt;
93
 
94
    /**
95
     * The date indicating when the batch was finished.
96
     *
97
     * @var \Carbon\CarbonImmutable|null
98
     */
99
    public $finishedAt;
100
 
101
    /**
102
     * Create a new batch instance.
103
     *
104
     * @param  \Illuminate\Contracts\Queue\Factory  $queue
105
     * @param  \Illuminate\Bus\BatchRepository  $repository
106
     * @param  string  $id
107
     * @param  string  $name
108
     * @param  int  $totalJobs
109
     * @param  int  $pendingJobs
110
     * @param  int  $failedJobs
111
     * @param  array  $failedJobIds
112
     * @param  array  $options
113
     * @param  \Carbon\CarbonImmutable  $createdAt
114
     * @param  \Carbon\CarbonImmutable|null  $cancelledAt
115
     * @param  \Carbon\CarbonImmutable|null  $finishedAt
116
     * @return void
117
     */
118
    public function __construct(QueueFactory $queue,
119
                                BatchRepository $repository,
120
                                string $id,
121
                                string $name,
122
                                int $totalJobs,
123
                                int $pendingJobs,
124
                                int $failedJobs,
125
                                array $failedJobIds,
126
                                array $options,
127
                                CarbonImmutable $createdAt,
128
                                ?CarbonImmutable $cancelledAt = null,
129
                                ?CarbonImmutable $finishedAt = null)
130
    {
131
        $this->queue = $queue;
132
        $this->repository = $repository;
133
        $this->id = $id;
134
        $this->name = $name;
135
        $this->totalJobs = $totalJobs;
136
        $this->pendingJobs = $pendingJobs;
137
        $this->failedJobs = $failedJobs;
138
        $this->failedJobIds = $failedJobIds;
139
        $this->options = $options;
140
        $this->createdAt = $createdAt;
141
        $this->cancelledAt = $cancelledAt;
142
        $this->finishedAt = $finishedAt;
143
    }
144
 
145
    /**
146
     * Get a fresh instance of the batch represented by this ID.
147
     *
148
     * @return self
149
     */
150
    public function fresh()
151
    {
152
        return $this->repository->find($this->id);
153
    }
154
 
155
    /**
156
     * Add additional jobs to the batch.
157
     *
158
     * @param  \Illuminate\Support\Enumerable|object|array  $jobs
159
     * @return self
160
     */
161
    public function add($jobs)
162
    {
163
        $count = 0;
164
 
165
        $jobs = Collection::wrap($jobs)->map(function ($job) use (&$count) {
166
            $job = $job instanceof Closure ? CallQueuedClosure::create($job) : $job;
167
 
168
            if (is_array($job)) {
169
                $count += count($job);
170
 
171
                return with($this->prepareBatchedChain($job), function ($chain) {
172
                    return $chain->first()
173
                            ->allOnQueue($this->options['queue'] ?? null)
174
                            ->allOnConnection($this->options['connection'] ?? null)
175
                            ->chain($chain->slice(1)->values()->all());
176
                });
177
            } else {
178
                $job->withBatchId($this->id);
179
 
180
                $count++;
181
            }
182
 
183
            return $job;
184
        });
185
 
186
        $this->repository->transaction(function () use ($jobs, $count) {
187
            $this->repository->incrementTotalJobs($this->id, $count);
188
 
189
            $this->queue->connection($this->options['connection'] ?? null)->bulk(
190
                $jobs->all(),
191
                $data = '',
192
                $this->options['queue'] ?? null
193
            );
194
        });
195
 
196
        return $this->fresh();
197
    }
198
 
199
    /**
200
     * Prepare a chain that exists within the jobs being added.
201
     *
202
     * @param  array  $chain
203
     * @return \Illuminate\Support\Collection
204
     */
205
    protected function prepareBatchedChain(array $chain)
206
    {
207
        return collect($chain)->map(function ($job) {
208
            $job = $job instanceof Closure ? CallQueuedClosure::create($job) : $job;
209
 
210
            return $job->withBatchId($this->id);
211
        });
212
    }
213
 
214
    /**
215
     * Get the total number of jobs that have been processed by the batch thus far.
216
     *
217
     * @return int
218
     */
219
    public function processedJobs()
220
    {
221
        return $this->totalJobs - $this->pendingJobs;
222
    }
223
 
224
    /**
225
     * Get the percentage of jobs that have been processed (between 0-100).
226
     *
227
     * @return int
228
     */
229
    public function progress()
230
    {
231
        return $this->totalJobs > 0 ? round(($this->processedJobs() / $this->totalJobs) * 100) : 0;
232
    }
233
 
234
    /**
235
     * Record that a job within the batch finished successfully, executing any callbacks if necessary.
236
     *
237
     * @param  string  $jobId
238
     * @return void
239
     */
240
    public function recordSuccessfulJob(string $jobId)
241
    {
242
        $counts = $this->decrementPendingJobs($jobId);
243
 
244
        if ($counts->pendingJobs === 0) {
245
            $this->repository->markAsFinished($this->id);
246
        }
247
 
248
        if ($counts->pendingJobs === 0 && $this->hasThenCallbacks()) {
249
            $batch = $this->fresh();
250
 
251
            collect($this->options['then'])->each(function ($handler) use ($batch) {
252
                $this->invokeHandlerCallback($handler, $batch);
253
            });
254
        }
255
 
256
        if ($counts->allJobsHaveRanExactlyOnce() && $this->hasFinallyCallbacks()) {
257
            $batch = $this->fresh();
258
 
259
            collect($this->options['finally'])->each(function ($handler) use ($batch) {
260
                $this->invokeHandlerCallback($handler, $batch);
261
            });
262
        }
263
    }
264
 
265
    /**
266
     * Decrement the pending jobs for the batch.
267
     *
268
     * @param  string  $jobId
269
     * @return \Illuminate\Bus\UpdatedBatchJobCounts
270
     */
271
    public function decrementPendingJobs(string $jobId)
272
    {
273
        return $this->repository->decrementPendingJobs($this->id, $jobId);
274
    }
275
 
276
    /**
277
     * Determine if the batch has finished executing.
278
     *
279
     * @return bool
280
     */
281
    public function finished()
282
    {
283
        return ! is_null($this->finishedAt);
284
    }
285
 
286
    /**
287
     * Determine if the batch has "success" callbacks.
288
     *
289
     * @return bool
290
     */
291
    public function hasThenCallbacks()
292
    {
293
        return isset($this->options['then']) && ! empty($this->options['then']);
294
    }
295
 
296
    /**
297
     * Determine if the batch allows jobs to fail without cancelling the batch.
298
     *
299
     * @return bool
300
     */
301
    public function allowsFailures()
302
    {
303
        return Arr::get($this->options, 'allowFailures', false) === true;
304
    }
305
 
306
    /**
307
     * Determine if the batch has job failures.
308
     *
309
     * @return bool
310
     */
311
    public function hasFailures()
312
    {
313
        return $this->failedJobs > 0;
314
    }
315
 
316
    /**
317
     * Record that a job within the batch failed to finish successfully, executing any callbacks if necessary.
318
     *
319
     * @param  string  $jobId
320
     * @param  \Throwable  $e
321
     * @return void
322
     */
323
    public function recordFailedJob(string $jobId, $e)
324
    {
325
        $counts = $this->incrementFailedJobs($jobId);
326
 
327
        if ($counts->failedJobs === 1 && ! $this->allowsFailures()) {
328
            $this->cancel();
329
        }
330
 
331
        if ($counts->failedJobs === 1 && $this->hasCatchCallbacks()) {
332
            $batch = $this->fresh();
333
 
334
            collect($this->options['catch'])->each(function ($handler) use ($batch, $e) {
335
                $this->invokeHandlerCallback($handler, $batch, $e);
336
            });
337
        }
338
 
339
        if ($counts->allJobsHaveRanExactlyOnce() && $this->hasFinallyCallbacks()) {
340
            $batch = $this->fresh();
341
 
342
            collect($this->options['finally'])->each(function ($handler) use ($batch, $e) {
343
                $this->invokeHandlerCallback($handler, $batch, $e);
344
            });
345
        }
346
    }
347
 
348
    /**
349
     * Increment the failed jobs for the batch.
350
     *
351
     * @param  string  $jobId
352
     * @return \Illuminate\Bus\UpdatedBatchJobCounts
353
     */
354
    public function incrementFailedJobs(string $jobId)
355
    {
356
        return $this->repository->incrementFailedJobs($this->id, $jobId);
357
    }
358
 
359
    /**
360
     * Determine if the batch has "catch" callbacks.
361
     *
362
     * @return bool
363
     */
364
    public function hasCatchCallbacks()
365
    {
366
        return isset($this->options['catch']) && ! empty($this->options['catch']);
367
    }
368
 
369
    /**
370
     * Determine if the batch has "finally" callbacks.
371
     *
372
     * @return bool
373
     */
374
    public function hasFinallyCallbacks()
375
    {
376
        return isset($this->options['finally']) && ! empty($this->options['finally']);
377
    }
378
 
379
    /**
380
     * Cancel the batch.
381
     *
382
     * @return void
383
     */
384
    public function cancel()
385
    {
386
        $this->repository->cancel($this->id);
387
    }
388
 
389
    /**
390
     * Determine if the batch has been cancelled.
391
     *
392
     * @return bool
393
     */
394
    public function canceled()
395
    {
396
        return $this->cancelled();
397
    }
398
 
399
    /**
400
     * Determine if the batch has been cancelled.
401
     *
402
     * @return bool
403
     */
404
    public function cancelled()
405
    {
406
        return ! is_null($this->cancelledAt);
407
    }
408
 
409
    /**
410
     * Delete the batch from storage.
411
     *
412
     * @return void
413
     */
414
    public function delete()
415
    {
416
        $this->repository->delete($this->id);
417
    }
418
 
419
    /**
420
     * Invoke a batch callback handler.
421
     *
422
     * @param  callable  $handler
423
     * @param  \Illuminate\Bus\Batch  $batch
424
     * @param  \Throwable|null  $e
425
     * @return void
426
     */
427
    protected function invokeHandlerCallback($handler, Batch $batch, Throwable $e = null)
428
    {
429
        try {
430
            return $handler($batch, $e);
431
        } catch (Throwable $e) {
432
            if (function_exists('report')) {
433
                report($e);
434
            }
435
        }
436
    }
437
 
438
    /**
439
     * Convert the batch to an array.
440
     *
441
     * @return array
442
     */
443
    public function toArray()
444
    {
445
        return [
446
            'id' => $this->id,
447
            'name' => $this->name,
448
            'totalJobs' => $this->totalJobs,
449
            'pendingJobs' => $this->pendingJobs,
450
            'processedJobs' => $this->processedJobs(),
451
            'progress' => $this->progress(),
452
            'failedJobs' => $this->failedJobs,
453
            'options' => $this->options,
454
            'createdAt' => $this->createdAt,
455
            'cancelledAt' => $this->cancelledAt,
456
            'finishedAt' => $this->finishedAt,
457
        ];
458
    }
459
 
460
    /**
461
     * Get the JSON serializable representation of the object.
462
     *
463
     * @return array
464
     */
465
    public function jsonSerialize(): array
466
    {
467
        return $this->toArray();
468
    }
469
 
470
    /**
471
     * Dynamically access the batch's "options" via properties.
472
     *
473
     * @param  string  $key
474
     * @return mixed
475
     */
476
    public function __get($key)
477
    {
478
        return $this->options[$key] ?? null;
479
    }
480
}