Skip to content

Commit 0791d2e

Browse files
author
Yitz Willroth
committed
feat: add job failure callbacks to batches
1 parent d3e8791 commit 0791d2e

File tree

2 files changed

+57
-35
lines changed

2 files changed

+57
-35
lines changed

src/Illuminate/Bus/Batch.php

Lines changed: 34 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -242,32 +242,33 @@ public function recordSuccessfulJob(string $jobId)
242242
$counts = $this->decrementPendingJobs($jobId);
243243

244244
if ($this->hasProgressCallbacks()) {
245-
$batch = $this->fresh();
246-
247-
(new Collection($this->options['progress']))->each(function ($handler) use ($batch) {
248-
$this->invokeHandlerCallback($handler, $batch);
249-
});
245+
$this->invokeCallbacks('progress');
250246
}
251247

252248
if ($counts->pendingJobs === 0) {
253249
$this->repository->markAsFinished($this->id);
254250
}
255251

256252
if ($counts->pendingJobs === 0 && $this->hasThenCallbacks()) {
257-
$batch = $this->fresh();
258-
259-
(new Collection($this->options['then']))->each(function ($handler) use ($batch) {
260-
$this->invokeHandlerCallback($handler, $batch);
261-
});
253+
$this->invokeCallbacks('then');
262254
}
263255

264256
if ($counts->allJobsHaveRanExactlyOnce() && $this->hasFinallyCallbacks()) {
265-
$batch = $this->fresh();
257+
$this->invokeCallbacks('finally');
258+
}
259+
}
266260

267-
(new Collection($this->options['finally']))->each(function ($handler) use ($batch) {
268-
$this->invokeHandlerCallback($handler, $batch);
261+
/**
262+
* Invoke the callbacks of the given type.
263+
*/
264+
public function invokeCallbacks(string $type, ?\Throwable $e = null): void
265+
{
266+
$batch = $this->fresh();
267+
268+
(new Collection($this->options[$type]))
269+
->each(function ($handler) use ($batch, $e) {
270+
$this->invokeHandlerCallback($handler, $batch, $e);
269271
});
270-
}
271272
}
272273

273274
/**
@@ -346,28 +347,22 @@ public function recordFailedJob(string $jobId, $e)
346347
$this->cancel();
347348
}
348349

349-
if ($this->hasProgressCallbacks() && $this->allowsFailures()) {
350-
$batch = $this->fresh();
350+
if ($this->allowsFailures()) {
351+
if ($this->hasProgressCallbacks()) {
352+
$this->invokeCallbacks('progress', $e);
353+
}
351354

352-
(new Collection($this->options['progress']))->each(function ($handler) use ($batch, $e) {
353-
$this->invokeHandlerCallback($handler, $batch, $e);
354-
});
355+
if ($this->hasFailureCallbacks()) {
356+
$this->invokeCallbacks('failure', $e);
357+
}
355358
}
356359

357360
if ($counts->failedJobs === 1 && $this->hasCatchCallbacks()) {
358-
$batch = $this->fresh();
359-
360-
(new Collection($this->options['catch']))->each(function ($handler) use ($batch, $e) {
361-
$this->invokeHandlerCallback($handler, $batch, $e);
362-
});
361+
$this->invokeCallbacks('catch', $e);
363362
}
364363

365364
if ($counts->allJobsHaveRanExactlyOnce() && $this->hasFinallyCallbacks()) {
366-
$batch = $this->fresh();
367-
368-
(new Collection($this->options['finally']))->each(function ($handler) use ($batch, $e) {
369-
$this->invokeHandlerCallback($handler, $batch, $e);
370-
});
365+
$this->invokeCallbacks('finally');
371366
}
372367
}
373368

@@ -402,6 +397,16 @@ public function hasFinallyCallbacks()
402397
return isset($this->options['finally']) && ! empty($this->options['finally']);
403398
}
404399

400+
/**
401+
* Determine if the batch has "failure" callbacks.
402+
*
403+
* @return bool
404+
*/
405+
public function hasFailureCallbacks()
406+
{
407+
return isset($this->options['failure']) && ! empty($this->options['failure']);
408+
}
409+
405410
/**
406411
* Cancel the batch.
407412
*

src/Illuminate/Bus/PendingBatch.php

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -237,14 +237,23 @@ public function finallyCallbacks()
237237
}
238238

239239
/**
240-
* Indicate that the batch should not be cancelled when a job within the batch fails.
241-
*
242-
* @param bool $allowFailures
243-
* @return $this
240+
* Indicate that the batch should not be cancelled when a job within the batch fails;
241+
* optionally add callbacks to be executed upon each job failure (this may be useful for
242+
* running other jobs when a job fails).
244243
*/
245-
public function allowFailures($allowFailures = true)
244+
public function allowFailures(bool|callable|Closure|array $param = true): self
246245
{
247-
$this->options['allowFailures'] = $allowFailures;
246+
if (! is_bool($param)) {
247+
$param = Arr::wrap($param);
248+
249+
foreach ($param as $callback) {
250+
$this->options['failure'][] = $callback instanceof Closure
251+
? new SerializableClosure($callback)
252+
: $callback;
253+
}
254+
}
255+
256+
$this->options['allowFailures'] = (bool) $param;
248257

249258
return $this;
250259
}
@@ -259,6 +268,14 @@ public function allowsFailures()
259268
return Arr::get($this->options, 'allowFailures', false) === true;
260269
}
261270

271+
/**
272+
* Get the "failure" callbacks that have been registered with the pending batch.
273+
*/
274+
public function failureCallbacks(): array
275+
{
276+
return $this->options['failure'] ?? [];
277+
}
278+
262279
/**
263280
* Set the name for the batch.
264281
*

0 commit comments

Comments
 (0)