feat(generator): добавлен поток активных визитов по тикам

- Зачем:
  - генератор должен выпускать события визита по запланированным тикам, не приклеивая весь визит к одному запуску.
- Что:
  - добавлен тиковый слой `TickStreamGenerator` с активными визитами и выпуском созревших событий.
  - добавлена валидация потолка активных визитов относительно потолка популяции.
  - сохранён событийный смысл `event_budget` и добавлен регрессионный тест против разгона интенсивности.
- Проверка:
  - `uv run --with-requirements generator/requirements.txt pytest generator/tests -q` — 81 passed.
This commit is contained in:
Dmitry Dementiev
2026-06-11 15:32:53 +03:00
parent 642789d484
commit d8da27187e
9 changed files with 316 additions and 48 deletions
+12 -6
View File
@@ -2,9 +2,9 @@
> Перед использованием как источник витрин прочитать
> [KNOWN_ISSUES.md](./KNOWN_ISSUES.md): часть старого дефекта уже исправлена
> (один `click_id` на визит, путь по страницам, монотонное время), но популяция
> возвращающихся пользователей и полноценное состояние активных визитов ещё
> остаются следующими шагами.
> (один `click_id` на визит, путь по страницам, монотонное время, активные
> визиты между тиками), но популяция возвращающихся пользователей и
> восстановление активных визитов после рестарта ещё остаются следующими шагами.
Автономный генератор событий для Kafka с режимом `steady-stream`.
@@ -27,7 +27,7 @@ generator-service -> Kafka topics -> (потребители отдельно)
| `src/clickstream_generator/dictionary.py` | загрузка и индексы исходных JSONL |
| `src/clickstream_generator/generation.py` | генерация одного связанного визита |
| `src/clickstream_generator/intensity.py` | расчёт событийного бюджета тика |
| `src/clickstream_generator/runtime.py` | временный тиковый слой до активных визитов |
| `src/clickstream_generator/runtime.py` | тиковый слой: активные визиты и выпуск созревших событий |
| `src/clickstream_generator/kafka_io.py` | Kafka publisher, история batch, Kafka-state и служебные топики |
| `src/clickstream_generator/state.py` | сериализуемое состояние генератора |
| `src/clickstream_generator/metrics.py` | Prometheus-метрики |
@@ -38,8 +38,10 @@ generator-service -> Kafka topics -> (потребители отдельно)
- Публикуем постепенно, **короткими тиками** (по умолчанию каждые 5 секунд)
- На каждом тике отправляем небольшую порцию сообщений
- Держим целевую интенсивность `events/min` без крупных минутных batch: тик
набирается из одного или нескольких визитов до рассчитанного бюджета событий
- Держим целевую интенсивность `events/min` без крупных минутных batch:
рассчитанный событийный бюджет тика планирует новые визиты и списывается по
фактической длине этих визитов, а события выходят позже по своим
запланированным меткам времени
- Распределяем события по 4 топикам:
- `browser_events`
- `location_events`
@@ -48,6 +50,8 @@ generator-service -> Kafka topics -> (потребители отдельно)
- Публичный вызов генеративного ядра строит один визит: общий `click_id`,
разные `event_id`, общий device/geo-контекст, путь по страницам воронки и
строго растущие запланированные `event_timestamp`.
- Тиковый слой хранит активные визиты между вызовами и выпускает только события,
у которых наступил `event_timestamp`; завершённые визиты удаляются из памяти.
- Сохраняем связи `event_id <-> location`, `click_id <-> device/geo`.
## Конфигурация (env)
@@ -61,6 +65,8 @@ generator-service -> Kafka topics -> (потребители отдельно)
| `GEN_MIN_EVENTS_PER_TICK` | Минимум событий за тик | `5` |
| `GEN_MAX_EVENTS_PER_TICK` | Максимум событий за тик | `50` |
| `GEN_MAX_SESSION_EVENTS` | Потолок длины одного визита, защита от петель | `30` |
| `GEN_MAX_ACTIVE_SESSIONS` | Потолок одновременных активных визитов | `200` |
| `GEN_POPULATION_MAX` | Будущий потолок популяции пользователей; сейчас нужен для валидации активных визитов | `300` |
| `GEN_DATA_DIR` | Путь к JSONL файлам | `/data` |
| `GEN_SEED` | Сид для воспроизводимости | — |
| `GEN_ENABLED` | Включить генерацию | `true` |