StateAccessor в YTsaurus Flow (Python)
StateAccessor — интерфейс для чтения, модификации и удаления значений стейта.
Общие сведения о stateful-обработке описаны в разделе Stateful processing.
Принцип работы
Стейт во Flow хранится в сортированных динамических таблицах.
В случае внешнего стейта эта таблица создаётся пользователем, в случае внутреннего стейта таблицы создаются и управляются Flow автоматически.
Для TTransformCompanionComputation ключевые колонки в таблице стейта совпадают с group_by_schema компьютейшена. Для внутреннего стейта TTransformOrderedSourceCompanionComputation ключом служит ключ партиции источника: group_by_schema в таком SourceComputation не поддерживается. Во всех случаях сообщения с одинаковым ключом разделяют один стейт.
Чтение и запись данных
Непосредственную работу с таблицей (чтение, запись, удаление данных) осуществляет воркер. При получении очередного батча сообщений воркер загружает значения стейтов для всех ключей в батче и отправляет их в компаньон вместе с сообщениями и таймерами. Подробнее про схему взаимодействия.
Запись новых значений в таблицу стейта осуществляется транзакционно в рамках эпохи.
Четыре типа аксессоров
Python SDK предоставляет четыре вида аксессоров для работы со стейтом:
| Аксессор | Формат | Получение | Описание |
|---|---|---|---|
| YsonStateAccessor | YSON (dict) | ctx.state(name, msg) |
Сериализация Python dict в YSON |
| RawStateAccessor | bytes |
ctx.raw_state(name, msg) |
Сырые байты без сериализации |
| ProtoStateAccessor | Protobuf | ctx.proto_state(name, msg, ProtoClass) |
Сериализация через Protobuf |
| ExternalStateAccessor | Payload (строка таблицы) | ctx.external_state("/name", msg) |
Типизированный доступ к внешней таблице |
Первые три аксессора работают с внутренним стейтом (таблицы управляются Flow автоматически). ExternalStateAccessor работает с внешним стейтом (пользователь создаёт таблицу самостоятельно).
Общий API
Все внутренние аксессоры (YsonStateAccessor, RawStateAccessor, ProtoStateAccessor) предоставляют единый набор методов:
| Метод | Описание |
|---|---|
get() |
Получить значение стейта (или None, если стейт отсутствует) |
set(value) |
Установить значение стейта |
clear() |
Удалить стейт для текущего ключа |
get_or_default(default) |
Получить значение или вернуть default |
Получение аксессора
Аксессор получается через RuntimeContext (ctx) внутри on_message или on_timer:
class MyFunction(RowFunction):
def on_message(self, message, output, ctx):
# YSON (dict)
yson_state = ctx.state("state-name", message)
# Raw bytes
raw_state = ctx.raw_state("state-name", message)
# Protobuf
proto_state = ctx.proto_state("state-name", message, MyProtoClass)
# External (имя обязательно начинается с "/")
ext_state = ctx.external_state("/state-name", message)
def on_timer(self, timer, output, ctx):
# Аналогично, но вместо message передаётся timer
state = ctx.state("state-name", timer)
Параметры:
name— строка с именем стейта, объявленным в статической спеке. Для внутренних стейтов — произвольная строка изinternal_states; для внешних стейтов — ключ изexternal_state_managers, обязательно начинающийся с/.message/timer— сообщение или таймер, для ключа которого нужно получить стейт.ProtoClass(только дляproto_state) — класс Protobuf-сообщения для десериализации.
Когда использовать какой тип
| Ситуация | Рекомендуемый аксессор |
|---|---|
| Простой словарь с несколькими полями | ctx.state() (YSON) |
| Произвольные двоичные данные | ctx.raw_state() (Raw) |
| Структурированные данные с фиксированной схемой | ctx.proto_state() (Protobuf) |
| Данные, к которым нужен доступ из других систем | ctx.external_state("/name", msg) (External) |
| Данные, требующие пользовательской таблицы | ctx.external_state("/name", msg) (External) |
См. также
- Internal State (Python)
- External State (Python)
- Работа со стейтами (Python) — краткий обзор всех типов
- Stateful processing (концепция)
- StateAccessor (Java)