diff --git a/src/exchange_data_manager/cache/connection_pool.py b/src/exchange_data_manager/cache/connection_pool.py index f781e77..6fa6bf2 100644 --- a/src/exchange_data_manager/cache/connection_pool.py +++ b/src/exchange_data_manager/cache/connection_pool.py @@ -76,6 +76,11 @@ class AsyncSQLitePool: conn = await aiosqlite.connect(self.db_path) # Enable WAL mode for better concurrent read/write performance await conn.execute("PRAGMA journal_mode=WAL") + # Set busy timeout to wait up to 5 seconds when database is locked + # This prevents "database is locked" errors during concurrent access + await conn.execute("PRAGMA busy_timeout=5000") + # Use NORMAL synchronous mode with WAL for good performance + durability + await conn.execute("PRAGMA synchronous=NORMAL") # Enable foreign keys await conn.execute("PRAGMA foreign_keys=ON") return conn diff --git a/src/exchange_data_manager/cache/database.py b/src/exchange_data_manager/cache/database.py index 98529ca..e99080b 100644 --- a/src/exchange_data_manager/cache/database.py +++ b/src/exchange_data_manager/cache/database.py @@ -73,8 +73,14 @@ class DatabaseCache: @contextmanager def _get_connection(self): """Get a database connection with proper cleanup.""" - conn = sqlite3.connect(self.db_path) + conn = sqlite3.connect(self.db_path, timeout=5.0) conn.row_factory = sqlite3.Row + # Enable WAL mode for better concurrent read/write performance + conn.execute("PRAGMA journal_mode=WAL") + # Set busy timeout to wait when database is locked (in addition to connect timeout) + conn.execute("PRAGMA busy_timeout=5000") + # Use NORMAL synchronous mode with WAL for good performance + durability + conn.execute("PRAGMA synchronous=NORMAL") try: yield conn finally: