Files
clickstream-ch-kafka-supers…/docs/adr/0004-steady-stream-synthetic-generator.md
ddadminandClaude Opus 4.8 49512b190a docs(generator): зафиксированы источник аналитики и стартовая история
- Зачем:
  - генератор даёт здоровую пирамиду, и стенду нужен единый источник аналитики вместо вырожденного статического сида.
- Что:
  - добавлен ADR-0006: генерация — единственный источник аналитики, статический сид становится архивным (кладовка значений до синтеза фактуры).
  - добавлена спека модельного времени: точка отсчёта, заливка прошлого, стартовая история, сохранение состояния, воспроизводимость и проверка в два шага.
  - в ADR-0004 и ADR-0005 добавлены указатели вперёд на ADR-0006 и спеку.
- Проверка:
  - чтение документов; перекрёстные ссылки между ADR-0004/0005/0006 и спекой согласованы.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-14 14:47:20 +03:00

7.6 KiB

ADR-0004: Steady-stream источник — синтетический иерархический генератор, не реплей

Принято: 2026-06-09 Статус: accepted Связано: generator/KNOWN_ISSUES.md (диагноз дефекта), CONTEXT.md, ADR-0002 (спеки как durable design-доки), спека docs/specs/2026-06-09-generator-rework-hierarchical.md (форма доработки).

Обновление (2026-06-14): тезис «генератор сосуществует с сидом, не заменяет его» частично пересмотрен в ADR-0006 — для аналитического контура стенда генерация заменяет статический сид; сид выводится из оборота (целевым образом — полностью). Сосуществование остаётся верным лишь для переходной роли сида (палитра атрибутов / dev-фикстура).

Решение

Режим 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-спеку и здесь намеренно не фиксируется.