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/package.json +5 -2
- package/rpc/handlers.js +9 -0
- package/rpc/routes/v1.js +2 -0
- package/scripts/hypercore-stallfix/apply.mjs +199 -0
- package/scripts/hypercore-stallfix/hypercore-11.18.3.mjs +434 -0
- package/scripts/hypercore-stallfix/hypercore-11.8.3.mjs +348 -0
- package/src/config/config.js +10 -0
- package/src/config/env.js +6 -0
- package/src/core/network/services/ReplicationStallGuard.js +177 -0
- package/src/core/state/ConfirmationWatch.js +82 -0
- package/src/core/state/State.js +5 -0
- package/src/index.js +28 -0
- package/src/utils/hypercoreStallfix.js +53 -0
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
|
+
}
|