|
10 | 10 | """ |
11 | 11 |
|
12 | 12 | import sqlite3 |
| 13 | +from collections.abc import Iterator |
| 14 | +from contextlib import contextmanager |
13 | 15 | from pathlib import Path |
14 | | -from typing import Any |
15 | 16 |
|
16 | 17 | from ..config import get_config_manager |
17 | 18 | from ..logging_config import get_detail_logger, get_status_logger |
18 | 19 | from ..utils.dead_code import code_is_used |
19 | | -from .connection_utils import ( |
20 | | - get_configured_connection, |
21 | | - get_connection_with_row_factory, |
22 | | -) |
| 20 | +from .connection_utils import configure_sqlite_connection |
23 | 21 | from .schema import init_database |
24 | 22 |
|
25 | 23 |
|
@@ -84,44 +82,69 @@ def __init__(self, db_path: Path | None = None): |
84 | 82 | raise RuntimeError(error_msg) from e |
85 | 83 |
|
86 | 84 | self.db_path = db_path |
| 85 | + self._conn: sqlite3.Connection | None = None |
| 86 | + |
| 87 | + def _open_conn(self) -> sqlite3.Connection: |
| 88 | + """Open and configure the persistent connection (called once per instance).""" |
| 89 | + conn = sqlite3.connect(str(self.db_path), timeout=30.0) |
| 90 | + configure_sqlite_connection(conn) |
| 91 | + return conn |
| 92 | + |
| 93 | + def _get_or_open_conn(self) -> sqlite3.Connection: |
| 94 | + """Return the persistent connection, creating it on first use.""" |
| 95 | + if self._conn is None: |
| 96 | + self._conn = self._open_conn() |
| 97 | + return self._conn |
| 98 | + |
| 99 | + @contextmanager |
| 100 | + def get_connection( |
| 101 | + self, timeout: float = 30.0, enable_wal: bool = True |
| 102 | + ) -> Iterator[sqlite3.Connection]: |
| 103 | + """Get the persistent SQLite connection to this cache's database. |
87 | 104 |
|
88 | | - def get_connection(self, timeout: float = 30.0, enable_wal: bool = True) -> Any: |
89 | | - """Get a configured SQLite connection to this cache's database. |
90 | | -
|
91 | | - This method provides the standard way to access the database with |
92 | | - consistent configuration across all cache components. Uses the |
93 | | - centralized connection configuration with proper timeout and WAL mode. |
| 105 | + Reuses a single long-lived connection per instance. Commits on success |
| 106 | + and rolls back on exception, but does not close the connection. |
94 | 107 |
|
95 | 108 | Args: |
96 | | - timeout: Connection timeout in seconds (default: 30.0) |
97 | | - enable_wal: Whether to enable WAL mode (default: True) |
98 | | -
|
99 | | - Returns: |
100 | | - Context manager yielding a configured SQLite connection |
101 | | -
|
102 | | - Example: |
103 | | - ```python |
104 | | - with self.get_connection() as conn: |
105 | | - cursor = conn.cursor() |
106 | | - cursor.execute("SELECT * FROM table") |
107 | | - results = cursor.fetchall() |
108 | | - ``` |
109 | | - """ |
110 | | - return get_configured_connection(self.db_path, timeout, enable_wal) |
| 109 | + timeout: Ignored (kept for API compatibility; set at construction) |
| 110 | + enable_wal: Ignored (kept for API compatibility; set at construction) |
111 | 111 |
|
| 112 | + Yields: |
| 113 | + Configured SQLite connection |
| 114 | + """ |
| 115 | + del timeout, enable_wal # set once at connection creation |
| 116 | + conn = self._get_or_open_conn() |
| 117 | + try: |
| 118 | + yield conn |
| 119 | + conn.commit() |
| 120 | + except Exception: |
| 121 | + conn.rollback() |
| 122 | + raise |
| 123 | + |
| 124 | + @contextmanager |
112 | 125 | def get_connection_with_row_factory( |
113 | 126 | self, timeout: float = 30.0, enable_wal: bool = True |
114 | | - ) -> Any: |
115 | | - """Get a configured SQLite connection with Row factory for dict-like access. |
| 127 | + ) -> Iterator[sqlite3.Connection]: |
| 128 | + """Get the persistent connection with Row factory for dict-like access. |
116 | 129 |
|
117 | | - Same as get_connection() but with sqlite3.Row factory enabled |
118 | | - for dictionary-style access to query results. |
| 130 | + Same as get_connection() but temporarily sets sqlite3.Row factory |
| 131 | + for the duration of the block. |
119 | 132 |
|
120 | 133 | Args: |
121 | | - timeout: Connection timeout in seconds (default: 30.0) |
122 | | - enable_wal: Whether to enable WAL mode (default: True) |
| 134 | + timeout: Ignored (kept for API compatibility; set at construction) |
| 135 | + enable_wal: Ignored (kept for API compatibility; set at construction) |
123 | 136 |
|
124 | | - Returns: |
125 | | - Context manager yielding a configured SQLite connection with Row factory |
| 137 | + Yields: |
| 138 | + Configured SQLite connection with Row factory |
126 | 139 | """ |
127 | | - return get_connection_with_row_factory(self.db_path, timeout, enable_wal) |
| 140 | + del timeout, enable_wal # set once at connection creation |
| 141 | + conn = self._get_or_open_conn() |
| 142 | + conn.row_factory = sqlite3.Row |
| 143 | + try: |
| 144 | + yield conn |
| 145 | + conn.commit() |
| 146 | + except Exception: |
| 147 | + conn.rollback() |
| 148 | + raise |
| 149 | + finally: |
| 150 | + conn.row_factory = None |
0 commit comments