Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can i use scheduler in seconds manner in Laravel 5.#

there i am trying to schedule some task in larave, but i find it hard to schedule my task in every 20 seconds. Checking laravel doc. for laravel schedular, it didn't have such method for seconds. While there is ->cron('* * * * * *') "Run the task on a custom Cron schedule", but it also couldn't solve my problem.

Below is my code in kernal.php file for scheduling.

protected function schedule(Schedule $schedule)
{ 
    // need to replace everyMinute() by some other method which can run it every 20 sec

    $schedule->call('path\to\controller@method)->everyMinute();

   // also tried cron() but didn't workout.
    $schedule->call('path\to\controller@method)->cron(*/20 * * * * *);
}    

Thanks.

like image 523
shakir Avatar asked Oct 12 '17 04:10

shakir


People also ask

How do I run a cron job every second?

It's not possible to run cron in every second but we can run cron in every second using this method, we use a sleep command before the echo date. Cron - Cron is command name that runs scheduled action using the crond daemon.

How do I schedule a cron job every 5 minutes?

basic 3. /usr/bin/vim. tiny 4. /bin/ed Choose 1-4 [1]: Make a new line at the bottom of this file and insert the following code. Of course, replace our example script with the command or script you wish to execute, but keep the */5 * * * * part as that is what tells cron to execute our job every 5 minutes.


2 Answers

There's no method that will do this for you out of the box, however there are a few suggestions of people who have been in the same situation as you already.

->cron(*/20 * * * * *) is actually saying run this every 20 minutes, not every 20 seconds. Given that cron doesn't go down to a sub-minute resolution this is probably why Laravel doesn't support it either.

If this really needs to run more than every 30 seconds then I would go for a combination of the two here: Laravel 5 schedule job every 30 seconds and Laravel schedular: execute a command every second

That is to say, you should still call your command every minute, but add the withoutOverlapping() method just to be safe.

Then inside your command you can run your code, sleep for 20 seconds, run it again, sleep for 20 seconds, and then run it again. This obviously works on the premise that your code is almost instantaneous to run. For example, if your code takes 5 seconds to run and then you sleep for 20 seconds and then run it again - your code is actually running every 25 seconds.

I imagine you have a fairly good idea of how long this code takes to run. If not, time it manually whilst running the artisan command to get an idea - something like this might help date && php artisan your:command && date. This will output the date in your shell, run the command then output the date again - this includes the time which you can use to see how many seconds it takes to run.

This will require you to either refactor the controller action out to a command or add the sleep() code to your controller action. The docs for artisan commands should help here.

I would suggest refactoring this into a command, but it's up to you.

//Console command
public function handle()
{
    \App\Investment::calculate(); //takes 2 seconds to run
    sleep(18); //sleep for 18 seconds to ensure we are only running the command every 20 seconds
    \App\Investment::calculate(); //takes 2 seconds to run
    sleep(18);
    \App\Investment::calculate(); //takes 2 seconds to run
}


//The console scheduler - Kernel.php  
protected function schedule(Schedule $schedule)
{     
    $schedule->call('path\to\controller@method)->everyMinute()->withoutOverlapping();
}   
like image 144
James Avatar answered Sep 24 '22 15:09

James


The thing is we can't handle scheduler on seconds basis but we can customize the closer of schedule() method by calling our method number of times based on how much time it takes to execute e.g:

    $obj = new ClassName();

    $schedule->call(function () use ($obj) {

            sleep(3);
        //call method calculate time it takes and based on that we can call method number of methods we want 
            $obj->method(); //call method
            sleep(3);       // pause of 3 seconds
            $obj->method(); //call again
            sleep(3);
            $obj->method(); //call again
            sleep(3);

    })->everyMinute();

Here i was able to call my method three times in one minute based on how time it takes to execute. Thanks i got my work done.

like image 38
shakir Avatar answered Sep 26 '22 15:09

shakir