Scriptorium / backend /session_store.py
mattkevan's picture
First in space
af4851b
Raw
History Blame Contribute Delete
2.43 kB
import shutil
import time
import json
from pathlib import Path
from typing import Any, Dict, List, Optional
from backend.types import SessionRecord
class SessionStore:
def __init__(self, root: Path, ttl_seconds: int) -> None:
self.root = Path(root)
self.ttl_seconds = ttl_seconds
self.root.mkdir(parents=True, exist_ok=True)
self._sessions: Dict[str, SessionRecord] = {}
def _now(self) -> float:
return time.time()
def ensure_session(self, session_id: str) -> SessionRecord:
now = self._now()
session_root = self.root / session_id
session_root.mkdir(parents=True, exist_ok=True)
for child in ("uploads", "previews", "renders", "exports"):
(session_root / child).mkdir(exist_ok=True)
existing = self._sessions.get(session_id)
if existing is None:
existing = SessionRecord(
session_id=session_id,
root=session_root,
created_at=now,
touched_at=now,
)
self._sessions[session_id] = existing
else:
existing.touched_at = now
return existing
def touch(self, session_id: str) -> SessionRecord:
session = self.ensure_session(session_id)
session.touched_at = self._now()
return session
def save_json(self, session_id: str, name: str, payload: Dict[str, Any]) -> Path:
session = self.touch(session_id)
path = session.root / name
path.write_text(json.dumps(payload, ensure_ascii=True, indent=2), encoding="utf-8")
return path
def load_json(self, session_id: str, name: str) -> Dict[str, Any]:
session = self.touch(session_id)
path = session.root / name
if not path.exists():
raise FileNotFoundError(f"Session asset not found: {name}")
return json.loads(path.read_text(encoding="utf-8"))
def cleanup_expired(self, now: Optional[float] = None) -> List[str]:
current = self._now() if now is None else now
removed: List[str] = []
for session_id, record in list(self._sessions.items()):
if current - record.touched_at <= self.ttl_seconds:
continue
if record.root.exists():
shutil.rmtree(record.root)
removed.append(session_id)
del self._sessions[session_id]
return removed