Scout APM is PHP application performance monitoring designed for developers. With tracing logic that ties issues back to the line of code causing them, you can pinpoint n+1 queries, memory leaks, and other abnormalities in real time so you can knock them out and get back to building a great product. Start your free 14-day trial today and get the performance insight you need in less than 4 minutes.

A package to schedule Artisan commands at sub-minute frequencies

Original – by Freek Van der Herten – 3 minute read

Laravel's native scheduler allows you to schedule Artisan commands to run every minute. For a project I'm working on I needed to schedule a command to run every few seconds. I found a good solution to do this using an ReactPHP powered event loop. Because this solution could be helpful for others as well, I decided to package it up.

Using the laravel-short-schedule package, you can schedule artisan commands to run every second or even lower frequencies. In this blogpost I'd like to introduce the package.

Scheduling commands with sub-minute frequencies

If you need to execute something with a higher frequency, you should add method named shortSchedule to app\Console\Kernel and let it accept an instance of \Spatie\ShortSchedule\ShortSchedule. Inside this method you can schedule your commands. Here's an example:

// in app\Console\Kernel.php

protected function shortSchedule(\Spatie\ShortSchedule\ShortSchedule $shortSchedule)
{
    // this command will run every second
    $shortSchedule->command('artisan-command')->everySecond();
    
    // this command will run every 30 seconds
    $shortSchedule->command('another-artisan-command')->everySeconds(30);
    
    // this command will run every half a second
    $shortSchedule->command('another-artisan-command')->everySeconds(0.5);
}

In addition to Artisan commands, you can also schedule bash commands.

$shortSchedule->bash('any-bash-command')->everySecond();

By default, a scheduled command will run, even if the previous invocation is still running. You can prevent that by tacking on withoutOverlapping:

$shortSchedule->command('artisan-command')->everySecond()->withoutOverlapping();

You can also add some constraints. Here the artisan command will only be executed every second between 09:00 and 17:00.

$shortSchedule->command('artisan-command')->between('09:00', '17:00')->everySecond();

How the package works under the hood

The package uses a ReactPHP event loop to schedule commands. I have recorded a video where I explain in detail how the package works, and another video where I explain how it is tested. I'm pretty sure everyone can learn something from how the package is built.

These videos are part of the Laravel Package Training. The course will teach you how to create quality packages and contains source dives of a bunch of other packes too.

Another way seeing the videos is by becoming a sponsor of Spatie. Both videos are available on the video section at spatie.be.

Along with those two videos, I recorded a third one that shows how the package can be used. You can see that one here:

In closing

Do you want to know more about the package? Head over to the readme on GitHub. There are a few options available, that were not mentioned in this blogpost.

This package isn't the first one my team and have built. Take a look at this long list of packages we open released previously.

Stay up to date with all things Laravel, PHP, and JavaScript.

Follow me on Twitter. I regularly tweet out programming tips, and what I myself have learned in ongoing projects.

Every two weeks I send out a newsletter containing lots of interesting stuff for the modern PHP developer.

Expect quick tips & tricks, interesting tutorials, opinions and packages. Because I work with Laravel every day there is an emphasis on that framework.

Rest assured that I will only use your email address to send you the newsletter and will not use it for any other purposes.

Comments

Webmentions

Julio Serpone liked on 9th June 2020
Placebo Domingo retweeted on 8th June 2020
Davis David liked on 8th June 2020
Tomasz Plusikowski liked on 8th June 2020
Patrick Brouwers liked on 8th June 2020
Patrick Brouwers retweeted on 8th June 2020
Michael Brooks liked on 8th June 2020
Sadegh PM liked on 8th June 2020
ninjaparade replied on 8th June 2020
John Teague 🦝 liked on 8th June 2020
Amirul Naim liked on 8th June 2020
Faisal ahmed liked on 8th June 2020
WaveHack liked on 8th June 2020
Tom Witkowski liked on 8th June 2020
Tom Witkowski replied on 8th June 2020
Until now my approach was a before sleep() but it's definitely not as fancy/easy as this.
Zubair Mohsin liked on 8th June 2020
Ken V. liked on 8th June 2020
Marvin Collins Hosea retweeted on 8th June 2020
Jay Hughes liked on 8th June 2020
Ron Melkhior liked on 8th June 2020
Mattias Geniar retweeted on 8th June 2020
Muhammad Imran liked on 8th June 2020
Florian Voutzinos ⚡ liked on 8th June 2020
Freek Van der Herten replied on 8th June 2020
The loop itself takes almost no cpu/memory. It entirely depends on the commands you schedule.
Marvin Collins Hosea replied on 8th June 2020
Make sense. and what is the impact on server and application performance?
Freek Van der Herten replied on 8th June 2020
Using cron the lowest frequency you can use is a minute.
Marvin Collins Hosea replied on 8th June 2020
Would love to know why you didn't use laravel.com/docs/7.x/sched…?