Планирани задачи - Laravel

uphero

Registered
Нов съм с Ларавел да уточня първо.
Имам 10 * 4 задачи които трябва веднъж на ден да се изпълняват.
Имат и последователност - първо минава задача 1 и после останалите 3 и така 10 пъти. Проблема, че тия 3 задачи отнемат по 1-2-3 минути и не знам как ще се справи с това ларвела.
Иска ми се да го направя по логиката на ларавел, как да ги подредя?
 
Има ли причина тези задачи да се пускат поотделно след като трябва да са последователно? Защо не събереш задачите да рънват като една? Така или иначе като се пускат като фонови задачи, не те интересува кога ще свършат.

Иначе може да погледнеш Task Hooks https://laravel.com/docs/10.x/scheduling#task-hooks

Или събития https://laravel.com/docs/10.x/scheduling#events . В този случай дадена задача ще тръгва само, ако друга е изпратила събитие, че е приключила.

Не използвам Ларавел, така че някой, който ползва може да има по-добър вариант.
 
Нов съм с Ларавел да уточня първо.
Имам 10 * 4 задачи които трябва веднъж на ден да се изпълняват.
Имат и последователност - първо минава задача 1 и после останалите 3 и така 10 пъти. Проблема, че тия 3 задачи отнемат по 1-2-3 минути и не знам как ще се справи с това ларвела.
Иска ми се да го направя по логиката на ларавел, как да ги подредя?
Laravel ще се справи повече от прекрасно с проблема ти. Ако са веднъж на ден можеш сам да си ги наредиш коя кога да се изпълни с метод dailyAt() . Във App\Console\Kerenl правиш нещо от този сорт:
PHP:
$schedule->command('system:command-1')
            ->dailyAt('06:30')
            ->withoutOverlapping()
            ->runInBackground()
            ->description('Command 1');
$schedule->command('system:command-2')
            ->dailyAt('06:35')
            ->withoutOverlapping()
            ->runInBackground()
            ->description('Command 2');

Ако използваш queue там е малко по-неудобно решаването на твоя проблем но също има варианти. Принципно ако ще го правиш със задачи не с kernel->schedule() е хубаво да си настроиш в config/queue.php времената за 'retry_after' и да ги вдигнеш на повече от стандартните 90 секунди.
 
Laravel ще се справи повече от прекрасно с проблема ти. Ако са веднъж на ден можеш сам да си ги наредиш коя кога да се изпълни с метод dailyAt() . Във App\Console\Kerenl правиш нещо от този сорт:
PHP:
$schedule->command('system:command-1')
            ->dailyAt('06:30')
            ->withoutOverlapping()
            ->runInBackground()
            ->description('Command 1');
$schedule->command('system:command-2')
            ->dailyAt('06:35')
            ->withoutOverlapping()
            ->runInBackground()
            ->description('Command 2');

Ако използваш queue там е малко по-неудобно решаването на твоя проблем но също има варианти. Принципно ако ще го правиш със задачи не с kernel->schedule() е хубаво да си настроиш в config/queue.php времената за 'retry_after' и да ги вдигнеш на повече от стандартните 90 секунди.
withoutOverlapping() не е ли да не overlap-ва същия таск? Според мен следващия ще си тръгне независимо дали първия е приключил.
И в този случай извикването на този метод е ненужно, освен ако задачата не върви за повече от 24ч.

The withoutOverlapping method is especially useful if you have tasks that vary drastically in their execution time, preventing you from predicting exactly how long a given task will take.
Което се отнася за един и същи таск.

Ако няма причина задачите да са разделени (няма да има случай, в който ще се изпълняват индивидуално по една или друга причина), то аз бих ги събрал в една задача. Нареждането им една след друга по време не е правилен подход, защото не е гарантирано, че дадена задача няма да се забави. Може базата данни да е бавна от натоварване или нещо друго. Никога не можеш да предвидиш колко време е нужно на една задача.

В такъв случай за спазване на последователност се използват или събития, или флагове (създаване и махане на файл, който дадена задача проверява - ако съществува, предната задача все още върви - това в повечето случаи се ползва за предотвратяване една задача да overlap-не, което вече е покрито в Ларавел), или просто една задача, която да си свърши всичко.
 
withoutOverlapping() не е ли да не overlap-ва същия таск? Според мен следващия ще си тръгне независимо дали първия е приключил.
И в този случай извикването на този метод е ненужно, освен ако задачата не върви за повече от 24ч.


Което се отнася за един и същи таск.

Ако няма причина задачите да са разделени (няма да има случай, в който ще се изпълняват индивидуално по една или друга причина), то аз бих ги събрал в една задача. Нареждането им една след друга по време не е правилен подход, защото не е гарантирано, че дадена задача няма да се забави. Може базата данни да е бавна от натоварване или нещо друго. Никога не можеш да предвидиш колко време е нужно на една задача.

В такъв случай за спазване на последователност се използват или събития, или флагове (създаване и махане на файл, който дадена задача проверява - ако съществува, предната задача все още върви - това в повечето случаи се ползва за предотвратяване една задача да overlap-не, което вече е покрито в Ларавел), или просто една задача, която да си свърши всичко.
withoutOverlapping - Не позволява на същата задача да се преизвика в следваща итерация без да е приключила предходното изпълнение. Иначе за последователността съм съгласен, задачите е добре да се обединят в една. От описанието на проблема, ако е необходимо бързо решение моето е и най-просто. Щом е веднъж дневно си реди задачите една след друга през примерно 5 минутки и ще решава казуса генерално друг ден. При ползването на hooks има няколко особености, които трябва да се взимат под внимание и реално гледам да ги избягвам.
По принцип ако може задачата да се изпълни, като една е най-сигурно, но ако трябва да сработи бързо и да може да се настройва моят вариант е достатъчно сигурен при коректен тайминг.
 
withoutOverlapping - Не позволява на същата задача да се преизвика в следваща итерация без да е приключила предходното изпълнение. Иначе за последователността съм съгласен, задачите е добре да се обединят в една. От описанието на проблема, ако е необходимо бързо решение моето е и най-просто. Щом е веднъж дневно си реди задачите една след друга през примерно 5 минутки и ще решава казуса генерално друг ден. При ползването на hooks има няколко особености, които трябва да се взимат под внимание и реално гледам да ги избягвам.
По принцип ако може задачата да се изпълни, като една е най-сигурно, но ако трябва да сработи бързо и да може да се настройва моят вариант е достатъчно сигурен при коректен тайминг.
Всъщност като прочетох по-добре документацията, то изглежда, че всички таскове просто трябва да ги нареди в каквато поредност му трябват и да ги зададе да тръгват по едно и също време.

By default, multiple tasks scheduled at the same time will execute sequentially based on the order they are defined in your schedule method. If you have long-running tasks, this may cause subsequent tasks to start much later than anticipated.
https://laravel.com/docs/10.x/scheduling#background-tasks

Така че това изцяло му решава проблема. Не му е нужно да мисли след колко време да тръгне следващия таск.
 
Всъщност като прочетох по-добре документацията, то изглежда, че всички таскове просто трябва да ги нареди в каквато поредност му трябват и да ги зададе да тръгват по едно и също време.


https://laravel.com/docs/10.x/scheduling#background-tasks

Така че това изцяло му решава проблема. Не му е нужно да мисли след колко време да тръгне следващия таск.
Принципно е така, но има също условност от към резултатите. Ако първата задача трябва да е минала за да има някакви резултати за втората задача, то реално трябва да даде час и минути забавяне за да има какво втората задача да обработва.

runInBackground() -> позволява да не се изчаква последователността и отговорите на тасковете (да мине първата, после втората и прочие). Тоест ако един процес тръгне в 11:00 всичките таскове тръгват да вървят успоредно и който мине мине, защото следващата итерация е в 11:01. Идеята е да се ползва в комбинация с овърлап защита, за да не се преизвиква, но и да не се чакат тежки операции да минат преди по-леки, а да тръгнат почти успоредно.

Ако не се ползва runInBackground() на практика редиш 5 планирани задачи и в следващата изпълнителна итерация на практика половината задачи може да не са започнали, да се изпълняват от предходната итерация (чакат някоя тежка задача да върне мине по-средата на метода schedule()), а ние минаваме и стартираме още веднъж.
 

Back
Горе