Skip to content

Commit e5e67c4

Browse files
khepintaylorotwell
andauthored
[10.x] Allow placing a batch on a chain (#48633)
* Allow placing a batch on a chain * missing file * Chains of batches of chains of batches * remove auto-format * remove auto-format * just collection * chained comes from queueable * better function name * reflop * messed up indentation * styleci * allow batch to fail but chain to succeed * formatting * formatting * formatting --------- Co-authored-by: Taylor Otwell <[email protected]>
1 parent f171d70 commit e5e67c4

File tree

3 files changed

+367
-0
lines changed

3 files changed

+367
-0
lines changed

src/Illuminate/Bus/ChainedBatch.php

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
<?php
2+
3+
namespace Illuminate\Bus;
4+
5+
use Illuminate\Container\Container;
6+
use Illuminate\Contracts\Bus\Dispatcher;
7+
use Illuminate\Contracts\Queue\ShouldQueue;
8+
use Illuminate\Foundation\Bus\Dispatchable;
9+
use Illuminate\Queue\InteractsWithQueue;
10+
use Illuminate\Support\Collection;
11+
use Throwable;
12+
13+
class ChainedBatch implements ShouldQueue
14+
{
15+
use Batchable, Dispatchable, InteractsWithQueue, Queueable;
16+
17+
/**
18+
* The collection of batched jobs.
19+
*
20+
* @var \Illuminate\Support\Collection
21+
*/
22+
public Collection $jobs;
23+
24+
/**
25+
* The name of the batch.
26+
*
27+
* @var string
28+
*/
29+
public string $name;
30+
31+
/**
32+
* The batch options.
33+
*
34+
* @var array
35+
*/
36+
public array $options;
37+
38+
/**
39+
* Create a new chained batch instance.
40+
*
41+
* @param \Illuminate\Bus\PendingBatch $batch
42+
* @return void
43+
*/
44+
public function __construct(PendingBatch $batch)
45+
{
46+
$this->jobs = static::prepareNestedBatches($batch->jobs);
47+
48+
$this->name = $batch->name;
49+
$this->options = $batch->options;
50+
}
51+
52+
/**
53+
* Prepare any nested batches within the given collection of jobs.
54+
*
55+
* @param \Illuminate\Support\Collection $jobs
56+
* @return \Illuminate\Support\Collection
57+
*/
58+
public static function prepareNestedBatches(Collection $jobs): Collection
59+
{
60+
return $jobs->map(fn ($job) => match (true) {
61+
is_array($job) => static::prepareNestedBatches(collect($job))->all(),
62+
$job instanceof Collection => static::prepareNestedBatches($job),
63+
$job instanceof PendingBatch => new ChainedBatch($job),
64+
default => $job,
65+
});
66+
}
67+
68+
/**
69+
* Handle the job.
70+
*
71+
* @return void
72+
*/
73+
public function handle()
74+
{
75+
$batch = new PendingBatch(Container::getInstance(), $this->jobs);
76+
77+
$batch->name = $this->name;
78+
$batch->options = $this->options;
79+
80+
if ($this->queue) {
81+
$batch->onQueue($this->queue);
82+
}
83+
84+
if ($this->connection) {
85+
$batch->onConnection($this->connection);
86+
}
87+
88+
$this->dispatchRemainderOfChainAfterBatch($batch);
89+
90+
foreach ($this->chainCatchCallbacks ?? [] as $callback) {
91+
$batch->catch(function (Batch $batch, ?Throwable $exception) use ($callback) {
92+
if (! $batch->allowsFailures()) {
93+
$callback($exception);
94+
}
95+
});
96+
}
97+
98+
$batch->dispatch();
99+
}
100+
101+
/**
102+
* Move the remainder of the chain to a "finally" batch callback.
103+
*
104+
* @param \Illuminate\Bus\PendingBatch $batch
105+
* @return
106+
*/
107+
protected function dispatchRemainderOfChainAfterBatch(PendingBatch $batch)
108+
{
109+
if (! empty($this->chained)) {
110+
$next = unserialize(array_shift($this->chained));
111+
112+
$next->chained = $this->chained;
113+
114+
$next->onConnection($next->connection ?: $this->chainConnection);
115+
$next->onQueue($next->queue ?: $this->chainQueue);
116+
117+
$next->chainConnection = $this->chainConnection;
118+
$next->chainQueue = $this->chainQueue;
119+
$next->chainCatchCallbacks = $this->chainCatchCallbacks;
120+
121+
$batch->finally(function (Batch $batch) use ($next) {
122+
if (! $batch->cancelled()) {
123+
Container::getInstance()->make(Dispatcher::class)->dispatch($next);
124+
}
125+
});
126+
127+
$this->chained = [];
128+
}
129+
}
130+
}

src/Illuminate/Bus/Dispatcher.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,7 @@ public function batch($jobs)
163163
public function chain($jobs)
164164
{
165165
$jobs = Collection::wrap($jobs);
166+
$jobs = ChainedBatch::prepareNestedBatches($jobs);
166167

167168
return new PendingChain($jobs->shift(), $jobs->toArray());
168169
}

0 commit comments

Comments
 (0)