fix(gateway): runtime-status writer merges over out-of-process stamps
The background writer persisted the in-memory canonical snapshot verbatim. origin/main re-read gateway_state.json on every write, so keys stamped by other processes survived; with the snapshot they were clobbered on the next publish. Out-of-process writers exist: hermes gateway migrate --standalone (_reconcile_standalone_runtime) rewrites the live multiplexer's file, and container_boot seeds desired_state/migrated_from. Re-read the file in the writer thread immediately before writing and lay the gateway's fields over it: the gateway wins for every key it owns, foreign keys survive.
This commit is contained in:
@@ -135,7 +135,7 @@ class _RuntimeStatusWriter:
|
||||
self._writing_generation = generation
|
||||
error: Optional[BaseException] = None
|
||||
try:
|
||||
(self._write_fn or _write_json_file)(path, payload)
|
||||
(self._write_fn or _write_json_file)(path, _merge_over_on_disk(path, payload))
|
||||
except BaseException as exc:
|
||||
error = exc
|
||||
with self._condition:
|
||||
@@ -162,6 +162,16 @@ class _RuntimeStatusWriter:
|
||||
_runtime_status_state_lock = threading.RLock()
|
||||
_runtime_status_state_path: Optional[Path] = None
|
||||
_runtime_status_state: Optional[dict[str, Any]] = None
|
||||
|
||||
|
||||
def _merge_over_on_disk(path: Path, payload: dict[str, Any]) -> dict[str, Any]:
|
||||
"""Lay the canonical snapshot over whatever is on disk right before writing. Out-of-process
|
||||
writers (``hermes gateway migrate --standalone`` clearing multiplex-owned status, container_boot
|
||||
seeding ``desired_state``) stamp this file directly; the gateway's fields win, theirs survive."""
|
||||
existing = _read_json_file(path)
|
||||
return {**existing, **payload} if isinstance(existing, dict) else payload
|
||||
|
||||
|
||||
_runtime_status_writer_lock = threading.Lock()
|
||||
_runtime_status_writer: Optional[_RuntimeStatusWriter] = None
|
||||
|
||||
|
||||
Reference in New Issue
Block a user