"""设置相关路由""" 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 router = APIRouter(prefix="/api/settings", tags=["settings"]) @router.get("") async def get_settings(settings_repo: SettingsRepository = Depends(get_settings_repo)): async with get_db() as db: settings = await settings_repo.get_all(db) return success_response("获取设置成功", settings) @router.post("") async def save_settings( request: SettingsSchema, http_request: Request, settings_repo: SettingsRepository = Depends(get_settings_repo), ): async with get_db() as db: success = await settings_repo.save(db, request.model_dump()) if not success: raise ProxyPoolException("保存设置失败", 500) # 热更新运行中调度器的间隔时间 scheduler = getattr(http_request.app.state, "scheduler", None) worker_pool = getattr(http_request.app.state, "worker_pool", None) validator = getattr(http_request.app.state, "validator", None) if scheduler: new_interval = request.validate_interval_minutes if scheduler.interval_minutes != new_interval: scheduler.interval_minutes = new_interval logger.info(f"Scheduler interval updated to {new_interval} minutes") want_run = bool(request.auto_validate) if want_run and not scheduler.running: try: await scheduler.start() except Exception as e: logger.error(f"Failed to start scheduler after settings save: {e}") elif not want_run and scheduler.running: try: await scheduler.stop() except Exception as e: logger.error(f"Failed to stop scheduler after settings save: {e}") # 热更新 Worker 池大小 if worker_pool and worker_pool.worker_count != request.default_concurrency: await worker_pool.resize(request.default_concurrency) logger.info(f"Worker pool resized to {request.default_concurrency}") # 热更新验证器超时和并发(下次验证时生效) if validator: 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 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}") return success_response("保存设置成功", request.model_dump())