Speed up API reads with data cache and faster server check/stats.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
orohi
2026-07-26 06:07:44 +03:00
co-authored by Cursor
parent 2b28892a9b
commit fa3569f81f
3 changed files with 280 additions and 190 deletions
+36 -1
View File
@@ -6,10 +6,12 @@ FastAPI handlers keep working without a full rewrite.
from __future__ import annotations
import copy
import json
import logging
import os
import shutil
import threading
from datetime import datetime, timezone
from pathlib import Path
from typing import Any, Optional
@@ -21,6 +23,11 @@ from .connection import get_pool, init_schema
logger = logging.getLogger(__name__)
# Process-wide snapshot cache. load_data() returns a deep copy so callers can
# mutate safely; save_data() refreshes the cache after a successful write.
_DATA_CACHE: Optional[dict] = None
_DATA_CACHE_LOCK = threading.RLock()
DEFAULT_SETTINGS = {
'appearance': {
'title': 'Amnezia',
@@ -208,7 +215,13 @@ def _row_to_invite(row) -> dict:
}
def load_data() -> dict:
def invalidate_data_cache() -> None:
global _DATA_CACHE
with _DATA_CACHE_LOCK:
_DATA_CACHE = None
def _fetch_data_from_db() -> dict:
init_schema()
pool = get_pool()
with pool.connection() as conn:
@@ -266,8 +279,20 @@ def load_data() -> dict:
}
def load_data() -> dict:
"""Return panel state. Uses an in-process cache; always returns a deep copy."""
global _DATA_CACHE
with _DATA_CACHE_LOCK:
if _DATA_CACHE is not None:
return copy.deepcopy(_DATA_CACHE)
data = _fetch_data_from_db()
_DATA_CACHE = data
return copy.deepcopy(data)
def save_data(data: dict) -> None:
"""Replace panel state in a single transaction (same semantics as rewriting data.json)."""
global _DATA_CACHE
init_schema()
servers = data.get('servers') or []
users = data.get('users') or []
@@ -419,6 +444,16 @@ def save_data(data: dict) -> None:
)
conn.commit()
# Keep caller dict and cache aligned with what was actually persisted
data['servers'] = servers
data['users'] = users
data['user_connections'] = connections
data['api_tokens'] = tokens
data['invite_links'] = invite_links
data['settings'] = settings
with _DATA_CACHE_LOCK:
_DATA_CACHE = copy.deepcopy(data)
def export_data_dict() -> dict:
"""Export current DB state as the legacy data.json document."""