h
This commit is contained in:
@@ -4,6 +4,7 @@ import sqlite3
|
||||
import json
|
||||
from pathlib import Path
|
||||
from typing import Any, Dict, List, Optional
|
||||
from contextlib import contextmanager
|
||||
|
||||
# The database is located in the project root
|
||||
ROOT_DIR = Path(__file__).resolve().parent.parent
|
||||
@@ -19,8 +20,20 @@ class Database:
|
||||
return cls._instance
|
||||
|
||||
def _init_db(self):
|
||||
self.conn = sqlite3.connect(str(DB_PATH), check_same_thread=False)
|
||||
self.conn = sqlite3.connect(
|
||||
str(DB_PATH),
|
||||
check_same_thread=False,
|
||||
timeout=30.0 # Increase timeout to 30s to avoid locking issues
|
||||
)
|
||||
self.conn.row_factory = sqlite3.Row
|
||||
|
||||
# Use WAL mode for better concurrency (allows multiple readers + 1 writer)
|
||||
try:
|
||||
self.conn.execute("PRAGMA journal_mode=WAL")
|
||||
self.conn.execute("PRAGMA synchronous=NORMAL")
|
||||
except sqlite3.Error:
|
||||
pass
|
||||
|
||||
self._create_tables()
|
||||
|
||||
def _create_tables(self):
|
||||
@@ -89,19 +102,58 @@ class Database:
|
||||
|
||||
def execute(self, query: str, params: tuple = ()):
|
||||
cursor = self.conn.cursor()
|
||||
cursor.execute(query, params)
|
||||
self.conn.commit()
|
||||
return cursor
|
||||
try:
|
||||
cursor.execute(query, params)
|
||||
if not self.conn.in_transaction:
|
||||
self.conn.commit()
|
||||
return cursor
|
||||
except Exception:
|
||||
if not self.conn.in_transaction:
|
||||
self.conn.rollback()
|
||||
raise
|
||||
|
||||
def executemany(self, query: str, param_list: List[tuple]):
|
||||
cursor = self.conn.cursor()
|
||||
try:
|
||||
cursor.executemany(query, param_list)
|
||||
if not self.conn.in_transaction:
|
||||
self.conn.commit()
|
||||
return cursor
|
||||
except Exception:
|
||||
if not self.conn.in_transaction:
|
||||
self.conn.rollback()
|
||||
raise
|
||||
|
||||
@contextmanager
|
||||
def transaction(self):
|
||||
"""Context manager for a database transaction."""
|
||||
if self.conn.in_transaction:
|
||||
# Already in a transaction, just yield
|
||||
yield self.conn
|
||||
else:
|
||||
try:
|
||||
self.conn.execute("BEGIN")
|
||||
yield self.conn
|
||||
self.conn.commit()
|
||||
except Exception:
|
||||
self.conn.rollback()
|
||||
raise
|
||||
|
||||
def fetchall(self, query: str, params: tuple = ()):
|
||||
cursor = self.conn.cursor()
|
||||
cursor.execute(query, params)
|
||||
return cursor.fetchall()
|
||||
try:
|
||||
cursor.execute(query, params)
|
||||
return cursor.fetchall()
|
||||
finally:
|
||||
cursor.close()
|
||||
|
||||
def fetchone(self, query: str, params: tuple = ()):
|
||||
cursor = self.conn.cursor()
|
||||
cursor.execute(query, params)
|
||||
return cursor.fetchone()
|
||||
try:
|
||||
cursor.execute(query, params)
|
||||
return cursor.fetchone()
|
||||
finally:
|
||||
cursor.close()
|
||||
|
||||
# Singleton instance
|
||||
db = Database()
|
||||
|
||||
Reference in New Issue
Block a user