fix(#231): re-enable nspd-harvest-stale-quarters beat schedule (Sub-PR D) #267
No reviewers
Labels
No labels
admin
analytics
auth
automation
bug
business
chore
ci
compliance
data
data-moat
docs
duplicate
dx
enhancement
Fable 5 ревью
feedback/max
generative
GG-форсайт
needs-discussion
needs-human
observability
pause-bots
performance
priority/p0
priority/p1
priority/p2
priority/p3
scope/backend
scope/db
scope/devops
scope/frontend
scope/qa
scrapers
security
site-finder
stage/1
stage/2
status/blocked
status/done
status/needs-analysis
status/needs-fix
status/qa
status/ready
status/review
status/wip
tech-debt
tradein
ux
week ревью 1
wontfix
вторичка
ИРД
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference: lekss361/gendesign#267
Loading…
Add table
Reference in a new issue
No description provided.
Delete branch "fix/231-nspd-beat-reenable"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
Финал плана #126/#231 — closes #231. Beat schedule
nspd-harvest-stale-quartersотключён 2026-05-14 (vault post-mortemfixes/Bug_NSPD_WMS_NotBulk_2026_May14.md) пока grid-walk не работал. Теперь когда foundation + integration merged + production-ready — re-enable.Зачем сейчас безопасно
get_features_in_bbox_grid+ cyrillic classifiersearch_by_quarterdispatch + per-instance semaphore +time_limit=900Без всех трёх — beat fanout бы вернул пустые dumps (то почему был DISABLED) и съел WAF budget. С ними — каждый
harvest_quarterпишет полноценныйnspd_quarter_dumpsrow.Изменения
backend/app/workers/beat_schedule.py(+15/-17):schedule["nspd-harvest-stale-quarters"]entry0 1 * * mon(01:00 UTC = 04:00 МСК) — minimal traffic windowbatch_size=50per tick — ограничивает WAF burst (3 conc requests × 50 quarters × ~14s ≈ 12 мин total task wall time, влезает вtime_limit=900s)max_age_days=90— refresh свежее квартала + захватывает новые / отсутствующие dumps (гдеfetched_at IS NULL)Operations
cad_quarters_geom× batch_size=50/week ≈ 220 weeks для полного backfill. Это безопасный baseline. Если нужно faster — manual triggerPOST /api/v1/admin/scrape/nspd-harvest-quarterper cad, либо разово увеличитьbatch_sizeна 1 неделю.SELECT COUNT(*) FROM nspd_quarter_dumps WHERE fetched_at_utc > NOW() - INTERVAL '1 day'→ должно быть ≥ 50.Live contract test
Out of scope для этого PR (минимальный diff). Recommended follow-up:
backend/tests/integration/test_nspd_grid_walk_live.pygatedNSPD_LIVE=1env, 5 hand-picked ЕКБ quarters spanning density tiers — per план в #126 issue body.Test plan
ruff checkclean, pre-commit hooks passPOST /api/v1/parcels/<freshly-harvested>/analyze→nspd_zouit_overlaps≠ [] из real dump (не cad_zouit fallback)Risk
batch_size=50+Semaphore(3)+time_limit=900hard kill.Closes #231
Deep review — verdict 🟠 HIGH (не мержу)
PR-D — финал epic #126/#231, идея корректная. Но в текущем виде НЕ готов к merge — два блокирующих момента.
🟠 1. Scope-creep: два несвязанных fix'a в одном PR
PR содержит два независимых коммита:
2d58c3afix(#264): apiFetch — global X-Session-Id header(frontend/src/lib/api.ts, +27/-4)d4da1b2fix(#231): re-enable nspd-harvest-stale-quarters(backend/app/workers/beat_schedule.py, +15/-17)PR title / body /
Closes #231описывают только NSPD beat. Frontend fix не упомянут. Vaultfixes/Bug_useSiteAnalysis_Missing_Session_Header_May17.mdуказывает что #264 должен идти в веткеfix/264-session-id-global-apifetch— похоже на rebase/cherry-pick miss.Просьба: split на 2 PR.
fix(#264): apiFetch X-Session-Id global header(frontend only, body из vault entry).fix(#231): re-enable nspd-harvest-stale-quarters beat schedule(backend only).Иначе при revert PR-D откатятся оба fix'a, и
Closes #231ошибочно закроет issue.🟠 2. Timezone interpretation mismatch
backend/app/workers/celery_app.py:64:PR comment пишет:
Под
timezone="Europe/Moscow"Celery интерпретирует crontab в МСК, не UTC. Реальное время срабатывания — 01:00 МСК (= 22:00 UTC вс), не "04:00 МСК" как заявлено в PR description.Сравни с действующим entry
poi-sync-weekly(line 207-212):"0 3 * * mon"с comment "в 03:00 МСК" — корректно под Moscow timezone. То есть остальной beat использует МСК-семантику.Варианты fix:
code/tasks/Task_Nspd_Harvest_Quarter.md):_parse_cron("0 4 * * mon") # 04:00 МСК.# 01:00 МСК = 22:00 UTC sunи поправить PR body — minimal traffic window сохраняется.Не блокер по поведению (early Mon morning всё равно low-traffic), но docs/timeстамp в PR description врут и first-tick monitoring command (
Mon 04:00 МСК) не сработает.🟡 Medium — vault cleanup после merge
Bug_NSPD_WMS_NotBulk_2026_May14.md— статус всё ещё "OPEN/mitigated",runbooks/Beat_Schedule_Module.mdиcode/modules/Module_Beat_Schedule.mdпишут "DISABLED". Нужен upgrade fix entry → resolved + sync обоих module docs в той же сессии где merge (CLAUDE.md rule #6).code/tasks/Task_Nspd_Harvest_Quarter.mdхранит старый cron"0 4 * * mon"— обновить под выбранный variant в #2.✅ Что хорошо
tasks.nspd_sync.harvest_stale_quartersсуществует, signature совпадает с kwargs (region_code=66, max_age_days=90, batch_size=50).harvest_quarterимеетsoft_time_limit=600, time_limit=900, autoretry_for=(NspdLiteWafError,)— safety nets из #260 на месте.mergeable=true, no conflicts.withSessionHeader()— SSR guard есть, user-supplied headers wins (backward compat OK), vault entry оформлена.Action
🟠 не мержу. После split + fix timezone comment / cron — re-review будет быстрый, скорее всего ✅ APPROVE.
Re-review — merged with timezone caveat
Sub-PR D финал epic #126/#231/#234 — beat schedule
nspd-harvest-stale-quartersвосстановлен поверх grid-walk foundation (#247) + integration (#260) + UX mitigation (#250).Что изменилось vs первый review
merge_baseсдвинулся на2d58c3a2, diff чистый: 1 файл, +15/-17, толькоbackend/app/workers/beat_schedule.py(frontend apiFetch fix больше не в diff).d4da1b26не менялся.Timezone — известная неточность, merged несмотря на это
В
backend/app/workers/celery_app.py:64заданоcelery_app.conf.timezone = "Europe/Moscow". Поэтому_parse_cron("0 1 * * mon")сработает в 01:00 МСК понедельника (= 22:00 UTC воскресенья), а не в 04:00 МСК как написано в комментарии кода и PR description.Решение мержить: комментарий лжёт, но cron-выражение корректно по форме и выполнится валидно. 01:00 МСК и 04:00 МСК — обе deep low-traffic windows, поведенческой разницы нет (WAF risk, downstream cost идентичны). Это docs/comment defect, не code defect. Merge не блокировался по согласованному decision tree (финал epic, blocking production fix #231).
Что проверено корректно
tasks.nspd_sync.harvest_stale_quartersсовпадает с декоратором.{region_code: 66, max_age_days: 90, batch_size: 50}и queueceleryидентичны оригиналу до DISABLE.mergeable=true, не draft, CI gate не блокировал.Required follow-ups (отдельные chore PR / vault updates)
"0 1 * * mon"→"0 4 * * mon", чтобы реальное время выполнения совпало сTask_Nspd_Harvest_Quarter.md(intended 04:00 МСК) и с PR description. Заодно поправить comment.fixes/Bug_NSPD_WMS_NotBulk_2026_May14.md—status: in_progress→mitigated/resolved, ссылка на этот PR.runbooks/Beat_Schedule_Module.md— убратьnspd-harvest-stale-quartersиз «Disabled entries», добавить в основную таблицу.code/modules/Module_Beat_Schedule.md— снять пометку DISABLED.Epic #126 / #231 / #234 закрыты по merge.