Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Understanding Queues and Scheduler on Laravel 5.2

I am experimenting on how to write jobs on Laravel.

Following the Laravel documentation, I created a simple job that sends email using mail:queue.

I also added a cron job that will call the scheduler every minute which in turn will run the job every 5 minutes.

Everything works fine when I manually run the command queue:listen.

Later I added a print statement inside the scheduler and I found a strange issue.

Whenever I run the queue:listen from the terminal, I see the print message that is inside the schedule function and it gets printed every 5 seconds.

So my question is does queue:listen call the schedule function? If yes, why do we need to add schedule:run as a cron job?

The code that I used:

protected function schedule(Schedule $schedule){     
    error_log("inside scheduler");
    $schedule->call(function () {
        dispatch(new \App\Jobs\SendEmail);
    })->everyFiveMinutes();              
}

This is the command I ran on the terminal.

php artisan queue:listen

Output that I get (every 5 seconds)
inside scheduler
inside scheduler
inside scheduler ...

Can someone explain what is happening here?

-Adding the job code for better understanding
SendEmail.php

 public function handle() {
 //do some task here
 Mail::queue("emails.send_update", [], function($message) {
  $message->to("[email protected]");
  $message->subject('Status has been updated');
 });
 }
like image 300
Santhosh Shet Avatar asked Jan 06 '23 06:01

Santhosh Shet


1 Answers

Queues and scheduling are different things.

Queues You can set up a mail queue, that you run on the server. This is always listening. If you add an email to the mail queue, your queue function will execute the sending of the mail as soon as it can: it just does this on a different thread.

Scheduling This is a way in Laravel for organising cron jobs. Laravel suggests you setup one cron command on your server that executes every minute called schedule:run. In this command, Laravel then looks at the scheduling scripts you've setup and their conditions, and executes the appropriate ones for you when they need to be executed.

When it comes to your mail task: you should be adding the mail to the jobs queue, and leaving it like that. Don't involve scheduling. Then on your server you would just have the queue running with queue:listen: when a mail gets added to the queue, it will be sent immediately.

On your server also setup the cron command for any scheduling scripts (as described under scheduling: starting the scheduler), but you can then forget that the cron was ever setup. Then you can just create your own scheduling scripts to be executed at certain times and Laravel will work its magic for you.

Updated response: In your SendEmail.php function, you need to handle the task of a mail being sent: something like

public function handle(Mailer $mailer)
{
    $mailer->send('emails.reminder', ['user' => $this->user], function ($m) {
        //
    });
}

At the moment, every 5 minutes you're adding a new job to the queue, but your job is to queue the email message. So you're effectively continually queuing messages but never really executing them.

like image 151
Tom Avatar answered Mar 02 '23 22:03

Tom