feat(scrapers): live pacing-регулятор + data-quality coverage API #1829
No reviewers
Labels
No labels
admin
analytics
auth
automation
bug
business
chore
ci
compliance
data
data-moat
docs
duplicate
dx
enhancement
Fable 5 ревью
feedback/max
generative
GG-форсайт
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
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference: lekss361/gendesign#1829
Loading…
Add table
Reference in a new issue
No description provided.
Delete branch "feat/scrapers-config-apis"
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?
Бэкенд для двух дыр из аудита
/scrapers(наблюдаемость данных + тюнинг без recreate). Парный фронт — отдельный PR.A. Live pacing-регулятор (per-provider интервалы без recreate)
До этого per-provider
BROWSER_MIN_PAGE_INTERVAL_S_*менялись только через env + recreate контейнера. Теперь — live in-memory.tradein-mvp/browser/server.py:GET /pacing(текущие живые интервалы + env-дефолт к чему сбросится на рестарте) иPUT /pacing {source, interval_s}(валидация source∈{avito,cian,yandex,generic}, interval_s≥0; пишет_MIN_PAGE_INTERVAL_BY_PROVIDERin-memory).admin.py:GET /api/v1/admin/scraper/pacing→{providers:[{source, interval_s, env_default_s}]}иPUT /scraper/pacing/{source}body{interval_s}(Field ge=0 le=120) →{ok, source, interval_s}. Прокси к browser (паттерн_probe_browser_health); browser недоступен → 502/503 с понятным detail.B. Data-quality coverage
admin.py:GET /api/v1/admin/scraper/data-quality→ fill% detail-полей по source + houses-enrichment. Один проходCOUNT(*) FILTERпоlistings WHERE is_active GROUP BY source. Поля (подтверждены через схему): description, photo_urls (jsonb<>'[]'), address, lat, lon, kitchen_area_m2, living_area_m2, ceiling_height (cian), ceiling_height_m (avito), metro_stations (jsonb). Houses: validated (avito_validated_at), rating_score, house_type,house_reviewscount.Тесты
browser pytest 16 passed (pacing GET/PUT + валидация), backend pytest 21 passed (pacing-прокси с мок-httpx + data-quality shape/диапазоны). ruff clean.
Деплой
browser + backend Python-изменения → пересборка обоих образов + recreate
tradein-browserиtradein-backend. Эндпоинты новые (аддитивно), без миграций. ⚠️ Мержить и дать деплою доехать ДО фронт-PR (иначе фронт-секции pacing/coverage покажут «API недоступен» — graceful, но пусто). NB: не мержить вплотную к другим tradein-PR (rapid-merge → cancelled test-gate → stale image).Cross-ref аудит
/scrapers, PR #1826 (per-provider pacing env).- browser/server.py: GET /pacing и PUT /pacing — read/write _MIN_PAGE_INTERVAL_BY_PROVIDER in-memory; валидация source in PROVIDERS, interval_s >= 0; логирует изменения; сбрасывается к env-дефолту на рестарте by design - backend/admin.py: GET /scraper/pacing — прокси к browser /pacing, PacingResponse pydantic; PUT /scraper/pacing/{source} — прокси PUT с валидацией ge=0 le=120; 502/503 при недоступности - backend/admin.py: GET /scraper/data-quality — single-pass FILTER-агрегаты по listings WHERE is_active GROUP BY source (description/photo_urls/address/lat/lon/kitchen_area_m2/living_area_m2/ ceiling_height/ceiling_height_m/metro_stations); houses (total/avito_validated_at%/rating_score%/ house_type%); house_reviews count - browser/test_server_pacing.py: 10 новых тестов GET+PUT /pacing (16 total, все зелёные) - backend/tests/test_scraper_admin_apis.py: тесты pacing-прокси + data-quality shape/pct-range (21 total, все зелёные)