Typed pydantic-settings config, structlog JSON logging with request/trace id propagation and redaction of phone numbers, tokens and face keys, the unified response envelope and error-code table from 架构文档 §9.2, async SQLAlchemy session management, ORM models for the eight foundation tables, and the OpenTelemetry/Prometheus wiring. packages/domain stays pure logic -- snowflake ids, the quota three-phase protocol and the tk_task state machine -- so it can be tested without a database and is held to mypy strict.
29 lines
677 B
Python
Executable File
29 lines
677 B
Python
Executable File
"""Shared Redis connection (cache / quota counters / cost budget counter)."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from redis.asyncio import Redis, from_url
|
|
|
|
from packages.shared.config import Settings, get_settings
|
|
|
|
_client: Redis | None = None
|
|
|
|
|
|
def create_redis(settings: Settings | None = None) -> Redis:
|
|
cfg = settings or get_settings()
|
|
return from_url(cfg.redis_url, encoding="utf-8", decode_responses=True)
|
|
|
|
|
|
def get_redis() -> Redis:
|
|
global _client
|
|
if _client is None:
|
|
_client = create_redis()
|
|
return _client
|
|
|
|
|
|
async def close_redis() -> None:
|
|
global _client
|
|
if _client is not None:
|
|
await _client.aclose()
|
|
_client = None
|