querysub 0.367.0 → 0.369.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.367.0",
3
+ "version": "0.369.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",
@@ -109,6 +109,10 @@ export function isOwnNodeId(nodeId: string): boolean {
109
109
  return false;
110
110
  }
111
111
 
112
+ export function isNodeIdOnOwnMachineId(nodeId: string): boolean {
113
+ return certs.getMachineId(nodeId) === getOwnMachineId() || nodeId.startsWith("127-0-0-1.");
114
+ }
115
+
112
116
  let nodeOverrides: string[] | undefined;
113
117
  let beforeGetNodeAllId = async () => { };
114
118
  export async function getAllNodeIds() {
@@ -12,7 +12,7 @@ import { ArchivesMemoryCacheStats, createArchivesMemoryCache } from "../../../-a
12
12
  import { registerShutdownHandler } from "../../periodic";
13
13
  import { measureBlock, measureFnc } from "socket-function/src/profiling/measure";
14
14
  import { isNode } from "typesafecss";
15
- import { getOwnMachineId } from "../../../-f-node-discovery/NodeDiscovery";
15
+ import { getOwnMachineId, isNodeIdOnOwnMachineId, isOwnNodeId } from "../../../-f-node-discovery/NodeDiscovery";
16
16
  import { TimeFilePath, TimeFileTree } from "./TimeFileTree";
17
17
  import { LogStreamer } from "./LogStreamer";
18
18
  import { moveLogsToPublic } from "./moveIndexLogsToPublic";
@@ -226,10 +226,11 @@ export class IndexedLogs<T> {
226
226
 
227
227
  private machineNodeCache = new Map<string, string>();
228
228
  private async getMachineNodes(): Promise<string[]> {
229
- let ownMachineId = getOwnMachineId();
230
229
  let nodeIds = await getAllNodeIds();
230
+ nodeIds = nodeIds.filter(x => !isNodeIdOnOwnMachineId(x));
231
231
  let byMachineId = keyByArray(nodeIds, x => getMachineId(x));
232
- byMachineId.delete(ownMachineId);
232
+
233
+ let nextCache = new Map<string, string>();
233
234
 
234
235
  await Promise.all(Array.from(byMachineId.entries()).map(async ([machineId, nodeIds]) => {
235
236
  let added = false;
@@ -239,12 +240,12 @@ export class IndexedLogs<T> {
239
240
  if (!hasLogger) return false;
240
241
  // NOTE: Prefer to do the searching on the move logs service. However, if it's not available, any service can do searching. It just might lag that server...
241
242
  if (preferredOnly) {
242
- let entryPoint = await NodeCapabilitiesController.nodes[nodeId].getEntryPoint();
243
- if (!entryPoint.includes("movelogs")) return false;
243
+ let entryPoint = await timeoutToUndefinedSilent(2500, NodeCapabilitiesController.nodes[nodeId].getEntryPoint());
244
+ if (!entryPoint?.includes("movelogs")) return false;
244
245
  }
245
246
  added = true;
246
247
 
247
- this.machineNodeCache.set(machineId, nodeId);
248
+ nextCache.set(machineId, nodeId);
248
249
  return true;
249
250
  };
250
251
  let cached = this.machineNodeCache.get(machineId);
@@ -261,6 +262,7 @@ export class IndexedLogs<T> {
261
262
  }
262
263
  }));
263
264
 
265
+ this.machineNodeCache = nextCache;
264
266
  return Array.from(this.machineNodeCache.values());
265
267
  }
266
268
 
@@ -298,21 +300,28 @@ export class IndexedLogs<T> {
298
300
  let backblazeLogs = this.getPublicLogs();
299
301
  let paths: TimeFilePath[] = [];
300
302
 
303
+ let promises: Promise<void>[] = [];
304
+
301
305
  if (config.only !== "public") {
302
- let localPaths = await new TimeFileTree(localLogs).findAllPaths({
303
- startTime: config.startTime,
304
- endTime: config.endTime,
305
- });
306
- paths.push(...localPaths);
306
+ promises.push((async () => {
307
+ let localPaths = await new TimeFileTree(localLogs).findAllPaths({
308
+ startTime: config.startTime,
309
+ endTime: config.endTime,
310
+ });
311
+ paths.push(...localPaths);
312
+ })());
307
313
  }
308
314
 
309
315
  if (config.only !== "local") {
310
- let backblazePaths = await new TimeFileTree(backblazeLogs).findAllPaths({
311
- startTime: config.startTime,
312
- endTime: config.endTime,
313
- });
314
- paths.push(...backblazePaths);
316
+ promises.push((async () => {
317
+ let backblazePaths = await new TimeFileTree(backblazeLogs).findAllPaths({
318
+ startTime: config.startTime,
319
+ endTime: config.endTime,
320
+ });
321
+ paths.push(...backblazePaths);
322
+ })());
315
323
  }
324
+ await Promise.all(promises);
316
325
 
317
326
  // Bake in the size to ensure more cache hits (without this, every single access will always result in a file/remote call).
318
327
  let pathsWithSize = await Promise.all(paths.map(async (path): Promise<TimeFilePathWithSize> => {
@@ -351,12 +360,16 @@ export class IndexedLogs<T> {
351
360
  let allResults = new Map<string, IndexedLogResults>();
352
361
  let allDone: Promise<void>[] = [];
353
362
 
354
- if (!config.params.only && (config.params.forceReadPublic || isPublic())) {
363
+ if (config.params.only !== "local" && (config.params.forceReadPublic || isPublic())) {
355
364
  let machineNodes = await this.getMachineNodes();
356
365
  allDone.push(...machineNodes.map(async (machineNode) => {
357
366
  try {
358
367
  let resultObj = await this.clientFind({
359
368
  ...config,
369
+ params: {
370
+ ...config.params,
371
+ only: "local",
372
+ },
360
373
  nodeId: machineNode,
361
374
  onResult(match) {
362
375
  config.onResult(match);
@@ -374,6 +387,7 @@ export class IndexedLogs<T> {
374
387
 
375
388
  // If we're forcefully reading from the public server, but we're not public, the code above will be the only code which adds to results
376
389
  if (!isPublic() && config.params.forceReadPublic) {
390
+ await Promise.all(allDone);
377
391
  return getFinalResults();
378
392
  }
379
393
 
@@ -696,7 +710,6 @@ class IndexedLogClient {
696
710
  indexedLogsName: string;
697
711
  result: unknown;
698
712
  }) {
699
- if (isNode()) return;
700
713
  let indexedLogs = loggerByName.get(config.indexedLogsName);
701
714
  if (!indexedLogs) throw new Error(`Indexed logs ${config.indexedLogsName} not found`);
702
715
  indexedLogs.onFindResult({
@@ -709,7 +722,6 @@ class IndexedLogClient {
709
722
  indexedLogsName: string;
710
723
  results: IndexedLogResults;
711
724
  }): Promise<boolean> {
712
- if (isNode()) return true;
713
725
  let indexedLogs = loggerByName.get(config.indexedLogsName);
714
726
  if (!indexedLogs) throw new Error(`Indexed logs ${config.indexedLogsName} not found`);
715
727
  return await indexedLogs.onResults({
@@ -25,6 +25,7 @@ import { errorToUndefined } from "../../../errors";
25
25
  import { IndexedLogResults, createEmptyIndexedLogResults, mergeIndexedLogResults } from "./BufferIndexHelpers";
26
26
  import { TimeFilePath } from "./TimeFileTree";
27
27
  import { isPublic } from "../../../config";
28
+ import { Zip } from "../../../zip";
28
29
 
29
30
  let searchText = new URLParam("searchText", "");
30
31
  let excludePendingResults = new URLParam("excludePendingResults", false);
@@ -76,7 +77,7 @@ export class LogViewer3 extends qreact.Component {
76
77
  let paths: TimeFilePathWithSize[] = [];
77
78
  if (savedPathsURL.value) {
78
79
  const compressed = Buffer.from(savedPathsURL.value, "base64");
79
- const decompressed = LZ4.decompress(compressed);
80
+ const decompressed = Zip.gunzipSync(compressed);
80
81
  paths = JSON.parse(decompressed.toString("utf8"));
81
82
  } else {
82
83
  paths = this.state.paths;
@@ -95,7 +96,7 @@ export class LogViewer3 extends qreact.Component {
95
96
  freezePaths() {
96
97
  const json = JSON.stringify(this.state.paths);
97
98
  const buffer = Buffer.from(json, "utf8");
98
- const compressed = LZ4.compress(buffer);
99
+ const compressed = Zip.gzipSync(buffer, 9);
99
100
  savedPathsURL.value = compressed.toString("base64");
100
101
  }
101
102
 
@@ -342,6 +343,8 @@ export class LogViewer3 extends qreact.Component {
342
343
 
343
344
  Querysub.commitLocal(() => {
344
345
  this.state.loadingPaths = true;
346
+ this.state.results = [];
347
+ this.state.stats = undefined;
345
348
  });
346
349
 
347
350
  let loggers = await getLoggers2Async();
@@ -364,15 +367,15 @@ export class LogViewer3 extends qreact.Component {
364
367
  let allPaths: TimeFilePathWithSize[] = [];
365
368
  let range = Querysub.localRead(() => getTimeRange());
366
369
 
367
- for (let logger of selectedLoggers) {
370
+ await Promise.all(selectedLoggers.map(async (logger) => {
368
371
  let paths = await logger.clientGetPaths({
369
372
  startTime: range.startTime,
370
373
  endTime: range.endTime,
371
- only: excludePendingResults.value ? "local" : undefined,
374
+ only: excludePendingResults.value ? "public" : undefined,
372
375
  forceReadPublic: readPublicLogs.value,
373
376
  });
374
377
  allPaths.push(...paths);
375
- }
378
+ }));
376
379
  sort(allPaths, x => -x.startTime);
377
380
 
378
381
  Querysub.commitLocal(() => {
@@ -679,7 +682,6 @@ export class LogViewer3 extends qreact.Component {
679
682
  return (
680
683
  <div className={css.vbox(20).pad2(20).fillBoth}>
681
684
  <div className={css.hbox(20)}>
682
- <div>Log Viewer 3</div>
683
685
  <InputLabelURL
684
686
  checkbox
685
687
  label="Exclude Pending Results"
@@ -740,7 +742,9 @@ export class LogViewer3 extends qreact.Component {
740
742
  </Button>
741
743
  <TimeRangeSelector />
742
744
  </div>
743
- {!isPublic() && readPublicLogs.value && <h1>Reading public logs</h1>}
745
+ {!isPublic() && readPublicLogs.value && <div className={css.fontSize(40).pad2(12, 6).hsl(280, 40, 50).colorhsl(0, 0, 100).boldStyle}>
746
+ Reading public logs
747
+ </div>}
744
748
 
745
749
  <div className={css.hbox(10).fillWidth}>
746
750
  <InputLabelURL
@@ -156,12 +156,12 @@ export class TimeFileTree {
156
156
  // Find all days in this month
157
157
  const days = await this.archives.find(monthFolder + "/", { shallow: true, type: "folders" });
158
158
 
159
- for (const dayFolder of days) {
159
+ await Promise.all(days.map(async (dayFolder) => {
160
160
  // dayFolder is a full path like "2024/01/15"
161
161
  const day = parseInt(dayFolder.split("/").at(-1) || "", 10);
162
162
 
163
163
  if (isNaN(day) || day < 1 || day > 31) {
164
- continue;
164
+ return;
165
165
  }
166
166
 
167
167
  // Check if this day is in range
@@ -169,7 +169,7 @@ export class TimeFileTree {
169
169
  const dayEndDate = new Date(Date.UTC(year, month - 1, day, 23, 59, 59, 999));
170
170
 
171
171
  if (dayEndDate.getTime() < config.startTime || dayDate.getTime() > config.endTime) {
172
- continue;
172
+ return;
173
173
  }
174
174
 
175
175
  // Find all log files in this day
@@ -187,7 +187,7 @@ export class TimeFileTree {
187
187
  results.push(decoded);
188
188
  }
189
189
  }
190
- }
190
+ }));
191
191
  }
192
192
  }
193
193
 
@@ -23,6 +23,8 @@ IMPORTANT! Now I am properly calling shutdown, so none of the streamed logs shou
23
23
  1) Verify isPublic searching works (from our local machine)
24
24
 
25
25
 
26
+ 1) Deploy our changes
27
+
26
28
 
27
29
  2) Create lot of remote server logs
28
30
  - Via our refresh loop