docs: define sync conflict semantics
This commit is contained in:
parent
02969ac7af
commit
24a0a3d153
5 changed files with 186 additions and 14 deletions
|
|
@ -1943,9 +1943,13 @@ async fn kv_sync_from_peer(
|
|||
for entry in entries {
|
||||
geth_kv::validate_kv_key(&entry.key)
|
||||
.map_err(|_| NodeError::InvalidKvKey(entry.key.clone()))?;
|
||||
let should_import = store
|
||||
.get_kv_entry(&kv.kv_id, &entry.key)?
|
||||
.is_none_or(|local| entry.updated_at_ms >= local.updated_at_ms);
|
||||
let should_import = should_import_kv_sync_entry(
|
||||
store
|
||||
.get_kv_entry(&kv.kv_id, &entry.key)?
|
||||
.as_ref()
|
||||
.map(|local| local.updated_at_ms),
|
||||
entry.updated_at_ms,
|
||||
);
|
||||
if should_import {
|
||||
store.set_kv_entry(&StoredKvEntry {
|
||||
kv_id: kv.kv_id.clone(),
|
||||
|
|
@ -3229,12 +3233,12 @@ async fn document_sync_from_peer(
|
|||
let mut updated = false;
|
||||
if let Some(state) = state {
|
||||
let local = ensure_local_document(&store, name)?;
|
||||
if state.updated_at.0 >= local.updated_at_ms {
|
||||
let state_json = if state.updated_at.0 > local.updated_at_ms {
|
||||
state.state_json
|
||||
} else {
|
||||
geth_document::merge_automerge_states(&local.state_json, &state.state_json)?
|
||||
};
|
||||
if let Some(state_json) = document_sync_state_json(
|
||||
&local.state_json,
|
||||
local.updated_at_ms,
|
||||
&state.state_json,
|
||||
state.updated_at.0,
|
||||
)? {
|
||||
store.insert_document_resource(&StoredDocumentResource {
|
||||
document_id: local.document_id,
|
||||
resource_id: local.resource_id,
|
||||
|
|
@ -3267,6 +3271,32 @@ async fn document_sync_from_peer(
|
|||
}
|
||||
}
|
||||
|
||||
fn should_import_kv_sync_entry(
|
||||
local_updated_at_ms: Option<i64>,
|
||||
remote_updated_at_ms: i64,
|
||||
) -> bool {
|
||||
local_updated_at_ms
|
||||
.is_none_or(|local_updated_at_ms| remote_updated_at_ms >= local_updated_at_ms)
|
||||
}
|
||||
|
||||
fn document_sync_state_json(
|
||||
local_state_json: &str,
|
||||
local_updated_at_ms: i64,
|
||||
remote_state_json: &str,
|
||||
remote_updated_at_ms: i64,
|
||||
) -> Result<Option<String>, NodeError> {
|
||||
if remote_updated_at_ms < local_updated_at_ms {
|
||||
return Ok(None);
|
||||
}
|
||||
if remote_updated_at_ms > local_updated_at_ms {
|
||||
return Ok(Some(remote_state_json.to_owned()));
|
||||
}
|
||||
Ok(Some(geth_document::merge_automerge_states(
|
||||
local_state_json,
|
||||
remote_state_json,
|
||||
)?))
|
||||
}
|
||||
|
||||
async fn sync_status_from_peer(
|
||||
node: &LocalNode,
|
||||
peer_node: &str,
|
||||
|
|
@ -11392,6 +11422,40 @@ mod tests {
|
|||
std::env::var_os("GETH_TEST_SKIP_IROH").is_some()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn kv_sync_import_rule_is_timestamp_last_writer_wins() {
|
||||
assert!(should_import_kv_sync_entry(None, 10));
|
||||
assert!(!should_import_kv_sync_entry(Some(11), 10));
|
||||
assert!(should_import_kv_sync_entry(Some(10), 10));
|
||||
assert!(should_import_kv_sync_entry(Some(9), 10));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn document_sync_rule_merges_equal_timestamps_only() {
|
||||
let older =
|
||||
document_sync_state_json(r#"{"title":"local"}"#, 20, r#"{"title":"remote"}"#, 19)
|
||||
.expect("older remote");
|
||||
assert_eq!(older, None);
|
||||
|
||||
let newer =
|
||||
document_sync_state_json(r#"{"title":"local"}"#, 20, r#"{"title":"remote"}"#, 21)
|
||||
.expect("newer remote");
|
||||
assert_eq!(newer.as_deref(), Some(r#"{"title":"remote"}"#));
|
||||
|
||||
let local_state =
|
||||
geth_document::create_automerge_state(r#"{"local":true}"#).expect("local envelope");
|
||||
let remote_state =
|
||||
geth_document::create_automerge_state(r#"{"remote":true}"#).expect("remote envelope");
|
||||
let equal = document_sync_state_json(&local_state, 20, &remote_state, 20)
|
||||
.expect("equal timestamp merge")
|
||||
.expect("merged state");
|
||||
let merged: serde_json::Value =
|
||||
serde_json::from_str(&geth_document::document_view_json(&equal).expect("view json"))
|
||||
.expect("merged json");
|
||||
assert_eq!(merged["local"], true);
|
||||
assert_eq!(merged["remote"], true);
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
enum RemoteGuardKind {
|
||||
Capability,
|
||||
|
|
|
|||
Loading…
Reference in a new issue