querysub 0.403.0 → 0.404.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.
Files changed (107) hide show
  1. package/.cursorrules +2 -0
  2. package/bin/audit-imports.js +4 -0
  3. package/package.json +7 -4
  4. package/spec.txt +77 -0
  5. package/src/-a-archives/archiveCache.ts +9 -4
  6. package/src/-a-archives/archivesBackBlaze.ts +1039 -1039
  7. package/src/-a-auth/certs.ts +0 -12
  8. package/src/-c-identity/IdentityController.ts +12 -3
  9. package/src/-f-node-discovery/NodeDiscovery.ts +32 -26
  10. package/src/-g-core-values/NodeCapabilities.ts +12 -2
  11. package/src/0-path-value-core/AuthorityLookup.ts +239 -0
  12. package/src/0-path-value-core/LockWatcher2.ts +150 -0
  13. package/src/0-path-value-core/PathRouter.ts +535 -0
  14. package/src/0-path-value-core/PathRouterRouteOverride.ts +72 -0
  15. package/src/0-path-value-core/PathRouterServerAuthoritySpec.tsx +65 -0
  16. package/src/0-path-value-core/PathValueCommitter.ts +222 -488
  17. package/src/0-path-value-core/PathValueController.ts +277 -239
  18. package/src/0-path-value-core/PathWatcher.ts +534 -0
  19. package/src/0-path-value-core/ShardPrefixes.ts +31 -0
  20. package/src/0-path-value-core/ValidStateComputer.ts +303 -0
  21. package/src/0-path-value-core/archiveLocks/ArchiveLocks.ts +1 -1
  22. package/src/0-path-value-core/archiveLocks/ArchiveLocks2.ts +80 -44
  23. package/src/0-path-value-core/archiveLocks/archiveSnapshots.ts +13 -16
  24. package/src/0-path-value-core/auditLogs.ts +2 -0
  25. package/src/0-path-value-core/hackedPackedPathParentFiltering.ts +97 -0
  26. package/src/0-path-value-core/pathValueArchives.ts +490 -492
  27. package/src/0-path-value-core/pathValueCore.ts +195 -1496
  28. package/src/0-path-value-core/startupAuthority.ts +74 -0
  29. package/src/1-path-client/RemoteWatcher.ts +90 -82
  30. package/src/1-path-client/pathValueClientWatcher.ts +808 -815
  31. package/src/2-proxy/PathValueProxyWatcher.ts +10 -8
  32. package/src/2-proxy/archiveMoveHarness.ts +182 -214
  33. package/src/2-proxy/garbageCollection.ts +9 -8
  34. package/src/2-proxy/schema2.ts +21 -1
  35. package/src/3-path-functions/PathFunctionHelpers.ts +206 -180
  36. package/src/3-path-functions/PathFunctionRunner.ts +943 -766
  37. package/src/3-path-functions/PathFunctionRunnerMain.ts +5 -3
  38. package/src/3-path-functions/pathFunctionLoader.ts +2 -2
  39. package/src/3-path-functions/syncSchema.ts +592 -521
  40. package/src/4-deploy/deployFunctions.ts +19 -4
  41. package/src/4-deploy/deployGetFunctionsInner.ts +8 -2
  42. package/src/4-deploy/deployMain.ts +51 -68
  43. package/src/4-deploy/edgeClientWatcher.tsx +1 -1
  44. package/src/4-deploy/edgeNodes.ts +2 -2
  45. package/src/4-dom/qreact.tsx +2 -4
  46. package/src/4-dom/qreactTest.tsx +7 -13
  47. package/src/4-querysub/Querysub.ts +21 -8
  48. package/src/4-querysub/QuerysubController.ts +45 -29
  49. package/src/4-querysub/permissions.ts +2 -2
  50. package/src/4-querysub/querysubPrediction.ts +80 -70
  51. package/src/4-querysub/schemaHelpers.ts +5 -1
  52. package/src/5-diagnostics/GenericFormat.tsx +14 -9
  53. package/src/archiveapps/archiveGCEntry.tsx +9 -2
  54. package/src/archiveapps/archiveJoinEntry.ts +87 -84
  55. package/src/archiveapps/archiveMergeEntry.tsx +2 -0
  56. package/src/bits.ts +19 -0
  57. package/src/config.ts +21 -3
  58. package/src/config2.ts +23 -48
  59. package/src/deployManager/components/DeployPage.tsx +7 -3
  60. package/src/deployManager/machineSchema.ts +4 -1
  61. package/src/diagnostics/ActionsHistory.ts +3 -8
  62. package/src/diagnostics/AuditLogPage.tsx +2 -3
  63. package/src/diagnostics/FunctionCallInfo.tsx +141 -0
  64. package/src/diagnostics/FunctionCallInfoState.ts +162 -0
  65. package/src/diagnostics/MachineThreadInfo.tsx +1 -1
  66. package/src/diagnostics/NodeViewer.tsx +37 -48
  67. package/src/diagnostics/SyncTestPage.tsx +241 -0
  68. package/src/diagnostics/auditImportViolations.ts +185 -0
  69. package/src/diagnostics/listenOnDebugger.ts +3 -3
  70. package/src/diagnostics/logs/IndexedLogs/BufferUnitSet.ts +10 -4
  71. package/src/diagnostics/logs/IndexedLogs/IndexedLogs.ts +2 -2
  72. package/src/diagnostics/logs/IndexedLogs/LogViewer3.tsx +24 -22
  73. package/src/diagnostics/logs/IndexedLogs/moveIndexLogsToPublic.ts +1 -1
  74. package/src/diagnostics/logs/diskLogGlobalContext.ts +1 -0
  75. package/src/diagnostics/logs/errorNotifications2/logWatcher.ts +1 -3
  76. package/src/diagnostics/logs/lifeCycleAnalysis/LifeCycleEntryEditor.tsx +34 -16
  77. package/src/diagnostics/logs/lifeCycleAnalysis/LifeCycleEntryReadMode.tsx +4 -6
  78. package/src/diagnostics/logs/lifeCycleAnalysis/LifeCycleInstanceTableView.tsx +36 -5
  79. package/src/diagnostics/logs/lifeCycleAnalysis/LifeCyclePage.tsx +19 -5
  80. package/src/diagnostics/logs/lifeCycleAnalysis/LifeCycleRenderer.tsx +15 -7
  81. package/src/diagnostics/logs/lifeCycleAnalysis/NestedLifeCycleInfo.tsx +28 -106
  82. package/src/diagnostics/logs/lifeCycleAnalysis/lifeCycleMatching.ts +2 -0
  83. package/src/diagnostics/logs/lifeCycleAnalysis/lifeCycleMisc.ts +0 -0
  84. package/src/diagnostics/logs/lifeCycleAnalysis/lifeCycleSearch.tsx +18 -7
  85. package/src/diagnostics/logs/lifeCycleAnalysis/lifeCycles.tsx +3 -0
  86. package/src/diagnostics/managementPages.tsx +10 -3
  87. package/src/diagnostics/misc-pages/ArchiveViewer.tsx +20 -26
  88. package/src/diagnostics/misc-pages/ArchiveViewerTree.tsx +6 -4
  89. package/src/diagnostics/misc-pages/ComponentSyncStats.tsx +2 -2
  90. package/src/diagnostics/misc-pages/LocalWatchViewer.tsx +7 -9
  91. package/src/diagnostics/misc-pages/SnapshotViewer.tsx +23 -12
  92. package/src/diagnostics/misc-pages/archiveViewerShared.tsx +1 -1
  93. package/src/diagnostics/pathAuditer.ts +486 -0
  94. package/src/diagnostics/pathAuditerCallback.ts +20 -0
  95. package/src/diagnostics/watchdog.ts +8 -1
  96. package/src/library-components/URLParam.ts +1 -1
  97. package/src/misc/hash.ts +1 -0
  98. package/src/path.ts +21 -7
  99. package/src/server.ts +54 -47
  100. package/src/user-implementation/loginEmail.tsx +1 -1
  101. package/tempnotes.txt +67 -0
  102. package/test.ts +288 -95
  103. package/src/0-path-value-core/NodePathAuthorities.ts +0 -1057
  104. package/src/0-path-value-core/PathController.ts +0 -1
  105. package/src/5-diagnostics/diskValueAudit.ts +0 -218
  106. package/src/5-diagnostics/memoryValueAudit.ts +0 -438
  107. package/src/archiveapps/lockTest.ts +0 -127
@@ -15,11 +15,9 @@ import { ClientWatcher, WatchSpecData, clientWatcher } from "../1-path-client/pa
15
15
  import { createPathValueProxy, getPathFromProxy, getProxyPath, getProxyPathAndWatch, isValueProxy, isValueProxy2 } from "./pathValueProxy";
16
16
  import { authorityStorage, compareTime, ReadLock, epochTime, getNextTime, MAX_ACCEPTED_CHANGE_AGE, PathValue, Time, getCreatorId, getTimeUnique } from "../0-path-value-core/pathValueCore";
17
17
  import { runCodeWithDatabase, rawSchema } from "./pathDatabaseProxyBase";
18
- import { LOCAL_DOMAIN } from "../0-path-value-core/PathController";
19
18
  import debugbreak from "debugbreak";
20
19
  import { pathValueCommitter } from "../0-path-value-core/PathValueController";
21
20
  import { pathValueSerializer } from "../-h-path-value-serialize/PathValueSerializer";
22
- import { LOCAL_DOMAIN_PATH } from "../0-path-value-core/NodePathAuthorities";
23
21
  import { registerPeriodic } from "../diagnostics/periodic";
24
22
  import { remoteWatcher } from "../1-path-client/RemoteWatcher";
25
23
  import { Schema2, Schema2Fncs } from "./schema2";
@@ -29,7 +27,6 @@ import type { CallSpec } from "../3-path-functions/PathFunctionRunner";
29
27
  import type { FunctionMetadata } from "../3-path-functions/syncSchema";
30
28
 
31
29
  import { DEPTH_TO_DATA, MODULE_INDEX, getCurrentCall, getCurrentCallObj } from "../3-path-functions/PathFunctionRunner";
32
- import { inlineNestedCalls } from "../3-path-functions/syncSchema";
33
30
  import { interceptCallsBase, runCall } from "../3-path-functions/PathFunctionHelpers";
34
31
  import { deepCloneCborx } from "../misc/cloneHelpers";
35
32
  import { formatNumber, formatPercent, formatTime } from "socket-function/src/formatting/format";
@@ -118,6 +115,7 @@ export interface WatcherOptions<Result> {
118
115
  atomicWrites?: boolean;
119
116
 
120
117
  debugName?: string;
118
+ source?: string;
121
119
 
122
120
  watchFunction: () => Result;
123
121
  baseFunction?: Function;
@@ -281,7 +279,7 @@ const getAllowedLockDomainsPrefixes = function getTrustedDomains(): string[] {
281
279
  // another user clicks at the same time and we race. Or... something? Maybe there
282
280
  // are no cases when we need it... and it would definitely slow things down, so...
283
281
  // maybe we just don't?
284
- return [getPathStr1(LOCAL_DOMAIN)];
282
+ return [LOCAL_DOMAIN_PATH];
285
283
  }
286
284
  };
287
285
 
@@ -1500,7 +1498,7 @@ export class PathValueProxyWatcher {
1500
1498
 
1501
1499
  return result;
1502
1500
  }
1503
- function updateWatchers(initialTriggerWatch?: boolean) {
1501
+ function updateWatchers() {
1504
1502
  watcher.lastWatches = {
1505
1503
  paths: watcher.pendingWatches.paths,
1506
1504
  parentPaths: watcher.pendingWatches.parentPaths,
@@ -1652,6 +1650,7 @@ export class PathValueProxyWatcher {
1652
1650
  eventWrite: options.eventWrite,
1653
1651
  dryRun: options.dryRun,
1654
1652
  forcedUndefinedWrites,
1653
+ source: options.source,
1655
1654
  });
1656
1655
  }
1657
1656
 
@@ -1882,7 +1881,7 @@ export class PathValueProxyWatcher {
1882
1881
  dispose();
1883
1882
  } else {
1884
1883
  // Set our watchers
1885
- updateWatchers(true);
1884
+ updateWatchers();
1886
1885
  clientWatcher.explicitlyTriggerWatcher(trigger, {
1887
1886
  synchronous: options.synchronousInit,
1888
1887
  });
@@ -2457,7 +2456,7 @@ const finishProxyAndTriggerNext = runInSerial(
2457
2456
  }
2458
2457
  }
2459
2458
  );
2460
- function isProxyBlockedByOrder(proxy: SyncWatcher): boolean {
2459
+ export function isProxyBlockedByOrder(proxy: SyncWatcher): boolean {
2461
2460
  let order = getProxyOrder(proxy);
2462
2461
  if (order === undefined) return false;
2463
2462
  let index = binarySearchBasic(proxiesOrdered, x => getProxyOrder(x) || 0, order);
@@ -2505,4 +2504,7 @@ registerPeriodic(function logWatcherTypes() {
2505
2504
  }
2506
2505
  });
2507
2506
 
2508
- // #endregion Proxy Ordering
2507
+ // #endregion Proxy Ordering
2508
+
2509
+ import { inlineNestedCalls } from "../3-path-functions/syncSchema"; import { LOCAL_DOMAIN_PATH } from "../0-path-value-core/PathRouter";
2510
+
@@ -1,27 +1,21 @@
1
1
  import { formatNumber, formatTime } from "socket-function/src/formatting/format";
2
2
  import { blue, green, red } from "socket-function/src/formatting/logColors";
3
3
  import { measureBlock, measureWrap } from "socket-function/src/profiling/measure";
4
- import { AuthorityPath, pathValueAuthority2 } from "../0-path-value-core/NodePathAuthorities";
5
4
  import { FileInfo, ArchiveTransaction } from "../0-path-value-core/archiveLocks/ArchiveLocks";
6
5
  import { DecodedValuePath, pathValueArchives, PathValueArchives } from "../0-path-value-core/pathValueArchives";
7
6
  import { PathValue, VALUE_GC_THRESHOLD, FILE_VALUE_COUNT_LIMIT, FILE_SIZE_LIMIT, compareTime } from "../0-path-value-core/pathValueCore";
8
7
  import { getSingleSizeEstimate } from "../5-diagnostics/shared";
9
- import { getOurAuthorities } from "../config2";
10
8
  import { logNodeStats } from "../-0-hooks/hooks";
11
9
  import debugbreak from "debugbreak";
12
-
13
- // NOTE: We probably COULD load values with skipStrings+skipValues, for some GCers, as some
14
- // GCing is as simple as, "if this value is undefined, delete it". But... we GC
15
- // so seldomly, that it wouldn't make a difference (going from 1 minute of GC time
16
- // per day to 20 seconds doesn't really matter).
17
-
18
- let lastFileWrites = new Map<string, string[]>();
10
+ import { AuthorityEntry } from "../0-path-value-core/AuthorityLookup";
11
+ import { AuthoritySpec, PathRouter } from "../0-path-value-core/PathRouter";
12
+ import { getOurAuthoritySpec } from "../0-path-value-core/PathRouterServerAuthoritySpec";
19
13
 
20
14
  export async function runArchiveMover(config: {
21
15
  debugName: string;
22
16
  // Defaults to getOurAuthorities
23
17
  // NOTE: Runs once per authority, as we want to keep data as sharded as possible
24
- authorities?: AuthorityPath[];
18
+ authority?: AuthoritySpec;
25
19
 
26
20
  // If set we will provide all values. This means this is a high chance out of order values will
27
21
  // be provided. Otherwise a consistent view of data at Date.now() - ARCHIVE_FLUSH_LIMIT
@@ -60,9 +54,8 @@ export async function runArchiveMover(config: {
60
54
  * - Of course, if readLiveData is set this is Number.POSITIVE_INFINITY, as we
61
55
  * try to provide the latest data... making this no longer an atomic snapshot.
62
56
  */
63
- authority: AuthorityPath;
57
+ authority: AuthoritySpec;
64
58
  snapshotTime: number;
65
- logKey: string;
66
59
  }
67
60
  ) => Promise<{
68
61
  newValues: "abort" | {
@@ -73,7 +66,7 @@ export async function runArchiveMover(config: {
73
66
  };
74
67
  }>;
75
68
  }) {
76
- let authorities = config.authorities ?? getOurAuthorities();
69
+ let authority = config.authority ?? await getOurAuthoritySpec(true);
77
70
  let minAge = config.readLiveData ? Number.NEGATIVE_INFINITY : VALUE_GC_THRESHOLD;
78
71
  let minThreshold = Date.now() - minAge;
79
72
  // NOTE: If the value count is too high, parsing in the ArchiveViewer might crash the browser.
@@ -100,232 +93,207 @@ export async function runArchiveMover(config: {
100
93
  return meets;
101
94
  }
102
95
 
103
- // NOTE: We COULD read from all authorities, handling them all at once. This MIGHT making
104
- // gcing more efficient. But... it also might not. We'll see.
105
- // - And, sharding shouldn't be random, it should be path based, just like GCing. Although,
106
- // if we have references, the best we can do is add parallel authorities to nodes,
107
- // so... we might have to handle all authorities at once, instead of looping like this...
108
- for (let authority of authorities) {
109
- let locker = await pathValueArchives.getArchiveLocker();
110
- let matchedDirs = await pathValueArchives.getAuthorityDirs(authority);
111
- let authorityDir = pathValueAuthority2.getArchiveDirectory(authority);
112
-
113
- let startTime = Date.now();
114
- let readCache = new Map<string, Buffer>();
115
- let lastAborted = false;
116
- let lastResult: "accepted" | "rejected" | "aborted" = "accepted";
96
+ let locker = await pathValueArchives.getArchiveLocker();
117
97
 
118
- let inputBytes = 0;
119
- let outputBytes = 0;
120
- let inputValueCount = 0;
121
- let outputValueCount = 0;
122
- let inputFiles = 0;
123
- let outputFiles = 0;
124
- let abortedDueToInsufficientReduction = false;
98
+ let startTime = Date.now();
99
+ let readCache = new Map<string, Buffer>();
100
+ let lastAborted = false;
101
+ let lastResult: "accepted" | "rejected" | "aborted" = "accepted";
125
102
 
126
- let reread = true;
127
- while (reread) {
128
- reread = false;
129
- lastAborted = false;
130
- lastResult = await locker.atomicSwapFiles({
131
- allowDuplicates: config.allowDuplicates,
132
- }, async (valueFiles, readFiles) => {
133
- valueFiles = valueFiles.filter(x => matchedDirs.some(y => x.file.startsWith(y)));
103
+ let inputBytes = 0;
104
+ let outputBytes = 0;
105
+ let inputValueCount = 0;
106
+ let outputValueCount = 0;
107
+ let inputFiles = 0;
108
+ let outputFiles = 0;
109
+ let abortedDueToInsufficientReduction = false;
134
110
 
135
- valueFiles = valueFiles.filter(x => {
136
- let obj = pathValueArchives.decodeDataPath(x.file);
137
- if (!obj.minTime) return true;
138
- return !(obj.minTime > minThreshold);
139
- });
111
+ let reread = true;
112
+ while (reread) {
113
+ reread = false;
114
+ lastAborted = false;
115
+ lastResult = await locker.atomicSwapFiles({
116
+ allowDuplicates: config.allowDuplicates,
117
+ }, async (valueFiles, readFiles) => {
118
+ valueFiles = valueFiles.filter(x => PathRouter.overlapsPathIdentifier(authority, x.file));
140
119
 
141
- let lastWriteHash = JSON.stringify(matchedDirs);
142
- // NOTE: ACTUALLY, this doesn't work, as the oldFiles might values which have GC timers,
143
- // or which... are large, and just became deleted.
144
- // let lastFiles = new Set(lastFileWrites.get(lastWriteHash) || []);
145
- // let newFiles = valueFiles.filter(x => !lastFiles.has(x.file));
146
- // // BEST case, ALL oldFiles are collapsed. And if that doesn't even cause a move,
147
- // // then just skip the check now
148
- // if (!config.force && meetsThreshold({
149
- // inputFiles: valueFiles.length,
150
- // inputBytes: valueFiles.map(x => x.size).reduce((a, b) => a + b, 0),
151
- // outputFiles: newFiles.length,
152
- // outputBytes: newFiles.map(x => x.size).reduce((a, b) => a + b, 0),
153
- // })) {
154
- // return [];
155
- // }
120
+ valueFiles = valueFiles.filter(x => {
121
+ let obj = pathValueArchives.decodeDataPath(x.file);
122
+ if (!obj.minTime) return true;
123
+ return !(obj.minTime > minThreshold);
124
+ });
156
125
 
157
- // Read files, and if any are missing, rerun until we can read all files
158
- await measureBlock(async function locker_readFiles() {
159
- let remainingFiles = valueFiles.filter(x => !readCache.has(x.file));
160
- let buffers = await readFiles(remainingFiles);
161
- for (let i = 0; i < remainingFiles.length; i++) {
162
- let buffer = buffers[i];
163
- if (!buffer) {
164
- console.log(`File missing, re-reading`, remainingFiles[i].file);
165
- reread = true;
166
- break;
167
- }
168
- readCache.set(remainingFiles[i].file, buffer);
126
+ // Read files, and if any are missing, rerun until we can read all files
127
+ await measureBlock(async function locker_readFiles() {
128
+ let remainingFiles = valueFiles.filter(x => !readCache.has(x.file));
129
+ let buffers = await readFiles(remainingFiles);
130
+ for (let i = 0; i < remainingFiles.length; i++) {
131
+ let buffer = buffers[i];
132
+ if (!buffer) {
133
+ console.log(`File missing, re-reading`, remainingFiles[i].file);
134
+ reread = true;
135
+ break;
169
136
  }
170
- });
171
- if (reread) {
172
- console.log(`Files changed, re-reading`);
173
- return [];
174
- }
175
- function isValueIncluded(value: PathValue) {
176
- if (value.time.time > minThreshold) return false;
177
- if (!pathValueAuthority2.isInAuthority(authority, value.path)) return false;
178
- return true;
137
+ readCache.set(remainingFiles[i].file, buffer);
179
138
  }
139
+ });
140
+ if (reread) {
141
+ console.log(`Files changed, re-reading`);
142
+ return [];
143
+ }
144
+ function isValueIncluded(value: PathValue) {
145
+ if (value.time.time > minThreshold) return false;
146
+ if (!PathRouter.matchesAuthoritySpec(authority, value.path)) return false;
147
+ return true;
148
+ }
180
149
 
181
- let mutatedFiles: FileInfo[] = [];
182
- // authorityFolder => values
183
- let floatingValues = new Map<string, PathValue[][]>();
184
- let inputValues: PathValue[][] = [];
185
- inputBytes = 0;
186
- inputFiles = 0;
187
- inputValueCount = 0;
150
+ let mutatedFiles: FileInfo[] = [];
151
+ // authorityFolder => values
152
+ let floatingValues = new Map<string, PathValue[][]>();
153
+ let inputValues: PathValue[][] = [];
154
+ inputBytes = 0;
155
+ inputFiles = 0;
156
+ inputValueCount = 0;
188
157
 
189
- await measureBlock(async function locker_parseFiles() {
190
- for (let file of valueFiles) {
191
- let buffer = readCache.get(file.file);
192
- if (!buffer) {
193
- throw new Error(`Buffer missing for ${file.file}`);
194
- }
195
- inputBytes += buffer.byteLength;
196
- inputFiles++;
197
- let valuesObj = await PathValueArchives.loadValuesFromBuffer({
198
- path: file.file,
199
- data: buffer,
200
- });
201
- let values = valuesObj.values;
202
- inputValueCount += values.length;
203
- let includedValues: PathValue[] = [];
204
- let excludedValues: PathValue[] = [];
205
- for (let value of values) {
206
- if (isValueIncluded(value)) {
207
- includedValues.push(value);
208
- } else {
209
- excludedValues.push(value);
210
- }
211
- }
212
- if (includedValues.length === 0) {
213
- continue;
158
+ await measureBlock(async function locker_parseFiles() {
159
+ for (let file of valueFiles) {
160
+ let buffer = readCache.get(file.file);
161
+ if (!buffer) {
162
+ throw new Error(`Buffer missing for ${file.file}`);
163
+ }
164
+ inputBytes += buffer.byteLength;
165
+ inputFiles++;
166
+ let valuesObj = await PathValueArchives.loadValuesFromBuffer({
167
+ path: file.file,
168
+ data: buffer,
169
+ });
170
+ let values = valuesObj.values;
171
+ inputValueCount += values.length;
172
+ let includedValues: PathValue[] = [];
173
+ let excludedValues: PathValue[] = [];
174
+ for (let value of values) {
175
+ if (isValueIncluded(value)) {
176
+ includedValues.push(value);
177
+ } else {
178
+ excludedValues.push(value);
214
179
  }
215
- if (excludedValues.length > 0) {
216
- let fileDir = file.file.split("/").slice(0, -1).join("/") + "/";
217
- let list = floatingValues.get(fileDir);
218
- if (!list) {
219
- floatingValues.set(fileDir, list = []);
220
- }
221
- list.push(excludedValues);
180
+ }
181
+ if (includedValues.length === 0) {
182
+ continue;
183
+ }
184
+ if (excludedValues.length > 0) {
185
+ let fileDir = file.file.split("/").slice(0, -1).join("/") + "/";
186
+ let list = floatingValues.get(fileDir);
187
+ if (!list) {
188
+ floatingValues.set(fileDir, list = []);
222
189
  }
223
- inputValues.push(includedValues);
224
- mutatedFiles.push(file);
190
+ list.push(excludedValues);
225
191
  }
226
- });
227
-
228
- let inputValuesFlat = inputValues.flat();
229
- let result = await measureBlock(async function locker_runApp() {
230
- return config.runMover({
231
- values: inputValuesFlat,
232
- authority,
233
- snapshotTime: minThreshold,
234
- logKey: authorityDir,
235
- });
236
- }, `locker_app_${config.runMover.name}`);
237
- if (result.newValues === "abort") {
238
- lastAborted = true;
239
- return [];
192
+ inputValues.push(includedValues);
193
+ mutatedFiles.push(file);
240
194
  }
195
+ });
241
196
 
242
- let transaction: ArchiveTransaction = {
243
- createFiles: [],
244
- deleteFiles: mutatedFiles,
245
- };
246
- const addValues = measureWrap(async function locker_addValues(dir: string, values: PathValue[], key: string) {
247
- let split = splitValuesBelowLimit({
248
- values,
249
- maxFileValueCount,
250
- maxFileByteCount,
251
- });
252
- outputFiles += split.length;
253
- outputValueCount += values.length;
254
- for (let splitValue of split) {
255
- let dataObj = await pathValueArchives.encodeValuePaths(splitValue.values, {
256
- pathOverrides: {
257
- sourceType: config.outputType,
258
- misc: key,
259
- },
260
- });
261
- if (!dataObj) continue;
262
- outputBytes += dataObj.data.byteLength;
263
- let fileName = pathValueArchives.encodeDataPath({
264
- ...pathValueArchives.getDefaultValuePathInput(),
265
- valueCount: splitValue.values.length,
266
- byteCount: dataObj.data.byteLength,
267
- minTime: splitValue.minTime,
268
- maxTime: splitValue.maxTime,
269
- sourceType: config.outputType,
270
- misc: key,
271
- });
272
- transaction.createFiles.push({
273
- data: dataObj.data,
274
- file: dir + fileName,
275
- });
276
- }
197
+ let inputValuesFlat = inputValues.flat();
198
+ let result = await measureBlock(async function locker_runApp() {
199
+ return config.runMover({
200
+ values: inputValuesFlat,
201
+ authority,
202
+ snapshotTime: minThreshold,
277
203
  });
204
+ }, `locker_app_${config.runMover.name}`);
205
+ if (result.newValues === "abort") {
206
+ lastAborted = true;
207
+ return [];
208
+ }
278
209
 
279
- for (let [authorityDir, values] of floatingValues) {
280
- await addValues(authorityDir, values.flat(), "floating");
210
+ let transaction: ArchiveTransaction = {
211
+ createFiles: [],
212
+ deleteFiles: mutatedFiles,
213
+ };
214
+ const addValues = measureWrap(async function locker_addValues(dir: string, values: PathValue[], key: string) {
215
+ let split = splitValuesBelowLimit({
216
+ values,
217
+ maxFileValueCount,
218
+ maxFileByteCount,
219
+ });
220
+ outputFiles += split.length;
221
+ outputValueCount += values.length;
222
+ for (let splitValue of split) {
223
+ let dataObj = await pathValueArchives.encodeValuePaths(splitValue.values, {
224
+ pathOverrides: {
225
+ sourceType: config.outputType,
226
+ },
227
+ });
228
+ if (!dataObj) continue;
229
+ outputBytes += dataObj.data.byteLength;
230
+ let fileName = pathValueArchives.encodeDataPath({
231
+ ...pathValueArchives.getDefaultValuePathInput(),
232
+ valueCount: splitValue.values.length,
233
+ byteCount: dataObj.data.byteLength,
234
+ minTime: splitValue.minTime,
235
+ maxTime: splitValue.maxTime,
236
+ sourceType: config.outputType,
237
+ misc: key,
238
+ });
239
+ transaction.createFiles.push({
240
+ data: dataObj.data,
241
+ file: dir + fileName,
242
+ });
281
243
  }
244
+ });
282
245
 
283
- for (let key in result.newValues) {
284
- let values = result.newValues[key];
285
- await addValues(authorityDir, values, key);
286
- }
246
+ for (let [authorityDir, values] of floatingValues) {
247
+ await addValues(authorityDir, values.flat(), "floating");
248
+ }
287
249
 
288
- if (!config.force && !meetsThreshold({ inputFiles, inputBytes, outputFiles, outputBytes })) {
289
- abortedDueToInsufficientReduction = true;
290
- return [];
291
- }
292
250
 
293
- lastFileWrites.set(lastWriteHash, transaction.createFiles.map(x => x.file));
251
+ for (let [key, values] of Object.entries(result.newValues)) {
252
+ let targets = PathRouter.getSelfPathIdentifierTargets(values);
253
+ for (let [target, values] of targets) {
254
+ await addValues(target + "/", values, key);
255
+ }
256
+ }
294
257
 
295
- return [transaction];
296
- });
297
- if (lastAborted) {
298
- lastResult = "aborted";
258
+ if (!config.force && !meetsThreshold({ inputFiles, inputBytes, outputFiles, outputBytes })) {
259
+ abortedDueToInsufficientReduction = true;
260
+ return [];
299
261
  }
262
+
263
+ return [transaction];
264
+ });
265
+ if (lastAborted) {
266
+ lastResult = "aborted";
300
267
  }
301
- let time = Date.now() - startTime;
302
- let resultFormat = (
303
- lastResult === "accepted" && green("accepted")
304
- || lastResult === "aborted" && green("noop")
305
- || red("rejected")
268
+ }
269
+ let time = Date.now() - startTime;
270
+ let resultFormat = (
271
+ lastResult === "accepted" && green("accepted")
272
+ || lastResult === "aborted" && green("noop")
273
+ || red("rejected")
274
+ );
275
+ console.log(`ArchiveMover ${config.debugName ?? config.runMover.name} in ${formatTime(time)}. Result = ${resultFormat}.`);
276
+ if (lastResult === "accepted" && !abortedDueToInsufficientReduction) {
277
+ console.log(
278
+ `ArchiveMover free committed ${config.debugName ?? config.runMover.name}`
279
+ + ` { files: ${formatNumber(inputFiles)}, values: ${formatNumber(inputValueCount)}, bytes: ${formatNumber(inputBytes)} }`
280
+ + "\n=>\n"
281
+ + ` { files: ${formatNumber(outputFiles)}, values: ${formatNumber(outputValueCount)}, bytes: ${formatNumber(outputBytes)} }`
282
+ ,
283
+ {
284
+ inputFiles,
285
+ outputBytes,
286
+ authority,
287
+ }
306
288
  );
307
- console.log(`ArchiveMover ${config.debugName ?? config.runMover.name} on ${authorityDir} in ${formatTime(time)}. Result = ${resultFormat}.`);
308
- if (lastResult === "accepted" && !abortedDueToInsufficientReduction) {
309
- console.log(
310
- `ArchiveMover free committed ${config.debugName ?? config.runMover.name} on ${authorityDir}`
311
- + ` { files: ${formatNumber(inputFiles)}, values: ${formatNumber(inputValueCount)}, bytes: ${formatNumber(inputBytes)} }`
312
- + "\n=>\n"
313
- + ` { files: ${formatNumber(outputFiles)}, values: ${formatNumber(outputValueCount)}, bytes: ${formatNumber(outputBytes)} }`
314
- ,
315
- {
316
- inputFiles,
317
- outputBytes,
318
- }
319
- );
320
- logNodeStats("archives|Input Files", formatNumber, time);
321
- logNodeStats("archives|Input Values", formatNumber, time);
322
- logNodeStats("archives|Input Bytes", formatNumber, time);
323
- logNodeStats("archives|Output Files", formatNumber, time);
324
- logNodeStats("archives|Output Values", formatNumber, time);
325
- logNodeStats("archives|Output Bytes", formatNumber, time);
326
- }
327
- console.log(" ");
289
+ logNodeStats("archives|Input Files", formatNumber, time);
290
+ logNodeStats("archives|Input Values", formatNumber, time);
291
+ logNodeStats("archives|Input Bytes", formatNumber, time);
292
+ logNodeStats("archives|Output Files", formatNumber, time);
293
+ logNodeStats("archives|Output Values", formatNumber, time);
294
+ logNodeStats("archives|Output Bytes", formatNumber, time);
328
295
  }
296
+ console.log(" ");
329
297
  }
330
298
 
331
299
  const splitValuesBelowLimit = measureWrap(function splitValuesBelowLimit(config: {
@@ -2,10 +2,9 @@ import { delay } from "socket-function/src/batching";
2
2
  import { cache, lazy } from "socket-function/src/caching";
3
3
  import { formatNumber } from "socket-function/src/formatting/format";
4
4
  import { magenta, blue, red, green, yellow } from "socket-function/src/formatting/logColors";
5
- import { nextId, sort, binarySearchBasic, timeInDay } from "socket-function/src/misc";
5
+ import { nextId, sort, binarySearchBasic, timeInDay, timeInMinute } from "socket-function/src/misc";
6
6
  import { measureWrap } from "socket-function/src/profiling/measure";
7
7
  import { canHaveChildren } from "socket-function/src/types";
8
- import { AuthorityPath, pathValueAuthority2 } from "../0-path-value-core/NodePathAuthorities";
9
8
  import { pathValueCommitter } from "../0-path-value-core/PathValueCommitter";
10
9
  import { ReadLock, epochTime, PathValue, authorityStorage, compareTime, getNextTime } from "../0-path-value-core/pathValueCore";
11
10
  import { WatchSpec, clientWatcher } from "../1-path-client/pathValueClientWatcher";
@@ -19,6 +18,7 @@ import { runArchiveMover } from "./archiveMoveHarness";
19
18
  import { getStorageDir, getSubFolder } from "../fs";
20
19
  import fs from "fs";
21
20
  import { sha256 } from "js-sha256";
21
+ import { AuthoritySpec, PathRouter } from "../0-path-value-core/PathRouter";
22
22
 
23
23
 
24
24
  export interface AliveChecker<T = unknown> {
@@ -235,7 +235,7 @@ function sandboxedIsAlive(config: {
235
235
  pathStr: string;
236
236
  path: string[];
237
237
  checker: AliveChecker;
238
- authority: AuthorityPath;
238
+ authority: AuthoritySpec;
239
239
  unsyncedPaths: Map<AliveChecker, Map<string, {
240
240
  paths: Set<string>;
241
241
  parentPaths: Set<string>;
@@ -286,13 +286,13 @@ function sandboxedIsAlive(config: {
286
286
 
287
287
  for (let path of evalResult.pathsRead) {
288
288
  if (authorityStorage.isSynced(path)) continue;
289
- if (!pathValueAuthority2.isInAuthority(authority, path)) {
289
+ if (!PathRouter.matchesAuthoritySpec(authority, path)) {
290
290
  getObj().paths.add(path);
291
291
  }
292
292
  }
293
293
  for (let path of evalResult.parentPathsRead) {
294
294
  if (authorityStorage.isParentSynced(path)) continue;
295
- if (!pathValueAuthority2.isInAuthority(authority, path)) {
295
+ if (!PathRouter.matchesAuthoritySpec(authority, path)) {
296
296
  getObj().parentPaths.add(path);
297
297
  }
298
298
  }
@@ -324,7 +324,7 @@ const runAliveCheckerIterationBase = measureWrap(function runAliveCheckerIterati
324
324
  checkPaths: Map<PathSelector, string[][]>;
325
325
  selectors: Map<PathSelector, AliveChecker>;
326
326
  useLocks: boolean;
327
- authority: AuthorityPath;
327
+ authority: AuthoritySpec;
328
328
  getValues: (path: string, parts: string[]) => PathValue[];
329
329
  unsyncedPaths: Map<AliveChecker, Map<string, {
330
330
  paths: Set<string>;
@@ -648,7 +648,7 @@ export async function runAliveCheckerIteration(config?: {
648
648
  parentPaths,
649
649
  promiseObj: wait,
650
650
  };
651
- await Promise.race([delay(15000), wait.promise]);
651
+ await Promise.race([delay(timeInMinute), wait.promise]);
652
652
  }
653
653
  {
654
654
  let totalFreeCount = 0;
@@ -697,6 +697,7 @@ export async function runAliveCheckerIteration(config?: {
697
697
  lockCount++;
698
698
  }
699
699
  for (let free of freeList) {
700
+ // NOTE: I recently changed this so it sets it to be an event, so it doesn't write it to the disk, and it clears it out of memory. This should be a lot more efficient because instead of deleting it from disk and then adding it back to disk and then having it cleaned up when we compress the archives on disk, we can just remove it from disk and never write it back to disk. But all the authorities will have the updated in-memory versions.
700
701
  lockWrites.push({
701
702
  path: free.value.path,
702
703
  time,
@@ -706,7 +707,7 @@ export async function runAliveCheckerIteration(config?: {
706
707
  isValueLazy: false,
707
708
 
708
709
  canGCValue: true,
709
- event: undefined,
710
+ event: true,
710
711
  isTransparent: true,
711
712
  valid: true,
712
713
  source: undefined,