fix(tradein/browser): повтор evaluate на той же странице — гонка случается ПОСЛЕ load (#2676) #2721

Merged
bot-backend merged 1 commit from fix/2676-inpage-context-retry into main 2026-08-06 10:18:15 +00:00
Collaborator

Fix-forward к #2716 (тот же issue #2676)

Прод-проверка #2716 показала половину результата: признак распознаётся (в логе сайдкара появилась новая ветка), но повтор не помогает.

10:03:49 WARNING страница ушла в навигацию (Error), retry fetch-json с ожиданием load: .../robots.txt
10:03:54 ERROR   Page.evaluate: Execution context was destroyed, most likely because of a navigation
10:03:54 "POST /fetch-json HTTP/1.1" 500

Воспроизведено вживую дважды (безобидный robots.txt, origin = корень и город) — обе попытки падают одинаково. При этом /fetch того же URL отдаёт 200 и настоящий robots.txt: площадка не блокирует, прокси жив, дело не в бане.

Вывод, который меняет правку: навигация origin-страницы происходит после события load. Поэтому ни settle, ни ожидание load её не опережают, а повтор на СВЕЖЕЙ странице честно воспроизводит ту же первую навигацию — он не может выиграть по построению.

Что сделано

  1. Повтор evaluate на ТОЙ ЖЕ странице. К моменту исключения навигация уже случилась, у страницы новый и уже стабильный контекст. Стоит миллисекунды против полной ре-навигации (~30-45с/дом).
  2. Внешний повтор на свежей странице убран — прод показал, что он бесполезен, а стоил ре-навигации. Страховкой остаётся один повтор всего запроса на стороне клиента (BrowserFetcher.fetch_json), который был и до #2716.
  3. JS in-page fetch вынесен в константу (нужен двум вызовам), ожидание load — в _wait_for_load_best_effort.

Итого попыток на один /fetch-json: 2 evaluate на одной странице (вместо 1) + прежний клиентский повтор. Ре-навигаций больше не стало.

Test plan

  • test_server_fetch_json.py: обе формы сообщения playwright → повтор на той же странице (browser.opened == 1, evaluate.await_count == 2); таймаут ожидания load не отменяет попытку; повтор ровно один; чужая ошибка evaluate не даёт второго прохода; причина остаётся в теле 500
  • 20 passed локально; на коде до правки падают 5 из 20
  • соседние файлы test_server*.py — 4 падения ПРЕ-СУЩЕСТВУЮЩИЕ (проверено на origin/main: _ensure_browser(proxy_override=...) и пейсинг); эти тесты вообще не запускаются в CI — ci-tradein.yml гоняет только tradein-mvp/backend
  • после мержа: повтор POST /fetch-json на robots.txt изнутри tradein-scraper → ожидаем 200 вместо 500

Refs #2676

## Fix-forward к #2716 (тот же issue #2676) Прод-проверка #2716 показала половину результата: **признак распознаётся** (в логе сайдкара появилась новая ветка), но **повтор не помогает**. ``` 10:03:49 WARNING страница ушла в навигацию (Error), retry fetch-json с ожиданием load: .../robots.txt 10:03:54 ERROR Page.evaluate: Execution context was destroyed, most likely because of a navigation 10:03:54 "POST /fetch-json HTTP/1.1" 500 ``` Воспроизведено вживую дважды (безобидный `robots.txt`, `origin` = корень и город) — обе попытки падают одинаково. При этом `/fetch` того же URL отдаёт **200 и настоящий robots.txt**: площадка не блокирует, прокси жив, дело не в бане. **Вывод, который меняет правку:** навигация origin-страницы происходит **после** события `load`. Поэтому ни settle, ни ожидание `load` её не опережают, а повтор на СВЕЖЕЙ странице честно воспроизводит ту же первую навигацию — он не может выиграть по построению. ## Что сделано 1. **Повтор `evaluate` на ТОЙ ЖЕ странице.** К моменту исключения навигация уже случилась, у страницы новый и уже стабильный контекст. Стоит миллисекунды против полной ре-навигации (~30-45с/дом). 2. **Внешний повтор на свежей странице убран** — прод показал, что он бесполезен, а стоил ре-навигации. Страховкой остаётся один повтор всего запроса на стороне клиента (`BrowserFetcher.fetch_json`), который был и до #2716. 3. JS in-page fetch вынесен в константу (нужен двум вызовам), ожидание `load` — в `_wait_for_load_best_effort`. Итого попыток на один `/fetch-json`: 2 evaluate на одной странице (вместо 1) + прежний клиентский повтор. Ре-навигаций больше не стало. ## Test plan - [x] `test_server_fetch_json.py`: обе формы сообщения playwright → повтор на той же странице (`browser.opened == 1`, `evaluate.await_count == 2`); таймаут ожидания `load` не отменяет попытку; повтор ровно один; чужая ошибка evaluate не даёт второго прохода; причина остаётся в теле 500 - [x] 20 passed локально; на коде до правки падают 5 из 20 - [x] соседние файлы `test_server*.py` — 4 падения ПРЕ-СУЩЕСТВУЮЩИЕ (проверено на origin/main: `_ensure_browser(proxy_override=...)` и пейсинг); эти тесты вообще не запускаются в CI — `ci-tradein.yml` гоняет только `tradein-mvp/backend` - [ ] после мержа: повтор `POST /fetch-json` на `robots.txt` изнутри `tradein-scraper` → ожидаем 200 вместо 500 Refs #2676
bot-backend added 1 commit 2026-08-06 10:10:39 +00:00
fix(tradein/browser): повтор evaluate на той же странице — гонка навигации случается ПОСЛЕ load (#2676)
All checks were successful
CI / changes (pull_request) Successful in 10s
CI Trade-In / changes (pull_request) Successful in 10s
CI Trade-In / backend-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
5d30772153
Fix-forward к смерженному PR #2716. Прод-проверка того PR показала, что признак
распознаётся (в логе появилась новая ветка), но сам повтор не помогает:

    10:03:49 WARNING страница ушла в навигацию (Error), retry fetch-json с ожиданием load
    10:03:54 ERROR   Page.evaluate: Execution context was destroyed

Воспроизведено вживую дважды (безобидный robots.txt, origin = корень и город) —
обе попытки падают одинаково, при этом `/fetch` того же URL отдаёт 200 и настоящий
robots.txt, то есть площадка не блокирует и прокси жив.

Причина: навигация origin-страницы происходит ПОСЛЕ события load, поэтому ни
settle, ни ожидание load её не опережают, а повтор на СВЕЖЕЙ странице честно
воспроизводит ту же первую навигацию.

Правка:

1. Повтор evaluate на ТОЙ ЖЕ странице: к моменту исключения навигация уже
   случилась, у страницы новый и уже стабильный контекст. Стоит миллисекунды
   против полной ре-навигации.

2. Внешний повтор на свежей странице УБРАН — прод показал, что он не может
   выиграть, а стоил полной ре-навигации. Страховкой остаётся один повтор всего
   запроса на стороне клиента (BrowserFetcher.fetch_json), который был и раньше.

3. JS in-page fetch вынесен в константу (нужен двум вызовам), ожидание load — в
   _wait_for_load_best_effort.

Refs #2676
bot-backend merged commit a52b9d07cf into main 2026-08-06 10:18:15 +00:00
bot-backend deleted branch fix/2676-inpage-context-retry 2026-08-06 10:18:15 +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#2721
No description provided.