Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

mottinger's avatar

Filament notifications within a custom job are delayed

I have a custom job for further processing of records that I trigger upon the completion of the Filament Import Action's Import job. From a pure functionality perspective it's working as expected. But I'm trying to surface notifications via Filament to the user as the import completes and the custom processing begins. I place the notification at the start of my custom job's handle function like so:

$recipient = User::find($this->userId);
        
        Notification::make()
            ->title('Phase 2: Creating records from the staging data')
            ->body('Processing the staged MLC data to identify and create unique writer, work, and artist records. This step may take several minutes.')
            ->info()
            ->sendToDatabase($recipient);

// more processing

and at the end of the handle function a similar notification indicating the processing is complete. What happens though is I will see these notifications only when the entire process has completed and because they come all at once, their order is scrambled. I've looked through the Notification source code in Filament to spot any way to have these invoke. I think the answer is related to dedicating a separate queue for notifications separate from the custom job's queue, but I'm not sure how to do that. Any advice on how to accomplish this would be greatly appreciated.

0 likes
4 replies
Glukinho's avatar
Level 31

It seems you should handle your processing and notifications in different queues and have two separate queue workers for them, so they don't interfere with each other.

I haven't found how to change queue for Filament notifications, but you can go opposite way and change queue for your processing job:

// App/Jobs/ProcessingJob.php

public function __construct()
{
    $this->onQueue('processing');
}

You should have another running queue worker dedicated for processing:

php artisan queue:work --queue=processing

Another approach is to just add more 'default' workers, this seems bad to me; having separated queues/workers is more predictable.

mottinger's avatar

Thank you for the response. I'm still ramping up on the concepts of queues. This is what I was able to do to get this working with separate queues:

Dispatch to my custom job to a dedicated queue:

MLCStagingOrchestrator::dispatch($userId)->onQueue('staging');

Modify my queue listening process to look for that queue:

php artisan queue:listen --timeout=3600 --queue=default,staging

Now the notifications are appearing in the correct order and at the time they're supposed to during overall execution.

Thanks again!

Glukinho's avatar

Having one worker with two processed queues is still a bit wrong. This --queue=default,staging means that the worker will process 'default' jobs with higher priority than 'staging' jobs. At first glance, this is exactly what you need.

However, a worker is still only one, and this situation may occur: a worker has no 'default' jobs, so it takes long job from 'staging' queue. While this long job is processed, you need to send notification (which job appears in 'default' queue). In this case your notification will have to wait until long job is done, and only after that a worker will be able to dispatch new notification. You will face it immediately after your app's load grows a little.

So, I advice to have two independent workers:

  • one for 'default' queue (with quickly processed notifications)
  • second for 'staging' queue (with long processed jobs)
php artisan queue:work --timeout=3600 --queue=default
php artisan queue:work --timeout=3600 --queue=staging

In this case workers are totally independent and don't interfere each other, long and short jobs are processed independently, in parallel.

Also, please note that queue:listen should be used in development only. In production you should use queue:work as it is faster and less resource-demanding (though queue:listen doesn't need to restart after code changing).

1 like
mottinger's avatar

Amazing, thank you again. I saw this exact issue once I ran this importing workflow through a full load. The notifications for the beginning of the large job were stuck until it finished. I'll now make two wrapper scripts on a cron for each dedicated queue. And yes I am using queue:work on production, but didn't realize the performance improvements it has. Thanks again for the great queue advice!

Please or to participate in this conversation.