Preskočiť na obsah
Backend Laravel 1. máj 2026 · 13 min čítania

Laravel Queues a Jobs — spracovanie na pozadí

Keď odosielanie e-mailu, generovanie PDF alebo import 10 000 riadkov z CSV spomaľuje HTTP request na viac ako 2 sekundy, je čas presunúť prácu do queue. Laravel Queues s Redis backendom a Horizon dashboardom sú priemyselný štandard pre asynchrónne spracovanie v PHP.

DC

Dušan Chlpek

Senior PHP vývojár · GEAR s.r.o. · 25+ rokov praxe

Prečo queues — kde synchronné spracovanie nestačí

Synchronné spracovanie blokovania HTTP requestu je vhodné pre operácie trvajúce menej ako 500 ms. Pre všetko ostatné potrebujete queue:

Porovnanie queue driverov

DriverVýkonSpoľahlivosťMonitoringKedy použiť
syncN/AN/ANieLokálny vývoj, testovanie
databaseNízkyDobráManuálneMalé projekty bez Redis
redisVysokýVýbornáHorizonProdukcia, odporúčané
sqsVysokýVýbornáAWS CloudWatchAWS infraštruktúra
beanstalkdVysokýDobráExterné nástrojeStaršie projekty

Konfigurácia Redis queue

Redis queue vyžaduje predis/predis alebo PHP rozšírenie phpredis. Pre produkciu odporúčam phpredis — je rýchlejší a stabilnejší.

# .env
QUEUE_CONNECTION=redis
REDIS_HOST=127.0.0.1
REDIS_PORT=6379
REDIS_PASSWORD=null
// config/queue.php — redis konfigurácia
'redis' => [
    'driver'      => 'redis',
    'connection'  => 'queue',      // separátna Redis DB pre queue
    'queue'       => env('REDIS_QUEUE', 'default'),
    'retry_after' => 90,            // sekúnd kým sa job považuje za stratený
    'block_for'   => null,
    'after_commit' => false,
],
// config/database.php — separátna Redis DB pre queue
'queue' => [
    'url'      => env('REDIS_URL'),
    'host'     => env('REDIS_HOST', '127.0.0.1'),
    'password' => env('REDIS_PASSWORD', null),
    'port'     => env('REDIS_PORT', '6379'),
    'database' => env('REDIS_QUEUE_DB', '1'),  // DB 1, nie 0 (cache)
],

Vytvorenie a dispatch Job triedy

php artisan make:job ProcessOrderExport
<?php
// app/Jobs/ProcessOrderExport.php
namespace App\Jobs;

use App\Models\Order;
use App\Services\ExportService;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;

class ProcessOrderExport implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    // Maximálny počet pokusov pred označením za failed
    public int $tries = 3;

    // Timeout jobu v sekundách
    public int $timeout = 120;

    // Exponenciálny backoff medzi pokusmi (sekundy)
    public array $backoff = [30, 60, 120];

    public function __construct(
        private readonly Order $order,
        private readonly string $format = 'xlsx'
    ) {}

    public function handle(ExportService $service): void
    {
        $path = $service->exportOrder($this->order, $this->format);

        // Notifikácia používateľa o hotovom exporte
        $this->order->user->notify(new ExportReadyNotification($path));
    }

    // Zavolá sa keď job definitívne zlyhá (po $tries pokusoch)
    public function failed(\Throwable $exception): void
    {
        \Log::error('Export jobu zlyhal', [
            'order_id' => $this->order->id,
            'error'    => $exception->getMessage(),
        ]);

        $this->order->user->notify(new ExportFailedNotification($this->order));
    }
}
// Dispatch metódy
use App\Jobs\ProcessOrderExport;

// Okamžité zaradenie do default queue
ProcessOrderExport::dispatch($order);

// S oneskorením 5 minút
ProcessOrderExport::dispatch($order)->delay(now()->addMinutes(5));

// Do špecifickej fronty s vyššou prioritou
ProcessOrderExport::dispatch($order)->onQueue('exports');

// Dispatch iba ak podmienka platí
ProcessOrderExport::dispatchIf($order->isPaid(), $order);

// Dispatch po úspešnom uložení (after database commit)
ProcessOrderExport::dispatch($order)->afterCommit();

Prioritné fronty a organizácia

Rôzne typy jobov by mali ísť do rôznych front s rôznymi prioritami. Worker spracúva fronty v poradí, v akom sú zadané.

# Worker spracúva critical pred high, high pred default
php artisan queue:work redis --queue=critical,high,default

# Príklady priradení jobov k frontám
SendTransactionalEmail::dispatch($mail)->onQueue('critical');
GenerateMonthlyReport::dispatch()->onQueue('default');
ResizeUploadedImages::dispatch($file)->onQueue('low');

Job Batching — paralelné spracovanie

Job Batching umožňuje dispatch skupiny jobov a sledovanie ich celkového stavu — ideálne pre import súborov alebo hromadné operácie.

use Illuminate\Bus\Batch;
use Illuminate\Support\Facades\Bus;

// Vytvorenie batch databázovej tabuľky
php artisan queue:batches-table
php artisan migrate
$batch = Bus::batch([
    new ImportChunk($rows->slice(0, 500)),
    new ImportChunk($rows->slice(500, 500)),
    new ImportChunk($rows->slice(1000)),
])->then(function (Batch $batch) {
    // Zavolá sa po úspešnom dokončení všetkých jobov
    ImportCompletedNotification::send($batch->id);
})->catch(function (Batch $batch, \Throwable $e) {
    // Zavolá sa pri prvom zlyhaní jobu v batch
    \Log::error('Import batch zlyhal', ['id' => $batch->id, 'error' => $e->getMessage()]);
})->finally(function (Batch $batch) {
    // Zavolá sa vždy po dokončení (úspech aj zlyhanie)
    Cache::forget("import_progress_{$batch->id}");
})->allowFailures()  // batch pokračuje aj pri čiastočných zlyhaniach
   ->onQueue('imports')
   ->dispatch();

// Sledovanie stavu batch
$progress = [
    'total'     => $batch->totalJobs,
    'processed' => $batch->processedJobs(),
    'failed'    => $batch->failedJobs,
    'percent'   => $batch->progress(),
];

Failed jobs — monitoring a obnova

# Vytvorenie tabuľky pre failed jobs
php artisan queue:failed-table
php artisan migrate

# Výpis failed jobov
php artisan queue:failed

# Retry konkrétneho jobu (podľa ID)
php artisan queue:retry 5

# Retry všetkých failed jobov
php artisan queue:retry all

# Zmazanie failed jobu
php artisan queue:forget 5
after_commit a databázové transakcie: Ak dispatchujete job vo vnútri databázovej transakcie, nastavte after_commit => true v konfigurácii alebo použite ->afterCommit(). Bez toho môže worker spustiť job skôr, ako sa transakcia commitne — a model ešte neexistuje v databáze.

Laravel Horizon — dashboard pre Redis queues

Horizon je first-party dashboard od Laravelu pre monitoring Redis queue workerov. Zobrazuje throughput, čas spracovania, failed jobs a umožňuje konfiguráciu workerov cez kód.

composer require laravel/horizon
php artisan horizon:install
php artisan migrate

# Spustenie Horizon (nahrádza queue:work)
php artisan horizon
// config/horizon.php — konfigurácia workerov
'environments' => [
    'production' => [
        'supervisor-1' => [
            'maxProcesses'  => 10,
            'balanceMaxShift' => 1,
            'balanceCooldown' => 3,
        ],
        'supervisor-exports' => [
            'queue'       => ['exports'],
            'maxProcesses' => 3,
            'timeout'     => 300,
        ],
    ],
    'local' => [
        'supervisor-1' => [
            'maxProcesses' => 3,
        ],
    ],
];

Horizon dashboard je dostupný na /horizon — v produkcii obmedzte prístup pomocou middleware v app/Providers/HorizonServiceProvider.php.

Supervisor — automatické reštartovanie workerov na VPS

Supervisor je process manager, ktorý zabezpečí, že queue worker sa automaticky reštartuje po páde alebo po php artisan horizon:terminate (napríklad po deployi).

# /etc/supervisor/conf.d/laravel-horizon.conf
[program:laravel-horizon]
process_name=%(program_name)s
command=php /var/www/myapp/artisan horizon
autostart=true
autorestart=true
user=www-data
redirect_stderr=true
stdout_logfile=/var/www/myapp/storage/logs/horizon.log
stopwaitsecs=3600
# Aplikovanie konfigurácie
sudo supervisorctl reread
sudo supervisorctl update
sudo supervisorctl start laravel-horizon:*

# Po každom deployi
php artisan horizon:terminate
# Supervisor automaticky reštartuje horizon s novou verziou kódu

Integrácia s CI/CD deploymentom

# Časť GitHub Actions deploment stepov
- name: Deploy na server
  run: |
    ssh user@server "cd /var/www/myapp && \
      git pull origin main && \
      composer install --no-dev --optimize-autoloader && \
      php artisan migrate --force && \
      php artisan config:cache && \
      php artisan route:cache && \
      php artisan view:cache && \
      php artisan horizon:terminate"
    # Supervisor automaticky reštartuje Horizon s novým kódom
Dlhotrvajúce joby a timeout: Nastavte $timeout v Job triede vždy o niekoľko sekúnd menej ako retry_after v konfigurácii queue drivera. Inak môže Redis job uvoľniť skôr, ako worker skončí — a job sa spustí viackrát súčasne.

Záver: Queues ako základ škálovateľnej Laravel aplikácie

Redis queue + Laravel Horizon + Supervisor je kombinácia, ktorá oddelí pomalé operácie od HTTP requestov a umožní spracovávať tisícky jobov za minútu na bežnom VPS serveri. Horizon dashboard dáva okamžitý prehľad o stave všetkých workerov a failed joboch.

Prvý krok: presunúť odosielanie e-mailov do queue. Trvá 15 minút a okamžite zrýchli každý formulár na webe.

Potrebujete pomoc s Laravel architecture alebo optimalizáciou výkonu?

Nastavím queues, Horizon a celú infraštruktúru pre vaše Laravel projekty. Audit + implementácia, odpoveď do 24 hodín.

Nezáväzný dopyt

Ďalšie články

Zavolať E-mail Dopyt

Ochrana súkromia

Táto stránka využíva cookies pre nevyhnutné fungovanie. Rešpektujeme vaše súkromie a legislatívu GDPR.