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.
- package/.cursorrules +2 -0
- package/bin/audit-imports.js +4 -0
- package/package.json +7 -4
- package/spec.txt +77 -0
- package/src/-a-archives/archiveCache.ts +9 -4
- package/src/-a-archives/archivesBackBlaze.ts +1039 -1039
- package/src/-a-auth/certs.ts +0 -12
- package/src/-c-identity/IdentityController.ts +12 -3
- package/src/-f-node-discovery/NodeDiscovery.ts +32 -26
- package/src/-g-core-values/NodeCapabilities.ts +12 -2
- package/src/0-path-value-core/AuthorityLookup.ts +239 -0
- package/src/0-path-value-core/LockWatcher2.ts +150 -0
- package/src/0-path-value-core/PathRouter.ts +535 -0
- package/src/0-path-value-core/PathRouterRouteOverride.ts +72 -0
- package/src/0-path-value-core/PathRouterServerAuthoritySpec.tsx +65 -0
- package/src/0-path-value-core/PathValueCommitter.ts +222 -488
- package/src/0-path-value-core/PathValueController.ts +277 -239
- package/src/0-path-value-core/PathWatcher.ts +534 -0
- package/src/0-path-value-core/ShardPrefixes.ts +31 -0
- package/src/0-path-value-core/ValidStateComputer.ts +303 -0
- package/src/0-path-value-core/archiveLocks/ArchiveLocks.ts +1 -1
- package/src/0-path-value-core/archiveLocks/ArchiveLocks2.ts +80 -44
- package/src/0-path-value-core/archiveLocks/archiveSnapshots.ts +13 -16
- package/src/0-path-value-core/auditLogs.ts +2 -0
- package/src/0-path-value-core/hackedPackedPathParentFiltering.ts +97 -0
- package/src/0-path-value-core/pathValueArchives.ts +490 -492
- package/src/0-path-value-core/pathValueCore.ts +195 -1496
- package/src/0-path-value-core/startupAuthority.ts +74 -0
- package/src/1-path-client/RemoteWatcher.ts +90 -82
- package/src/1-path-client/pathValueClientWatcher.ts +808 -815
- package/src/2-proxy/PathValueProxyWatcher.ts +10 -8
- package/src/2-proxy/archiveMoveHarness.ts +182 -214
- package/src/2-proxy/garbageCollection.ts +9 -8
- package/src/2-proxy/schema2.ts +21 -1
- package/src/3-path-functions/PathFunctionHelpers.ts +206 -180
- package/src/3-path-functions/PathFunctionRunner.ts +943 -766
- package/src/3-path-functions/PathFunctionRunnerMain.ts +5 -3
- package/src/3-path-functions/pathFunctionLoader.ts +2 -2
- package/src/3-path-functions/syncSchema.ts +592 -521
- package/src/4-deploy/deployFunctions.ts +19 -4
- package/src/4-deploy/deployGetFunctionsInner.ts +8 -2
- package/src/4-deploy/deployMain.ts +51 -68
- package/src/4-deploy/edgeClientWatcher.tsx +1 -1
- package/src/4-deploy/edgeNodes.ts +2 -2
- package/src/4-dom/qreact.tsx +2 -4
- package/src/4-dom/qreactTest.tsx +7 -13
- package/src/4-querysub/Querysub.ts +21 -8
- package/src/4-querysub/QuerysubController.ts +45 -29
- package/src/4-querysub/permissions.ts +2 -2
- package/src/4-querysub/querysubPrediction.ts +80 -70
- package/src/4-querysub/schemaHelpers.ts +5 -1
- package/src/5-diagnostics/GenericFormat.tsx +14 -9
- package/src/archiveapps/archiveGCEntry.tsx +9 -2
- package/src/archiveapps/archiveJoinEntry.ts +87 -84
- package/src/archiveapps/archiveMergeEntry.tsx +2 -0
- package/src/bits.ts +19 -0
- package/src/config.ts +21 -3
- package/src/config2.ts +23 -48
- package/src/deployManager/components/DeployPage.tsx +7 -3
- package/src/deployManager/machineSchema.ts +4 -1
- package/src/diagnostics/ActionsHistory.ts +3 -8
- package/src/diagnostics/AuditLogPage.tsx +2 -3
- package/src/diagnostics/FunctionCallInfo.tsx +141 -0
- package/src/diagnostics/FunctionCallInfoState.ts +162 -0
- package/src/diagnostics/MachineThreadInfo.tsx +1 -1
- package/src/diagnostics/NodeViewer.tsx +37 -48
- package/src/diagnostics/SyncTestPage.tsx +241 -0
- package/src/diagnostics/auditImportViolations.ts +185 -0
- package/src/diagnostics/listenOnDebugger.ts +3 -3
- package/src/diagnostics/logs/IndexedLogs/BufferUnitSet.ts +10 -4
- package/src/diagnostics/logs/IndexedLogs/IndexedLogs.ts +2 -2
- package/src/diagnostics/logs/IndexedLogs/LogViewer3.tsx +24 -22
- package/src/diagnostics/logs/IndexedLogs/moveIndexLogsToPublic.ts +1 -1
- package/src/diagnostics/logs/diskLogGlobalContext.ts +1 -0
- package/src/diagnostics/logs/errorNotifications2/logWatcher.ts +1 -3
- package/src/diagnostics/logs/lifeCycleAnalysis/LifeCycleEntryEditor.tsx +34 -16
- package/src/diagnostics/logs/lifeCycleAnalysis/LifeCycleEntryReadMode.tsx +4 -6
- package/src/diagnostics/logs/lifeCycleAnalysis/LifeCycleInstanceTableView.tsx +36 -5
- package/src/diagnostics/logs/lifeCycleAnalysis/LifeCyclePage.tsx +19 -5
- package/src/diagnostics/logs/lifeCycleAnalysis/LifeCycleRenderer.tsx +15 -7
- package/src/diagnostics/logs/lifeCycleAnalysis/NestedLifeCycleInfo.tsx +28 -106
- package/src/diagnostics/logs/lifeCycleAnalysis/lifeCycleMatching.ts +2 -0
- package/src/diagnostics/logs/lifeCycleAnalysis/lifeCycleMisc.ts +0 -0
- package/src/diagnostics/logs/lifeCycleAnalysis/lifeCycleSearch.tsx +18 -7
- package/src/diagnostics/logs/lifeCycleAnalysis/lifeCycles.tsx +3 -0
- package/src/diagnostics/managementPages.tsx +10 -3
- package/src/diagnostics/misc-pages/ArchiveViewer.tsx +20 -26
- package/src/diagnostics/misc-pages/ArchiveViewerTree.tsx +6 -4
- package/src/diagnostics/misc-pages/ComponentSyncStats.tsx +2 -2
- package/src/diagnostics/misc-pages/LocalWatchViewer.tsx +7 -9
- package/src/diagnostics/misc-pages/SnapshotViewer.tsx +23 -12
- package/src/diagnostics/misc-pages/archiveViewerShared.tsx +1 -1
- package/src/diagnostics/pathAuditer.ts +486 -0
- package/src/diagnostics/pathAuditerCallback.ts +20 -0
- package/src/diagnostics/watchdog.ts +8 -1
- package/src/library-components/URLParam.ts +1 -1
- package/src/misc/hash.ts +1 -0
- package/src/path.ts +21 -7
- package/src/server.ts +54 -47
- package/src/user-implementation/loginEmail.tsx +1 -1
- package/tempnotes.txt +67 -0
- package/test.ts +288 -95
- package/src/0-path-value-core/NodePathAuthorities.ts +0 -1057
- package/src/0-path-value-core/PathController.ts +0 -1
- package/src/5-diagnostics/diskValueAudit.ts +0 -218
- package/src/5-diagnostics/memoryValueAudit.ts +0 -438
- 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 [
|
|
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(
|
|
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(
|
|
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
|
-
|
|
14
|
-
|
|
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
|
-
|
|
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:
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
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
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
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
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
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
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
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
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
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
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
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
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
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
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
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
|
-
|
|
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
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
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
|
-
|
|
280
|
-
|
|
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
|
-
|
|
284
|
-
|
|
285
|
-
|
|
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
|
-
|
|
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
|
-
|
|
296
|
-
|
|
297
|
-
|
|
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
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
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
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
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:
|
|
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 (!
|
|
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 (!
|
|
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:
|
|
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(
|
|
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:
|
|
710
|
+
event: true,
|
|
710
711
|
isTransparent: true,
|
|
711
712
|
valid: true,
|
|
712
713
|
source: undefined,
|