Files
clickstream-ch-kafka-supers…/docs/specs/2026-07-19-mentee-path-redesign.md
T
ddadmin 8c68d6cd73 docs(specs): спека уточнена после проверки свежим взглядом
- Зачем:
  - три обещания спеки расходились с фактами кода и замеров HITL.
- Что:
  - в путь менти возвращён шаг make superset-init; критерий «терминал
    только make up» поправлен честно.
  - критерий стоимости world_next_day сужен до генерации+manifest:
    ETL full_refresh растёт с миром — явно вынесен в «чего не делаем».
  - проверка профиля ×1 уточнена: runtime-seam уже на daily-wave,
    проверять надо дефолты launch.py и автотесты.
- Проверка:
  - сверка с scripts/run_generated_history_runtime_check.sh, Makefile
    и замерами HITL (ETL 30 с на 110k событий).
2026-07-19 23:20:44 +03:00

163 lines
12 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Редизайн пути менти: мир из артефакта и две ветки роста
Статус: принято, в работе (ветка `feature/mentee-path`).
Источник: ручной HITL-прогон пути менти 2026-07-19 — находки F1F9
(рабочая копия — `.scratch/hitl-findings.md`; постоянный след — история git,
срез `0e312b3`). Решения приняты в обсуждении с пользователем 2026-07-19.
## Проблема
Сегодняшний первый шаг менти — `backfill`: генерация истории с нуля.
Это медленно (день модельной истории — минуты и десятки минут CPU),
а результат беден (6 часов плоского профиля `ci`). Вокруг — ворох трения:
- пульт `generator_control` подсовывает `backfill` дефолтом и носит имя,
непонятное осваивающему стенд;
- два профиля (`ci`/`daily-wave`) путают: менти достаётся плоский тестовый;
- `next-day` спрятан в общем пульте и не годится для расписания:
каждый прогон перечитывает всю историю Kafka заново — стоимость растёт
квадратично по дням, память — линейно (риск OOM);
- готового артефакта в репозитории нет: механизм `import` есть, а
импортировать нечего.
## Цели
- Менти получает богатый мир за секунды-минуты, а не генерирует его.
- Путь менти проходится в Airflow UI пустыми формами, без справочника.
- У всех менти одинаковый мир: числа в лабах воспроизводимы число-в-число.
- Мир можно растить двумя осознанными способами: пакетно по дням и живым
потоком.
- Плановый `next-day` перестаёт дорожать с возрастом мира.
## Целевая модель
**Основной режим менти — `import` эталонного мира.** От восстановленного
состояния расходятся две ветки — это три режима менти (термины — в
`CONTEXT.md`):
- **База: `import`** — загрузить эталонный мир из артефакта в git.
- **Ветка A: `next-day`** — пакетно добавить следующий модельный день.
- **Ветка B: `continue`** — живой поток от той же границы (скорость ×60).
`backfill` уходит мейнтейнеру: это инструмент сборки эталонного мира,
не первый шаг менти (аналогия из соседнего курса Airflow: по умолчанию
загружают готовый первый месяц, а не собирают его генератором).
### Путь менти (UX)
1. `make up` — поднять стенд (единственная команда терминала).
2. Airflow UI: `ddl_init` — создать схему.
3. Airflow UI: `world_init` — Trigger с пустой формой. Дефолтная операция —
`import`, путь к артефакту — дефолтом на эталонный мир. DAG сам заливает
Kafka, запускает ETL и сверяет витрины.
4. `make superset-init` — разовая инициализация дашборда (терминал).
5. Superset — готовый трёхдневный мир.
6. Дальше по выбору лабы: `world_next_day` (кнопка без параметров) или
`make generator-continue` (живой поток).
### Решения
1. **Эталонный мир**: 3 модельных дня на профиле `daily-wave` (суточная
волна видна, есть «средний» день и сравнение день-к-дню). Собирает
мейнтейнер один раз через `backfill`; хранится в git по фиксированному
пути `data/startup_history/` сжатым `xz` (~13 МБ; замер 2026-07-19:
`xz -9e` жмёт артефакт в 48 раз). Формат не меняется: `import` требует
`raw_topics`, сжатие снимает вопрос размера. Паттерн-образец —
`airflow-greenplum-solution` (сид `demo.sql.xz` в git, стрим-распаковка
при загрузке).
2. **Пульт переименовывается: `generator_control` → `world_init`.**
Дефолт формы — `import` (сейчас `backfill` — корень находки F3);
`backfill` и `check` остаются в выпадашке, но уходят из учебных
инструкций в runbook мейнтейнера. Список DAG'ов читается лесенкой:
`ddl_init``world_init``world_next_day`. Цена: история прогонов
старого dag_id теряется (на учебном стенде не жалко), доки и
контрактный тест правятся синхронно.
3. **`world_next_day` — отдельный беспараметрный DAG**: триггернул — день
добавился. `schedule` прописан, но DAG paused и `catchup=False`:
процесс тяжёлый, автозапуск включается осознанно (шаг лабы), живой
рост мира и так даёт ветка `continue`.
4. **Инкрементальные счётчики manifest — предусловие расписания.**
Накопительное состояние счётчиков (суммы, множества uid/click_id,
катящаяся контрольная сумма) переезжает в state/manifest; новый день
только добавляется. Полная перечитка Kafka уходит: стоимость дня
становится ~постоянной (сейчас день 2 — 638 с и растёт), риск OOM
снимается. Разбор по коду — hitl-findings, F9.
5. **Один учебный профиль**: `daily-wave` (волна, ×60). `ci` (×1, плоско,
6h) — служебный для автотестов, менти не предлагается. Runtime-seam-
проверка уже идёт на `daily-wave`; перед слиянием проверить остальных
потребителей `ci` — дефолты `launch.py` и автотесты, где профиль зашит.
## Чего здесь не делаем
- **Не параллелим генерацию** — ломает детерминизм (один поток ГПСЧ,
переходящие визиты); корень стоимости не в ней, а в перечитке (F9).
- **Не трогаем гео-фактуру** — отдельная спека по ADR-0006.
- **Не мигрируем лабы курса** (`docs/course/`) — они отстали от реальности
и потребуют редизайна под три режима; отдельная работа, зафиксирована
issue в трекере.
- **Не чиним здесь F5** (быстрый разлогин Airflow/Superset) **и F4**
(JS-ошибка Grid) — отдельные issues вне фичи.
- **Не включаем расписание по умолчанию** и не занимаемся retention сверх
инкрементальных счётчиков.
- **Не делаем инкрементальный ETL**: `world_next_day` по-прежнему зовёт
`full_refresh`, его стоимость растёт с миром (на текущих объёмах —
десятки секунд). Известная цена; исторический план —
`plans/incremental-etl-v2.md` (legacy).
## Форма работ
Четыре дочерних issue (GitHub, по контракту `docs/agents/issue-tracker.md`;
корневой issue ссылается сюда):
1. **Эталонный мир**: сборка 3-дневного артефакта, `xz`-хранение в git,
стрим-распаковка на `import`, дефолтный путь в форме.
2. **Поверхность DAG'ов**: переименование в `world_init`, дефолт `import`,
вынос `world_next_day` беспараметрным DAG'ом с paused-расписанием,
синхронная правка доков и контрактных тестов.
3. **Инкрементальные счётчики manifest** (без них расписание не включать).
4. **Один учебный профиль**: `daily-wave` — учебный дефолт, `ci`
служебный; проверка независимости runtime-seam-теста от ×1.
Зависимости: (1) и (4) сцеплены (эталонный мир собирается на `daily-wave`);
(3) блокирует включение расписания из (2), но не сам DAG.
## Проверка
- Чистый стенд: путь менти из раздела UX проходится пустыми формами;
терминал — только `make up` и `make superset-init`.
- `import` эталонного мира — секунды-минуты, не десятки минут.
- После `import` у любого менти совпадают manifest-числа эталонного мира
(события, визиты, пользователи, контрольная сумма).
- Задача генерации+manifest в `world_next_day` на дне N по времени
~равна дню 1 (ETL `full_refresh` растёт с миром — это вне скоупа,
см. «Чего не делаем»); `make generated-history-chain-check` зелёный
на стыках.
- `make test` / `make lint` зелёные; профиль `ci` продолжает обслуживать
автотесты.
## Решения и отклонённые варианты
- **Без артефакта, просто ускорить backfill** — отклонено: время менти и
воспроизводимость (общий файл надёжнее «одинаковой генерации у всех»).
- **Мир «из коробки» при `make up`** — отклонено: механизм становится
невидимым, магия в учебном стенде мстит; явный `import` — учебная
ценность и общее начало обеих лаб.
- **Расписание включённым по умолчанию** — отклонено: эпизодический стенд,
тяжёлый процесс, сюрпризы catchup.
- **Три тонких DAG вместо пульта** — отклонено: плодит сущности; пульт с
правильным дефолтом + один тонкий `world_next_day` достаточно.
- **git-lfs / релизные ассеты для артефакта** — отклонено: после `xz`
артефакт помещается в обычный git.
## Влияние на документацию
- `README.md`, `docs/OPERATIONS.md`, `docs/ARCHITECTURE.md`,
`docs/REPO_MAP.md` — новый путь менти и имена DAG'ов (в тех же PR, что
и изменения).
- `docs/runbooks/startup-history.md``backfill`/сборка эталонного мира
переезжают сюда как процедура мейнтейнера; дополнить про размер и
хранение.
- `CONTEXT.md` — термины «мир (стенда)», «эталонный мир», «три режима
менти» (добавлены этой же спекой).
- Лабы `docs/course/` — сознательно не здесь (см. «Чего не делаем»).