Introduction
In the past, whenever I needed a task to run on a web server, my go-to solution was a cron configuration entry.
However, as the number of scheduled tasks grows, managing cron entries across multiple servers can quickly become a burden.
Especially since you always have to connect to your server to manage your cron jobs separately from your application code.
Laravel Task Scheduling provides a centralized solution that allows you to configure your scheduling logic entirely within the application itself. Instead of defining each task separately as a cron job in the server’s configuration, you can define your scheduled tasks alongside the rest of your application code.
How does it work?
Schedules can be easily defined in your routes/console.php file.
For example, let’s say we would like to clean up all tickets that have been soft deleted for more than a month:
If you now type in the php artisan schedule:list command into your terminal you will get something like this:
This allows you to see all of your scheduled tasks, and when they are due.
However, Laravel still needs to be triggered periodically to check whether a scheduled task is due. To make this work, we only need to add a single cron entry to our server.
This will check your scheduled tasks every minute. Laravel will then execute any tasks that are due.
If your hosting provider allows long running processes an even cleaner approach would be to use php artisan schedule:work. This command starts a continuously running process that checks and executes tasks when due. Removing the need for any cron job.
Deeper dive into Tasks
In our initial example, we have already seen how to define closures in routes/console.php as a way of implementing scheduled tasks. However there are other possibilities, let’s take a deeper look.
Invokable Objects
Instead of defining the logic directly inside a closure, we can move it into an invokable class. This keeps our routes/console.php file clean.
Let’s implement this on our previous example:
Now, in our routes/console.php file we only need to add:
Artisan Commands
Additionally, you can also schedule Artisan commands.
Let’s say, for example, we want to soft delete all tickets that are stale for longer than 3 months.
First, let's create our command:
The command would look as follows:
In our routes/console.php file we only need to add:
Queued Jobs
Laravel also allows you to schedule queued jobs directly using Schedule::job().
For example, let's say we want to send reminders for tickets that have been stale for too long:
The Job contains the actual work:
Here we check all the tickets that have an open status and haven't beenupdated for two months. Once the scheduled task is due, the SendStaleTicketReminders job is dispatched to the queue. There a queue worker can pick up the job.
Difference between the Scheduler, Jobs and Queues
At this point, we have seen that Laravel's Scheduler can determine when a task should run. And we have also seen that a scheduled task can dispatch a queued job.
This leaves us with the question: where does the task end and the job begins? The easiest way to understand this is to look at the responsibility of each component.
The scheduler is responsible for determining when something should happen. It checks the schedule and executes the scheduled task once it is due. When the task is a queued job, Laravel dispatches the job to the queue.
With a queued job your application can accept the work without having to process everything immediately. The jobs are then stored in a queue until a worker can execute it. For this to work there has to be a queue worker available.