tablyinc / otto-test

Otto: a unified approach to CRDTs and OT
Apache License 2.0
16 stars 1 forks source link

Investigate otto vs diamond types divergence #8

Open amascolo opened 2 years ago

amascolo commented 2 years ago

We have run diamond types' fuzzing test, comparing otto and diamond types side-by-side.

Otto agents converge to a common state. Diamond types agents converge to a common state.

In some cases, however, this common state isn't the same for otto and diamond types.

Even on unordered document contents – i.e. excluding cases where the changes appear in reverse order.

It would be interesting to see if we can tweak otto's behaviour to match diamond types' exactly.


Test case:

https://github.com/tablyinc/otto-test/blob/a986dd31ba1bf0574b2893f4e1fc5f441e795614/tests/oplog_merge_fuzzer.rs#L196-L199

Raw dump:

i 0
random operations at agent: 0
Operation { loc: RangeRev { span: T 0..1, fwd: true }, kind: Ins, content: Some("a") }
random operations at agent: 2
Operation { loc: RangeRev { span: T 0..1, fwd: true }, kind: Ins, content: Some("a") }
syncing agents: 0 ↔ 2
diamond types (before): a
diamond types (before): a
diamond types (after): aa
otto (before): a
otto (before): a
otto (after): aa

i 1
random operations at agent: 1
Operation { loc: RangeRev { span: T 0..1, fwd: true }, kind: Ins, content: Some("a") }
random operations at agent: 0
Operation { loc: RangeRev { span: T 1..2, fwd: true }, kind: Del, content: Some("a") }
syncing agents: 1 ↔ 2
diamond types (before): a
diamond types (before): aa
diamond types (after): aaa
otto (before): a
otto (before): aa
otto (after): aaa

i 2
random operations at agent: 2
Operation { loc: RangeRev { span: T 0..2, fwd: true }, kind: Del, content: Some("aa") }
random operations at agent: 1
Operation { loc: RangeRev { span: T 2..3, fwd: true }, kind: Del, content: Some("a") }
syncing agents: 0 ↔ 2
diamond types (before): a
diamond types (before): a
diamond types (after): 
otto (before): a
otto (before): a
otto (after): a

Diagrams showing otto's behaviour:

┌────0────┐    ┌────1────┐    ┌────2────┐
└────∅────┘    └────∅────┘    └────∅────┘

random operations at agent: 0

┌────0────┐    ┌────1────┐    ┌────2────┐
│ 0 ins a │    └────∅────┘    └────∅────┘
└────a────┘

random operations at agent: 2

┌────0────┐    ┌────1────┐    ┌────2────┐
│ 0 ins a │    └────∅────┘    │ 2 ins a │
└────a────┘                   └────a────┘

syncing agents: 0 ↔ 2

     ┌ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┐
     |                             ▼
┌────0────┐    ┌────1────┐    ┌────2────┐
│ 0 ins a │    └────∅────┘    │ 2 ins a │
│ 2 ins a │                   │ 0 ins a │
└────aa───┘                   └────aa───┘
     ▲                             |
     └ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┘

random operations at agent: 1

┌────0────┐    ┌────1────┐    ┌────2────┐
│ 0 ins a │    │ 1 ins a │    │ 2 ins a │
│ 2 ins a │    └────a────┘    │ 0 ins a │
└────aa───┘                   └────aa───┘

random operations at agent: 0

┌────0────┐    ┌────1────┐    ┌────2────┐
│ 0 ins a │    │ 1 ins a │    │ 2 ins a │
│ 2 ins a │    └────a────┘    │ 0 ins a │
│ 0 del a │                   └────aa───┘
└────a────┘

syncing agents: 1 ↔ 2

                    ┌ ─ ─ ─ ─ ─ ─ ─┐
                    |              ▼
┌────0────┐    ┌────1────┐    ┌────2────┐
│ 0 ins a │    │ 1 ins a │    │ 2 ins a │
│ 2 ins a │    │ 2 ins a │    │ 0 ins a │
│ 0 del a │    │ 0 ins a │    │ 1 ins a │
└────a────┘    └───aaa───┘    └───aaa───┘
                    ▲              |
                    └─ ─ ─ ─ ─ ─ ─ ┘

random operations at agent: 2

┌────0────┐    ┌────1────┐    ┌────2────┐
│ 0 ins a │    │ 1 ins a │    │ 2 ins a │
│ 2 ins a │    │ 2 ins a │    │ 0 ins a │
│ 0 del a │    │ 0 ins a │    │ 1 ins a │
└────a────┘    └───aaa───┘    │ 2 del aa│
                              └────a────┘

random operations at agent: 1

┌────0────┐    ┌────1────┐    ┌────2────┐
│ 0 ins a │    │ 1 ins a │    │ 2 ins a │
│ 2 ins a │    │ 2 ins a │    │ 0 ins a │
│ 0 del a │    │ 0 ins a │    │ 1 ins a │
└────a────┘    │ 1 del a │    │ 2 del aa│
               └────aa───┘    └────a────┘

syncing agents: 0 ↔ 2

     ┌ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┐
     |                             ▼
┌────0────┐    ┌────1────┐    ┌────2────┐
│ 0 ins a │    │ 1 ins a │    │ 2 ins a │
│ 2 ins a │    │ 2 ins a │    │ 0 ins a │
│ 0 del a │    │ 0 ins a │    │ 1 ins a │
│ 1 ins a │    │ 1 del a │    │ 2 del aa│
│ 2 del aa│    └────aa───┘    │ 0 del a │
└────∅────┘                   └────∅────┘
     ▲                             |
     └ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┘
amascolo commented 2 years ago

Experimented with assigning each instruction a unique ID, but no change in behaviour https://github.com/tablyinc/otto-test/compare/main%40%7Bac7c412%7D...unique-ids