crunzphp / crunz

A PHP-based job scheduler
MIT License
176 stars 16 forks source link

Multiple Schedule objects from one task-file #53

Open gennadiylitvinyuk opened 1 year ago

gennadiylitvinyuk commented 1 year ago

Description
It would be very helpful to have a possibility to return multiple different Schedule objects from one task-file. One possible usage scenario is external schedule source for Schedules.

Possible implementations are simple array or a Schedule-collection object.

Example

use Crunz\Schedule;
//...
$schedules = []; //  new ScheduleArrayObject();
forearch ($externalDefinitions as $definition) {
  $schedule = new Schedule();
  // configure $schedule
  // ...

  $schedules[] = $schedule;
}

return $schedules;
PabloKowalczyk commented 1 year ago

Hello, You can do it already, but with multiple events:

$commands = [
    [
        'command' => 'php -v',
        'cron' => '* * * * *',
    ],
    [
        'command' => 'php -v',
        'cron' => '* * * * *',
    ],
];

$schedule = new Schedule();
foreach ($commands as $command) {
    $task = $schedule->run($command['command']);
    $task->cron($command['cron']);
}

return $schedule;
ivankuraev commented 6 months ago

Hello, You can do it already, but with multiple events:

$commands = [
    [
        'command' => 'php -v',
        'cron' => '* * * * *',
    ],
    [
        'command' => 'php -v',
        'cron' => '* * * * *',
    ],
];

$schedule = new Schedule();
foreach ($commands as $command) {
    $task = $schedule->run($command['command']);
    $task->cron($command['cron']);
}

return $schedule;

Hello. This doesn't work with preventOverlapping(). Only the first event is executed.

PabloKowalczyk commented 6 months ago

@ivankuraev could You post some code to reproduce?

ivankuraev commented 6 months ago
$schedule = new Schedule();

$onDemandTasks = Tasks::instance()->getActive('ondemand');
foreach ($onDemandTasks as $onDemandTask) {
    $task = $schedule->run(function() use ($onDemandTask) {
        switch ($onDemandTask->command) {
            case 'cmd1':
                ToolsOne::instance()->run();
                break;
            case 'cmd2':
                ToolsTwo::instance()->run();
                break;
            // .....
        }
    });

    $task
        ->everyMinute()
        ->description($onDemandTask->title)
        ->preventOverlapping()
        ->appendOutputTo(sprintf('logs/ondemand_%s.log', $onDemandTask->command))
        ->after(function() use ($onDemandTask) {
            Tasks::instance()->toggleActiveStatus($onDemandTask->id);
        })
    ;
}

return $schedule;

It's a little problematic to give complete working code to run it. There are tasks that can be launched periodically. If we have, for example, 3 tasks to run. When using preventOverlapping(), only one task is performed. If you don't specify preventOverlapping(), all three are executed simultaneously.

PabloKowalczyk commented 6 months ago

It happens because both commands generate same hash for preventOverlapping, try not using closure.