shad-go/distbuild/pkg/scheduler
2020-04-05 16:24:48 +03:00
..
export_test.go Finish pkg/scheduler 2020-04-05 14:29:46 +03:00
README.md Finish pkg/scheduler 2020-04-05 14:29:46 +03:00
scheduler.go Place build tags 2020-04-05 16:24:48 +03:00
scheduler_test.go Finish pkg/scheduler 2020-04-05 14:29:46 +03:00

scheduler

Пакет scheduler реализует планировщик системы. scheduler.Scheduler хранит полное состояние кластера и принимает решение на каком воркере и какой джоб нужно запустить.

Шедулер является точкой координации между воркерами и билдами. Бегущие билды обращаются к шедулеру, передавая джобы в функцию ScheduleJob. Воркеры забирают джобы из шедулера вызывая функцию PickJob.

Вы можете отложить реализацию полной версии шедулера на последний шаг, и реализовать упрощённую версию на одном глобальном канале. Такой реализации будет достаточно, чтобы работали все интеграционные тесты с одним воркером.

Алгоритм планирования

Планировщик поддерживает множество очередей:

  1. Одна глобальная очередь
  2. По две локальные очереди на воркер.

При запросе нового джоба воркер выбирает случайную джобу из трех очередей - глобальной, и двух локальных относящихся к этому воркеру. Случайная очередь выбирается одним вызовом select {}.

Ожидающий исполнения джоб всегда находится в первой локальной очереди воркеров, на которых есть результаты работы этого джоба.

Если джоб ждёт выполнения дольше CacheTimeout или если в момент SchedulerJob джоба небыло в кеше ни на одном из воркеров, то он находится во всех вторых локальных очередях воркеров, на которых есть хотябы один артефакт из множества зависимостей этого джоба.

Определения первой и второй локальной очереди не зависят от того, в каком порядке в шедулер пришли джобы и информация о кеше артефактов. Тоесть, если джоб уже находится в глобальной очереди, и в этот момент приходит информация, что этот джоб находится в кеше на W0, то джоб должен быть добавлен в первую локальную очередь W0.

Если джоб ждёт выполнения дольше DepTimeout, то он помещается в глобальную очередь.

Тестирование

Вместо реального времени, юниттесты шедулера используют библиотеку clockwork. Это накладывает ограничения на детали вашей реализации. Ожидание CacheTimeout и DepTimeout должно быть реализовано как select {} на канале, который вернула функция timeAfter. Мы считаем что CacheTimeout > DepTimeout, и ожидание этих таймаутов происходит последовательно в одной горутине.