Зачем Стенд поднимался пустым, и всякая приёмка следующих этапов начиналась с ручной заливки данных. Теперь `make up` сам приводит стенд к одному и тому же состоянию, а в git лежит то, чем это состояние проверяется. Что - Опись мира `data/world-inventory.json`: паспорт (зерно, версия генератора, хеш каталога) и по строке на каждый из восьми дней — дата, число событий, хеш байтов. Собирается `make inventory`, свежесть сторожит `test_inventory.py` — тем же способом, что свежесть описания выгрузки. - Разовая служба `world-init` вышла из-под профиля и играет в топик восемь дней при каждом подъёме; зависимый у неё — `airflow-init`, иначе `--wait` считает успешно отработавшую службу упавшей. - `scripts/wait-for-world.sh` — вторая половина `make up`: приём асинхронный, поэтому ждать надо доезда до `ods.event`, а не завершения заливки. Ограниченный цикл опроса, не пауза наугад. - Девятая проверка `make check-clickhouse`: подневный счёт событий против описи, рамка по датам стартового мира, счёт через `FINAL`. При расхождении называет, где искать, — в событиях или в браке. - Порог «день ≤ 30 с» снят из спеки генератора в обоих местах: замер дал 1,7 с, порог был выше факта в восемнадцать раз. На его месте — замеры с датой. Раздел 9 спеки закрыт: открытых вопросов не осталось. - Слова: «манифест» стал описью мира, «зерновой мир» — стартовым миром (решение владельца). Оба заведены в словарь CONTEXT.md. Проверка `make clean && make up` с нуля — 2 м 50 с, доехало ровно 401 185 событий. `make check-clickhouse` зелёный (8 с), `make smoke` зелёный (9 с), `make test` — 407 тестов за 71 с, `make lint`, `make typecheck`, `make config-test` зелёные. Что проверка умеет краснеть, снято двумя поломками: снос партиции 2026-06-03 дал диагноз «не доехали до ODS», негодная строка в сырье — «сломан разбор». Строки опыта убраны, день переигран, счёт вернулся. Тест свежести проверен молчаливой правкой цены в каталоге: покраснел. Ссылка: #42
28 lines
1.6 KiB
Python
28 lines
1.6 KiB
Python
"""Проверка описи мира: та ли она, что собирается из кода сегодня.
|
|
|
|
Опись собирается из кода, значит разойтись они могут только одним способом —
|
|
код правили, опись не пересобрали. Ровно это здесь и сторожится, тем же
|
|
способом, что свежесть «описания выгрузки».
|
|
|
|
Проверка дорогая — она пересчитывает восемь модельных дней целиком, и это
|
|
единственный способ сравнить хеши: дешевле мир не пересобрать. Зато краснеет
|
|
она там, где надо, — сразу после правки генератора, а не через полчаса на
|
|
поднятом стенде, где расхождение счётчиков выглядит поломкой хранилища.
|
|
"""
|
|
|
|
import json
|
|
from pathlib import Path
|
|
|
|
from clickstream_generator.inventory import build
|
|
|
|
INVENTORY_PATH = Path(__file__).resolve().parents[2] / "data" / "world-inventory.json"
|
|
|
|
|
|
def test_inventory_is_up_to_date():
|
|
stored = json.loads(INVENTORY_PATH.read_text(encoding="utf-8"))
|
|
assert stored == build(), (
|
|
"опись мира отстала от кода — пересоберите: make inventory."
|
|
" Разошлись хеши дней и каталога — правили data/catalog/products.csv;"
|
|
" разошлись только дни — правили генератор"
|
|
)
|