2020-04-05 11:29:46 +00:00
|
|
|
|
# scheduler
|
|
|
|
|
|
|
|
|
|
Пакет `scheduler` реализует планировщик системы. `scheduler.Scheduler` хранит полное состояние кластера
|
|
|
|
|
и принимает решение на каком воркере и какой джоб нужно запустить.
|
|
|
|
|
|
|
|
|
|
Шедулер является точкой координации между воркерами и билдами. Бегущие билды обращаются к шедулеру,
|
|
|
|
|
передавая джобы в функцию `ScheduleJob`. Воркеры забирают джобы из шедулера вызывая функцию `PickJob`.
|
|
|
|
|
|
|
|
|
|
Вы можете отложить реализацию полной версии шедулера на последний шаг, и реализовать упрощённую версию
|
|
|
|
|
на одном глобальном канале. Такой реализации будет достаточно, чтобы работали все интеграционные тесты с одним
|
|
|
|
|
воркером.
|
|
|
|
|
|
|
|
|
|
## Алгоритм планирования
|
|
|
|
|
|
|
|
|
|
Планировщик поддерживает множество очередей:
|
|
|
|
|
1. Одна глобальная очередь
|
|
|
|
|
2. По две локальные очереди на воркер.
|
|
|
|
|
|
|
|
|
|
При запросе нового джоба воркер выбирает случайную джобу из трех очередей - глобальной, и двух локальных относящихся
|
|
|
|
|
к этому воркеру. Случайная очередь выбирается одним вызовом `select {}`.
|
|
|
|
|
|
|
|
|
|
Ожидающий исполнения джоб всегда находится в первой локальной очереди воркеров, на которых есть
|
|
|
|
|
результаты работы этого джоба.
|
|
|
|
|
|
2020-04-05 15:19:59 +00:00
|
|
|
|
Если джоб ждёт выполнения дольше `CacheTimeout` или если в момент `SchedulerJob` джоба не было в кеше ни на одном
|
|
|
|
|
из воркеров, то он попадает во все вторые локальные очереди воркеров, на которых есть хотя бы один артефакт
|
2020-04-05 11:29:46 +00:00
|
|
|
|
из множества зависимостей этого джоба.
|
|
|
|
|
|
|
|
|
|
Определения первой и второй локальной очереди не зависят от того, в каком порядке в шедулер пришли джобы
|
2020-04-05 15:19:59 +00:00
|
|
|
|
и информация о кеше артефактов. То есть, если джоб уже находится в глобальной очереди, и в этот момент приходит
|
|
|
|
|
информация, что этот джоб находится в кеше на воркере `W0`, то джоб должен быть добавлен
|
2020-04-05 11:29:46 +00:00
|
|
|
|
в первую локальную очередь `W0`.
|
|
|
|
|
|
|
|
|
|
Если джоб ждёт выполнения дольше `DepTimeout`, то он помещается в глобальную очередь.
|
|
|
|
|
|
|
|
|
|
## Тестирование
|
|
|
|
|
|
|
|
|
|
Вместо реального времени, юниттесты шедулера используют библиотеку `clockwork`. Это накладывает ограничения
|
|
|
|
|
на детали вашей реализации. Ожидание `CacheTimeout` и `DepTimeout` должно быть реализовано как `select {}` на
|
|
|
|
|
канале, который вернула функция `timeAfter`. Мы считаем что `CacheTimeout > DepTimeout`, и ожидание этих
|
|
|
|
|
таймаутов происходит последовательно в одной горутине.
|