← Назад к вопросам

Как выполнить действие в конце очереди в Laravel?

1.7 Middle🔥 131 комментариев
#Очереди и брокеры сообщений#Фреймворки

Комментарии (1)

🐱
deepseek-v3.2PrepBro AI5 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Управление очередями в Laravel: выполнение действий в конце

В Laravel существует несколько подходов для выполнения действия в конце очереди, то есть после того, как все остальные задачи были обработаны. Вот основные методы:

1. Использование обратного вызова then()

Метод then() объекта PendingChain или PendingBatch позволяет задать колбэк, который выполнится после завершения всех задач в цепочке или пакете.

use App\Jobs\ProcessPodcast;
use Illuminate\Support\Facades\Bus;

Bus::chain([
    new ProcessPodcast,
    new OptimizePodcast,
    new ReleasePodcast,
])->then(function () {
    // Этот код выполнится после успешного завершения ВСЕХ задач
    Podcast::where('processed', false)->update(['status' => 'completed']);
    Mail::to('admin@example.com')->send(new QueueCompletedMail());
})->dispatch();

2. Использование событий и слушателей

Laravel предоставляет системные события для мониторинга работы очередей:

// В сервис-провайдере
protected $listen = [
    'Illuminate\Queue\Events\JobProcessed' => [
        'App\Listeners\LogJobProcessed',
    ],
    'Illuminate\Queue\Events\WorkerStopping' => [
        'App\Listeners\HandleWorkerStop',
    ],
];

// Пример слушателя для завершения работы воркера
class HandleWorkerStop
{
    public function handle($event)
    {
        if ($event->worker->shouldQuit || $event->status === 'stopped') {
            // Выполнить финальные действия
            $this->cleanupTempFiles();
            $this->sendNotification();
        }
    }
}

3. Пакетная обработка с методом finally()

Для пакетной обработки задач можно использовать метод finally():

use App\Jobs\ProcessVideo;
use Illuminate\Bus\Batch;
use Illuminate\Support\Facades\Bus;

Bus::batch([
    new ProcessVideo('video1.mp4'),
    new ProcessVideo('video2.mp4'),
    new ProcessVideo('video3.mp4'),
])->then(function (Batch $batch) {
    // Выполнится при успешном завершении всех задач
})->catch(function (Batch $batch, Throwable $e) {
    // Выполнится при возникновении ошибки
})->finally(function (Batch $batch) {
    // Выполнится ВСЕГДА после завершения пакета
    // Независимо от успеха или ошибки
    Storage::deleteDirectory('temp/videos');
    Log::info('Batch processing completed');
})->dispatch();

4. Создание финального джоба в цепочке

Вы можете создать специальный джоб, который будет выполняться последним:

class FinalCleanupJob implements ShouldQueue
{
    public function handle()
    {
        // Выполнить финальные действия
        Cache::forget('queue_last_run');
        DB::table('queue_logs')->insert(['completed_at' => now()]);
    }
}

// Использование в цепочке
Bus::chain([
    new ProcessData,
    new ValidateData,
    new FinalCleanupJob, // Финальный джоб
])->dispatch();

5. Кастомные воркеры и middleware

Для сложных сценариев можно создать кастомный воркер или middleware:

class QueueTerminationMiddleware
{
    public function handle($job, $next)
    {
        try {
            $response = $next($job);
        } finally {
            // Этот код выполнится после каждой работы джоба
            if (app()->runningInConsole() && app('queue.worker')->shouldQuit) {
                $this->executeFinalActions();
            }
        }
        
        return $response;
    }
}

Ключевые моменты для выбора подхода:

  • then() и finally() — идеальны для цепочек и пакетов задач
  • Системные события — подходят для глобального мониторинга очередей
  • Финальные джобы — простой и понятный подход для последовательностей
  • Middleware — дает максимальный контроль, но сложнее в реализации

Рекомендации по использованию:

  1. Для простых последовательностей используйте метод then() в цепочках
  2. Для гарантированного выполнения независимо от результата используйте finally()
  3. Для глобального логирования и мониторинга используйте системные события
  4. Для сложной бизнес-логики создавайте специализированные финальные джобы
  5. Всегда добавляйте обработку ошибок и таймаутов для финальных операций

Выбор конкретного метода зависит от вашего сценария использования, требований к надежности и сложности бизнес-логики. Для большинства случаев методов then() и finally() будет достаточно.