yorkie-team/yorkie

Document doesn't converge when using `Array.MoveAfter`

chacha912 opened this issue · 0 comments

What happened:

When using moveAfter with the reference element being moved, the document does not converge as expected.

image

What you expected to happen:

The document should converge to [2,1,3,4,0].

How to reproduce it (as minimally and precisely as possible):

Execute the following test code in the yorkie-js-sdk:

it('Can handle concurrent moveAfter', async function ({ task }) {
  type TestDoc = { k1: JSONArray<number> };
  await withTwoClientsAndDocuments<TestDoc>(async (c1, d1, c2, d2) => {
    d1.update((root) => {
      root.k1 = [0, 1, 2, 3, 4];
      assert.equal('{"k1":[0,1,2,3,4]}', root.toJSON!());
    });
    await c1.sync();
    await c2.sync();
    assert.equal(d1.toJSON!(), d2.toJSON!());

    d1.update((root) => {
      const prev = root.k1.getElementByIndex!(0);
      const item = root.k1.getElementByIndex!(2);
      root.k1.moveAfter!(prev.getID!(), item.getID!());
      assert.equal('{"k1":[0,2,1,3,4]}', root.toJSON!());
    });

    d2.update((root) => {
      const prev = root.k1.getElementByIndex!(4);
      const item = root.k1.getElementByIndex!(0);
      root.k1.moveAfter!(prev.getID!(), item.getID!());
      assert.equal('{"k1":[1,2,3,4,0]}', root.toJSON!());
    });

    await c1.sync();
    await c2.sync();
    await c1.sync();
    // d1 /= d2 
    assert.equal(d1.toSortedJSON(), `{"k1":[2,1,3,4,0]}`);
    assert.equal(d2.toSortedJSON(), `{"k1":[1,3,4,0,2]}`);
  }, task.name);
});

Anything else we need to know?:

In cases where the same node is moved or when elements are moved to the same position, the operation is commutative by comparing movedAt and executedAt. However, when the reference element is moved, a different approach may be necessary for convergence. (Refer to: Why a move operation is hard)

Environment:

  • Operating system:
  • Browser and version:
  • Yorkie version (use yorkie version): v0.4.8
  • Yorkie JS SDK version: v0.4.8