Internal State Machine
Statement
Each character in the eg-walker internal state carries two independent state variables:
- Prepare state
- Effect state
The prepare state tracks whether a character is visible in the author's context and handles concurrent deletions via a counter. The effect state tracks the character's status in the cumulative document.
State Transition Diagram
The prepare state follows these transitions:
stateDiagram-v2
[*] --> NotInsertedYet : record created (via apply of concurrent insert)
[*] --> Ins : apply(insert) — own character
NotInsertedYet --> Ins : advance(insert)
Ins --> NotInsertedYet : retreat(insert)
Ins --> Del1 : apply(delete) or advance(delete)
Del1 --> Ins : retreat(delete)
Del1 --> Del2 : apply(delete₂) or advance(delete₂)
Del2 --> Del1 : retreat(delete₂)
Del2 --> Del3 : apply(delete₃) or advance(delete₃)
Del3 --> Del2 : retreat(delete₃)
The effect state is simpler — it only moves forward:
Formal Definitions
Definition (Character Record). A record in the internal state sequence is a tuple:
where is the unique ID of the inserting event.
Invariant 1 (Effect monotonicity). Once , it never returns to .
Invariant 2 (Version containment). The prepare version is always a subset of the effect version:
Invariant 3 (Del counter correctness). iff exactly delete events targeting this character are in the current prepare version.
Transition Rules
| Event type | Operation | transition | transition |
|---|---|---|---|
| Insert | apply | ||
| Insert | retreat | — | |
| Insert | advance | — | |
| Delete | apply | or | |
| Delete | retreat | or | — |
| Delete | advance | or | — |
Why the Del Counter?
When multiple users concurrently delete the same character, the prepare version must track how many of those deletions are currently "active":
After processing both, . Retreating one deletion gives (still deleted), not . Only after retreating both does the character become visible again.
Visualization: Worked Example
Three users concurrently edit the document "ab":
Initial: "ab" (records: [a: Ins/Ins, b: Ins/Ins])
User 1: Delete(0) — deletes 'a'
User 2: Delete(0) — also deletes 'a' (concurrent with User 1)
User 3: Insert(1, 'x') — inserts between 'a' and 'b'
Processing in order (User 1), (User 3), (User 2):
| Step | Action | Record 'a' (/) | Record 'x' (/) | Record 'b' (/) |
|---|---|---|---|---|
| 0 | initial | Ins/Ins | — | Ins/Ins |
| 1 | apply(: Del 'a') | Del₁/Del | — | Ins/Ins |
| 2 | retreat(), apply(: Ins 'x') | Ins/Del | Ins/Ins | Ins/Ins |
| 3 | advance(), apply(: Del 'a') | Del₂/Del | Ins/Ins | Ins/Ins |
Final state: 'a' has , — correctly deleted. The document is "xb".
B-tree Index Structure
Records are stored in a balanced B-tree with augmented counts at each internal node:
This enables operations:
- Find -th visible character in either version: descend the tree using augmented counts
- Translate position between versions: sum counts on the path from leaf to root
- Update on retreat/advance: update ancestor counts
Connections
The state machine is the foundation on which the Advance and Retreat MechanismAdvance and Retreat MechanismHow eg-walker navigates the causal graph by advancing and retreating individual events to simulate each operation's original context.Read more → operates. Its invariants are essential for the Event Graph Convergence ProofEvent Graph Convergence ProofFormal proof that eg-walker produces identical document states regardless of topological sort order — strong eventual consistency.Read more →. The B-tree structure gives eg-walker its per-operation complexity, contributing to the performance advantages over traditional CRDTs described in Eg-walker: Event Graph WalkerEg-walker: Event Graph WalkerA collaboration algorithm for text editing that combines CRDT convergence with OT-competitive memory and merge performance.Read more →.
Referenced by
- Compact Event Graph EncodingDistributed Systems
- Eg-walker: Event Graph WalkerDistributed Systems
- Advance and Retreat MechanismDistributed Systems
- Event Graph Convergence ProofDistributed Systems
- Critical Versions and Partial ReplayDistributed Systems