querysub 0.357.0 → 0.358.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.
@@ -2,8 +2,8 @@ import { lazy } from "socket-function/src/caching";
2
2
  import { Archives, nestArchives } from "../../../-a-archives/archives";
3
3
  import { deepCloneJSON, keyByArray, nextId, sort, timeInHour, timeInMinute, timeInSecond } from "socket-function/src/misc";
4
4
  import { BufferIndex } from "./BufferIndex";
5
- import { delay, runInSerial, runInfinitePoll } from "socket-function/src/batching";
6
- import { Reader, SearchParams } from "./BufferIndexHelpers";
5
+ import { delay, runInParallel, runInSerial, runInfinitePoll } from "socket-function/src/batching";
6
+ import { IndexedLogResults, Reader, SearchParams, addReadToResults, createEmptyIndexedLogResults, INDEX_EXTENSION } from "./BufferIndexHelpers";
7
7
  import { getDomain, isPublic } from "../../../config";
8
8
  import { getArchivesLocal } from "../../../-a-archives/archivesDisk";
9
9
  import { getArchivesBackblaze, getArchivesBackblazePrivateImmutable } from "../../../-a-archives/archivesBackBlaze";
@@ -21,49 +21,16 @@ import { FindProgressTracker } from "./FindProgressTracker";
21
21
  import { SocketFunction } from "socket-function/SocketFunction";
22
22
  import { assertIsManagementUser } from "../../managementPages";
23
23
  import { ignoreErrors } from "../../../errors";
24
+ import { blue } from "socket-function/src/formatting/logColors";
25
+ import { LimitGroup } from "../../../functional/limitProcessing";
24
26
 
25
27
  export type TimeFilePathWithSize = TimeFilePath & {
26
28
  size: number;
27
- sourceName: string;
28
- };
29
-
30
- export type IndexedLogResults = {
31
- matchCount: number;
32
-
33
- // NOTE: A lot of the metadata won't be accurate if multiple searches happen at the same time. However, for debugging, it should be sufficient.
34
- reads: {
35
- cached: boolean;
36
- remote: boolean;
37
- count: number;
38
- size: number;
39
-
40
- totalSize: number;
41
- totalCount: number;
42
- }[];
43
-
44
- localFilesSearched: number;
45
- backblazeFilesSearched: number;
46
-
47
- totalBlockCount: number;
48
- blockCheckedCount: number;
49
- blocksCheckedCompressedSize: number;
50
- blocksCheckedDecompressedSize: number;
51
- blockErrors: string[];
52
-
53
- fileErrors: string[];
54
-
55
- indexesSearched: number;
56
29
  indexSize: number;
57
-
58
- timeToFirstMatch: number;
59
- fileFindTime: number;
60
- indexSearchTime: number;
61
- blockSearchTime: number;
62
-
63
- totalSearchTime: number;
30
+ sourceName: string;
64
31
  };
65
32
 
66
- let logByName = new Map<string, IndexedLogs<unknown>>();
33
+ let loggerByName = new Map<string, IndexedLogs<unknown>>();
67
34
 
68
35
 
69
36
  export class IndexedLogs<T> {
@@ -74,22 +41,24 @@ export class IndexedLogs<T> {
74
41
  forceUsePublicLogs?: boolean;
75
42
  getTime: (result: T) => number | undefined;
76
43
  }) {
77
- logByName.set(this.config.name, this as any);
44
+ loggerByName.set(this.config.name, this as any);
78
45
  }
79
46
 
80
47
 
81
48
  private static shouldRunLoop = false;
82
49
  public static runLogMoveLoop() {
83
50
  IndexedLogs.shouldRunLoop = true;
84
- for (let indexedLogs of logByName.values()) {
51
+ for (let indexedLogs of loggerByName.values()) {
85
52
  indexedLogs.runLogMoverLoop();
86
53
  }
87
54
  }
88
55
 
89
56
  private findCallbacks = new Map<string, (match: T) => void>();
57
+ private resultsCallbacks = new Map<string, (results: IndexedLogResults) => void>();
90
58
  public async clientFind(config: {
91
59
  params: SearchParams;
92
60
  onResult: (match: T) => void;
61
+ onResults?: (results: IndexedLogResults) => void;
93
62
  }): Promise<IndexedLogResults> {
94
63
  let controller = IndexedLogShimController.nodes[SocketFunction.getBrowserNodeId()];
95
64
  let findId = nextId();
@@ -97,6 +66,9 @@ export class IndexedLogs<T> {
97
66
  config.onResult(match);
98
67
  };
99
68
  this.findCallbacks.set(findId, callback);
69
+ if (config.onResults) {
70
+ this.resultsCallbacks.set(findId, config.onResults);
71
+ }
100
72
  try {
101
73
  return await controller.find({
102
74
  findId,
@@ -107,9 +79,14 @@ export class IndexedLogs<T> {
107
79
  // There's some trailing time after the controller call finishes when the results will be trickling back to us.
108
80
  setTimeout(() => {
109
81
  this.findCallbacks.delete(findId);
82
+ this.resultsCallbacks.delete(findId);
110
83
  }, timeInMinute * 30);
111
84
  }
112
85
  }
86
+ public clientCancelAllCallbacks() {
87
+ this.findCallbacks.clear();
88
+ this.resultsCallbacks.clear();
89
+ }
113
90
  public async clientGetPaths(config: {
114
91
  startTime: number;
115
92
  endTime: number;
@@ -128,12 +105,24 @@ export class IndexedLogs<T> {
128
105
  result: unknown;
129
106
  }) {
130
107
  let callback = this.findCallbacks.get(config.findId);
131
- if (!callback) return;
108
+ if (!callback) throw new Error(`Find callback ${config.findId} not found`);
132
109
  callback(config.result as T);
133
110
  }
111
+ public async onResults(config: {
112
+ findId: string;
113
+ results: IndexedLogResults;
114
+ }): Promise<boolean> {
115
+ let callback = this.resultsCallbacks.get(config.findId);
116
+ if (!callback) throw new Error(`Results callback ${config.findId} not found`);
117
+ callback(config.results);
118
+ return true;
119
+ }
134
120
 
135
121
  public async clientForceMoveLogsToPublic() {
136
- await this.moveLogsToPublic(true);
122
+ let controller = IndexedLogShimController.nodes[SocketFunction.getBrowserNodeId()];
123
+ await controller.forceMoveLogsToPublic({
124
+ indexedLogsName: this.config.name,
125
+ });
137
126
  }
138
127
 
139
128
  private localLogsStats = {
@@ -153,23 +142,29 @@ export class IndexedLogs<T> {
153
142
  totalCacheCount: 0,
154
143
  };
155
144
 
145
+ private fileSizeCache = new Map<string, number>();
146
+
156
147
  private getLocalLogs = lazy((): Archives => {
157
148
  let baseDisk = getArchivesLocal(getDomain());
158
149
  let archives = nestArchives("indexed-logs/" + this.config.name, baseDisk);
159
150
  archives = createArchivesMemoryCache(archives, {
160
151
  maxSize: 1024 * 1024 * 512,
161
152
  maxCount: 1000 * 100,
162
- stats: this.localLogsStats
153
+ stats: this.localLogsStats,
154
+ sizeCache: this.fileSizeCache,
155
+ // Local disk reads are fast, but even local reads can have high latency
156
+ extraReadSize: 1024 * 1024 * 1,
163
157
  });
164
158
  return archives;
165
159
  });
166
160
  private getPublicLogs = lazy((): Archives => {
167
161
  let basePublic: Archives = getArchivesLocal(getDomain());
168
- let extraReadSize = 1024;
162
+ // NOTE: The local disk is so fast that reading in 10 megabytes is nothing, And if we read in too small of a value, the overhead per read ends up making this take forever.
163
+ let extraReadSize = 1024 * 1024 * 10;
169
164
  if (this.config.forceUsePublicLogs || isPublic()) {
170
165
  basePublic = getArchivesBackblaze(getDomain());
171
- // The latency on Backblaze is so high that if we're going to do a read, we might as well read a lot. As in, minimum 2s latency. The bandwidth is good though.
172
- extraReadSize = 1024 * 1024 * 10;
166
+ // NOTE: While the latency to back plays is high, now we're reading in parallel, so it shouldn't be as big of an issue.
167
+ extraReadSize = 1024 * 1024 * 1;
173
168
  }
174
169
  let archives = nestArchives("final-indexed-logs/" + this.config.name, basePublic);
175
170
  archives = createArchivesMemoryCache(archives, {
@@ -178,6 +173,7 @@ export class IndexedLogs<T> {
178
173
  fullyImmutable: true,
179
174
  extraReadSize,
180
175
  stats: this.backblazeLogsStats,
176
+ sizeCache: this.fileSizeCache,
181
177
  });
182
178
  return archives;
183
179
  });
@@ -198,20 +194,19 @@ export class IndexedLogs<T> {
198
194
  private forceFlushStream: (() => Promise<void>) | undefined;
199
195
 
200
196
  private getCurrentLogStream(): LogStreamer<T> {
197
+
201
198
  if (!this.currentLogStream) {
202
199
  let { startTime, endTime } = this.getTimeBlock(Date.now());
203
200
  let path = new TimeFileTree(this.getLocalLogs()).getNewPendingPath({ startTime, endTime });
204
- let indexPath = this.getIndexPath(path);
205
201
  let streamer = BufferIndex.createStreamer();
206
202
  let currentLogStreamSize = 0;
207
203
  let currentLogStreamCount = 0;
208
204
  let newStreamer = async () => {
209
205
  let result = streamer.close();
210
206
  await this.getLocalLogs().append(path, result.data);
211
- await this.getLocalLogs().append(indexPath, result.index);
207
+ await this.getLocalLogs().append(path + INDEX_EXTENSION, result.index);
212
208
 
213
209
  path = new TimeFileTree(this.getLocalLogs()).getNewPendingPath({ startTime, endTime });
214
- indexPath = this.getIndexPath(path);
215
210
  streamer = BufferIndex.createStreamer();
216
211
  currentLogStreamSize = 0;
217
212
  currentLogStreamCount = 0;
@@ -224,6 +219,14 @@ export class IndexedLogs<T> {
224
219
 
225
220
  };
226
221
  let writeBuffers = async (buffers: Buffer[]) => {
222
+ if (Date.now() > endTime) {
223
+ let timeBlockObj = this.getTimeBlock(Date.now());
224
+ startTime = timeBlockObj.startTime;
225
+ endTime = timeBlockObj.endTime;
226
+ path = new TimeFileTree(this.getLocalLogs()).getNewPendingPath(timeBlockObj);
227
+ await newStreamer();
228
+ }
229
+
227
230
  let maxSize = this.config.maxSingleFileData || MAX_SINGLE_FILE_DATA;
228
231
  let maxCount = this.config.maxCountPerFile || MAX_COUNT_PER_FILE;
229
232
 
@@ -239,7 +242,7 @@ export class IndexedLogs<T> {
239
242
  let result = streamer.add(group);
240
243
  await this.getLocalLogs().append(path, result.data);
241
244
  if (result.index) {
242
- await this.getLocalLogs().append(indexPath, result.index);
245
+ await this.getLocalLogs().append(path + INDEX_EXTENSION, result.index);
243
246
  }
244
247
 
245
248
  currentLogStreamSize += result.data.length;
@@ -284,10 +287,6 @@ export class IndexedLogs<T> {
284
287
  return groups;
285
288
  }
286
289
 
287
- private getIndexPath(dataPath: string): string {
288
- return dataPath + ".index";
289
- }
290
-
291
290
  public append(datum: T) {
292
291
  this.getCurrentLogStream().append(datum);
293
292
  if (IndexedLogs.shouldRunLoop) {
@@ -295,6 +294,7 @@ export class IndexedLogs<T> {
295
294
  }
296
295
  }
297
296
 
297
+ @measureFnc
298
298
  public async getPaths(config: {
299
299
  startTime: number;
300
300
  endTime: number;
@@ -326,16 +326,98 @@ export class IndexedLogs<T> {
326
326
  let archives = path.logCount !== undefined ? backblazeLogs : localLogs;
327
327
  let info = await archives.getInfo(path.fullPath);
328
328
  let size = info?.size || 0;
329
- return { ...path, size, sourceName: this.config.name };
329
+ this.fileSizeCache.set(path.fullPath, size);
330
+ let indexPath = path.fullPath + INDEX_EXTENSION;
331
+ let indexInfo = await archives.getInfo(indexPath);
332
+ let indexSize = indexInfo?.size || 0;
333
+ this.fileSizeCache.set(indexPath, indexSize);
334
+ return { ...path, size, indexSize, sourceName: this.config.name };
330
335
  }));
331
336
 
332
337
  return pathsWithSize;
333
338
  }
334
339
 
340
+ @measureFnc
335
341
  public async find(config: {
336
342
  params: SearchParams;
337
343
  onResult: (match: T) => void;
344
+ onResults?: (results: IndexedLogResults) => Promise<boolean>;
338
345
  }): Promise<IndexedLogResults> {
346
+ let startTime = Date.now();
347
+ let interval: NodeJS.Timeout | undefined;
348
+
349
+ let results: IndexedLogResults = createEmptyIndexedLogResults();
350
+ results.limitGroup = new LimitGroup({
351
+ maxTimePerBeforeWait: 500,
352
+ waitTime: 250,
353
+ });
354
+
355
+ let initialLocalStats = deepCloneJSON(this.localLogsStats);
356
+ let initialBackblazeStats = deepCloneJSON(this.backblazeLogsStats);
357
+
358
+ let updateResultsStats = () => {
359
+ results.reads = [];
360
+
361
+ function addStatsRead(initial: ArchivesMemoryCacheStats, final: ArchivesMemoryCacheStats, remote: boolean) {
362
+ let uncached = addReadToResults(results, {
363
+ cached: false,
364
+ remote,
365
+ count: final.uncachedReads - initial.uncachedReads,
366
+ size: final.uncachedReadSize - initial.uncachedReadSize,
367
+ });
368
+ uncached.totalSize = final.totalCacheSize;
369
+ uncached.totalCount = final.totalCacheCount;
370
+
371
+ let cached = addReadToResults(results, {
372
+ cached: true,
373
+ remote,
374
+ count: final.cachedReads - initial.cachedReads,
375
+ size: final.cachedReadSize - initial.cachedReadSize,
376
+ });
377
+ cached.totalSize = final.totalCacheSize;
378
+ cached.totalCount = final.totalCacheCount;
379
+ }
380
+
381
+ addStatsRead(initialLocalStats, this.localLogsStats, false);
382
+ addStatsRead(initialBackblazeStats, this.backblazeLogsStats, true);
383
+
384
+ results.totalSearchTime = Date.now() - startTime;
385
+ };
386
+
387
+ const onResultsCallback = config.onResults;
388
+ if (onResultsCallback) {
389
+ interval = setInterval(async () => {
390
+ updateResultsStats();
391
+ let shouldContinue = await onResultsCallback(deepCloneJSON(results));
392
+ if (!shouldContinue) {
393
+ if (!results.cancel) {
394
+ console.log(blue(`Cancelled search on ${this.config.name}`));
395
+ }
396
+ results.cancel = true;
397
+ }
398
+ }, timeInSecond);
399
+ }
400
+
401
+ try {
402
+ await this.findBase({
403
+ params: config.params,
404
+ onResult: config.onResult,
405
+ results,
406
+ });
407
+ updateResultsStats();
408
+ return results;
409
+ } finally {
410
+ if (interval) {
411
+ clearInterval(interval);
412
+ }
413
+ }
414
+ }
415
+
416
+ private async findBase(config: {
417
+ params: SearchParams;
418
+ onResult: (match: T) => void;
419
+ results: IndexedLogResults;
420
+ }): Promise<void> {
339
421
  let startTime = Date.now();
340
422
  let localLogs = this.getLocalLogs();
341
423
  let backblazeLogs = this.getPublicLogs();
@@ -347,54 +429,56 @@ export class IndexedLogs<T> {
347
429
  only: config.params.only,
348
430
  });
349
431
  paths = paths.filter(x => x.sourceName === this.config.name);
432
+ for (let path of paths) {
433
+ this.fileSizeCache.set(path.fullPath, path.size);
434
+ this.fileSizeCache.set(path.fullPath + INDEX_EXTENSION, path.indexSize);
435
+ }
350
436
  fileFindTime = Date.now() - fileFindTime;
351
437
 
352
438
  // Newest first
353
439
  sort(paths, x => - x.startTime);
354
440
 
441
+ let results = config.results;
355
442
  let localPaths = paths.filter(x => x.logCount === undefined);
356
- let backblazePaths = paths.filter(x => x.logCount !== undefined);
357
-
358
- let initialLocalStats = deepCloneJSON(this.localLogsStats);
359
- let initialBackblazeStats = deepCloneJSON(this.backblazeLogsStats);
360
- let stats = {
361
- blockCheckedCount: 0,
362
- blocksCheckedCompressedSize: 0,
363
- blocksCheckedDecompressedSize: 0,
364
- totalBlockCount: 0,
365
- indexSearchTime: 0,
366
- blockSearchTime: 0,
367
- indexesSearched: 0,
368
- indexSize: 0,
369
- matchCount: 0,
370
- timeToFirstMatch: -1,
371
- };
372
- let fileErrors: string[] = [];
373
- let blockErrors: string[] = [];
443
+ let remotePaths = paths.filter(x => x.logCount !== undefined);
444
+ results.totalLocalFiles = localPaths.length;
445
+ results.totalBackblazeFiles = remotePaths.length;
446
+ results.fileFindTime = fileFindTime;
374
447
 
375
448
  let progressTracker = new FindProgressTracker<T>({
376
449
  params: config.params,
377
450
  deserialize: (buffer: Buffer) => LogStreamer.deserialize<T>(buffer),
378
451
  getTime: this.config.getTime,
379
452
  onResult: (match: T) => {
380
- if (stats.timeToFirstMatch < 0) {
381
- stats.timeToFirstMatch = Date.now() - startTime;
453
+ if (results.timeToFirstMatch < 0) {
454
+ results.timeToFirstMatch = Date.now() - startTime;
382
455
  }
383
- stats.matchCount++;
456
+ results.matchCount++;
384
457
  config.onResult(match);
385
458
  },
386
459
  });
387
460
 
388
461
 
389
- for (let path of paths) {
390
- if (!progressTracker.isSourceRelevant(path)) continue;
462
+ const searchPath = async (path: TimeFilePathWithSize) => {
463
+ if (!progressTracker.isSourceRelevant(path)) return;
464
+ // Wait, so we don't lock up the main thread?
465
+ await delay(0);
391
466
 
392
- let archives = path.logCount !== undefined ? backblazeLogs : localLogs;
467
+ let remote = path.logCount !== undefined;
468
+ let archives = remote ? backblazeLogs : localLogs;
469
+ if (remote) {
470
+ results.backblazeFilesSearched++;
471
+ } else {
472
+ results.localFilesSearched++;
473
+ }
393
474
  try {
394
475
  let readIndexTime = Date.now();
395
- let index = await archives.get(this.getIndexPath(path.fullPath)) || Buffer.alloc(0);
476
+ let index = await archives.get(
477
+ path.fullPath + INDEX_EXTENSION,
478
+ { range: { start: 0, end: path.indexSize } }
479
+ ) || Buffer.alloc(0);
396
480
  readIndexTime = Date.now() - readIndexTime;
397
- stats.indexSearchTime += readIndexTime;
481
+ results.indexSearchTime += readIndexTime;
398
482
  let dataReader: Reader = {
399
483
  getLength: async () => path.size,
400
484
  read: async (offset, length) => {
@@ -406,76 +490,44 @@ export class IndexedLogs<T> {
406
490
  },
407
491
  };
408
492
  let totalSearchTime = Date.now();
409
- let findObj = await BufferIndex.find({
493
+ let blockSearchTimeBefore = results.blockSearchTime;
494
+ await BufferIndex.find({
410
495
  index,
411
496
  dataReader,
412
497
  params: {
413
498
  ...config.params,
414
- limit: config.params.limit - stats.matchCount,
499
+ limit: config.params.limit - results.matchCount,
415
500
  },
416
- keepIterating: () => progressTracker.isSourceRelevant(path),
501
+ keepIterating: () => !results.cancel && progressTracker.isSourceRelevant(path),
417
502
  onResult: (match: Buffer) => {
418
- if (stats.matchCount >= config.params.limit) return;
503
+ if (results.matchCount >= config.params.limit) return;
419
504
  progressTracker.addResult(match, path);
420
505
  },
506
+ results,
421
507
  });
422
- blockErrors.push(...findObj.blocksWithErrors);
423
508
  totalSearchTime = Date.now() - totalSearchTime;
424
- stats.indexSearchTime += totalSearchTime - findObj.blockSearchTime;
425
- stats.blockSearchTime += findObj.blockSearchTime;
426
- stats.indexesSearched += findObj.indexCount;
427
- stats.indexSize += findObj.indexSize;
428
- stats.blockCheckedCount += findObj.blocksChecked;
429
- stats.blocksCheckedCompressedSize += findObj.blocksCheckedCompressedSize;
430
- stats.blocksCheckedDecompressedSize += findObj.blocksCheckedDecompressedSize;
431
- stats.totalBlockCount += findObj.totalBlockCount;
432
-
433
- if (stats.matchCount >= config.params.limit) break;
509
+ let blockSearchTimeAdded = results.blockSearchTime - blockSearchTimeBefore;
510
+ results.indexSearchTime += totalSearchTime - blockSearchTimeAdded;
511
+
434
512
  } catch (e: any) {
435
- fileErrors.push(String(e?.stack || e));
513
+ results.fileErrors.push({ error: String(e?.stack || e), path: path.fullPath });
436
514
  console.warn(`Error in reading log file ${path.fullPath} logs: ${e}`);
437
515
  }
438
- }
439
-
440
- if (stats.timeToFirstMatch < 0) {
441
- stats.timeToFirstMatch = Date.now() - startTime;
442
- }
443
-
444
-
445
- let reads: { cached: boolean; remote: boolean; count: number; size: number; totalSize: number; totalCount: number; }[] = [];
446
- function addStatsRead(initial: ArchivesMemoryCacheStats, final: ArchivesMemoryCacheStats, remote: boolean) {
447
- reads.push({
448
- cached: false,
449
- remote,
450
- count: final.uncachedReads - initial.uncachedReads,
451
- size: final.uncachedReadSize - initial.uncachedReadSize,
452
- totalSize: final.totalCacheSize,
453
- totalCount: final.totalCacheCount,
454
- });
455
- reads.push({
456
- cached: true,
457
- remote,
458
- count: final.cachedReads - initial.cachedReads,
459
- size: final.cachedReadSize - initial.cachedReadSize,
460
- totalSize: final.totalCacheSize,
461
- totalCount: final.totalCacheCount,
462
- });
463
- }
464
-
465
- addStatsRead(initialLocalStats, this.localLogsStats, false);
466
- addStatsRead(initialBackblazeStats, this.backblazeLogsStats, true);
467
-
468
-
469
- return {
470
- reads,
471
- localFilesSearched: localPaths.length,
472
- backblazeFilesSearched: backblazePaths.length,
473
- fileFindTime,
474
- fileErrors,
475
- blockErrors,
476
- totalSearchTime: Date.now() - startTime,
477
- ...stats,
478
516
  };
517
+ let localDone = (async () => {
518
+ for (let path of localPaths) {
519
+ await searchPath(path);
520
+ }
521
+ })();
522
+ // No parallel count when running locally, as running it in parallel makes timing more difficult.
523
+ let parallelCount = isPublic() ? 32 : 1;
524
+ let remoteParallel = runInParallel({ parallelCount }, searchPath);
525
+ await Promise.all(remotePaths.map(remoteParallel));
526
+ await localDone;
527
+
528
+ if (results.timeToFirstMatch < 0) {
529
+ results.timeToFirstMatch = Date.now() - startTime;
530
+ }
479
531
  }
480
532
 
481
533
  public async moveLogsToPublic(forceAll = false) {
@@ -490,7 +542,7 @@ export class IndexedLogs<T> {
490
542
  publicMoveThreshold: PUBLIC_MOVE_THRESHOLD,
491
543
  maxSingleFileData: this.config.maxSingleFileData || MAX_SINGLE_FILE_DATA,
492
544
  movingTimeout: MOVING_TIMEOUT,
493
- getIndexPath: (path: string) => this.getIndexPath(path),
545
+ indexExtension: INDEX_EXTENSION,
494
546
  });
495
547
  }
496
548
 
@@ -529,13 +581,26 @@ class IndexedLogClient {
529
581
  result: unknown;
530
582
  }) {
531
583
  if (isNode()) return;
532
- let indexedLogs = logByName.get(config.indexedLogsName);
584
+ let indexedLogs = loggerByName.get(config.indexedLogsName);
533
585
  if (!indexedLogs) throw new Error(`Indexed logs ${config.indexedLogsName} not found`);
534
586
  indexedLogs.onFindResult({
535
587
  findId: config.findId,
536
588
  result: config.result,
537
589
  });
538
590
  }
591
+ public async onResults(config: {
592
+ findId: string;
593
+ indexedLogsName: string;
594
+ results: IndexedLogResults;
595
+ }): Promise<boolean> {
596
+ if (isNode()) return true;
597
+ let indexedLogs = loggerByName.get(config.indexedLogsName);
598
+ if (!indexedLogs) throw new Error(`Indexed logs ${config.indexedLogsName} not found`);
599
+ return await indexedLogs.onResults({
600
+ findId: config.findId,
601
+ results: config.results,
602
+ });
603
+ }
539
604
  }
540
605
  class IndexedLogShim {
541
606
  public async find(config: {
@@ -544,8 +609,9 @@ class IndexedLogShim {
544
609
  params: SearchParams;
545
610
  }): Promise<IndexedLogResults> {
546
611
  let caller = SocketFunction.getCaller();
547
- let indexedLogs = logByName.get(config.indexedLogsName);
612
+ let indexedLogs = loggerByName.get(config.indexedLogsName);
548
613
  if (!indexedLogs) throw new Error(`Indexed logs ${config.indexedLogsName} not found`);
614
+
549
615
  return indexedLogs.find({
550
616
  params: config.params,
551
617
  onResult: (match: unknown) => {
@@ -555,6 +621,18 @@ class IndexedLogShim {
555
621
  result: match,
556
622
  }));
557
623
  },
624
+ onResults: async (results: IndexedLogResults) => {
625
+ try {
626
+ await IndexedLogClientController.nodes[caller.nodeId].onResults({
627
+ findId: config.findId,
628
+ indexedLogsName: config.indexedLogsName,
629
+ results: results,
630
+ });
631
+ return true;
632
+ } catch (e) {
633
+ return false;
634
+ }
635
+ },
558
636
  });
559
637
  }
560
638
  public async getPaths(config: {
@@ -563,7 +641,7 @@ class IndexedLogShim {
563
641
  endTime: number;
564
642
  only?: "local" | "public";
565
643
  }): Promise<TimeFilePathWithSize[]> {
566
- let indexedLogs = logByName.get(config.indexedLogsName);
644
+ let indexedLogs = loggerByName.get(config.indexedLogsName);
567
645
  if (!indexedLogs) throw new Error(`Indexed logs ${config.indexedLogsName} not found`);
568
646
  return indexedLogs.getPaths({
569
647
  startTime: config.startTime,
@@ -571,6 +649,14 @@ class IndexedLogShim {
571
649
  only: config.only,
572
650
  });
573
651
  }
652
+
653
+ public async forceMoveLogsToPublic(config: {
654
+ indexedLogsName: string;
655
+ }) {
656
+ let indexedLogs = loggerByName.get(config.indexedLogsName);
657
+ if (!indexedLogs) throw new Error(`Indexed logs ${config.indexedLogsName} not found`);
658
+ await indexedLogs.moveLogsToPublic(true);
659
+ }
574
660
  }
575
661
 
576
662
  const IndexedLogShimController = SocketFunction.register(
@@ -583,7 +669,7 @@ const IndexedLogShimController = SocketFunction.register(
583
669
  getPaths: {
584
670
  hooks: [assertIsManagementUser]
585
671
  },
586
- clientForceMoveLogsToPublic: {
672
+ forceMoveLogsToPublic: {
587
673
  hooks: [assertIsManagementUser]
588
674
  }
589
675
  })
@@ -593,6 +679,7 @@ const IndexedLogClientController = SocketFunction.register(
593
679
  "IndexedLogClient-019c87b9-1c6d-72ed-8bc9-d52451e2c1b9",
594
680
  new IndexedLogClient(),
595
681
  () => ({
596
- onFind: {}
682
+ onFind: {},
683
+ onResults: {}
597
684
  })
598
685
  );