Live sync KV stores over Iroh

This commit is contained in:
Eric Wendland 2026-05-18 18:36:03 +02:00
commit f85039367c
9 changed files with 473 additions and 13 deletions

View file

@ -4,7 +4,7 @@ use geth_db::{CrSqliteChangeBatch, DbResource};
use geth_discovery::{DiscoveredPeer, PeerCard};
use geth_document::{DocumentResource, DocumentState};
use geth_keychain::KeychainOp;
use geth_kv::{KvEntry, KvResource};
use geth_kv::{KvEntry, KvResource, KvSyncEntry};
use geth_pipe::{PipeConnection, PipeListener};
use geth_pubsub::PubsubMessage;
use geth_resource::ResourceDescriptor;
@ -196,6 +196,10 @@ pub enum ControlRequest {
name: String,
key: String,
},
KvSync {
node: String,
name: String,
},
DocumentCreate {
name: String,
},
@ -422,6 +426,16 @@ pub enum ControlResponse {
KvGet {
entry: Option<KvEntry>,
},
KvSynced {
peer_node_id: String,
peer_agent_id: String,
endpoint_id: String,
name: String,
entries_imported: usize,
allowed: bool,
reason: String,
note: String,
},
DocumentCreated {
document: DocumentResource,
},
@ -521,6 +535,12 @@ pub enum PeerControlRequest {
since_ms: i64,
nonce: String,
},
KvSync {
peer_card: PeerCard,
name: String,
since_ms: i64,
nonce: String,
},
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
@ -589,6 +609,20 @@ pub enum PeerControlResponse {
nonce: String,
note: String,
},
KvSynced {
node_id: String,
agent_id: String,
endpoint_id: String,
remote_endpoint_id: String,
name: String,
entries: Vec<KvSyncEntry>,
high_water_ms: i64,
allowed: bool,
reason: String,
evaluated_ops: usize,
nonce: String,
note: String,
},
Error {
message: String,
},
@ -747,6 +781,30 @@ mod tests {
response
);
let request = ControlRequest::KvSync {
node: "node:peer".to_owned(),
name: "prefs".to_owned(),
};
assert_eq!(
decode_request(&encode_request(&request).expect("encode")).expect("decode"),
request
);
let response = ControlResponse::KvSynced {
peer_node_id: "node:peer".to_owned(),
peer_agent_id: "agent:peer".to_owned(),
endpoint_id: "endpoint:peer".to_owned(),
name: "prefs".to_owned(),
entries_imported: 1,
allowed: true,
reason: "direct grant".to_owned(),
note: "kv sync".to_owned(),
};
assert_eq!(
decode_response(&encode_response(&response).expect("encode")).expect("decode"),
response
);
let request = ControlRequest::DocumentSet {
name: "notes".to_owned(),
state_json: r#"{"title":"notes"}"#.to_owned(),
@ -908,5 +966,29 @@ mod tests {
.expect("decode"),
response
);
let response = PeerControlResponse::KvSynced {
node_id: "node:peer".to_owned(),
agent_id: "agent:peer".to_owned(),
endpoint_id: "endpoint:peer".to_owned(),
remote_endpoint_id: "endpoint:caller".to_owned(),
name: "prefs".to_owned(),
entries: vec![KvSyncEntry {
key: "apps/foo/theme".to_owned(),
value: "dark".to_owned(),
updated_at_ms: 42,
}],
high_water_ms: 43,
allowed: true,
reason: "direct grant".to_owned(),
evaluated_ops: 1,
nonce: "nonce".to_owned(),
note: "kv sync".to_owned(),
};
assert_eq!(
decode_peer_response(&encode_peer_response(&response).expect("encode"))
.expect("decode"),
response
);
}
}