All checks were successful
CI Trade-In / changes (pull_request) Successful in 8s
CI / changes (pull_request) Successful in 8s
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 2m40s
49 lines
3 KiB
PL/PgSQL
49 lines
3 KiB
PL/PgSQL
-- 198_scrape_proxy_rotations.sql
|
||
-- Issue #2600 п.5 — ротация exit-IP прокси ASocks по бану, со счётчиком и громким
|
||
-- отказом. АДДИТИВНО, не трогает scrape_proxies (157_scrape_proxies.sql) кроме
|
||
-- FK-ссылки; не трогает proxy_pool.py (параллельный PR #2609).
|
||
--
|
||
-- WHY:
|
||
-- Провайдер (ASocks, безлимитные порты) ограничивает ручную ротацию exit-IP тремя
|
||
-- вызовами в сутки на порт (эмпирика, владелец аккаунта). app.services.proxy_rotation
|
||
-- должен и проверять этот лимит ПЕРЕД обращением к API, и вести аудит попыток —
|
||
-- без отдельной таблицы истории лимит негде считать (scrape_proxies хранит только
|
||
-- текущее состояние, не историю).
|
||
--
|
||
-- Semantics:
|
||
-- Одна строка = одна попытка ротации (успешная ИЛИ неуспешная), но НЕ каждый
|
||
-- вызов rotate_proxy() пишет строку — локально отклонённые попытки (нет
|
||
-- rotate_url / нет ASOCKS_API_TOKEN / лимит уже исчерпан) вообще не доходят до
|
||
-- HTTP-вызова и в таблицу не пишутся (см. app.services.proxy_rotation docstring
|
||
-- за полным обоснованием "какие попытки считать против лимита").
|
||
-- http_status NULL = сетевая ошибка (ответа от провайдера не было вообще).
|
||
--
|
||
-- Idempotency:
|
||
-- CREATE TABLE IF NOT EXISTS + CREATE INDEX IF NOT EXISTS → повторный прогон
|
||
-- no-op (auto-apply strict на деплое это требует). Весь файл в BEGIN/COMMIT.
|
||
--
|
||
-- Dependencies:
|
||
-- 157_scrape_proxies.sql (scrape_proxies.id — FK-таргет).
|
||
|
||
BEGIN;
|
||
|
||
CREATE TABLE IF NOT EXISTS scrape_proxy_rotations (
|
||
id bigserial PRIMARY KEY,
|
||
proxy_id bigint NOT NULL REFERENCES scrape_proxies (id),
|
||
rotated_at timestamptz NOT NULL DEFAULT now(),
|
||
success boolean NOT NULL,
|
||
http_status integer,
|
||
note text
|
||
);
|
||
|
||
COMMENT ON TABLE scrape_proxy_rotations IS
|
||
'Аудит + суточный лимит (#2600 п.5) ручных ротаций exit-IP через ASocks '
|
||
'refresh-ip. Лимит провайдера — 3 попытки/сутки на порт; app.services.'
|
||
'proxy_rotation._quota_used_today считает только строки с http_status '
|
||
'IS NOT NULL AND != 401 (реально дошедшие до провайдера) за последние 24ч.';
|
||
|
||
-- Проверка суточного лимита + выборка истории по прокси: (proxy_id, rotated_at).
|
||
CREATE INDEX IF NOT EXISTS idx_scrape_proxy_rotations_proxy_time
|
||
ON scrape_proxy_rotations (proxy_id, rotated_at);
|
||
|
||
COMMIT;
|