mirror of
https://github.com/maxdorninger/MediaManager.git
synced 2026-04-18 01:54:00 +02:00
prevent circular imports
This commit is contained in:
@@ -1,44 +1,82 @@
|
||||
# media_manager/database/__init__.py
|
||||
import logging
|
||||
import os
|
||||
from contextvars import ContextVar
|
||||
from typing import Annotated, Any, Generator
|
||||
from typing import Annotated, Any, Generator, Optional
|
||||
|
||||
from fastapi import Depends
|
||||
from sqlalchemy import create_engine
|
||||
from sqlalchemy.engine import Engine
|
||||
from sqlalchemy.orm import Session, declarative_base, sessionmaker
|
||||
|
||||
from media_manager.config import AllEncompassingConfig
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
config = AllEncompassingConfig().database
|
||||
|
||||
db_url = (
|
||||
"postgresql+psycopg"
|
||||
+ "://"
|
||||
+ config.user
|
||||
+ ":"
|
||||
+ config.password
|
||||
+ "@"
|
||||
+ config.host
|
||||
+ ":"
|
||||
+ str(config.port)
|
||||
+ "/"
|
||||
+ config.dbname
|
||||
)
|
||||
|
||||
engine = create_engine(
|
||||
db_url,
|
||||
echo=False,
|
||||
pool_size=10,
|
||||
max_overflow=10,
|
||||
pool_timeout=30,
|
||||
pool_recycle=1800,
|
||||
)
|
||||
log.debug("initializing sqlalchemy declarative base")
|
||||
Base = declarative_base()
|
||||
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
|
||||
|
||||
engine: Optional[Engine] = None
|
||||
SessionLocal: Optional[sessionmaker] = None
|
||||
|
||||
|
||||
def build_db_url(
|
||||
user: str,
|
||||
password: str,
|
||||
host: str,
|
||||
port: int | str,
|
||||
dbname: str,
|
||||
) -> str:
|
||||
return f"postgresql+psycopg://{user}:{password}@{host}:{port}/{dbname}"
|
||||
|
||||
|
||||
def init_engine(
|
||||
db_config: Any | None = None,
|
||||
url: str | None = None,
|
||||
) -> Engine:
|
||||
"""
|
||||
Initialize the global SQLAlchemy engine and session factory.
|
||||
Pass either a DbConfig-like object or a full URL. Only initializes once.
|
||||
"""
|
||||
global engine, SessionLocal
|
||||
if engine is not None:
|
||||
return engine
|
||||
|
||||
if url is None:
|
||||
if db_config is None:
|
||||
url = os.getenv("DATABASE_URL")
|
||||
if not url:
|
||||
raise RuntimeError("DB config or `DATABASE_URL` must be provided")
|
||||
else:
|
||||
url = build_db_url(
|
||||
db_config.user,
|
||||
db_config.password,
|
||||
db_config.host,
|
||||
db_config.port,
|
||||
db_config.dbname,
|
||||
)
|
||||
|
||||
engine = create_engine(
|
||||
url,
|
||||
echo=False,
|
||||
pool_size=10,
|
||||
max_overflow=10,
|
||||
pool_timeout=30,
|
||||
pool_recycle=1800,
|
||||
)
|
||||
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
|
||||
log.debug("SQLAlchemy engine initialized")
|
||||
return engine
|
||||
|
||||
|
||||
def get_engine() -> Engine:
|
||||
if engine is None:
|
||||
raise RuntimeError("Engine not initialized. Call init_engine(...) first.")
|
||||
return engine
|
||||
|
||||
|
||||
def get_session() -> Generator[Session, Any, None]:
|
||||
if SessionLocal is None:
|
||||
raise RuntimeError(
|
||||
"Session factory not initialized. Call init_engine(...) first."
|
||||
)
|
||||
db = SessionLocal()
|
||||
try:
|
||||
yield db
|
||||
@@ -46,12 +84,10 @@ def get_session() -> Generator[Session, Any, None]:
|
||||
except Exception as e:
|
||||
db.rollback()
|
||||
log.critical(f"error occurred: {e}")
|
||||
raise e
|
||||
raise
|
||||
finally:
|
||||
db.close()
|
||||
|
||||
|
||||
db_session: ContextVar[Session] = ContextVar("db_session")
|
||||
|
||||
|
||||
DbSessionDependency = Annotated[Session, Depends(get_session)]
|
||||
|
||||
Reference in New Issue
Block a user