Метод finally
Метод finally класса Batch позволяет зарегистрировать колбэк,
который будет вызван после того, как все задания в пакете завершатся.
Этот метод полезен для выполнения финальных действий, таких как
очистка ресурсов, отправка уведомлений о завершении или
логирование результатов. Колбэк получает объект пакета в
качестве аргумента, из которого можно получить информацию
о количестве успешно выполненных и провалившихся заданий.
Синтаксис
<?php
Bus::batch($jobs)
->then($thenCallback)
->catch($catchCallback)
->finally($finallyCallback)
->dispatch();
?>
Пример
Давайте создадим пакет заданий и зарегистрируем колбэки для каждого этапа:
<?php
namespace App\Http\Controllers;
use App\Jobs\ProcessDataJob;
use App\Jobs\ValidateDataJob;
use App\Jobs\CleanupJob;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Bus;
use Illuminate\Support\Facades\Log;
class BatchController extends Controller
{
public function index()
{
$jobs = [
new ValidateDataJob(),
new ProcessDataJob(),
new CleanupJob()
];
$batch = Bus::batch($jobs)
->then(function ($batch) {
Log::info('All jobs completed successfully');
})
->catch(function ($batch, $e) {
Log::error('Error occurred in batch', [
'error' => $e->getMessage()
]);
})
->finally(function ($batch) {
Log::info('Batch finished', [
'total' => $batch->totalJobs,
'successful' => $batch->processedJobs(),
'failed' => $batch->failedJobs
]);
})
->dispatch();
return response()->json([
'batch_id' => $batch->id,
'message' => 'Batch dispatched'
]);
}
}
?>
Результат выполнения кода:
["batch_id" => "abc123", "message" => "Batch dispatched"]
Пример
Рассмотрим пример с очисткой временных данных после обработки файлов:
<?php
namespace App\Jobs;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
class ProcessFileJob implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
protected $fileId;
public function __construct($fileId)
{
$this->fileId = $fileId;
}
public function handle()
{
$file = File::find($this->fileId);
if ($file) {
$content = file_get_contents($file->path);
$processed = strtoupper($content);
file_put_contents($file->path, $processed);
$file->processed = true;
$file->save();
}
}
}
?>
<?php
namespace App\Http\Controllers;
use App\Jobs\ProcessFileJob;
use App\Models\File;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Bus;
use Illuminate\Support\Facades\Storage;
class FileController extends Controller
{
public function processFiles(Request $request)
{
$fileIds = $request->input('file_ids', []);
$jobs = [];
foreach ($fileIds as $id) {
$jobs[] = new ProcessFileJob($id);
}
$batch = Bus::batch($jobs)
->finally(function ($batch) {
$tempPath = storage_path('app/temp');
if (is_dir($tempPath)) {
Storage::deleteDirectory('temp');
}
if ($batch->failedJobs === 0) {
return [
'status' => 'success',
'processed' => $batch->processedJobs()
];
} else {
return [
'status' => 'partial',
'processed' => $batch->processedJobs(),
'failed' => $batch->failedJobs
];
}
})
->dispatch();
return response()->json([
'batch_id' => $batch->id,
'status' => 'processing'
]);
}
}
?>
Результат выполнения при успешной обработке всех файлов:
["status" => "success", "processed" => 5]
Результат выполнения при частичной обработке:
["status" => "partial", "processed" => 3, "failed" => 2]