docs(storage): приняты решения по приёму событий и именам

- Зачем:
  - тикет #37 молча опирался на конвенции хранилища, которых в проекте не
    было; без них #43 и следующие этапы разъехались бы в именах, служебных
    колонках и механике приёма.
- Что:
  - ADR 0005: топик читается байтами в STG, разбор идёт функциями в матвью
    ODS; строгий приём — сверка набора ключей плюс Nullable на пяти опорных
    колонках.
  - ADR 0006: суффикс вида в именах объектов (_rep, _dist, _kafka, _mv, _v).
  - docs/architecture/storage.md: конвенции имён и служебных колонок, путь в
    keeper, раскладка по шардам, срок жизни сырья, свойства приёма, раскладка
    файлов DDL и карта таблиц.
  - спеки приведены в соответствие: механизм строгого приёма, имена объектов,
    контракт транспорта «одно событие — одно сообщение Kafka», три проверки
    при исполнении.
- Проверка:
  - make config-test
This commit is contained in:
ddadmin committed 2026-08-04 00:14:13 +03:00
1 parent a18e6b7a80
commit 319db308bf
5 files changed
+490 -24

No files matched your search

+11 -4
View File
@@ -157,7 +157,7 @@
строк; сверка — по хешам манифеста, а два локально пересобранных снимка
сравнимы обычным diff — пустой означает «ничего не изменилось». Вне
обещания — транспорт: офсеты и партиции Kafka, какая нода прочитала,
`_ingested_at`, темп живого дня.
`_load_ts`, темп живого дня.
- **Условия обещания.** Детерминизм держится при зафиксированном `uv.lock`
и внутри канонического контейнера — то есть везде Linux, на маке и в WSL
тоже; единственная переменная — архитектура CPU. Истина — CI на Linux; сходимость любой машины проверяет
@@ -224,13 +224,13 @@
менти несёт рендеренная таблица в доках, не модуль. Уточнение при
исполнении (#36): нормализованное имя — имя источника, приведённое к
нашему стилю, а не имя атрибута в модели данных. Слой DDS складывает свою
модель и называет атрибуты по ней; `dds.v_event` эти имена берёт (раздел 7
модель и называет атрибуты по ней; `dds.event_v` эти имена берёт (раздел 7
мастер-спеки), но контракт их не диктует и тестами не сторожит.
- **Сторона хранилища пишется по документации, не генерируется.** DDL
`ods.event`, SELECT матвью, `dds.v_event`, трансформации — работа
`ods.event`, SELECT матвью, `dds.event_v`, трансформации — работа
следующих этапов по «описанию выгрузки», как в бою хранилище адаптируется
к источнику. Границу сторожат два боевых механизма: строгий приём
(`input_format_skip_unknown_fields = 0`, таблицы `*_errors` — раздел 6
(`Nullable`-разбор со сверкой набора ключей, таблицы `*_errors` — раздел 6
мастер-спеки) и contract-тест в smoke — сравнение `system.columns`
поднятого стенда со схемой генератора.
@@ -254,6 +254,13 @@
превращается в JSON. Приёмники не знают о содержимом: файл (локальный кэш
для пересборки и проверок манифеста), Kafka пачкой — пакетный режим,
Kafka с темпом ×60 — живой день. Новых топиков нет.
- **Одно событие — одно сообщение Kafka.** «Пачкой» относится к темпу
отправки, а не к упаковке: приёмник шлёт события подряд без пауз, но каждое
отдельным сообщением. Контракт транспорта, не деталь реализации — сторона
хранилища читает топик байтами и кладёт сообщение строкой
([ADR 0005](../adr/0005-event-ingestion.md)), поэтому склейка нескольких
событий в одно сообщение сломала бы разбор целиком. Сторожится тестом
приёмника.
- **Рабочий выбор сериализатора — orjson**: быстрее stdlib json в 5–14 раз,
numpy-массивы и datetime сериализует нативно (заметка исследования #31).
Смена библиотеки меняет канонические байты, поэтому проходит как