0

Failed jobs — failed_jobs table, retry artisan command

Intermediate5 min read·lv-19-005
sql

Concept

Laravel Horizon is an official Laravel package that provides a beautiful dashboard for monitoring Redis queues. It offers real-time visibility into job throughput, runtime, and failures, and adds process management capabilities.

What Horizon adds:

  • Real-time dashboard: throughput, runtime, failures per queue.
  • Job search by job name, ID, or status.
  • Failed job browser with retry from the UI.
  • Automatic worker management: Horizon manages PHP worker processes automatically, scaling up/down based on queue depth.
  • Metrics retention: stores recent job metrics in Redis for historical analysis.

Supervisor mode: Horizon acts as a supervisor process. Instead of running queue:work manually, you run php artisan horizon. Horizon manages worker pools internally.

Configuration (config/horizon.php):

  • environments: Configure different worker counts and queues per environment (production vs local).
  • defaults: Named supervisor configurations with queue assignment, processes count, timeout.
  • supervisor-1: Supervisor watching specific queues.

Deployment: Always run php artisan horizon:terminate before deploying new code. Horizon will auto-restart workers with the new code after receiving the terminate signal. In production, use a process manager (Supervisor, systemd) to run horizon and keep it alive.

Authorization: Horizon::auth() callback in HorizonServiceProvider controls who can view the dashboard.

Code Example

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

// config/horizon.php
'environments' => [
    'production' => [
        'supervisor-1' => [
            'maxProcesses'   => 10,         // up to 10 workers
            'balanceMaxShift' => 1,          // scale one process at a time
            'balanceCooldown' => 3,          // wait 3s between scale events
        ],
    ],
    'local' => [
        'supervisor-1' => [
            'maxProcesses' => 3,
        ],
    ],
],

'defaults' => [
    'supervisor-1' => [
        'connection' => 'redis',
        'queue'      => ['default', 'emails', 'orders'],
        'balance'    => 'auto',    // auto-balance workers across queues
        'minProcesses' => 1,
        'maxProcesses' => 10,
        'timeout'    => 60,
        'tries'      => 3,
        'nice'       => 0,
    ],
],

// Starting Horizon
// php artisan horizon
// php artisan horizon:status   — check if running
// php artisan horizon:pause    — pause processing
// php artisan horizon:continue — resume
// php artisan horizon:terminate — graceful shutdown

// Access control — HorizonServiceProvider::boot()
\Laravel\Horizon\Horizon::auth(function($request) {
    return $request->user()?->isAdmin() ?? false;
    // Or: return in_array($request->user()?->email, config('horizon.allowed_emails'));
});

// Dashboard URL
// /horizon — requires authentication as configured above

// Supervisor config for production (keep Horizon running)
// /etc/supervisor/conf.d/laravel-horizon.conf
// [program:laravel-horizon]
// process_name=%(program_name)s
// command=php /var/www/html/artisan horizon
// autostart=true
// autorestart=true
// user=www-data
// redirect_stderr=true
// stdout_logfile=/var/www/html/storage/logs/horizon.log