rath.persistence#
Cross-plane atomic writes, root layout compatibility, and retention/garbage
collection for OpenRath’s .openrath/ data root.
Source#
Module |
Purpose |
|---|---|
|
Atomic text/JSON replacement helpers. |
|
Root layout and plane schema versions. |
|
Dry-run-first retention across persisted planes. |
Atomic writes#
from rath.persistence import atomic_write_json, atomic_write_text
atomic_write_text(path, "ready\n")
atomic_write_json(path, {"ready": True}, mode=0o600)
The helpers write a temporary sibling and replace the destination with
os.replace. A process-local, path-keyed lock serializes writers in the same
process; Windows sharing violations receive bounded retries.
This is not a cross-process transaction and does not replace the append/FileLock protocol used by Session JSONL persistence.
Root layout manifest#
.openrath/manifest.json records layout_version plus schema versions for the
config, backend, and memory planes. It does not describe Session JSONL.
API |
Behavior |
|---|---|
|
Creates or refreshes the current manifest. |
|
Rejects a layout version newer than this install. Missing legacy manifests are accepted. |
|
Current overall on-disk layout version. |
|
Raised for a newer unsupported layout. |
ConfigStore load/save is the automatic wiring point in v1.3.0. Other users of the data root may call the public helpers explicitly.
Two different manifests
.openrath/manifest.json is an on-disk compatibility record.
flow.ResourceManifest is a compile-time Workflow resource snapshot. They are
unrelated despite sharing the word “manifest.”
Garbage collection#
from datetime import timedelta
from rath.persistence import gc
preview = gc(older_than=timedelta(days=30))
deleted = gc(older_than=timedelta(days=30), dry_run=False)
dry_run=True is the default. GCReport contains sessions,
local_sandboxes, remote_sandboxes, memory_stores, memory_commits, and
dry_run.
Deletion is confined to the resolved OpenRath data root. Pruning a remote sandbox deletes the local registry record; it does not terminate the remote container.
Autodoc#
- rath.persistence.atomic_write_text(path: Path | str, text: str, *, newline: bool = False, encoding: str = 'utf-8', mode: int | None = None) None[source]#
Atomically write
texttopath.Creates the parent directory if missing. Writes a uniquely-named temp file in the same directory, then
os.replaceit into place. Concurrent writers to the same resolved path are serialized; the Windows sharing-violation window is retried. On any failure the temp file is removed and the original target is left untouched.newlineappends a trailing"\n"when the caller has not already.mode(e.g.0o600) restricts the final file on POSIX; ignored on Windows (matchingrath.config.secrets.chmod_user_only()).
- rath.persistence.atomic_write_json(path: Path | str, payload: Any, *, indent: int | None = 2, sort_keys: bool = False, ensure_ascii: bool = False, mode: int | None = None) None[source]#
Atomically write
payloadas JSON topath.Serialization happens before the temp file is created, so an unserializable payload raises without touching the filesystem (no temp debris, original target intact). Otherwise defers to
atomic_write_text().
- rath.persistence.gc(*, older_than: timedelta, dry_run: bool = True) GCReport[source]#
Sweep prunable artifacts older than
older_thanacross all planes.With
dry_run=True(default) nothing is deleted — the report lists what would be removed. Withdry_run=Falsethe existing per-plane prune helpers run and the memory commits archive is trimmed. Deletion is confined to the resolved data root.
- class rath.persistence.GCReport(sessions: list[~uuid.UUID] = <factory>, local_sandboxes: list[~uuid.UUID] = <factory>, remote_sandboxes: list[~uuid.UUID] = <factory>, memory_stores: list[~uuid.UUID] = <factory>, memory_commits: list[~pathlib.Path] = <factory>, dry_run: bool = True)[source]#
What a
gc()sweep removed (or would remove, in dry-run).
- rath.persistence.ensure_manifest(root: Path) dict[str, Any][source]#
Create the manifest if missing; return the effective manifest.
Idempotent: an existing current-layout manifest is refreshed with the latest per-plane schema versions but keeps its layout version.
- rath.persistence.check_manifest(root: Path) None[source]#
Raise
ManifestVersionErrorif the layout is newer than ours.No-op when the manifest is absent (fresh or legacy root) — this must never break an install that predates the manifest.