| from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession, async_sessionmaker |
| from sqlalchemy.orm import DeclarativeBase |
| from sqlalchemy.pool import NullPool |
| from app.core.config import get_settings |
| import ssl |
|
|
| settings = get_settings() |
|
|
| |
| db_url = settings.ASYNC_DATABASE_URL |
| if not db_url: |
| print("WARNING: DATABASE_URL not set. Using in-memory SQLite.") |
| db_url = "sqlite+aiosqlite:///:memory:" |
|
|
| |
| engine = None |
|
|
| try: |
| connect_args = {} |
| poolclass = None |
| |
| if "sqlite" in db_url: |
| connect_args = {"check_same_thread": False} |
| else: |
| |
| connect_args = { |
| "statement_cache_size": 0, |
| "server_settings": {"application_name": "grip_backend"}, |
| "timeout": 20, |
| "command_timeout": 20 |
| } |
| |
| |
| if "supabase" in db_url.lower(): |
| |
| if ":6543" in db_url: |
| poolclass = NullPool |
| |
| |
| ssl_context = ssl.create_default_context() |
| ssl_context.check_hostname = False |
| ssl_context.verify_mode = ssl.CERT_NONE |
| connect_args["ssl"] = ssl_context |
|
|
| |
| engine_kwargs = {"echo": False, "connect_args": connect_args} |
| |
| if poolclass is NullPool: |
| engine_kwargs["poolclass"] = NullPool |
| else: |
| engine_kwargs.update({ |
| "pool_pre_ping": True, |
| "pool_recycle": 300, |
| "pool_size": 10, |
| "max_overflow": 20, |
| }) |
| |
| engine = create_async_engine(db_url, **engine_kwargs) |
| |
| except Exception as e: |
| print(f"CRITICAL: Failed to create database engine: {e}") |
| import traceback |
| traceback.print_exc() |
| |
| engine = create_async_engine("sqlite+aiosqlite:///:memory:", poolclass=NullPool) |
|
|
| |
| AsyncSessionLocal = async_sessionmaker( |
| bind=engine, |
| class_=AsyncSession, |
| expire_on_commit=False, |
| autoflush=False |
| ) |
|
|
| |
| class Base(DeclarativeBase): |
| pass |
|
|
| |
| async def get_db(): |
| async with AsyncSessionLocal() as session: |
| yield session |
|
|