"""Persist RegistryManager by replaying create/update events.""" from __future__ import annotations import base64 import json from pathlib import Path from typing import Any import zkac def save_events(path: Path, events: list[dict[str, Any]]) -> None: path.parent.mkdir(parents=True, exist_ok=True) path.write_text(json.dumps({"events": events}, indent=2), encoding="utf-8") def load_events(path: Path) -> list[dict[str, Any]]: if not path.is_file(): return [] data = json.loads(path.read_text(encoding="utf-8")) return list(data.get("events", [])) def replay_manager(events: list[dict[str, Any]]) -> zkac.RegistryManager: """Rebuild manager from persisted events (multiple registries supported).""" mgr = zkac.RegistryManager() by_rid: dict[bytes, list[dict[str, Any]]] = {} for e in events: st = base64.b64decode(e["state_b64"]) st_obj = zkac.RegistryState.deserialize(st) rid = st_obj.registry_id() by_rid.setdefault(rid, []).append(e) for rid, evs in by_rid.items(): evs.sort( key=lambda e: zkac.RegistryState.deserialize( base64.b64decode(e["state_b64"]) ).version() ) for i, e in enumerate(evs): st = base64.b64decode(e["state_b64"]) cert = base64.b64decode(e["state_cert_b64"]) if i == 0: mgr.create(st, cert) else: mgr.update(rid, st, cert) return mgr def append_event(path: Path, op: str, state_bytes: bytes, state_cert: bytes) -> None: events = load_events(path) events.append( { "op": op, "state_b64": base64.b64encode(state_bytes).decode(), "state_cert_b64": base64.b64encode(state_cert).decode(), } ) save_events(path, events)