querysub 0.611.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.611.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.84",
78
+ "sliftutils": "^1.7.85",
79
79
  "socket-function": "^1.2.30",
80
80
  "terser": "^5.31.0",
81
81
  "typenode": "^6.6.1",
@@ -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
- let path = "node0_" + getOwnNodeId();
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 Promise.all(Array.from(registeredNodePaths).map(async nodePath => {
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 Promise.all(Array.from(registeredNodePaths).map(async nodePath => {
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
- for (let nodePath of Array.from(registeredNodePaths)) {
249
- let buffer = await edgeNodeStorage.get(nodePath);
250
- if (!buffer) continue;
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
- let buffer = await edgeNodeStorage.get(nodePath);
276
- if (!buffer) return;
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(Array.from(bestByNodeId.values()), x => -(x.heartbeatTime || x.bootTime));
323
+ let newEdgeNodes = sort(configs, x => -(x.heartbeatTime || x.bootTime));
346
324
  let newEdgeNodeIndex: EdgeNodesIndex = {
347
325
  edgeNodes: newEdgeNodes,
348
326
  liveHash,