@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.
@@ -46,9 +46,31 @@ export type ReplicationInfoV2LocalCapabilityAdvertisement = {
46
46
  firstAttempt?: Promise<void>;
47
47
  };
48
48
  type ReplicationInfoV2RemoteFullRearm = {
49
- lastAttemptAt: number;
49
+ peerHash: string;
50
+ receiveEpoch: object | null;
51
+ receiverTransportSession: bigint;
52
+ nextAttemptAt: number;
53
+ attemptsStarted: number;
54
+ outstandingAttempts: number;
50
55
  inFlight?: Promise<void>;
56
+ controller?: AbortController;
51
57
  };
58
+ export type ReplicationInfoV2ReceiveDiagnostic = Readonly<{
59
+ state: "absent" | "current" | "stale";
60
+ /** Current-state classification; no historical packet/drop log is retained. */
61
+ reason: "state-absent" | "peer-session-mismatch" | "receive-epoch-mismatch" | "transport-session-mismatch" | "state-not-current" | "admission-pending" | "active" | "request-parked" | "request-in-flight" | "request-scheduled" | "awaiting-full" | "resync";
62
+ phase?: ReplicationInfoV2ReceivePhase;
63
+ requestState?: "idle" | "scheduled" | "in-flight" | "parked" | "admission-pending";
64
+ lastAppliedSequence?: string;
65
+ requestAttempts?: number;
66
+ capabilityAdvertisementAttempts: number;
67
+ capabilityAdvertisement: "absent" | "advertising" | "ready" | "stale";
68
+ remoteFullRearm: "idle" | "in-flight" | "cooldown" | "limited";
69
+ remoteFullRearmAttempts: number;
70
+ remoteFullRearmOutstanding: number;
71
+ remoteFullRearmGlobalOutstanding: number;
72
+ remoteFullRearmCooldownRemainingMs?: number;
73
+ }>;
52
74
  export type ReplicationInfoV2LocalCapabilityRefresh = {
53
75
  receiverTransportSession: bigint;
54
76
  requestNotBeforeMs: number;
@@ -111,6 +133,9 @@ export type ReplicationInfoV2ReceiveDeps = {
111
133
  requestRetryMs?: number;
112
134
  maxRequestRetryMs?: number;
113
135
  requestMaxAttempts?: number;
136
+ remoteFullRearmAttemptTimeoutMs?: number;
137
+ remoteFullRearmCooldownMs?: number;
138
+ maxRemoteFullRearmOutstandingGlobal?: number;
114
139
  };
115
140
  /**
116
141
  * Authenticated receive grants and sender-authoritative ordering for
@@ -133,11 +158,16 @@ export declare class ReplicationInfoV2ReceiveCoordinator {
133
158
  _localCapabilityContextBySession: WeakMap<object, ReplicationInfoV2LocalCapabilityContext>;
134
159
  _localCapabilityAdvertisementsByPeer: Map<string, ReplicationInfoV2LocalCapabilityAdvertisement>;
135
160
  _remoteFullRearmBySession: WeakMap<object, ReplicationInfoV2RemoteFullRearm>;
161
+ _remoteFullRearmsInFlight: Set<ReplicationInfoV2RemoteFullRearm>;
162
+ _remoteFullRearmOutstanding: Set<object>;
136
163
  _reservedAdmissionsByPeer: Map<string, ReplicationInfoV2ReceiveAdmission>;
137
164
  private readonly now;
138
165
  private readonly requestRetryMs;
139
166
  private readonly maxRequestRetryMs;
140
167
  private readonly requestMaxAttempts;
168
+ private readonly remoteFullRearmAttemptTimeoutMs;
169
+ private readonly remoteFullRearmCooldownMs;
170
+ private readonly maxRemoteFullRearmOutstandingGlobal;
141
171
  constructor(deps: ReplicationInfoV2ReceiveDeps);
142
172
  resetForOpen(): void;
143
173
  clearForClose(): void;
@@ -171,9 +201,14 @@ export declare class ReplicationInfoV2ReceiveCoordinator {
171
201
  * stream that was lost while both directions otherwise remained current.
172
202
  *
173
203
  * This deliberately does not mutate the steady advertisement worker. One
174
- * attempt is coalesced per PeerSession and bound to the caller's signal; the
175
- * readiness wait's bounded recovery tick decides whether another attempt is
176
- * needed.
204
+ * attempt is coalesced per exact PeerSession/receive generation and bound to
205
+ * its own deadline as well as the caller's signal. A cooldown avoids rotating
206
+ * a healthy in-flight challenge on every recovery tick. The remote rotates
207
+ * only when its receive state is active; later hints during resync only nudge
208
+ * that same bounded request generation. At most two transports that disregard
209
+ * abort remain outstanding for one exact session (64 across this coordinator's
210
+ * lifetime); reaching either cap stops new hints while the persisted-readiness
211
+ * gate remains fail closed.
177
212
  */
178
213
  reAdvertiseLocalCapabilityForRemoteFull(properties: {
179
214
  peerHash: string;
@@ -181,6 +216,16 @@ export declare class ReplicationInfoV2ReceiveCoordinator {
181
216
  receiveEpoch: object | null;
182
217
  signal: AbortSignal;
183
218
  }): boolean;
219
+ /**
220
+ * Bounded, read-only state for persisted-readiness troubleshooting. This
221
+ * intentionally omits transport sessions, challenges, payloads, and maps.
222
+ */
223
+ diagnosePeer(properties: {
224
+ peerHash: string;
225
+ peerSession?: object;
226
+ receiveEpoch?: object | null;
227
+ senderTransportSession?: bigint;
228
+ }): ReplicationInfoV2ReceiveDiagnostic;
184
229
  private promoteLocalCapabilityAdvertisement;
185
230
  /**
186
231
  * Re-advertise one exact current recovery epoch from the stable membership
@@ -1 +1 @@
1
- {"version":3,"file":"replication-info-v2-receive.d.ts","sourceRoot":"","sources":["../../src/replication-info-v2-receive.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"replication-info-v2-receive.d.ts","sourceRoot":"","sources":["../../src/replication-info-v2-receive.ts"],"names":[],"mappings":"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"}
@@ -8,6 +8,11 @@ const REQUIRED_SENDER_CAPABILITIES = SYNC_CAPABILITY_REPLICATION_INFO_V2_DECODE
8
8
  const DEFAULT_REQUEST_RETRY_MS = 1_000;
9
9
  const DEFAULT_MAX_REQUEST_RETRY_MS = 30_000;
10
10
  const DEFAULT_REQUEST_MAX_ATTEMPTS = 7;
11
+ const DEFAULT_REMOTE_FULL_REARM_ATTEMPT_TIMEOUT_MS = 2_000;
12
+ const DEFAULT_REMOTE_FULL_REARM_COOLDOWN_MS = 5_000;
13
+ const MAX_REMOTE_FULL_REARM_OUTSTANDING_PER_SESSION = 2;
14
+ const MAX_REMOTE_FULL_REARM_OUTSTANDING_GLOBAL = 64;
15
+ const MAX_TIMER_MS = 2_147_483_647;
11
16
  const MAX_U64 = (1n << 64n) - 1n;
12
17
  const MAX_BACKOFF_EXPONENT = 20;
13
18
  const bytesEqual = (left, right) => {
@@ -56,23 +61,38 @@ export class ReplicationInfoV2ReceiveCoordinator {
56
61
  _localCapabilityContextBySession;
57
62
  _localCapabilityAdvertisementsByPeer;
58
63
  _remoteFullRearmBySession;
64
+ _remoteFullRearmsInFlight;
65
+ _remoteFullRearmOutstanding;
59
66
  _reservedAdmissionsByPeer;
60
67
  now;
61
68
  requestRetryMs;
62
69
  maxRequestRetryMs;
63
70
  requestMaxAttempts;
71
+ remoteFullRearmAttemptTimeoutMs;
72
+ remoteFullRearmCooldownMs;
73
+ maxRemoteFullRearmOutstandingGlobal;
64
74
  constructor(deps) {
65
75
  this.deps = deps;
66
76
  this.now = deps.now ?? Date.now;
67
77
  this.requestRetryMs = Math.max(1, deps.requestRetryMs ?? DEFAULT_REQUEST_RETRY_MS);
68
78
  this.maxRequestRetryMs = Math.max(this.requestRetryMs, deps.maxRequestRetryMs ?? DEFAULT_MAX_REQUEST_RETRY_MS);
69
79
  this.requestMaxAttempts = Math.max(1, Math.floor(deps.requestMaxAttempts ?? DEFAULT_REQUEST_MAX_ATTEMPTS));
80
+ this.remoteFullRearmAttemptTimeoutMs = Math.max(1, Math.min(MAX_TIMER_MS, Math.floor(deps.remoteFullRearmAttemptTimeoutMs ??
81
+ DEFAULT_REMOTE_FULL_REARM_ATTEMPT_TIMEOUT_MS)));
82
+ this.remoteFullRearmCooldownMs = Math.max(this.requestRetryMs, Math.min(MAX_TIMER_MS, Math.floor(deps.remoteFullRearmCooldownMs ??
83
+ DEFAULT_REMOTE_FULL_REARM_COOLDOWN_MS)));
84
+ // The injected value is a test seam that may only tighten this lifetime
85
+ // resource bound, never widen it.
86
+ this.maxRemoteFullRearmOutstandingGlobal = Math.min(MAX_REMOTE_FULL_REARM_OUTSTANDING_GLOBAL, Math.max(1, Math.floor(deps.maxRemoteFullRearmOutstandingGlobal ??
87
+ MAX_REMOTE_FULL_REARM_OUTSTANDING_GLOBAL)));
70
88
  this._receiveStates = new Map();
71
89
  this._cutoverPeerSessions = new WeakSet();
72
90
  this._localCapabilityReadyBySession = new WeakMap();
73
91
  this._localCapabilityContextBySession = new WeakMap();
74
92
  this._localCapabilityAdvertisementsByPeer = new Map();
75
93
  this._remoteFullRearmBySession = new WeakMap();
94
+ this._remoteFullRearmsInFlight = new Set();
95
+ this._remoteFullRearmOutstanding = new Set();
76
96
  this._reservedAdmissionsByPeer = new Map();
77
97
  }
78
98
  resetForOpen() {
@@ -83,9 +103,14 @@ export class ReplicationInfoV2ReceiveCoordinator {
83
103
  this._localCapabilityContextBySession = new WeakMap();
84
104
  this._localCapabilityAdvertisementsByPeer = new Map();
85
105
  this._remoteFullRearmBySession = new WeakMap();
106
+ this._remoteFullRearmsInFlight = new Set();
86
107
  this._reservedAdmissionsByPeer = new Map();
87
108
  }
88
109
  clearForClose() {
110
+ for (const rearm of this._remoteFullRearmsInFlight ?? []) {
111
+ rearm.controller?.abort(new Error("Replication-info V2 receiver closed during remote Full rearm"));
112
+ }
113
+ this._remoteFullRearmsInFlight?.clear();
89
114
  for (const advertisement of [
90
115
  ...(this._localCapabilityAdvertisementsByPeer?.values() ?? []),
91
116
  ]) {
@@ -114,10 +139,23 @@ export class ReplicationInfoV2ReceiveCoordinator {
114
139
  this._localCapabilityContextBySession.delete(state.peerSession);
115
140
  this._cutoverPeerSessions.delete(state.peerSession);
116
141
  }
142
+ if (!expectedSession) {
143
+ for (const rearm of this._remoteFullRearmsInFlight) {
144
+ if (rearm.peerHash === peerHash) {
145
+ rearm.controller?.abort(new Error("Replication-info V2 peer cleared during rearm"));
146
+ }
147
+ }
148
+ }
149
+ const rearmSession = expectedSession ?? state?.peerSession ?? advertisement?.peerSession;
150
+ if (rearmSession) {
151
+ this._remoteFullRearmBySession
152
+ .get(rearmSession)
153
+ ?.controller?.abort(new Error("Replication-info V2 peer session cleared during rearm"));
154
+ this._remoteFullRearmBySession.delete(rearmSession);
155
+ }
117
156
  if (expectedSession) {
118
157
  this._localCapabilityReadyBySession.delete(expectedSession);
119
158
  this._localCapabilityContextBySession.delete(expectedSession);
120
- this._remoteFullRearmBySession.delete(expectedSession);
121
159
  this._cutoverPeerSessions.delete(expectedSession);
122
160
  }
123
161
  }
@@ -388,9 +426,14 @@ export class ReplicationInfoV2ReceiveCoordinator {
388
426
  * stream that was lost while both directions otherwise remained current.
389
427
  *
390
428
  * This deliberately does not mutate the steady advertisement worker. One
391
- * attempt is coalesced per PeerSession and bound to the caller's signal; the
392
- * readiness wait's bounded recovery tick decides whether another attempt is
393
- * needed.
429
+ * attempt is coalesced per exact PeerSession/receive generation and bound to
430
+ * its own deadline as well as the caller's signal. A cooldown avoids rotating
431
+ * a healthy in-flight challenge on every recovery tick. The remote rotates
432
+ * only when its receive state is active; later hints during resync only nudge
433
+ * that same bounded request generation. At most two transports that disregard
434
+ * abort remain outstanding for one exact session (64 across this coordinator's
435
+ * lifetime); reaching either cap stops new hints while the persisted-readiness
436
+ * gate remains fail closed.
394
437
  */
395
438
  reAdvertiseLocalCapabilityForRemoteFull(properties) {
396
439
  const context = this._localCapabilityContextBySession.get(properties.peerSession);
@@ -408,33 +451,69 @@ export class ReplicationInfoV2ReceiveCoordinator {
408
451
  return false;
409
452
  }
410
453
  const now = this.now();
454
+ const receiverTransportSession = ready.receiverTransportSession;
411
455
  let rearm = this._remoteFullRearmBySession.get(properties.peerSession);
456
+ if (rearm &&
457
+ (rearm.peerHash !== properties.peerHash ||
458
+ rearm.receiveEpoch !== properties.receiveEpoch ||
459
+ rearm.receiverTransportSession !== receiverTransportSession)) {
460
+ rearm.controller?.abort(new Error("Replication-info V2 remote Full rearm generation changed"));
461
+ rearm = undefined;
462
+ }
412
463
  if (rearm?.inFlight) {
413
464
  return true;
414
465
  }
415
- if (rearm !== undefined &&
416
- now - rearm.lastAttemptAt < this.requestRetryMs) {
466
+ if (rearm !== undefined && now < rearm.nextAttemptAt) {
467
+ return true;
468
+ }
469
+ if ((rearm?.outstandingAttempts ?? 0) >=
470
+ MAX_REMOTE_FULL_REARM_OUTSTANDING_PER_SESSION ||
471
+ this._remoteFullRearmOutstanding.size >=
472
+ this.maxRemoteFullRearmOutstandingGlobal) {
417
473
  return true;
418
474
  }
419
475
  if (!rearm) {
420
- rearm = { lastAttemptAt: now };
476
+ rearm = {
477
+ peerHash: properties.peerHash,
478
+ receiveEpoch: properties.receiveEpoch,
479
+ receiverTransportSession,
480
+ nextAttemptAt: now + this.remoteFullRearmCooldownMs,
481
+ attemptsStarted: 0,
482
+ outstandingAttempts: 0,
483
+ };
421
484
  this._remoteFullRearmBySession.set(properties.peerSession, rearm);
422
485
  }
423
486
  else {
424
- rearm.lastAttemptAt = now;
425
- }
426
- const operationSignal = AbortSignal.any([
427
- context.lifecycleSignal,
428
- properties.signal,
429
- ]);
430
- let operation;
431
- const detach = () => {
432
- if (rearm?.inFlight === operation) {
433
- rearm.inFlight = undefined;
434
- }
487
+ rearm.nextAttemptAt = now + this.remoteFullRearmCooldownMs;
488
+ }
489
+ const attemptState = rearm;
490
+ const outstandingReservation = {};
491
+ attemptState.attemptsStarted = Math.min(MAX_REMOTE_FULL_REARM_OUTSTANDING_GLOBAL, attemptState.attemptsStarted + 1);
492
+ attemptState.outstandingAttempts++;
493
+ this._remoteFullRearmOutstanding.add(outstandingReservation);
494
+ const attemptController = new AbortController();
495
+ const operationSignal = attemptController.signal;
496
+ attemptState.controller = attemptController;
497
+ this._remoteFullRearmsInFlight.add(attemptState);
498
+ const sourceSignals = Array.from(new Set([context.lifecycleSignal, properties.signal]));
499
+ const onSourceAbort = (event) => {
500
+ const source = event.currentTarget;
501
+ attemptController.abort(source.reason);
502
+ };
503
+ for (const source of sourceSignals) {
504
+ source.addEventListener("abort", onSourceAbort, { once: true });
505
+ }
506
+ const attemptTimer = setTimeout(() => attemptController.abort(new Error("Replication-info V2 remote Full rearm attempt timed out")), this.remoteFullRearmAttemptTimeoutMs);
507
+ attemptTimer.unref?.();
508
+ let releasedOutstanding = false;
509
+ const releaseOutstanding = () => {
510
+ if (releasedOutstanding)
511
+ return;
512
+ releasedOutstanding = true;
513
+ this._remoteFullRearmOutstanding.delete(outstandingReservation);
514
+ attemptState.outstandingAttempts--;
435
515
  };
436
- operation = Promise.resolve()
437
- .then(() => {
516
+ const refresh = Promise.resolve().then(() => {
438
517
  if (operationSignal.aborted) {
439
518
  throw operationSignal.reason;
440
519
  }
@@ -446,7 +525,40 @@ export class ReplicationInfoV2ReceiveCoordinator {
446
525
  signal: operationSignal,
447
526
  requestRemoteFullRearm: true,
448
527
  });
449
- })
528
+ });
529
+ void refresh.then(releaseOutstanding, releaseOutstanding);
530
+ let operation;
531
+ const detach = () => {
532
+ clearTimeout(attemptTimer);
533
+ operationSignal.removeEventListener("abort", detach);
534
+ for (const source of sourceSignals) {
535
+ source.removeEventListener("abort", onSourceAbort);
536
+ }
537
+ if (attemptState.inFlight === operation) {
538
+ this._remoteFullRearmsInFlight.delete(attemptState);
539
+ attemptState.inFlight = undefined;
540
+ attemptState.controller = undefined;
541
+ }
542
+ };
543
+ const raceWithAttemptSignal = (promise) => new Promise((resolve, reject) => {
544
+ const onAbort = () => {
545
+ operationSignal.removeEventListener("abort", onAbort);
546
+ reject(operationSignal.reason);
547
+ };
548
+ operationSignal.addEventListener("abort", onAbort, { once: true });
549
+ if (operationSignal.aborted) {
550
+ onAbort();
551
+ return;
552
+ }
553
+ promise.then((value) => {
554
+ operationSignal.removeEventListener("abort", onAbort);
555
+ resolve(value);
556
+ }, (error) => {
557
+ operationSignal.removeEventListener("abort", onAbort);
558
+ reject(error);
559
+ });
560
+ });
561
+ operation = raceWithAttemptSignal(refresh)
450
562
  .then(() => undefined)
451
563
  .catch((error) => {
452
564
  if (!operationSignal.aborted &&
@@ -456,17 +568,152 @@ export class ReplicationInfoV2ReceiveCoordinator {
456
568
  }
457
569
  })
458
570
  .finally(() => {
459
- operationSignal.removeEventListener("abort", detach);
460
571
  detach();
461
572
  });
462
- rearm.inFlight = operation;
573
+ attemptState.inFlight = operation;
463
574
  operationSignal.addEventListener("abort", detach, { once: true });
464
- if (operationSignal.aborted) {
465
- detach();
575
+ for (const source of sourceSignals) {
576
+ if (source.aborted) {
577
+ attemptController.abort(source.reason);
578
+ break;
579
+ }
466
580
  }
467
581
  void operation;
468
582
  return true;
469
583
  }
584
+ /**
585
+ * Bounded, read-only state for persisted-readiness troubleshooting. This
586
+ * intentionally omits transport sessions, challenges, payloads, and maps.
587
+ */
588
+ diagnosePeer(properties) {
589
+ const state = this._receiveStates.get(properties.peerHash);
590
+ const advertisement = this._localCapabilityAdvertisementsByPeer.get(properties.peerHash);
591
+ const session = properties.peerSession ??
592
+ state?.peerSession ??
593
+ advertisement?.peerSession;
594
+ const ready = session
595
+ ? this._localCapabilityReadyBySession.get(session)
596
+ : undefined;
597
+ let capabilityAdvertisement = "absent";
598
+ if (ready && ready.peerHash === properties.peerHash) {
599
+ capabilityAdvertisement =
600
+ session !== undefined &&
601
+ this.deps.isPeerSessionCurrent(properties.peerHash, session) &&
602
+ this.deps.isReceiveEpochCurrent(properties.peerHash, ready.receiveEpoch) &&
603
+ ready.receiverTransportSession ===
604
+ this.deps.getReceiverTransportSession() &&
605
+ (properties.receiveEpoch === undefined ||
606
+ ready.receiveEpoch === properties.receiveEpoch)
607
+ ? "ready"
608
+ : "stale";
609
+ }
610
+ else if (advertisement) {
611
+ capabilityAdvertisement =
612
+ advertisement.peerHash === properties.peerHash &&
613
+ advertisement.peerSession === session &&
614
+ (properties.receiveEpoch === undefined ||
615
+ advertisement.receiveEpoch === properties.receiveEpoch) &&
616
+ this.isLocalCapabilityAdvertisementGenerationCurrent(advertisement)
617
+ ? "advertising"
618
+ : "stale";
619
+ }
620
+ const rearm = session
621
+ ? this._remoteFullRearmBySession.get(session)
622
+ : undefined;
623
+ const now = this.now();
624
+ const rearmLimited = (rearm?.outstandingAttempts ?? 0) >=
625
+ MAX_REMOTE_FULL_REARM_OUTSTANDING_PER_SESSION ||
626
+ this._remoteFullRearmOutstanding.size >=
627
+ this.maxRemoteFullRearmOutstandingGlobal;
628
+ const rearmStatus = rearm?.inFlight
629
+ ? "in-flight"
630
+ : rearmLimited
631
+ ? "limited"
632
+ : rearm && now < rearm.nextAttemptAt
633
+ ? "cooldown"
634
+ : "idle";
635
+ const common = {
636
+ capabilityAdvertisementAttempts: Math.min(MAX_BACKOFF_EXPONENT + 1, Math.max(0, advertisement?.attempts ?? 0)),
637
+ capabilityAdvertisement,
638
+ remoteFullRearm: rearmStatus,
639
+ remoteFullRearmAttempts: Math.min(MAX_REMOTE_FULL_REARM_OUTSTANDING_GLOBAL, Math.max(0, rearm?.attemptsStarted ?? 0)),
640
+ remoteFullRearmOutstanding: Math.min(MAX_REMOTE_FULL_REARM_OUTSTANDING_PER_SESSION, Math.max(0, rearm?.outstandingAttempts ?? 0)),
641
+ remoteFullRearmGlobalOutstanding: Math.min(this.maxRemoteFullRearmOutstandingGlobal, this._remoteFullRearmOutstanding.size),
642
+ ...(rearm && now < rearm.nextAttemptAt
643
+ ? {
644
+ remoteFullRearmCooldownRemainingMs: Math.min(MAX_TIMER_MS, Math.max(0, rearm.nextAttemptAt - now)),
645
+ }
646
+ : {}),
647
+ };
648
+ if (!state) {
649
+ return Object.freeze({
650
+ state: "absent",
651
+ reason: "state-absent",
652
+ ...common,
653
+ });
654
+ }
655
+ let status = "current";
656
+ let reason;
657
+ if (properties.peerSession !== undefined &&
658
+ state.peerSession !== properties.peerSession) {
659
+ status = "stale";
660
+ reason = "peer-session-mismatch";
661
+ }
662
+ else if (properties.receiveEpoch !== undefined &&
663
+ state.receiveEpoch !== properties.receiveEpoch) {
664
+ status = "stale";
665
+ reason = "receive-epoch-mismatch";
666
+ }
667
+ else if (properties.senderTransportSession !== undefined &&
668
+ state.senderTransportSession !== properties.senderTransportSession) {
669
+ status = "stale";
670
+ reason = "transport-session-mismatch";
671
+ }
672
+ else if (!this.isStateCurrent(state)) {
673
+ status = "stale";
674
+ reason = "state-not-current";
675
+ }
676
+ else if (state.reservedAdmission !== undefined ||
677
+ this._reservedAdmissionsByPeer.has(properties.peerHash)) {
678
+ reason = "admission-pending";
679
+ }
680
+ else if (state.phase === "active") {
681
+ reason = "active";
682
+ }
683
+ else if (state.requestParked) {
684
+ reason = "request-parked";
685
+ }
686
+ else if (state.requestInFlight !== undefined) {
687
+ reason = "request-in-flight";
688
+ }
689
+ else if (state.requestTimer !== undefined) {
690
+ reason = "request-scheduled";
691
+ }
692
+ else {
693
+ reason = state.phase;
694
+ }
695
+ const requestState = state.reservedAdmission !== undefined ||
696
+ this._reservedAdmissionsByPeer.has(properties.peerHash)
697
+ ? "admission-pending"
698
+ : state.requestParked
699
+ ? "parked"
700
+ : state.requestInFlight !== undefined
701
+ ? "in-flight"
702
+ : state.requestTimer !== undefined
703
+ ? "scheduled"
704
+ : "idle";
705
+ return Object.freeze({
706
+ state: status,
707
+ reason,
708
+ phase: state.phase,
709
+ requestState,
710
+ ...(state.lastSequence === undefined
711
+ ? {}
712
+ : { lastAppliedSequence: state.lastSequence.toString() }),
713
+ requestAttempts: Math.min(this.requestMaxAttempts, Math.max(0, state.requestAttempts)),
714
+ ...common,
715
+ });
716
+ }
470
717
  promoteLocalCapabilityAdvertisement(state) {
471
718
  const ready = state.acknowledgedReady;
472
719
  if (state.ready ||