Removing Failed Jobs in Laravel Horizon

Removing Failed Jobs in Laravel Horizon, how is that done really? First you will notice you can restart jobs, but you cannot remove them. And if you had quite a few failed jobs like me during your testing you would want to get rid off them like me.

Flushing Horizon Queues

You can do this by flushing the queues from the command line. That is how it should work anyways. I Did a:

php artisan queue:flush

as suggested, but in my case things did not work out right away.

Table ‘forge.failed_jobs’ doesn’t exist

What I saw was an error:

Base table or view not found: 1146 Table 'forge.failed_jobs' doesn't exist (SQL: delete from `failed_jobs`)

It stated that the table failed jobs did not exist yet.

Failed Jobs Setup

Well, I decided to  check how this was setup. So I opened:

config/queue.php

to check for the failed jobs setup. We had a default setup:

/*
    |--------------------------------------------------------------------------
    | Failed Queue Jobs
    |--------------------------------------------------------------------------
    |
    | These options configure the behavior of failed queue job logging so you
    | can control which database and table are used to store the jobs that
    | have failed. You may change them to any database / table you wish.
    |
    */

    'failed' => [
        'database' => env('DB_CONNECTION', 'mysql'),
        'table' => 'failed_jobs',
    ],

];

And so we had not set up a failed jobs queue as of yet. The migration of that table was not done.

Current Failed Jobs Location

But like me you will be asking yourself. Where are the current failed jobs stored then?

when I checked the .env we had this default block

BROADCAST_DRIVER=log
CACHE_DRIVER=file
SESSION_DRIVER=file
QUEUE_DRIVER=redis

So the queue driver setup for us was redis. Only failed jobs were not set up for using Redis in app/config. Then I checked redis:

redis-cli
<127.0.0.1:6379> INFO keyspace
# Keyspace
db0:keys=20,expires=15,avg_ttl=361086240

So there were 20 key value blocks. Now let’s see keys stored

127.0.0.1:6379> KEYS *
 1) "horizon:5"
 2) "horizon:9"
 3) "horizon:3"
 4) "horizon:12"
 5) "horizon:7"
 6) "horizon:job_id"
 7) "horizon:1"
 8) "horizon:supervisors"
 9) "horizon:8"
10) "horizon:10"
11) "horizon:failed_jobs"
12) "horizon:6"
13) "horizon:monitor:time-to-clear"
14) "horizon:supervisor:xxx-prod-w-1-ZFbL:supervisor-1"
15) "horizon:last_snapshot_at"
16) "horizon:2"
17) "horizon:11"
18) "horizon:4"
19) "horizon:master:xxx-prod-w-1-ZFbL"
20) "horizon:masters"

I understood that scan is better though so for the same result use

redis-cli --scan --pattern '*'

Key eleven showed the failed_jobs. Now to list its content you first need to check its type:

 type "horizon:failed_jobs"
zset

It is a zset. To list there values I did:

zrange  horizon:failed_jobs 0 -1 withscores
 1) "12"
 2) "-1532314417.1113"
 3) "11"
 4) "-1532254375.6877"
 5) "10"
 6) "-1532224555.5265999"
 7) "9"
 8) "-1532153045.0869"
 9) "8"
10) "-1532152135.5623"
11) "7"
12) "-1532152078.1642001"
13) "6"
14) "-1532148754.2614999"
15) "5"
16) "-1532148589.0857"
17) "4"
18) "-1532148378.8659999"
19) "3"
20) "-1532147918.7011001"
21) "2"
22) "-1532147879.5788"
23) "1"
24) "-1531992162.2793"

To be continued …

Failed Jobs Table Migration

If you do want to set up this table in your MariaDB or MySQL database then you must create the migration* :

php artisan queue:failed-table

And finally run the migrations:

php artisan migrate

*source mingalevme at laravel.io at this thread.

That should do the trick.

Driver Change

If you however just want to continue using redis, also for failed jobs as you may have like us you will probably need to change the driver. More information on that will follow.

Medis & Command Line

Thanks to Stef I found a way to more easily remove keys with Medis and using the command line though:

Stef Blokdijk mentioned at https://github.com/laravel/horizon/issues/122#issuecomment-412394779 that you can use Medis to remove the keys as well. It is a Redis GUI Tool. He also mentioned some manual option he found on SO to remove failed jobs:

I manually deleted the horizon:failed_jobs key.
Then I deleted all the other failed jobs with this Redis CLI command. (source: stackoverflow)

EVAL "return redis.call('del', unpack(redis.call('keys', ARGV[1])))" 0 horizon:failed:*

 

Tagged in : Tagged in : ,
Jasper Frumau

Jasper has been working with web frameworks and applications such as Laravel, Magento and his favorite CMS WordPress including Roots Trellis and Sage for more than a decade. He helps customers with web design and online marketing. Services provided are web design, ecommerce, SEO, content marketing. When Jasper is not coding, marketing a website, reading about the web or dreaming the internet of things he plays with his son, travels or run a few blocks.