0

Job chaining and batching (Bus::chain, Bus::batch)

Advanced5 min read·lv-19-006
interview

Concept

Laravel Horizon is the official Redis queue monitoring dashboard. It provides real-time metrics, failed job inspection, and automatic worker management.

What Horizon adds over bare queue:work:

  • Web dashboard at /horizon — real-time throughput graphs, failed jobs, pending jobs.
  • Auto-scaling workers — defines min/max processes per queue, scales based on load.
  • Job tagging — jobs with Eloquent models are tagged with model ID for searchability.
  • Job retention — recent job history stored in Redis for inspection.
  • Metrics — tracks job runtime, throughput, failure rate.

Installation:

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

Worker management: In config/horizon.php, define supervisor configurations per environment. Horizon starts the configured number of workers and auto-balances them across queues.

Running: php artisan horizon — starts Horizon (replaces multiple queue:work commands).

Deployment: php artisan horizon:terminate before deploy. Process manager (Supervisor/systemd) auto-restarts it. New workers pick up the new code.

Pausing: php artisan horizon:pause / horizon:continue for maintenance.

Tagging: Jobs automatically tag their model arguments. ProcessOrder for Order{id:42} is tagged App\Models\Order:42. Searchable in the dashboard.

Code Example

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

// config/horizon.php — worker configuration
'environments' => [
    'production' => [
        'supervisor-1' => [
            'connection'     => 'redis',
            'queue'          => ['high', 'default', 'low'],
            'balance'        => 'auto',       // auto, simple, false
            'autoScalingStrategy' => 'time',  // 'time' or 'size'
            'maxProcesses'   => 20,
            'minProcesses'   => 2,
            'balanceMaxShift' => 1,
            'balanceCooldown' => 3,
            'memory'         => 128,
            'tries'          => 3,
            'timeout'        => 60,
            'nice'           => 0,
        ],
        'supervisor-email' => [
            'connection'   => 'redis',
            'queue'        => ['emails'],
            'balance'      => 'simple',
            'maxProcesses' => 5,
            'minProcesses' => 1,
        ],
    ],
    'local' => [
        'supervisor-1' => [
            'maxProcesses' => 3,
            'tries'        => 1,
        ],
    ],
],

// Authorization — who can view /horizon
// app/Providers/HorizonServiceProvider.php
\Laravel\Horizon\Horizon::auth(function ($request) {
    return auth()->check() && auth()->user()->isAdmin();
});

// Custom tags on jobs
class ProcessOrder implements \Illuminate\Contracts\Queue\ShouldQueue
{
    use \Illuminate\Bus\Queueable, \Illuminate\Foundation\Bus\Dispatchable;
    use \Illuminate\Queue\InteractsWithQueue, \Illuminate\Queue\SerializesModels;

    public function __construct(private readonly \App\Models\Order $order) {}

    // Custom tags for Horizon search
    public function tags(): array
    {
        return [
            "order:{$this->order->id}",
            "user:{$this->order->user_id}",
            "status:{$this->order->status}",
        ];
    }

    public function handle(): void { ... }
}

// Supervisor/systemd to keep Horizon running
// [program:laravel-horizon]
// command=php /var/www/artisan horizon
// autostart=true
// autorestart=true
// user=www-data