feat(auth): implement auth stack

This commit is contained in:
2025-12-29 09:55:30 +00:00
parent 3170f10e86
commit ad94833830
13 changed files with 1199 additions and 11 deletions

View File

@@ -2,8 +2,10 @@
from collections.abc import AsyncGenerator
from contextlib import asynccontextmanager
from contextvars import ContextVar
import asyncpg
from asyncpg.pool import PoolConnectionProxy
import redis.asyncio as redis
@@ -27,7 +29,7 @@ class Database:
await self.pool.close()
@asynccontextmanager
async def connection(self) -> AsyncGenerator[asyncpg.Connection, None]:
async def connection(self) -> AsyncGenerator[asyncpg.Connection | PoolConnectionProxy, None]:
"""Acquire a connection from the pool."""
if not self.pool:
raise RuntimeError("Database not connected")
@@ -35,7 +37,7 @@ class Database:
yield conn
@asynccontextmanager
async def transaction(self) -> AsyncGenerator[asyncpg.Connection, None]:
async def transaction(self) -> AsyncGenerator[asyncpg.Connection | PoolConnectionProxy, None]:
"""Acquire a connection with an active transaction."""
if not self.pool:
raise RuntimeError("Database not connected")
@@ -74,7 +76,26 @@ db = Database()
redis_client = RedisClient()
async def get_conn() -> AsyncGenerator[asyncpg.Connection, None]:
"""Dependency for getting a database connection."""
async with db.connection() as conn:
yield conn
_connection_ctx: ContextVar[asyncpg.Connection | PoolConnectionProxy | None] = ContextVar(
"db_connection",
default=None,
)
async def get_conn() -> AsyncGenerator[asyncpg.Connection | PoolConnectionProxy, None]:
"""Dependency that reuses the same DB connection within a request context."""
existing_conn = _connection_ctx.get()
if existing_conn is not None:
yield existing_conn
return
if not db.pool:
raise RuntimeError("Database not connected")
async with db.pool.acquire() as conn:
token = _connection_ctx.set(conn)
try:
yield conn
finally:
_connection_ctx.reset(token)