@sovereignbase/sequencer 0.0.2 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/INTERNALS.md ADDED
@@ -0,0 +1,897 @@
1
+ # How sequencer works
2
+
3
+ Sequencer keeps an ordered sequence synchronized between replicas.
4
+
5
+ Applications see a normal indexed sequence:
6
+
7
+ ```text
8
+ A B C D
9
+ ```
10
+
11
+ with positions:
12
+
13
+ ```text
14
+ 0 1 2 3
15
+ ```
16
+
17
+ Internally Sequencer cannot use those positions to describe replicated edits.
18
+
19
+ If another Frame is inserted before `B`:
20
+
21
+ ```text
22
+ A X B C D
23
+ ```
24
+
25
+ `B` moves from position `1` to position `2`.
26
+
27
+ Instead, when an edit is made, Sequencer finds the existing history around that position and records the edit relative to it.
28
+
29
+ ## Projection and Structural Order
30
+
31
+ The **Projection** is the sequence the application currently sees.
32
+
33
+ For example:
34
+
35
+ ```text
36
+ A B C D
37
+ ```
38
+
39
+ has four visible Frames:
40
+
41
+ ```text
42
+ A B C D
43
+ 0 1 2 3
44
+ ```
45
+
46
+ Insertion positions are boundaries between Frames:
47
+
48
+ ```text
49
+ | A | B | C | D |
50
+ 0 1 2 3 4
51
+ ```
52
+
53
+ Behind the Projection is **Structural Order**.
54
+
55
+ Structural Order contains the Insertions that produced the sequence, including history that may no longer be visible.
56
+
57
+ A simple sequence might start as:
58
+
59
+ ```text
60
+ Structural Order
61
+
62
+ [A B C D]
63
+
64
+ Projection
65
+
66
+ A B C D
67
+ ```
68
+
69
+ After `B C` are removed, the Projection becomes:
70
+
71
+ ```text
72
+ A D
73
+ ```
74
+
75
+ but Structural Order still contains the original positive Insertion and the history describing the removal.
76
+
77
+ More history can later attach to those original coordinates, so hidden history may remain useful long after its Frames disappear from the Projection.
78
+
79
+ ## Insertions
80
+
81
+ History is made of **Insertions**.
82
+
83
+ An Insertion has six coordinates:
84
+
85
+ ```text
86
+ anchorSession
87
+ anchorStart
88
+ anchorDiff
89
+
90
+ insertionSession
91
+ insertionStart
92
+ insertionDiff
93
+ ```
94
+
95
+ The first three describe where the Insertion belongs:
96
+
97
+ ```text
98
+ (anchorSession, anchorStart, anchorDiff)
99
+ ```
100
+
101
+ The next two identify the Insertion:
102
+
103
+ ```text
104
+ (insertionSession, insertionStart)
105
+ ```
106
+
107
+ and `insertionDiff` describes its original Frame length and whether it adds or removes Frames.
108
+
109
+ A positive Insertion adds Frames:
110
+
111
+ ```text
112
+ insertionDiff = 4
113
+ ```
114
+
115
+ A reducing Insertion masks Frames:
116
+
117
+ ```text
118
+ insertionDiff = -4
119
+ ```
120
+
121
+ Positive Insertions can also carry **Footage**, which contains the actual values.
122
+
123
+ Sequencer orders the Insertion. Footage is what eventually appears in the Projection.
124
+
125
+ ## Frames and logical points
126
+
127
+ Suppose one Insertion contains:
128
+
129
+ ```text
130
+ A B C
131
+ ```
132
+
133
+ It has three Frames:
134
+
135
+ ```text
136
+ A B C
137
+ 0 1 2
138
+ ```
139
+
140
+ and four logical points:
141
+
142
+ ```text
143
+ | A | B | C |
144
+ 0 1 2 3
145
+ ```
146
+
147
+ An anchor points to one of these boundaries.
148
+
149
+ For example:
150
+
151
+ ```text
152
+ anchorDiff = 2
153
+ ```
154
+
155
+ refers to:
156
+
157
+ ```text
158
+ A B | C
159
+ ```
160
+
161
+ inside that original Insertion.
162
+
163
+ If later edits move `C` somewhere else in the Projection, this point is still point `2` of the same original Insertion.
164
+
165
+ ## Anchoring an edit
166
+
167
+ Suppose the Projection contains:
168
+
169
+ ```text
170
+ Hello world
171
+ ```
172
+
173
+ and `big ` is inserted here:
174
+
175
+ ```text
176
+ Hello | world
177
+ ```
178
+
179
+ Sequencer first finds which original Insertion owns that boundary.
180
+
181
+ If the boundary is point `6` of an Insertion identified by:
182
+
183
+ ```text
184
+ (session 4, start 20)
185
+ ```
186
+
187
+ the new Insertion can anchor to:
188
+
189
+ ```text
190
+ anchorSession = 4
191
+ anchorStart = 20
192
+ anchorDiff = 6
193
+ ```
194
+
195
+ Another replica might currently see:
196
+
197
+ ```text
198
+ Well, Hello world
199
+ ```
200
+
201
+ The same anchor still refers to the point after `Hello ` in the original Insertion.
202
+
203
+ The Projection position is different, but the relationship is the same.
204
+
205
+ ## Insertion identity
206
+
207
+ An Insertion is identified by:
208
+
209
+ ```text
210
+ (insertionSession, insertionStart)
211
+ ```
212
+
213
+ The anchor is not part of its identity.
214
+
215
+ If the same Insertion arrives twice, both copies have the same identity.
216
+
217
+ Sequencer can keep the first and ignore the duplicate instead of inserting the same content twice.
218
+
219
+ Fragments of an Insertion also keep this identity. Splitting an Insertion at runtime does not create new replicated history.
220
+
221
+ ## Sessions
222
+
223
+ Insertions are authored inside **Sessions**.
224
+
225
+ A Session has its own logical time.
226
+
227
+ Suppose a Session creates a three-Frame Insertion starting at `0`.
228
+
229
+ Its Frame coordinates occupy:
230
+
231
+ ```text
232
+ 0 1 2
233
+ ```
234
+
235
+ and its endpoint is:
236
+
237
+ ```text
238
+ 3
239
+ ```
240
+
241
+ A new independent Insertion normally starts after another reserved logical point:
242
+
243
+ ```text
244
+ 0 1 2 | 3
245
+ ↑
246
+ boundary
247
+
248
+ next start = 4
249
+ ```
250
+
251
+ The gap gives the previous Insertion its own endpoint without making that endpoint the identity of the next independent Insertion.
252
+
253
+ Positive and reducing history use separate Sessions.
254
+
255
+ Session identifiers are also separate from Actor identifiers. Two replicas belonging to the same Actor can author their own Sessions without sharing one sequencing clock.
256
+
257
+ ## Structural Order
258
+
259
+ Every materialized Insertion is placed into one Structural Order.
260
+
261
+ Suppose the original history is:
262
+
263
+ ```text
264
+ A B
265
+ ```
266
+
267
+ and a new Insertion anchors between them:
268
+
269
+ ```text
270
+ A | B
271
+ ```
272
+
273
+ Structural Order can now represent:
274
+
275
+ ```text
276
+ A X B
277
+ ```
278
+
279
+ If another replica concurrently inserts `Y` at the same anchor, both new Insertions describe the same historical point:
280
+
281
+ ```text
282
+ A | B
283
+ X
284
+ Y
285
+ ```
286
+
287
+ They must get the same order on every replica even when they arrive in different orders.
288
+
289
+ Sequencer orders competing Insertions from the anchor outward by:
290
+
291
+ 1. positive Insertions before reducing Insertions;
292
+ 2. greater Session first;
293
+ 3. within the same Session, greater start first.
294
+
295
+ So receiving:
296
+
297
+ ```text
298
+ X
299
+ Y
300
+ ```
301
+
302
+ or:
303
+
304
+ ```text
305
+ Y
306
+ X
307
+ ```
308
+
309
+ produces the same Structural Order once both are known.
310
+
311
+ ## Causal subtrees
312
+
313
+ An Insertion can have more history attached to it.
314
+
315
+ Suppose two replicas start from an empty sequence.
316
+
317
+ One creates:
318
+
319
+ ```text
320
+ Project notes
321
+ ```
322
+
323
+ and continues editing it.
324
+
325
+ The other independently creates:
326
+
327
+ ```text
328
+ Shopping list
329
+ ```
330
+
331
+ and continues editing that.
332
+
333
+ The two initial Insertions compete at the root.
334
+
335
+ Their later edits are descendants of those roots:
336
+
337
+ ```text
338
+ Project notes
339
+ ├─ child
340
+ └─ child
341
+
342
+ Shopping list
343
+ ├─ child
344
+ └─ child
345
+ ```
346
+
347
+ When the roots are ordered, their descendants stay with them:
348
+
349
+ ```text
350
+ [Project notes subtree]
351
+ [Shopping list subtree]
352
+ ```
353
+
354
+ rather than becoming interleaved:
355
+
356
+ ```text
357
+ part of Project notes
358
+ part of Shopping list
359
+ rest of Project notes
360
+ rest of Shopping list
361
+ ```
362
+
363
+ When a competitor is inserted into Structural Order, its place is determined relative to the complete subtree of the competitors already there.
364
+
365
+ ## History can arrive before its parent
366
+
367
+ Suppose one replica creates:
368
+
369
+ ```text
370
+ Hello
371
+ ```
372
+
373
+ and then inserts:
374
+
375
+ ```text
376
+ world
377
+ ```
378
+
379
+ after it.
380
+
381
+ The second Insertion anchors to the first.
382
+
383
+ Another replica may receive:
384
+
385
+ ```text
386
+ world
387
+ ```
388
+
389
+ before:
390
+
391
+ ```text
392
+ Hello
393
+ ```
394
+
395
+ There is not yet anything local that can resolve the anchor.
396
+
397
+ The Insertion waits.
398
+
399
+ When `Hello` arrives, its identity becomes available and the waiting Insertion can be placed:
400
+
401
+ ```text
402
+ Hello world
403
+ ```
404
+
405
+ The same thing can happen when the parent exists but has not yet grown far enough to contain the referenced logical point.
406
+
407
+ The relationship itself does not change while it waits.
408
+
409
+ ## Author-time relationships
410
+
411
+ This allows edits to describe the sequence as it existed when they were authored without requiring another replica to pass through the same intermediate states.
412
+
413
+ For example, one replica may produce:
414
+
415
+ ```text
416
+ world
417
+ Hello world
418
+ Well, Hello world
419
+ Well, actually Hello world
420
+ Now, Well, actually Hello world
421
+ Okay, Now, Well, actually Hello world
422
+ ```
423
+
424
+ Another replica might receive the Insertions in this order:
425
+
426
+ ```text
427
+ world
428
+ Hello
429
+ actually
430
+ Now
431
+ Well
432
+ Okay
433
+ ```
434
+
435
+ `actually` is still attached to the historical Insertion it followed when it was authored.
436
+
437
+ Once the required history has arrived, the relationships can be resolved into:
438
+
439
+ ```text
440
+ Okay, Now, Well, actually Hello world
441
+ ```
442
+
443
+ ## Strips
444
+
445
+ An Insertion does not always stay in one piece inside a running Projection.
446
+
447
+ Suppose an original Insertion contains:
448
+
449
+ ```text
450
+ A B C D
451
+ ```
452
+
453
+ An edit at the middle may split its runtime representation into:
454
+
455
+ ```text
456
+ [A B] [C D]
457
+ ```
458
+
459
+ These pieces are **Strips**.
460
+
461
+ Both Strips still belong to the same original Insertion.
462
+
463
+ The original coordinate space is still:
464
+
465
+ ```text
466
+ | A | B | C | D |
467
+ 0 1 2 3 4
468
+ ```
469
+
470
+ The left Strip represents one part of that space and the right Strip represents another.
471
+
472
+ An operation authored earlier against point `3` can still find point `3` even though the original Insertion is no longer represented by one Strip.
473
+
474
+ Different replicas can also have different fragmentation.
475
+
476
+ One might currently have:
477
+
478
+ ```text
479
+ [A B C D]
480
+ ```
481
+
482
+ while another has:
483
+
484
+ ```text
485
+ [A] [B C] [D]
486
+ ```
487
+
488
+ They still agree on the original Insertion and its coordinates.
489
+
490
+ ## Extending an Insertion
491
+
492
+ Consecutive editing often continues the Insertion that was just created.
493
+
494
+ Typing:
495
+
496
+ ```text
497
+ H
498
+ He
499
+ Hel
500
+ Hell
501
+ Hello
502
+ ```
503
+
504
+ does not need five unrelated canonical Insertions.
505
+
506
+ When the new content is a clean continuation of the latest local positive Insertion, its original extent can grow:
507
+
508
+ ```text
509
+ H
510
+ ↓
511
+ He
512
+ ↓
513
+ Hel
514
+ ↓
515
+ Hell
516
+ ↓
517
+ Hello
518
+ ```
519
+
520
+ The continuation starts at the old endpoint of the same Session, so another replica can recognize it as an extension of the existing Insertion.
521
+
522
+ This is only done while the old endpoint can safely grow.
523
+
524
+ If other history already depends on that endpoint in a way that would change its ordering, the new content becomes a normal separate Insertion instead.
525
+
526
+ An Insertion can also be extended after it has fragmented. The new suffix may need its own Strip, but it still belongs to the same canonical Insertion.
527
+
528
+ ## Removal
529
+
530
+ Removal is represented by reducing Insertions.
531
+
532
+ Suppose one positive Insertion contains:
533
+
534
+ ```text
535
+ A B C D
536
+ ```
537
+
538
+ and `B C` are removed.
539
+
540
+ The removal anchors to the original positive Insertion and covers those original Frames:
541
+
542
+ ```text
543
+ original
544
+
545
+ A B C D
546
+ └─┬─┘
547
+ removed
548
+ ```
549
+
550
+ The Projection becomes:
551
+
552
+ ```text
553
+ A D
554
+ ```
555
+
556
+ The original coordinates still exist in Structural Order.
557
+
558
+ This becomes especially useful when insertion and removal happen concurrently.
559
+
560
+ Suppose both replicas start with:
561
+
562
+ ```text
563
+ The old house
564
+ ```
565
+
566
+ Replica A removes:
567
+
568
+ ```text
569
+ old
570
+ ```
571
+
572
+ and sees:
573
+
574
+ ```text
575
+ The house
576
+ ```
577
+
578
+ At the same time Replica B inserts:
579
+
580
+ ```text
581
+ small
582
+ ```
583
+
584
+ after `old `:
585
+
586
+ ```text
587
+ The old small house
588
+ ```
589
+
590
+ The removal authored by A refers to the original Frames of `old `.
591
+
592
+ It never referred to `small ` because those Frames did not exist in A's history.
593
+
594
+ After synchronization:
595
+
596
+ ```text
597
+ The small house
598
+ ```
599
+
600
+ The concurrent insertion survives.
601
+
602
+ ## A removal can cross several Insertions
603
+
604
+ A visible range can contain Frames from several original Insertions.
605
+
606
+ For example, the Projection:
607
+
608
+ ```text
609
+ Hello world
610
+ ```
611
+
612
+ might have been built from:
613
+
614
+ ```text
615
+ [Hello] [ ] [world]
616
+ ```
617
+
618
+ Removing:
619
+
620
+ ```text
621
+ lo wo
622
+ ```
623
+
624
+ crosses all three.
625
+
626
+ Sequencer describes the removal against the original Frames of each Insertion it crosses.
627
+
628
+ The visible edit is one range, but its historical description can contain several reducing Insertions.
629
+
630
+ ## Removal fragments
631
+
632
+ A reducing Insertion can also become fragmented.
633
+
634
+ Suppose an original positive Insertion contains:
635
+
636
+ ```text
637
+ A B C D E F
638
+ ```
639
+
640
+ and its current structural representation has already become:
641
+
642
+ ```text
643
+ [A B] [C D] [E F]
644
+ ```
645
+
646
+ A removal covering:
647
+
648
+ ```text
649
+ B C D E
650
+ ```
651
+
652
+ may need mask fragments at several places in Structural Order.
653
+
654
+ Those mask Strips still belong to one canonical reducing Insertion.
655
+
656
+ Its identity and original target coordinates do not change.
657
+
658
+ ## Overlapping removals
659
+
660
+ Two replicas can remove some of the same original Frames.
661
+
662
+ Starting from:
663
+
664
+ ```text
665
+ the brown fox jumps
666
+ ```
667
+
668
+ one replica might remove:
669
+
670
+ ```text
671
+ brown fox
672
+ ```
673
+
674
+ while another removes:
675
+
676
+ ```text
677
+ fox jumps
678
+ ```
679
+
680
+ Both target the original Frames of `fox`.
681
+
682
+ When the second removal is integrated, those Frames may already be masked.
683
+
684
+ They cannot reduce the Projection again.
685
+
686
+ The reducing Insertion still describes the range it originally targeted, while its runtime effect is limited to original Frames that remain available for it to consume.
687
+
688
+ This lets overlapping removals arrive in either order without changing the result.
689
+
690
+ ## Replacement
691
+
692
+ Replacement is a removal followed by a positive Insertion.
693
+
694
+ Changing:
695
+
696
+ ```text
697
+ Draft
698
+ ```
699
+
700
+ to:
701
+
702
+ ```text
703
+ Final
704
+ ```
705
+
706
+ first masks the Frames of:
707
+
708
+ ```text
709
+ Draft
710
+ ```
711
+
712
+ and then anchors:
713
+
714
+ ```text
715
+ Final
716
+ ```
717
+
718
+ into the resulting history.
719
+
720
+ Both parts use the same insertion and removal rules as every other edit.
721
+
722
+ ## Actors and acknowledgements
723
+
724
+ Removal history cannot always be discarded when it disappears from the Projection.
725
+
726
+ Suppose one replica removes some Frames while another replica is offline.
727
+
728
+ The offline replica may still have unsent history anchored to those Frames.
729
+
730
+ The removed Frames must remain addressable until that old history no longer needs to be supported.
731
+
732
+ Actors report how far they have observed each reducing Session.
733
+
734
+ For example:
735
+
736
+ ```text
737
+ Actor 3
738
+
739
+ removal Session 17
740
+ observed through logical time 42
741
+ ```
742
+
743
+ The reported point is a **frontier**.
744
+
745
+ A single frontier summarizes a received prefix of a Session rather than acknowledging every reducing Insertion separately.
746
+
747
+ ## Compaction
748
+
749
+ When all active Actors agree on the same frontier for a reducing Session, the acknowledged part can be removed from future retained Sequences.
750
+
751
+ Suppose history contains:
752
+
753
+ ```text
754
+ positive Frames
755
+ removal mask
756
+ surviving descendants
757
+ ```
758
+
759
+ and every active Actor has seen the removal.
760
+
761
+ A new retained Sequence no longer needs to preserve all of the machinery that represented that deletion.
762
+
763
+ Compaction can remove the acknowledged masks and remove deleted Frames from retained Footage.
764
+
765
+ If only part of a positive Insertion was deleted:
766
+
767
+ ```text
768
+ A B C D
769
+ ```
770
+
771
+ with:
772
+
773
+ ```text
774
+ B C
775
+ ```
776
+
777
+ gone, the retained positive history can shrink to the surviving content:
778
+
779
+ ```text
780
+ A D
781
+ ```
782
+
783
+ Anchors and remaining removals that referred to the old coordinates are adjusted to the smaller retained coordinate space.
784
+
785
+ The running Projection does not need to be rewritten when this happens. Compaction produces another retained description of the same history.
786
+
787
+ ## Collapsed historical points
788
+
789
+ Compaction can make two old logical points collapse onto the same retained point.
790
+
791
+ Imagine:
792
+
793
+ ```text
794
+ A | removed Frames | B
795
+ ```
796
+
797
+ with surviving descendants attached on both sides of the removed region.
798
+
799
+ Before compaction those descendants were separated by different historical coordinates.
800
+
801
+ After the deleted Frames disappear from retained history, that space no longer exists.
802
+
803
+ Their order has already been resolved in Structural Order, so the compacted history keeps that order when it re-anchors the survivors around the remaining boundary.
804
+
805
+ The discarded history is no longer needed to make the same ordering decision again.
806
+
807
+ ## Actor retirement
808
+
809
+ An Actor that will never return would otherwise remain part of acknowledgement consensus forever.
810
+
811
+ Retiring an Actor removes it from future compaction requirements.
812
+
813
+ It does not remove Insertions authored by that Actor.
814
+
815
+ It only changes which Actors must agree before old removal history can be discarded.
816
+
817
+ Whether an Actor is permanently gone is something the surrounding application has to decide.
818
+
819
+ ## Sequence
820
+
821
+ A retained **Sequence** stores enough history to reconstruct the Projection later.
822
+
823
+ It contains canonical Insertion history, acknowledgement frontiers and the Footage belonging to surviving positive history.
824
+
825
+ Runtime fragmentation is not persisted as separate Insertions.
826
+
827
+ If one canonical Insertion currently exists as:
828
+
829
+ ```text
830
+ [A] [B C] [D]
831
+ ```
832
+
833
+ the retained history still describes the one original Insertion:
834
+
835
+ ```text
836
+ A B C D
837
+ ```
838
+
839
+ along with the other canonical history that caused its current result.
840
+
841
+ The next runtime can fragment it again as needed.
842
+
843
+ ## Hydration
844
+
845
+ Loading a Sequence rebuilds Structural Order and derives the Projection from it.
846
+
847
+ A hydrated runtime does not need to reproduce the exact Strip layout of the runtime that saved the Sequence.
848
+
849
+ For example, the old runtime may have ended with:
850
+
851
+ ```text
852
+ [A] [B C] [D]
853
+ ```
854
+
855
+ while the new one initially materializes:
856
+
857
+ ```text
858
+ [A B C D]
859
+ ```
860
+
861
+ If later history needs a boundary inside it, it can split again.
862
+
863
+ Both represent the same canonical Insertion.
864
+
865
+ The visible sequence and the relationships available to future edits remain the same.
866
+
867
+ ## Projection and history keep changing at different rates
868
+
869
+ A Projection can change dramatically while very little canonical history is added.
870
+
871
+ A long contiguous typing session may extend one positive Insertion.
872
+
873
+ A removal can hide many Frames while leaving the positive Insertion itself in history.
874
+
875
+ Compaction can later make retained history smaller without changing the Projection at all.
876
+
877
+ So these are separate views of the same sequence:
878
+
879
+ ```text
880
+ Projection
881
+ ```
882
+
883
+ is the content visible now.
884
+
885
+ ```text
886
+ Structural Order
887
+ ```
888
+
889
+ is the history currently needed to resolve ordering and removals.
890
+
891
+ ```text
892
+ Sequence
893
+ ```
894
+
895
+ is the retained form of that history, with acknowledged obsolete history compacted away when possible.
896
+
897
+ An edit starts from the Projection, becomes a relationship in Structural Order, and can eventually survive in a much smaller retained Sequence after the history around it is no longer needed.