Skip to content

Commit

Permalink
feat: make client id conflict behavior same as yjs
Browse files Browse the repository at this point in the history
  • Loading branch information
darkskygit committed Sep 12, 2024
1 parent a9ae042 commit 8e4dcdc
Show file tree
Hide file tree
Showing 4 changed files with 20 additions and 5 deletions.
9 changes: 9 additions & 0 deletions y-octo-node/native/src/doc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -114,8 +114,17 @@ impl YDoc {

#[napi]
pub fn apply_update(&mut self, update: JsBuffer) -> Result<()> {
let client = self.doc.client();
let before_current_state = self.doc.get_state_vector().get(&client);

self.doc.apply_update_from_binary_v1(update)?;

// if update received from remote and current client state has been changed
// that means another client using same client id, we need to change the client id to avoid conflict
if self.doc.get_state_vector().get(&client) != before_current_state {
self.doc.renew_client();
}

Ok(())
}

Expand Down
4 changes: 3 additions & 1 deletion y-octo-node/tests/doc.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,9 @@ test("y-octo doc update should be apply", (t) => {
let map2 = doc2.getOrCreateMap("map");
let text2 = doc2.getOrCreateText("text");

t.is(doc2.clientId, client_id);
// after apply update that include same client id's change
// the client id should be changed
t.not(doc2.clientId, client_id);
t.is(array2.length, 4);
t.is(array2.get(0), true);
t.is(array2.get(1), false);
Expand Down
8 changes: 4 additions & 4 deletions y-octo-node/tests/yjs/doc.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,13 +41,13 @@ test.skip("testOriginInTransaction", (t) => {
/**
* Client id should be changed when an instance receives updates from another client using the same client id.
*/
test.skip("testClientIdDuplicateChange", (t) => {
test("testClientIdDuplicateChange", (t) => {
const doc1 = new Y.Doc(0);
const doc2 = new Y.Doc(0);
t.assert(doc2.clientID === doc1.clientID);
t.assert(doc2.clientId === doc1.clientId);
doc1.getArray("a").insert(0, [1, 2]);
Y.applyUpdate(doc2, Y.encodeStateAsUpdate(doc1));
t.assert(doc2.clientID !== doc1.clientID);
Y.applyUpdate(doc2, Y.encodeStateAsUpdate(doc1), false);
t.assert(doc2.clientId !== doc1.clientId);
});

test.skip("testGetTypeEmptyId", (t) => {
Expand Down
4 changes: 4 additions & 0 deletions y-octo/src/doc/document.rs
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,10 @@ impl Doc {
self.client_id = client_id;
}

pub fn renew_client(&mut self) {
self.client_id = prefer_small_random();
}

pub fn clients(&self) -> Vec<u64> {
self.store.read().unwrap().clients()
}
Expand Down

0 comments on commit 8e4dcdc

Please sign in to comment.