docs(glossary): четыре термина переименованы, world.md и stand.md вычитаны

- Зачем:
  - справочники читает человек со стороны, а «пульт мира», «опись мира»,
    «работник» и «сырьё» звучали шуткой или калькой времён разработки
    (тикет #214, выбор владельца).
- Что:
  - CONTEXT.md: статьи «Паспорт мира», «Даги модельного времени»,
    «Шаговый даг», «Сырые данные», старые слова в строках «Избегать»;
    пометки в ADR 0005, 0008, 0009 без переписывания решений.
  - замены по README, справочникам, путеводителю, лабам, спекам,
    комментариям дагов и SQL, тегу дага и панели Grafana; имена в коде
    не тронуты.
  - world.md и stand.md: 35 находок вычитки внесены, регистр выровнен.
- Проверка:
  - make config-test; make lint в корне и в generator/; make test в
    generator/ (437 passed); скрипт ссылок из #212 пуст; grep старых
    слов вне ADR, research и CONTEXT.md пуст.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014QBCtU38qSHg5DvgtnKXcW
This commit is contained in:
ddadminandClaude Fable 5.1 committed 2026-09-02 16:46:50 +03:00
1 parent 86ad8afaf2
commit 59d8c83b17
54 files changed
+794 -776

No files matched your search

+64 -68
View File
@@ -272,12 +272,13 @@ CSV в репозитории (`data/catalog/products.csv`: `sku`, `name`, `cate
Классы пересекаются — приоритет: `cancelled` > `lost_event` >
`duplicate_event` > `amount_delta` > `match`.
Пятое — **опоздание** — бесплатно даёт формат доставки: часть заказов
впервые появляется в слепке D+1/D+2 («вчера не сходилось, сегодня сошлось»),
ориентир ~10%. Точные доли зафиксированы замером на каноническом мире
(28 дней, 2026-08-30, #194) — запись в «Что проверено»
[карты проверок](../architecture/testing.md); опись хранит счётчики наблюдаемых классов после приоритета — в заказах и
только по дням с закрытым окном (раздел 8).
Пятое — **опоздание** — бесплатно даёт формат доставки: часть заказов впервые
появляется в слепке D+1/D+2 («вчера не сходилось, сегодня сошлось»), ориентир
~10%. Точные доли зафиксированы замером на каноническом мире (28 дней,
2026-08-30, #194) — запись в «Что проверено» [карты
проверок](../architecture/testing.md); паспорт хранит счётчики наблюдаемых
классов после приоритета — в заказах и только по дням с закрытым окном (раздел
8).
Не берём: сироту-фрод (`purchase` есть, а заказа не будет никогда) —
механически дублирует B.
@@ -311,14 +312,13 @@ CSV в репозитории (`data/catalog/products.csv`: `sku`, `name`, `cate
запуск пишет полный текущий набор различных пар; предыдущий результат не
служит источником следующего.
- **N:1**: часть покупателей покупает с двух кук («телефон и ноутбук») —
параметр мира; значение фиксирует эта спека: 15%, детерминировано
от seed. Ядро лабы:
`uniq(посетителей) > uniq(людей)`, менти выводит расхождение сам.
Константа мира: каждый двухкуковый покупатель делает минимум по одному
заказу с каждой куки — иначе вторая кука не попадает в карту соответствий
(она строится только из покупок) и лаба не воспроизводится. Число таких
пар растёт, пока мир едет, и в опись не кладётся
([что хранит опись](../architecture/orders/inventory.md)).
параметр мира; значение фиксирует эта спека: 15%, детерминировано от seed.
Ядро лабы: `uniq(посетителей) > uniq(людей)`, менти выводит расхождение сам.
Константа мира: каждый двухкуковый покупатель делает минимум по одному заказу
с каждой куки — иначе вторая кука не попадает в карту соответствий (она
строится только из покупок) и лаба не воспроизводится. Число таких пар растёт,
пока мир едет, и в паспорт не кладётся ([что хранит
паспорт](../architecture/orders/inventory.md)).
- Витрины разводят имена честно: **«посетители»** (`uniq(ClientID)`) и
**«известные пользователи»** (после склейки) — оба числа рядом в дашборде.
@@ -339,16 +339,14 @@ CSV в репозитории (`data/catalog/products.csv`: `sku`, `name`, `cate
ноду 2**. Это осознанная ловушка правильных ошибок: забытый ON CLUSTER или
VIEW поверх локальной таблицы проявляются в дашборде сами.
- **Приём Kafka**: у событий — Kafka-таблицы и MV на обеих нодах, одна
consumer group, 2 партиции на топик `hits`; MV пишут в Distributed-цели.
У заказов приём другого рода — пакетный забор без MV, чтец на одной ноде,
топик `orders` в одну партицию ([ADR 0008](../adr/0008-order-ingestion.md)).
Раскладку в обоих случаях решает ключ:
события — по `cityHash64(ClientID)` (см. 1.3), заказы —
`cityHash64(order_id)`, сырьё STG — `cityHash64(сырой строки)`; полный
список и доводы — в [доке хранилища](../architecture/storage.md). Урок
«какая нода читала топик — меняется между прогонами, куда легли данные —
нет» живёт на событиях: при пакетном заборе читает та нода, которую
спросили.
consumer group, 2 партиции на топик `hits`; MV пишут в Distributed-цели. У
заказов приём другого рода — пакетный забор без MV, чтец на одной ноде, топик
`orders` в одну партицию ([ADR 0008](../adr/0008-order-ingestion.md)).
Раскладку в обоих случаях решает ключ: события — по `cityHash64(ClientID)`
(см. 1.3), заказы — `cityHash64(order_id)`, STG — `cityHash64(сырой строки)`;
полный список и доводы — в [доке хранилища](../architecture/storage.md). Урок
«какая нода читала топик — меняется между прогонами, куда легли данные — нет»
живёт на событиях: при пакетном заборе читает та нода, которую спросили.
- **Приём строгий**: пять опорных колонок — `WatchID`, `VisitID`, `ClientID`,
`EventDate`, `UTCEventTime` — разбираются как `Nullable`, а набор ключей
сообщения сверяется с контрактным; строка с NULL среди опорных колонок
@@ -444,23 +442,24 @@ README.
| DM | витрины `dm.*_v`, `dm.dq_summary` | см. ниже |
У каждой таблицы слоя — пара из локальной и распределённой, имена по конвенции
суффиксов; она же задаёт служебные колонки, нарезку и срок хранения сырья —
см. [доку хранилища](../architecture/storage.md).
Потребительские запросы и витрины читают сущности DDS через `_v` с явным
списком колонок; `_rep` и `_dist` служат загрузке, диагностике и обслуживанию.
Договор держится конвенцией, а не правами: модель доступа описана в
[ADR 0007](../adr/0007-clickhouse-access.md), договор чтения — в
[доке хранилища](../architecture/storage.md), «Имена объектов».
суффиксов; она же задаёт служебные колонки, нарезку и срок хранения сырых данных
— см. [доку хранилища](../architecture/storage.md). Потребительские запросы и
витрины читают сущности DDS через `_v` с явным списком колонок; `_rep` и `_dist`
служат загрузке, диагностике и обслуживанию. Договор держится конвенцией, а не
правами: модель доступа описана в [ADR 0007](../adr/0007-clickhouse-access.md),
договор чтения — в [доке хранилища](../architecture/storage.md), «Имена
объектов».
Заказы принимаются **пакетным забором** ([ADR
0008](../adr/0008-order-ingestion.md), [ADR
0010](../adr/0010-order-versions-in-ods.md)): чтец топика байтовый, как у событий, но
матвью к нему не привязана, и сырьё забирает шаг, которым управляет Airflow —
одно прямое чтение вставляет порцию в `stg.orders_raw` с `_load_id` запуска.
Один следующий `task_id` двумя последовательными запросами пишет годные строки
и ошибки из того же среза. `ods.order` выбирает текущую версию по максимальной
`snapshot_date` ([ADR 0014](../adr/0014-order-version-snapshot-date.md)). Слой
сырья остаётся точкой повтора и разбора одной принятой порции.
0010](../adr/0010-order-versions-in-ods.md)): чтец топика байтовый, как у
событий, но матвью к нему не привязана, и порцию в STG забирает шаг под
управлением Airflow — одно прямое чтение вставляет её в `stg.orders_raw` с
`_load_id` запуска. Один следующий `task_id` двумя последовательными запросами
пишет годные строки и ошибки из того же среза. `ods.order` выбирает текущую
версию по максимальной `snapshot_date` ([ADR
0014](../adr/0014-order-version-snapshot-date.md)). Слой Сырой слой остаётся
точкой повтора и разбора одной принятой порции.
Состав служебных колонок задаёт дока хранилища. Спеке важны два следствия:
`ods.event` и `ods.order` получают метку загрузки `_load_ts`, но версию
@@ -531,31 +530,28 @@ Kafka день переигрывается генератором заново:
пачками), Postgres остаётся только служебной базой Airflow. Смешанность
ландшафта выражена режимами и частотами, а не второй трубой.
## 8. Эталонный мир и опись
## 8. Эталонный мир и паспорт
В git хранится только опись эталонного мира; сам снимок генерируется на
месте — при `make up` и при проверках (решение развилки «Производительность»
карты #26, подробности — [спека генератора](2026-08-01-generator.md),
раздел 5). Снимок — 8 дней, совпадает со стартовым миром: обещание в 14 дней
снято на этапе 7. Опись несёт
паспорт мира (каноническое зерно, версия генератора), контрольные счётчики
и хеши по дням; проверки «пустой git diff» и «пересгенерируй день N —
сравни хеш» живут на ней. Политика версионирования артефакта (бывший туман
карты #10) закрыта этим же ходом: версионируется опись.
Контрольные числа описи:
В git хранится только паспорт эталонного мира; сам снимок генерируется на месте
— при `make up` и при проверках (решение развилки «Производительность» карты
#26, подробности — [спека генератора](2026-08-01-generator.md), раздел 5).
Снимок — 8 дней, совпадает со стартовым миром: обещание в 14 дней снято на этапе
7. Паспорт несёт шапку с каноническим зерном и версией генератора, контрольные
счётчики и хеши по дням; проверки «пустой git diff» и «пересгенерируй день N —
сравни хеш» живут на нём. Политика версионирования артефакта (бывший туман карты
#10) закрыта этим же ходом: версионируется паспорт. Контрольные числа паспорта:
- по строке на каждый отправленный слепок — хеш байтов: побайтовое обещание
«слепок переснимается и даёт те же байты» опись сторожит наравне с днями;
«слепок переснимается и даёт те же байты» паспорт сторожит наравне с днями;
- заказная сторона: счётчики наблюдаемых классов расхождений после
приоритета; каждый показывает число заказов и хранится только для дня с
закрытым окном (читатель — техническая проверка `classes_vs_inventory`
звена DQ; при N сыгранных днях таких дней N − 7). Отдельных полей для
общего числа заказов и выручки в описи пока нет: для них не назван
читатель;
закрытым окном (читатель — техническая проверка `classes_vs_inventory` звена
DQ; при N сыгранных днях таких дней N − 7). Отдельных полей для общего числа
заказов и выручки в паспорте пока нет: для них не назван читатель;
- контрольные числа идентичности не заводятся: uniq известных пользователей
и число двухкуковых покупателей растут, пока мир едет, а счётчик без
названного читателя в опись не кладётся
([что хранит опись](../architecture/orders/inventory.md)).
названного читателя в паспорт не кладётся ([что хранит
паспорт](../architecture/orders/inventory.md)).
Размер снимка замерен на этапе 7 — запись в разделе «Что проверено»
[карты проверок](../architecture/testing.md).
@@ -572,7 +568,7 @@ v2 стартует пустым, поэтому объём ниже — это
| SQL | DDL по слоям и ролям (ON CLUSTER, Replicated*, Distributed; раскладка файлов — в доке хранилища) + трансформации событий, заказов, identity, сверки + словарь | L — ~12–15 файлов, главная сложность |
| Airflow | DAG'и по образцу v1: etl_pipeline (партиционная переобработка), world_init/next_day, helpers; первый даг — переливка слепка — приходит раньше, этапом 3 | M — ~5–6 файлов |
| Superset | датасеты + дашборд с тремя новыми сюжетами | M — 2 файла |
| Эталонный мир | пересборка снимка на месте, счётчики описи, чек-скрипты | M–L |
| Эталонный мир | пересборка снимка на месте, счётчики паспорта, чек-скрипты | M–L |
| Мониторинг | дашборды Grafana «данные», «кластер», «запросы»; ClickHouse источником данных, панели на SQL; Prometheus тонким полом (ADR 0002) | M — конфиги и дашборды |
| Документация | доки v2 пишутся заново (см. раздел 12) | M, в тех же PR |
@@ -619,8 +615,8 @@ v2 стартует пустым, поэтому объём ниже — это
4. Трансформации и витрины: модель DDS заказа, сессии, identity_map,
выручка, сверка A+C.
5. Airflow: `etl_pipeline` (партиционная переобработка).
6. Расхождения B+D и опоздания; счётчики описи.
7. Эталонный мир: опись и пересборка снимка, чек-скрипты. CI-генерация
6. Расхождения B+D и опоздания; счётчики паспорта.
7. Эталонный мир: паспорт и пересборка снимка, чек-скрипты. CI-генерация
снята (спека генератора, раздел 5).
8. Superset-дашборд v2.
9. Мониторинг и runbook «keeper упал / DDL повис в очереди». Состав дашбордов
@@ -658,15 +654,15 @@ ADR 0002 с приёмочными совпадают почти целиком.
расхождение часов клиент/коллектор — туман карты, вернётся своим тикетом.
- Лабы и курс: v2 — другой стенд, лабы для него пишутся с нуля отдельной
работой после этой спеки; редизайн лаб v1 (#7) остаётся в v1 и сюда не
переносится. Исключение — домашки слоя DM: ТЗ витрин менти и даг
самопроверки забраны в этап 4 резолюцией #135, потому что витрина менти и
конвейер, в который она встает, проектируются вместе. Сюда же —
необязательная лаба «свой дашборд в Superset» (#197): она стоит на
витринах домашек DM и продумана до готового ТЗ в этапе 8, тогда как
остальные лабы пока на уровне идей. Единый стиль блока
домашек — за работой учебного пути. Спека даёт будущим лабам только
опорные точки — контрольные числа описи (сверка, идентичность). Явное
следствие: после этапа 9 стенд работает, но учебного пути на нём ещё нет.
переносится. Исключение — домашки слоя DM: ТЗ витрин менти и даг самопроверки
забраны в этап 4 резолюцией #135, потому что витрина менти и конвейер, в
который она встает, проектируются вместе. Сюда же — необязательная лаба «свой
дашборд в Superset» (#197): она стоит на витринах домашек DM и продумана до
готового ТЗ в этапе 8, тогда как остальные лабы пока на уровне идей. Единый
стиль блока домашек — за работой учебного пути. Спека даёт будущим лабам
только опорные точки — контрольные числа паспорта (сверка, идентичность).
Явное следствие: после этапа 9 стенд работает, но учебного пути на нём ещё
нет.
- Инкрементальный ETL (#8) — свой issue.
- Реплики (2×2), HAProxy, репликационная эксплуатация — в лекцию, не в стенд.
- TLS между нодами, настоящее хранилище и ротация секретов, внешние учётные