study / services /storage /json_storage.py
xiaolongmr
Add shop access and persistent bucket support
a318da0
Raw History Blame Contribute Delete
4.32 kB
from __future__ import annotations
import json
from pathlib import Path
from typing import Any
from services.storage.base import StorageBackend
class JSONStorageBackend(StorageBackend):
"""Local JSON file storage backend."""
def __init__(self, file_path: Path, auth_keys_path: Path | None = None, shop_state_path: Path | None = None):
self.file_path = file_path
self.auth_keys_path = auth_keys_path or file_path.with_name("auth_keys.json")
self.shop_state_path = shop_state_path or file_path.with_name("shop_state.json")
self.file_path.parent.mkdir(parents=True, exist_ok=True)
self.auth_keys_path.parent.mkdir(parents=True, exist_ok=True)
self.shop_state_path.parent.mkdir(parents=True, exist_ok=True)
@staticmethod
def _load_json_list(file_path: Path) -> list[dict[str, Any]]:
if not file_path.exists():
return []
try:
data = json.loads(file_path.read_text(encoding="utf-8"))
return data if isinstance(data, list) else []
except (json.JSONDecodeError, Exception):
return []
@staticmethod
def _save_json_list(file_path: Path, items: list[dict[str, Any]]) -> None:
file_path.parent.mkdir(parents=True, exist_ok=True)
file_path.write_text(
json.dumps(items, ensure_ascii=False, indent=2) + "\n",
encoding="utf-8",
)
def load_accounts(self) -> list[dict[str, Any]]:
return self._load_json_list(self.file_path)
def save_accounts(self, accounts: list[dict[str, Any]]) -> None:
self._save_json_list(self.file_path, accounts)
def load_auth_keys(self) -> list[dict[str, Any]]:
if not self.auth_keys_path.exists():
return []
try:
data = json.loads(self.auth_keys_path.read_text(encoding="utf-8"))
except (json.JSONDecodeError, Exception):
return []
if isinstance(data, dict):
data = data.get("items")
return data if isinstance(data, list) else []
def save_auth_keys(self, auth_keys: list[dict[str, Any]]) -> None:
self.auth_keys_path.parent.mkdir(parents=True, exist_ok=True)
self.auth_keys_path.write_text(
json.dumps({"items": auth_keys}, ensure_ascii=False, indent=2) + "\n",
encoding="utf-8",
)
def load_shop_state(self) -> dict[str, Any]:
if not self.shop_state_path.exists():
return {}
try:
data = json.loads(self.shop_state_path.read_text(encoding="utf-8"))
except (json.JSONDecodeError, Exception):
return {}
return data if isinstance(data, dict) else {}
def save_shop_state(self, state: dict[str, Any]) -> None:
self.shop_state_path.parent.mkdir(parents=True, exist_ok=True)
self.shop_state_path.write_text(
json.dumps(state, ensure_ascii=False, indent=2) + "\n",
encoding="utf-8",
)
def health_check(self) -> dict[str, Any]:
try:
if self.file_path.exists():
self.file_path.read_text(encoding="utf-8")
return {
"status": "healthy",
"backend": "json",
"file_exists": self.file_path.exists(),
"file_path": str(self.file_path),
"auth_keys_file_exists": self.auth_keys_path.exists(),
"auth_keys_file_path": str(self.auth_keys_path),
"shop_state_file_exists": self.shop_state_path.exists(),
"shop_state_file_path": str(self.shop_state_path),
}
except Exception as e:
return {
"status": "unhealthy",
"backend": "json",
"error": str(e),
}
def get_backend_info(self) -> dict[str, Any]:
return {
"type": "json",
"description": "Local JSON file storage",
"file_path": str(self.file_path),
"file_exists": self.file_path.exists(),
"auth_keys_file_path": str(self.auth_keys_path),
"auth_keys_file_exists": self.auth_keys_path.exists(),
"shop_state_file_path": str(self.shop_state_path),
"shop_state_file_exists": self.shop_state_path.exists(),
}