@peerbit/shared-log 13.2.36 → 15.0.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/dist/src/errors.d.ts +11 -0
- package/dist/src/errors.d.ts.map +1 -1
- package/dist/src/errors.js +16 -0
- package/dist/src/errors.js.map +1 -1
- package/dist/src/index.d.ts +6 -6
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +36 -19
- package/dist/src/index.js.map +1 -1
- package/dist/src/replication-announcement.d.ts +3 -4
- package/dist/src/replication-announcement.d.ts.map +1 -1
- package/dist/src/replication-announcement.js +22 -3
- package/dist/src/replication-announcement.js.map +1 -1
- package/dist/src/replication-info-mutation.d.ts +34 -0
- package/dist/src/replication-info-mutation.d.ts.map +1 -0
- package/dist/src/replication-info-mutation.js +2 -0
- package/dist/src/replication-info-mutation.js.map +1 -0
- package/dist/src/replication-info-v2-send.d.ts +5 -5
- package/dist/src/replication-info-v2-send.d.ts.map +1 -1
- package/dist/src/replication-info-v2-send.js +9 -8
- package/dist/src/replication-info-v2-send.js.map +1 -1
- package/package.json +9 -9
- package/src/errors.ts +19 -0
- package/src/index.ts +48 -26
- package/src/replication-announcement.ts +27 -6
- package/src/replication-info-mutation.ts +34 -0
- package/src/replication-info-v2-send.ts +10 -16
package/src/index.ts
CHANGED
|
@@ -144,6 +144,7 @@ import {
|
|
|
144
144
|
debouncedAccumulatorMap,
|
|
145
145
|
} from "./debounce.js";
|
|
146
146
|
import {
|
|
147
|
+
CompatibilityModeRetiredError,
|
|
147
148
|
NativeDurableCommitError,
|
|
148
149
|
NoPeersError,
|
|
149
150
|
isNotStartedError,
|
|
@@ -248,6 +249,10 @@ import {
|
|
|
248
249
|
type ReplicationDomain,
|
|
249
250
|
type ReplicationDomainConstructor,
|
|
250
251
|
} from "./replication-domain.js";
|
|
252
|
+
import type {
|
|
253
|
+
AddedReplicationInfoMutation,
|
|
254
|
+
FullReplicationInfoMutation,
|
|
255
|
+
} from "./replication-info-mutation.js";
|
|
251
256
|
import { ReplicationInfoV2ReceiveCoordinator } from "./replication-info-v2-receive.js";
|
|
252
257
|
import { ReplicationInfoV2SendCoordinator } from "./replication-info-v2-send.js";
|
|
253
258
|
import {
|
|
@@ -428,6 +433,7 @@ export {
|
|
|
428
433
|
EntryReplicatedU32,
|
|
429
434
|
EntryReplicatedU64,
|
|
430
435
|
type CoverRange,
|
|
436
|
+
CompatibilityModeRetiredError,
|
|
431
437
|
NativeDurableCommitError,
|
|
432
438
|
NoPeersError,
|
|
433
439
|
};
|
|
@@ -1248,7 +1254,6 @@ export type SharedLogOptions<
|
|
|
1248
1254
|
waitForPruneDelay?: number;
|
|
1249
1255
|
distributionDebounceTime?: number;
|
|
1250
1256
|
strictFullReplicaFallback?: boolean;
|
|
1251
|
-
compatibility?: number;
|
|
1252
1257
|
domain?: ReplicationDomainConstructor<D>;
|
|
1253
1258
|
eagerBlocks?: EagerBlocksSetting;
|
|
1254
1259
|
fanout?: SharedLogFanoutOptions;
|
|
@@ -3760,7 +3765,10 @@ export class SharedLog<
|
|
|
3760
3765
|
}
|
|
3761
3766
|
|
|
3762
3767
|
get compatibility(): number | undefined {
|
|
3763
|
-
|
|
3768
|
+
// B12: the open option was removed and any defined value rejects at
|
|
3769
|
+
// open(); this is permanently undefined and dies with the residual
|
|
3770
|
+
// gates in a later cleanup stage.
|
|
3771
|
+
return (this._logProperties as any)?.compatibility;
|
|
3764
3772
|
}
|
|
3765
3773
|
|
|
3766
3774
|
/**
|
|
@@ -5710,7 +5718,7 @@ export class SharedLog<
|
|
|
5710
5718
|
mergeSegments?: boolean;
|
|
5711
5719
|
rebalance?: boolean;
|
|
5712
5720
|
announce?: (
|
|
5713
|
-
msg:
|
|
5721
|
+
msg: AddedReplicationInfoMutation | FullReplicationInfoMutation,
|
|
5714
5722
|
) => void;
|
|
5715
5723
|
} = {},
|
|
5716
5724
|
replicationOwnershipLifecycleController = this.captureReplicationOwnershipLifecycle(),
|
|
@@ -5946,9 +5954,11 @@ export class SharedLog<
|
|
|
5946
5954
|
|
|
5947
5955
|
if (confirmedPreliminaryRemovals.length > 0) {
|
|
5948
5956
|
await this._announcements.sendReplicationAnnouncement(
|
|
5949
|
-
|
|
5950
|
-
|
|
5951
|
-
|
|
5957
|
+
{
|
|
5958
|
+
stopped: {
|
|
5959
|
+
segmentIds: confirmedPreliminaryRemovals.map((x) => x.id),
|
|
5960
|
+
},
|
|
5961
|
+
},
|
|
5952
5962
|
replicationOwnershipLifecycleController,
|
|
5953
5963
|
);
|
|
5954
5964
|
this.throwIfReplicationOwnershipLifecycleInactive(
|
|
@@ -5973,7 +5983,7 @@ export class SharedLog<
|
|
|
5973
5983
|
);
|
|
5974
5984
|
this.validatePersistedReplicationRangeSnapshot(segments);
|
|
5975
5985
|
await this._announcements.sendReplicationAnnouncement(
|
|
5976
|
-
|
|
5986
|
+
{ full: { segments } },
|
|
5977
5987
|
replicationOwnershipLifecycleController,
|
|
5978
5988
|
);
|
|
5979
5989
|
} catch (error) {
|
|
@@ -6029,7 +6039,7 @@ export class SharedLog<
|
|
|
6029
6039
|
rebalance?: boolean;
|
|
6030
6040
|
mergeSegments?: boolean;
|
|
6031
6041
|
announce?: (
|
|
6032
|
-
msg:
|
|
6042
|
+
msg: FullReplicationInfoMutation | AddedReplicationInfoMutation,
|
|
6033
6043
|
) => void;
|
|
6034
6044
|
},
|
|
6035
6045
|
) {
|
|
@@ -6270,7 +6280,7 @@ export class SharedLog<
|
|
|
6270
6280
|
}
|
|
6271
6281
|
try {
|
|
6272
6282
|
await this._announcements.sendReplicationAnnouncement(
|
|
6273
|
-
|
|
6283
|
+
{ stopped: { segmentIds: removedSegmentIds } },
|
|
6274
6284
|
replicationOwnershipLifecycleController,
|
|
6275
6285
|
);
|
|
6276
6286
|
this.throwIfReplicationOwnershipLifecycleInactive(
|
|
@@ -6567,7 +6577,7 @@ export class SharedLog<
|
|
|
6567
6577
|
if (isMe && !ownerHasRanges) {
|
|
6568
6578
|
try {
|
|
6569
6579
|
await this._announcements.sendReplicationAnnouncement(
|
|
6570
|
-
|
|
6580
|
+
{ full: { segments: [] } },
|
|
6571
6581
|
replicationOwnershipLifecycleController,
|
|
6572
6582
|
);
|
|
6573
6583
|
} catch (error) {
|
|
@@ -7490,7 +7500,7 @@ export class SharedLog<
|
|
|
7490
7500
|
rebalance?: boolean;
|
|
7491
7501
|
shouldApply?: () => boolean;
|
|
7492
7502
|
announce?: (
|
|
7493
|
-
msg:
|
|
7503
|
+
msg: FullReplicationInfoMutation | AddedReplicationInfoMutation,
|
|
7494
7504
|
) => void;
|
|
7495
7505
|
} = {},
|
|
7496
7506
|
replicationOwnershipLifecycleController = this.captureReplicationOwnershipLifecycle(),
|
|
@@ -7537,7 +7547,7 @@ export class SharedLog<
|
|
|
7537
7547
|
);
|
|
7538
7548
|
this.validatePersistedReplicationRangeSnapshot(segments);
|
|
7539
7549
|
await this._announcements.sendReplicationAnnouncement(
|
|
7540
|
-
|
|
7550
|
+
{ full: { segments } },
|
|
7541
7551
|
replicationOwnershipLifecycleController,
|
|
7542
7552
|
);
|
|
7543
7553
|
} catch (error) {
|
|
@@ -7588,17 +7598,17 @@ export class SharedLog<
|
|
|
7588
7598
|
}
|
|
7589
7599
|
|
|
7590
7600
|
let message:
|
|
7591
|
-
|
|
|
7592
|
-
|
|
|
7601
|
+
| FullReplicationInfoMutation
|
|
7602
|
+
| AddedReplicationInfoMutation
|
|
7593
7603
|
| undefined = undefined;
|
|
7594
7604
|
if (options.reset) {
|
|
7595
|
-
message =
|
|
7596
|
-
segments: added.map((x) => x.range.toReplicationRange()),
|
|
7597
|
-
}
|
|
7605
|
+
message = {
|
|
7606
|
+
full: { segments: added.map((x) => x.range.toReplicationRange()) },
|
|
7607
|
+
};
|
|
7598
7608
|
} else {
|
|
7599
|
-
message =
|
|
7600
|
-
segments: added.map((x) => x.range.toReplicationRange()),
|
|
7601
|
-
}
|
|
7609
|
+
message = {
|
|
7610
|
+
added: { segments: added.map((x) => x.range.toReplicationRange()) },
|
|
7611
|
+
};
|
|
7602
7612
|
}
|
|
7603
7613
|
if (options.announce) {
|
|
7604
7614
|
return options.announce(message);
|
|
@@ -14166,6 +14176,17 @@ export class SharedLog<
|
|
|
14166
14176
|
}
|
|
14167
14177
|
|
|
14168
14178
|
async open(options?: Args<T, D, R>): Promise<void> {
|
|
14179
|
+
// B12: replication-info network compatibility modes are retired. Read the
|
|
14180
|
+
// RAW argument value (the option no longer exists on the type) so untyped
|
|
14181
|
+
// JS callers cannot smuggle a value past the removed field, and reject
|
|
14182
|
+
// ANY defined value — including 10, which previously behaved like the
|
|
14183
|
+
// default — BEFORE any open-time side effect (rpc.open, index/native
|
|
14184
|
+
// setup, domain resolution, synchronizer creation, subscription setup).
|
|
14185
|
+
// An explicitly-present `undefined` stays accepted.
|
|
14186
|
+
const rawCompatibility = (options as any)?.compatibility;
|
|
14187
|
+
if (rawCompatibility !== undefined) {
|
|
14188
|
+
throw new CompatibilityModeRetiredError(rawCompatibility);
|
|
14189
|
+
}
|
|
14169
14190
|
this.ensureNativeDurabilityRuntimeState();
|
|
14170
14191
|
this._nativeStrictDurableTransactionsClosing = false;
|
|
14171
14192
|
this._replicationRangeMutationsClosing = false;
|
|
@@ -14227,7 +14248,8 @@ export class SharedLog<
|
|
|
14227
14248
|
this.domain = options?.domain
|
|
14228
14249
|
? (options.domain(this) as unknown as D)
|
|
14229
14250
|
: (createReplicationDomainHash(
|
|
14230
|
-
options?.compatibility !== undefined &&
|
|
14251
|
+
(options as any)?.compatibility !== undefined &&
|
|
14252
|
+
(options as any).compatibility < 10
|
|
14231
14253
|
? "u32"
|
|
14232
14254
|
: "u64",
|
|
14233
14255
|
)(this) as unknown as D);
|
|
@@ -14837,7 +14859,7 @@ export class SharedLog<
|
|
|
14837
14859
|
sendOptions?: { priority?: number; signal?: AbortSignal },
|
|
14838
14860
|
) => this.trySendFusedRawExchangeHeads(hashes, to, sendOptions),
|
|
14839
14861
|
warn,
|
|
14840
|
-
compatibility: this._logProperties?.compatibility,
|
|
14862
|
+
compatibility: (this._logProperties as any)?.compatibility,
|
|
14841
14863
|
resolution: this.domain.resolution,
|
|
14842
14864
|
sync: options?.sync,
|
|
14843
14865
|
syncronizer: options?.syncronizer,
|
|
@@ -20540,7 +20562,7 @@ export class SharedLog<
|
|
|
20540
20562
|
throwIfInactive();
|
|
20541
20563
|
|
|
20542
20564
|
if (options?.replicate) {
|
|
20543
|
-
let messageToSend:
|
|
20565
|
+
let messageToSend: AddedReplicationInfoMutation | undefined = undefined;
|
|
20544
20566
|
|
|
20545
20567
|
if (assumeSynced) {
|
|
20546
20568
|
throwIfInactive();
|
|
@@ -20568,14 +20590,14 @@ export class SharedLog<
|
|
|
20568
20590
|
// in one large message instead
|
|
20569
20591
|
announce: (msg) => {
|
|
20570
20592
|
throwIfInactive();
|
|
20571
|
-
if (
|
|
20593
|
+
if (!("added" in msg)) {
|
|
20572
20594
|
throw new Error("Unexpected");
|
|
20573
20595
|
}
|
|
20574
20596
|
|
|
20575
20597
|
if (messageToSend) {
|
|
20576
20598
|
// merge segments to make it into one messages
|
|
20577
|
-
for (const segment of msg.segments) {
|
|
20578
|
-
messageToSend.segments.push(segment);
|
|
20599
|
+
for (const segment of msg.added.segments) {
|
|
20600
|
+
messageToSend.added.segments.push(segment);
|
|
20579
20601
|
}
|
|
20580
20602
|
} else {
|
|
20581
20603
|
messageToSend = msg;
|
|
@@ -10,6 +10,7 @@ import { TimeoutError, debounceFixedInterval } from "@peerbit/time";
|
|
|
10
10
|
import { isNotStartedError } from "./errors.js";
|
|
11
11
|
import type { TransportMessage } from "./message.js";
|
|
12
12
|
import type { ReplicationRangeIndexable } from "./ranges.js";
|
|
13
|
+
import type { ReplicationInfoMutation } from "./replication-info-mutation.js";
|
|
13
14
|
import {
|
|
14
15
|
AddedReplicationSegmentMessage,
|
|
15
16
|
AllReplicatingSegmentsMessage,
|
|
@@ -206,14 +207,34 @@ export type ReplicationAnnouncementDeps<R extends "u32" | "u64"> = {
|
|
|
206
207
|
queueCurrentReplicationStateAnnouncementRetry: (error: unknown) => boolean;
|
|
207
208
|
// V2 is always current. Legacy publication is enabled only for an explicit
|
|
208
209
|
// compatibility open and retains its exact rejection/retry semantics there.
|
|
209
|
-
enqueueReplicationInfoV2: (
|
|
210
|
+
enqueueReplicationInfoV2: (mutation: ReplicationInfoMutation) => void;
|
|
210
211
|
isLegacyReplicationInfoEnabled: () => boolean;
|
|
211
212
|
};
|
|
212
213
|
|
|
213
|
-
|
|
214
|
+
/**
|
|
215
|
+
* The dormant legacy tail still broadcasts the retired wire classes when an
|
|
216
|
+
* explicit compatibility open enabled it (impossible since B12 stage 1; the
|
|
217
|
+
* tail is deleted in stage 3). Materialize the frame from the neutral
|
|
218
|
+
* mutation locally so the tail keeps its exact byte semantics until then.
|
|
219
|
+
*/
|
|
220
|
+
const toLegacyReplicationInfoFrame = (
|
|
221
|
+
mutation: ReplicationInfoMutation,
|
|
222
|
+
):
|
|
214
223
|
| AllReplicatingSegmentsMessage
|
|
215
224
|
| AddedReplicationSegmentMessage
|
|
216
|
-
| StoppedReplicating
|
|
225
|
+
| StoppedReplicating => {
|
|
226
|
+
if ("full" in mutation) {
|
|
227
|
+
return new AllReplicatingSegmentsMessage({
|
|
228
|
+
segments: mutation.full.segments,
|
|
229
|
+
});
|
|
230
|
+
}
|
|
231
|
+
if ("added" in mutation) {
|
|
232
|
+
return new AddedReplicationSegmentMessage({
|
|
233
|
+
segments: mutation.added.segments,
|
|
234
|
+
});
|
|
235
|
+
}
|
|
236
|
+
return new StoppedReplicating({ segmentIds: mutation.stopped.segmentIds });
|
|
237
|
+
};
|
|
217
238
|
|
|
218
239
|
export class ReplicationAnnouncementCoordinator<R extends "u32" | "u64"> {
|
|
219
240
|
replicationAnnouncementRetryDebounced:
|
|
@@ -627,7 +648,7 @@ export class ReplicationAnnouncementCoordinator<R extends "u32" | "u64"> {
|
|
|
627
648
|
}
|
|
628
649
|
|
|
629
650
|
async sendReplicationAnnouncement(
|
|
630
|
-
|
|
651
|
+
mutation: ReplicationInfoMutation,
|
|
631
652
|
ownershipLifecycleController = this.deps.captureReplicationOwnershipLifecycle(),
|
|
632
653
|
options?: { shouldSend?: () => boolean },
|
|
633
654
|
): Promise<void> {
|
|
@@ -652,12 +673,12 @@ export class ReplicationAnnouncementCoordinator<R extends "u32" | "u64"> {
|
|
|
652
673
|
// after that stale send settles.
|
|
653
674
|
this.rotateAnnouncementSession();
|
|
654
675
|
this.advanceCurrentReplicationStateAnnouncementRepairGeneration();
|
|
655
|
-
this.deps.enqueueReplicationInfoV2(
|
|
676
|
+
this.deps.enqueueReplicationInfoV2(mutation);
|
|
656
677
|
if (!this.deps.isLegacyReplicationInfoEnabled()) {
|
|
657
678
|
return;
|
|
658
679
|
}
|
|
659
680
|
try {
|
|
660
|
-
await this.deps.getRpc().send(
|
|
681
|
+
await this.deps.getRpc().send(toLegacyReplicationInfoFrame(mutation), {
|
|
661
682
|
priority: CONVERGENCE_MESSAGE_PRIORITY,
|
|
662
683
|
signal: ownershipLifecycleController.signal,
|
|
663
684
|
});
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { ReplicationRangeMessage } from "./ranges.js";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Neutral internal representation of a local replication-state mutation.
|
|
5
|
+
*
|
|
6
|
+
* Producers (replicate/unreplicate/join and their corrective snapshot paths)
|
|
7
|
+
* hand these plain tagged objects to the announcement coordinator, which maps
|
|
8
|
+
* them onto the directed V2 wire messages:
|
|
9
|
+
*
|
|
10
|
+
* - `full` -> FullReplicationInfoV2Message (authoritative snapshot)
|
|
11
|
+
* - `added` -> AddedReplicationInfoV2Message (incremental delta)
|
|
12
|
+
* - `stopped` -> StoppedReplicationInfoV2Message (retired segment ids)
|
|
13
|
+
*
|
|
14
|
+
* The retired legacy announcement classes (AllReplicatingSegmentsMessage,
|
|
15
|
+
* AddedReplicationSegmentMessage, StoppedReplicating) remain registered
|
|
16
|
+
* decode tombstones on the wire surface but are no longer the internal
|
|
17
|
+
* currency between mutation producers and the V2 sender.
|
|
18
|
+
*/
|
|
19
|
+
export type FullReplicationInfoMutation = {
|
|
20
|
+
full: { segments: ReplicationRangeMessage<any>[] };
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
export type AddedReplicationInfoMutation = {
|
|
24
|
+
added: { segments: ReplicationRangeMessage<any>[] };
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
export type StoppedReplicationInfoMutation = {
|
|
28
|
+
stopped: { segmentIds: Uint8Array[] };
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
export type ReplicationInfoMutation =
|
|
32
|
+
| FullReplicationInfoMutation
|
|
33
|
+
| AddedReplicationInfoMutation
|
|
34
|
+
| StoppedReplicationInfoMutation;
|
|
@@ -8,13 +8,11 @@ import {
|
|
|
8
8
|
import type { TransportMessage } from "./message.js";
|
|
9
9
|
import type { ReplicationRangeIndexable } from "./ranges.js";
|
|
10
10
|
import { deriveReplicationInfoV2ReceiverBinding } from "./replication-info-v2-binding.js";
|
|
11
|
+
import type { ReplicationInfoMutation } from "./replication-info-mutation.js";
|
|
11
12
|
import {
|
|
12
13
|
AddedReplicationInfoV2Message,
|
|
13
|
-
AddedReplicationSegmentMessage,
|
|
14
|
-
AllReplicatingSegmentsMessage,
|
|
15
14
|
FullReplicationInfoV2Message,
|
|
16
15
|
RequestReplicationInfoV2Message,
|
|
17
|
-
StoppedReplicating,
|
|
18
16
|
StoppedReplicationInfoV2Message,
|
|
19
17
|
} from "./replication.js";
|
|
20
18
|
|
|
@@ -27,14 +25,9 @@ const MAX_BACKOFF_EXPONENT = 20;
|
|
|
27
25
|
|
|
28
26
|
export { deriveReplicationInfoV2ReceiverBinding } from "./replication-info-v2-binding.js";
|
|
29
27
|
|
|
30
|
-
export type LegacyReplicationInfoMessage =
|
|
31
|
-
| AllReplicatingSegmentsMessage
|
|
32
|
-
| AddedReplicationSegmentMessage
|
|
33
|
-
| StoppedReplicating;
|
|
34
|
-
|
|
35
28
|
type SendRequest =
|
|
36
29
|
| { kind: "snapshot" }
|
|
37
|
-
| { kind: "
|
|
30
|
+
| { kind: "mutation"; mutation: ReplicationInfoMutation };
|
|
38
31
|
|
|
39
32
|
export type ReplicationInfoV2SendState = {
|
|
40
33
|
peerHash: string;
|
|
@@ -393,9 +386,9 @@ export class ReplicationInfoV2SendCoordinator<R extends "u32" | "u64"> {
|
|
|
393
386
|
return true;
|
|
394
387
|
}
|
|
395
388
|
|
|
396
|
-
enqueue(
|
|
389
|
+
enqueue(mutation: ReplicationInfoMutation): void {
|
|
397
390
|
for (const state of [...this._sendStates.values()]) {
|
|
398
|
-
this.enqueueState(state, { kind: "
|
|
391
|
+
this.enqueueState(state, { kind: "mutation", mutation });
|
|
399
392
|
}
|
|
400
393
|
}
|
|
401
394
|
|
|
@@ -538,20 +531,21 @@ export class ReplicationInfoV2SendCoordinator<R extends "u32" | "u64"> {
|
|
|
538
531
|
this.deps.validatePersistedReplicationRangeSnapshot(segments);
|
|
539
532
|
return new FullReplicationInfoV2Message({ ...common, segments });
|
|
540
533
|
}
|
|
541
|
-
|
|
542
|
-
|
|
534
|
+
const { mutation } = request;
|
|
535
|
+
if ("full" in mutation) {
|
|
536
|
+
const segments = mutation.full.segments;
|
|
543
537
|
this.deps.validatePersistedReplicationRangeSnapshot(segments);
|
|
544
538
|
return new FullReplicationInfoV2Message({ ...common, segments });
|
|
545
539
|
}
|
|
546
|
-
if (
|
|
540
|
+
if ("added" in mutation) {
|
|
547
541
|
return new AddedReplicationInfoV2Message({
|
|
548
542
|
...common,
|
|
549
|
-
segments:
|
|
543
|
+
segments: mutation.added.segments,
|
|
550
544
|
});
|
|
551
545
|
}
|
|
552
546
|
return new StoppedReplicationInfoV2Message({
|
|
553
547
|
...common,
|
|
554
|
-
segmentIds:
|
|
548
|
+
segmentIds: mutation.stopped.segmentIds,
|
|
555
549
|
});
|
|
556
550
|
}
|
|
557
551
|
|