62 lines
2.2 KiB
Python
62 lines
2.2 KiB
Python
from __future__ import annotations
|
|
|
|
import json
|
|
import threading
|
|
from pathlib import Path
|
|
from typing import Any
|
|
|
|
|
|
class SessionStore:
|
|
def __init__(self, base_dir: Path) -> None:
|
|
self.base_dir = base_dir
|
|
self.base_dir.mkdir(parents=True, exist_ok=True)
|
|
self._lock = threading.RLock()
|
|
|
|
def _path(self, session_id: str) -> Path:
|
|
return self.base_dir / f"{session_id}.json"
|
|
|
|
def load(self, session_id: str) -> dict[str, Any]:
|
|
path = self._path(session_id)
|
|
if not path.exists():
|
|
return {"session_id": session_id, "messages": []}
|
|
return json.loads(path.read_text(encoding="utf-8"))
|
|
|
|
def save(self, session_id: str, payload: dict[str, Any]) -> None:
|
|
with self._lock:
|
|
self._path(session_id).write_text(
|
|
json.dumps(payload, ensure_ascii=False, indent=2),
|
|
encoding="utf-8",
|
|
)
|
|
|
|
def append_message(self, session_id: str, message: dict[str, Any]) -> dict[str, Any]:
|
|
with self._lock:
|
|
payload = self.load(session_id)
|
|
payload.setdefault("messages", []).append(message)
|
|
self.save(session_id, payload)
|
|
return payload
|
|
|
|
def list_sessions(self) -> list[dict[str, Any]]:
|
|
sessions: list[dict[str, Any]] = []
|
|
for path in sorted(self.base_dir.glob("*.json")):
|
|
try:
|
|
payload = json.loads(path.read_text(encoding="utf-8"))
|
|
except (OSError, json.JSONDecodeError):
|
|
continue
|
|
sessions.append(
|
|
{
|
|
"session_id": payload.get("session_id", path.stem),
|
|
"user_id": payload.get("user_id"),
|
|
"updated_at": payload.get("updated_at"),
|
|
"message_count": len(payload.get("messages", [])),
|
|
"last_answer": payload.get("last_answer"),
|
|
}
|
|
)
|
|
sessions.sort(key=lambda item: item.get("updated_at") or 0, reverse=True)
|
|
return sessions
|
|
|
|
def clear(self, session_id: str) -> None:
|
|
with self._lock:
|
|
path = self._path(session_id)
|
|
if path.exists():
|
|
path.unlink()
|