chore(tradein/proxy): выпилить мёртвые узлы mobileproxy и их ключи из пула (#2613) #2614
No reviewers
Labels
No labels
Fable 5 ревью
GG-форсайт
admin
analytics
auth
automation
bug
business
chore
ci
compliance
data
data-moat
docs
duplicate
dx
enhancement
feedback/max
generative
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#2614
Loading…
Add table
Reference in a new issue
No description provided.
Delete branch "chore/tradein-purge-dead-mobileproxy"
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?
Summary
Владелец подтвердил: подписка mobileproxy закрыта, продлевать не будут. Прямая проба каждого узла из контейнера подтвердила смерть (id 2 — connection refused, id 3/4/5 — 407 Proxy Authentication Required; last_check_at у всех — 4-9 июля).
data/sql/201_purge_dead_mobileproxy_proxies.sql—DELETE FROM scrape_proxies WHERE url LIKE '%mobileproxy.space%'. Условие по домену вurl, не поid(id разъезжается между средами, тот же приём что и в 199).rotate_urlу трёх из четырёх строк (https://changeip.mobileproxy.space/?proxy_key=<секрет>) — из-за неоднородности этой колонки глубокое ревью PR #2611 нашло блокер (вызов ротации для такой строки отправил бы наш токен ASocks на чужой хост). Пин хоста в #2611 уже закрывает уязвимость, но сам чужой секрет в базе не нужен.DELETE, неUPDATE: единственный FK наscrape_proxies—scrape_proxy_rotations.proxy_id(NO ACTION), таблица сейчас пуста (0 строк вообще), 0 ссылок на id 2-5. Если строки появятся до применения —DELETEупадёт по FK внутри той же транзакции (BEGIN/COMMIT), деплой завершится ошибкой без порчи данных; отдельныйON DELETE-обработчик не нужен (узлыenabled=false,acquire()их не выдаёт — новым ротациям взяться неоткуда).tests/test_migration_201_purge_dead_mobileproxy_proxies.pyпо образцуtest_migration_200_*: транзакционность, domain-based (не id-based) условие, отсутствие DDL, отсутствие literal-секрета в файле, отсутствие psycopg:x::type.Замеры (прод, read-only, перед миграцией)
ha-507932, id 3gi-501114, id 4ard-500825, id 5aup-501129).asocks-residential-1, id 9asocks-mobile-1, id 10asocks-mobile-2, id 11asocks-mobile-3).scrape_proxy_rotationsна id 2-5: 0 (таблица пуста целиком, 0 строк всего).token|bearer|secret|key=|password, regex, case-insensitive) вrotate_urlостающихся 4 строк: 0 совпадений — все четыреhttps://api.asocks.com/unlimited-proxy/<portId>/refresh-ip, без query-параметров, авторизация Bearer-заголовком вне URL.scrape_proxies: ровно один —scrape_proxy_rotations.proxy_id -> scrape_proxies.id,delete_rule = NO ACTION.Границы
rotate_url..env.runtime— отдельная задача, и НЕ раньше неё (при пустом проксиcurl_proxy_urlотдаётNone= прямое подключение с IP сервера).app/services/proxy_pool.py,proxy_rotation.py, скраперы.forgejo/main(max 200), всем открытым PR (#2545/#2546/#2547 — не вdata/sql) и по истории коммитов за файлами*/data/sql/20*.sqlво всех remote-ветках — коллизий нет.Test plan
uv run pytest -qвtradein-mvp/backend: 3056 passed, 1 pre-existing fail (tests/test_search_api.py::test_search_cache_hit, 401 RBAC — не связан с этим PR, не чинится), 9 skipped.ruff check/ruff format— чисто (pre-commit hooks прошли).Refs #2613