Files
orion/app/core/database.py
Samir Boulahtit 942f3722f5 fix: improve SQLite concurrency and database logging reliability
Database improvements:
- Enable WAL mode for better concurrent read/write access
- Add busy_timeout (30s) to wait for locked database
- Add synchronous=NORMAL for balanced safety/performance
- Configure check_same_thread=False for thread safety

Logging improvements:
- Add retry logic (3 attempts) for database locked errors
- Silently skip logging on persistent failures to avoid spam
- Properly rollback failed transactions

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-12 22:36:27 +01:00

69 lines
1.9 KiB
Python

# app/core/database.py
"""
Database configuration and session management.
This module provides classes and functions for:
- Database engine creation and configuration
- Session management with connection pooling
- Database dependency for FastAPI routes
"""
import logging
from sqlalchemy import create_engine, event
from sqlalchemy.orm import declarative_base, sessionmaker
from .config import settings
def _configure_sqlite_connection(dbapi_connection, connection_record):
"""Configure SQLite connection for better concurrency.
- WAL mode: Allows concurrent reads during writes
- busy_timeout: Wait up to 30 seconds if database is locked
- synchronous=NORMAL: Balance between safety and performance
"""
cursor = dbapi_connection.cursor()
cursor.execute("PRAGMA journal_mode=WAL")
cursor.execute("PRAGMA busy_timeout=30000")
cursor.execute("PRAGMA synchronous=NORMAL")
cursor.close()
# Create engine with SQLite-specific configuration
engine_kwargs = {}
# Add SQLite-specific settings for better concurrent access
if settings.database_url.startswith("sqlite"):
engine_kwargs["connect_args"] = {"check_same_thread": False}
engine = create_engine(settings.database_url, **engine_kwargs)
# Configure SQLite pragmas on connection
if settings.database_url.startswith("sqlite"):
event.listen(engine, "connect", _configure_sqlite_connection)
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
Base = declarative_base()
logger = logging.getLogger(__name__)
def get_db():
"""
Database session dependency for FastAPI routes.
Yields a database session and ensures proper cleanup.
Handles exceptions and rolls back transactions on error.
"""
db = SessionLocal()
try:
yield db
except Exception as e:
logger.error(f"Database session error: {e}")
db.rollback()
raise
finally:
db.close()