Backend (quarter_dump_lookup.py): - _acquire_harvest_lock: Redis SETNX TTL=120s на quarter, защищает от burst N concurrent analyze, ставящих N одинаковых harvest task в очередь - _trigger_harvest: использует lock перед apply_async, возвращает False если lock уже взят (другой запрос триггернул раньше) - make_empty_result/EMPTY_DUMP_RESULT: новое поле harvest_eta_seconds в nspd_dump dict, типичный harvest_quarter = 60с - /analyze: пробрасывает поле через nspd_dump dict (нет typed schema — response_model=None для /analyze endpoint, dict уходит как есть) Frontend (NspdFreshnessBadge, NspdZoningBlock): - Countdown «НСПД: загрузка ~Nс» вместо бесконечного спиннера - После остановки countdown (remaining=0) NspdZoningBlock показывает «загрузка дольше обычного» + ссылку на ПКК вместо infinite skeleton Tests: 5 новых unit + 2 для empty_result schema (всего +7, pass) Closes #234 (UX-side; data-side resolves когда Sub-PR B + D merged). |
||
|---|---|---|
| .. | ||
| __init__.py | ||
| best_layouts.py | ||
| cadastre_fetch.py | ||
| competitors.py | ||
| filters.py | ||
| gate_verdict.py | ||
| layout_signature.py | ||
| layout_velocity_refresh.py | ||
| noise_loader.py | ||
| parser.py | ||
| poi_loader.py | ||
| pzz_loader.py | ||
| quarter_dump_lookup.py | ||
| quarter_price_refresh.py | ||
| scorer.py | ||
| velocity.py | ||
| weight_profiles.py | ||