@peerbit/shared-log 16.0.1 → 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/index.d.ts +10 -0
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +40 -1
- package/dist/src/index.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 +12 -12
- package/src/index.ts +46 -0
- 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,
|
|
@@ -3294,6 +3305,7 @@ export class SharedLog<
|
|
|
3294
3305
|
private _repairSweepOptimisticGidsByPeer!: Map<string, Set<string>>;
|
|
3295
3306
|
private _entryKnownPeers!: Map<string, Set<string>>;
|
|
3296
3307
|
private _entryKnownPeerObservedAt!: Map<string, Map<string, number>>;
|
|
3308
|
+
private _entryKnownPeerObservedAtSweptAt = 0;
|
|
3297
3309
|
private _joinAuthoritativeRepairTimersByDelay!: Map<
|
|
3298
3310
|
number,
|
|
3299
3311
|
ReturnType<typeof setTimeout>
|
|
@@ -3644,6 +3656,7 @@ export class SharedLog<
|
|
|
3644
3656
|
this._repairSweepOptimisticGidsByPeer = new Map();
|
|
3645
3657
|
this._entryKnownPeers = new Map();
|
|
3646
3658
|
this._entryKnownPeerObservedAt = new Map();
|
|
3659
|
+
this._entryKnownPeerObservedAtSweptAt = 0;
|
|
3647
3660
|
this._joinAuthoritativeRepairTimersByDelay = new Map();
|
|
3648
3661
|
this._joinAuthoritativeRepairPeersByDelay = new Map();
|
|
3649
3662
|
this._appendBackfillPendingByTarget = new Map();
|
|
@@ -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;
|
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
|