Fix concurrent DuckDB queries: use cursor() per thread

_conn.execute() is not thread-safe for concurrent calls from multiple
threads. asyncio.gather submits each analytics query to the thread pool
via asyncio.to_thread, causing race conditions that silently returned
empty result sets. _conn.cursor() creates an independent cursor that is
safe to use from separate threads simultaneously.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Deeman
2026-02-20 19:04:09 +01:00
parent d569ba0162
commit fef9f3d705

View File

@@ -57,7 +57,8 @@ async def fetch_analytics(sql: str, params: list | None = None) -> list[dict]:
assert _conn is not None, "Analytics DB not initialized — call open_analytics_db() first" assert _conn is not None, "Analytics DB not initialized — call open_analytics_db() first"
def _query(): def _query():
result = _conn.execute(sql, params or []) cursor = _conn.cursor()
result = cursor.execute(sql, params or [])
columns = [desc[0] for desc in result.description] columns = [desc[0] for desc in result.description]
return [dict(zip(columns, row)) for row in result.fetchall()] return [dict(zip(columns, row)) for row in result.fetchall()]