All skills
asyrafhussin avatar

/laravel-queues

@2631530

Laravel 13 queue and job patterns — driver choice, job design (idempotency, ShouldQueue, model serialisation), retry and failure handling, worker scaling, Bus batching and chaining, Horizon when warranted, queue testing. Use when designing async jobs, scheduling background work, configuring Horizon, debugging stuck jobs, or auditing queue health. Triggers on "Laravel queue", "Laravel job", "background job", "Horizon setup", "failed jobs", "Bus batch", "queue worker tuning".

Use this Skill: https://skilld.dev/gh/asyrafhussin/agent-skills/laravel-queues

This session only. Nothing lands on disk.

rulesdesign-shouldqueue.md

≈1.1k tokens on demand. Your agent reads this file only when SKILL.md points to it.

implements ShouldQueue — The #1 Production Bug

Impact: CRITICAL (Without ShouldQueue, the job runs synchronously inside the request — what was meant as 'queued' blocks HTTP)

The single most common Laravel queue bug: a class that uses Dispatchable and looks like a job, but doesn't implement ShouldQueue. Without that one interface marker, dispatch() calls handle() inline, blocking whatever called it. The 800ms "queued" Stripe charge isn't queued — it's adding 800ms to the checkout request.

AI-generated job scaffolding sometimes drops the implements ShouldQueue or names a "service" class as if it were a job. Always verify.

Incorrect

// ❌ No ShouldQueue — looks queued, runs sync

namespace App\Jobs;

use Illuminate\Bus\Queueable;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;

class SendWelcomeEmail
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    public function __construct(public readonly int $userId) {}

    public function handle(): void
    {
        $user = User::findOrFail($this->userId);
        Mail::to($user)->send(new WelcomeEmail($user));   // takes 600ms
    }
}

// Controller:
public function register(Request $request)
{
    $user = User::create($request->validated());

    SendWelcomeEmail::dispatch($user->id);   // ← runs SYNCHRONOUSLY (no ShouldQueue!)

    return response()->json(['user' => $user]);
}

What happens:

  • dispatch() checks: does this class implement ShouldQueue? No.
  • Laravel: "OK, calling handle() immediately."
  • 600ms email send happens inside the HTTP request
  • User sees a 600ms+ register endpoint

Why this happens:

  • Job class scaffolded but implements ShouldQueue forgotten
  • Copy-pasted from a "Dispatchable" helper trait example
  • AI generated a class that looks like a job but isn't

Correct

// ✅ Implements ShouldQueue — actually queues

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 SendWelcomeEmail implements ShouldQueue   // ← critical
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    public function __construct(public readonly int $userId) {}

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

// Controller — same code, now actually async
SendWelcomeEmail::dispatch($user->id);

Sanity check during a code review

When you see Dispatchable + handle(), immediately scan for implements ShouldQueue. If it's missing, that's the bug.

The "dispatchSync intentionally" exception

Sometimes you genuinely want a job-style class to run sync — e.g., a complex orchestration you want to call from both controllers and queued contexts. Two acceptable patterns:

// ✅ Always sync — don't pretend to be a job
final class CalculateInvoiceTotals  // no Dispatchable, no ShouldQueue
{
    public function __invoke(Invoice $invoice): Money { /* ... */ }
}
// ✅ Sync OR queued, caller's choice — but the class IS a queued job
final class CalculateInvoiceTotals implements ShouldQueue { /* ... */ }

// To run sync from a controller:
CalculateInvoiceTotals::dispatchSync($invoice->id);

The bug is the third option — a class that looks like it queues but doesn't.

Detection

# Find Dispatchable classes missing ShouldQueue
for f in app/Jobs/*.php app/Jobs/**/*.php; do
  if grep -q 'use Dispatchable' "$f" && ! grep -q 'implements ShouldQueue\|implements .* ShouldQueue' "$f"; then
    echo "MISSING ShouldQueue: $f"
  fi
done

# PHPStan rule (custom): require classes in app/Jobs/ to implement ShouldQueue
# (file a custom rule in your phpstan.neon ignoreErrors → become an architectural constraint)

Reference: Laravel 13 — Queues: Creating Jobs

Source: SKILL.md on GitHub

No alerts16d3 checks · Risk SAFE
  • Gen Agent Trust Hub16d

    The analyzed skill contains high-quality reference guidelines and checklists for configuring and auditing Laravel 13 queue structures and background jobs. No security risks, malicious patterns, or vulnerabilities were identified.

  • Socket16d

    No alerts

  • Snyk16d

    Risk: LOW · No issues

Signed by skilld at 2631530. This ties the file your Agent reads to that commit on GitHub. It does not review the instructions.

Last checked against GitHub last month.

Steadyupdated 5 months ago
metadata
{
  "author": "agent-skills",
  "version": "1.0.0"
}

README badge

README badge for asyrafhussin/agent-skills/laravel-queues