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
Owner

Проблема

mark_health(ok=True) присваивал exit_ip/latency_ms безусловно. Из healthcheck'а это верно — он передаёт измеренные значения. Но подавляющее большинство вызовов приходит не оттуда:

  • BrowserFetcher._report_fetch_result — на каждый успешный /fetch;
  • finally у curl_proxy_url — на каждый lease.

Оба зовут 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. Аудита «на каком адресе мы были в момент бана» не существовало.

Гипотезу, что виновата неуспешная проба, разведка опровергла: ветка ok=False exit_ip вообще не трогает. Затирает именно успех.

Правка

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

Проверка

На живом PostgreSQL, не только в тестах: тот же UPDATE с NULL-параметрами внутри транзакции сохранил 9.9.9.9 / 42, транзакция откачена, прод не тронут.

UPDATE 1
 id | exit_ip | latency
----+---------+---------
 13 | 9.9.9.9 |      42
ROLLBACK

FakeSession в тестах интерпретирует SQL по фрагментам и делала безусловное присваивание — её ветка mark_health приведена в соответствие с COALESCE. Без этого тест проверял бы фейк, а не поведение; поэтому и добавлена проверка на живой БД выше.

Два новых теста: mark_health(ok=True) без адреса сохраняет прежний; с адресом — перезаписывает (поле не стало append-only).

5254 passed, 37 skipped, ruff чисто.

## Проблема `mark_health(ok=True)` присваивал `exit_ip`/`latency_ms` безусловно. Из healthcheck'а это верно — он передаёт измеренные значения. Но подавляющее большинство вызовов приходит **не оттуда**: - `BrowserFetcher._report_fetch_result` — на **каждый** успешный `/fetch`; - `finally` у `curl_proxy_url` — на каждый lease. Оба зовут `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`. Аудита «на каком адресе мы были в момент бана» не существовало. Гипотезу, что виновата **неуспешная** проба, разведка опровергла: ветка `ok=False` `exit_ip` вообще не трогает. Затирает именно **успех**. ## Правка `COALESCE(:param, <колонка>)` на обе строки. Явное значение по-прежнему пишется; очистить поле через `mark_health` больше нельзя — для этого есть прямой `UPDATE`. ## Проверка **На живом PostgreSQL**, не только в тестах: тот же `UPDATE` с `NULL`-параметрами внутри транзакции сохранил `9.9.9.9` / `42`, транзакция откачена, прод не тронут. ``` UPDATE 1 id | exit_ip | latency ----+---------+--------- 13 | 9.9.9.9 | 42 ROLLBACK ``` `FakeSession` в тестах интерпретирует SQL по фрагментам и делала безусловное присваивание — её ветка `mark_health` приведена в соответствие с `COALESCE`. Без этого тест проверял бы фейк, а не поведение; поэтому и добавлена проверка на живой БД выше. Два новых теста: `mark_health(ok=True)` без адреса сохраняет прежний; с адресом — перезаписывает (поле не стало append-only). `5254 passed, 37 skipped`, ruff чисто.
lekss361 added 1 commit 2026-08-31 14:30:55 +00:00
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
c0c462252f
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.
bot-backend merged commit 4c29b59041 into main 2026-08-31 14:53:34 +00:00
bot-backend deleted branch fix/3283d-mark-health-clobbers-exit-ip 2026-08-31 14:53:34 +00:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: lekss361/gendesign#3305
No description provided.