skip to Main Content

What I would like to do is dispatch a Job, and then continuing to dispatch the same Job after the previous one was finished so there is a continuous loop of the Job being dispatched. As indicated under option one this was previously working with the database queue driver.

I use Redis now so I can more easily monitor my jobs via Horizon.

To start the first job I use a custom artisan command, but this could as well be from within a controller, it’s just the first dispatch.

My config/horizon (local config is the same as production):

'production' => [
            'supervisor-1' => [
                'connection' => 'redis',
                'queue' => ['arbitrage'],
                'balance' => 'auto',
                'processes' => 2,
                'tries' => 1,
            ],
            'supervisor-2' => [
                'connection' => 'redis',
                'queue' => ['trade'],
                'balance' => 'auto',
                'processes' => 4,
                'tries' => 1,
            ],
            'supervisor-3' => [
                'connection' => 'redis',
                'queue' => ['balance', 'trade_meta'],
                'balance' => 'auto',
                'processes' => 5,
                'tries' => 1,
            ],
            'supervisor-4' => [
                'connection' => 'redis',
                'queue' => ['notifications'],
                'balance' => 'auto',
                'processes' => 2,
                'tries' => 1,
            ],
        ],

Option 1: dispatch a new job at the end of the job

At the end of this Job’s handle() I re-dispatch it so that it runs continuously.

This actually worked fine (the process ran for weeks on end) when using the database driver.

Job:

class ArbitrageJob implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    public $tries = 1;
    public $timeout = 30;

    // Process things here

    ArbitrageJob::dispatch()->onQueue('arbitrage');
}

Option 2: dispatch a new job with Queue:after

Job:

class ArbitrageJob implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    public $tries = 1;
    public $timeout = 30;
}

Then in AppServiceProvider:

Queue::after(function (JobProcessed $event) {
        ProcessArbitrage::dispatch()->onQueue('arbitrage');
});

What I see happening now, for both options, is that for every time it runs, it’s racking up memory (I log this via memory_get_usage(true)).

The first run it’s 28MB, the next one it’s 32MB, and it keeps increasing until it’s around 122MB and then I get the following error: IlluminateQueueMaxAttemptsExceededException: AppJobsArbitrageJob has been attempted too many times or run too long. The job may have previously timed out.

Probably related: in config/horizon I’ve set memory_limit to 768MB but it looks like it fails a lot earlier than that. Or is that because it limits the memory to 128MB per worker?

2

Answers


  1. Chosen as BEST ANSWER

    The problem was resolved after restarting my computer. Not sure why, because I did run the commands below. I'm now using option 1 and everything works fine.

    php artisan config:cache
    php artisan cache:clear
    php artisan queue:restart
    

  2. You gather jobs on each other so all jobs exist behind each other so its clear that your memory should racks up.

    You should use switches when use php artisan queue:work . I suggest that test it:

    php artisan queue:work –once
    try other switches too that can work just last works.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search