libgrite-git
Git-backed write-ahead log, distributed synchronization, and snapshot management for event-sourced applications.
libgrite-git bridges Grite's event model to git repositories. It writes events as an append-only WAL in git refs, manages periodic snapshots of materialized state, handles multi-actor synchronization with CRDT semantics, and coordinates distributed locks across agents.
If you are building an application that needs append-only logs in git, distributed sync through existing git remotes, or deterministic CRDT merging, this crate provides the infrastructure.
What This Crate Provides
Git-Backed Write-Ahead Log (WAL)
The WalManager stores events as git commits in refs/grite/wal, with each commit containing:
- A
meta.jsonblob with actor ID, chunk hash, and parent reference - A CBOR-encoded chunk of events in a date-based tree structure (
events/YYYY/MM/DD/<hash>.bin)
This design gives you:
- Version-controlled history — Every event batch is a git commit. Use standard git tools to inspect, diff, and revert.
- Content-addressed chunks — Each chunk is identified by its BLAKE2b hash. Corruption is immediately detectable.
- Efficient storage — CBOR encoding is compact. Date-based tree sharding prevents giant directories.
- Atomic appends — A WAL commit is all-or-nothing. No partial writes.
Distributed Synchronization
The SyncManager pulls WAL refs from remote repositories and merges them using the CRDT semantics defined in libgrite-core:
- Pull remote WALs —
git fetchretrieves remoterefs/grite/walreferences. - CRDT merge — New events are merged into the local WAL using deterministic ordering. No conflicts, no manual resolution.
- Push local WALs —
git pushpublishes your events to the shared remote. - Branch awareness — Issues created on a feature branch stay on that branch. Merge the branch, merge the issues.
This means your issue tracker syncs through the exact same mechanism as your code. If you can collaborate on code with git, you can collaborate on issues with Grite. No new protocols, no new infrastructure.
Snapshot Management
The SnapshotManager creates and restores snapshots of the materialized view:
- Fast rebuild — Snapshots capture the full sled database state as git tree objects. Rebuild from a snapshot in ~50ms instead of replaying thousands of events.
- Automatic creation — Snapshots are created automatically when the event count exceeds a threshold.
- Garbage collection — Old snapshots are pruned to keep storage bounded.
Distributed Locks
The LockManager provides lease-based distributed locking across actors:
- Resource claims — Lock any string resource (file path, module name, task ID) with a configurable TTL.
- Lease expiration — Locks automatically expire, preventing deadlocks when agents crash.
- Reentrant safety — The same actor can renew or extend an existing lock.
- Git-backed storage — Lock state lives in
refs/grite/locks/, synced with the rest of the WAL.
Key Types
WAL Manager
use WalManager;
// Open the WAL for a repository
let wal = open?;
// Append events (creates a new git commit)
let oid = wal.append?;
// Read all events from the WAL
let all_events = wal.read_all?;
// Read events since a specific commit
let new_events = wal.read_since?;
Snapshot Manager
use SnapshotManager;
let snapshots = open?;
// Create a snapshot from the current materialized state
let snapshot_oid = snapshots.create?;
// List all snapshots (newest first)
let list = snapshots.list?;
// Read events from a snapshot
let events = snapshots.read?;
// GC old snapshots, keeping the 3 most recent
let stats = snapshots.gc?;
Sync Manager
use SyncManager;
let sync = open?;
// Pull and merge remote WAL
sync.pull?;
// Push local WAL to remote
sync.push?;
Lock Manager
use LockManager;
let locks = open?;
// Acquire a lock with a 1-hour TTL
locks.acquire?;
// Check if a resource is locked
if let Some = locks.check?
// Release a lock
locks.release?;
Quick Example
use WalManager;
use ;
use ;
WAL Format
Each WAL commit is a git commit with the following tree structure:
<commit>
├── meta.json # Actor ID, chunk hash, parent WAL ref
└── events/
└── 2026/
└── 05/
└── 09/
└── <blake2b-hash>.bin # CBOR-encoded event chunk
meta.json
Chunk Encoding
Events are grouped into chunks and encoded with CBOR:
- Compact — CBOR is a binary JSON alternative that is smaller and faster to parse.
- Schema-evolvable — New event kinds can be added without breaking existing readers.
- Hash-verified — The chunk hash in
meta.jsonensures integrity.
Design Decisions
Why Git Refs Instead of Files?
We store the WAL in git refs (refs/grite/wal) rather than tracked files for several reasons:
- No working tree pollution — The working tree stays clean. No
.grite/directory full of JSON files. - Automatic versioning — Every WAL append is a git commit. You get history, diffs, and revert for free.
- Native sync —
git fetchandgit pushsync the WAL alongside your code. No new protocols. - Branch isolation — WAL refs are per-branch. Issues on a feature branch do not leak into main until merged.
Why Not Pack Files?
Git pack files are great for code but not ideal for append-only event logs:
- Random access — We need to read the latest events without unpacking the entire history.
- Independent chunks — Each WAL commit contains only its own events, not the full history.
- Snapshot optimization — Snapshots provide fast random access to materialized state without replay.
Why Date-Based Tree Sharding?
The events/YYYY/MM/DD/<hash>.bin structure prevents any single git tree from growing too large:
- Git trees with thousands of entries become slow.
- Date sharding keeps each directory to a manageable size.
- The hash in the filename ensures uniqueness even if multiple chunks occur on the same day.
Use Cases Beyond Grite
libgrite-git is designed for Grite but its primitives are reusable:
- Audit logging in git — Append audit events to a git ref for tamper-evident, version-controlled logs.
- Distributed state machines — Use the WAL + CRDT merge pattern for any collaborative state that needs to sync through git.
- Git-backed databases — The snapshot + WAL pattern is a general-purpose embedded database architecture.
- Lock coordination — The distributed lock manager works for any resource that needs cross-agent coordination.
See Also
- Grite Repository — Main project and documentation
- libgrite-core — Data model and CRDT projections (used by this crate)
- libgrite-ipc — IPC protocol for daemon communication
- docs.rs/libgrite-git — Full Rust API documentation
License
MIT License — see LICENSE for details.