yjs / yjs

Shared data types for building collaborative software
https://docs.yjs.dev
Other
16.55k stars 593 forks source link

encodeStateAsUpdate(doc1, vectorOfDoc2) don't return empty update between 2 equal docs #374

Closed evilfant closed 2 years ago

evilfant commented 2 years ago

Describe the bug To Reproduce

  1. If create doc and make next changes with it's yText
const doc1 = new Doc();
const yText1 = doc1.getText('code');

yText1.insert(0, 'a');
yText1.delete(0, 1);
yText1.insert(0, 'b');
  1. Then create identical doc
const doc2 = new Doc();
applyUpdate(doc2, encodeStateAsUpdate(doc1));
  1. After that take vector of the first doc and calc diff between identical docs. Calculated update won't be empty It will have a DeleteItem
const vector1 = encodeStateVector(doc1);

const diff1 = encodeStateAsUpdate(doc2, vector1);

// not empty update, but it should
logUpdate(diff1);
/*
Structs:  []
DeleteSet:  DeleteSet { clients: Map { 1241621181 => [ [DeleteItem] ] } }
*/

codesandbox1 It works fine if remove the line yText1.delete(0, 1);

It also reproduces with only one doc codesandbox2

Expected behavior Update should contains an empty DeleteSet

Environment Information

Huly®: YJS-275

mlajtos commented 2 years ago

Deletes are not tracked by state vectors, hence clients always exchange all deletes with each other. This is encoded very efficiently and it does not make sense to optimize this further. Not tracking this kind of information (we don't have to assign a lamport timestamp to each delete operation) also allows us to do further compressing of the data. The advantage is that we have a much smaller initial load. The disadvantage is that we always have a small load of deletes even when we are fully synced.

Source: https://github.com/yjs/yjs/issues/346#issuecomment-963955415

dmonad commented 2 years ago

Thank you @mlajtos!

Closing this issue.