60 lines
1.8 KiB
Python
60 lines
1.8 KiB
Python
"""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)
|