mirror of
https://github.com/fawney19/Aether.git
synced 2026-09-03 01:40:21 +08:00
chore: 升级到 Python 3.14 并现代化代码
- 升级 Docker 基础镜像从 Python 3.12 到 3.14 - 更新 pyproject.toml 支持 Python 3.13/3.14 - 移除 Python 3.8/3.9/3.10/3.11 分类器 - 更新 black 和 mypy 配置目标版本 - 将 get_event_loop() 替换为 get_running_loop() 加上 RuntimeError 处理 - 简化 compute_cost_sync 中的 asyncio.run 使用 - Dict/List/Tuple/Set → dict/list/tuple/set (PEP 585) - Optional[T] → T | None (PEP 604) - Union[A, B] → A | B (PEP 604) - 移除废弃的 typing 导入 - 移除不必要的字符串引号注解
This commit is contained in:
@@ -8,11 +8,13 @@
|
||||
3. 连接池复用:Keep-alive 连接减少 TCP 握手开销
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import asyncio
|
||||
import hashlib
|
||||
import time
|
||||
from contextlib import asynccontextmanager
|
||||
from typing import Any, Dict, Optional, Tuple
|
||||
from typing import Any
|
||||
from urllib.parse import quote, urlparse
|
||||
|
||||
import httpx
|
||||
@@ -26,7 +28,7 @@ _proxy_clients_lock = asyncio.Lock()
|
||||
_default_client_lock = asyncio.Lock()
|
||||
|
||||
|
||||
def _compute_proxy_cache_key(proxy_config: Optional[Dict[str, Any]]) -> str:
|
||||
def _compute_proxy_cache_key(proxy_config: dict[str, Any] | None) -> str:
|
||||
"""
|
||||
计算代理配置的缓存键
|
||||
|
||||
@@ -48,7 +50,7 @@ def _compute_proxy_cache_key(proxy_config: Optional[Dict[str, Any]]) -> str:
|
||||
return f"proxy:{hashlib.md5(proxy_url.encode()).hexdigest()[:16]}"
|
||||
|
||||
|
||||
def build_proxy_url(proxy_config: Dict[str, Any]) -> Optional[str]:
|
||||
def build_proxy_url(proxy_config: dict[str, Any]) -> str | None:
|
||||
"""
|
||||
根据代理配置构建完整的代理 URL
|
||||
|
||||
@@ -103,11 +105,11 @@ class HTTPClientPool:
|
||||
3. LRU 淘汰:代理客户端超过上限时淘汰最久未使用的
|
||||
"""
|
||||
|
||||
_instance: Optional["HTTPClientPool"] = None
|
||||
_default_client: Optional[httpx.AsyncClient] = None
|
||||
_clients: Dict[str, httpx.AsyncClient] = {}
|
||||
_instance: HTTPClientPool | None = None
|
||||
_default_client: httpx.AsyncClient | None = None
|
||||
_clients: dict[str, httpx.AsyncClient] = {}
|
||||
# 代理客户端缓存:{cache_key: (client, last_used_time)}
|
||||
_proxy_clients: Dict[str, Tuple[httpx.AsyncClient, float]] = {}
|
||||
_proxy_clients: dict[str, tuple[httpx.AsyncClient, float]] = {}
|
||||
# 代理客户端缓存上限(避免内存泄漏)
|
||||
_max_proxy_clients: int = 50
|
||||
|
||||
@@ -242,7 +244,7 @@ class HTTPClientPool:
|
||||
@classmethod
|
||||
async def get_proxy_client(
|
||||
cls,
|
||||
proxy_config: Optional[Dict[str, Any]] = None,
|
||||
proxy_config: dict[str, Any] | None = None,
|
||||
) -> httpx.AsyncClient:
|
||||
"""
|
||||
获取代理客户端(带缓存复用)
|
||||
@@ -280,7 +282,7 @@ class HTTPClientPool:
|
||||
await cls._evict_lru_proxy_client()
|
||||
|
||||
# 创建新客户端(使用默认超时,请求时可覆盖)
|
||||
client_config: Dict[str, Any] = {
|
||||
client_config: dict[str, Any] = {
|
||||
"http2": False,
|
||||
"verify": get_ssl_context(),
|
||||
"follow_redirects": True,
|
||||
@@ -370,8 +372,8 @@ class HTTPClientPool:
|
||||
@classmethod
|
||||
def create_client_with_proxy(
|
||||
cls,
|
||||
proxy_config: Optional[Dict[str, Any]] = None,
|
||||
timeout: Optional[httpx.Timeout] = None,
|
||||
proxy_config: dict[str, Any] | None = None,
|
||||
timeout: httpx.Timeout | None = None,
|
||||
**kwargs: Any,
|
||||
) -> httpx.AsyncClient:
|
||||
"""
|
||||
@@ -387,7 +389,7 @@ class HTTPClientPool:
|
||||
Returns:
|
||||
配置好的 httpx.AsyncClient 实例(调用者需要负责关闭)
|
||||
"""
|
||||
client_config: Dict[str, Any] = {
|
||||
client_config: dict[str, Any] = {
|
||||
"http2": False,
|
||||
"verify": get_ssl_context(),
|
||||
"follow_redirects": True,
|
||||
@@ -413,7 +415,7 @@ class HTTPClientPool:
|
||||
return httpx.AsyncClient(**client_config)
|
||||
|
||||
@classmethod
|
||||
def get_pool_stats(cls) -> Dict[str, Any]:
|
||||
def get_pool_stats(cls) -> dict[str, Any]:
|
||||
"""获取连接池统计信息"""
|
||||
return {
|
||||
"default_client_active": cls._default_client is not None,
|
||||
|
||||
@@ -9,10 +9,11 @@
|
||||
- 调用方可以根据状态决定降级策略
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
import time
|
||||
from enum import Enum
|
||||
from typing import Optional
|
||||
|
||||
import redis.asyncio as aioredis
|
||||
from src.core.logger import logger
|
||||
@@ -35,8 +36,8 @@ class RedisClientManager:
|
||||
提供 Redis 连接管理、熔断器保护和状态监控。
|
||||
"""
|
||||
|
||||
_instance: Optional["RedisClientManager"] = None
|
||||
_redis: Optional[aioredis.Redis] = None
|
||||
_instance: RedisClientManager | None = None
|
||||
_redis: aioredis.Redis | None = None
|
||||
|
||||
def __new__(cls):
|
||||
"""单例模式"""
|
||||
@@ -50,11 +51,11 @@ class RedisClientManager:
|
||||
return
|
||||
|
||||
self._initialized = True
|
||||
self._circuit_open_until: Optional[float] = None
|
||||
self._circuit_open_until: float | None = None
|
||||
self._consecutive_failures: int = 0
|
||||
self._circuit_threshold = int(os.getenv("REDIS_CIRCUIT_BREAKER_THRESHOLD", "3"))
|
||||
self._circuit_reset_seconds = int(os.getenv("REDIS_CIRCUIT_BREAKER_RESET_SECONDS", "60"))
|
||||
self._last_error: Optional[str] = None # 记录最后一次错误
|
||||
self._last_error: str | None = None # 记录最后一次错误
|
||||
|
||||
def get_state(self) -> RedisState:
|
||||
"""
|
||||
@@ -100,7 +101,7 @@ class RedisClientManager:
|
||||
self._consecutive_failures = 0
|
||||
self._last_error = None
|
||||
|
||||
async def initialize(self, require_redis: bool = False) -> Optional[aioredis.Redis]:
|
||||
async def initialize(self, require_redis: bool = False) -> aioredis.Redis | None:
|
||||
"""
|
||||
初始化Redis连接
|
||||
|
||||
@@ -236,7 +237,7 @@ class RedisClientManager:
|
||||
self._redis = None
|
||||
logger.info("全局Redis客户端已关闭")
|
||||
|
||||
def get_client(self) -> Optional[aioredis.Redis]:
|
||||
def get_client(self) -> aioredis.Redis | None:
|
||||
"""
|
||||
获取Redis客户端(非异步)
|
||||
|
||||
@@ -249,10 +250,10 @@ class RedisClientManager:
|
||||
|
||||
|
||||
# 全局单例
|
||||
_redis_manager: Optional[RedisClientManager] = None
|
||||
_redis_manager: RedisClientManager | None = None
|
||||
|
||||
|
||||
async def get_redis_client(require_redis: bool = False) -> Optional[aioredis.Redis]:
|
||||
async def get_redis_client(require_redis: bool = False) -> aioredis.Redis | None:
|
||||
"""
|
||||
获取全局Redis客户端
|
||||
|
||||
@@ -277,7 +278,7 @@ async def get_redis_client(require_redis: bool = False) -> Optional[aioredis.Red
|
||||
return _redis_manager.get_client()
|
||||
|
||||
|
||||
def get_redis_client_sync() -> Optional[aioredis.Redis]:
|
||||
def get_redis_client_sync() -> aioredis.Redis | None:
|
||||
"""
|
||||
同步获取Redis客户端(不会初始化)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user