querysub 0.677.0 → 0.679.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.677.0",
3
+ "version": "0.679.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",
package/src/config.ts CHANGED
@@ -32,8 +32,8 @@ let yargObj = parseArgsFactory()
32
32
  })
33
33
  .option("logbackblaze", { type: "boolean", desc: "Log all backblaze activity to disk." })
34
34
  .option("slowdown", { type: "number", desc: "Delay all input data values by this amount of time, pretending like we didn't even receive it until this time is up." })
35
- .option("network", { type: "array", desc: `The networks this node is on (pass multiple arguments to be on multiple, ex: --network test --network default). Authorities only satisfy paths on their networks ("default" if unset). Function calls are put on the first network in the list. If no FunctionRunner is on a call's network, the call will fail to run.` })
36
- .option("networkfile", { type: "string", desc: `The same as --network, except the networks are read from the given file (one per line). Supports "~/" for the home directory. If the file doesn't exist, the process exits with an error.` })
35
+ .option("network", { type: "array", desc: `The networks this node is on (pass multiple arguments to be on multiple, ex: --network test --network default, or comma separate them: --network test,default). Authorities only satisfy paths on their networks ("default" if unset). Function calls are put on the first network in the list. If no FunctionRunner is on a call's network, the call will fail to run.` })
36
+ .option("networkfile", { type: "string", desc: `The same as --network, except the networks are read from the given file (one per line, and commas separate as well). Supports "~/" for the home directory. If the file doesn't exist, the process exits with an error.` })
37
37
  .option("port", { type: "number", desc: "The storage port for `yarn storageserve`" })
38
38
  .argv
39
39
  ;
@@ -62,7 +62,7 @@ let networkFileNetworks = lazy((): string[] => {
62
62
  console.error(`--networkfile file not found: ${path}`);
63
63
  process.exit(1);
64
64
  }
65
- return fs.readFileSync(path, "utf8").split("\n").map(x => x.trim()).filter(x => x);
65
+ return fs.readFileSync(path, "utf8").split(/[\n,]/).map(x => x.trim()).filter(x => x);
66
66
  });
67
67
 
68
68
  /** The networks a function runner listens on, from the command line (--network / --networkfile). */
@@ -73,7 +73,8 @@ export function getNetworks(): string[] {
73
73
  } else if (!Array.isArray(networks)) {
74
74
  networks = [networks];
75
75
  }
76
- let result = networks.map(x => String(x));
76
+ // Comma separated is the same as repeating the flag, so a templated list of networks can be passed as one argument.
77
+ let result = networks.flatMap(x => String(x).split(",")).map(x => x.trim()).filter(x => x);
77
78
  if (isNode()) {
78
79
  result = [...result, ...networkFileNetworks()];
79
80
  }
@@ -20,6 +20,7 @@ import { createLink } from "../../../library-components/ATag";
20
20
  import { showingManagementURL, managementPageURL } from "../../managementPages";
21
21
  import { atomic } from "../../../2-proxy/PathValueProxyWatcher";
22
22
  import { magenta } from "socket-function/src/formatting/logColors";
23
+ import { formatTime } from "socket-function/src/formatting/format";
23
24
  import { TicketServiceBase } from "../errorTickets/tickets";
24
25
  import { getArchives2 } from "../../../-a-archives/archives2";
25
26
 
@@ -48,6 +49,8 @@ let pendingDiscordNotifications = new Map<string, {
48
49
  errorCount: number;
49
50
  isNew: boolean;
50
51
  }>();
52
+ // Time the currently pending batch started collecting, so the digest can state the window it covers instead of reading as "this is happening right now".
53
+ let pendingDiscordNotificationsStartTime = 0;
51
54
  export async function getSuppressionEntries(): Promise<SuppressionEntry[]> {
52
55
  return await suppression.values();
53
56
  }
@@ -247,6 +250,9 @@ Respond with a JSON object with a "pattern" field containing the search string.`
247
250
  }
248
251
 
249
252
  function queueDiscordNotification(suppressionId: string, errorCount: number, isNew: boolean) {
253
+ if (pendingDiscordNotifications.size === 0) {
254
+ pendingDiscordNotificationsStartTime = Date.now();
255
+ }
250
256
  const existing = pendingDiscordNotifications.get(suppressionId);
251
257
  if (existing) {
252
258
  existing.errorCount += errorCount;
@@ -307,8 +313,10 @@ const trySendDiscordNotificationsBase = batchFunction({ delay: 1000 * 3 }, async
307
313
  { param: showingManagementURL, value: true },
308
314
  { param: managementPageURL, value: "ErrorNotificationPage" },
309
315
  ]);
316
+
317
+ const digestWindow = Date.now() - (pendingDiscordNotificationsStartTime || Date.now());
310
318
  const messageText = messageLines.join("\n");
311
- const message = `[${messageText}](${link})`;
319
+ const message = `Digest for errors for ${formatTime(digestWindow)}:\n[${messageText}](${link})`;
312
320
 
313
321
  try {
314
322
  await sendDiscordMessage({ webhookURL, message });
@@ -326,6 +334,7 @@ const trySendDiscordNotificationsBase = batchFunction({ delay: 1000 * 3 }, async
326
334
  }, EXISTING_SUPPRESSION_THROTTLE);
327
335
 
328
336
  pendingDiscordNotifications.clear();
337
+ pendingDiscordNotificationsStartTime = 0;
329
338
  } catch (error) {
330
339
  console.error("Failed to send Discord notification:", error);
331
340
  }