Files
clickstream-ch-kafka-supers…/docs/adr/0004-steady-stream-synthetic-generator.md
T
Dmitry DementievandClaude Fable 5 6efa031023 docs(generator): добавлена мат-спека модели и исправлен профиль сида
- Зачем:
  - закрыть Open questions спеки формы доработки перед передачей на
    реализацию; адверсариальное ревью показало, что прежние ориентиры
    (популяция/паузы/интенсивность) взаимно несовместимы, а документы
    опираются на неверный факт о сиде («1..7 событий на визит»).
- Что:
  - добавлена docs/specs/2026-06-10-generator-math-model.md: марковская
    цепочка по страницам, формула связи «популяция-интенсивность-пауза»
    (λ по умолчанию 30/мин), кулдаун возврата, правило 30 минут на рестарт,
    критерии приёмки.
  - в CONTEXT.md добавлен профиль сид-датасета (полный замер: длины визитов
    1..27, медиана 10, конверсия 25%, петли и события после /confirmation)
    и исправлено ложное «разброс времени внутри click_id <= 1 мин».
  - исправлен факт «1..7 событий» в KNOWN_ISSUES.md и ADR-0004; критерии
    Validation спеки формы доработки приведены к фактам сида.
- Проверка:
  - перекрёстные ссылки между спеками/ADR/CONTEXT.md открываются; цифры
    профиля сида воспроизводятся скриптом подсчёта по полным data/*.jsonl.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-10 17:32:47 +03:00

81 lines
7.0 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.
# ADR-0004: Steady-stream источник — синтетический иерархический генератор, не реплей
Принято: 2026-06-09
Статус: accepted
Связано: [`generator/KNOWN_ISSUES.md`](../../generator/KNOWN_ISSUES.md) (диагноз
дефекта), [`CONTEXT.md`](../../CONTEXT.md),
[ADR-0002](./0002-specs-as-durable-design-docs.md) (спеки как durable design-доки),
спека [`docs/specs/2026-06-09-generator-rework-hierarchical.md`](../specs/2026-06-09-generator-rework-hierarchical.md)
(форма доработки).
## Решение
Режим `steady-stream` (живой поток на стенде) питается **синтетическим
генератором, переписанным с нуля по иерархической модели** «популяция
пользователей → сессии → события», а **не реплеем статического сида**. Модель
интенсивности текущего генератора (Poisson по тикам + дневной коэффициент +
jitter) сохраняется. Режим `bootstrap` (статический сид `data/*.jsonl`) и уроки
0–6 остаются прежними — генератор **сосуществует** с сидом, не заменяет его.
## Контекст
Проект сменил назначение на учебный стенд с курсом. Базовый курс стоит на
статическом сиде, и это осознанно: сид **честен внутри визита** (`click_id`
группирует несколько событий — настоящая воронка; по полному замеру 2026-06-10 —
1..27 событий, медиана 10, см. профиль сид-датасета в `CONTEXT.md`). Но у сида
два потолка, которые
сид принципиально не закрывает:
- **`users == sessions`** — каждый пользователь имеет ровно один `click_id` (1:1),
возвращающихся пользователей нет (см. `CONTEXT.md`).
- **одноразовость** — сид заливается батчем; не видно, как ClickHouse и витрины
ведут себя на непрерывном живом потоке.
Нужен режим, в котором стенд **живёт и движется** на правдоподобных данных
(воронка + жизнеподобные колебания интенсивности), при **скромном объёме** (у
менти может не быть мощного железа — на объём/стресс не закладываемся).
Двойная учебная ценность — ключевой критерий выбора: ценны не только *данные*
(живой стенд + честная пирамида `users < sessions < events`), но и **сам
генератор как объект изучения** — его генеративная модель достойна того, чтобы её
разбирать в курсе.
Текущая реализация генератора не дорабатывается инкрементально: у неё
концептуальный дефект модели сущностей (свежий `click_id` на каждое событие
схлопывает иерархию — см. `generator/KNOWN_ISSUES.md`), переписываем с нуля.
## Рассмотренные варианты
- **A — синтетический иерархический генератор (принято).** Популяция юзеров с
постоянным `user_domain_id` → 1..N сессий (`click_id` на сессию) → 1..M
упорядоченных по времени событий с правдоподобной воронкой. Единственный
вариант, дающий возвращающихся пользователей (`users < sessions < events`) и
учебную ценность самого моделирования. Цена — самый большой объём работы и
риск ошибиться в статистической модели.
- **C — реплей честного сида на часах.** Лить реальные записи сида в Kafka во
времени, переписывая `event_timestamp` в «сейчас», зацикливая пул и модулируя
rate. **Отклонено.** Дёшев и даёт гарантированно честную воронку почти без
риска, **но**: (1) обходит ровно ту генеративно-модельную часть, ради учебной
ценности которой всё и затевается; (2) наследует вырождение `users == sessions`
из сида — полную пирамиду не даёт никогда; (3) «бесконечность» = зацикленный
конечный пул.
- **B — минимальный «живой» генератор с грубой воронкой.** Тот же rewrite, но
воронка на фиксированных вероятностях, без глубины. Отклонено как
половинчатое: числа воронки менее убедительны, а вопрос возвратов всё равно
надо решать — то есть основной сложности не избегает.
## Последствия
- Режим `steady-stream` фиксируется как синтетическая генерация; направление
переоткрывать не нужно (типовой вопрос «почему не реплей?» закрыт здесь).
- `bootstrap`-сид и уроки 0–6 не трогаем; живой поток подаётся отдельным уроком 7.
- Контракт данных потока: здоровая пирамида `users < sessions < events`,
монотонное время внутри сессии, `click_id` переиспользуется внутри сессии.
Этот контракт наследуют будущие артефакты (спека доработки, урок 7, возможные
правки витрин).
- Детальная архитектура/требования — в спеке `2026-06-09-generator-rework-hierarchical.md`.
- **Статистическая модель** (распределения событий/сессия, сессий/пользователь,
межсессионные паузы; нужен ли настоящий session-timeout; персистентность
популяции через рестарты) **выносится в отдельную follow-up-спеку** и здесь
намеренно не фиксируется.