Fix SQLite lock errors on /api/stats under concurrent writes.
Retry stats cache commits, serialize refresh, and fall back to read-only compute so the stats API does not return 500 when the database is briefly locked. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+12
-5
@@ -7,11 +7,16 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import threading
|
||||
from datetime import datetime
|
||||
from typing import Any, Optional
|
||||
|
||||
from zoneinfo import ZoneInfo
|
||||
|
||||
from db_conn import commit_retry, execute_retry
|
||||
|
||||
_stats_refresh_lock = threading.Lock()
|
||||
|
||||
TZ = ZoneInfo("Asia/Shanghai")
|
||||
|
||||
STATS_VIEWS = [
|
||||
@@ -288,13 +293,14 @@ def build_all_stats(conn, live_capital: float = 0.0) -> dict:
|
||||
|
||||
|
||||
def save_stats_cache(conn, data: dict) -> None:
|
||||
conn.execute(
|
||||
execute_retry(
|
||||
conn,
|
||||
"""INSERT INTO stats_cache (key, data_json, updated_at)
|
||||
VALUES ('all', ?, ?)
|
||||
ON CONFLICT(key) DO UPDATE SET data_json=excluded.data_json, updated_at=excluded.updated_at""",
|
||||
(json.dumps(data, ensure_ascii=False), data["updated_at"]),
|
||||
)
|
||||
conn.commit()
|
||||
commit_retry(conn)
|
||||
|
||||
|
||||
def load_stats_cache(conn) -> Optional[dict]:
|
||||
@@ -310,6 +316,7 @@ def load_stats_cache(conn) -> Optional[dict]:
|
||||
|
||||
|
||||
def refresh_stats_cache(conn, live_capital: float = 0.0) -> dict:
|
||||
data = build_all_stats(conn, live_capital)
|
||||
save_stats_cache(conn, data)
|
||||
return data
|
||||
with _stats_refresh_lock:
|
||||
data = build_all_stats(conn, live_capital)
|
||||
save_stats_cache(conn, data)
|
||||
return data
|
||||
|
||||
Reference in New Issue
Block a user