querysub 0.375.0 → 0.377.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.375.0",
3
+ "version": "0.377.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",
@@ -16,8 +16,7 @@
16
16
  "test-wat": "yarn typenode ./src/wat/watCompiler.ts",
17
17
  "error-watch": "yarn typenode ./src/diagnostics/logs/errorNotifications/errorWatchEntry.tsx",
18
18
  "error-email": "yarn typenode ./src/diagnostics/logs/errorNotifications/errorDigestEntry.tsx",
19
- "build-native": "cd src/diagnostics/logs/IndexedLogs && node-gyp rebuild",
20
- "postinstall": "node scripts/postinstall.js"
19
+ "build-native": "cd src/diagnostics/logs/IndexedLogs && node-gyp rebuild"
21
20
  },
22
21
  "bin": {
23
22
  "deploy": "./bin/deploy.js",
@@ -10,7 +10,7 @@ import { measureBlock, measureFnc, measureWrap } from "socket-function/src/profi
10
10
  import { formatNumber, formatTime } from "socket-function/src/formatting/format";
11
11
  import { magenta, yellow } from "socket-function/src/formatting/logColors";
12
12
  import { Unit, getAllUnits, Reader, createOffsetReader, SearchParams, IndexedLogResults } from "./BufferIndexHelpers";
13
- import { createMatchesPattern, getSearchUnits } from "./bufferMatcher";
13
+ import { createMatchesPattern, getSearchUnits } from "./bufferSearchFindMatcher";
14
14
  import { UnitSet } from "./BufferUnitSet";
15
15
  import { BufferUnitIndex } from "./BufferUnitIndex";
16
16
  import { BufferListStreamer } from "./BufferListStreamer";
@@ -178,13 +178,13 @@ export class BufferIndex {
178
178
 
179
179
  // IMPORTANT! The input data values should be sorted from newest to oldest.
180
180
  @measureFnc
181
- public static encodeAll(config: {
181
+ public static async encodeAll(config: {
182
182
  data: Buffer[];
183
- }): {
183
+ }): Promise<{
184
184
  data: Buffer;
185
185
  index: Buffer;
186
- } {
187
- let obj = BufferUnitIndex.encode(config.data, {
186
+ }> {
187
+ let obj = await BufferUnitIndex.encode(config.data, {
188
188
  type: BULK_TYPE,
189
189
  });
190
190
  return {
@@ -453,6 +453,11 @@ export class BufferIndex {
453
453
  results.remoteIndexesSearched += 1;
454
454
  results.remoteIndexSize += index.length;
455
455
  } else {
456
+ let dataLength = await dataReader.getLength();
457
+ if (dataLength < 32) {
458
+ // If it's a small file, nothing of value will be lost by ignoring it. And almost all of our errors are coming from extremely small files.
459
+ return;
460
+ }
456
461
  throw new Error(`Unknown type in index file: ${type}`);
457
462
  }
458
463
  }
@@ -3,6 +3,21 @@
3
3
  #include <string.h>
4
4
  #include <algorithm>
5
5
 
6
+ static uint32_t RemapUnit(uint32_t unit) {
7
+ uint8_t byte0 = (unit >> 0) & 0xFF;
8
+ uint8_t byte1 = (unit >> 8) & 0xFF;
9
+ uint8_t byte2 = (unit >> 16) & 0xFF;
10
+ uint8_t byte3 = (unit >> 24) & 0xFF;
11
+
12
+ if (byte0 >= 65 && byte0 <= 90) byte0 += 32;
13
+ if (byte1 >= 65 && byte1 <= 90) byte1 += 32;
14
+ if (byte2 >= 65 && byte2 <= 90) byte2 += 32;
15
+ if (byte3 >= 65 && byte3 <= 90) byte3 += 32;
16
+
17
+ return byte0 | (byte1 << 8) | (byte2 << 16) | (byte3 << 24);
18
+ }
19
+
20
+
6
21
  static napi_value PopulateUnits(napi_env env, napi_callback_info info) {
7
22
  size_t argc = 2;
8
23
  napi_value args[2];
@@ -75,6 +90,8 @@ static napi_value PopulateUnits(napi_env env, napi_callback_info info) {
75
90
  (bufferData[i+2] << 16) |
76
91
  (bufferData[i+3] << 24);
77
92
 
93
+ unit = RemapUnit(unit);
94
+
78
95
  if (unit == 0) continue;
79
96
 
80
97
  unitsArray[currentOffset] = unit;
@@ -184,6 +201,8 @@ static napi_value BuildHashTable(napi_env env, napi_callback_info info) {
184
201
  // This reads 4 bytes starting at position i
185
202
  uint32_t unit = *(uint32_t*)(blockData + i);
186
203
 
204
+ unit = RemapUnit(unit);
205
+
187
206
  uint32_t maskedHash = GetMaskedHash(unit, mask);
188
207
  uint32_t currentHead = hashTable[maskedHash];
189
208
 
@@ -291,6 +310,8 @@ static napi_value EstimateUniqueUnits(napi_env env, napi_callback_info info) {
291
310
  // Read unit directly by casting pointer (little-endian architecture)
292
311
  uint32_t unit = *(uint32_t*)(bufferData + i);
293
312
 
313
+ unit = RemapUnit(unit);
314
+
294
315
  // Get masked hash with 0xFFFF mask (16-bit)
295
316
  uint32_t maskedHash = GetMaskedHash(unit, 0xFFFF);
296
317
 
@@ -57,6 +57,33 @@ export function createOffsetReader(reader: Reader, offset: number): Reader {
57
57
  };
58
58
  }
59
59
 
60
+ export function remapUnit(unit: Unit): Unit {
61
+ let byte0 = (unit >> 0) & 0xFF;
62
+ let byte1 = (unit >> 8) & 0xFF;
63
+ let byte2 = (unit >> 16) & 0xFF;
64
+ let byte3 = (unit >> 24) & 0xFF;
65
+
66
+ if (byte0 >= 65 && byte0 <= 90) byte0 += 32;
67
+ if (byte1 >= 65 && byte1 <= 90) byte1 += 32;
68
+ if (byte2 >= 65 && byte2 <= 90) byte2 += 32;
69
+ if (byte3 >= 65 && byte3 <= 90) byte3 += 32;
70
+
71
+ return (byte0 | (byte1 << 8) | (byte2 << 16) | (byte3 << 24)) >>> 0;
72
+ }
73
+ export function remapSearchBuffer(buffer: Buffer) {
74
+ let newBuffer = Buffer.alloc(buffer.length);
75
+ buffer.copy(newBuffer);
76
+ buffer = newBuffer;
77
+ for (let i = 0; i < buffer.length; i++) {
78
+ let byte = buffer[i];
79
+ if (byte >= 65 && byte <= 90) {
80
+ buffer[i] = byte + 32;
81
+ } else {
82
+ buffer[i] = byte;
83
+ }
84
+ }
85
+ return buffer;
86
+ }
60
87
 
61
88
  export const getAllUnits = measureWrap(function getAllUnits(config: {
62
89
  buffer: Buffer;
@@ -71,7 +98,7 @@ export const getAllUnits = measureWrap(function getAllUnits(config: {
71
98
  const result: UnitRef[] = [];
72
99
  // For each byte position, create a unit from that position and the next 3 bytes
73
100
  for (let i = 0; i <= buffer.length - 4; i++) {
74
- const unit = buffer.readUint32LE(i);
101
+ const unit = remapUnit(buffer.readUint32LE(i));
75
102
  if (!unit) continue;
76
103
 
77
104
  result.push({
@@ -3,31 +3,79 @@
3
3
  import { LZ4 } from "../../../storage/LZ4";
4
4
  import { measureBlock, measureFnc } from "socket-function/src/profiling/measure";
5
5
  import { Zip } from "../../../zip";
6
- import { BufferReader, Reader, SearchParams, IndexedLogResults, Unit } from "./BufferIndexHelpers";
6
+ import { BufferReader, Reader, SearchParams, IndexedLogResults, Unit, remapUnit } from "./BufferIndexHelpers";
7
7
  import { formatNumber, formatPercent } from "socket-function/src/formatting/format";
8
8
  import { lazy } from "socket-function/src/caching";
9
9
  import { list, sort } from "socket-function/src/misc";
10
10
  import { testDisableCache } from "../../../-a-archives/archivesMemoryCache";
11
- import { devDebugbreak } from "../../../config";
11
+ import { devDebugbreak, isPublic } from "../../../config";
12
12
  import { BufferUnitIndexParallelSearchCount, DEFAULT_BLOCK_SIZE, DEFAULT_TARGET_UNITS_PER_BUCKET } from "./BufferIndexLogsOptimizationConstants";
13
13
  import { runInParallel } from "socket-function/src/batching";
14
- import { createMatchesPattern } from "./bufferMatcher";
14
+ import { createMatchesPattern } from "./bufferSearchFindMatcher";
15
+ import * as path from "path";
16
+ import * as fs from "fs";
17
+ import { runPromise } from "socket-function/src/runPromise";
18
+ import * as crypto from "crypto";
15
19
 
16
20
  const USE_COMPRESSION = true;
17
21
 
22
+ const getCppAddon = lazy(async () => {
23
+ if (typeof process === "undefined" || !process.versions || !process.versions.node) {
24
+ return undefined;
25
+ }
18
26
 
19
- // Lazy-load the C++ addon (only loaded when actually needed, not in client-side code)
20
- let getCppAddon = lazy(() => {
21
- try {
22
- // Check if we're in Node.js environment
23
- if (typeof process === "undefined" || !process.versions || !process.versions.node) {
27
+ const checkNeedsBuild = (): boolean => {
28
+ const cppFilePath = path.join(__dirname, "BufferIndexCPP.cpp");
29
+ const distPath = path.join(__dirname, "dist");
30
+ const versionFilePath = path.join(distPath, "BufferIndexCPP.version");
31
+ const buildPath = path.join(__dirname, "build");
32
+
33
+ if (!fs.existsSync(buildPath)) {
34
+ return true;
35
+ }
36
+ if (!fs.existsSync(versionFilePath)) {
37
+ return true;
38
+ }
39
+ try {
40
+ const cppFileContent = fs.readFileSync(cppFilePath, "utf-8");
41
+ const currentHash = crypto.createHash("sha256").update(cppFileContent).digest("hex");
42
+ const storedHash = fs.readFileSync(versionFilePath, "utf-8").trim();
43
+ if (storedHash !== currentHash) {
44
+ return true;
45
+ }
46
+ } catch (e) {
47
+ return true;
48
+ }
49
+ return false;
50
+ };
51
+
52
+ if (checkNeedsBuild()) {
53
+ try {
54
+ await runPromise("yarn build-native", {
55
+ cwd: __dirname
56
+ });
57
+ const cppFilePath = path.join(__dirname, "BufferIndexCPP.cpp");
58
+ const distPath = path.join(__dirname, "dist");
59
+ const versionFilePath = path.join(distPath, "BufferIndexCPP.version");
60
+ if (!fs.existsSync(distPath)) {
61
+ fs.mkdirSync(distPath, { recursive: true });
62
+ }
63
+ const cppFileContent = fs.readFileSync(cppFilePath, "utf-8");
64
+ const currentHash = crypto.createHash("sha256").update(cppFileContent).digest("hex");
65
+ fs.writeFileSync(versionFilePath, currentHash);
66
+ } catch (e) {
67
+ if (!isPublic()) {
68
+ require("debugbreak")(2);
69
+ debugger;
70
+ console.error(`Error building C++ addon: ${e}`);
71
+ }
24
72
  return undefined;
25
73
  }
26
- // Try to require the C++ addon
27
- const addon = require("./BufferIndexCPP") as typeof import("./BufferIndexCPP");
28
- return addon;
74
+ }
75
+
76
+ try {
77
+ return require("./BufferIndexCPP") as typeof import("./BufferIndexCPP");
29
78
  } catch (e) {
30
- console.warn("C++ addon not available, falling back to TypeScript implementation", e);
31
79
  return undefined;
32
80
  }
33
81
  });
@@ -107,14 +155,14 @@ export class BufferUnitIndex {
107
155
 
108
156
  // IMPORTANT! The input data values should be sorted from newest to oldest.
109
157
  @measureFnc
110
- public static encode(allData: Buffer[], options: {
158
+ public static async encode(allData: Buffer[], options: {
111
159
  type: number;
112
160
  blockSize?: number;
113
161
  targetUnitsPerBucket?: number;
114
- }): {
162
+ }): Promise<{
115
163
  blocks: Buffer;
116
164
  index: Buffer;
117
- } {
165
+ }> {
118
166
  const type = options.type;
119
167
  const BLOCK_SIZE = options.blockSize ?? DEFAULT_BLOCK_SIZE;
120
168
  const TARGET_UNITS_PER_BUCKET = options.targetUnitsPerBucket ?? DEFAULT_TARGET_UNITS_PER_BUCKET;
@@ -199,8 +247,8 @@ export class BufferUnitIndex {
199
247
  return Buffer.concat([blocksHeaderBuffer, ...compressedBlocks]);
200
248
  }, `createFinalBlocksBuffer`);
201
249
 
202
- const estimatedUniqueUnits = measureBlock(() => {
203
- const cppAddon = getCppAddon();
250
+ const estimatedUniqueUnits = await measureBlock(async () => {
251
+ const cppAddon = await getCppAddon();
204
252
  if (cppAddon) {
205
253
  // Use C++ addon for performance
206
254
  return cppAddon.estimateUniqueUnits(allData);
@@ -213,7 +261,7 @@ export class BufferUnitIndex {
213
261
 
214
262
  for (const buffer of allData) {
215
263
  for (let i = 0; i <= buffer.length - 4; i++) {
216
- const unit = buffer.readUint32LE(i);
264
+ const unit = remapUnit(buffer.readUint32LE(i));
217
265
  const maskedHash = getMaskedHash(unit, 0xFFFF);
218
266
 
219
267
  if (seenMaskedHashes[maskedHash] === 0) {
@@ -251,8 +299,8 @@ export class BufferUnitIndex {
251
299
 
252
300
 
253
301
  // Step 4: Build hash table with linked lists using Uint32Arrays for performance
254
- const { hashTable, linkedListData, nodeCount, filledSlots } = measureBlock(() => {
255
- const cppAddon = getCppAddon();
302
+ const { hashTable, linkedListData, nodeCount, filledSlots } = await measureBlock(async () => {
303
+ const cppAddon = await getCppAddon();
256
304
  if (cppAddon) {
257
305
  // Use C++ addon for performance
258
306
  return cppAddon.buildHashTable(blocksUncompressed, hashTableCapacity, mask);
@@ -298,7 +346,7 @@ export class BufferUnitIndex {
298
346
 
299
347
  // Iterate through all units and add them directly
300
348
  for (let i = 0; i <= blockUncompressed.length - 4; i++) {
301
- const unit = blockUncompressed.readUint32LE(i);
349
+ const unit = remapUnit(blockUncompressed.readUint32LE(i));
302
350
  const maskedHash = getMaskedHash(unit, mask);
303
351
 
304
352
  const currentHead = hashTable[maskedHash];
@@ -1,7 +1,7 @@
1
1
  import { formatPercent, formatNumber } from "socket-function/src/formatting/format";
2
2
  import { red } from "socket-function/src/formatting/logColors";
3
3
  import { measureFnc } from "socket-function/src/profiling/measure";
4
- import { Unit } from "./BufferIndexHelpers";
4
+ import { Unit, remapUnit } from "./BufferIndexHelpers";
5
5
 
6
6
  export class UnitSet {
7
7
  // Hash-based set for checking unit membership (no positions stored)
@@ -58,7 +58,7 @@ export class UnitSet {
58
58
  const buffer = block[bufferIndex];
59
59
  // Extract units directly
60
60
  for (let i = 0; i <= buffer.length - 4; i++) {
61
- const unit = buffer.readUint32LE(i);
61
+ const unit = remapUnit(buffer.readUint32LE(i));
62
62
  if (!unit) continue;
63
63
 
64
64
  totalInserts++;
@@ -283,8 +283,8 @@ export class LogViewer3 extends qreact.Component {
283
283
  forceReadProduction: readProductionLogsURL.value,
284
284
  },
285
285
  onResult: (match: LogDatum) => {
286
- console.log("onResult", match);
287
286
  results.push(match);
287
+ sort(results, x => -x.time);
288
288
  void updateResults();
289
289
  },
290
290
  onResults: (loggerStats: IndexedLogResults) => {
@@ -433,6 +433,52 @@ export class LogViewer3 extends qreact.Component {
433
433
  );
434
434
  }
435
435
 
436
+ renderForceMoveLogs() {
437
+ return <><Button
438
+ onClick={async () => {
439
+ Querysub.commitLocal(() => {
440
+ this.state.forceMoveStartTime = Date.now();
441
+ this.state.forceMoveEndTime = undefined;
442
+ });
443
+
444
+ let forceMoveInterval = setInterval(() => {
445
+ this.forceUpdate();
446
+ }, 100);
447
+
448
+ try {
449
+ let loggers = await getLoggers2Async();
450
+ for (let logger of Object.values(loggers)) {
451
+ await logger.clientForceMoveLogsToPublic();
452
+ }
453
+ await this.loadPaths();
454
+ } finally {
455
+ if (forceMoveInterval) {
456
+ clearInterval(forceMoveInterval);
457
+ }
458
+
459
+ Querysub.commitLocal(() => {
460
+ this.state.forceMoveEndTime = Date.now();
461
+ });
462
+ }
463
+ }}
464
+ hue={180}
465
+ >
466
+ Force Move Logs to Public
467
+ </Button>
468
+ {(() => {
469
+ if (this.state.forceMoveStartTime !== undefined && this.state.forceMoveEndTime === undefined) {
470
+ const elapsed = Date.now() - this.state.forceMoveStartTime;
471
+ return <div>Moving logs... {formatTime(elapsed)}</div>;
472
+ }
473
+ if (this.state.forceMoveStartTime !== undefined && this.state.forceMoveEndTime !== undefined) {
474
+ const duration = this.state.forceMoveEndTime - this.state.forceMoveStartTime;
475
+ return <div>Moved logs in {formatTime(duration)}</div>;
476
+ }
477
+ return undefined;
478
+ })()}
479
+ </>;
480
+ }
481
+
436
482
  renderPendingLogWarnings() {
437
483
  const paths = this.getPaths();
438
484
  const now = Date.now();
@@ -499,48 +545,7 @@ export class LogViewer3 extends qreact.Component {
499
545
  <span>is not moving logs to remote storage. {formatNumber(warning.count)} files ({formatNumber(warning.totalSize)}B) are {formatTime(now - warning.oldestTime)} old</span>
500
546
  </div>
501
547
  ))}
502
- {!isPublic() && !readProductionLogsURL.value && <Button
503
- onClick={async () => {
504
- Querysub.commitLocal(() => {
505
- this.state.forceMoveStartTime = Date.now();
506
- this.state.forceMoveEndTime = undefined;
507
- });
508
-
509
- let forceMoveInterval = setInterval(() => {
510
- this.forceUpdate();
511
- }, 100);
512
-
513
- try {
514
- let loggers = await getLoggers2Async();
515
- for (let logger of Object.values(loggers)) {
516
- await logger.clientForceMoveLogsToPublic();
517
- }
518
- await this.loadPaths();
519
- } finally {
520
- if (forceMoveInterval) {
521
- clearInterval(forceMoveInterval);
522
- }
523
-
524
- Querysub.commitLocal(() => {
525
- this.state.forceMoveEndTime = Date.now();
526
- });
527
- }
528
- }}
529
- hue={180}
530
- >
531
- Force Move Logs to Public
532
- </Button>}
533
- {(() => {
534
- if (this.state.forceMoveStartTime !== undefined && this.state.forceMoveEndTime === undefined) {
535
- const elapsed = Date.now() - this.state.forceMoveStartTime;
536
- return <div>Moving logs... {formatTime(elapsed)}</div>;
537
- }
538
- if (this.state.forceMoveStartTime !== undefined && this.state.forceMoveEndTime !== undefined) {
539
- const duration = this.state.forceMoveEndTime - this.state.forceMoveStartTime;
540
- return <div>Moved logs in {formatTime(duration)}</div>;
541
- }
542
- return undefined;
543
- })()}
548
+ {!isPublic() && !readProductionLogsURL.value && this.renderForceMoveLogs()}
544
549
  </>
545
550
  )}
546
551
  </div>
@@ -709,6 +714,7 @@ export class LogViewer3 extends qreact.Component {
709
714
  number
710
715
  url={limitURL}
711
716
  />
717
+ {!isPublic() && this.renderForceMoveLogs()}
712
718
  </div>
713
719
 
714
720
  <div className={css.hbox(10)}>
@@ -1,5 +1,5 @@
1
1
  import { measureWrap } from "socket-function/src/profiling/measure";
2
- import { Unit, getAllUnits } from "./BufferIndexHelpers";
2
+ import { Unit, getAllUnits, remapSearchBuffer } from "./BufferIndexHelpers";
3
3
 
4
4
  const WILD_CARD_BYTE = 42;
5
5
  const WILD_CARD_CHAR = "*";
@@ -54,6 +54,8 @@ function parseMatchStructure(pattern: Buffer): MatchStructure {
54
54
  }
55
55
  // inside is and, outside is outer
56
56
  export function getSearchUnits(pattern: Buffer, disableSpecialCharacters: boolean): Unit[][] {
57
+ pattern = remapSearchBuffer(pattern);
58
+
57
59
  if (disableSpecialCharacters || !pattern.includes(SEARCH_OR_BYTE) && !pattern.includes(SEARCH_AND_BYTE) && !pattern.includes(WILD_CARD_BYTE)) {
58
60
  return [getAllUnits({ buffer: pattern, bufferIndex: 0, block: 0 }).map(u => u.unit)];
59
61
  }
@@ -107,9 +109,11 @@ function getSimplerStructure(structure: MatchStructure): Buffer[][] {
107
109
  // side must appear in order somewhere within buffer.
108
110
  // Returns a function that matches buffers against the pre-processed pattern.
109
111
  export function createMatchesPattern(pattern: Buffer, disableSpecialCharacters: boolean): (buffer: Buffer) => boolean {
112
+ pattern = remapSearchBuffer(pattern);
110
113
 
111
114
  if (disableSpecialCharacters || !pattern.includes(SEARCH_OR_BYTE) && !pattern.includes(SEARCH_AND_BYTE) && !pattern.includes(WILD_CARD_BYTE)) {
112
115
  return measureWrap(function matchesPattern(buffer: Buffer): boolean {
116
+ buffer = remapSearchBuffer(buffer);
113
117
  return buffer.indexOf(pattern) !== -1;
114
118
  }, "BufferIndex|matchesPatternExact");
115
119
  }
@@ -120,6 +124,7 @@ export function createMatchesPattern(pattern: Buffer, disableSpecialCharacters:
120
124
  let hasAnyWildcard = pattern.includes(WILD_CARD_BYTE);
121
125
 
122
126
  return measureWrap(function matchesPattern(buffer: Buffer): boolean {
127
+ buffer = remapSearchBuffer(buffer);
123
128
  // 1) First, use simplerStructure to exclude any false cases
124
129
  // simplerStructure is Buffer[][] where outer array is OR, inner array is AND
125
130
  let anyOrClausePassed = false;
@@ -147,7 +147,7 @@ export async function moveLogsToPublic(config: {
147
147
  }));
148
148
  if (buffers.length === 0) continue;
149
149
 
150
- console.log(magenta(`Merging and moving ${group.length} log files backblaze`));
150
+ console.log(magenta(`Merging and moving ${group.length} log files backblaze (${blue(config.loggerName)})`));
151
151
 
152
152
  let allBuffers: Buffer[][] = [];
153
153
 
@@ -188,7 +188,7 @@ export async function moveLogsToPublic(config: {
188
188
  for (let buffer of group) {
189
189
  uncompressedSize += buffer.length;
190
190
  }
191
- let obj = BufferIndex.encodeAll({
191
+ let obj = await BufferIndex.encodeAll({
192
192
  data: group,
193
193
  });
194
194
  encoded.push({
@@ -221,7 +221,7 @@ export async function moveLogsToPublic(config: {
221
221
  await localLogs.del(path.fullPath + indexExtension);
222
222
  }));
223
223
 
224
- console.log(green(`(${i + 1}/${groups.length}) Wrote ${encoded.length} log files to public (${formatNumber(encoded.reduce((acc, x) => acc + x.uncompressedSize, 0))}B compressed to ${formatNumber(encoded.reduce((acc, x) => acc + x.compressedSize, 0))}B + ${formatNumber(encoded.reduce((acc, x) => acc + x.index.length, 0))}B index) in ${formatTime(Date.now() - time)}`));
224
+ console.log(green(`(${i + 1}/${groups.length}) Wrote ${encoded.length} log files to public (${formatNumber(encoded.reduce((acc, x) => acc + x.uncompressedSize, 0))}B compressed to ${formatNumber(encoded.reduce((acc, x) => acc + x.compressedSize, 0))}B + ${formatNumber(encoded.reduce((acc, x) => acc + x.index.length, 0))}B index) in ${formatTime(Date.now() - time)}`) + ` (${blue(config.loggerName)})`);
225
225
  }
226
226
 
227
227
  // Clean up orphaned index files (index files without corresponding data files)
@@ -1,3 +1,9 @@
1
1
 
2
2
  //todonext
3
- // FIRST, finish up our logs stuff, which is just about done...
3
+
4
+ // single service, no history search, discord messaging, suppression and suppression page
5
+ // - Storing suppression history just in memory? (although suppression values, obviously, on disk)
6
+ // - receive all errors, and service will do suppression
7
+
8
+ // Start with page itself showing errors and suppressing them, for debugging/testing
9
+ // - Ai to automatically create suppression searches, and combine existing ones, etc
@@ -24,7 +24,6 @@ IMPORTANT! Now I am properly calling shutdown, so none of the streamed logs shou
24
24
  2) Create lot of remote server logs
25
25
  - Via our refresh loop
26
26
 
27
-
28
27
  3) Verify search is still fast, and works correctly!
29
28
  - Try to get a rare value in that is in the logs, but is hard to find
30
29
  Good rare search. Checks for sending emails, which we do very rarely. If we pack in 10GB of logs after this, it will really stress our indexing system.
@@ -32,13 +31,6 @@ IMPORTANT! Now I am properly calling shutdown, so none of the streamed logs shou
32
31
  https://127-0-0-1.querysubtest.com:7007/?hot&readPublicLogs&showingmanagement&machineview=services&managementpage=LogViewer3&searchText=Sending%20email&selectedFields=%7B%22path%22%3Atrue%7D
33
32
 
34
33
 
35
-
36
- Remove old error digest/notification code
37
- - We don't need email digests anymore. I think discord messaging is enough
38
- Remove all old LogViewer/FastArchiveAppendable code
39
- - Make sure to find all links and update them as well
40
-
41
-
42
34
 
43
35
  Rewrite error notification code
44
36
  - Single service, which talks to all machines
@@ -1,23 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- // Only run build-native if we're being installed as a dependency in someone else's project
4
- // Not when we're the root project adding new dependencies
5
- const path = require("path");
6
- const { execSync } = require("child_process");
7
-
8
- // Check if we're in node_modules (installed as a dependency)
9
- const isInstalledAsDependency = __dirname.includes("node_modules");
10
-
11
- if (isInstalledAsDependency) {
12
- console.log("Running native build for querysub...");
13
- try {
14
- execSync("node-gyp rebuild", {
15
- cwd: path.join(__dirname, "..", "src", "diagnostics", "logs", "IndexedLogs"),
16
- stdio: "inherit"
17
- });
18
- } catch (err) {
19
- console.log("Native build failed (this is okay, continuing...)");
20
- }
21
- } else {
22
- console.log("Skipping native build (running in development)");
23
- }