Files
clickstream-data-platform/generator/pyproject.toml
T
ddadminandClaude Opus 5 a61f7934ec feat(generator): сериализатор, приёмники, проигрыватель и запуск контейнером
- Зачем:
  - до сих пор генератор умел собирать день, но не умел его отдать: топик
    hits наполнялся пробником, а не настоящими данными. Тикет #41 доводит
    события до стенда и закрывает форму на проводе, на которую обопрётся
    типизированный ODS (#43).
  - сериализатор один по решению спеки: второе место, печатающее событие в
    JSON, разошлось бы с первым молча.
- Что:
  - serialize.py — канонический сериализатор на orjson: единственное место,
    где событие целиком становится JSON; 47 ключей всегда, «пусто» это
    пустое значение, даты ISO-8601, ecommerce строкой. Вложенный блок
    ecommerce в commerce.py вторым сериализатором не считается — правило
    про событие, а не про блок внутри него.
  - sinks.py — приёмники: файл (одно событие — одна строка) и Kafka (одно
    событие — одно сообщение). Ключа у сообщения нет: WatchID уникален,
    ключом он был бы ключом лишь на вид.
  - player.py, cli.py — проигрыватель и интерфейс запуска: режимы batch и
    live (темп ×60), несколько дней одним запуском, ограниченная пачка,
    раздельные тайминги генерации и доставки, лаг в логе.
  - день на оси и имя топика умолчаний не имеют: параметр, описывающий
    среду или позицию, приходит от зовущего, иначе отказ до генерации.
    Умолчания зерна, числа дней и темпа остаются — они описывают мир.
  - generator/Dockerfile — свой образ: зависимости из uv.lock, база
    закреплена до патча, раскладка репозитория сохранена ради каталога
    товаров. Образ Airflow не тронут.
  - разовая служба compose под профилем, цели generate-batch и
    generate-live, .dockerignore, tmp/ в .gitignore.
  - решения внесены в спеку (разделы 4, 8, 9), быстрый старт — в README.
- Проверка:
  - make test 406 passed, make lint, make typecheck, make config-test.
  - побайтовый детерминизм: два прогона дня в независимых процессах дают
    один sha256; день в контейнере совпадает с днём на машине.
  - на стенде: пакетный день доехал до stg.hits_raw_dist, счёт по
    Distributed сошёлся — отправлено 50626, в таблице 50626.
  - топик прочитан обеими нодами: clickhouse-01 раздел 0 (26368),
    clickhouse-02 раздел 1 (24258).
  - живой день: модельное время 01:00 на 60-й секунде, 02:00 на 120-й —
    темп ×60, лаг печатается.
  - форма на проводе в колонке raw: даты читаются глазами, ecommerce лежит
    строкой.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-07 12:05:11 +03:00

42 lines
1.8 KiB
TOML

[project]
name = "clickstream-generator"
version = "0.1.0"
description = "Генератор кликстрима учебного стенда: контракт схемы события и модельный мир"
readme = "README.md"
# Верхняя граница — не педантизм: обещание побайтовой воспроизводимости
# держится на зафиксированных версиях (спека генератора, раздел 2).
requires-python = ">=3.14,<3.15"
dependencies = [
"numpy>=2",
"orjson>=3.11.9",
]
[project.optional-dependencies]
# Клиент Kafka — необязательная часть пакета: без него генератор пишет в файл
# и остаётся переносимым (спека генератора, раздел 9). Приёмник импортирует
# клиента внутри функции, поэтому пакет без этой группы живой.
kafka = ["confluent-kafka>=2.6"]
[dependency-groups]
dev = [
"pytest>=8",
# Тот же клиент нужен и на машине разработчика: иначе ty не разберёт
# импорт приёмника, а ruff и тесты видели бы половину кода.
"confluent-kafka>=2.6",
"ruff>=0.15",
# Типчекер; молод (0.0.x), но версия закреплена в uv.lock. Настройка
# сверена с доками Astral через Context7: запуск `uv run ty check`,
# правил по умолчанию пока достаточно.
"ty>=0.0.65",
]
[build-system]
requires = ["uv_build>=0.11.21,<0.12.0"]
build-backend = "uv_build"
[tool.pytest.ini_options]
testpaths = ["tests"]
[tool.ruff.lint]
select = ["E", "F", "I", "UP", "B"]