@alexsmirnovdotcom

Почему Laravel Schedule при задании интервала менее минуты скрипт пропускает минуту?

В новых версиях Laravel добавлена возможность повтора задач чаще чем раз в минуту.
При попытке запустить к примеру задачу которая выполняется через очередь и сделать повтор на каждые 10 секунд :
\App\Console\Kernel.php
protected function schedule(Schedule $schedule): void
    {
        Log::debug('SCHEDULE RUN');
        $schedule->job(new SyncChangesFrom1C)->everyTenSeconds();
    }

Все работает, но каждый раз пропускается минута.
Из логов Laravel:
[2023-12-25 08:22:01] local.DEBUG: SCHEDULE RUN
[2023-12-25 08:24:00] local.DEBUG: SCHEDULE RUN
[2023-12-25 08:26:00] local.DEBUG: SCHEDULE RUN
[2023-12-25 08:28:00] local.DEBUG: SCHEDULE RUN

Из логов Cron:

2023-12-25 08:26:00 Running [App\Jobs\OneC\SyncChangesFrom1C] .... 14ms DONE
2023-12-25 08:26:10 Running [App\Jobs\OneC\SyncChangesFrom1C] ..... 6ms DONE
2023-12-25 08:26:20 Running [App\Jobs\OneC\SyncChangesFrom1C] .... 10ms DONE
2023-12-25 08:26:30 Running [App\Jobs\OneC\SyncChangesFrom1C] ..... 5ms DONE
2023-12-25 08:26:41 Running [App\Jobs\OneC\SyncChangesFrom1C] ..... 3ms DONE
2023-12-25 08:26:51 Running [App\Jobs\OneC\SyncChangesFrom1C] .... 15ms DONE

2023-12-25 08:28:00 Running [App\Jobs\OneC\SyncChangesFrom1C] .... 39ms DONE
2023-12-25 08:28:10 Running [App\Jobs\OneC\SyncChangesFrom1C] ..... 3ms DONE
2023-12-25 08:28:21 Running [App\Jobs\OneC\SyncChangesFrom1C] ..... 2ms DONE
2023-12-25 08:28:31 Running [App\Jobs\OneC\SyncChangesFrom1C] ..... 2ms DONE
2023-12-25 08:28:41 Running [App\Jobs\OneC\SyncChangesFrom1C] ..... 5ms DONE
2023-12-25 08:28:51 Running [App\Jobs\OneC\SyncChangesFrom1C] ..... 2ms DONE

При этом если заменить на:
protected function schedule(Schedule $schedule): void
    {
        Log::debug('SCHEDULE RUN');
        $schedule->job(new SyncChangesFrom1C)->everyMinute();
    }


Все работает как надо.
Если судить по коду в ядре и документации, там простой бесконечный цикл в течение минуты...

Сам крон файл:
* * * * * php /var/www/api/artisan schedule:run >> /var/www/api/storage/logs/cron.log 2>&1

Всё работает в докере.
Указанный Job исполняется из очереди и если указать интервал >= минуте, скрипт выполняется как нужно.
В чём может быть причина того, что крон не запускает команду и пропускает минуту?

UPD: Создал issue в репозитории Laravel
  • Вопрос задан
  • 837 просмотров
Пригласить эксперта
Ответы на вопрос 2
nokimaro
@nokimaro
Меня невозможно остановить, если я смогу начать.
Можно самому реализовать то же самое, добавив бесконечный цикл внутрь обработчика
$schedule->job(new SyncChangesFrom1C)
    ->everyMinute()
    ->withoutOverlapping()
    ->runInBackground();


В обработчике внутри handle()
while(true) {

    //делаем работу

    sleep(10);
}

return 0;


p.s. В целях утечек памяти скрипт всё-же лучше переодически перезапускать. Хотя бы пару раз в день или через N-повторений.
Так же учтите что withoutOverlapping() по умолчанию ставит лок на 24 часа (на 1440 минут) и если скрипт крутится больше этого времени то будет запущен второй экземпляр.
Ответ написан
@vism
Вобщем в spatie/laravel-short-schedule тоже отказались люди от скрипта такого и делают так
Я вот задумался и тоже наверное проще отказаться и для пары джобов делать так
//Yes, we also decided not to use the package. We want to try use a task scheduling to run queue jobs with delay =)

//For example (command):

// run the job now
dispatch(new ExampleJob);

// and every 10 seconds this minute
for ($i = 1; $i <= 5; $i++ ) {
dispatch(new ExampleJob)->delay($i * 10);
}


А внутри джобы у меня unique интерфейс, чтоб не стакались они в случае чего
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы