querysub 0.610.0 → 0.612.0
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
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "querysub",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.612.0",
|
|
4
4
|
"main": "index.js",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"note1": "note on node-forge fork, see https://github.com/digitalbazaar/forge/issues/744 for details",
|
|
@@ -75,7 +75,7 @@
|
|
|
75
75
|
"node-forge": "https://github.com/sliftist/forge#e618181b469b07bdc70b968b0391beb8ef5fecd6",
|
|
76
76
|
"pako": "^2.1.0",
|
|
77
77
|
"peggy": "^5.0.6",
|
|
78
|
-
"sliftutils": "^1.7.
|
|
78
|
+
"sliftutils": "^1.7.85",
|
|
79
79
|
"socket-function": "^1.2.30",
|
|
80
80
|
"terser": "^5.31.0",
|
|
81
81
|
"typenode": "^6.6.1",
|
|
@@ -24,7 +24,7 @@ import { logDisk } from "../diagnostics/logs/diskLogger";
|
|
|
24
24
|
import { MaybePromise } from "socket-function/src/types";
|
|
25
25
|
import { getPathStr2 } from "../path";
|
|
26
26
|
|
|
27
|
-
let HEARTBEAT_INTERVAL = timeInMinute *
|
|
27
|
+
let HEARTBEAT_INTERVAL = timeInMinute * 1;
|
|
28
28
|
// Interval which we check other heartbeats
|
|
29
29
|
let CHECK_INTERVAL = HEARTBEAT_INTERVAL;
|
|
30
30
|
// If the heartbeat is older than thing, it fails the dead check
|
|
@@ -34,7 +34,7 @@ let DEAD_THRESHOLD = HEARTBEAT_INTERVAL * 2;
|
|
|
34
34
|
let DEAD_CHECK_COUNT = 4;
|
|
35
35
|
// If we find we are unable to write our heartbeat, we have to kill our own process. Otherwise it may
|
|
36
36
|
// be too out of sync, and might commit unverified data to the disk.
|
|
37
|
-
let SUICIDE_HEARTBEAT_THRESHOLD = HEARTBEAT_INTERVAL * 4;
|
|
37
|
+
let SUICIDE_HEARTBEAT_THRESHOLD = Math.max(timeInMinute * 10, HEARTBEAT_INTERVAL * 4);
|
|
38
38
|
|
|
39
39
|
let CLIENTSIDE_POLL_RATE = timeInMinute * 30;
|
|
40
40
|
|
|
@@ -56,6 +56,7 @@ let DEAD_NODE_POLL_COOLDOWN = timeInMinute * 5;
|
|
|
56
56
|
|
|
57
57
|
let shutdown = false;
|
|
58
58
|
|
|
59
|
+
// NOTE: It's not really required to use buffered archives for this. Previously, our heartbeat interval was five minutes and we could raise it again to five minutes. However, keeping it fast means that if our buffered archives has bugs, we'll notice it pretty quickly because if files disappear, for example, if our node discovery file disappears, processes will terminate themselves, which makes it really obvious that there's a problem, and files should never disappear. So it's kind of a canary to say, hey, there's something wrong with our storage, we need to fix it. Even if one node goes away, its writes should have already been propagated.
|
|
59
60
|
const archives = lazy(() => getArchives2Buffered("nodes/"));
|
|
60
61
|
|
|
61
62
|
let logging = true;
|
|
@@ -26,6 +26,8 @@ import { getGitRefLive, getGitURLLive } from "./git";
|
|
|
26
26
|
import { DeployProgress } from "./deployFunctions";
|
|
27
27
|
import { PromiseObj } from "../promise";
|
|
28
28
|
import type { FunctionRunnerIndex } from "../4-querysub/FunctionRunnerTracking";
|
|
29
|
+
import { isDefined } from "sliftutils/misc/types";
|
|
30
|
+
|
|
29
31
|
const UPDATE_POLL_INTERVAL = timeInMinute * 15;
|
|
30
32
|
const HEARTBEAT_INTERVAL = timeInMinute;
|
|
31
33
|
const EDGE_NODE_DELETE_THRESHOLD = timeInMinute * 15;
|
|
@@ -34,11 +36,8 @@ const EDGE_NODE_READ_PARALLEL = 64;
|
|
|
34
36
|
export const edgeNodeStorage = isNodeTrue() && getArchives2BufferedPublic("edgenodes2/");
|
|
35
37
|
export const edgeNodeIndexFile = "edge-nodes-index.json";
|
|
36
38
|
|
|
37
|
-
let registeredNodePaths = new Set<string>();
|
|
38
39
|
function getNextNodePath() {
|
|
39
|
-
|
|
40
|
-
registeredNodePaths.add(path);
|
|
41
|
-
return path;
|
|
40
|
+
return "node0_" + getOwnNodeId();
|
|
42
41
|
}
|
|
43
42
|
|
|
44
43
|
let edgeShutdown = false;
|
|
@@ -94,6 +93,7 @@ declare global {
|
|
|
94
93
|
var EDGE_NODE_STATS: EdgeNodeStats | undefined;
|
|
95
94
|
}
|
|
96
95
|
let registeredEdgeNode: { host: string; entryPaths: string[] } | boolean | undefined;
|
|
96
|
+
let lastEdgeNodeConfig: EdgeNodeConfig | undefined;
|
|
97
97
|
export async function registerEdgeNode(config: {
|
|
98
98
|
host: string;
|
|
99
99
|
entryPaths: string[];
|
|
@@ -114,9 +114,7 @@ export async function registerEdgeNode(config: {
|
|
|
114
114
|
registerShutdownHandler(async () => {
|
|
115
115
|
edgeShutdown = true;
|
|
116
116
|
console.log(magenta(`Removing node from edge node list due to shutdown`));
|
|
117
|
-
await
|
|
118
|
-
await edgeNodeStorage.del(nodePath);
|
|
119
|
-
}));
|
|
117
|
+
await edgeNodeStorage.del(getNextNodePath());
|
|
120
118
|
await updateEdgeNodesFile();
|
|
121
119
|
});
|
|
122
120
|
const { watchScheduledShutdown } = await import("../-g-core-values/scheduledShutdown");
|
|
@@ -128,9 +126,7 @@ export async function registerEdgeNode(config: {
|
|
|
128
126
|
// Wait a bit to fully remove ourself from the edge node list
|
|
129
127
|
await delay(Math.max(0, duration * 0.2));
|
|
130
128
|
console.log(magenta(`Removing node from edge node list due to scheduled shutdown at ${new Date(time).toLocaleString()}`));
|
|
131
|
-
await
|
|
132
|
-
await edgeNodeStorage.del(nodePath);
|
|
133
|
-
}));
|
|
129
|
+
await edgeNodeStorage.del(getNextNodePath());
|
|
134
130
|
await updateEdgeNodesFile();
|
|
135
131
|
})();
|
|
136
132
|
});
|
|
@@ -177,7 +173,7 @@ export async function registerEdgeNode(config: {
|
|
|
177
173
|
public: isPublic(),
|
|
178
174
|
functionRunnerIndex: await getInitialFunctionRunnerIndex(),
|
|
179
175
|
};
|
|
180
|
-
|
|
176
|
+
lastEdgeNodeConfig = edgeNodeConfig;
|
|
181
177
|
await edgeNodeStorage.set(getNextNodePath(), Buffer.from(JSON.stringify(edgeNodeConfig)));
|
|
182
178
|
}
|
|
183
179
|
registeredEdgeNode = {
|
|
@@ -229,6 +225,7 @@ const loadEntryPointsByHash = runInSerial(async function loadEntryPointsByHash(c
|
|
|
229
225
|
public: isPublic(),
|
|
230
226
|
functionRunnerIndex: await getInitialFunctionRunnerIndex(),
|
|
231
227
|
};
|
|
228
|
+
lastEdgeNodeConfig = edgeNodeConfig;
|
|
232
229
|
|
|
233
230
|
await edgeNodeStorage.set(getNextNodePath(), Buffer.from(JSON.stringify(edgeNodeConfig)));
|
|
234
231
|
console.log(magenta(`Registered edge node`), edgeNodeConfig);
|
|
@@ -245,14 +242,9 @@ async function getInitialFunctionRunnerIndex(): Promise<FunctionRunnerIndex | un
|
|
|
245
242
|
}
|
|
246
243
|
|
|
247
244
|
async function publishOwnScheduledShutdown(time: number) {
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
let config: EdgeNodeConfig = JSON.parse(buffer.toString());
|
|
252
|
-
if (config.scheduledShutdownTime === time) continue;
|
|
253
|
-
config.scheduledShutdownTime = time;
|
|
254
|
-
await edgeNodeStorage.set(nodePath, Buffer.from(JSON.stringify(config)));
|
|
255
|
-
}
|
|
245
|
+
if (!lastEdgeNodeConfig) return;
|
|
246
|
+
lastEdgeNodeConfig.scheduledShutdownTime = time;
|
|
247
|
+
await edgeNodeStorage.set(getNextNodePath(), Buffer.from(JSON.stringify(lastEdgeNodeConfig)));
|
|
256
248
|
await updateEdgeNodesFile();
|
|
257
249
|
}
|
|
258
250
|
|
|
@@ -271,12 +263,10 @@ const startUpdateLoop = lazy(async () => {
|
|
|
271
263
|
|
|
272
264
|
async function heartbeatLoop() {
|
|
273
265
|
if (edgeShutdown) return;
|
|
266
|
+
if (!lastEdgeNodeConfig) return;
|
|
274
267
|
let nodePath = getNextNodePath();
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
let config: EdgeNodeConfig = JSON.parse(buffer.toString());
|
|
278
|
-
config.heartbeatTime = Date.now();
|
|
279
|
-
await edgeNodeStorage.set(nodePath, Buffer.from(JSON.stringify(config)));
|
|
268
|
+
lastEdgeNodeConfig.heartbeatTime = Date.now();
|
|
269
|
+
await edgeNodeStorage.set(nodePath, Buffer.from(JSON.stringify(lastEdgeNodeConfig)));
|
|
280
270
|
// Push the fresh heartbeat into the index so clients see it (they read only the index, not the per-node files).
|
|
281
271
|
await updateEdgeNodesFile();
|
|
282
272
|
}
|
|
@@ -287,7 +277,6 @@ async function updateLoop() {
|
|
|
287
277
|
}
|
|
288
278
|
|
|
289
279
|
async function updateEdgeNodesFile() {
|
|
290
|
-
// Snapshot the time BEFORE reading anything below. Staleness is judged against when we STARTED, so if the reads block we can never mass-evict live nodes just because wall-clock advanced while we were stuck.
|
|
291
280
|
let now = Date.now();
|
|
292
281
|
|
|
293
282
|
let prevEdgeNodeFile = await edgeNodeStorage.get(edgeNodeIndexFile);
|
|
@@ -318,7 +307,6 @@ async function updateEdgeNodesFile() {
|
|
|
318
307
|
let edgeNodeFiles = await edgeNodeStorage.find("node", { type: "files" });
|
|
319
308
|
// Reads are independent, so run them in parallel (bounded): with many files a serial pass would take files × read-latency, which could be minutes.
|
|
320
309
|
let readEdgeNodeFile = runInParallel({ parallelCount: EDGE_NODE_READ_PARALLEL }, async (nodeFile: string) => {
|
|
321
|
-
// Read directly, not through a cache: heartbeatTime mutates every minute, so a cached config would report a stale heartbeat and wrongly evict a live peer.
|
|
322
310
|
let buffer = await edgeNodeStorage.get(nodeFile);
|
|
323
311
|
if (!buffer) return undefined;
|
|
324
312
|
let config: EdgeNodeConfig = JSON.parse(buffer.toString());
|
|
@@ -330,19 +318,9 @@ async function updateEdgeNodesFile() {
|
|
|
330
318
|
}
|
|
331
319
|
return config;
|
|
332
320
|
});
|
|
333
|
-
let configs = await Promise.all(edgeNodeFiles.map(readEdgeNodeFile));
|
|
334
|
-
|
|
335
|
-
let bestByNodeId = new Map<string, EdgeNodeConfig>();
|
|
336
|
-
for (let config of configs) {
|
|
337
|
-
if (!config) continue;
|
|
338
|
-
// One entry per nodeId (re-registrations can leave more than one), keeping the freshest heartbeat.
|
|
339
|
-
let existing = bestByNodeId.get(config.nodeId);
|
|
340
|
-
if (!existing || (config.heartbeatTime || config.bootTime) > (existing.heartbeatTime || existing.bootTime)) {
|
|
341
|
-
bestByNodeId.set(config.nodeId, config);
|
|
342
|
-
}
|
|
343
|
-
}
|
|
321
|
+
let configs = (await Promise.all(edgeNodeFiles.map(readEdgeNodeFile))).filter(isDefined);
|
|
344
322
|
|
|
345
|
-
let newEdgeNodes = sort(
|
|
323
|
+
let newEdgeNodes = sort(configs, x => -(x.heartbeatTime || x.bootTime));
|
|
346
324
|
let newEdgeNodeIndex: EdgeNodesIndex = {
|
|
347
325
|
edgeNodes: newEdgeNodes,
|
|
348
326
|
liveHash,
|