fix(nspd_geo): split zombie thresholds running=6m / paused=30m (#1215) #1254
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#1254
Loading…
Add table
Reference in a new issue
No description provided.
Delete branch "fix/nspd-zombie-threshold-vs-waf-backoff"
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
Closes #1215 (P2 concurrency, prod).
cleanup_zombiesс порогом 2 мин ре-enqueue'ил живой WAF-job worker'а → дубль NSPD-запросов углублял бан.Bug
nspd_geoworker в WAF-ветке:wait = 30 * min(consecutive_waf, 8) = до 240с, heartbeat коммитится ДОtime.sleep(wait).cleanup_zombiesбежит каждую минуту с порогомINTERVAL '2 minutes'дляstatus IN ('running', 'paused'). Приconsecutive_waf >= 5(sleep 150–240с > 120с) cleanup гарантированно ре-enqueue'ит живой job → новый worker берёт SELECT pending безFOR UPDATE SKIP LOCKED→ два worker'а параллельно долбят забаненный NSPD-сервис (углубляя бан), счётчикиdone/failedзатираются.Бонус:
status='paused'(после 8 WAF подряд) воскресает через минуту → WAF-защита аннулирована.Fix (Вариант A+C из issue)
Module-level константы + параметризованный SQL (
CAST(:x AS interval)per psycopg v3):_ZOMBIE_RUNNING_THRESHOLD = "6 minutes"— выше max WAF backoff (4 мин)._ZOMBIE_PAUSED_THRESHOLD = "30 minutes"— реальная WAF-пауза.Beat-расписание (1 мин tick) НЕ тронут. WAF-логика (вариант B) и
FOR UPDATE SKIP LOCKEDдля таргетов (вариант «идеальный») вне scope этого PR — отдельные follow-up'ы.Test plan
test_nspd_geo.py: psycopg v3 guard, оба порога биндятся, два предиката вместо одного, paused > running.pytest tests/workers/test_nspd_geo.py→ 18 passed.pytest -k nspd_geo→ 18 passed, 1 skipped.ruff check→ All checks passed.grep ':[a-z_]+::[a-z]'→ clean (psycopg v3).Closes #1215
В WAF-ветке `nspd_geo` worker спит до 240с (4 мин при consecutive_waf=8), heartbeat коммитится ДО сна. Старый `cleanup_zombies` (`* * * * *`) с порогом `INTERVAL '2 minutes'` для status IN ('running', 'paused') гарантированно ре-enqueue'ил **живой** WAF-job: - Два worker'а параллельно долбили забаненный NSPD-сервис, углубляя бан. - SELECT pending без `FOR UPDATE SKIP LOCKED` → дубли запросов. - Counter'ы done/failed двух инстансов затираются друг другом. Бонус-баг: status='paused' (после 8 WAF подряд) воскресал через минуту, аннулируя WAF-защиту. Patch: разделил пороги через module-level константы и параметризованный SQL (CAST(:x AS interval) per psycopg v3 rule): - `_ZOMBIE_RUNNING_THRESHOLD = "6 minutes"` — выше max WAF backoff (4 мин). - `_ZOMBIE_PAUSED_THRESHOLD = "30 minutes"` — реальная WAF-пауза. Beat-расписание (1 мин tick) не тронуто. WAF-логика / heartbeat-in-loop (вариант B) / FOR UPDATE SKIP LOCKED (вариант «идеальный») вне scope. 4 новых юнит-теста (test_nspd_geo.py): psycopg v3 guard, оба порога биндятся, два предиката вместо одного, paused > running. 18/18 nspd_geo тестов зелёные. ruff clean. Closes #1215