diff --git a/.scratch/feature-data-generator/issues/02-5-generator-service-cleanup.md b/.scratch/feature-data-generator/issues/02-5-generator-service-cleanup.md new file mode 100644 index 0000000..1cd0022 --- /dev/null +++ b/.scratch/feature-data-generator/issues/02-5-generator-service-cleanup.md @@ -0,0 +1,52 @@ +Status: ready-for-agent + +# Уборка сервиса генератора перед активными визитами + +## What to build + +Разнести текущий `generator/generator.py` на понятные модули, не меняя внешнее +поведение генератора. Цель — подготовить код к задаче 03, где появятся активные +визиты между тиками. + +Источник решений: `docs/specs/2026-06-11-generator-service-cleanup.md`, +`docs/specs/2026-06-10-generator-math-model.md`, задачи 01-03 в этом каталоге. + +## Acceptance criteria + +- [ ] Генеративная модель визита отделена от Kafka, состояния, метрик и + сервисного цикла. +- [ ] Код загрузки и индексации JSONL-сида вынесен из сервисного слоя. +- [ ] Расчёт интенсивности отделён от генерации одного визита. +- [ ] Kafka publisher, Kafka-state и создание служебных топиков не смешаны с + генеративной моделью. +- [ ] `generator/generator.py` остаётся тонкой точкой входа или совместимым + фасадом, чтобы не ломать запуск и тесты без причины. +- [ ] `generate_tick_batch()` не остаётся в чистой генеративной модели визита: + он вынесен в переходный тиковый слой и подготовлен к замене активными визитами + в задаче 03. +- [ ] Dockerfile и запуск контейнера обновлены под новую структуру файлов. +- [ ] Все существующие тесты генератора проходят. +- [ ] README генератора кратко отражает новую структуру файлов. + +## Non-goals + +- Не реализовывать активные визиты между тиками. +- Не добавлять популяцию пользователей и возвраты. +- Не вводить состояние версии 2. +- Не менять Kafka-топики и формат событий. +- Не удалять `generator_batch_history`, если отдельно не доказано, что он больше + не нужен. + +## Blocked by + +- `.scratch/feature-data-generator/issues/02-visit-page-path-and-monotonic-time.md` + +## Blocks + +- `.scratch/feature-data-generator/issues/03-tick-stream-with-active-visits.md` + +## Comments + +Задача появилась после разбора распухания сервиса: первые два среза уже внесли +новую модель визита, а третий срез добавит состояние активных визитов. Перед ним +нужно отделить модель, тиковый слой и Kafka-интеграцию. diff --git a/.scratch/feature-data-generator/issues/03-tick-stream-with-active-visits.md b/.scratch/feature-data-generator/issues/03-tick-stream-with-active-visits.md index 2caba4f..5a50ca3 100644 --- a/.scratch/feature-data-generator/issues/03-tick-stream-with-active-visits.md +++ b/.scratch/feature-data-generator/issues/03-tick-stream-with-active-visits.md @@ -31,6 +31,6 @@ Status: ready-for-agent ## Blocked by - `.scratch/feature-data-generator/issues/02-visit-page-path-and-monotonic-time.md` +- `.scratch/feature-data-generator/issues/02-5-generator-service-cleanup.md` ## Comments - diff --git a/docs/specs/2026-06-11-generator-service-cleanup.md b/docs/specs/2026-06-11-generator-service-cleanup.md new file mode 100644 index 0000000..5a9cc03 --- /dev/null +++ b/docs/specs/2026-06-11-generator-service-cleanup.md @@ -0,0 +1,130 @@ +# Уборка сервиса генератора перед активными визитами + +Дата: 2026-06-11 +Статус: Draft +Связано: [спека математической модели](./2026-06-10-generator-math-model.md), +[спека иерархической переработки](./2026-06-09-generator-rework-hierarchical.md), +[`generator/KNOWN_ISSUES.md`](../../generator/KNOWN_ISSUES.md), +задачи `.scratch/feature-data-generator/issues/01..07`. + +## Problem + +После первых двух срезов новый генератор уже умеет строить связанный визит и +путь по страницам, но сервисный код начал распухать. В одном +`generator/generator.py` смешаны генеративная модель, чтение сида, тиковая +логика, Kafka, состояние, история пачек, метрики и запуск сервиса. + +Следующая задача — активные визиты между тиками — добавит новый слой состояния. +Если продолжить в текущей форме, этот слой ляжет поверх временного +`generate_tick_batch()`, который набирает тик целыми визитами и не соответствует +целевой модели. + +## Goals + +- Разнести код генератора по понятным учебным модулям без изменения внешнего + поведения сервиса. +- Подготовить место для задачи 03: активные визиты должны появиться в отдельном + тиковом слое, а не внутри большого `generator.py`. +- Явно отделить временные части старой модели от контрактов, которые надо + сохранить. +- Сохранить прежние команды запуска, Kafka-топики, формат сообщений и полезные + метрики. + +## Non-goals + +- Не реализовывать активные визиты из задачи 03. +- Не добавлять популяцию пользователей, возвраты, калибровку интенсивности или + состояние версии 2. +- Не менять DDL, ETL, витрины или Superset. +- Не делать большой перепил поведения генератора под видом уборки. + +## Current state + +`generator/generator.py` содержит около тысячи строк и несколько разных +ответственностей: + +- `Config` — настройки; +- `EventDictionary` — чтение и индексация JSONL-сида; +- `EventGenerator` — генерация визитов, страниц, пауз и интенсивности; +- `BatchRecord`, `KafkaBatchHistory` — история пачек в Kafka; +- `GeneratorState`, `KafkaStateManager` — состояние версии 1; +- `KafkaPublisher`, `ensure_topics` — работа с Kafka; +- `GeneratorService` — метрики, запуск, основной цикл. + +`generate_tick_batch()` сейчас является переходным механизмом: он добирает +событийный бюджет полными визитами. Это допустимо после задач 01-02, но должно +быть заменено в задаче 03 тиковым слоем с активными визитами. + +## Options considered + +- **Минимальная уборка в одном файле.** Быстро, но файл останется тяжёлым и + следующая задача снова его раздует. +- **Разнести код по модулям.** Чище для чтения, лучше соответствует учебной + цели и даёт место для активных визитов. +- **Сначала выбросить лишнее.** Может заметно сократить код, но требует решения, + какие сервисные возможности больше не нужны. + +## Recommended approach + +Принят смешанный вариант: разнести код по модулям и по ходу явно отметить или +удалить очевидно временные части, если они не являются внешним контрактом. + +Целевая форма: + +- `generator/config.py` — конфигурация и её валидация; +- `generator/dictionary.py` — загрузка и индексы исходных JSONL; +- `generator/generation.py` — чистая генеративная модель визита, страниц и пауз; +- `generator/intensity.py` — расчёт бюджета активности: Пуассон, часовой + коэффициент, jitter; +- `generator/kafka_io.py` — Kafka publisher, создание топиков, Kafka-state; +- `generator/state.py` — сериализуемое состояние генератора; +- `generator/service.py` — основной сервисный цикл и метрики; +- `generator/generator.py` — тонкая точка входа или совместимый фасад для + старых импортов тестов. + +Сейчас `generator/` не оформлен как Python-пакет: тесты импортируют +`generator/generator.py` как модуль `generator`, а Dockerfile копирует только +`generator.py`. В рамках этой уборки нужно сохранить совместимость импортов и +обновить контейнерный запуск под новую структуру файлов; превращать каталог в +пакет через `__init__.py` не требуется. + +Точное разбиение может быть чуть проще, если это уменьшит шум, но граница между +моделью генерации, тиковым runtime и Kafka-интеграцией должна быть явной. + +## Decisions and rejected alternatives + +- **Принято:** уборка идёт перед задачей 03. Причина: активные визиты добавляют + новый слой состояния, и его нельзя удобно встроить в текущий монолит. +- **Принято:** внешнее поведение генератора не меняется. Цель задачи — форма + кода, а не новая модель данных. +- **Принято:** `generate_tick_batch()` считать временным переходным механизмом. + После задачи 03 тик должен выпускать созревшие события активных визитов. +- **Отклонено:** ограничиться перестановкой функций внутри `generator.py`. + Это не решает учебную читаемость и не создаёт ясного места для следующих + срезов. +- **Отклонено:** удалить историю пачек без отдельного решения. Её можно + упростить или вынести, но пока не доказано, что она не нужна для демо и + мониторинга. + +## Validation + +- Все существующие тесты генератора проходят. +- Импорты, которые используют тесты, либо обновлены, либо сохранены через фасад + `generator/generator.py`. +- `generate_batch()` продолжает строить один связанный визит с монотонным + временем, как после задач 01-02. +- Временный `generate_tick_batch()` не остаётся в чистой модели визита: он вынесен + в переходный тиковый слой или явно подготовлен к замене задачей 03. +- Сервисный контур продолжает публиковать в те же четыре Kafka-топика: + `browser_events`, `location_events`, `device_events`, `geo_events`. +- Dockerfile и запуск контейнера учитывают новую структуру файлов. +- В коде есть ясное место, куда задача 03 добавит активные визиты без расширения + Kafka-слоя и без переписывания генерации одного визита. + +## Documentation impact + +- После реализации уборки обновить `generator/README.md`: описать новую + структуру файлов и убрать формулировки, которые привязаны к одному + `generator.py`. +- Если по ходу будет принято решение удалить или заменить `generator_batch_history`, + это должно быть отдельно отражено в README и в задаче реализации.