fix(tradein/estimator): IMV-путь /estimate через пул прокси; пустой пул — честная деградация без IMV (#3386 п.в) #3397
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
2 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference: lekss361/gendesign#3397
Loading…
Add table
Reference in a new issue
No description provided.
Delete branch "fix/3386-estimator-imv-proxy-pool"
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?
Часть #3386 (п. в). Не закрывает issue.
Поправка к постановке. IMV из эстиматора — curl_cffi, не сайдкар:
_get_or_fetch_imv_cached → evaluate_via_imvбезbrowser_fetcher(флагavito_imv_use_browser_fetcherчитает толькоhouse_imv_backfill). 4 запроса однойAsyncSession(warm-up → coords → geo/position → realty-imv/get-data). Безproxy_providercurl_proxy_url:use_pool = флаг AND provider is not None→ False →proxies = SCRAPER_PROXY_URL(выключенный узел 9, 407) → Авито отвечает 403/ошибка →/estimateбез IMV-якоря с момента смерти узла (02.09). История «сайдкар держит чужую аренду» относится к бэкфиллу, не к/estimate.Фикс (
app/services/estimator.py:786, :819):proxy_provider=RealProxyProvider()(lazy import как вhouse_imv_backfill.py:744-755). Lease — один на вызовevaluate_via_imv(providers/_proxy.py:57-135черезExitStackвimv.py:497-534), release гарантированfinally(mark_banned → mark_health → release, каждый в своём try) на штатном выходе, исключении и таймауте_with_budget.Деградация:
NoProxyAvailableErrorподнимается до HTTP из__enter__, доходит доexcept Exceptionв_get_or_fetch_imv_cached→None→/estimate200 без блокаavito_imv; добавлена развилкаcaused_by_no_proxy(e)→ логimv: пул прокси пуст — estimator продолжает без IMVвместоfetch failed(читалось как «Авито отвалился»). Поляimv_error_reasonв ответе/estimateнет и не было (колонкаhouses) — не добавлял.acquireсинхронный (SELECT FOR UPDATE SKIP LOCKED + UPDATE, мс) внутри kit — как у соседей; та же корутина уже делает синхронный кэш-лукап (#3083 — потолок назван).Тесты
tests/test_3386_estimator_imv_proxy_pool.py(5): оба вызова получаютproxy_provider is not None; пустой пул в production → результат без IMV, без исключения, честный лог; lease освобождён ровно один раз на успехе и на ошибке IMV.Фальсификация (
git apply -Restimator.py): 5 failed по значению —assert None is not None(kwargs безproxy_provider) ×2, логfetch failedвместо «пул прокси пуст»,acquired == 0×2. Восстановлено.Прогоны: полный backend
5535 passed, 35 skipped(rc=0); ruff OK.Приёмка на проде: (1)
printenv USE_PROXY_POOL_CURL= true в backend (для эстиматора важен именно curl-флаг); (2)POST /estimateизнутри контейнера на адресе без IMV-кэша за 24 ч → блокavito_imvв ответе, в логахimv: cache MISS … → imv: fresh recommended=…; (3) во время вызова у узлаaffinity IN ('avito','any')leased_byзанят, после — свободен; (4) отрицательный контроль — сравнить долю оценок с IMV-якорем до/после по логам (fresh recommendedvsfetch failed).Code-review (06.09): ⚠️ minor. Проверено: проводка настоящая (
use_proxy_pool_curl/environmentуRealScraperConfigесть —scraper_adapters.py:194/204),NoProxyAvailableError→ 200 без IMV (тест по значению),SKIP LOCKEDв acquire — на блокировке строки не ждёт, lease не течёт (release вfinallyна всех выходах, тест через настоящийcurl_proxy_url), сессия роута не отравляется (RealProxyProvider— свояSessionLocal), lazy-импорта не нужно (estimator.py:83), контроль на main красный по значению.Докатываю до мержа:
except Exception→except BaseExceptionв_proxy.py:127(наCancelledErrorот_with_budgetузел записывалсяok=True— дефект старый, досягаемым делает этот PR) + тест на отмену;create=Trueиз патчей теста;admin.py:1098IMV через_kit_proxy_provider(). Хвосты (statement_timeout/зависание вне бюджета, атрибуция IMV-банов источнику avito — решение владельца,house_imv_backfill.py:929) — #3398.