gMAS / src /utils /state_storage.py
Артём Боярских
chore: initial commit
3193174
import json
from pathlib import Path
from typing import Any
__all__ = ["FileStateStorage", "InMemoryStateStorage"]
class InMemoryStateStorage:
"""Simple in-memory storage for node states."""
def __init__(self) -> None:
self._store: dict[str, dict[str, Any]] = {}
def save(self, node_id: str, state: dict[str, Any]) -> None:
self._store[node_id] = state
def load(self, node_id: str) -> dict[str, Any] | None:
return self._store.get(node_id)
def delete(self, node_id: str) -> None:
self._store.pop(node_id, None)
def keys(self) -> list[str]:
return list(self._store.keys())
def clear(self) -> None:
self._store.clear()
class FileStateStorage:
"""File-based JSON storage for node states."""
def __init__(self, directory: Path | str) -> None:
self._dir = Path(directory)
self._dir.mkdir(parents=True, exist_ok=True)
def _path(self, node_id: str) -> Path:
safe_id = "".join(c if c.isalnum() or c in "-_" else "_" for c in node_id)
return self._dir / f"{safe_id}.json"
def save(self, node_id: str, state: dict[str, Any]) -> None:
path = self._path(node_id)
with path.open("w", encoding="utf-8") as f:
json.dump({"node_id": node_id, "state": state}, f, ensure_ascii=False, indent=2)
def load(self, node_id: str) -> dict[str, Any] | None:
path = self._path(node_id)
if not path.exists():
return None
with path.open("r", encoding="utf-8") as f:
data = json.load(f)
return data.get("state")
def delete(self, node_id: str) -> None:
path = self._path(node_id)
if path.exists():
path.unlink()
def keys(self) -> list[str]:
result = []
for p in self._dir.glob("*.json"):
try:
with p.open("r", encoding="utf-8") as f:
data = json.load(f)
if "node_id" in data:
result.append(data["node_id"])
except (json.JSONDecodeError, KeyError):
continue
return result
def clear(self) -> None:
for p in self._dir.glob("*.json"):
p.unlink()