|
@@ -216,6 +216,8 @@ _DASH_TTL = 60.0 # 秒
|
|
|
def _invalidate_dashboard():
|
|
def _invalidate_dashboard():
|
|
|
with _DASH_LOCK:
|
|
with _DASH_LOCK:
|
|
|
_DASH_CACHE["ts"] = 0.0
|
|
_DASH_CACHE["ts"] = 0.0
|
|
|
|
|
+ with _QUERIES_LOCK: # query 列表同样只在任务完成时变,一并作废
|
|
|
|
|
+ _QUERIES_CACHE.clear()
|
|
|
|
|
|
|
|
|
|
|
|
|
def _dashboard_cached():
|
|
def _dashboard_cached():
|
|
@@ -229,6 +231,24 @@ def _dashboard_cached():
|
|
|
return data
|
|
return data
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
+# ── query 列表缓存 ────────────────────────────────────────────────────────────
|
|
|
|
|
+# /api/queries 要全表 JSON_EXTRACT 算每组采纳数(远程 RDS ~2s),数据同样只在任务完成时变。
|
|
|
|
|
+# 缓存 per mode,任务结束随 dashboard 一并作废(见 _invalidate_dashboard);TTL 兜底外部改库。
|
|
|
|
|
+_QUERIES_CACHE = {} # mode -> {"data": [...], "ts": float}
|
|
|
|
|
+_QUERIES_LOCK = threading.Lock()
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+def _queries_cached(mode):
|
|
|
|
|
+ with _QUERIES_LOCK:
|
|
|
|
|
+ c = _QUERIES_CACHE.get(mode)
|
|
|
|
|
+ if c and time.monotonic() - c["ts"] < _DASH_TTL:
|
|
|
|
|
+ return c["data"]
|
|
|
|
|
+ data = db.fetch_queries(mode) # 计算放锁外,不阻塞其它请求
|
|
|
|
|
+ with _QUERIES_LOCK:
|
|
|
|
|
+ _QUERIES_CACHE[mode] = {"data": data, "ts": time.monotonic()}
|
|
|
|
|
+ return data
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
def _dashboard():
|
|
def _dashboard():
|
|
|
posts, procs, tools = db.fetch_dashboard_rows()
|
|
posts, procs, tools = db.fetch_dashboard_rows()
|
|
|
|
|
|
|
@@ -494,7 +514,7 @@ class Handler(BaseHTTPRequestHandler):
|
|
|
elif u.path == "/api/dashboard":
|
|
elif u.path == "/api/dashboard":
|
|
|
self._json_etag(_dashboard_cached())
|
|
self._json_etag(_dashboard_cached())
|
|
|
elif u.path == "/api/queries":
|
|
elif u.path == "/api/queries":
|
|
|
- self._json(db.fetch_queries(qs.get("mode", "process")))
|
|
|
|
|
|
|
+ self._json_etag(_queries_cached(qs.get("mode", "process")))
|
|
|
elif u.path == "/api/posts":
|
|
elif u.path == "/api/posts":
|
|
|
self._json(db.fetch_posts(qs.get("query_id", ""), qs.get("mode", "process")))
|
|
self._json(db.fetch_posts(qs.get("query_id", ""), qs.get("mode", "process")))
|
|
|
elif u.path == "/api/post":
|
|
elif u.path == "/api/post":
|