Архитектура: источник истины схемы и разделение потока и пакета #29

Closed
opened 2026-08-01 15:46:07 +03:00 by ddmitry · 1 comment
Owner

Part of #26.

Вопрос

Где живёт источник истины схемы события (раздел 1.4 мастер-спеки: одно машинное описание — python-модуль или YAML) и как из него выводятся остальные ~семь мест, где повторяются 47 колонок (генератор, DDL, SELECT матвью, трансформации, витрины, манифест, доки)? Как разделены живой поток (×60) и пакетная генерация?

Развилка отложена мастер-спекой (см. тикет #14).

Хвост из решения «Модель мира» (#27): решить и доставку эталонного снимка при старте стенда — проигрывание через Kafka или прямая загрузка в ClickHouse.

Part of #26. ## Вопрос Где живёт источник истины схемы события (раздел 1.4 мастер-спеки: одно машинное описание — python-модуль или YAML) и как из него выводятся остальные ~семь мест, где повторяются 47 колонок (генератор, DDL, SELECT матвью, трансформации, витрины, манифест, доки)? Как разделены живой поток (×60) и пакетная генерация? Развилка отложена мастер-спекой (см. тикет #14). Хвост из решения «Модель мира» (#27): решить и доставку эталонного снимка при старте стенда — проигрывание через Kafka или прямая загрузка в ClickHouse.
ddmitry added the wayfinder:grilling label 2026-08-01 15:46:43 +03:00
ddmitry self-assigned this 2026-08-01 16:52:20 +03:00
Author
Owner

Резолюция (сессия 2026-08-01, владелец подтвердил):

  1. Граница вывода — по шву «трекер | склад», как data contract. Контракт схемы — собственность генератора, как формат выгрузки — собственность Метрики. Из него выводятся: сам генератор, его валидация и публичное «описание выгрузки» в доках (рендеренная таблица колонок — аналог документации Метрики). Сторона склада — DDL ods.event, SELECT матвью, dds.v_event, трансформации — пишется по этой документации на следующих этапах нами (руками, автогенератором или ЛЛМ — приём разработки, не архитектура). Границу сторожат два боевых механизма: строгий приём (skip_unknown_fields = 0, *_errors, раздел 6 мастер-спеки) и contract-тест в smoke — сравнение system.columns поднятого стенда со схемой генератора.
  2. Форма источника истины — импортируемый python-модуль с чистыми данными: описатели колонок (имя Метрики, тип ClickHouse, тип numpy, snake_case-имя для DDS, группа полей, порядок), никакой логики. Читаемость для менти несёт рендеренная таблица в доках, не модуль.
  3. Разрез потока и пакета — один канонический сериализатор, глупые приёмники. День-функция выдаёт упорядоченный поток канонических байтов; приёмники: файл (только git-снимок data/startup_history/ и пересборка этапа 7), Kafka пачкой (пакетный режим), Kafka с темпом ×60 (живой день). Промежуточные файлы вне git-снимка не хранятся: файл дня — кэш чистой функции, потерял — пересчитал. Обрыв любого режима — переигровка дня целиком, дедуп склеивает повторы (механизм уже выбран в #28). Новых топиков нет.
  4. Эталонный снимок при старте стенда — через Kafka, пакетным режимом проигрывателя: отдельный механизм заливки не строится, каждый make up бесплатно прогоняет весь конвейер и contract-тест на настоящих данных. Оговорка-условие: если #30 назначит снимку объём, при котором заливка уходит в десятки минут, вернуться к прямой загрузке как осознанному backfill-компромиссу.

Отклонено с доводами:

  • Автогенерация DDL склада из контракта (буква раздела 1.4): пересекает границу ответственности компонент — в бою склад адаптируется к источнику руками, менти пришлось бы объяснять приём, которого в жизни нет. Data contract даёт тот же щит от дрейфа без этой условности.
  • YAML как форма контракта: красота ценой загрузчика и «схемы для схемы»; потребителя вне Python нет — склад читает рендеренную документацию, не машинный файл.
  • Отдельный топик / Kafka как хранилище дней: офсеты и партиции вне обещания #28, retention конечен, в git топик не положишь, хеш с манифестом не сверишь; Kafka на стенде — труба, не хранилище (раздел 7).
  • Файл как обязательная станция доставки: доигрывание обрыва уже решено через дедуп (#28), канон держит единственный сериализатор, а не диск; файл остаётся только там, где нужен git.
  • Прямая загрузка снимка в ClickHouse (и гибрид с ручным заполнением сырого слоя): второй путь приёма, пустой либо поддельный stg.hits_raw — теряются переобработка дня X по event_date и урок виртуальных колонок «какая нода читала топик».

Хвосты: в #32 — правка раздела 1.4 мастер-спеки тем же коммитом (вывод склада заменить на data contract + contract-тест); термины для CONTEXT.md: контракт схемы, канонический сериализатор, проигрыватель, пакетный режим / живой день. В #30 — при фиксации объёма снимка проверить оговорку из п. 4.

Резолюция (сессия 2026-08-01, владелец подтвердил): 1. **Граница вывода — по шву «трекер | склад», как data contract.** Контракт схемы — собственность генератора, как формат выгрузки — собственность Метрики. Из него выводятся: сам генератор, его валидация и публичное «описание выгрузки» в доках (рендеренная таблица колонок — аналог документации Метрики). Сторона склада — DDL `ods.event`, SELECT матвью, `dds.v_event`, трансформации — пишется по этой документации на следующих этапах нами (руками, автогенератором или ЛЛМ — приём разработки, не архитектура). Границу сторожат два боевых механизма: строгий приём (`skip_unknown_fields = 0`, `*_errors`, раздел 6 мастер-спеки) и contract-тест в smoke — сравнение `system.columns` поднятого стенда со схемой генератора. 2. **Форма источника истины — импортируемый python-модуль с чистыми данными**: описатели колонок (имя Метрики, тип ClickHouse, тип numpy, snake_case-имя для DDS, группа полей, порядок), никакой логики. Читаемость для менти несёт рендеренная таблица в доках, не модуль. 3. **Разрез потока и пакета — один канонический сериализатор, глупые приёмники.** День-функция выдаёт упорядоченный поток канонических байтов; приёмники: файл (только git-снимок `data/startup_history/` и пересборка этапа 7), Kafka пачкой (пакетный режим), Kafka с темпом ×60 (живой день). Промежуточные файлы вне git-снимка не хранятся: файл дня — кэш чистой функции, потерял — пересчитал. Обрыв любого режима — переигровка дня целиком, дедуп склеивает повторы (механизм уже выбран в #28). Новых топиков нет. 4. **Эталонный снимок при старте стенда — через Kafka, пакетным режимом проигрывателя**: отдельный механизм заливки не строится, каждый `make up` бесплатно прогоняет весь конвейер и contract-тест на настоящих данных. Оговорка-условие: если #30 назначит снимку объём, при котором заливка уходит в десятки минут, вернуться к прямой загрузке как осознанному backfill-компромиссу. **Отклонено с доводами:** - *Автогенерация DDL склада из контракта* (буква раздела 1.4): пересекает границу ответственности компонент — в бою склад адаптируется к источнику руками, менти пришлось бы объяснять приём, которого в жизни нет. Data contract даёт тот же щит от дрейфа без этой условности. - *YAML как форма контракта*: красота ценой загрузчика и «схемы для схемы»; потребителя вне Python нет — склад читает рендеренную документацию, не машинный файл. - *Отдельный топик / Kafka как хранилище дней*: офсеты и партиции вне обещания #28, retention конечен, в git топик не положишь, хеш с манифестом не сверишь; Kafka на стенде — труба, не хранилище (раздел 7). - *Файл как обязательная станция доставки*: доигрывание обрыва уже решено через дедуп (#28), канон держит единственный сериализатор, а не диск; файл остаётся только там, где нужен git. - *Прямая загрузка снимка в ClickHouse* (и гибрид с ручным заполнением сырого слоя): второй путь приёма, пустой либо поддельный `stg.hits_raw` — теряются переобработка дня X по `event_date` и урок виртуальных колонок «какая нода читала топик». **Хвосты:** в #32 — правка раздела 1.4 мастер-спеки тем же коммитом (вывод склада заменить на data contract + contract-тест); термины для CONTEXT.md: контракт схемы, канонический сериализатор, проигрыватель, пакетный режим / живой день. В #30 — при фиксации объёма снимка проверить оговорку из п. 4.
Sign in to join this conversation.