shad-go/distbuild/pkg/scheduler
2020-04-22 01:35:28 +03:00
..
export_test.go Finish pkg/scheduler 2020-04-05 14:29:46 +03:00
README.md Clarify scheduler 2020-04-22 01:35:28 +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.

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

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

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

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

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

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

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

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

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

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

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

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