nlp-classifier-api / database.py
tvganeshcse2025
fix: sync all pending changes to HF Space
6054640
Raw
History Blame Contribute Delete
2.54 kB
"""
Phase G - database.py
Auto-switches between MySQL (local Docker) and SQLite (HF Spaces).
Set DB_BACKEND=sqlite for HF Spaces, DB_BACKEND=mysql for local Docker.
"""
from __future__ import annotations
import logging
import os
from pathlib import Path
from dotenv import load_dotenv
from sqlalchemy.ext.asyncio import AsyncSession, async_sessionmaker, create_async_engine
from sqlalchemy.orm import DeclarativeBase
from typing import AsyncGenerator
load_dotenv(dotenv_path=Path(__file__).parent / ".env", override=True)
log = logging.getLogger("phase_g.database")
DB_BACKEND = os.getenv("DB_BACKEND", "mysql")
if DB_BACKEND == "sqlite":
SQLITE_PATH = os.getenv("SQLITE_PATH", "/app/data/nlp.db")
os.makedirs(os.path.dirname(SQLITE_PATH), exist_ok=True)
DATABASE_URL = f"sqlite+aiosqlite:///{SQLITE_PATH}"
engine = create_async_engine(
DATABASE_URL,
connect_args={"check_same_thread": False},
echo=os.getenv("DB_ECHO", "false").lower() == "true",
)
else:
from urllib.parse import quote_plus
MYSQL_USER = os.getenv("MYSQL_USER", "root")
MYSQL_PASSWORD = os.getenv("MYSQL_PASSWORD", "")
MYSQL_HOST = os.getenv("MYSQL_HOST", "localhost")
MYSQL_PORT = os.getenv("MYSQL_PORT", "3306")
MYSQL_DB = os.getenv("MYSQL_DB", os.getenv("MYSQL_DATABASE", "nlp_classifier"))
DATABASE_URL = (
f"mysql+aiomysql://{MYSQL_USER}:{quote_plus(MYSQL_PASSWORD)}"
f"@{MYSQL_HOST}:{MYSQL_PORT}/{MYSQL_DB}"
f"?charset=utf8mb4"
)
engine = create_async_engine(
DATABASE_URL,
pool_size=10,
max_overflow=20,
pool_pre_ping=True,
pool_recycle=1800,
echo=os.getenv("DB_ECHO", "false").lower() == "true",
)
AsyncSessionLocal = async_sessionmaker(
bind=engine,
class_=AsyncSession,
expire_on_commit=False,
autoflush=False,
autocommit=False,
)
class Base(DeclarativeBase):
pass
async def get_db() -> AsyncGenerator[AsyncSession, None]:
async with AsyncSessionLocal() as session:
try:
yield session
await session.commit()
except Exception:
await session.rollback()
raise
async def create_tables() -> None:
async with engine.begin() as conn:
await conn.run_sync(lambda conn: Base.metadata.create_all(conn, checkfirst=True))
log.info("Database tables ready")
async def close_db() -> None:
await engine.dispose()
log.info("Database pool closed.")
# rebuild 1781059258.3590245