Horizon lists pending, completed and failed jobs. A job released with a five-minute backoff is none of those,
so for five minutes it is nowhere in the dashboard. The same goes for anything dispatched with
delay() or later().
That gap shows up at the worst moment. A payment provider starts returning 503s, your webhook jobs release themselves with a backoff, and Horizon's pending count stays flat while hundreds of jobs sit waiting. You cannot see how many there are, when they will come back, or push one through once the provider has recovered.
A Retries page in Horizon's own sidebar
After composer require, a Retries link appears under Failed Jobs. The page lists
every job waiting in a queue's delayed set, with its queue, its attempt count and how long until a worker can
take it. Tabs split jobs released for a retry from jobs that were scheduled for later, and you can filter by
queue or job name.
Run now ends the wait early. The job goes onto the back of its ready queue, exactly as it
would when its backoff expired. The payload is not touched, so the job keeps its attempt count and its
retryUntil. You can select several jobs and run them together.
It reads the queue, so it cannot drift
Laravel already keeps delayed jobs in a Redis sorted set per queue, scored by the time each one becomes available. The page reads that set directly. There is no listener on dispatch, no extra table and nothing written on the worker path, which is why installing it cannot slow your jobs down.
Running a job early is a single Lua script. If two people press the button at once, or a worker migrates the job in the same instant, only one of them moves it. A job whose backoff expired while the page was open comes back as "no longer delayed" rather than a success that did nothing.
What it does not do
- It does not show why a job failed last time. That exception lives in Horizon's job record, so look the job id up in Horizon's own job view.
-
It only covers queues a Horizon supervisor processes, from the running supervisors and from
config/horizon.php. A queue nothing works on can be added by name in the config.
Horizon's dashboard is a compiled Vue bundle with no extension points, so the package splices its page into
Horizon's layout at three anchors. If a Horizon release changes one of them, that piece is skipped with a
warning and the rest of the dashboard keeps working. We wrote up
how the layout override works separately.
Set perform_now to false if you want the page read-only.
Every configuration key, and how to run the test suite, is in the README on GitHub. Bugs and questions go in its issues.