feat(shared): cross-cutting plumbing and pure domain layer
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.
This commit is contained in:
Executable
+28
@@ -0,0 +1,28 @@
|
||||
"""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
|
||||
Reference in New Issue
Block a user