fix(tradein): вернуть фотографии подсказок Avito IMV задним числом (#2674) #2693

Merged
bot-backend merged 1 commit from fix/2674-parsed-but-not-stored into main 2026-08-06 05:40:03 +00:00
Collaborator

Summary

Класс эпика «площадка прислала, парсер разобрал, до базы не доехало».

Аудит утверждал два дефекта сразу: (а) парсер выбрасывает imageLink, (б) колонка не входит в INSERT. Оба уже починены в PR #2682 (смержен 2026-08-06 02:29) — проверил по коду: imv.py:307 кладёт image_link=raw.get("imageLink"), house_imv_backfill.py:359 перечисляет image_link в INSERT. Здесь остаётся то, чего #2682 не делал: исторические строки.

Числа с прода (2026-08-06, точный count(*))

house_suggestions всего 25 055
из них с image_link 0
max(fetched_at) 2026-07-03 17:21
house_imv_evaluations 2 685, raw_response у 2 685
из них с suggestions.items[0].imageLink 2 685
восстановимо этим JOIN (SELECT-прогон) 21 480 / 25 055 (85.7%)

Подтверждение по сырому ответу

tests/fixtures/avito_imv_getdata.json (живой capture), ключ suggestions.items[].imageLink:

https://80.img.avito.st/image/1/1._ByNPLa1UPX7nIL1-VP1R7ucUvUzl5L0651S9w...

Почему 3 575 строк невосстановимы

house_imv_evaluations имеет UNIQUE(house_id) + ON CONFLICT DO UPDATE → повторная оценка дома перетирает raw_response, старый набор подсказок остаётся без сырья. Это не недоделанный бэкфилл, а утраченный источник — записано в COMMENT ON COLUMN, чтобы следующий читатель не искал баг в разнице 25 055 vs 21 480.

Test plan

  • pre-commit на изменённом файле — зелёный
  • Логика JOIN проверена SELECT-прогоном на проде (read-only): 21 480 / 3 575
  • Парсер + писатель уже покрыты test_2674_writers_honor_schema.py (в т.ч. живой фикстурой) — не дублирую
  • Post-deploy: SELECT count(image_link) FROM house_suggestions → ожидаю 21 480

DB-харнесса в CI нет, поэтому проверка миграции — прод-счётчик после деплоя.

Отдельно: почему это НЕ проверить живым скрейпером

house_imv_backfill бежит (последний прогон 2026-08-05 16:45, статус done), но пишет ноль: {"saved": 0, "errors": 35, "checked": 50, "skipped": 15}. Причина в houses.imv_error_reason: 246 домов — Avito geocode A network error: Server error '503 Service Unavailable' for url 'http://tradein-browser:3000/fetch-json', ещё 23 — 500, 12 — HTTP 403. Продюсер IMV мёртв с 2026-07-03 — отдельная находка, кандидат в issue.

Refs #2674

## Summary Класс эпика «площадка прислала, парсер разобрал, до базы не доехало». Аудит утверждал два дефекта сразу: (а) парсер выбрасывает `imageLink`, (б) колонка не входит в INSERT. **Оба уже починены** в PR #2682 (смержен 2026-08-06 02:29) — проверил по коду: `imv.py:307` кладёт `image_link=raw.get("imageLink")`, `house_imv_backfill.py:359` перечисляет `image_link` в INSERT. Здесь остаётся то, чего #2682 не делал: **исторические строки**. ### Числа с прода (2026-08-06, точный `count(*)`) | | | |---|---| | `house_suggestions` всего | 25 055 | | из них с `image_link` | **0** | | `max(fetched_at)` | 2026-07-03 17:21 | | `house_imv_evaluations` | 2 685, `raw_response` у 2 685 | | из них с `suggestions.items[0].imageLink` | **2 685** | | восстановимо этим JOIN (SELECT-прогон) | **21 480 / 25 055 (85.7%)** | ### Подтверждение по сырому ответу `tests/fixtures/avito_imv_getdata.json` (живой capture), ключ `suggestions.items[].imageLink`: ``` https://80.img.avito.st/image/1/1._ByNPLa1UPX7nIL1-VP1R7ucUvUzl5L0651S9w... ``` ### Почему 3 575 строк невосстановимы `house_imv_evaluations` имеет `UNIQUE(house_id)` + `ON CONFLICT DO UPDATE` → повторная оценка дома перетирает `raw_response`, старый набор подсказок остаётся без сырья. Это не недоделанный бэкфилл, а утраченный источник — записано в `COMMENT ON COLUMN`, чтобы следующий читатель не искал баг в разнице 25 055 vs 21 480. ## Test plan - [x] pre-commit на изменённом файле — зелёный - [x] Логика JOIN проверена SELECT-прогоном на проде (read-only): 21 480 / 3 575 - [x] Парсер + писатель уже покрыты `test_2674_writers_honor_schema.py` (в т.ч. живой фикстурой) — не дублирую - [ ] Post-deploy: `SELECT count(image_link) FROM house_suggestions` → ожидаю 21 480 DB-харнесса в CI нет, поэтому проверка миграции — прод-счётчик после деплоя. ## Отдельно: почему это НЕ проверить живым скрейпером `house_imv_backfill` бежит (последний прогон 2026-08-05 16:45, статус `done`), но пишет ноль: `{"saved": 0, "errors": 35, "checked": 50, "skipped": 15}`. Причина в `houses.imv_error_reason`: 246 домов — `Avito geocode A network error: Server error '503 Service Unavailable' for url 'http://tradein-browser:3000/fetch-json'`, ещё 23 — 500, 12 — `HTTP 403`. Продюсер IMV мёртв с 2026-07-03 — отдельная находка, кандидат в issue. Refs #2674
bot-backend added 1 commit 2026-08-06 00:57:37 +00:00
fix(tradein): вернуть фотографии подсказок Avito IMV задним числом (#2674)
All checks were successful
CI Trade-In / changes (pull_request) Successful in 9s
CI Trade-In / frontend-checks (pull_request) Has been skipped
CI / changes (pull_request) Successful in 10s
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 3m1s
521d35fe49
Класс «площадка прислала, парсер разобрал, до базы не доехало». Правка #2682
починила ПУТЬ (парсер отдаёт imageLink, INSERT его перечисляет), но только для
будущих строк — исторические так и остались с NULL.

Прод 2026-08-06, точные count(*):
  house_suggestions            25 055 строк, image_link заполнен у 0
  house_imv_evaluations         2 685 строк, raw_response есть у 2 685,
                                suggestions.items[0].imageLink есть у 2 685

Сырьё сохранено целиком, поэтому исторические ВОССТАНОВИМЫ: ключ подсказки
(house_id, ext_item_id) однозначно ложится на (e.house_id, item->>'id').
SELECT-прогон того же JOIN на проде: 21 480 из 25 055 (85.7%) восстановимо.

Остальные 3 575 невосстановимы в принципе, и это не недоделанный бэкфилл:
house_imv_evaluations имеет UNIQUE(house_id) и ON CONFLICT DO UPDATE, поэтому
повторная оценка дома перетирает raw_response — старый набор подсказок остаётся
без своего сырья. Пишу это в комментарий к колонке, чтобы следующий читатель
не искал баг в разнице 25 055 vs 21 480.

Идемпотентно: WHERE image_link IS NULL — повтор не трогает заполненное и не
перетирает то, что напишет живой скрейпер.
bot-backend merged commit a7ca0e9ee8 into main 2026-08-06 05:40:03 +00:00
bot-backend deleted branch fix/2674-parsed-but-not-stored 2026-08-06 05:40:04 +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#2693
No description provided.