Skip to content

Commit 8e4dcdc

Browse files
committed
feat: make client id conflict behavior same as yjs
1 parent a9ae042 commit 8e4dcdc

File tree

4 files changed

+20
-5
lines changed

4 files changed

+20
-5
lines changed

y-octo-node/native/src/doc.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,8 +114,17 @@ impl YDoc {
114114

115115
#[napi]
116116
pub fn apply_update(&mut self, update: JsBuffer) -> Result<()> {
117+
let client = self.doc.client();
118+
let before_current_state = self.doc.get_state_vector().get(&client);
119+
117120
self.doc.apply_update_from_binary_v1(update)?;
118121

122+
// if update received from remote and current client state has been changed
123+
// that means another client using same client id, we need to change the client id to avoid conflict
124+
if self.doc.get_state_vector().get(&client) != before_current_state {
125+
self.doc.renew_client();
126+
}
127+
119128
Ok(())
120129
}
121130

y-octo-node/tests/doc.spec.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,9 @@ test("y-octo doc update should be apply", (t) => {
4444
let map2 = doc2.getOrCreateMap("map");
4545
let text2 = doc2.getOrCreateText("text");
4646

47-
t.is(doc2.clientId, client_id);
47+
// after apply update that include same client id's change
48+
// the client id should be changed
49+
t.not(doc2.clientId, client_id);
4850
t.is(array2.length, 4);
4951
t.is(array2.get(0), true);
5052
t.is(array2.get(1), false);

y-octo-node/tests/yjs/doc.spec.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,13 +41,13 @@ test.skip("testOriginInTransaction", (t) => {
4141
/**
4242
* Client id should be changed when an instance receives updates from another client using the same client id.
4343
*/
44-
test.skip("testClientIdDuplicateChange", (t) => {
44+
test("testClientIdDuplicateChange", (t) => {
4545
const doc1 = new Y.Doc(0);
4646
const doc2 = new Y.Doc(0);
47-
t.assert(doc2.clientID === doc1.clientID);
47+
t.assert(doc2.clientId === doc1.clientId);
4848
doc1.getArray("a").insert(0, [1, 2]);
49-
Y.applyUpdate(doc2, Y.encodeStateAsUpdate(doc1));
50-
t.assert(doc2.clientID !== doc1.clientID);
49+
Y.applyUpdate(doc2, Y.encodeStateAsUpdate(doc1), false);
50+
t.assert(doc2.clientId !== doc1.clientId);
5151
});
5252

5353
test.skip("testGetTypeEmptyId", (t) => {

y-octo/src/doc/document.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,10 @@ impl Doc {
162162
self.client_id = client_id;
163163
}
164164

165+
pub fn renew_client(&mut self) {
166+
self.client_id = prefer_small_random();
167+
}
168+
165169
pub fn clients(&self) -> Vec<u64> {
166170
self.store.read().unwrap().clients()
167171
}

0 commit comments

Comments
 (0)