Перейти к основному содержимому

Модель выполнения

Один бинарь​

Пайплайн компилируется в один бинарь. Этот бинарь исполняется в двух ролях; код одинаковый, роль назначает окружение запуска:

РольГде работаетЧто делает
runпроцесс рана: контейнер, запущенный сервером, или процесс, запущенный пользователемведёт ран
machineконтейнер на машине агентавыполняет действия, адресованные этой машине

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

Кто с кем соединяется​

Соединений в системе ровно три вида, все ведут к серверу — исходящие. Внутренняя инфраструктура — Temporal (durable-ядро), реестр образов, хранилище блобов — снаружи не видна и не адресуема:

Пайплайн, агент и браузер знают один адрес: порт сервера.

Ран​

Ран стартует через сервер. Идентификатор называет ровно одно логическое исполнение — в любом состоянии. Тот же запрос под тем же id (пайплайн и параметры) отвечает exists и возвращает этот ран, открытый или закрытый, как бы он ни закрылся: клиент, потерявший ответ, спрашивает ещё раз, и ничего не стартует дважды. Другой запрос под занятым id — конфликт (ALREADY_EXISTS), никогда не второе исполнение; повторный прогон — новый id. Горизонт этого обещания — retention исполнений в namespace: после него id — новое имя. «Отсутствует» говорится только когда так сказал сервис — сервер, не сумевший спросить Temporal, отвечает UNAVAILABLE, а не NOT_FOUND.

При политике queue пайплайна срабатывание, пришедшее при живом ране, — queued: у него сразу есть run id, стартует, когда живой ран закончится. Очередь держит одно срабатывание — cron не копится за долгим раном — и новое вытесняет старое, которое называется в ответе и не запускается.

Дать рану исполнителя можно двумя способами:

  • Managed — при старте указан образ: сервер сам запускает контейнер и сам убирает его после завершения.
  • Inplace — пользователь запускает бинарь сам, где угодно: локальная разработка, свой оркестратор. Сервер только стартует процесс рана.

Ран восстановим: история выполнения живёт в Temporal, а не в процессе. Падение процесса, рестарт, обрыв сети не теряют выполнение — когда исполнитель возвращается, ран продолжается с места остановки. Успешно завершённые действия не выполняются повторно.

Действия на машине​

Действие всегда адресовано агенту и выполняется на его машине — не в процессе рана. Контейнер — один на пару агент × ран, поднимается первым действием:

Агент — хост, не исполнитель: он поднимает контейнер и следит за ним, но не заглядывает внутрь действий.

Записывающий проход​

Перед стартом рана функция пайплайна выполняется один раз в режиме записи:

  • ничего не исполняется — объявления действий и ресурсов только регистрируются;
  • чтения из ресурсов возвращают оптимистичные нули (булевы поля — true), чтобы охранные условия не обрывали обход;
  • всё найденное — действия, типы ресурсов — становится известно исполнителю до начала работы.

Поэтому действия и ресурсы объявляются прямо по месту использования, без отдельной регистрации. Цена: код пайплайна обязан переживать проход с нулевыми данными.

Завершение рана​

Успех, ошибка и отмена завершаются одной дорогой: