Ресурсы компаньона: краткий дизайн

Ресурс компаньона — это тяжёлый объект, которым управляет Flow, но который живёт в
процессе-компаньоне и доступен пользовательским process function. Например, это может быть
распакованный словарь, модель или пул соединений. Ресурс общий для всего процесса-компаньона,
а не для отдельного джоба, поэтому он не должен хранить изменяемое состояние джоба и обязан
поддерживать параллельное использование.

Компоненты

  • Контроллер ресурса определяет желаемую ревизию и публикует её в Flow.
  • TCompanionResource на воркере является прокси: готовит ревизию, управляет жизненным циклом
    и отправляет команды в компаньон.
  • TResourceStore в C++-компаньоне хранит ресурсы по resource_id. Хранилище принадлежит
    процессу и переживает создание и удаление джобов.
  • Process function получает только ресурсы, перечисленные в required_resource_ids, с учётом
    алиасов и транзитивных зависимостей.

Доставка и ссылки

Воркер вызывает RPC ResourceExecute(resource_id, command, argument). Команда задаётся enum и
имеет два значения: init и unload. Результат содержит отдельный статус команды ресурса и
структурированную ошибку TError.

Основной путь использует идемпотентный init. В аргумент входят статическая и динамическая
спеки, подготовленная ревизия, идентификатор и поколение инкарнации, поколение конфигурации и
точные ссылки на зависимости. Зависимости инициализируются раньше зависимого ресурса. В TJobInfo
передаются те же точные ссылки: resource_id, incarnation_id,
configuration_generation и необязательный алиас. Перед запуском пользовательского кода
компаньон проверяет каждую ссылку и выдаёт process function ссылки только на совпавшие
экземпляры.

Реконфигурация и восстановление

  • Новая целевая ревизия сначала асинхронно готовится на воркере через
    PrepareResourceRevision; неуспешный результат не публикуется в компаньон.
  • Успешная подготовка увеличивает поколение конфигурации и запускает сходящийся init.
  • Компаньон публикует новое поколение только после того, как ресурс применил целевую ревизию:
    Reconfigure по контракту может лишь передать цель асинхронному переключению. Пока
    GetRevisionState сообщает отстающую применённую ревизию, init возвращает временный
    resource_not_initialized, а повторы сходятся без пересоздания экземпляра.
  • Монотонное поколение инкарнации не позволяет запоздалой команде оживить старый экземпляр или
    удалить новый.
  • Воркер периодически повторяет init, а каждый компьютейшен доставляет требуемые ресурсы по
    своему каналу. Это восстанавливает состояние после перезапуска процесса-компаньона.
  • Если ProcessBatch возвращает RESOURCE_NOT_INITIALIZED, воркер повторно инициализирует граф
    ресурсов, обновляет ссылки и сведения о джобе и повторяет запрос с ограниченным числом попыток.
  • unload выполняется по возможности. Уже работающие джобы удерживают ссылки на старый объект,
    но новые джобы его больше не получают.

Полная серверная реализация сейчас есть у C++-компаньона. Java, Go и Python пока возвращают из
ResourceExecute статус Unsupported.

Предыдущая
Следующая