@sovereignbase/sequencer 1.0.2 → 1.1.0
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 +3 -3
- package/README.md +44 -44
- package/dist/index.cjs +30 -7
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +11 -6
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.ts +11 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +30 -7
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/INTERNALS.md
CHANGED
|
@@ -752,9 +752,9 @@ The application must exchange pending history before treating an acknowledgement
|
|
|
752
752
|
|
|
753
753
|
When all active Actors agree on the same frontier for a reducing Session, the acknowledged part can be removed from future retained Sequences.
|
|
754
754
|
|
|
755
|
-
This is whole-Session eligibility: every active Actor must report the same complete Session frontier. A missing claim or a different endpoint blocks that Session.
|
|
755
|
+
This is whole-Session eligibility: every active Actor must report the same complete Session frontier. A missing claim or a different endpoint blocks that Session.
|
|
756
756
|
|
|
757
|
-
Eligible masks must disappear from the exported Sequence. Wholly removed positive Insertions and deleted Footage disappear as well.
|
|
757
|
+
Eligible masks must disappear from the exported Sequence. Wholly removed positive Insertions and deleted Footage disappear as well. Acknowledgments of compacted Sessions are dropped, Actor membership is retained.
|
|
758
758
|
|
|
759
759
|
Suppose history contains:
|
|
760
760
|
|
|
@@ -794,7 +794,7 @@ The running Projection does not need to be rewritten when this happens. Compacti
|
|
|
794
794
|
|
|
795
795
|
The exported Sequence is a retained checkpoint. Its shorter Insertions and translated anchors can use different coordinates from the live graph before export. Continued editors must use compatible retained state; a compacted checkpoint does not preserve a permanent mapping to discarded history.
|
|
796
796
|
|
|
797
|
-
An offline Actor's unacknowledged history blocks compaction only if that Actor was registered.
|
|
797
|
+
An offline Actor's unacknowledged history blocks compaction only if that Actor was registered.
|
|
798
798
|
|
|
799
799
|
## Collapsed historical points
|
|
800
800
|
|
package/README.md
CHANGED
|
@@ -27,27 +27,27 @@ console.log(projection.value(0)) // undefined
|
|
|
27
27
|
projection.destroy()
|
|
28
28
|
```
|
|
29
29
|
|
|
30
|
+
For text stored as UTF-16 code units, `projection.sequence(true)` returns string
|
|
31
|
+
Footage. Construction and merge accept either form; `sequence()` keeps array
|
|
32
|
+
Footage. See [Projection.sequence](https://sovereignbase.dev/sequencer/classes/Projection.html#sequence).
|
|
33
|
+
|
|
30
34
|
### See documentation
|
|
31
35
|
|
|
32
36
|
- [How sequencer works?](INTERNALS.md)
|
|
33
37
|
- [Typescript](https://sovereignbase.dev/sequencer/classes/Projection.html)
|
|
34
38
|
- [C++](https://sovereignbase.dev/sequencer/c++)
|
|
35
39
|
|
|
36
|
-
Register active Actors, including offline Actors, before removals. When every
|
|
37
|
-
active Actor acknowledges the same complete removal Session frontier,
|
|
38
|
-
`sequence()` omits its masks and deleted Footage. Actor membership remains.
|
|
39
|
-
See the [compaction contract](INTERNALS.md#compaction).
|
|
40
|
-
|
|
41
40
|
### Errors
|
|
42
41
|
|
|
43
42
|
Library-reported failures throw `SequencerError`, with a stable `SequencerErrorCode`
|
|
44
43
|
and a message prefixed with `{@sovereignbase/sequencer}`. Both are exported from
|
|
45
44
|
the package. The constructor accepts standard `ErrorOptions`, including `cause`.
|
|
46
45
|
|
|
47
|
-
| Code | Meaning
|
|
48
|
-
| ------------------------- |
|
|
49
|
-
| `PROJECTION_DESTROYED` | An operation was called after the Projection was destroyed.
|
|
50
|
-
| `NATIVE_OPERATION_FAILED` | The native runtime reported an initialization or operation failure.
|
|
46
|
+
| Code | Meaning |
|
|
47
|
+
| ------------------------- | ---------------------------------------------------------------------------- |
|
|
48
|
+
| `PROJECTION_DESTROYED` | An operation was called after the Projection was destroyed. |
|
|
49
|
+
| `NATIVE_OPERATION_FAILED` | The native runtime reported an initialization or operation failure. |
|
|
50
|
+
| `STRING_ENCODING_FAILED` | Snapshot Footage concatenation failed; `cause` preserves the original error. |
|
|
51
51
|
|
|
52
52
|
Invalid Gossip or Sequence input to `apply()` or `merge()` returns `undefined`.
|
|
53
53
|
Platform errors retain their original types.
|
|
@@ -58,8 +58,8 @@ Platform errors retain their original types.
|
|
|
58
58
|
|
|
59
59
|
| Format | Raw (KiB) | Minified (KiB) | Minified + gzip (KiB) |
|
|
60
60
|
| -------- | --------: | -------------: | --------------------: |
|
|
61
|
-
| ESM |
|
|
62
|
-
| CommonJS |
|
|
61
|
+
| ESM | 136.19 | 109.61 | 39.20 |
|
|
62
|
+
| CommonJS | 136.33 | 110.32 | 39.27 |
|
|
63
63
|
|
|
64
64
|
Both bundles include WASM. Terser uses three compression passes; gzip uses level 9.
|
|
65
65
|
|
|
@@ -72,37 +72,37 @@ Strips contain 1–100 Frames (visible entries). Headers show Strip counts and m
|
|
|
72
72
|
|
|
73
73
|
| Method / case | 1,000 Strips<br>50,871 Frames | 5,000 Strips<br>252,214 Frames | 10,000 Strips<br>504,871 Frames | 15,000 Strips<br>758,280 Frames | 20,000 Strips<br>1,010,749 Frames | 25,000 Strips<br>1,264,003 Frames |
|
|
74
74
|
| -------------- | ----------------------------: | -----------------------------: | ------------------------------: | ------------------------------: | --------------------------------: | --------------------------------: |
|
|
75
|
-
| apply.random |
|
|
76
|
-
| insert.head | 1,
|
|
77
|
-
| insert.random |
|
|
78
|
-
| insert.tail | 1,
|
|
75
|
+
| apply.random | 168,473 | 87,171 | 60,658 | 46,603 | 38,343 | 32,658 |
|
|
76
|
+
| insert.head | 1,271,814 | 999,755 | 1,074,002 | 1,093,264 | 1,106,172 | 1,105,184 |
|
|
77
|
+
| insert.random | 475,390 | 255,768 | 161,979 | 124,466 | 100,709 | 85,015 |
|
|
78
|
+
| insert.tail | 1,470,843 | 1,177,272 | 1,266,352 | 1,276,470 | 1,281,022 | 1,280,911 |
|
|
79
79
|
| remove.head | — | — | — | — | — | — |
|
|
80
|
-
| remove.random |
|
|
80
|
+
| remove.random | 358,067 | 180,092 | 117,059 | 86,936 | 69,330 | 57,290 |
|
|
81
81
|
| remove.tail | — | — | — | — | — | — |
|
|
82
|
-
| replace.head |
|
|
83
|
-
| replace.random |
|
|
84
|
-
| replace.tail |
|
|
85
|
-
| value.head | 2,
|
|
86
|
-
| value.random |
|
|
87
|
-
| value.tail | 5,
|
|
82
|
+
| replace.head | 453,369 | 416,649 | 429,360 | 394,513 | 395,389 | 403,713 |
|
|
83
|
+
| replace.random | 298,112 | 160,606 | 108,525 | 80,892 | 65,452 | 54,680 |
|
|
84
|
+
| replace.tail | 401,284 | 449,608 | 412,634 | 430,354 | 408,033 | 387,953 |
|
|
85
|
+
| value.head | 2,827,881 | 3,525,681 | 3,620,595 | 3,723,069 | 3,810,856 | 3,811,845 |
|
|
86
|
+
| value.random | 731,172 | 255,071 | 143,482 | 100,113 | 78,156 | 63,980 |
|
|
87
|
+
| value.tail | 5,453,695 | 5,310,238 | 5,096,734 | 5,044,621 | 5,054,127 | 4,915,815 |
|
|
88
88
|
|
|
89
89
|
**↓ Scale down (25,000 → 0 Strips)**
|
|
90
90
|
|
|
91
91
|
| Method / case | 20,000 Strips<br>1,012,742 Frames | 15,000 Strips<br>755,860 Frames | 10,000 Strips<br>504,103 Frames | 5,000 Strips<br>251,203 Frames | 1,000 Strips<br>51,057 Frames | 0 Strips<br>0 Frames |
|
|
92
92
|
| -------------- | --------------------------------: | ------------------------------: | ------------------------------: | -----------------------------: | ----------------------------: | -------------------: |
|
|
93
|
-
| apply.random |
|
|
93
|
+
| apply.random | 21,832 | 22,291 | 22,406 | 22,966 | 23,864 | 24,211 |
|
|
94
94
|
| insert.head | — | — | — | — | — | — |
|
|
95
|
-
| insert.random |
|
|
95
|
+
| insert.random | 53,637 | 55,767 | 57,227 | 57,796 | 60,536 | 60,616 |
|
|
96
96
|
| insert.tail | — | — | — | — | — | — |
|
|
97
|
-
| remove.head |
|
|
98
|
-
| remove.random |
|
|
99
|
-
| remove.tail |
|
|
100
|
-
| replace.head |
|
|
101
|
-
| replace.random |
|
|
102
|
-
| replace.tail |
|
|
103
|
-
| value.head | 1,
|
|
104
|
-
| value.random |
|
|
105
|
-
| value.tail |
|
|
97
|
+
| remove.head | 493,654 | 493,034 | 492,611 | 492,704 | 494,704 | 497,520 |
|
|
98
|
+
| remove.random | 37,466 | 39,462 | 41,048 | 43,073 | 45,209 | 45,778 |
|
|
99
|
+
| remove.tail | 491,829 | 472,405 | 399,771 | 416,614 | 426,344 | 383,461 |
|
|
100
|
+
| replace.head | 380,504 | 371,861 | 365,935 | 312,468 | 315,039 | 271,629 |
|
|
101
|
+
| replace.random | 35,794 | 37,986 | 39,619 | 41,464 | 43,674 | 43,633 |
|
|
102
|
+
| replace.tail | 198,219 | 176,520 | 166,748 | 150,292 | 149,123 | 140,224 |
|
|
103
|
+
| value.head | 1,820,081 | 1,813,320 | 1,792,267 | 1,804,349 | 1,844,976 | 1,872,844 |
|
|
104
|
+
| value.random | 41,888 | 43,912 | 45,754 | 48,224 | 51,108 | 52,192 |
|
|
105
|
+
| value.tail | 2,154,911 | 2,130,711 | 2,112,616 | 2,133,349 | 2,207,459 | 2,246,004 |
|
|
106
106
|
|
|
107
107
|
### API throughput at checkpoint
|
|
108
108
|
|
|
@@ -112,17 +112,17 @@ Checkpoint calls, in ops/s, averaged across runs.
|
|
|
112
112
|
|
|
113
113
|
| Method | 1,000 Strips<br>50,871 Frames | 5,000 Strips<br>252,214 Frames | 10,000 Strips<br>504,871 Frames | 15,000 Strips<br>758,280 Frames | 20,000 Strips<br>1,010,749 Frames | 25,000 Strips<br>1,264,003 Frames |
|
|
114
114
|
| --------------------------------- | ----------------------------: | -----------------------------: | ------------------------------: | ------------------------------: | --------------------------------: | --------------------------------: |
|
|
115
|
-
| new Projection(actorID, sequence) |
|
|
116
|
-
| sequence() |
|
|
117
|
-
| values() |
|
|
115
|
+
| new Projection(actorID, sequence) | 4,665 | 968 | 614 | 420 | 291 | 244 |
|
|
116
|
+
| sequence() | 611 | 102 | 50 | 31 | 21 | 15 |
|
|
117
|
+
| values() | 669 | 251 | 84 | 50 | 50 | 31 |
|
|
118
118
|
|
|
119
119
|
**↓ Scale down (25,000 → 0 Strips)**
|
|
120
120
|
|
|
121
121
|
| Method | 20,000 Strips<br>1,012,742 Frames | 15,000 Strips<br>755,860 Frames | 10,000 Strips<br>504,103 Frames | 5,000 Strips<br>251,203 Frames | 1,000 Strips<br>51,057 Frames | 0 Strips<br>0 Frames |
|
|
122
122
|
| --------------------------------- | --------------------------------: | ------------------------------: | ------------------------------: | -----------------------------: | ----------------------------: | -------------------: |
|
|
123
|
-
| new Projection(actorID, sequence) |
|
|
124
|
-
| sequence() |
|
|
125
|
-
| values() |
|
|
123
|
+
| new Projection(actorID, sequence) | 276 | 420 | 499 | 1,294 | 5,450 | 23,249 |
|
|
124
|
+
| sequence() | 15 | 14 | 10 | 12 | 11 | 10 |
|
|
125
|
+
| values() | 46 | 45 | 68 | 96 | 258 | 150,052 |
|
|
126
126
|
|
|
127
127
|
### Sequence disk size at checkpoint
|
|
128
128
|
|
|
@@ -132,8 +132,8 @@ Complete exported Sequences, including Footage and acknowledgements. Sizes are i
|
|
|
132
132
|
|
|
133
133
|
| Encoding | 1,000 Strips<br>50,871 Frames | 5,000 Strips<br>252,214 Frames | 10,000 Strips<br>504,871 Frames | 15,000 Strips<br>758,280 Frames | 20,000 Strips<br>1,010,749 Frames | 25,000 Strips<br>1,264,003 Frames |
|
|
134
134
|
| ------------------ | ----------------------------: | -----------------------------: | ------------------------------: | ------------------------------: | --------------------------------: | --------------------------------: |
|
|
135
|
-
| JSON | 277.
|
|
136
|
-
| JSON + gzip | 14.
|
|
135
|
+
| JSON | 277.29 | 1,622.20 | 3,262.86 | 4,902.77 | 7,043.50 | 9,165.60 |
|
|
136
|
+
| JSON + gzip | 14.60 | 73.83 | 150.38 | 226.92 | 311.16 | 391.60 |
|
|
137
137
|
| MessagePack | 164.81 | 818.88 | 1,639.69 | 3,529.41 | 5,081.04 | 6,483.22 |
|
|
138
138
|
| MessagePack + gzip | 12.38 | 61.62 | 124.91 | 198.59 | 263.54 | 332.77 |
|
|
139
139
|
|
|
@@ -141,8 +141,8 @@ Complete exported Sequences, including Footage and acknowledgements. Sizes are i
|
|
|
141
141
|
|
|
142
142
|
| Encoding | 20,000 Strips<br>1,012,742 Frames | 15,000 Strips<br>755,860 Frames | 10,000 Strips<br>504,103 Frames | 5,000 Strips<br>251,203 Frames | 1,000 Strips<br>51,057 Frames | 0 Strips<br>0 Frames |
|
|
143
143
|
| ------------------ | --------------------------------: | ------------------------------: | ------------------------------: | -----------------------------: | ----------------------------: | -------------------: |
|
|
144
|
-
| JSON | 7,
|
|
145
|
-
| JSON + gzip | 323.
|
|
144
|
+
| JSON | 7,449.19 | 5,619.45 | 3,771.17 | 1,886.19 | 383.37 | 0.02 |
|
|
145
|
+
| JSON + gzip | 323.17 | 244.42 | 163.89 | 80.61 | 16.33 | 0.03 |
|
|
146
146
|
| MessagePack | 5,237.17 | 3,930.33 | 2,628.38 | 1,312.43 | 266.67 | 0.01 |
|
|
147
147
|
| MessagePack + gzip | 274.96 | 207.78 | 137.38 | 67.41 | 13.67 | 0.03 |
|
|
148
148
|
|
|
@@ -171,7 +171,7 @@ Peer synchronization, encoding and JS process garbage collection are outside API
|
|
|
171
171
|
|
|
172
172
|
### Behaviour guaranteed by excessive tests
|
|
173
173
|
|
|
174
|
-
The latest verification passed
|
|
174
|
+
The latest verification passed 221 Vitest tests and 117 compatibility checks.
|
|
175
175
|
The configured 100% coverage threshold is met (100% statements, 100% branches, 100% functions, 100% lines).
|
|
176
176
|
See the [test suites](test/README.md) and
|
|
177
177
|
[automated test report](https://sovereignbase.dev/sequencer/tests/).
|
package/dist/index.cjs
CHANGED
|
@@ -332,6 +332,11 @@ var Runtime = class {
|
|
|
332
332
|
const heap = module$1.HEAPU32;
|
|
333
333
|
return this.content[id][heap[pointer]]?.[heap[pointer + 1]];
|
|
334
334
|
}
|
|
335
|
+
/** Exports native spans directly, with optional string Footage assembled in JavaScript. */
|
|
336
|
+
sequence(id, stringEncode) {
|
|
337
|
+
if (id < 0) throw new SequencerError("PROJECTION_DESTROYED", "Projection has been destroyed.");
|
|
338
|
+
return this.result(Operation.Sequence, id, module$1._runtime_dispatch(Operation.Sequence, id, 0, 0, 0, 0, 0), stringEncode);
|
|
339
|
+
}
|
|
335
340
|
/** Authors trusted local Frames through the dedicated six-word result path. */
|
|
336
341
|
insert(id, values, at) {
|
|
337
342
|
if (id < 0) throw new SequencerError("PROJECTION_DESTROYED", "Projection has been destroyed.");
|
|
@@ -449,16 +454,16 @@ var Runtime = class {
|
|
|
449
454
|
a0 = value ?? absent;
|
|
450
455
|
a1 = at ?? absent;
|
|
451
456
|
} else if (operation === Operation.Retire) a0 = value;
|
|
452
|
-
else
|
|
457
|
+
else {
|
|
453
458
|
a0 = operation === Operation.Create ? value : 0;
|
|
454
459
|
const sequence = operation === Operation.Create ? at : value;
|
|
455
|
-
const valid = operation === Operation.Create && sequence === void 0 || Array.isArray(sequence) && sequence.length === 2 && (Array.isArray(sequence[0]) || sequence[0] instanceof Uint32Array) && Array.isArray(sequence[1]) && (operation === Operation.Create || sequence[0] instanceof Uint32Array || sequence[0].every((word) => Number.isInteger(word) && word >= 0 && word <= absent));
|
|
460
|
+
const valid = operation === Operation.Create && sequence === void 0 || Array.isArray(sequence) && sequence.length === 2 && (Array.isArray(sequence[0]) || sequence[0] instanceof Uint32Array) && (Array.isArray(sequence[1]) || typeof sequence[1] === "string") && (operation === Operation.Create || sequence[0] instanceof Uint32Array || sequence[0].every((word) => Number.isInteger(word) && word >= 0 && word <= absent));
|
|
456
461
|
a2 = valid ? 1 : 0;
|
|
457
462
|
if (valid && sequence !== void 0) {
|
|
458
463
|
const words = sequence[0];
|
|
459
464
|
heap.set(words, base);
|
|
460
465
|
a1 = contents.length;
|
|
461
|
-
footage = sequence[1];
|
|
466
|
+
footage = typeof sequence[1] === "string" ? sequence[1].split("") : sequence[1];
|
|
462
467
|
}
|
|
463
468
|
}
|
|
464
469
|
const resultPointer = module$1._runtime_dispatch(operation, id, a0, a1, a2, pointer, count);
|
|
@@ -472,7 +477,7 @@ var Runtime = class {
|
|
|
472
477
|
return this.result(operation, id, resultPointer);
|
|
473
478
|
}
|
|
474
479
|
/** Consumes borrowed native output before another call may overwrite its storage. */
|
|
475
|
-
result(operation, id, pointer) {
|
|
480
|
+
result(operation, id, pointer, stringEncode) {
|
|
476
481
|
const heap = module$1.HEAPU32, header = pointer >>> 2, content = this.content[id];
|
|
477
482
|
const kind = heap[header], p0 = heap[header + 3], n0 = heap[header + 4], p1 = heap[header + 5], n1 = heap[header + 6];
|
|
478
483
|
const mutable = this.mutable[id];
|
|
@@ -589,6 +594,22 @@ var Runtime = class {
|
|
|
589
594
|
metadata.length = n0;
|
|
590
595
|
for (let i = 0, at = p0 >>> 2; i < n0; ++i) metadata[i] = heap[at + i];
|
|
591
596
|
} else metadata = words(p0, n0);
|
|
597
|
+
if (stringEncode) {
|
|
598
|
+
let text = "";
|
|
599
|
+
try {
|
|
600
|
+
for (let at = p1 >>> 2, end = at + n1 * 3; at < end; at += 3) {
|
|
601
|
+
const source = content[heap[at]], start = heap[at + 1], count = heap[at + 2];
|
|
602
|
+
for (let i = 0; i < count; ++i) {
|
|
603
|
+
const value = source?.[start + i];
|
|
604
|
+
text += value === void 0 ? "\0" : value;
|
|
605
|
+
}
|
|
606
|
+
}
|
|
607
|
+
} catch (cause) {
|
|
608
|
+
throw new SequencerError("STRING_ENCODING_FAILED", "Sequence Footage could not be encoded as a string.", { cause });
|
|
609
|
+
}
|
|
610
|
+
result = [metadata, text];
|
|
611
|
+
break;
|
|
612
|
+
}
|
|
592
613
|
const span = p1 >>> 2, token = heap[span];
|
|
593
614
|
const shared = n1 === 1 && heap[span + 1] === 0 && content[token]?.length === heap[span + 2] && !!mutable[token];
|
|
594
615
|
if (shared && mutable[token] !== 3) {
|
|
@@ -657,7 +678,7 @@ var Projection = class {
|
|
|
657
678
|
* Prepares to sequence a projection, optionally hydrating from a trusted sequence stored by the application.
|
|
658
679
|
*
|
|
659
680
|
* @param actorID Actor identifier used in acknowledgements.
|
|
660
|
-
* @param trustedSequence Optional trusted Sequence in Structural Order
|
|
681
|
+
* @param trustedSequence Optional trusted Sequence in Structural Order; string Footage is split into UTF-16 code units.
|
|
661
682
|
* @throws {@link SequencerError} if native initialization fails.
|
|
662
683
|
*/
|
|
663
684
|
constructor(actorID, trustedSequence) {
|
|
@@ -750,11 +771,13 @@ var Projection = class {
|
|
|
750
771
|
* permit masks and deleted Footage to be omitted from the retained checkpoint.
|
|
751
772
|
* Compaction may translate retained anchors without rewriting this instance.
|
|
752
773
|
*
|
|
774
|
+
* @param stringEncode Whether to concatenate Footage into a string; each text Frame must be one UTF-16 code unit. Defaults to `false`.
|
|
753
775
|
* @returns A Sequence with acknowledged removals compacted in the exported state.
|
|
754
776
|
* @throws {@link SequencerError} if destroyed or the native runtime reports an operation failure.
|
|
777
|
+
* @throws {@link SequencerError} with code `STRING_ENCODING_FAILED` if Footage concatenation fails.
|
|
755
778
|
*/
|
|
756
|
-
sequence() {
|
|
757
|
-
return runtime.
|
|
779
|
+
sequence(stringEncode) {
|
|
780
|
+
return runtime.sequence(this.id, stringEncode);
|
|
758
781
|
}
|
|
759
782
|
/**
|
|
760
783
|
* Returns the value at a Projection position.
|