How to apply multiple updates on yDoc and get the correct result

Hi all helpers,
the following code produce the require result:

  const serverUpdates = [];
  yDoc.on('update', (update, origin, c) => {
    serverUpdates.splice(serverUpdates.length, 0, update);
  });
  const yText = yDoc.getText('textBlock');
  yText.applyDelta([{ insert: 'r' }]);
  yText.applyDelta([{ insert: 'o' }]);
  yText.applyDelta([{ insert: 'n' }]);
  yText.applyDelta([{ insert: 'e' }]);
  yText.applyDelta([{ insert: 'n' }]);

  const yDoc1 = new YJS.Doc();
  YJS.applyUpdate(yDoc1, serverUpdates[0]);
  const update1 = YJS.encodeStateAsUpdate(yDoc1);

  const yDoc2 = new YJS.Doc();
  YJS.applyUpdate(yDoc2, update1);
  YJS.applyUpdate(yDoc2, serverUpdates[1]);
  const update2 = YJS.encodeStateAsUpdate(yDoc2);

  const yDoc3 = new YJS.Doc();
  YJS.applyUpdate(yDoc3, update2);
  YJS.applyUpdate(yDoc3, serverUpdates[2]);
  const update3 = YJS.encodeStateAsUpdate(yDoc3);

  const yDoc4 = new YJS.Doc();
  YJS.applyUpdate(yDoc4, update3);
  YJS.applyUpdate(yDoc4, serverUpdates[3]);
  const update4 = YJS.encodeStateAsUpdate(yDoc4);

  const yDoc5 = new YJS.Doc();
  YJS.applyUpdate(yDoc5, update4);
  YJS.applyUpdate(yDoc5, serverUpdates[4]);
  const update5 = YJS.encodeStateAsUpdate(yDoc5);

  const yText5 = yDoc5.getText('textBlock');
  console.log('ronen calculate  ', yText5.toDelta());

while this now is produce result that cut in the middle

const yDoc = new YJS.Doc();
  const serverUpdates = [];
  yDoc.on('update', (update, origin, c) => {
    serverUpdates.splice(serverUpdates.length, 0, update);
  });
  const yText = yDoc.getText('textBlock');
  yText.applyDelta([{ insert: 'r' }]);
  yText.applyDelta([{ insert: 'o' }]);
  yText.applyDelta([{ insert: 'n' }]);
  yText.applyDelta([{ insert: 'e' }]);
  yText.applyDelta([{ insert: 'n' }]);

  const yDoc1 = new YJS.Doc();
  YJS.applyUpdate(yDoc1, serverUpdates[0]);
  const update1 = YJS.encodeStateAsUpdate(yDoc1);

  const yDoc2 = new YJS.Doc();
  YJS.applyUpdate(yDoc2, update1);
  YJS.applyUpdate(yDoc2, serverUpdates[1]);
  const update2 = YJS.encodeStateAsUpdate(yDoc2);

  const yDoc3 = new YJS.Doc();
  YJS.applyUpdate(yDoc3, update2);
  YJS.applyUpdate(yDoc3, serverUpdates[3]);
  const update3 = YJS.encodeStateAsUpdate(yDoc3);

  const yDoc4 = new YJS.Doc();
  YJS.applyUpdate(yDoc4, update3);
  YJS.applyUpdate(yDoc4, serverUpdates[2]);
  const update4 = YJS.encodeStateAsUpdate(yDoc4);

  const yDoc5 = new YJS.Doc();
  YJS.applyUpdate(yDoc5, update4);
  YJS.applyUpdate(yDoc5, serverUpdates[4]);
  const update5 = YJS.encodeStateAsUpdate(yDoc5);

  const yText5 = yDoc5.getText('textBlock');
  console.log('ronen calculate  ', yText5.toDelta());

what do I miss here???

the problem was we missed the pending structure in encodeStateAsUpdate but in encodeStateAsUpdateV2 it’s working well so the following code is working well

const yDoc = new YJS.Doc();
  const serverUpdates = [];
  yDoc.on('update', (update, origin, c) => {
    serverUpdates.splice(serverUpdates.length, 0, update);
  });
  const yText = yDoc.getText('textBlock');
  yText.applyDelta([{ insert: 'r' }]);
  yText.applyDelta([{ insert: 'o' }]);
  yText.applyDelta([{ insert: 'n' }]);
  yText.applyDelta([{ insert: 'e' }]);
  yText.applyDelta([{ insert: 'n' }]);

  const yDoc1 = new YJS.Doc();
  YJS.applyUpdate(yDoc1, serverUpdates[0]);
  const update1 = YJS.encodeStateAsUpdateV2(yDoc1);

  const yDoc2 = new YJS.Doc();
  YJS.applyUpdateV2(yDoc2, update1);
  YJS.applyUpdate(yDoc2, serverUpdates[1]);
  const update2 = YJS.encodeStateAsUpdateV2(yDoc2);

  const yDoc3 = new YJS.Doc();
  YJS.applyUpdateV2(yDoc3, update2);
  YJS.applyUpdate(yDoc3, serverUpdates[3]);
  const update3 = YJS.encodeStateAsUpdateV2(yDoc3);

  const yDoc4 = new YJS.Doc();
  YJS.applyUpdateV2(yDoc4, update3);
  YJS.applyUpdate(yDoc4, serverUpdates[2]);
  const update4 = YJS.encodeStateAsUpdateV2(yDoc4);

  const yDoc5 = new YJS.Doc();
  YJS.applyUpdateV2(yDoc5, update4);
  YJS.applyUpdate(yDoc5, serverUpdates[4]);
  const update5 = YJS.encodeStateAsUpdateV2(yDoc5);

  const yText5 = yDoc5.getText('textBlock');
  console.log('ronen calculate  ', yText5.toDelta());

Hi @SabagRonen,

I spent two days finding the bug. I’m very glad you shared it because it caught a problem that is hard to reproduce with the current testing suite.

I fixed the issue that you are describing in Yjs@13.5.11. Could you please confirm that it is fixed?

1 Like

thank a lot @dmonad your fix is working well, we almost started to migrate our data from regular encodeStateAsUpdate format to encodeStateAsUpdateV2 format which is breaking change, meaning that if I have used encodeStateAsUpdateV2 I must use applyUpdateV2, this will remain breaking change?