Laravel schedule - hourly, daily - understanding when exactly start

Viewed 7998

Example from Laravel documentation:

protected function schedule(Schedule $schedule)
{
    $schedule->call(function () {
        DB::table('recent_users')->delete();
    })->daily();
}

Notice the daily function.

I can't figure out , how will it find out at what time to start? Will it always start at midnight or at random floating time?

I tried to read the source code:

/**
 * Schedule the event to run daily.
 *
 * @return $this
 */
public function daily()
{
    return $this->spliceIntoPosition(1, 0)
                ->spliceIntoPosition(2, 0);
}

So I checked spliceIntoPosition function:

    /**
 * Splice the given value into the given position of the expression.
 *
 * @param  int  $position
 * @param  string  $value
 * @return $this
 */
protected function spliceIntoPosition($position, $value)
{
    $segments = explode(' ', $this->expression);

    $segments[$position - 1] = $value;

    return $this->cron(implode(' ', $segments));
}

And eventually I got totally lost. Any ideas how it behaves?

2 Answers

Looking quickly it seems quite complicated, but in general in:

\Illuminate\Console\Scheduling\Event

class you have:

public $expression = '* * * * * *';

when running daily() method it's changed into:

public $expression = '0 0 * * * *';

Later when determining if this Event should be run, there is isDue() method in same class and it's finally calling:

CronExpression::factory($this->expression)->isDue($date->toDateTimeString())

In the same class CronExpression you have isDue() method which will finally run getRunDate() from same class and this method calculates time when this command should be run next time and finally it's compared to current time in line:

return $this->getNextRunDate($currentDate, 0, true)->getTimestamp() == $currentTime;

so answering your question for me it seems it will be run at exact minutes, so when you use for example every 5 minutes, it will be run at 1:00, 1:05, 1:10 and so on that's why you should have scheduler set to be running every single minute.

Laravel docs specifies exactly at what time it will run daily

daily();    // Run the task every day at midnight

Bassicaly after you add

* * * * * php /path-to-your-project/artisan schedule:run >> /dev/null 2>&1

to your crontab Laravel will call scheduler every minute and and at each call will evaluate your scheduled tasks and run the tasks that are due.

I recommend reading about cron and how rules works and this will give you the idea why function spliceIntoPosition() is called there and what it does.

Example cron tab records

* * * * * // will run every single minute
0 * * * * // will run every single hour at 30 [ 0:00, 1:00 ...] 
30 1 * * * // will run every single day at 1:30 [ Mon 1:30, Tue 1:30 ...] 

So for daily() after that spliceIntoPosition() calls we get:

"0 0 * * *" // which will be called at 0:00 every single day
Related