feat(clickhouse): добавлен словарь товаров из каталога

- Зачем:
  - витринам нужен общий с генератором каталог, а менти — пример штатного обновления словаря.
- Что:
  - каталог смонтирован read-only в обе ноды и создан как dds.products ON CLUSTER.
  - роли получили dictGet, а check-clickhouse сверяет ответ под etl с исходным CSV.
  - источник, раскладка и явная политика обновления записаны в документации.
- Проверка:
  - make up с чистыми томами; make lint; make config-test; make smoke; make check-clickhouse.
  - в generator: make lint typecheck test — 427 тестов прошли.
This commit is contained in:
2026-08-19 00:50:14 +03:00
parent 62b275ef94
commit 13abc58d98
8 changed files with 106 additions and 22 deletions
+30 -2
View File
@@ -12,6 +12,8 @@ keeper, Kafka, каркас сервисов. Этап 2 идёт: в `sql/ddl/`
Этап 3 добавил вход второго источника и довёл его до ODS: топик `orders`, свой
чтец, своё сырьё, версии заказов с таблицей ошибок и поверхность текущего
состояния. Наполняет всю цепочку даг `orders_ingest` двумя шагами, а не матвью.
Тот же этап принёс первый объект DDS — словарь товаров из общего с генератором
CSV-файла.
Дальше по тексту устройство описано так, как оно проектируется; построенное от
заложенного отличает карта таблиц в конце.
@@ -414,6 +416,23 @@ kafka_offset)`: смотрят такую таблицу от класса, а
разрастается до имени отдельного поля. Точная граница приёма — в
[спецификации заказов](orders/ingestion.md).
## Словарь товаров
`dds.products` читает `data/catalog/products.csv` напрямую. Compose монтирует
каталог только для чтения в `user_files` обеих нод, а DDL создаёт словарь
`ON CLUSTER`: имя и форма одни, но каждая нода держит свою копию в памяти.
Источник `FILE` с форматом `CSVWithNames` читает заголовок файла. Строковый ключ
`sku` требует `COMPLEX_KEY_HASHED`; числовой `FLAT` здесь неприменим. Цена
остаётся целым числом копеек типа `Int64`, как в контракте события.
`LIFETIME(0)` отключает фоновое обновление. Каталог меняется только явной
правкой репозитория, а независимый опрос двух нод позволил бы им временно
отвечать разными версиями. Изменение применяют к обеим нодам штатной командой:
`SYSTEM RELOAD DICTIONARY ON CLUSTER clickstream_cluster dds.products`.
Это административная операция: её выполняют под `default`; роль `etl` права
перезагрузки словарей не получает.
## Раскладка SQL
Исполняемые дагами запросы лежат по правилу
@@ -439,6 +458,7 @@ Airflow читает и собирает эти файлы штатным шаб
| `00-databases.sql` | базы слоёв |
| `10-stg-tables.sql` | чтецы топиков `hits` и `orders`, локальные и распределённые таблицы сырья обоих источников |
| `20-ods-tables.sql` | типизированное событие, версии заказа и обе таблицы ошибок |
| `25-dds-dictionaries.sql` | словарь товаров из общего CSV-каталога |
| `30-ods-views.sql` | актуальные события, текущие заказы и матвью разбора в ODS |
| `40-stg-views.sql` | матвью приёма: чтец в сырьё |
@@ -501,13 +521,14 @@ ODS. Второе: матвью приёма создаётся последне
| ODS | `ods.order_snapshot_rep` / `_dist` | типизированные версии заказа |
| ODS | `ods.order_v` | текущая версия заказа на языке источника |
| ODS | `ods.order_snapshot_errors_rep` / `_dist` | строки слепка, не прошедшие строгий приём |
| DDS | `dds.products` | словарь товаров из общего с генератором CSV-каталога |
Матвью разбора у заказов нет: срез сырья раскладывают по этим двум целям два
`INSERT SELECT` шага `parse_batch` из файлов `sql/ods/order_snapshot_load.sql`
и `sql/ods/order_snapshot_errors_load.sql`.
Слои DDS и DM появляются на следующих этапах; их состав задан разделом 7
мастер-спеки и переносится сюда по мере постройки.
Таблицы DDS и слой DM появляются на следующих этапах; их состав задан разделом
7 мастер-спеки и переносится сюда по мере постройки.
## Что проверено
@@ -525,6 +546,13 @@ MCP Context7 подтвердила обычное представление с
`ods.event_v` остался равен `ods.event_dist FINAL`. Имена и типы всех колонок
представления совпали с распределённой таблицей.
**Проверка словаря товаров 19 августа 2026 года (#95).** Context7 подтвердил
DDL-словарь с файловым источником внутри `user_files`, хешированную раскладку
для строкового ключа и отключение фонового обновления через `LIFETIME(0)`.
На закреплённом ClickHouse 26.3 цена известного `sku` после правки CSV и
`SYSTEM RELOAD DICTIONARY ON CLUSTER`
изменилась на обеих нодах; после отката и повторной команды вернулась обратно.
**Проверка версий заказов 18 августа 2026 года (#94).** MCP Context7 подтвердил,
что `JSONType` возвращает имя типа значения JSON, — на нём стоит проверка типов
в предикате приёма заказов. Остальное снято на закреплённом ClickHouse 26.3.