fix(tradein/proxy): успешный fetch затирал exit_ip и latency_ms в NULL (#3283) #3305

Merged
bot-backend merged 1 commit from fix/3283d-mark-health-clobbers-exit-ip into main 2026-08-31 14:53:34 +00:00

1 commit

Author SHA1 Message Date
bot-backend
c0c462252f fix(tradein/proxy): успешный fetch затирал exit_ip и latency_ms в NULL (#3283)
All checks were successful
CI Trade-In / changes (pull_request) Successful in 8s
CI / changes (pull_request) Successful in 11s
CI Trade-In / browser-tests (pull_request) Has been skipped
CI Trade-In / frontend-checks (pull_request) Has been skipped
CI / backend-tests (pull_request) Has been skipped
CI / frontend-tests (pull_request) Has been skipped
CI / openapi-codegen-check (pull_request) Has been skipped
CI Trade-In / backend-tests (pull_request) Successful in 4m56s
mark_health(ok=True) присваивал exit_ip/latency_ms без условия. Из healthcheck'а
это верно — он передаёт измеренные значения. Но подавляющее большинство вызовов
приходит не оттуда, а из BrowserFetcher._report_fetch_result на КАЖДЫЙ успешный
/fetch и из finally у curl_proxy_url: они зовут mark_health(lease, ok) без
exit_ip/latency_ms, адаптер подставляет None — и None затирал адрес, записанный
proxy_rotation._update_exit_ip минутой раньше.

Прод 31.08: у обоих живых узлов exit_ip IS NULL, при том что в логе ротации
new_ip=31.173.86.74. Аудита «на каком адресе мы были» не существовало.

Правка — COALESCE(:param, <колонка>) на обе строки. Явное значение по-прежнему
пишется; очистить поле через mark_health больше нельзя, для этого есть прямой
UPDATE.

Проверено на живом PostgreSQL: тот же UPDATE с NULL-параметрами в транзакции
сохраняет прежние значения (транзакция откачена, прод не тронут). FakeSession в
тестах интерпретирует SQL по фрагментам, поэтому её ветка mark_health приведена
в соответствие — иначе тест проверял бы фейк, а не поведение.

Тесты: 5254 passed, 37 skipped.
2026-08-31 17:30:33 +03:00