@peerbit/shared-log 13.2.24 → 13.2.25
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 +12 -0
- package/dist/src/checked-prune.d.ts.map +1 -1
- package/dist/src/checked-prune.js +33 -0
- package/dist/src/checked-prune.js.map +1 -1
- package/dist/src/coordinate-persistence.d.ts +211 -0
- package/dist/src/coordinate-persistence.d.ts.map +1 -0
- package/dist/src/coordinate-persistence.js +1133 -0
- package/dist/src/coordinate-persistence.js.map +1 -0
- package/dist/src/errors.d.ts +1 -0
- package/dist/src/errors.d.ts.map +1 -1
- package/dist/src/errors.js +19 -0
- package/dist/src/errors.js.map +1 -1
- package/dist/src/index.d.ts +127 -133
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +1400 -4269
- package/dist/src/index.js.map +1 -1
- package/dist/src/instance-lifecycle.d.ts +117 -0
- package/dist/src/instance-lifecycle.d.ts.map +1 -0
- package/dist/src/instance-lifecycle.js +254 -0
- package/dist/src/instance-lifecycle.js.map +1 -0
- package/dist/src/join-warmup.d.ts +86 -0
- package/dist/src/join-warmup.d.ts.map +1 -0
- package/dist/src/join-warmup.js +351 -0
- package/dist/src/join-warmup.js.map +1 -0
- package/dist/src/native-write-through-block-store.d.ts +123 -0
- package/dist/src/native-write-through-block-store.d.ts.map +1 -0
- package/dist/src/native-write-through-block-store.js +989 -0
- package/dist/src/native-write-through-block-store.js.map +1 -0
- package/dist/src/peer-session.d.ts +117 -0
- package/dist/src/peer-session.d.ts.map +1 -0
- package/dist/src/peer-session.js +259 -0
- package/dist/src/peer-session.js.map +1 -0
- package/dist/src/replication-announcement.d.ts +116 -0
- package/dist/src/replication-announcement.d.ts.map +1 -0
- package/dist/src/replication-announcement.js +515 -0
- package/dist/src/replication-announcement.js.map +1 -0
- package/dist/src/replicator-liveness.d.ts +59 -0
- package/dist/src/replicator-liveness.d.ts.map +1 -0
- package/dist/src/replicator-liveness.js +304 -0
- package/dist/src/replicator-liveness.js.map +1 -0
- package/dist/src/sync/dispatch-lifecycle.d.ts +48 -0
- package/dist/src/sync/dispatch-lifecycle.d.ts.map +1 -0
- package/dist/src/sync/dispatch-lifecycle.js +141 -0
- package/dist/src/sync/dispatch-lifecycle.js.map +1 -0
- package/dist/src/sync/factory.d.ts +29 -0
- package/dist/src/sync/factory.d.ts.map +1 -0
- package/dist/src/sync/factory.js +87 -0
- package/dist/src/sync/factory.js.map +1 -0
- package/dist/src/sync/pending-sync-store.d.ts +105 -0
- package/dist/src/sync/pending-sync-store.d.ts.map +1 -0
- package/dist/src/sync/pending-sync-store.js +877 -0
- package/dist/src/sync/pending-sync-store.js.map +1 -0
- package/dist/src/sync/rateless-iblt.d.ts +4 -1
- package/dist/src/sync/rateless-iblt.d.ts.map +1 -1
- package/dist/src/sync/rateless-iblt.js +102 -106
- package/dist/src/sync/rateless-iblt.js.map +1 -1
- package/dist/src/sync/simple.d.ts +10 -41
- package/dist/src/sync/simple.d.ts.map +1 -1
- package/dist/src/sync/simple.js +259 -952
- package/dist/src/sync/simple.js.map +1 -1
- package/dist/src/sync/sync-peer-state.d.ts +16 -0
- package/dist/src/sync/sync-peer-state.d.ts.map +1 -0
- package/dist/src/sync/sync-peer-state.js +82 -0
- package/dist/src/sync/sync-peer-state.js.map +1 -0
- package/package.json +9 -9
- package/src/checked-prune.ts +35 -0
- package/src/coordinate-persistence.ts +1796 -0
- package/src/errors.ts +21 -0
- package/src/index.ts +4014 -7858
- package/src/instance-lifecycle.ts +351 -0
- package/src/join-warmup.ts +507 -0
- package/src/native-write-through-block-store.ts +1170 -0
- package/src/peer-session.ts +336 -0
- package/src/replication-announcement.ts +744 -0
- package/src/replicator-liveness.ts +439 -0
- package/src/sync/dispatch-lifecycle.ts +230 -0
- package/src/sync/factory.ts +154 -0
- package/src/sync/pending-sync-store.ts +1085 -0
- package/src/sync/rateless-iblt.ts +122 -132
- package/src/sync/simple.ts +334 -1144
- package/src/sync/sync-peer-state.ts +107 -0
|
@@ -25,6 +25,11 @@ import { SilentDelivery } from "@peerbit/stream-interface";
|
|
|
25
25
|
import { type EntryWithRefs } from "../exchange-heads.js";
|
|
26
26
|
import { TransportMessage } from "../message.js";
|
|
27
27
|
import { type EntryReplicated } from "../ranges.js";
|
|
28
|
+
import {
|
|
29
|
+
DispatchLifecycleRegistry,
|
|
30
|
+
isOwnershipGenerationActive,
|
|
31
|
+
isTrackedSessionActive,
|
|
32
|
+
} from "./dispatch-lifecycle.js";
|
|
28
33
|
import type {
|
|
29
34
|
HashSymbolRangeResolver,
|
|
30
35
|
RepairSession,
|
|
@@ -47,6 +52,10 @@ import {
|
|
|
47
52
|
SYNC_MESSAGE_PRIORITY,
|
|
48
53
|
SimpleSyncronizer,
|
|
49
54
|
} from "./simple.js";
|
|
55
|
+
import {
|
|
56
|
+
SyncPeerSlotRegistry,
|
|
57
|
+
type SyncPeerSlotRow,
|
|
58
|
+
} from "./sync-peer-state.js";
|
|
50
59
|
|
|
51
60
|
export const logger = loggerFn("peerbit:shared-log:rateless");
|
|
52
61
|
|
|
@@ -847,12 +856,19 @@ export class RatelessIBLTSynchronizer<D extends "u32" | "u64">
|
|
|
847
856
|
outgoingSyncProcesses: Map<string, OutgoingRatelessSyncProcess>;
|
|
848
857
|
private outgoingSyncProcessByTarget: Map<string, OutgoingRatelessSyncProcess>;
|
|
849
858
|
private ratelessDispatchLifecycleController: AbortController;
|
|
850
|
-
private
|
|
851
|
-
|
|
852
|
-
|
|
859
|
+
private readonly ratelessDispatchRegistry: DispatchLifecycleRegistry<
|
|
860
|
+
RatelessDispatchLifecycle,
|
|
861
|
+
RatelessDispatchTargetLifecycle
|
|
853
862
|
>;
|
|
863
|
+
|
|
854
864
|
private activeRatelessResponseCount: number;
|
|
855
865
|
private activeRatelessResponseCountByPeer: Map<string, number>;
|
|
866
|
+
// Per-peer slot rows for active rateless responses (shared registry; see
|
|
867
|
+
// sync-peer-state.ts for the lifetime policy). Release closures capture
|
|
868
|
+
// the row: disconnect returns current-generation quota and logical
|
|
869
|
+
// ownership immediately, while the global physical permit remains charged
|
|
870
|
+
// until the shipment actually settles.
|
|
871
|
+
private readonly ratelessPeerSlotRows: SyncPeerSlotRegistry;
|
|
856
872
|
private ratelessClosed: boolean;
|
|
857
873
|
|
|
858
874
|
constructor(readonly properties: SynchronizerComponents<D>) {
|
|
@@ -862,9 +878,27 @@ export class RatelessIBLTSynchronizer<D extends "u32" | "u64">
|
|
|
862
878
|
this.outgoingSyncProcesses = new Map();
|
|
863
879
|
this.outgoingSyncProcessByTarget = new Map();
|
|
864
880
|
this.ratelessDispatchLifecycleController = new AbortController();
|
|
865
|
-
this.
|
|
881
|
+
this.ratelessDispatchRegistry = new DispatchLifecycleRegistry<
|
|
882
|
+
RatelessDispatchLifecycle,
|
|
883
|
+
RatelessDispatchTargetLifecycle
|
|
884
|
+
>({
|
|
885
|
+
isClosed: () => this.ratelessClosed,
|
|
886
|
+
currentOwnershipLifecycleController: () =>
|
|
887
|
+
this.ratelessDispatchLifecycleController,
|
|
888
|
+
hasRetainedWork: (lifecycle) =>
|
|
889
|
+
[...lifecycle.targets.values()].some(
|
|
890
|
+
(target) => target.retainedByProcess || target.responseLeases > 0,
|
|
891
|
+
),
|
|
892
|
+
// Target-activity strategy: set membership in the active-target
|
|
893
|
+
// registry (rateless target lifecycles carry no epochs).
|
|
894
|
+
isTargetCurrent: (targetLifecycle) =>
|
|
895
|
+
this.ratelessDispatchRegistry.activeTargets
|
|
896
|
+
.get(targetLifecycle.target)
|
|
897
|
+
?.has(targetLifecycle) === true,
|
|
898
|
+
});
|
|
866
899
|
this.activeRatelessResponseCount = 0;
|
|
867
900
|
this.activeRatelessResponseCountByPeer = new Map();
|
|
901
|
+
this.ratelessPeerSlotRows = new SyncPeerSlotRegistry();
|
|
868
902
|
this.ratelessClosed = false;
|
|
869
903
|
this.ingoingSyncProcesses = new Map();
|
|
870
904
|
this.incomingRatelessProcessAdmissions = new Set();
|
|
@@ -917,15 +951,16 @@ export class RatelessIBLTSynchronizer<D extends "u32" | "u64">
|
|
|
917
951
|
private isRatelessRepairSessionActive(
|
|
918
952
|
session: RatelessRepairSessionLifecycle,
|
|
919
953
|
): boolean {
|
|
920
|
-
return (
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
this.ratelessDispatchLifecycleController
|
|
927
|
-
|
|
928
|
-
|
|
954
|
+
return isTrackedSessionActive({
|
|
955
|
+
closed: this.ratelessClosed,
|
|
956
|
+
cancelled: session.cancelled,
|
|
957
|
+
sessionController: session.controller,
|
|
958
|
+
ownershipLifecycleController: session.ownershipLifecycleController,
|
|
959
|
+
currentOwnershipLifecycleController:
|
|
960
|
+
this.ratelessDispatchLifecycleController,
|
|
961
|
+
session,
|
|
962
|
+
registered: this.ratelessRepairSessions.get(session.id),
|
|
963
|
+
});
|
|
929
964
|
}
|
|
930
965
|
|
|
931
966
|
private cancelRatelessRepairSession(
|
|
@@ -1409,42 +1444,17 @@ export class RatelessIBLTSynchronizer<D extends "u32" | "u64">
|
|
|
1409
1444
|
disposed: false,
|
|
1410
1445
|
} satisfies RatelessDispatchLifecycle;
|
|
1411
1446
|
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1447
|
+
this.ratelessDispatchRegistry.register(
|
|
1448
|
+
lifecycle,
|
|
1449
|
+
targets,
|
|
1450
|
+
(forLifecycle, target) => ({
|
|
1451
|
+
lifecycle: forLifecycle,
|
|
1415
1452
|
target,
|
|
1416
1453
|
controller: new AbortController(),
|
|
1417
1454
|
retainedByProcess: false,
|
|
1418
1455
|
responseLeases: 0,
|
|
1419
|
-
}
|
|
1420
|
-
lifecycle.targets.set(target, targetLifecycle);
|
|
1421
|
-
let activeForTarget = this.ratelessDispatchTargets.get(target);
|
|
1422
|
-
if (!activeForTarget) {
|
|
1423
|
-
activeForTarget = new Set();
|
|
1424
|
-
this.ratelessDispatchTargets.set(target, activeForTarget);
|
|
1425
|
-
}
|
|
1426
|
-
activeForTarget.add(targetLifecycle);
|
|
1427
|
-
}
|
|
1428
|
-
|
|
1429
|
-
ownershipLifecycleController.signal.addEventListener(
|
|
1430
|
-
"abort",
|
|
1431
|
-
lifecycle.onOwnerOrCallerAbort,
|
|
1432
|
-
{ once: true },
|
|
1456
|
+
}),
|
|
1433
1457
|
);
|
|
1434
|
-
if (callerSignal && callerSignal !== ownershipLifecycleController.signal) {
|
|
1435
|
-
callerSignal.addEventListener("abort", lifecycle.onOwnerOrCallerAbort, {
|
|
1436
|
-
once: true,
|
|
1437
|
-
});
|
|
1438
|
-
}
|
|
1439
|
-
if (
|
|
1440
|
-
this.ratelessClosed ||
|
|
1441
|
-
ownershipLifecycleController !==
|
|
1442
|
-
this.ratelessDispatchLifecycleController ||
|
|
1443
|
-
ownershipLifecycleController.signal.aborted ||
|
|
1444
|
-
callerSignal?.aborted
|
|
1445
|
-
) {
|
|
1446
|
-
lifecycle.onOwnerOrCallerAbort();
|
|
1447
|
-
}
|
|
1448
1458
|
return lifecycle;
|
|
1449
1459
|
}
|
|
1450
1460
|
|
|
@@ -1452,93 +1462,33 @@ export class RatelessIBLTSynchronizer<D extends "u32" | "u64">
|
|
|
1452
1462
|
targetLifecycle: RatelessDispatchTargetLifecycle,
|
|
1453
1463
|
reason?: unknown,
|
|
1454
1464
|
): void {
|
|
1455
|
-
|
|
1456
|
-
targetLifecycle.controller.abort(reason);
|
|
1457
|
-
}
|
|
1458
|
-
this.maybeDisposeRatelessDispatchLifecycle(targetLifecycle.lifecycle);
|
|
1465
|
+
this.ratelessDispatchRegistry.abortTarget(targetLifecycle, reason);
|
|
1459
1466
|
}
|
|
1460
1467
|
|
|
1461
1468
|
private abortRatelessDispatchLifecycle(
|
|
1462
1469
|
lifecycle: RatelessDispatchLifecycle,
|
|
1463
1470
|
reason?: unknown,
|
|
1464
1471
|
): void {
|
|
1465
|
-
|
|
1466
|
-
lifecycle.controller.abort(reason);
|
|
1467
|
-
}
|
|
1468
|
-
for (const targetLifecycle of lifecycle.targets.values()) {
|
|
1469
|
-
this.abortRatelessDispatchTarget(targetLifecycle, reason);
|
|
1470
|
-
}
|
|
1471
|
-
this.maybeDisposeRatelessDispatchLifecycle(lifecycle);
|
|
1472
|
+
this.ratelessDispatchRegistry.abortLifecycle(lifecycle, reason);
|
|
1472
1473
|
}
|
|
1473
1474
|
|
|
1474
1475
|
private finishRatelessDispatchLifecycle(
|
|
1475
1476
|
lifecycle: RatelessDispatchLifecycle,
|
|
1476
1477
|
): void {
|
|
1477
|
-
lifecycle
|
|
1478
|
-
this.maybeDisposeRatelessDispatchLifecycle(lifecycle);
|
|
1478
|
+
this.ratelessDispatchRegistry.finish(lifecycle);
|
|
1479
1479
|
}
|
|
1480
1480
|
|
|
1481
1481
|
private maybeDisposeRatelessDispatchLifecycle(
|
|
1482
1482
|
lifecycle: RatelessDispatchLifecycle,
|
|
1483
1483
|
): void {
|
|
1484
|
-
|
|
1485
|
-
lifecycle.disposed ||
|
|
1486
|
-
!lifecycle.dispatchFinished ||
|
|
1487
|
-
[...lifecycle.targets.values()].some(
|
|
1488
|
-
(target) => target.retainedByProcess || target.responseLeases > 0,
|
|
1489
|
-
)
|
|
1490
|
-
) {
|
|
1491
|
-
return;
|
|
1492
|
-
}
|
|
1493
|
-
lifecycle.disposed = true;
|
|
1494
|
-
lifecycle.ownershipLifecycleController.signal.removeEventListener(
|
|
1495
|
-
"abort",
|
|
1496
|
-
lifecycle.onOwnerOrCallerAbort,
|
|
1497
|
-
);
|
|
1498
|
-
if (
|
|
1499
|
-
lifecycle.callerSignal &&
|
|
1500
|
-
lifecycle.callerSignal !== lifecycle.ownershipLifecycleController.signal
|
|
1501
|
-
) {
|
|
1502
|
-
lifecycle.callerSignal.removeEventListener(
|
|
1503
|
-
"abort",
|
|
1504
|
-
lifecycle.onOwnerOrCallerAbort,
|
|
1505
|
-
);
|
|
1506
|
-
}
|
|
1507
|
-
for (const targetLifecycle of lifecycle.targets.values()) {
|
|
1508
|
-
const activeForTarget = this.ratelessDispatchTargets.get(
|
|
1509
|
-
targetLifecycle.target,
|
|
1510
|
-
);
|
|
1511
|
-
activeForTarget?.delete(targetLifecycle);
|
|
1512
|
-
if (activeForTarget?.size === 0) {
|
|
1513
|
-
this.ratelessDispatchTargets.delete(targetLifecycle.target);
|
|
1514
|
-
}
|
|
1515
|
-
}
|
|
1484
|
+
this.ratelessDispatchRegistry.maybeDispose(lifecycle);
|
|
1516
1485
|
}
|
|
1517
1486
|
|
|
1518
1487
|
private isRatelessDispatchLifecycleActive(
|
|
1519
1488
|
lifecycle: RatelessDispatchLifecycle,
|
|
1520
1489
|
target?: string,
|
|
1521
1490
|
): boolean {
|
|
1522
|
-
|
|
1523
|
-
this.ratelessClosed ||
|
|
1524
|
-
lifecycle.disposed ||
|
|
1525
|
-
lifecycle.ownershipLifecycleController !==
|
|
1526
|
-
this.ratelessDispatchLifecycleController ||
|
|
1527
|
-
lifecycle.ownershipLifecycleController.signal.aborted ||
|
|
1528
|
-
lifecycle.callerSignal?.aborted ||
|
|
1529
|
-
lifecycle.controller.signal.aborted
|
|
1530
|
-
) {
|
|
1531
|
-
return false;
|
|
1532
|
-
}
|
|
1533
|
-
if (target === undefined) {
|
|
1534
|
-
return true;
|
|
1535
|
-
}
|
|
1536
|
-
const targetLifecycle = lifecycle.targets.get(target);
|
|
1537
|
-
return (
|
|
1538
|
-
targetLifecycle !== undefined &&
|
|
1539
|
-
!targetLifecycle.controller.signal.aborted &&
|
|
1540
|
-
this.ratelessDispatchTargets.get(target)?.has(targetLifecycle) === true
|
|
1541
|
-
);
|
|
1491
|
+
return this.ratelessDispatchRegistry.isLifecycleActive(lifecycle, target);
|
|
1542
1492
|
}
|
|
1543
1493
|
|
|
1544
1494
|
private getIncomingSyncProcessKey(sender: string, syncId: string): string {
|
|
@@ -1548,12 +1498,12 @@ export class RatelessIBLTSynchronizer<D extends "u32" | "u64">
|
|
|
1548
1498
|
private isIncomingSyncGenerationActive(
|
|
1549
1499
|
ownershipLifecycleController: AbortController,
|
|
1550
1500
|
): boolean {
|
|
1551
|
-
return (
|
|
1552
|
-
|
|
1553
|
-
ownershipLifecycleController
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
);
|
|
1501
|
+
return isOwnershipGenerationActive({
|
|
1502
|
+
closed: this.ratelessClosed,
|
|
1503
|
+
ownershipLifecycleController,
|
|
1504
|
+
currentOwnershipLifecycleController:
|
|
1505
|
+
this.ratelessDispatchLifecycleController,
|
|
1506
|
+
});
|
|
1557
1507
|
}
|
|
1558
1508
|
|
|
1559
1509
|
private isIncomingSyncProcessActive(
|
|
@@ -2309,41 +2259,77 @@ export class RatelessIBLTSynchronizer<D extends "u32" | "u64">
|
|
|
2309
2259
|
|
|
2310
2260
|
const targetLifecycle = process.targetLifecycle;
|
|
2311
2261
|
targetLifecycle.responseLeases += 1;
|
|
2262
|
+
const slotRow = this.getOrCreateRatelessResponseSlotRow(target);
|
|
2263
|
+
slotRow.active += 1;
|
|
2312
2264
|
this.activeRatelessResponseCount += 1;
|
|
2313
2265
|
this.activeRatelessResponseCountByPeer.set(
|
|
2314
2266
|
target,
|
|
2315
2267
|
(this.activeRatelessResponseCountByPeer.get(target) ?? 0) + 1,
|
|
2316
2268
|
);
|
|
2317
|
-
let
|
|
2269
|
+
let logicalReleased = false;
|
|
2270
|
+
let physicalReleased = false;
|
|
2271
|
+
const releaseLogical = () => {
|
|
2272
|
+
if (logicalReleased) {
|
|
2273
|
+
return;
|
|
2274
|
+
}
|
|
2275
|
+
logicalReleased = true;
|
|
2276
|
+
slotRow.activeReleases.delete(releaseLogical);
|
|
2277
|
+
targetLifecycle.responseLeases -= 1;
|
|
2278
|
+
this.maybeDisposeRatelessDispatchLifecycle(targetLifecycle.lifecycle);
|
|
2279
|
+
};
|
|
2280
|
+
slotRow.activeReleases.add(releaseLogical);
|
|
2318
2281
|
return {
|
|
2319
2282
|
process,
|
|
2320
2283
|
authorized,
|
|
2321
2284
|
remaining,
|
|
2322
2285
|
signal: targetLifecycle.controller.signal,
|
|
2323
2286
|
release: (options) => {
|
|
2324
|
-
if (
|
|
2287
|
+
if (physicalReleased) {
|
|
2325
2288
|
return;
|
|
2326
2289
|
}
|
|
2327
|
-
|
|
2328
|
-
|
|
2329
|
-
|
|
2330
|
-
|
|
2290
|
+
physicalReleased = true;
|
|
2291
|
+
try {
|
|
2292
|
+
releaseLogical();
|
|
2293
|
+
} finally {
|
|
2294
|
+
if (options?.rollback) {
|
|
2295
|
+
for (const hash of authorized) {
|
|
2296
|
+
process.consumedResponseHashes.delete(hash);
|
|
2297
|
+
}
|
|
2298
|
+
}
|
|
2299
|
+
this.activeRatelessResponseCount -= 1;
|
|
2300
|
+
slotRow.active -= 1;
|
|
2301
|
+
if (slotRow.attached) {
|
|
2302
|
+
const activeForPeer =
|
|
2303
|
+
(this.activeRatelessResponseCountByPeer.get(target) ?? 1) - 1;
|
|
2304
|
+
if (activeForPeer === 0) {
|
|
2305
|
+
this.activeRatelessResponseCountByPeer.delete(target);
|
|
2306
|
+
} else {
|
|
2307
|
+
this.activeRatelessResponseCountByPeer.set(target, activeForPeer);
|
|
2308
|
+
}
|
|
2309
|
+
this.ratelessPeerSlotRows.maybeDropIdle(slotRow);
|
|
2331
2310
|
}
|
|
2332
2311
|
}
|
|
2333
|
-
targetLifecycle.responseLeases -= 1;
|
|
2334
|
-
this.activeRatelessResponseCount -= 1;
|
|
2335
|
-
const activeForPeer =
|
|
2336
|
-
(this.activeRatelessResponseCountByPeer.get(target) ?? 1) - 1;
|
|
2337
|
-
if (activeForPeer === 0) {
|
|
2338
|
-
this.activeRatelessResponseCountByPeer.delete(target);
|
|
2339
|
-
} else {
|
|
2340
|
-
this.activeRatelessResponseCountByPeer.set(target, activeForPeer);
|
|
2341
|
-
}
|
|
2342
|
-
this.maybeDisposeRatelessDispatchLifecycle(targetLifecycle.lifecycle);
|
|
2343
2312
|
},
|
|
2344
2313
|
};
|
|
2345
2314
|
}
|
|
2346
2315
|
|
|
2316
|
+
private getOrCreateRatelessResponseSlotRow(peer: string): SyncPeerSlotRow {
|
|
2317
|
+
return this.ratelessPeerSlotRows.ensure(peer);
|
|
2318
|
+
}
|
|
2319
|
+
|
|
2320
|
+
private detachRatelessResponseSlotRow(peer: string): void {
|
|
2321
|
+
const row = this.ratelessPeerSlotRows.detach(peer);
|
|
2322
|
+
if (!row) {
|
|
2323
|
+
return;
|
|
2324
|
+
}
|
|
2325
|
+
this.activeRatelessResponseCountByPeer.delete(peer);
|
|
2326
|
+
// Release logical lifecycle ownership immediately. Each underlying
|
|
2327
|
+
// shipment retains its global physical-work permit until its own finally.
|
|
2328
|
+
for (const releaseLogical of [...row.activeReleases]) {
|
|
2329
|
+
releaseLogical();
|
|
2330
|
+
}
|
|
2331
|
+
}
|
|
2332
|
+
|
|
2347
2333
|
async onMessage(
|
|
2348
2334
|
message: TransportMessage,
|
|
2349
2335
|
context: RequestContext,
|
|
@@ -3240,13 +3226,17 @@ export class RatelessIBLTSynchronizer<D extends "u32" | "u64">
|
|
|
3240
3226
|
}
|
|
3241
3227
|
}
|
|
3242
3228
|
for (const targetLifecycle of [
|
|
3243
|
-
...(this.
|
|
3229
|
+
...(this.ratelessDispatchRegistry.activeTargets.get(target) ?? []),
|
|
3244
3230
|
]) {
|
|
3245
3231
|
this.abortRatelessDispatchTarget(
|
|
3246
3232
|
targetLifecycle,
|
|
3247
3233
|
new Error("rateless sync target disconnected"),
|
|
3248
3234
|
);
|
|
3249
3235
|
}
|
|
3236
|
+
// A response ship for this peer may never settle. Detach current-generation
|
|
3237
|
+
// quota and logical ownership, but keep its global physical permit charged
|
|
3238
|
+
// until settlement. open() likewise preserves physical accounting.
|
|
3239
|
+
this.detachRatelessResponseSlotRow(target);
|
|
3250
3240
|
return this.simple.onPeerDisconnected(target);
|
|
3251
3241
|
}
|
|
3252
3242
|
|