THIS IS WHERE CRDTS GET REALLY CLEVER!
The problem with deletions:
State: ABCD
User A inserts X at position 2: ABXCD
User B deletes position 3 (which was C)
What position does B delete now?
Solution: Tombstones!
Interface TextOp has: id, character, afterId, deleted (boolean tombstone!), timestamp, userId.
class CRDTDocument:
ops is a Map of string to TextOp.
applyOp(op): adds op to the map.
deleteOp(opId): finds the op and sets deleted equals true (MARK AS DELETED).
render(): filters out deleted ops (SKIP TOMBSTONES), sorts by afterId references, joins characters.
How it handles our conflict:
Initial: ABCD equals opA, opB, opC, opD
A inserts X after B: opA, opB, opX, opC, opD equals ABXCD
B deletes C: opC.deleted equals true
Final: opA, opB, opX, opD equals ABXD
The beauty: Everyone sees the same final state, no position-based conflicts, deleted items stay in the structure (as tombstones), convergence is guaranteed!
Tradeoff: More memory (tombstones accumulate). Solution: Periodic compaction (when no one is editing).
Want to implement the full collaboration server?