trac-msb 0.2.24 → 0.2.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/src/index.js CHANGED
@@ -29,6 +29,8 @@ import {safeDecodeApplyOperation, safeEncodeApplyOperation} from "./utils/protob
29
29
  import PartialTransactionValidator from "./core/network/protocols/shared/validators/PartialTransactionValidator.js";
30
30
  import PartialTransferValidator from "./core/network/protocols/shared/validators/PartialTransferValidator.js";
31
31
  import { BroadcastError, ValidationError } from "./utils/errors.js";
32
+ import { ReplicationStallGuard } from "./core/network/services/ReplicationStallGuard.js";
33
+ import { hypercoreStallfixLine, hypercoreStallfixStatus } from "./utils/hypercoreStallfix.js";
32
34
 
33
35
  export class MainSettlementBus extends ReadyResource {
34
36
  #store;
@@ -37,6 +39,7 @@ export class MainSettlementBus extends ReadyResource {
37
39
  #state;
38
40
  #isClosing = false;
39
41
  #config
42
+ #replicationGuard = null;
40
43
 
41
44
  /**
42
45
  * @param {import("./config/config.js").Config} config
@@ -87,6 +90,13 @@ export class MainSettlementBus extends ReadyResource {
87
90
  this.#wallet,
88
91
  );
89
92
 
93
+ console.log(hypercoreStallfixLine('MSB', this.#state.base.core));
94
+ this.#replicationGuard = new ReplicationStallGuard(this.#state.base, () => this.#network?.swarm ?? null, {
95
+ timeout: this.#config.replicationStallTimeout,
96
+ refresh: () => this.#network?.swarm?.status?.(this.#config.channel)?.refresh?.()
97
+ });
98
+ this.#replicationGuard.start();
99
+
90
100
  const adminEntry = await this.#state.getAdminEntry();
91
101
  await this.#setUpRoleAutomatically(adminEntry);
92
102
 
@@ -106,6 +116,7 @@ export class MainSettlementBus extends ReadyResource {
106
116
  console.log("Closing everything gracefully... This may take a moment.");
107
117
 
108
118
  this.#isClosing = true;
119
+ this.#replicationGuard?.stop();
109
120
  await this.#network.close();
110
121
 
111
122
  await sleep(100);
@@ -121,6 +132,18 @@ export class MainSettlementBus extends ReadyResource {
121
132
  await sleep(100);
122
133
  }
123
134
 
135
+ /**
136
+ * Replication health: whether the loaded Hypercore carries the stall fix, and the stall guard state
137
+ * ('ok' | 'behind' | 'stalled'). Read-only.
138
+ */
139
+ replicationStatus() {
140
+ return {
141
+ hypercoreStallfix: hypercoreStallfixStatus(this.#state?.base?.core, this.#store),
142
+ stall: this.#replicationGuard?.status() ?? null,
143
+ connections: this.#network?.swarm?.connections?.size ?? 0
144
+ };
145
+ }
146
+
124
147
  async destroy() {
125
148
  return await this.close();
126
149
  }
@@ -316,6 +339,11 @@ export class MainSettlementBus extends ReadyResource {
316
339
  console.log("---------- flags ----------");
317
340
  console.log(`isIndexer: ${this.#state?.isIndexer?.() ?? "unset"}`);
318
341
  console.log(`isWriter: ${this.#state?.isWritable?.() ?? "unset"}`);
342
+ const replication = this.replicationStatus();
343
+ console.log("---------- replication ----------");
344
+ console.log(`hypercoreStallfix: ${replication.hypercoreStallfix.patched ? replication.hypercoreStallfix.marker : "NOT ACTIVE"}` +
345
+ ` (expired requests: ${replication.hypercoreStallfix.expiredRequests ?? "n/a"}, timed pauses: ${replication.hypercoreStallfix.invalidOperationPauses ?? "n/a"})`);
346
+ console.log(`replicationStall: ${replication.stall?.state ?? "off"} (reconnects: ${replication.stall?.reconnects ?? 0})`);
319
347
  } catch (error) {
320
348
  console.error("Error during DAG monitoring:", error.message);
321
349
  }
@@ -0,0 +1,53 @@
1
+ // Runtime view of the install-time Hypercore patch (scripts/hypercore-stallfix/). It looks at the Replicator class
2
+ // of a live core, so it reports the Hypercore copy that is actually loaded, not the one npm resolution suggests.
3
+ export const HYPERCORE_STALLFIX_MARKER = 'openmayhem-stallfix-v2';
4
+
5
+ /**
6
+ * @param {object} core a Hypercore session (for MSB: state.base.core, the system view)
7
+ * @param {object|null} store optional Corestore; when given, request counters are summed over its open cores
8
+ */
9
+ export function hypercoreStallfixStatus(core, store = null) {
10
+ const Replicator = core?.core?.replicator?.constructor ?? null;
11
+ const marker = typeof Replicator?.STALLFIX === 'string' ? Replicator.STALLFIX : null;
12
+ const status = {
13
+ patched: marker === HYPERCORE_STALLFIX_MARKER,
14
+ marker,
15
+ expiredRequests: null,
16
+ notAvailableSent: null,
17
+ notAvailableSuppressed: null,
18
+ invalidOperationPauses: null,
19
+ invalidOperationPermanent: null
20
+ };
21
+ if (marker === null) return status;
22
+
23
+ let expired = 0;
24
+ let sent = 0;
25
+ let suppressed = 0;
26
+ let opPauses = 0;
27
+ let opPermanent = 0;
28
+ const cores = store?.cores?.map;
29
+ const list = cores && typeof cores.values === 'function' ? cores.values() : [core.core];
30
+ for (const c of list) {
31
+ const stats = c?.replicator?._sfStats;
32
+ if (!stats) continue;
33
+ expired += stats.expired;
34
+ sent += stats.notAvailableSent;
35
+ suppressed += stats.notAvailableSuppressed;
36
+ opPauses += stats.invalidOperationPauses ?? 0; // 11.18.3 only (11.8.3 never pauses on INVALID_OPERATION)
37
+ opPermanent += stats.invalidOperationPermanent ?? 0;
38
+ }
39
+ status.expiredRequests = expired;
40
+ status.notAvailableSent = sent;
41
+ status.notAvailableSuppressed = suppressed;
42
+ status.invalidOperationPauses = opPauses;
43
+ status.invalidOperationPermanent = opPermanent;
44
+ return status;
45
+ }
46
+
47
+ /** One startup line for logs/alerts. */
48
+ export function hypercoreStallfixLine(label, core) {
49
+ const { patched, marker } = hypercoreStallfixStatus(core);
50
+ if (patched) return `[${label}] Hypercore replication stall fix: active (${marker}); closed-stream guard #911 active`;
51
+ return `[${label}] WARNING: Hypercore replication stall fix NOT active in the loaded hypercore` +
52
+ ` (marker: ${marker ?? 'none'}). Reinstall without --ignore-scripts or run scripts/hypercore-stallfix/apply.mjs.`;
53
+ }