Coverage for app/core/db.py: 93%
41 statements
« prev ^ index » next coverage.py v7.6.10, created at 2026-06-04 22:29 +0000
« prev ^ index » next coverage.py v7.6.10, created at 2026-06-04 22:29 +0000
1import sqlite3
2from datetime import date, datetime
3from typing import Optional
5from sqlalchemy import Connection, Engine, create_engine, event
7from app.core.config import settings
8from app.core.logger import logger
11class DBConnectionManager:
12 def __init__(self, db_uri: str) -> None:
13 self.base_uri: str = db_uri
14 self.read_engine: Engine = self._create_engine(read_only=True)
15 self.write_engine: Engine = self._create_engine(read_only=False)
16 self._register_event_listeners()
18 def _create_engine(self, read_only: bool) -> Engine:
19 uri = self.base_uri
20 if read_only:
21 uri += "&mode=ro"
22 return create_engine(uri, echo=False, connect_args={"check_same_thread": False})
24 def _register_event_listeners(self) -> None:
25 for engine in [self.read_engine, self.write_engine]:
27 @event.listens_for(engine, "connect")
28 def apply_conn_settings(
29 dbapi_connection: Connection, connection_record: Optional[object]
30 ) -> None:
31 sqlite3.register_adapter(date, date.isoformat)
32 sqlite3.register_adapter(datetime, datetime.isoformat)
33 cursor = dbapi_connection.cursor()
34 cursor.execute("PRAGMA foreign_keys = ON")
35 cursor.execute("PRAGMA busy_timeout = 5000")
36 cursor.execute("PRAGMA synchronous = normal;")
37 cursor.execute("PRAGMA case_sensitive_like = ON")
38 cursor.close()
40 def get_engine(self, read_only: bool = True) -> Engine:
41 engine = self.read_engine if read_only else self.write_engine
42 return engine
45try:
46 logger.info("Creating database manager instance")
47 db_manager = DBConnectionManager(settings.SQLALCHEMY_DATABASE_URI)
48 read_engine = db_manager.read_engine
49 write_engine = db_manager.write_engine
50 logger.info("Database engines initialized successfully")
51except Exception as e:
52 logger.critical(f"Failed to initialize database: {str(e)}")
53 raise