Files
life-echo/api/app/core/redis_lock.py
Sully 53e0065e3e refactor(api): TOML 配置 SSOT、统一错误契约、Auth/事务加固与可观测性 (#33)
配置 SSOT(TOML + .env)
统一错误契约
Auth 与事务边界
Redis / Celery 可靠性:业务 Redis(DB/0)与 Celery broker/backend(DB/1)显式拆分;连接池、sync client
可观测性(OpenTelemetry + LGTM)
2026-05-22 13:44:50 +08:00

39 lines
1.0 KiB
Python

"""Small Redis lock helpers for background tasks."""
import uuid
from dataclasses import dataclass
from app.core.redis_sync import get_sync_redis
@dataclass(frozen=True)
class RedisLockHandle:
key: str
token: bytes
def acquire_redis_lock(key: str, *, ttl_seconds: int) -> RedisLockHandle | None:
"""Acquire a single-owner Redis lock or return None when unavailable."""
client = get_sync_redis(decode_responses=False)
token = uuid.uuid4().hex.encode("utf-8")
if not client.set(key, token, nx=True, ex=ttl_seconds):
return None
return RedisLockHandle(key=key, token=token)
def release_redis_lock(handle: RedisLockHandle | None) -> None:
"""Release the lock only if we still own it."""
if handle is None:
return
get_sync_redis(decode_responses=False).eval(
"""
if redis.call("GET", KEYS[1]) == ARGV[1] then
return redis.call("DEL", KEYS[1])
end
return 0
""",
1,
handle.key,
handle.token,
)