问题
My question is more of a general wondering. I have two commands created using Laravel, let's call them A and B.
Each one of these commands are scheduled with the ->dailyAt($par) method. But the $par parameter comes from a query.
I mean something like this:
protected function schedule(Schedule $schedule)
{
$schedulerTime_commandA = App\Model\CommandsTime::where('id', 1)->first()->time;
$schedulerTime_commandB = App\Model\CommandsTime::where('id', 2)->first()->time;
$schedule->command('A')
->dailyAt($schedulerTime_commandA);
$schedule->command('B')
->dailyAt($schedulerTime_commandB);
}
This is because the superuser wants to schedule the time when those commands will run. My question here is: How Laravel knows this schedule method within the App\Console\Kernel.php file has been changed?
NOTE: I have the following cron entry as Laravel talks about it on the docs.
* * * * * php /path/to/artisan schedule:run >> /dev/null 2>&1
回答1:
The way Laravel's scheduler system works is it uses a cron job that runs once every minute (that's the * * * * *
part in the cron entry: match every minute of every hour of every day of every month of every year).
So every minute, php /path/to/artisan schedule:run >> /dev/null 2>&1
is being run by cron.
When that command runs, it should check the schedule as defined by the schedule()
method in the Kernel class when it is run.
So technically, Laravel doesn't know that the schedule has changed, per se. Every minute it should run, hit the schedule()
method, which will grab the latest values from the database, and then return the schedule as it is set at that particular minute in time.
Each individual run of the cron knows nothing about the ones that came before it, or the ones that will come after it.
At least that's my understand of the scheduler. I've only spent a little time in the core Laravel Kernel code, but I believe that to what is going on from my own experience.
Hope that helps!
Edit 1
Just confirmed my logic in Laravel's code. Every time the cron script runs, the schedule is rebuilt, so the changes to the schedule in the database will be used the next time the cron entry runs. Laravel doesn't really know that it changed - it just checks every time it runs and uses what it finds.
Specifically, here's the chain through code if it's of interest:
- Calling
php artisan
on the command line will run the artisan file in the project root; - In the artisan file the Application is bootstrapped and a Kernel object is initialized;
- When the Kernel class is initialized, the constructor for the Kernel class (Laravel\Lumen\Console\Kernel) calls the
defineConsoleSchedule()
method on itself; - The
defineConsoleSchedule()
method initializes a blank Schedule object (Illuminate\Console\Scheduling\Schedule); - The blank Schedule object will be passed to the
schedule()
method on the Kernel class; and finally - In the
schedule()
method, which is where you defined your command schedule, your two DB queries will be run, and your two schedule entries will be defined with the values that the DB returns at that moment.
The above actions happen every time the console application bootstraps, which means on every call to php artisan
, regardless of what command you wish to run.
When running the schedule:run command specifically, here's what happens next:
- After the application bootstraps, the ScheduleRunCommand object (Illuminate\Console\Scheduling\ScheduleRuneCommand) is initialized; and
- The
fire()
method is called on the ScheduleRunCommand object, which runs through all the commands defined on the Schedule object when the application bootstrapped; and - Checks each command to see if that command must be run at that time by calling the
isDue()
method on the Event (Illuminate\Console\Scheduling\Event) that represents the command; and finally - Each command that needs to be run at that minute, by returning
true
fromisDue()
will be run.
来源:https://stackoverflow.com/questions/36093287/how-laravel-knows-when-the-scheduler-has-been-updated