"""Persistent cost state management. Cost state is stored at /data/cost_state.json, separate from config.json. This file is updated each time a cost calculation occurs, enabling persistence across restarts without bloating the config file. """ import json import logging import os import tempfile from typing import Optional logger = logging.getLogger(__name__) COST_STATE_PATH = "/data/cost_state.json" def load_cost_state(path: Optional[str] = None) -> dict: """Load persisted cost state from disk. Returns: Dict keyed by meter_id (str) with cost state values. """ path = path or COST_STATE_PATH if not os.path.isfile(path): return {} try: with open(path) as f: return json.load(f) except Exception as e: logger.warning("Failed to load cost state: %s", e) return {} def save_cost_state(states: dict, path: Optional[str] = None): """Atomically save cost state to disk.""" path = path or COST_STATE_PATH dir_path = os.path.dirname(path) if dir_path: os.makedirs(dir_path, exist_ok=True) fd, tmp_path = tempfile.mkstemp(dir=dir_path or ".", suffix=".tmp") try: with os.fdopen(fd, "w") as f: json.dump(states, f, indent=2) f.write("\n") f.flush() os.fsync(f.fileno()) os.replace(tmp_path, path) except Exception: try: os.unlink(tmp_path) except OSError: pass raise