feat: stabilize multi-region runtime sync and worker orchestration

This commit is contained in:
root
2026-04-27 15:48:12 +08:00
parent 7cbde2aa78
commit 215a364891
137 changed files with 31931 additions and 1943 deletions

View File

@@ -0,0 +1,129 @@
from __future__ import annotations
import os
import threading
import redis
from app.config import config
_CLIENTS: dict[tuple[str, bool], redis.Redis] = {}
_LOCK = threading.Lock()
def _safe_int(raw_value: object, default: int, minimum: int) -> int:
try:
parsed = int(raw_value)
except Exception:
parsed = default
return max(minimum, parsed)
def _safe_float(raw_value: object, default: float, minimum: float) -> float:
try:
parsed = float(raw_value)
except Exception:
parsed = default
return max(minimum, parsed)
def _pool_options(role: str, *, decode_responses: bool) -> dict:
normalized_role = str(role or "standard").strip().lower() or "standard"
node_code = str(getattr(config, "NODE_CODE", "") or "").strip() or "unknown"
if normalized_role == "pubsub":
return {
"host": config.REDIS_HOST,
"port": config.REDIS_PORT,
"password": config.REDIS_PASSWORD or None,
"db": config.REDIS_DB,
"decode_responses": decode_responses,
"socket_connect_timeout": _safe_float(
os.getenv("DOMAINCHECK_REDIS_PUBSUB_CONNECT_TIMEOUT", "30"),
30.0,
1.0,
),
"socket_timeout": _safe_float(
os.getenv("DOMAINCHECK_REDIS_PUBSUB_SOCKET_TIMEOUT", "60"),
60.0,
1.0,
),
"health_check_interval": _safe_int(
os.getenv("DOMAINCHECK_REDIS_HEALTH_CHECK_INTERVAL", "30"),
30,
0,
),
"retry_on_timeout": True,
"max_connections": _safe_int(
os.getenv("DOMAINCHECK_REDIS_PUBSUB_MAX_CONNECTIONS", "2"),
2,
1,
),
"timeout": _safe_float(
os.getenv("DOMAINCHECK_REDIS_PUBSUB_POOL_TIMEOUT", "5"),
5.0,
0.1,
),
"client_name": f"domaincheck:pubsub:{node_code}:{os.getpid()}",
}
return {
"host": config.REDIS_HOST,
"port": config.REDIS_PORT,
"password": config.REDIS_PASSWORD or None,
"db": config.REDIS_DB,
"decode_responses": decode_responses,
"socket_connect_timeout": _safe_float(
os.getenv("DOMAINCHECK_REDIS_CONNECT_TIMEOUT", "5"),
5.0,
0.5,
),
"socket_timeout": _safe_float(
os.getenv("DOMAINCHECK_REDIS_SOCKET_TIMEOUT", "10"),
10.0,
0.5,
),
"health_check_interval": _safe_int(
os.getenv("DOMAINCHECK_REDIS_HEALTH_CHECK_INTERVAL", "30"),
30,
0,
),
"retry_on_timeout": True,
"max_connections": _safe_int(
os.getenv("DOMAINCHECK_REDIS_MAX_CONNECTIONS", "12"),
12,
1,
),
"timeout": _safe_float(
os.getenv("DOMAINCHECK_REDIS_POOL_TIMEOUT", "1.5"),
1.5,
0.1,
),
"client_name": f"domaincheck:standard:{node_code}:{os.getpid()}",
}
def get_redis_client(*, role: str = "standard", decode_responses: bool = True) -> redis.Redis:
normalized_role = str(role or "standard").strip().lower() or "standard"
cache_key = (normalized_role, bool(decode_responses))
with _LOCK:
cached = _CLIENTS.get(cache_key)
if cached is not None:
return cached
pool = redis.BlockingConnectionPool(**_pool_options(normalized_role, decode_responses=decode_responses))
client = redis.Redis(connection_pool=pool)
_CLIENTS[cache_key] = client
return client
def reset_redis_clients_for_tests() -> None:
with _LOCK:
clients = list(_CLIENTS.values())
_CLIENTS.clear()
for client in clients:
try:
client.close()
except Exception:
pass