@peerbit/shared-log 16.0.25 → 16.0.27
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/index.d.ts +45 -6
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +167 -26
- package/dist/src/index.js.map +1 -1
- package/dist/src/replication-info-v2-receive.d.ts +49 -4
- package/dist/src/replication-info-v2-receive.d.ts.map +1 -1
- package/dist/src/replication-info-v2-receive.js +272 -25
- package/dist/src/replication-info-v2-receive.js.map +1 -1
- package/dist/src/replication-info-v2-send.d.ts +27 -0
- package/dist/src/replication-info-v2-send.d.ts.map +1 -1
- package/dist/src/replication-info-v2-send.js +112 -0
- package/dist/src/replication-info-v2-send.js.map +1 -1
- package/package.json +16 -16
- package/src/index.ts +297 -34
- package/src/replication-info-v2-receive.ts +409 -31
- package/src/replication-info-v2-send.ts +164 -0
|
@@ -55,6 +55,7 @@ type ApplicationConfirmationTarget = {
|
|
|
55
55
|
type ApplicationConfirmationWaiter = {
|
|
56
56
|
revision: bigint;
|
|
57
57
|
minPeers: number;
|
|
58
|
+
startedAt: number;
|
|
58
59
|
target?: ApplicationConfirmationTarget;
|
|
59
60
|
resolve: () => void;
|
|
60
61
|
reject: (error: unknown) => void;
|
|
@@ -63,6 +64,37 @@ type ApplicationConfirmationWaiter = {
|
|
|
63
64
|
onAbort?: () => void;
|
|
64
65
|
};
|
|
65
66
|
|
|
67
|
+
export type ReplicationInfoV2SendDiagnostic = Readonly<{
|
|
68
|
+
state: "absent" | "current" | "stale";
|
|
69
|
+
/** Current-state classification; no historical packet/drop log is retained. */
|
|
70
|
+
reason:
|
|
71
|
+
| "state-absent"
|
|
72
|
+
| "state-retiring"
|
|
73
|
+
| "peer-session-mismatch"
|
|
74
|
+
| "transport-session-mismatch"
|
|
75
|
+
| "destination-not-current"
|
|
76
|
+
| "destination-not-open"
|
|
77
|
+
| "ownership-inactive"
|
|
78
|
+
| "retry-backoff"
|
|
79
|
+
| "send-in-flight"
|
|
80
|
+
| "send-pending"
|
|
81
|
+
| "confirmation-in-flight"
|
|
82
|
+
| "latest-applied"
|
|
83
|
+
| "latest-unconfirmed";
|
|
84
|
+
established?: boolean;
|
|
85
|
+
suspended?: boolean;
|
|
86
|
+
currentRevision: string;
|
|
87
|
+
pendingRevision?: string;
|
|
88
|
+
inFlightRevision?: string;
|
|
89
|
+
inFlightSequence?: string;
|
|
90
|
+
appliedRevision?: string;
|
|
91
|
+
confirmationRevision?: string;
|
|
92
|
+
confirmationSequence?: string;
|
|
93
|
+
retryAttempts?: number;
|
|
94
|
+
confirmationWaiters: number;
|
|
95
|
+
oldestConfirmationAgeMs?: number;
|
|
96
|
+
}>;
|
|
97
|
+
|
|
66
98
|
export type ReplicationInfoV2ConfirmationOptions = {
|
|
67
99
|
/** Distinct current peers that must report durable application. Defaults to 1. */
|
|
68
100
|
minPeers?: number;
|
|
@@ -460,6 +492,7 @@ export class ReplicationInfoV2SendCoordinator<R extends "u32" | "u64"> {
|
|
|
460
492
|
const waiter: ApplicationConfirmationWaiter = {
|
|
461
493
|
revision: this._revision,
|
|
462
494
|
minPeers: properties.minPeers,
|
|
495
|
+
startedAt: Date.now(),
|
|
463
496
|
target: properties.target ? { ...properties.target } : undefined,
|
|
464
497
|
resolve,
|
|
465
498
|
reject,
|
|
@@ -488,6 +521,137 @@ export class ReplicationInfoV2SendCoordinator<R extends "u32" | "u64"> {
|
|
|
488
521
|
});
|
|
489
522
|
}
|
|
490
523
|
|
|
524
|
+
/**
|
|
525
|
+
* Bounded, read-only state for persisted-readiness troubleshooting. Opaque
|
|
526
|
+
* session/challenge values and peer maps are intentionally excluded.
|
|
527
|
+
*/
|
|
528
|
+
diagnosePeer(target: {
|
|
529
|
+
peerHash: string;
|
|
530
|
+
peerSession?: object;
|
|
531
|
+
receiverTransportSession?: bigint;
|
|
532
|
+
}): ReplicationInfoV2SendDiagnostic {
|
|
533
|
+
const state = this._sendStates.get(target.peerHash);
|
|
534
|
+
let matchingConfirmationCount = 0;
|
|
535
|
+
let oldestStartedAt: number | undefined;
|
|
536
|
+
for (const waiter of this._confirmations) {
|
|
537
|
+
if (
|
|
538
|
+
waiter.target?.peerHash !== target.peerHash ||
|
|
539
|
+
(target.peerSession !== undefined &&
|
|
540
|
+
waiter.target.peerSession !== target.peerSession) ||
|
|
541
|
+
(target.receiverTransportSession !== undefined &&
|
|
542
|
+
waiter.target.receiverTransportSession !==
|
|
543
|
+
target.receiverTransportSession)
|
|
544
|
+
) {
|
|
545
|
+
continue;
|
|
546
|
+
}
|
|
547
|
+
matchingConfirmationCount++;
|
|
548
|
+
oldestStartedAt =
|
|
549
|
+
oldestStartedAt === undefined
|
|
550
|
+
? waiter.startedAt
|
|
551
|
+
: Math.min(oldestStartedAt, waiter.startedAt);
|
|
552
|
+
}
|
|
553
|
+
const common = {
|
|
554
|
+
currentRevision: this._revision.toString(),
|
|
555
|
+
confirmationWaiters: Math.min(
|
|
556
|
+
this.maxConfirmationWaiters,
|
|
557
|
+
matchingConfirmationCount,
|
|
558
|
+
),
|
|
559
|
+
...(oldestStartedAt === undefined
|
|
560
|
+
? {}
|
|
561
|
+
: {
|
|
562
|
+
oldestConfirmationAgeMs: Math.min(
|
|
563
|
+
MAX_TIMER_MS,
|
|
564
|
+
Math.max(0, Date.now() - oldestStartedAt),
|
|
565
|
+
),
|
|
566
|
+
}),
|
|
567
|
+
};
|
|
568
|
+
if (!state) {
|
|
569
|
+
return Object.freeze({
|
|
570
|
+
state: this._retiringWorkersByPeer.has(target.peerHash)
|
|
571
|
+
? ("stale" as const)
|
|
572
|
+
: ("absent" as const),
|
|
573
|
+
reason: this._retiringWorkersByPeer.has(target.peerHash)
|
|
574
|
+
? ("state-retiring" as const)
|
|
575
|
+
: ("state-absent" as const),
|
|
576
|
+
...common,
|
|
577
|
+
});
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
let status: "current" | "stale" = "current";
|
|
581
|
+
let reason: ReplicationInfoV2SendDiagnostic["reason"];
|
|
582
|
+
if (
|
|
583
|
+
target.peerSession !== undefined &&
|
|
584
|
+
state.peerSession !== target.peerSession
|
|
585
|
+
) {
|
|
586
|
+
status = "stale";
|
|
587
|
+
reason = "peer-session-mismatch";
|
|
588
|
+
} else if (
|
|
589
|
+
target.receiverTransportSession !== undefined &&
|
|
590
|
+
state.receiverTransportSession !== target.receiverTransportSession
|
|
591
|
+
) {
|
|
592
|
+
status = "stale";
|
|
593
|
+
reason = "transport-session-mismatch";
|
|
594
|
+
} else if (!this.isDestinationCurrent(state)) {
|
|
595
|
+
status = "stale";
|
|
596
|
+
reason = "destination-not-current";
|
|
597
|
+
} else if (!this.isDestinationReady(state)) {
|
|
598
|
+
reason = "destination-not-open";
|
|
599
|
+
} else if (
|
|
600
|
+
!this.deps.isReplicationOwnershipLifecycleActive(
|
|
601
|
+
state.ownershipLifecycleController,
|
|
602
|
+
)
|
|
603
|
+
) {
|
|
604
|
+
reason = "ownership-inactive";
|
|
605
|
+
} else if (state.suspended || state.retryTimer !== undefined) {
|
|
606
|
+
reason = "retry-backoff";
|
|
607
|
+
} else if (state.applicationConfirmationRequest !== undefined) {
|
|
608
|
+
reason = "confirmation-in-flight";
|
|
609
|
+
} else if (state.inFlightRevision !== undefined) {
|
|
610
|
+
reason = "send-in-flight";
|
|
611
|
+
} else if (state.pending !== undefined) {
|
|
612
|
+
reason = "send-pending";
|
|
613
|
+
} else if (
|
|
614
|
+
state.appliedRevision !== undefined &&
|
|
615
|
+
state.appliedRevision >= this._revision
|
|
616
|
+
) {
|
|
617
|
+
reason = "latest-applied";
|
|
618
|
+
} else {
|
|
619
|
+
reason = "latest-unconfirmed";
|
|
620
|
+
}
|
|
621
|
+
|
|
622
|
+
return Object.freeze({
|
|
623
|
+
state: status,
|
|
624
|
+
reason,
|
|
625
|
+
established: state.established,
|
|
626
|
+
suspended: state.suspended,
|
|
627
|
+
...common,
|
|
628
|
+
...(state.pending === undefined
|
|
629
|
+
? {}
|
|
630
|
+
: { pendingRevision: state.pending.revision.toString() }),
|
|
631
|
+
...(state.inFlightRevision === undefined
|
|
632
|
+
? {}
|
|
633
|
+
: { inFlightRevision: state.inFlightRevision.toString() }),
|
|
634
|
+
...(state.inFlightSequence === undefined
|
|
635
|
+
? {}
|
|
636
|
+
: { inFlightSequence: state.inFlightSequence.toString() }),
|
|
637
|
+
...(state.appliedRevision === undefined
|
|
638
|
+
? {}
|
|
639
|
+
: { appliedRevision: state.appliedRevision.toString() }),
|
|
640
|
+
...(state.applicationConfirmationRequest === undefined
|
|
641
|
+
? {}
|
|
642
|
+
: {
|
|
643
|
+
confirmationRevision:
|
|
644
|
+
state.applicationConfirmationRequest.revision.toString(),
|
|
645
|
+
confirmationSequence:
|
|
646
|
+
state.applicationConfirmationRequest.sequence.toString(),
|
|
647
|
+
}),
|
|
648
|
+
retryAttempts: Math.min(
|
|
649
|
+
MAX_BACKOFF_EXPONENT + 1,
|
|
650
|
+
Math.max(0, state.retryAttempts),
|
|
651
|
+
),
|
|
652
|
+
});
|
|
653
|
+
}
|
|
654
|
+
|
|
491
655
|
/**
|
|
492
656
|
* Wait until the latest committed local replication revision is reported as
|
|
493
657
|
* durably applied by the configured number of current peers. Revisions newer
|