@peerbit/shared-log 16.0.0 → 16.0.2
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/checked-prune.d.ts.map +1 -1
- package/dist/src/checked-prune.js +12 -0
- package/dist/src/checked-prune.js.map +1 -1
- package/dist/src/index.d.ts +10 -1
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +55 -19
- package/dist/src/index.js.map +1 -1
- package/dist/src/instance-lifecycle.d.ts.map +1 -1
- package/dist/src/instance-lifecycle.js +9 -0
- package/dist/src/instance-lifecycle.js.map +1 -1
- package/dist/src/peer-session.d.ts.map +1 -1
- package/dist/src/peer-session.js +9 -0
- package/dist/src/peer-session.js.map +1 -1
- package/dist/src/pid.d.ts +0 -2
- package/dist/src/pid.d.ts.map +1 -1
- package/dist/src/pid.js +0 -5
- package/dist/src/pid.js.map +1 -1
- package/dist/src/replication-info-v2-receive.d.ts +9 -7
- package/dist/src/replication-info-v2-receive.d.ts.map +1 -1
- package/dist/src/replication-info-v2-receive.js +14 -8
- package/dist/src/replication-info-v2-receive.js.map +1 -1
- package/dist/src/role.d.ts +0 -4
- package/dist/src/role.d.ts.map +1 -1
- package/dist/src/role.js +0 -9
- package/dist/src/role.js.map +1 -1
- package/dist/src/sync/simple.d.ts +1 -0
- package/dist/src/sync/simple.d.ts.map +1 -1
- package/dist/src/sync/simple.js +1 -1
- package/dist/src/sync/simple.js.map +1 -1
- package/package.json +11 -11
- package/src/checked-prune.ts +12 -0
- package/src/index.ts +63 -23
- package/src/instance-lifecycle.ts +9 -0
- package/src/peer-session.ts +9 -0
- package/src/pid.ts +0 -6
- package/src/replication-info-v2-receive.ts +14 -14
- package/src/role.ts +0 -13
- package/src/sync/simple.ts +1 -1
package/src/index.ts
CHANGED
|
@@ -290,6 +290,7 @@ import {
|
|
|
290
290
|
} from "./sync/profile.js";
|
|
291
291
|
import {
|
|
292
292
|
ConfirmEntriesMessage,
|
|
293
|
+
RECENT_KNOWN_EXCHANGE_HEAD_SUPPRESSION_MS,
|
|
293
294
|
SYNC_MESSAGE_PRIORITY,
|
|
294
295
|
SimpleSyncronizer,
|
|
295
296
|
} from "./sync/simple.js";
|
|
@@ -1439,6 +1440,16 @@ const JOIN_AUTHORITATIVE_RETRY_SCHEDULE_MS = [
|
|
|
1439
1440
|
];
|
|
1440
1441
|
const APPEND_BACKFILL_RETRY_SCHEDULE_MS = [0, 1_000, 3_000, 7_000];
|
|
1441
1442
|
const RECENT_KNOWN_REPAIR_SUPPRESSION_MS = 30_000;
|
|
1443
|
+
// `_entryKnownPeerObservedAt` is read ONLY through isEntryRecentlyKnownByPeer,
|
|
1444
|
+
// which treats an over-age row and an absent row identically (both false). So
|
|
1445
|
+
// rows older than the longest horizon any caller asks about are dead weight,
|
|
1446
|
+
// and dropping them is behaviour-identical rather than merely safe. Derived
|
|
1447
|
+
// from the horizons themselves -- never hardcode it -- so a future caller with
|
|
1448
|
+
// a longer window cannot silently outlive the retention that serves it.
|
|
1449
|
+
const ENTRY_KNOWN_PEER_OBSERVED_AT_RETENTION_MS = Math.max(
|
|
1450
|
+
RECENT_KNOWN_REPAIR_SUPPRESSION_MS,
|
|
1451
|
+
RECENT_KNOWN_EXCHANGE_HEAD_SUPPRESSION_MS,
|
|
1452
|
+
);
|
|
1442
1453
|
const JOIN_AUTHORITATIVE_REPAIR_DELAY_MS = 2_000;
|
|
1443
1454
|
const JOIN_AUTHORITATIVE_REPAIR_SWEEP_DELAYS_MS = [
|
|
1444
1455
|
JOIN_AUTHORITATIVE_REPAIR_DELAY_MS,
|
|
@@ -2017,7 +2028,6 @@ export class SharedLog<
|
|
|
2017
2028
|
|
|
2018
2029
|
uniqueReplicators!: Set<string>;
|
|
2019
2030
|
private _replicatorJoinEmitted!: Set<string>;
|
|
2020
|
-
private _replicatorsReconciled!: boolean;
|
|
2021
2031
|
|
|
2022
2032
|
/* private _totalParticipation!: number; */
|
|
2023
2033
|
|
|
@@ -3295,6 +3305,7 @@ export class SharedLog<
|
|
|
3295
3305
|
private _repairSweepOptimisticGidsByPeer!: Map<string, Set<string>>;
|
|
3296
3306
|
private _entryKnownPeers!: Map<string, Set<string>>;
|
|
3297
3307
|
private _entryKnownPeerObservedAt!: Map<string, Map<string, number>>;
|
|
3308
|
+
private _entryKnownPeerObservedAtSweptAt = 0;
|
|
3298
3309
|
private _joinAuthoritativeRepairTimersByDelay!: Map<
|
|
3299
3310
|
number,
|
|
3300
3311
|
ReturnType<typeof setTimeout>
|
|
@@ -3645,6 +3656,7 @@ export class SharedLog<
|
|
|
3645
3656
|
this._repairSweepOptimisticGidsByPeer = new Map();
|
|
3646
3657
|
this._entryKnownPeers = new Map();
|
|
3647
3658
|
this._entryKnownPeerObservedAt = new Map();
|
|
3659
|
+
this._entryKnownPeerObservedAtSweptAt = 0;
|
|
3648
3660
|
this._joinAuthoritativeRepairTimersByDelay = new Map();
|
|
3649
3661
|
this._joinAuthoritativeRepairPeersByDelay = new Map();
|
|
3650
3662
|
this._appendBackfillPendingByTarget = new Map();
|
|
@@ -3658,7 +3670,6 @@ export class SharedLog<
|
|
|
3658
3670
|
this.recentlyRebalanced = new Cache<string>({ max: 1e4, ttl: 1e5 });
|
|
3659
3671
|
this.uniqueReplicators = new Set();
|
|
3660
3672
|
this._replicatorJoinEmitted = new Set();
|
|
3661
|
-
this._replicatorsReconciled = false;
|
|
3662
3673
|
this._liveness = this.createReplicatorLivenessMonitor();
|
|
3663
3674
|
this._v2Receive = this.createReplicationInfoV2ReceiveCoordinator();
|
|
3664
3675
|
this._v2Send = this.createReplicationInfoV2SendCoordinator();
|
|
@@ -6779,7 +6790,7 @@ export class SharedLog<
|
|
|
6779
6790
|
rebalance?: boolean;
|
|
6780
6791
|
checkDuplicates?: boolean;
|
|
6781
6792
|
timestamp?: number;
|
|
6782
|
-
|
|
6793
|
+
allowOrderedReplacementPairs?: boolean;
|
|
6783
6794
|
onConfirmedDurableStateChanged?: () => void;
|
|
6784
6795
|
onDurableApplyCommitted?: () => boolean | void;
|
|
6785
6796
|
shouldApply?: () => boolean;
|
|
@@ -6821,7 +6832,7 @@ export class SharedLog<
|
|
|
6821
6832
|
checkDuplicates,
|
|
6822
6833
|
timestamp: ts,
|
|
6823
6834
|
rebalance,
|
|
6824
|
-
|
|
6835
|
+
allowOrderedReplacementPairs,
|
|
6825
6836
|
onConfirmedDurableStateChanged,
|
|
6826
6837
|
onDurableApplyCommitted,
|
|
6827
6838
|
shouldApply,
|
|
@@ -6830,7 +6841,7 @@ export class SharedLog<
|
|
|
6830
6841
|
rebalance?: boolean;
|
|
6831
6842
|
checkDuplicates?: boolean;
|
|
6832
6843
|
timestamp?: number;
|
|
6833
|
-
|
|
6844
|
+
allowOrderedReplacementPairs?: boolean;
|
|
6834
6845
|
onConfirmedDurableStateChanged?: () => void;
|
|
6835
6846
|
onDurableApplyCommitted?: () => boolean | void;
|
|
6836
6847
|
shouldApply?: () => boolean;
|
|
@@ -6869,17 +6880,19 @@ export class SharedLog<
|
|
|
6869
6880
|
incomingRangeCountsById.set(range.idString, count);
|
|
6870
6881
|
if (
|
|
6871
6882
|
count > 1 &&
|
|
6872
|
-
(!
|
|
6883
|
+
(!allowOrderedReplacementPairs || reset === true || count > 2)
|
|
6873
6884
|
) {
|
|
6874
6885
|
throw new Error(
|
|
6875
6886
|
`Duplicate replication range id in announcement: ${range.idString}`,
|
|
6876
6887
|
);
|
|
6877
6888
|
}
|
|
6878
|
-
//
|
|
6879
|
-
//
|
|
6880
|
-
//
|
|
6881
|
-
//
|
|
6882
|
-
//
|
|
6889
|
+
// Rolling-upgrade relaxation on the live V2 Added path: a peer may
|
|
6890
|
+
// still express a non-reset replacement as the retired geometry
|
|
6891
|
+
// followed by the current geometry under one id. The sender is already
|
|
6892
|
+
// authorized to replace that id with the final item, so collapsing an
|
|
6893
|
+
// EXACT two-item incremental pair to its last item accepts the older
|
|
6894
|
+
// wire shape without broadening authority. Deliberately narrow — reset
|
|
6895
|
+
// announcements and any run longer than two still fail as duplicates.
|
|
6883
6896
|
incomingRangesById.set(range.idString, range);
|
|
6884
6897
|
}
|
|
6885
6898
|
const incomingRanges = [...incomingRangesById.values()];
|
|
@@ -7649,6 +7662,16 @@ export class SharedLog<
|
|
|
7649
7662
|
this._nativeSharedLogState?.markEntriesKnownByPeer(hashArray, peer);
|
|
7650
7663
|
this._nativeBackbone?.markEntriesKnownByPeer(hashArray, peer);
|
|
7651
7664
|
const now = Date.now();
|
|
7665
|
+
// Growth is driven by writes, so the sweep rides the write path rather
|
|
7666
|
+
// than a timer or the rebalance pass: cost stays proportional to the
|
|
7667
|
+
// traffic that creates rows. Rate-limited to one pass per retention
|
|
7668
|
+
// window, over a map that after the first pass holds one window of marks.
|
|
7669
|
+
if (
|
|
7670
|
+
now - this._entryKnownPeerObservedAtSweptAt >=
|
|
7671
|
+
ENTRY_KNOWN_PEER_OBSERVED_AT_RETENTION_MS
|
|
7672
|
+
) {
|
|
7673
|
+
this.sweepEntryKnownPeerObservedAt(now);
|
|
7674
|
+
}
|
|
7652
7675
|
for (const hash of hashArray) {
|
|
7653
7676
|
let peers = this._entryKnownPeers.get(hash);
|
|
7654
7677
|
if (!peers) {
|
|
@@ -7718,6 +7741,28 @@ export class SharedLog<
|
|
|
7718
7741
|
return observedAt != null && Date.now() - observedAt <= maxAgeMs;
|
|
7719
7742
|
}
|
|
7720
7743
|
|
|
7744
|
+
/** Drop recency marks no reader can still act on.
|
|
7745
|
+
*
|
|
7746
|
+
* Touches ONLY `_entryKnownPeerObservedAt`. `_entryKnownPeers` carries
|
|
7747
|
+
* membership, not recency, and its rows stay until the peer dimension
|
|
7748
|
+
* clears them; the native mirrors have no recency dimension at all
|
|
7749
|
+
* (mark/remove/removePeer only), so this must not call into them or the
|
|
7750
|
+
* two sides would disagree.
|
|
7751
|
+
*/
|
|
7752
|
+
private sweepEntryKnownPeerObservedAt(now: number) {
|
|
7753
|
+
for (const [hash, observedAt] of this._entryKnownPeerObservedAt) {
|
|
7754
|
+
for (const [peer, timestamp] of observedAt) {
|
|
7755
|
+
if (now - timestamp > ENTRY_KNOWN_PEER_OBSERVED_AT_RETENTION_MS) {
|
|
7756
|
+
observedAt.delete(peer);
|
|
7757
|
+
}
|
|
7758
|
+
}
|
|
7759
|
+
if (observedAt.size === 0) {
|
|
7760
|
+
this._entryKnownPeerObservedAt.delete(hash);
|
|
7761
|
+
}
|
|
7762
|
+
}
|
|
7763
|
+
this._entryKnownPeerObservedAtSweptAt = now;
|
|
7764
|
+
}
|
|
7765
|
+
|
|
7721
7766
|
private markRepairSweepOptimisticPeer(
|
|
7722
7767
|
gid: string,
|
|
7723
7768
|
peer: string,
|
|
@@ -14213,6 +14258,7 @@ export class SharedLog<
|
|
|
14213
14258
|
this._repairSweepOptimisticGidsByPeer = new Map();
|
|
14214
14259
|
this._entryKnownPeers = new Map();
|
|
14215
14260
|
this._entryKnownPeerObservedAt = new Map();
|
|
14261
|
+
this._entryKnownPeerObservedAtSweptAt = 0;
|
|
14216
14262
|
this._joinAuthoritativeRepairTimersByDelay = new Map();
|
|
14217
14263
|
this._joinAuthoritativeRepairPeersByDelay = new Map();
|
|
14218
14264
|
this._assumeSyncedRepairSuppressedUntil = 0;
|
|
@@ -14235,7 +14281,6 @@ export class SharedLog<
|
|
|
14235
14281
|
|
|
14236
14282
|
this.uniqueReplicators = new Set();
|
|
14237
14283
|
this._replicatorJoinEmitted = new Set();
|
|
14238
|
-
this._replicatorsReconciled = false;
|
|
14239
14284
|
// Deserialized instances never ran the constructor; create the monitor and
|
|
14240
14285
|
// coordinator lazily on first open. Reopens keep the SAME instances so
|
|
14241
14286
|
// stale async continuations observe resets via property lookup.
|
|
@@ -15513,16 +15558,8 @@ export class SharedLog<
|
|
|
15513
15558
|
const existingSubscribersPromise = this.node.services.pubsub.getSubscribers(
|
|
15514
15559
|
this.topic,
|
|
15515
15560
|
);
|
|
15516
|
-
const replicationLifecycleController =
|
|
15517
|
-
this._instanceLifecycle?.membershipLifecycleController;
|
|
15518
|
-
|
|
15519
15561
|
// We do this here, because these calls requires this.closed == false
|
|
15520
15562
|
void this.pruneOfflineReplicators()
|
|
15521
|
-
.then(() => {
|
|
15522
|
-
if (this.isReplicationLifecycleActive(replicationLifecycleController)) {
|
|
15523
|
-
this._replicatorsReconciled = true;
|
|
15524
|
-
}
|
|
15525
|
-
})
|
|
15526
15563
|
.catch((error) => {
|
|
15527
15564
|
if (isNotStartedError(error as Error)) {
|
|
15528
15565
|
return;
|
|
@@ -19652,7 +19689,7 @@ export class SharedLog<
|
|
|
19652
19689
|
reset: msg instanceof FullReplicationInfoV2Message,
|
|
19653
19690
|
checkDuplicates: true,
|
|
19654
19691
|
timestamp: Number(context.message.header.timestamp),
|
|
19655
|
-
|
|
19692
|
+
allowOrderedReplacementPairs:
|
|
19656
19693
|
msg instanceof AddedReplicationInfoV2Message,
|
|
19657
19694
|
shouldApply: () => {
|
|
19658
19695
|
mutationGateChecked = true;
|
|
@@ -19761,7 +19798,6 @@ export class SharedLog<
|
|
|
19761
19798
|
}
|
|
19762
19799
|
}
|
|
19763
19800
|
|
|
19764
|
-
|
|
19765
19801
|
async calculateTotalParticipation(options?: { sum?: boolean }) {
|
|
19766
19802
|
if (options?.sum) {
|
|
19767
19803
|
const ranges = await this.replicationIndex.iterate().all();
|
|
@@ -23063,7 +23099,11 @@ export class SharedLog<
|
|
|
23063
23099
|
}
|
|
23064
23100
|
const receiveEpoch = this._peerSessions.receiveEpoch(peerHash);
|
|
23065
23101
|
if (
|
|
23066
|
-
!this._v2Receive.isRequestParked({
|
|
23102
|
+
!this._v2Receive.isRequestParked({
|
|
23103
|
+
peerHash,
|
|
23104
|
+
peerSession,
|
|
23105
|
+
receiveEpoch,
|
|
23106
|
+
})
|
|
23067
23107
|
) {
|
|
23068
23108
|
// Active, or a bounded request cycle is still running its own
|
|
23069
23109
|
// exponential retries. Keep polling for the next park.
|
|
@@ -66,10 +66,19 @@ export class InstanceLifecycle {
|
|
|
66
66
|
// code. Incremented synchronously with leader-cache invalidation so the
|
|
67
67
|
// handler can detect whether its pre-join plan needs one fresh
|
|
68
68
|
// post-persist audit.
|
|
69
|
+
//
|
|
70
|
+
// PERMANENT (fence census closed NO-GO 2026-08-12): a sub-generation
|
|
71
|
+
// WITHIN one lifecycle — it advances while the lifecycle identity is
|
|
72
|
+
// deliberately unchanged, so an identity/session token cannot tell a
|
|
73
|
+
// pre-invalidation plan from a post-invalidation one.
|
|
69
74
|
public _receiveOwnershipRevision = 0;
|
|
70
75
|
// Count of ownership-changing range mutations from queue admission
|
|
71
76
|
// through settlement, including mutations already pending when a receive
|
|
72
77
|
// starts.
|
|
78
|
+
//
|
|
79
|
+
// PERMANENT (fence census closed NO-GO 2026-08-12): a concurrency-DEPTH
|
|
80
|
+
// refcount, not a staleness token — identity answers "which generation
|
|
81
|
+
// started this?", never "how many mutation lanes are open right now?".
|
|
73
82
|
public _receiveOwnershipMutationAdmissions = 0;
|
|
74
83
|
|
|
75
84
|
// ---- stage 4: physically owned controllers (moved from SharedLog) ----
|
package/src/peer-session.ts
CHANGED
|
@@ -131,6 +131,11 @@ export class PeerSessionRegistry {
|
|
|
131
131
|
// peer stays subscribed), and it must also fence a peer that never had a
|
|
132
132
|
// session. Unlike sessions this map IS cleared at _close (see
|
|
133
133
|
// clearReceiveEpochsForClose) and replaced at open.
|
|
134
|
+
//
|
|
135
|
+
// PERMANENT (fence census closed NO-GO 2026-08-12): the per-PEER lifetime
|
|
136
|
+
// above is the whole mechanism — a session token would rotate at exactly
|
|
137
|
+
// the moments this map must survive, and could not fence a session-less
|
|
138
|
+
// peer at all.
|
|
134
139
|
_replicationInfoReceiveEpochByPeer!: Map<string, object>;
|
|
135
140
|
// Moved from SharedLog (fence B6, same name — the sanctioned file-to-file
|
|
136
141
|
// ratchet move). Refcount of in-flight destructive peer cleanups: while
|
|
@@ -140,6 +145,10 @@ export class PeerSessionRegistry {
|
|
|
140
145
|
// reconnect may rotate the session; a fresh session with a zero gate
|
|
141
146
|
// would reopen receive admission mid-drain. The map instance is replaced
|
|
142
147
|
// only at open (resetForOpen) and cleared in place at _close.
|
|
148
|
+
//
|
|
149
|
+
// PERMANENT (fence census closed NO-GO 2026-08-12): both structural
|
|
150
|
+
// reasons at once — a concurrency-DEPTH refcount whose per-PEER lifetime
|
|
151
|
+
// deliberately spans the session rotation a reconnect causes mid-drain.
|
|
143
152
|
_receiveCleanupGateByPeer!: Map<string, number>;
|
|
144
153
|
// Moved from SharedLog (fence B5, same name). Peers whose replication-info
|
|
145
154
|
// is fenced: added when a departure/unsubscribe rotation or a reconnect
|
package/src/pid.ts
CHANGED
|
@@ -3,8 +3,6 @@ const MIN_MEMORY_HEADROOM_BALANCE_SCALER = 0.25;
|
|
|
3
3
|
export class PIDReplicationController {
|
|
4
4
|
integral!: number;
|
|
5
5
|
prevError!: number;
|
|
6
|
-
prevMemoryUsage!: number;
|
|
7
|
-
prevTotalFactor!: number;
|
|
8
6
|
kp: number;
|
|
9
7
|
ki: number;
|
|
10
8
|
kd: number;
|
|
@@ -42,9 +40,6 @@ export class PIDReplicationController {
|
|
|
42
40
|
let { memoryUsage, totalFactor, peerCount, cpuUsage, currentFactor } =
|
|
43
41
|
properties;
|
|
44
42
|
|
|
45
|
-
this.prevTotalFactor = totalFactor;
|
|
46
|
-
this.prevMemoryUsage = memoryUsage;
|
|
47
|
-
|
|
48
43
|
const estimatedTotalSize =
|
|
49
44
|
currentFactor > 0 ? memoryUsage / currentFactor : 1e5;
|
|
50
45
|
|
|
@@ -238,6 +233,5 @@ export class PIDReplicationController {
|
|
|
238
233
|
reset() {
|
|
239
234
|
this.prevError = 0;
|
|
240
235
|
this.integral = 0;
|
|
241
|
-
this.prevMemoryUsage = 0;
|
|
242
236
|
}
|
|
243
237
|
}
|
|
@@ -84,12 +84,6 @@ type LocalCapabilityReadyProperties = {
|
|
|
84
84
|
|
|
85
85
|
export type ReplicationInfoV2LocalCapabilityAdvertisementHandle = {
|
|
86
86
|
firstAttempt: Promise<void>;
|
|
87
|
-
/**
|
|
88
|
-
* B12: the two-phase legacy barrier is retired — an ACKed advert promotes
|
|
89
|
-
* readiness immediately. Retained as a no-op so the handle shape (and the
|
|
90
|
-
* tests that drive it) stay stable.
|
|
91
|
-
*/
|
|
92
|
-
releaseLegacyBarrier(): void;
|
|
93
87
|
};
|
|
94
88
|
|
|
95
89
|
export type ReplicationInfoV2LocalCapabilityContext = {
|
|
@@ -203,6 +197,14 @@ export type ReplicationInfoV2ReceiveDeps = {
|
|
|
203
197
|
*/
|
|
204
198
|
export class ReplicationInfoV2ReceiveCoordinator {
|
|
205
199
|
_receiveStates!: Map<string, ReplicationInfoV2ReceiveState>;
|
|
200
|
+
/**
|
|
201
|
+
* Post-B12 V2 resync memory: sessions that have already taken one full
|
|
202
|
+
* replication-info snapshot. Two load-bearing reads, both in
|
|
203
|
+
* observeCapability: phase selection (a remembered session opens in
|
|
204
|
+
* "resync" instead of "awaiting-full"), and capability refresh (the
|
|
205
|
+
* preserveCutover decision, which keeps the memory only when a re-advert
|
|
206
|
+
* arrives under the same session with a ready sender).
|
|
207
|
+
*/
|
|
206
208
|
_cutoverPeerSessions!: WeakSet<object>;
|
|
207
209
|
_localCapabilityReadyBySession!: WeakMap<object, LocalCapabilityReady>;
|
|
208
210
|
_localCapabilityContextBySession!: WeakMap<
|
|
@@ -292,15 +294,17 @@ export class ReplicationInfoV2ReceiveCoordinator {
|
|
|
292
294
|
}
|
|
293
295
|
|
|
294
296
|
/** Revoke an unauthenticated or downgraded capability generation. */
|
|
295
|
-
revokePeerCapability(peerHash: string
|
|
297
|
+
revokePeerCapability(peerHash: string): void {
|
|
296
298
|
const state = this._receiveStates.get(peerHash);
|
|
297
299
|
if (!state) {
|
|
298
300
|
return;
|
|
299
301
|
}
|
|
300
302
|
this.clearState(state);
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
303
|
+
// Unconditional: the revoked session must lose its resync memory so a
|
|
304
|
+
// re-advert starts from the first phase again. (This used to sit behind
|
|
305
|
+
// an opt-out parameter that defaulted to true, had no else-arm, and that
|
|
306
|
+
// no caller ever overrode.)
|
|
307
|
+
this._cutoverPeerSessions.delete(state.peerSession);
|
|
304
308
|
}
|
|
305
309
|
|
|
306
310
|
private clearState(state: ReplicationInfoV2ReceiveState): void {
|
|
@@ -531,7 +535,6 @@ export class ReplicationInfoV2ReceiveCoordinator {
|
|
|
531
535
|
) {
|
|
532
536
|
return {
|
|
533
537
|
firstAttempt: Promise.resolve(),
|
|
534
|
-
releaseLegacyBarrier: () => {},
|
|
535
538
|
};
|
|
536
539
|
}
|
|
537
540
|
let context = this._localCapabilityContextBySession.get(
|
|
@@ -545,7 +548,6 @@ export class ReplicationInfoV2ReceiveCoordinator {
|
|
|
545
548
|
) {
|
|
546
549
|
return {
|
|
547
550
|
firstAttempt: Promise.resolve(),
|
|
548
|
-
releaseLegacyBarrier: () => {},
|
|
549
551
|
};
|
|
550
552
|
}
|
|
551
553
|
if (!context) {
|
|
@@ -584,7 +586,6 @@ export class ReplicationInfoV2ReceiveCoordinator {
|
|
|
584
586
|
) {
|
|
585
587
|
return {
|
|
586
588
|
firstAttempt: Promise.resolve(),
|
|
587
|
-
releaseLegacyBarrier: () => {},
|
|
588
589
|
};
|
|
589
590
|
}
|
|
590
591
|
if (!state) {
|
|
@@ -619,7 +620,6 @@ export class ReplicationInfoV2ReceiveCoordinator {
|
|
|
619
620
|
(state.firstAttempt = this.runLocalCapabilityAdvertisement(state));
|
|
620
621
|
return {
|
|
621
622
|
firstAttempt,
|
|
622
|
-
releaseLegacyBarrier: () => {},
|
|
623
623
|
};
|
|
624
624
|
}
|
|
625
625
|
|
package/src/role.ts
CHANGED
|
@@ -6,19 +6,10 @@
|
|
|
6
6
|
import { field, variant, vec } from "@dao-xyz/borsh";
|
|
7
7
|
import { MAX_U32, denormalizer } from "./integers.js";
|
|
8
8
|
|
|
9
|
-
export const overlaps = (x1: number, x2: number, y1: number, y2: number) => {
|
|
10
|
-
if (x1 <= y2 && y1 <= x2) {
|
|
11
|
-
return true;
|
|
12
|
-
}
|
|
13
|
-
return false;
|
|
14
|
-
};
|
|
15
|
-
|
|
16
9
|
export abstract class Role {
|
|
17
10
|
abstract equals(other: Role): boolean;
|
|
18
11
|
}
|
|
19
12
|
|
|
20
|
-
export const NO_TYPE_VARIANT = new Uint8Array([0]);
|
|
21
|
-
|
|
22
13
|
@variant(0)
|
|
23
14
|
export class NoType extends Role {
|
|
24
15
|
equals(other: Role) {
|
|
@@ -26,8 +17,6 @@ export class NoType extends Role {
|
|
|
26
17
|
}
|
|
27
18
|
}
|
|
28
19
|
|
|
29
|
-
export const OBSERVER_TYPE_VARIANT = new Uint8Array([1]);
|
|
30
|
-
|
|
31
20
|
@variant(1)
|
|
32
21
|
export class Observer extends Role {
|
|
33
22
|
equals(other: Role) {
|
|
@@ -35,8 +24,6 @@ export class Observer extends Role {
|
|
|
35
24
|
}
|
|
36
25
|
}
|
|
37
26
|
|
|
38
|
-
export const REPLICATOR_TYPE_VARIANT = new Uint8Array([2]);
|
|
39
|
-
|
|
40
27
|
const denormalizeru32 = denormalizer("u32");
|
|
41
28
|
export class RoleReplicationSegment {
|
|
42
29
|
@field({ type: "u64" })
|
package/src/sync/simple.ts
CHANGED
|
@@ -325,7 +325,7 @@ export const SYNC_MESSAGE_PRIORITY = CONVERGENCE_MESSAGE_PRIORITY;
|
|
|
325
325
|
// large historical backfills.
|
|
326
326
|
const SIMPLE_SYNC_RETRY_AFTER_MS = 10_000;
|
|
327
327
|
const EXCHANGE_HEAD_RESPONSE_DEDUPE_TTL_MS = SIMPLE_SYNC_RETRY_AFTER_MS - 1_000;
|
|
328
|
-
const RECENT_KNOWN_EXCHANGE_HEAD_SUPPRESSION_MS = 30_000;
|
|
328
|
+
export const RECENT_KNOWN_EXCHANGE_HEAD_SUPPRESSION_MS = 30_000;
|
|
329
329
|
const PENDING_MAYBE_SYNC_RESPONSE_TTL_MS = 30_000;
|
|
330
330
|
// An incoming maybe-sync claim keeps one retry candidate in both
|
|
331
331
|
// syncInFlightQueue and syncInFlightQueueInverted. Bound associations rather
|