d228a501dc
Задача 5: RunAutopodborStudyJob::handle() оборачивает существующее тело в try/finally — после ЛЮБОГО завершения прогона (done/empty/failed, включая проброшенное исключение) распорядитель AutopodborStudyScheduler::tick() берёт следующего кандидата с освободившейся дорожки шага 2. Задача 6: artisan autopodbor:study-tick — крон-страховка раз в минуту на случай, если дорожка освободилась не через завершение джобы. Без withoutOverlapping() — требует таблицу cache_locks, которой нет в схеме (см. комментарий в routes/console.php); overlap уже защищён внутренним Cache::lock в AutopodborStudyScheduler::tick().