4

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("someone@somedomain.com");
  $message->subject('Status has been updated');
 });
 }
Santhosh Shet
  • 97
  • 1
  • 3
  • 11
  • Have you get any solutions. And I also confused why the `schedule()` function is executed by the `queue:listen`. – LF00 Nov 30 '17 at 03:08

2 Answers2

10

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.

Tom
  • 1,068
  • 2
  • 25
  • 39
  • Hi Tom. I am actually doing what you have mentioned. The requirement is to have a job that does a particular task and then sends an email. It needs to run every 5 minutes. I also have setup cron jobs to call the scheduler as you mentioned. Everything works as described. The thing that I am not able to understand is since queue and scheduler different, why is queue:listen calling the schedule function? As you can see in my OP, the error_log prints the message every 5 secs. – Santhosh Shet Apr 15 '16 at 06:27
  • I don't know queue:listen execute the `schedule()` function in the question. – LF00 Nov 30 '17 at 03:07
0

The queue:listen will execute partly of 'schedule()' function in Kernel.php, which make it output contents periodically in your code. Change queue:listen to queue:work will solve this issue.

Refer this laravel cannot run scheduled command, while queue:listen run schedule() periodically and answer for more information.

LF00
  • 27,015
  • 29
  • 156
  • 295