diff --git a/backend/src/playlist/sql.py b/backend/src/playlist/sql.py index c7440ca..0248166 100644 --- a/backend/src/playlist/sql.py +++ b/backend/src/playlist/sql.py @@ -20,12 +20,10 @@ from playlist import models # Initialize asynchronous logger logger = aiologger.Logger.with_default_handlers(name="sql_logger") -engine = sqlalchemy.ext.asyncio.create_async_engine(env.DATABASE_URL, echo=True) +_engine = sqlalchemy.ext.asyncio.create_async_engine(env.DATABASE_URL, echo=True) -mapper_registry = sqlalchemy.orm.registry() - -async_session_maker = sqlalchemy.orm.sessionmaker( - engine, class_=sqlalchemy.ext.asyncio.AsyncSession, expire_on_commit=False +_async_session_maker = sqlalchemy.orm.sessionmaker( + _engine, class_=sqlalchemy.ext.asyncio.AsyncSession, expire_on_commit=False ) @@ -88,6 +86,8 @@ def _coro_db_logger(func: Sessionizable) -> Sessionizable: await kwargs["session"].rollback() raise + return wrapper + def _async_gen_db_logger(func: Sessionizable) -> Sessionizable: @functools.wraps(func) @@ -108,13 +108,15 @@ def _async_gen_db_logger(func: Sessionizable) -> Sessionizable: await kwargs["session"].rollback() raise + return wrapper + def sessionize(func: Sessionizable) -> Sessionizable: """Decorator that ensures a database session is available to an async function or generator. This decorator automatically injects a `session` of type sqlalchemy.ext.asyncio.AsyncSession into the decorated function if one is not provided. If the `session` keyword argument is - missing or set to None, a new session is created using the async_session_maker and passed to + missing or set to None, a new session is created using the _async_session_maker and passed to the function. If a session is already provided when the function is called, it uses the existing session. @@ -168,7 +170,7 @@ def sessionize(func: Sessionizable) -> Sessionizable: logged_func = _coro_db_logger(func) if kwargs["session"] is None: - async with async_session_maker as kwargs["session"]: + async with _async_session_maker() as kwargs["session"]: return await logged_func(*args, **kwargs) else: return await logged_func(*args, **kwargs) @@ -186,7 +188,7 @@ def sessionize(func: Sessionizable) -> Sessionizable: logged_func = _async_gen_db_logger(func) if kwargs["session"] is None: - async with async_session_maker as kwargs["session"]: + async with _async_session_maker() as kwargs["session"]: async for element in logged_func(*args, **kwargs): yield element else: @@ -209,8 +211,8 @@ def sessionize(func: Sessionizable) -> Sessionizable: async def init_db() -> None: """Create all tables asynchronously.""" try: - async with engine.begin() as conn: - await conn.run_sync(mapper_registry.metadata.create_all) + async with _engine.begin() as conn: + await conn.run_sync(models.mapper_registry.metadata.create_all) await logger.info("Database tables created.") except Exception as e: await logger.error(f"Failed to create tables: {e}") @@ -219,8 +221,8 @@ async def init_db() -> None: async def drop_db() -> None: """Drop all tables asynchronously for clean slate testing or teardown.""" try: - async with engine.begin() as conn: - await conn.run_sync(mapper_registry.metadata.drop_all) + async with _engine.begin() as conn: + await conn.run_sync(models.mapper_registry.metadata.drop_all) await logger.info("Database tables dropped.") except Exception as e: await logger.error(f"Failed to drop tables: {e}")