phplaravelschedulerlaravel-scheduler

Laravel scheduler chain process calls


I have several processes that I want to chain using the laravel scheduler.

<?php

namespace App\Process;

use App\Loggers\Logger;

class UtilsProcess
{
    public function test1()
    {
        Logger::info("Launch 'UtilsProcess::test1' process");
        sleep(5);
        Logger::info("Process 'UtilsProcess::test1' succeedeed");
    }
    public function test2()
    {
        Logger::info("Launch 'UtilsProcess::test2' process");
        sleep(20);
        Logger::info("Process 'UtilsProcess::test2' succeedeed");
    }
    public function test3()
    {
        Logger::info("Launch 'UtilsProcess::test3' process");
        sleep(10);
        Logger::info("Process 'UtilsProcess::test3' succeedeed");
    }
}

I tried to reproduce this, in order to have test2 running once test1 is finished and test3 after test2 is finished.

protected function schedule(Schedule $schedule)
{
    $schedule->call('App\Process\UtilsProcess@test1')->everyMinute()->name("test1")
        ->then(function(){
            $this->call("App\Process\UtilsProcess@test2")->name("test2");
            $this->call("App\Process\UtilsProcess@test3")->name("test3");
        }
    );
}

However after test1 is finished, I'm facing the following error

[2023-06-30 07:32:48] local.INFO: Launch 'UtilsProcess::test1' process  
[2023-06-30 07:32:53] local.INFO: Process 'UtilsProcess::test1' succeedeed
[2023-06-30 07:32:53] local.ERROR: The command "AppProcessUtilsProcess@test2" does not exist.

I tried several solutions but I can't find a way to have the test2 function being called within the Closure callback.


Solution

  • I had to define test2 and test3 as commands by creating a file for each under App\Console\Commands as follow

    // File \App\Console\Commands\test2.php
    
    <?php
    
    namespace App\Console\Commands;
    
    use App\Process\UtilsProcess;
    use Illuminate\Console\Command;
    
    class test2 extends Command
    {
        /**
         * The name and signature of the console command.
         *
         * @var string
         */
        protected $signature = 'test2';
    
        /**
         * The console command description.
         *
         * @var string
         */
        protected $description = 'Test 2';
    
        /**
         * Create a new command instance.
         *
         * @return void
         */
        public function __construct()
        {
            parent::__construct();
        }
    
        /**
         * Execute the console command.
         *
         * @return int
         */
        public function handle()
        {
            $utils = new UtilsProcess();
            $utils->test2();
        }
    }
    

    And then call the commands from \App\Console\Kernel.php as follow

    protected function schedule(Schedule $schedule)
    {
        $schedule->call('App\Process\UtilsProcess@test1')->everyMinute()->name("test1")
            ->then(function(){
                $this->call("test2")->name("test2");
                $this->call("test3")->name("test3");
            }
        );
    }
    

    I would have preferred to directly call the class method from within then function but couldn't find any way to do it