querysub 0.404.0 → 0.405.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/bin/join.js +1 -1
- package/package.json +1 -1
- package/src/0-path-value-core/PathRouter.ts +18 -10
- package/src/0-path-value-core/PathRouterServerAuthoritySpec.tsx +9 -1
- package/src/0-path-value-core/pathValueArchives.ts +2 -1
- package/src/2-proxy/archiveMoveHarness.ts +2 -2
- package/src/3-path-functions/syncSchema.ts +6 -2
- package/src/4-deploy/edgeClientWatcher.tsx +5 -0
- package/src/archiveapps/archiveJoinEntry.ts +30 -21
- package/tempnotes.txt +0 -2
- package/test.ts +25 -17
- package/src/archiveapps/archiveMergeEntry.tsx +0 -50
package/bin/join.js
CHANGED
package/package.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { sort } from "socket-function/src/misc";
|
|
2
|
-
import { getLastPathPart, getPathDepth, getPathIndex, getPathStr1 } from "../path";
|
|
2
|
+
import { getLastPathPart, getPathDepth, getPathIndex, getPathStr1, hack_stripPackedPath } from "../path";
|
|
3
3
|
import { AuthorityEntry, authorityLookup } from "./AuthorityLookup";
|
|
4
4
|
import { PathValue } from "./pathValueCore";
|
|
5
5
|
import { shuffle } from "../misc/random";
|
|
@@ -59,8 +59,9 @@ export class PathRouter {
|
|
|
59
59
|
path: string;
|
|
60
60
|
spec: AuthoritySpec;
|
|
61
61
|
}): number {
|
|
62
|
-
// NOTE:
|
|
62
|
+
// NOTE: getPathIdentifierTargets also hardcodes this logic, so it can hash many values quickly
|
|
63
63
|
let { path, spec } = config;
|
|
64
|
+
path = hack_stripPackedPath(path);
|
|
64
65
|
let override = getRoutingOverride(path);
|
|
65
66
|
if (override) {
|
|
66
67
|
if (!hasPrefixHash({ spec, prefixHash: override.prefixHash })) return -1;
|
|
@@ -70,7 +71,11 @@ export class PathRouter {
|
|
|
70
71
|
let prefix = spec.prefixes.find(x => path.startsWith(x.prefix) && x.prefix !== path);
|
|
71
72
|
if (prefix) {
|
|
72
73
|
let key = getPathIndex(path, prefix.hashIndex);
|
|
73
|
-
if (key === undefined)
|
|
74
|
+
if (key === undefined) {
|
|
75
|
+
require("debugbreak")(2);
|
|
76
|
+
debugger;
|
|
77
|
+
throw new Error(`Impossible, hash index ${prefix.hashIndex} is out of range for path ${path}, but it matched the prefix ${prefix.prefix}`);
|
|
78
|
+
}
|
|
74
79
|
return this.getSingleKeyRoute(key);
|
|
75
80
|
}
|
|
76
81
|
if (spec.excludeDefault) return -1;
|
|
@@ -107,13 +112,13 @@ export class PathRouter {
|
|
|
107
112
|
private static encodeIdentifier(config: { prefixes: string[]; rangeStart: number; rangeEnd: number } | "remaining"): string {
|
|
108
113
|
if (config === "remaining") return "P!REMAINING";
|
|
109
114
|
let { prefixes, rangeStart, rangeEnd } = config;
|
|
110
|
-
return ["P", rangeStart.toString(), rangeEnd.toString(), ...prefixes.map(x => this.getPrefixHash(x))].join("!");
|
|
115
|
+
return ["P", rangeStart.toString(), rangeEnd.toString(), ...prefixes.map(x => this.getPrefixHash(x)), ""].join("!");
|
|
111
116
|
|
|
112
117
|
}
|
|
113
118
|
private static decodeIdentifier(identifier: string): { prefixHashes: string[]; rangeStart: number; rangeEnd: number } | "remaining" {
|
|
114
119
|
if (!identifier.startsWith("P")) return "remaining";
|
|
115
120
|
let parts = identifier.split("!");
|
|
116
|
-
if (parts[1]
|
|
121
|
+
if (parts[1].startsWith("REMAINING")) return "remaining";
|
|
117
122
|
return {
|
|
118
123
|
rangeStart: parseFloat(parts[1]),
|
|
119
124
|
rangeEnd: parseFloat(parts[2]),
|
|
@@ -125,7 +130,7 @@ export class PathRouter {
|
|
|
125
130
|
// NOTE: Encodes all the data, even if it matches our spec or not. If you don't want this, you have to filter first
|
|
126
131
|
// - If this becomes an issue we COULD filter, as we can do it quickly, but I don't think it is required, as all the present usecases prefilter anyways.
|
|
127
132
|
@measureFnc
|
|
128
|
-
public static
|
|
133
|
+
public static getPathIdentifierTargets(values: PathValue[], ourSpec: AuthoritySpec): Map<string, PathValue[]> {
|
|
129
134
|
// NOTE: The file size limit is 1024 bytes. But we also have our folder, etc, so we want to add enough buffer
|
|
130
135
|
// - Shorter hashes means we can store more, but there's a point when the collisions make it less useful.
|
|
131
136
|
const MAX_PREFIXES_PER_FILE = 50;
|
|
@@ -135,13 +140,11 @@ export class PathRouter {
|
|
|
135
140
|
return new Map([[this.encodeIdentifier("remaining"), values]]);
|
|
136
141
|
}
|
|
137
142
|
|
|
138
|
-
let ourSpec = authorityLookup.getOurSpec();
|
|
139
|
-
|
|
140
143
|
let prefixes = ourSpec.prefixes.slice();
|
|
141
144
|
sort(prefixes, x => x.prefix.length);
|
|
142
145
|
function getPrefix(path: string): string | undefined {
|
|
143
146
|
for (let prefix of prefixes) {
|
|
144
|
-
if (path.startsWith(prefix.prefix)) return prefix.prefix;
|
|
147
|
+
if (path.startsWith(prefix.prefix) && prefix.prefix !== path) return prefix.prefix;
|
|
145
148
|
}
|
|
146
149
|
return undefined;
|
|
147
150
|
}
|
|
@@ -165,6 +168,9 @@ export class PathRouter {
|
|
|
165
168
|
}));
|
|
166
169
|
sort(prefixGroups, x => -x.values.length);
|
|
167
170
|
|
|
171
|
+
require("debugbreak")(2);
|
|
172
|
+
debugger;
|
|
173
|
+
|
|
168
174
|
let groups: {
|
|
169
175
|
prefixes: string[];
|
|
170
176
|
values: PathValue[][];
|
|
@@ -216,7 +222,9 @@ export class PathRouter {
|
|
|
216
222
|
let hashIndex = getPathDepth(prefix);
|
|
217
223
|
for (let value of values) {
|
|
218
224
|
let key = getPathIndex(value.path, hashIndex);
|
|
219
|
-
if (key === undefined)
|
|
225
|
+
if (key === undefined) {
|
|
226
|
+
throw new Error(`Impossible, hash index ${hashIndex} is out of range for path ${value.path}, but it matched the prefix ${prefix}`);
|
|
227
|
+
}
|
|
220
228
|
let route = this.getSingleKeyRoute(key);
|
|
221
229
|
let routeIndex = Math.floor(route * splitCount);
|
|
222
230
|
let routeValues = byRouteGroup.get(routeIndex);
|
|
@@ -16,7 +16,15 @@ export async function getOurAuthoritySpec(defaultToAll?: boolean): Promise<Autho
|
|
|
16
16
|
|
|
17
17
|
if (!range) {
|
|
18
18
|
if (defaultToAll) {
|
|
19
|
-
return
|
|
19
|
+
return {
|
|
20
|
+
nodeId: "",
|
|
21
|
+
routeStart: 0,
|
|
22
|
+
routeEnd: 1,
|
|
23
|
+
prefixes: prefixes.map(prefix => ({
|
|
24
|
+
prefix,
|
|
25
|
+
hashIndex: getPathDepth(prefix),
|
|
26
|
+
})),
|
|
27
|
+
};
|
|
20
28
|
}
|
|
21
29
|
return undefined;
|
|
22
30
|
}
|
|
@@ -13,6 +13,7 @@ import { createArchiveLocker2 } from "./archiveLocks/ArchiveLocks2";
|
|
|
13
13
|
import { devDebugbreak, isNoNetwork } from "../config";
|
|
14
14
|
import { wrapArchivesWithCache } from "../-a-archives/archiveCache";
|
|
15
15
|
import { AuthoritySpec, PathRouter } from "./PathRouter";
|
|
16
|
+
import { authorityLookup } from "./AuthorityLookup";
|
|
16
17
|
|
|
17
18
|
export const archives = lazy(() => wrapArchivesWithCache(getArchives("path-values/")));
|
|
18
19
|
export const archivesLocks = lazy(() => getArchives("path-values-locks/"));
|
|
@@ -161,7 +162,7 @@ export class PathValueArchives {
|
|
|
161
162
|
|
|
162
163
|
@measureFnc
|
|
163
164
|
public async archiveValues(values: PathValue[]) {
|
|
164
|
-
let parts = PathRouter.
|
|
165
|
+
let parts = PathRouter.getPathIdentifierTargets(values, authorityLookup.getOurSpec());
|
|
165
166
|
|
|
166
167
|
for (let [pathIdentifier, values] of parts) {
|
|
167
168
|
let encodedObj = await this.encodeValuePaths(values);
|
|
@@ -7,7 +7,7 @@ import { PathValue, VALUE_GC_THRESHOLD, FILE_VALUE_COUNT_LIMIT, FILE_SIZE_LIMIT,
|
|
|
7
7
|
import { getSingleSizeEstimate } from "../5-diagnostics/shared";
|
|
8
8
|
import { logNodeStats } from "../-0-hooks/hooks";
|
|
9
9
|
import debugbreak from "debugbreak";
|
|
10
|
-
import { AuthorityEntry } from "../0-path-value-core/AuthorityLookup";
|
|
10
|
+
import { AuthorityEntry, authorityLookup } from "../0-path-value-core/AuthorityLookup";
|
|
11
11
|
import { AuthoritySpec, PathRouter } from "../0-path-value-core/PathRouter";
|
|
12
12
|
import { getOurAuthoritySpec } from "../0-path-value-core/PathRouterServerAuthoritySpec";
|
|
13
13
|
|
|
@@ -249,7 +249,7 @@ export async function runArchiveMover(config: {
|
|
|
249
249
|
|
|
250
250
|
|
|
251
251
|
for (let [key, values] of Object.entries(result.newValues)) {
|
|
252
|
-
let targets = PathRouter.
|
|
252
|
+
let targets = PathRouter.getPathIdentifierTargets(values, authority);
|
|
253
253
|
for (let [target, values] of targets) {
|
|
254
254
|
await addValues(target + "/", values, key);
|
|
255
255
|
}
|
|
@@ -2,7 +2,7 @@ import fs from "fs";
|
|
|
2
2
|
import { cache, lazy } from "socket-function/src/caching";
|
|
3
3
|
import { getStringKeys, sort } from "socket-function/src/misc";
|
|
4
4
|
import { Args } from "socket-function/src/types";
|
|
5
|
-
import { appendToPathStr, getPathFromStr, getPathStr, rootPathStr } from "../path";
|
|
5
|
+
import { appendToPathStr, getPathFromStr, getPathStr, joinPathStres, rootPathStr } from "../path";
|
|
6
6
|
import { writeFunctionCall } from "./PathFunctionHelpers";
|
|
7
7
|
import { CallSpec, functionSchema } from "./PathFunctionRunner";
|
|
8
8
|
import { getDomain, isLocal } from "../config";
|
|
@@ -323,6 +323,7 @@ export function syncSchema<Schema>(schema?: Schema2): SyncSchemaResult<Schema> {
|
|
|
323
323
|
createObjectAliveChecker(data, path, gcDelay);
|
|
324
324
|
}
|
|
325
325
|
|
|
326
|
+
|
|
326
327
|
let undoChecks = Schema2Fncs.getAllUndoChecks(schema);
|
|
327
328
|
for (let checkObj of undoChecks) {
|
|
328
329
|
// Need at least one check
|
|
@@ -368,7 +369,10 @@ export function syncSchema<Schema>(schema?: Schema2): SyncSchemaResult<Schema> {
|
|
|
368
369
|
}
|
|
369
370
|
|
|
370
371
|
// Register all root lookups as prefixes.
|
|
371
|
-
let
|
|
372
|
+
let dataRoot = getProxyPath(() => functionSchema()[getDomain()].PathFunctionRunner[moduleId].Data);
|
|
373
|
+
let paths = Schema2Fncs.getLookups(schema).map(x =>
|
|
374
|
+
joinPathStres(dataRoot, getPathStr(x))
|
|
375
|
+
);
|
|
372
376
|
// NOTE: This will break with wildcards, but... we also take only the highest level lookups, so it shouldn't be an issue
|
|
373
377
|
sort(paths, x => x.length);
|
|
374
378
|
let rootLookups = new Set<string>();
|
|
@@ -16,6 +16,11 @@ import { lazy } from "socket-function/src/caching";
|
|
|
16
16
|
import { Button } from "../library-components/Button";
|
|
17
17
|
import { updateRootDiscoveryLocation } from "../-f-node-discovery/NodeDiscovery";
|
|
18
18
|
|
|
19
|
+
setImmediate(() => {
|
|
20
|
+
// Modal
|
|
21
|
+
import("../5-diagnostics/Modal");
|
|
22
|
+
});
|
|
23
|
+
|
|
19
24
|
const SWITCH_SERVER_TIMEOUT = timeInSecond * 15;
|
|
20
25
|
const MAX_DISPLAY_INTERVAL = timeInMinute * 5;
|
|
21
26
|
const FINAL_DELAY = timeInSecond * 30;
|
|
@@ -2,23 +2,29 @@ import "../inject";
|
|
|
2
2
|
|
|
3
3
|
import { logErrors } from "../errors";
|
|
4
4
|
import { PathValueArchives, pathValueArchives } from "../0-path-value-core/pathValueArchives";
|
|
5
|
-
import {
|
|
5
|
+
import { PathValue, VALUE_GC_THRESHOLD } from "../0-path-value-core/pathValueCore";
|
|
6
6
|
import { runInfinitePollCallAtStart } from "socket-function/src/batching";
|
|
7
7
|
import { measureBlock } from "socket-function/src/profiling/measure";
|
|
8
8
|
import { pathValueSerializer } from "../-h-path-value-serialize/PathValueSerializer";
|
|
9
9
|
import { ArchiveTransaction, FileInfo } from "../0-path-value-core/archiveLocks/ArchiveLocks";
|
|
10
10
|
import { formatNumber } from "socket-function/src/formatting/format";
|
|
11
|
-
import { sort } from "socket-function/src/misc";
|
|
11
|
+
import { isNodeTrue, sort } from "socket-function/src/misc";
|
|
12
12
|
import { Querysub } from "../4-querysub/QuerysubController";
|
|
13
13
|
import { magenta } from "socket-function/src/formatting/logColors";
|
|
14
14
|
import { PathRouter } from "../0-path-value-core/PathRouter";
|
|
15
15
|
import { disablePathAuditer } from "../diagnostics/pathAuditerCallback";
|
|
16
16
|
import { getOurAuthoritySpec } from "../0-path-value-core/PathRouterServerAuthoritySpec";
|
|
17
|
+
import yargs from "yargs";
|
|
17
18
|
|
|
18
|
-
|
|
19
|
+
let yargObj = isNodeTrue() && yargs(process.argv)
|
|
20
|
+
.option("watch", { type: "boolean", desc: "If true, we only join genesis values, but we join in a loop, otherwise we just join absolutely everything, and then exit." })
|
|
21
|
+
.argv || {}
|
|
22
|
+
;
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
async function runGenesisJoinIteration(config?: { force?: boolean }) {
|
|
19
26
|
let authoritySpec = await getOurAuthoritySpec(true);
|
|
20
27
|
let locker = await pathValueArchives.getArchiveLocker();
|
|
21
|
-
let maxAge = Date.now() - VALUE_GC_THRESHOLD;
|
|
22
28
|
|
|
23
29
|
let readCache = new Map<string, Buffer>();
|
|
24
30
|
let reread = true;
|
|
@@ -31,15 +37,16 @@ async function runGenesisJoinIteration() {
|
|
|
31
37
|
// Merge the newest first, so if we hit a big file, we can just ignore it,
|
|
32
38
|
// and next time merge the smaller files after it.
|
|
33
39
|
sort(valueFiles, x => -x.createTime);
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
+
if (!config?.force) {
|
|
41
|
+
valueFiles = valueFiles.filter(x => {
|
|
42
|
+
let obj = pathValueArchives.decodeDataPath(x.file);
|
|
43
|
+
if (!obj.minTime) return false;
|
|
44
|
+
return obj.sourceType === "genesis";
|
|
45
|
+
});
|
|
46
|
+
}
|
|
40
47
|
let withinTimeRangeCount = valueFiles.length;
|
|
41
48
|
|
|
42
|
-
if (valueFiles.length < 3) return [];
|
|
49
|
+
if (valueFiles.length < 3 && !config?.force) return [];
|
|
43
50
|
|
|
44
51
|
await measureBlock(async function locker_readFiles() {
|
|
45
52
|
let remainingFiles = valueFiles.filter(x => !readCache.has(x.file));
|
|
@@ -65,28 +72,20 @@ async function runGenesisJoinIteration() {
|
|
|
65
72
|
let allValues: PathValue[][] = [];
|
|
66
73
|
for (let valueFile of valueFiles) {
|
|
67
74
|
let buffer = readCache.get(valueFile.file)!;
|
|
68
|
-
if (totalSize + buffer.length > FILE_SIZE_LIMIT) {
|
|
69
|
-
break;
|
|
70
|
-
}
|
|
71
75
|
let newValues = await PathValueArchives.loadValuesFromBuffer({
|
|
72
76
|
path: valueFile.file,
|
|
73
77
|
data: buffer,
|
|
74
78
|
});
|
|
75
79
|
|
|
76
80
|
let readValues = newValues.values;
|
|
77
|
-
if (readValues.length + totalCount > FILE_VALUE_COUNT_LIMIT) {
|
|
78
|
-
break;
|
|
79
|
-
}
|
|
80
81
|
allValues.push(readValues);
|
|
81
82
|
usedFiles.push(valueFile);
|
|
82
83
|
totalSize += buffer.length;
|
|
83
84
|
totalCount += readValues.length;
|
|
84
85
|
}
|
|
85
|
-
if (usedFiles.length <= 1) return [];
|
|
86
86
|
|
|
87
87
|
let allCombinedValues = allValues.flat();
|
|
88
88
|
|
|
89
|
-
|
|
90
89
|
let transaction: ArchiveTransaction = {
|
|
91
90
|
createFiles: [],
|
|
92
91
|
deleteFiles: [],
|
|
@@ -95,7 +94,7 @@ async function runGenesisJoinIteration() {
|
|
|
95
94
|
transaction.deleteFiles.push(file);
|
|
96
95
|
}
|
|
97
96
|
|
|
98
|
-
let targets = PathRouter.
|
|
97
|
+
let targets = PathRouter.getPathIdentifierTargets(allCombinedValues, authoritySpec);
|
|
99
98
|
for (let [target, values] of targets) {
|
|
100
99
|
|
|
101
100
|
let dataObj = await pathValueArchives.encodeValuePaths(values, {
|
|
@@ -123,7 +122,17 @@ async function main() {
|
|
|
123
122
|
disablePathAuditer();
|
|
124
123
|
await Querysub.hostService("join");
|
|
125
124
|
|
|
126
|
-
|
|
125
|
+
if (yargObj.watch) {
|
|
126
|
+
await runInfinitePollCallAtStart(VALUE_GC_THRESHOLD * 0.8, runGenesisJoinIteration);
|
|
127
|
+
} else {
|
|
128
|
+
try {
|
|
129
|
+
await runGenesisJoinIteration({ force: true });
|
|
130
|
+
} catch (error) {
|
|
131
|
+
console.error(error);
|
|
132
|
+
} finally {
|
|
133
|
+
process.exit();
|
|
134
|
+
}
|
|
135
|
+
}
|
|
127
136
|
}
|
|
128
137
|
|
|
129
138
|
main().catch(logErrors);
|
package/tempnotes.txt
CHANGED
package/test.ts
CHANGED
|
@@ -3,6 +3,7 @@ chdir("D:/repos/qs-cyoa/");
|
|
|
3
3
|
|
|
4
4
|
import "./inject";
|
|
5
5
|
|
|
6
|
+
import path from "path";
|
|
6
7
|
import { list, sort } from "socket-function/src/misc";
|
|
7
8
|
import { formatNumber } from "socket-function/src/formatting/format";
|
|
8
9
|
import { PathValueArchives, archives, archivesLocks, archivesRecycleBin, pathValueArchives } from "./src/0-path-value-core/pathValueArchives";
|
|
@@ -19,26 +20,31 @@ import { unique } from "./src/misc";
|
|
|
19
20
|
import { getAllAuthoritySpec, getOurAuthoritySpec } from "./src/0-path-value-core/PathRouterServerAuthoritySpec";
|
|
20
21
|
import { PathRouter } from "./src/0-path-value-core/PathRouter";
|
|
21
22
|
import { pathValueSerializer } from "./src/-h-path-value-serialize/PathValueSerializer";
|
|
23
|
+
import { getShardPrefixes } from "./src/0-path-value-core/ShardPrefixes";
|
|
22
24
|
|
|
23
25
|
async function main() {
|
|
24
|
-
let
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
26
|
+
let prefixes = await getShardPrefixes();
|
|
27
|
+
console.log(prefixes);
|
|
28
|
+
let deployPath = path.resolve("./deploy.ts");
|
|
29
|
+
await import(deployPath);
|
|
30
|
+
// let paths = await pathValueArchives.getValuePaths(getAllAuthoritySpec());
|
|
31
|
+
// paths = paths.filter(x => x.startsWith("P!REMAINING/"));
|
|
32
|
+
// for (let path of paths) {
|
|
33
|
+
// let data = await archives().get(path);
|
|
34
|
+
// if (!data) {
|
|
35
|
+
// console.log(`Missing data file: ${path}`);
|
|
36
|
+
// continue;
|
|
37
|
+
// }
|
|
38
|
+
// let loadObj = await PathValueArchives.loadValuesFromBuffer({ path, data });
|
|
33
39
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
}
|
|
41
|
-
return;
|
|
40
|
+
// for (let value of loadObj.values) {
|
|
41
|
+
// if (!PathRouter.matchesAuthoritySpec(getAllAuthoritySpec(), value.path)) {
|
|
42
|
+
// throw new Error(`Value ${value.path} does not match authority spec`);
|
|
43
|
+
// }
|
|
44
|
+
// console.log(pathValueSerializer.getPathValue(value));
|
|
45
|
+
// }
|
|
46
|
+
// }
|
|
47
|
+
// return;
|
|
42
48
|
|
|
43
49
|
// let path = "P!REMAINING/data_37c5d323e0f9a083.1ed7a7340a015680.querysubtest.com:52026_1775097754671.579_3_1_337_1775097652829.5793_1775097652829.5793_genesis_.data";
|
|
44
50
|
// let value = await archives().get(path);
|
|
@@ -54,6 +60,7 @@ async function main() {
|
|
|
54
60
|
// return path.split("/").at(-1)!;
|
|
55
61
|
// }
|
|
56
62
|
|
|
63
|
+
/*
|
|
57
64
|
let allValuesObj = await pathValueArchives.loadValues({
|
|
58
65
|
nodeId: "",
|
|
59
66
|
prefixes: [],
|
|
@@ -62,6 +69,7 @@ async function main() {
|
|
|
62
69
|
});
|
|
63
70
|
let allValues = Object.values(allValuesObj.values).flat();
|
|
64
71
|
console.log(`Total values loaded: ${formatNumber(allValues.length)}`);
|
|
72
|
+
*/
|
|
65
73
|
|
|
66
74
|
// const badDeleteTransaction = "transaction_ tSeqNum=887 tWriteTime=1774715868374.9143 thread=9dc0 cCount=14 dCount=3482 create=X,X,X,X,X,X,X,X,X,X,X,X,X,X delete=2@0977,3@0977,4@0977,1@0a2a,2@0a2a,3@0a2a,4@0a2... .transaction";
|
|
67
75
|
|
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
import "../inject";
|
|
2
|
-
|
|
3
|
-
import { Querysub } from "../4-querysub/QuerysubController";
|
|
4
|
-
import { logErrors } from "../errors";
|
|
5
|
-
import { timeInDay, timeInHour } from "socket-function/src/misc";
|
|
6
|
-
import { runArchiveMover } from "../2-proxy/archiveMoveHarness";
|
|
7
|
-
import { PathValue, compareTime } from "../0-path-value-core/pathValueCore";
|
|
8
|
-
import { disablePathAuditer } from "../diagnostics/pathAuditerCallback";
|
|
9
|
-
|
|
10
|
-
const MERGE_DELAY = timeInHour;
|
|
11
|
-
|
|
12
|
-
async function mergeFiles() {
|
|
13
|
-
await runArchiveMover({
|
|
14
|
-
debugName: "merge",
|
|
15
|
-
outputType: "merge",
|
|
16
|
-
async runMover(config) {
|
|
17
|
-
let values = config.values;
|
|
18
|
-
let latestValues = new Map<string, PathValue>();
|
|
19
|
-
for (let value of values) {
|
|
20
|
-
let prev = latestValues.get(value.path);
|
|
21
|
-
if (prev && compareTime(value.time, prev.time) < 0) continue;
|
|
22
|
-
latestValues.set(value.path, value);
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
values = Array.from(latestValues.values());
|
|
26
|
-
values = values.filter(x => !x.canGCValue);
|
|
27
|
-
|
|
28
|
-
return {
|
|
29
|
-
newValues: {
|
|
30
|
-
"": values,
|
|
31
|
-
},
|
|
32
|
-
};
|
|
33
|
-
},
|
|
34
|
-
});
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
async function main() {
|
|
38
|
-
disablePathAuditer();
|
|
39
|
-
await Querysub.hostService("merge");
|
|
40
|
-
await mergeFiles();
|
|
41
|
-
process.exit();
|
|
42
|
-
|
|
43
|
-
// while (true) {
|
|
44
|
-
// await mergeFiles();
|
|
45
|
-
// let delay = MERGE_DELAY * (1 + Math.random() * 0.1);
|
|
46
|
-
// await new Promise(resolve => setTimeout(resolve, delay));
|
|
47
|
-
// }
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
main().catch(logErrors);
|