fix(tradein/geocoder): темп Nominatim сдерживается перед запросом, а не после успеха (#2953) #2954
No reviewers
Labels
No labels
Fable 5 ревью
GG-форсайт
admin
analytics
auth
automation
bug
business
chore
ci
compliance
data
data-moat
docs
duplicate
dx
enhancement
feedback/max
generative
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#2954
Loading…
Add table
Reference in a new issue
No description provided.
Delete branch "fix/2953-nominatim-throttle"
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?
Закрывает #2953.
Что было
194 события
429 Too many requestsот Nominatim за неделю. Политику 1 req/sec изображали триasyncio.sleep(1.0), и ни один не ограничивал:geocode()if result is not None— только после успеха_nominatim_lookup()Для неразрешимого адреса: tier-1 в t=0, четыре варианта к t=4 — 5 запросов за 4 секунды, дальше сразу следующий адрес без паузы. Темп сбрасывался ровно тогда, когда сервер просит притормозить.
Почему это происходит каждый прогон, а не изредка
Разбор 16 947 объявлений без координат (20.08):
97 % активных «без координат» — повторные неудачи, возвращающиеся в очередь каждые 7 суток. Череда неудач — норма прогона, а не исключение.
Правка
Один общий ограничитель, пауза перед каждым обращением, одна на все три точки вызова (
/search×2,/reverse). Четыре прежнихsleepубраны как избыточные — код стал короче.Повторы на
429намеренно не трогал. Если убрать их той же правкой, падение счётчика 429 нельзя будет приписать именно ограничителю — а критерий приёмки в #2953 сформулирован через этот счётчик. Если 429 останутся, повторы — следующий шаг.ponytail: ограничитель внутрипроцессный. Если бэкфилл и пользовательские запросы разъедут по разным процессам, темпы снова сложатся — тогда понадобится общий счётчик (Redis). Ceiling записан комментарием в коде.Проверка — двусторонняя, по поведению
Тест меряет расстояние между исходящими запросами, а не наличие нового символа:
from … import _nominatim_throttleдал бы наorigin/mainImportError, то есть «возможности нет», и красный ничего бы не доказывал.Против кода
origin/main:Третий тест — контроль в обе стороны: он же сломается, если интервал по недосмотру начнёт применяться дважды за запрос или если «время последнего вызова» инициализируют текущим временем (тогда каждый холодный старт платил бы интервал ни за что).
Прогоны
Ни одного нового падения, +3 своих. Падения и collection-errors средовые — в локальном venv нет
scraper_kit/bcrypt/lxml; проверено подстановкой файла сorigin/mainи повторным прогоном.На проде — 194 события «429 Too many requests» от Nominatim за неделю. Это не внешняя случайность: политику 1 req/sec изображали три разрозненных asyncio.sleep(1.0), и ни один не давал ограничения на самом деле. geocode() — сон ВНУТРИ `if result is not None`, то есть только после УСПЕХА; после неудачи паузы не было; _nominatim_lookup() — сон МЕЖДУ typo-вариантами, но не перед tier-1; цикл бэкфилла — своей паузы не имеет вовсе, зовёт geocode() последовательно. Для неразрешимого адреса выходило 5 запросов за 4 секунды и сразу следующий адрес без паузы. То есть темп сбрасывался ровно тогда, когда сервер и просит притормозить, и разгонялся ровно на тех адресах, что не резолвятся. А череда неудач — не редкость, а норма прогона. Разбор 16947 объявлений без координат на 20.08: активных 1948, из них с пригодным адресом 1471, доступно бэкфиллу прямо сейчас 47, а 1424 лежат в семидневном backoff — то есть 97% активных «без координат» это повторные неудачи, возвращающиеся в очередь каждые 7 суток. Разгон происходит каждый прогон. Теперь пауза берётся ПЕРЕД каждым обращением и одна на все три точки вызова (/search x2, /reverse). Четыре прежних sleep убраны как избыточные. Повторы на 429 намеренно НЕ трогал. Если убрать их той же правкой, падение счётчика 429 нельзя будет приписать именно ограничителю темпа — а критерий приёмки в #2953 сформулирован через этот счётчик. Тест проверяет ПОВЕДЕНИЕ (расстояние между исходящими запросами), а не наличие нового символа: импорт _nominatim_throttle дал бы на origin/main ImportError, то есть «возможности нет», и красный ничего бы не доказывал. Против кода origin/main: зазоры между тремя запросами [0.0003, 0.0001] вместо >=0.08 -> падает стык двух неудачных поисков 0.0022с вместо >=0.08 -> падает первый запрос не ждёт впустую контроль, зелёный на обеих сторонах Прогон tradein-сьюта: 280 failed / 2099 passed против базы 280 failed / 2096 passed на origin/main — ни одного нового падения, +3 своих. Падения и 216 collection-errors средовые (нет scraper_kit/bcrypt/lxml в локальном venv). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>