feat: fpw plugins, validation/crawl perf, WS stats, test DB isolation

- Add Free_Proxy_Website-style fpw_* plugins and register them
- Per-plugin crawl timeout (crawl_timeout_seconds=120); remove global crawl_timeout setting
- Validator: fix connect vs total timeout on save; SOCKS session LRU cache; drop redundant semaphore
- Validation handler uses single DB connection; batch upsert after crawl; WorkerPool put_nowait
- Remove unused max_retries from settings API/UI; settings maintenance SQL + init_db cleanup of deprecated keys
- WebSocket dashboard stats; ProxyList pool_filter and API alignment
- POST /api/proxies/delete-one for IPv6-safe deletes; task poll stops on 404
- pytest uses PROXYPOOL_DB_PATH=db/proxies.test.sqlite so tests do not wipe production DB
- .gitignore: explicit proxies.test.sqlite patterns; fix plugin_service ValidationException import

Made-with: Cursor
This commit is contained in:
祀梦
2026-04-05 13:39:19 +08:00
parent 92c7fa19e2
commit 0131c8b408
63 changed files with 2331 additions and 531 deletions

View File

@@ -1,10 +1,13 @@
"""设置相关路由"""
import asyncio
from fastapi import APIRouter, Request, Depends
from app.core.db import get_db
from app.repositories.settings_repo import SettingsRepository
from app.models.schemas import SettingsSchema
from app.api.common import success_response
from app.api.deps import get_settings_repo
from app.core.config import settings as app_settings
from app.core.exceptions import ProxyPoolException
from app.core.log import logger
@@ -47,17 +50,21 @@ async def save_settings(
# 热更新验证器超时和并发(下次验证时生效)
if validator:
validator._init_timeout = request.validation_timeout
validator._init_connect_timeout = request.validation_timeout
vt = float(request.validation_timeout)
validator._init_timeout = vt
# 连接阶段单独收紧:勿与 total 等同,否则死代理会在 connect 上耗满整段超时
validator._init_connect_timeout = min(
float(app_settings.validator_connect_timeout), vt
)
validator._init_max_concurrency = request.default_concurrency
if request.validation_targets is not None:
validator.update_test_urls(request.validation_targets)
# 延迟关闭旧 session让正在验证的代理继续使用旧 session
# 新请求会通过 _ensure_session() 自动创建使用新配置的 session
await validator.close_socks_sessions()
old_session = validator._http_session
validator._http_session = None
validator._http_connector = None
validator._semaphore = None
if old_session and not old_session.closed:
asyncio.create_task(old_session.close())
logger.info(f"Validator config updated: timeout={request.validation_timeout}, concurrency={request.default_concurrency}, targets={request.validation_targets}")