Git-backed KV store with CRDT sync (extension module for mizchi/bit)
Dependencies
┌─────────────────────────────────────────────────────────┐
│ GitDb │
├─────────────────────────────────────────────────────────┤
│ Hierarchical KV Store │
│ - Keys: "/users/alice/profile" → Git tree path │
│ - Values: Bytes → Git blob │
├─────────────────────────────────────────────────────────┤
│ GitFs (Copy-on-Write Layer) │
│ - Read: Git tree/blob traversal with caching │
│ - Write: In-memory working layer │
│ - Snapshot: Creates Git commits │
├─────────────────────────────────────────────────────────┤
│ Gossip Protocol │
│ - VectorClock: Causal ordering │
│ - Announce: Broadcast HEAD state │
│ - Sync: Exchange Git objects │
│ - Merge: LWW / KeepBoth / Custom strategies │
└─────────────────────────────────────────────────────────┘let db = GitDb::empty(NodeId::new("node1"), "/repo/.git")
// Set/Get
db.set("/users/alice/name", b"Alice")
let name = db.get(fs, "/users/alice/name") // Some(b"Alice")
// List keys
let users = db.list(fs, "/users") // ["alice", "bob"]
// Delete
db.delete("/users/alice/name")// Commit changes
let commit_id = db.commit(fs, fs, "Add user alice", timestamp)
// Rollback uncommitted changes
db.rollback()// Get current state for broadcasting
let state = db.get_gossip_state(timestamp)
// Handle incoming gossip message
let response = db.handle_gossip(fs, message, timestamp)
// Select random peers for gossip
let peers = db.select_gossip_peers(3, seed)
// Merge with remote state
let result = db.merge(fs, fs, their_head, their_clock, LastWriteWins, timestamp)| Approach | Consistency | Complexity | Use Case |
|---|---|---|---|
| Raft | Strong (CP) | High (leader election, log replication) | Financial, config management |
| Git + Gossip | Eventual | Low (push/pull + conflict resolution) | Code, data, config |
// Durable Object
export class GitDbNode {
private db: GitDb;
async fetch(request: Request) {
const msg = await request.json() as GossipMessage;
const response = this.db.handle_gossip(msg, Date.now());
return Response.json(response);
}
// Periodic gossip with random peers
async alarm() {
const peers = this.db.select_gossip_peers(3, Date.now());
for (const peer of peers) {
const state = this.db.get_gossip_state(Date.now());
await fetch(peer.endpoint, {
method: 'POST',
body: JSON.stringify({ type: 'Announce', state })
});
}
}
}pub(all) struct GossipState {
node_id : NodeId
head : ObjectId
clock : VectorClock
timestamp : Int64
}pub struct Kv {
node_id : NodeId
tree : &WorkingTree
store : &ObjectStore
clock : VectorClock
head : ObjectId
sync_engine : SyncEngine
pending_objects : Map[String, GitObject]
snapshot_cache : Map[Int, SerializedSnapshot]
snapshot_bytes_cache : Map[Int, Bytes]
}fn Kv::merge(self : Kv, their_head : ObjectId, their_clock : VectorClock, strategy : MergeStrategy, timestamp : Int64) -> MergeResult raise GitErrorfn Kv::sync_round(self : Kv, count : Int, seed : Int64, timestamp : Int64, exchange : (PeerInfo, GossipMessage) -> Result[GossipMessage?, String]) -> SyncRoundResultpub(all) struct KvConfig {
node_id : NodeId
max_peers : Int
gossip_interval_ms : Int
sync_batch_size : Int
}pub(all) enum MergeStrategy {
LastWriteWins
KeepBoth
Custom((Bytes, Bytes) -> Bytes)
}pub(all) struct NodeId {
id : String
}pub(all) struct PeerSyncState {
peer : PeerInfo
cursor : Int64?
last_sync_at : Int64?
last_attempt_at : Int64?
retry_count : Int
next_retry_at : Int64
}pub(all) struct SerializationStats {
total_bytes : Int
object_count : Int
commit_count : Int
tree_count : Int
blob_count : Int
blob_bytes : Int
}pub(all) struct SerializedObject {
id : Bytes
obj_type : Int
data : Bytes
}pub(all) struct SerializedSnapshot {
version : Int
node_id : String
head : Bytes
clock : Array[(String, Int64)]
objects : Array[SerializedObject]
}pub(all) enum SnapshotMode {
FullHistory
HeadState
TreeAndBlobOnly
}fn SyncEngine::record_sync_result(self : SyncEngine, node_id : NodeId, success : Bool, timestamp : Int64) -> Unitfn SyncEngine::select_peers(self : SyncEngine, count : Int, seed : Int64, timestamp : Int64) -> Array[PeerInfo]pub(all) struct SyncEngineConfig {
anti_entropy_interval_ms : Int64
retry_base_ms : Int64
retry_max_ms : Int64
}pub(all) struct SyncRoundResult {
selected : Int
attempted : Int
succeeded : Int
failed : Int
messages_sent : Int
messages_received : Int
}Git-backed KV store with CRDT sync (extension module for mizchi/bit)
Dependencies