feat(stg): DDL-бутстрап, топик hits и приём сырья обеими нодами #53

Merged
ddmitry merged 1 commits from feat/37-ddl-bootstrap-stg-ingest into main 2026-08-06 09:21:20 +03:00
Owner

Closes #37

Стенд получает руки для DDL, а сырьё из Kafka доезжает до STG обеими нодами
кластера. Между make clean и рабочим приёмом ручных шагов не остаётся.

Что внутри

  • sql/ddl/ — три файла, применяются по порядку имён: базы stg и ods,
    Kafka-чтец формата RawBLOB, реплицируемая и распределённая таблицы сырья,
    матвью приёма. Пропуск в нумерации (20/30) намеренный: их приносит #43, и
    матвью приёма обязана создаваться после матвью разбора.
  • compose.yaml — одноразовые kafka-init и clickhouse-init, hostname:
    у обеих нод ClickHouse, зависимость airflow-init от clickhouse-init.
  • Документация — конвенции и раздел «Что проверено» в справочнике хранилища,
    указатели и границы обещаний в ADR 0005, снятые пункты в разделе 11 спеки.

Решения сверх буквы тикета

Три штуки, приняты владельцем по ходу; доводы — в комментарии к #37 и в
справочнике хранилища. Коротко: форма kafka_timestamp выбрана по итогу
опыта, hostname: добавлен ради осмысленного consumer_host, а поведение
make up --wait с одноразовыми службами решено замером — служба без
зависимых считается упавшей даже при выходе с нулём.

Известная граница

RawBLOB молча теряет запись с пустым значением и запись-надгробие. Запасной
LineAsString теряет их так же, поэтому формат тут не рычаг. Принято как
свойство; замер и практический признак — в справочнике хранилища.

Проверка

make lint, make typecheck, make config-test, make smoke (25 проверок),
make smoke-guards — зелёные. Приёмочный прогон с чистого тома подтвердил все
шесть критериев #37.

🤖 Generated with Claude Code

Closes #37 Стенд получает руки для DDL, а сырьё из Kafka доезжает до STG обеими нодами кластера. Между `make clean` и рабочим приёмом ручных шагов не остаётся. ## Что внутри - `sql/ddl/` — три файла, применяются по порядку имён: базы `stg` и `ods`, Kafka-чтец формата `RawBLOB`, реплицируемая и распределённая таблицы сырья, матвью приёма. Пропуск в нумерации (20/30) намеренный: их приносит #43, и матвью приёма обязана создаваться после матвью разбора. - `compose.yaml` — одноразовые `kafka-init` и `clickhouse-init`, `hostname:` у обеих нод ClickHouse, зависимость `airflow-init` от `clickhouse-init`. - Документация — конвенции и раздел «Что проверено» в справочнике хранилища, указатели и границы обещаний в ADR 0005, снятые пункты в разделе 11 спеки. ## Решения сверх буквы тикета Три штуки, приняты владельцем по ходу; доводы — в комментарии к #37 и в справочнике хранилища. Коротко: форма `kafka_timestamp` выбрана по итогу опыта, `hostname:` добавлен ради осмысленного `consumer_host`, а поведение `make up --wait` с одноразовыми службами решено замером — служба без зависимых считается упавшей даже при выходе с нулём. ## Известная граница `RawBLOB` молча теряет запись с пустым значением и запись-надгробие. Запасной `LineAsString` теряет их так же, поэтому формат тут не рычаг. Принято как свойство; замер и практический признак — в справочнике хранилища. ## Проверка `make lint`, `make typecheck`, `make config-test`, `make smoke` (25 проверок), `make smoke-guards` — зелёные. Приёмочный прогон с чистого тома подтвердил все шесть критериев #37. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
ddmitry added 1 commit 2026-08-06 08:13:16 +03:00
Зачем: стенду нужен воспроизводимый холодный старт, при котором схема
хранилища и топик появляются сами, а сырьё из Kafka доезжает в STG обеими
нодами кластера — без ручных шагов между `make clean` и рабочим приёмом.

Что:
- `sql/ddl/` — три файла, применяются по порядку имён: базы `stg` и `ods`,
  Kafka-чтец `hits_raw_kafka` формата RawBLOB, реплицируемая `hits_raw_rep`
  с окном TTL в трое суток, распределённая `hits_raw_dist` и матвью
  `hits_raw_mv`, переносящая сырьё вместе с метаданными доставки.
- `compose.yaml` — службы `kafka-init` (топик `hits` на две партиции, с
  ремонтом уже созданного однопартиционного) и `clickhouse-init` (применяет
  `/ddl/*.sql`); `hostname:` у обеих нод, чтобы `hostName()` отдавал имя узла,
  а не идентификатор контейнера; `airflow-init` зависит от `clickhouse-init` —
  без зависимого успешный одноразовый сервис считается упавшим для `--wait`.
- Доки: конвенции и раздел «Что проверено» в справочнике хранилища, указатели
  и границы обещаний в ADR 0005, снятые пункты в разделе 11 спеки.

Проверка: `make lint`, `make typecheck`, `make config-test`, `make smoke`
(25 проверок), `make smoke-guards` — зелёные. Приёмочный прогон с чистого
тома подтвердил все пять критериев #37: холодный старт и идемпотентный
повтор, две партиции у `hits`, метаданные доставки у доехавшего сообщения,
обе партиции на обеих потребляющих нодах в одном прогоне, некорректный JSON
лежит сырым и приём не встаёт.

Известная граница: RawBLOB молча теряет запись с пустым значением и
запись-надгробие; принято как свойство, замер и довод — в справочнике
хранилища.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
ddmitry merged commit c99e853fd3 into main 2026-08-06 09:21:20 +03:00
ddmitry deleted branch feat/37-ddl-bootstrap-stg-ingest 2026-08-06 09:21:24 +03:00
Sign in to join this conversation.
No Reviewers
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: ddmitry/clickstream-data-platform#53