querysub 0.2.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/.dependency-cruiser.js +304 -0
- package/.eslintrc.js +51 -0
- package/.github/copilot-instructions.md +1 -0
- package/.vscode/settings.json +25 -0
- package/bin/deploy.js +4 -0
- package/bin/function.js +4 -0
- package/bin/server.js +4 -0
- package/costsBenefits.txt +112 -0
- package/deploy.ts +3 -0
- package/inject.ts +1 -0
- package/package.json +60 -0
- package/prompts.txt +54 -0
- package/spec.txt +820 -0
- package/src/-a-archives/archiveCache.ts +913 -0
- package/src/-a-archives/archives.ts +148 -0
- package/src/-a-archives/archivesBackBlaze.ts +792 -0
- package/src/-a-archives/archivesDisk.ts +418 -0
- package/src/-a-archives/copyLocalToBackblaze.ts +24 -0
- package/src/-a-auth/certs.ts +517 -0
- package/src/-a-auth/der.ts +122 -0
- package/src/-a-auth/ed25519.ts +1015 -0
- package/src/-a-auth/node-forge-ed25519.d.ts +17 -0
- package/src/-b-authorities/dnsAuthority.ts +203 -0
- package/src/-b-authorities/emailAuthority.ts +57 -0
- package/src/-c-identity/IdentityController.ts +200 -0
- package/src/-d-trust/NetworkTrust2.ts +150 -0
- package/src/-e-certs/EdgeCertController.ts +288 -0
- package/src/-e-certs/certAuthority.ts +192 -0
- package/src/-f-node-discovery/NodeDiscovery.ts +543 -0
- package/src/-g-core-values/NodeCapabilities.ts +134 -0
- package/src/-g-core-values/oneTimeForward.ts +91 -0
- package/src/-h-path-value-serialize/PathValueSerializer.ts +769 -0
- package/src/-h-path-value-serialize/stringSerializer.ts +176 -0
- package/src/0-path-value-core/LoggingClient.tsx +24 -0
- package/src/0-path-value-core/NodePathAuthorities.ts +978 -0
- package/src/0-path-value-core/PathController.ts +1 -0
- package/src/0-path-value-core/PathValueCommitter.ts +565 -0
- package/src/0-path-value-core/PathValueController.ts +231 -0
- package/src/0-path-value-core/archiveLocks/ArchiveLocks.ts +154 -0
- package/src/0-path-value-core/archiveLocks/ArchiveLocks2.ts +820 -0
- package/src/0-path-value-core/archiveLocks/archiveSnapshots.ts +180 -0
- package/src/0-path-value-core/debugLogs.ts +90 -0
- package/src/0-path-value-core/pathValueArchives.ts +483 -0
- package/src/0-path-value-core/pathValueCore.ts +2217 -0
- package/src/1-path-client/RemoteWatcher.ts +558 -0
- package/src/1-path-client/pathValueClientWatcher.ts +702 -0
- package/src/2-proxy/PathValueProxyWatcher.ts +1857 -0
- package/src/2-proxy/archiveMoveHarness.ts +376 -0
- package/src/2-proxy/garbageCollection.ts +753 -0
- package/src/2-proxy/pathDatabaseProxyBase.ts +37 -0
- package/src/2-proxy/pathValueProxy.ts +139 -0
- package/src/2-proxy/schema2.ts +518 -0
- package/src/3-path-functions/PathFunctionHelpers.ts +129 -0
- package/src/3-path-functions/PathFunctionRunner.ts +619 -0
- package/src/3-path-functions/PathFunctionRunnerMain.ts +67 -0
- package/src/3-path-functions/deployBlock.ts +10 -0
- package/src/3-path-functions/deployCheck.ts +7 -0
- package/src/3-path-functions/deployMain.ts +160 -0
- package/src/3-path-functions/pathFunctionLoader.ts +282 -0
- package/src/3-path-functions/syncSchema.ts +475 -0
- package/src/3-path-functions/tests/functionsTest.ts +135 -0
- package/src/3-path-functions/tests/rejectTest.ts +77 -0
- package/src/4-dom/css.tsx +29 -0
- package/src/4-dom/cssTypes.d.ts +212 -0
- package/src/4-dom/qreact.tsx +2322 -0
- package/src/4-dom/qreactTest.tsx +417 -0
- package/src/4-querysub/Querysub.ts +877 -0
- package/src/4-querysub/QuerysubController.ts +620 -0
- package/src/4-querysub/copyEvent.ts +0 -0
- package/src/4-querysub/permissions.ts +289 -0
- package/src/4-querysub/permissionsShared.ts +1 -0
- package/src/4-querysub/querysubPrediction.ts +525 -0
- package/src/5-diagnostics/FullscreenModal.tsx +67 -0
- package/src/5-diagnostics/GenericFormat.tsx +165 -0
- package/src/5-diagnostics/Modal.tsx +79 -0
- package/src/5-diagnostics/Table.tsx +183 -0
- package/src/5-diagnostics/TimeGrouper.tsx +114 -0
- package/src/5-diagnostics/diskValueAudit.ts +216 -0
- package/src/5-diagnostics/memoryValueAudit.ts +442 -0
- package/src/5-diagnostics/nodeMetadata.ts +135 -0
- package/src/5-diagnostics/qreactDebug.tsx +309 -0
- package/src/5-diagnostics/shared.ts +26 -0
- package/src/5-diagnostics/synchronousLagTracking.ts +47 -0
- package/src/TestController.ts +35 -0
- package/src/allowclient.flag +0 -0
- package/src/bits.ts +86 -0
- package/src/buffers.ts +69 -0
- package/src/config.ts +53 -0
- package/src/config2.ts +48 -0
- package/src/diagnostics/ActionsHistory.ts +56 -0
- package/src/diagnostics/NodeViewer.tsx +503 -0
- package/src/diagnostics/SizeLimiter.ts +62 -0
- package/src/diagnostics/TimeDebug.tsx +18 -0
- package/src/diagnostics/benchmark.ts +139 -0
- package/src/diagnostics/errorLogs/ErrorLogController.ts +515 -0
- package/src/diagnostics/errorLogs/ErrorLogCore.ts +274 -0
- package/src/diagnostics/errorLogs/LogClassifiers.tsx +302 -0
- package/src/diagnostics/errorLogs/LogFilterUI.tsx +84 -0
- package/src/diagnostics/errorLogs/LogNotify.tsx +101 -0
- package/src/diagnostics/errorLogs/LogTimeSelector.tsx +724 -0
- package/src/diagnostics/errorLogs/LogViewer.tsx +757 -0
- package/src/diagnostics/errorLogs/hookErrors.ts +60 -0
- package/src/diagnostics/errorLogs/logFiltering.tsx +149 -0
- package/src/diagnostics/heapTag.ts +13 -0
- package/src/diagnostics/listenOnDebugger.ts +77 -0
- package/src/diagnostics/logs/DiskLoggerPage.tsx +572 -0
- package/src/diagnostics/logs/ObjectDisplay.tsx +165 -0
- package/src/diagnostics/logs/ansiFormat.ts +108 -0
- package/src/diagnostics/logs/diskLogGlobalContext.ts +38 -0
- package/src/diagnostics/logs/diskLogger.ts +305 -0
- package/src/diagnostics/logs/diskShimConsoleLogs.ts +32 -0
- package/src/diagnostics/logs/injectFileLocationToConsole.ts +50 -0
- package/src/diagnostics/logs/logGitHashes.ts +30 -0
- package/src/diagnostics/managementPages.tsx +289 -0
- package/src/diagnostics/periodic.ts +89 -0
- package/src/diagnostics/runSaturationTest.ts +416 -0
- package/src/diagnostics/satSchema.ts +64 -0
- package/src/diagnostics/trackResources.ts +82 -0
- package/src/diagnostics/watchdog.ts +55 -0
- package/src/errors.ts +132 -0
- package/src/forceProduction.ts +3 -0
- package/src/fs.ts +72 -0
- package/src/heapDumps.ts +666 -0
- package/src/https.ts +2 -0
- package/src/inject.ts +1 -0
- package/src/library-components/ATag.tsx +84 -0
- package/src/library-components/Button.tsx +344 -0
- package/src/library-components/ButtonSelector.tsx +64 -0
- package/src/library-components/DropdownCustom.tsx +151 -0
- package/src/library-components/DropdownSelector.tsx +32 -0
- package/src/library-components/Input.tsx +334 -0
- package/src/library-components/InputLabel.tsx +198 -0
- package/src/library-components/InputPicker.tsx +125 -0
- package/src/library-components/LazyComponent.tsx +62 -0
- package/src/library-components/MeasureHeightCSS.tsx +48 -0
- package/src/library-components/MeasuredDiv.tsx +47 -0
- package/src/library-components/ShowMore.tsx +51 -0
- package/src/library-components/SyncedController.ts +171 -0
- package/src/library-components/TimeRangeSelector.tsx +407 -0
- package/src/library-components/URLParam.ts +263 -0
- package/src/library-components/colors.tsx +14 -0
- package/src/library-components/drag.ts +114 -0
- package/src/library-components/icons.tsx +692 -0
- package/src/library-components/niceStringify.ts +50 -0
- package/src/library-components/renderToString.ts +52 -0
- package/src/misc/PromiseRace.ts +101 -0
- package/src/misc/color.ts +30 -0
- package/src/misc/getParentProcessId.cs +53 -0
- package/src/misc/getParentProcessId.ts +53 -0
- package/src/misc/hash.ts +83 -0
- package/src/misc/ipPong.js +13 -0
- package/src/misc/networking.ts +2 -0
- package/src/misc/random.ts +45 -0
- package/src/misc.ts +19 -0
- package/src/noserverhotreload.flag +0 -0
- package/src/path.ts +226 -0
- package/src/persistentLocalStore.ts +37 -0
- package/src/promise.ts +15 -0
- package/src/server.ts +73 -0
- package/src/src.d.ts +1 -0
- package/src/test/heapProcess.ts +36 -0
- package/src/test/mongoSatTest.tsx +55 -0
- package/src/test/satTest.ts +193 -0
- package/src/test/test.tsx +552 -0
- package/src/zip.ts +92 -0
- package/src/zipThreaded.ts +106 -0
- package/src/zipThreadedWorker.js +19 -0
- package/tsconfig.json +27 -0
- package/yarnSpec.txt +56 -0
|
@@ -0,0 +1,552 @@
|
|
|
1
|
+
// import { disableMeasurements } from "socket-function/src/profiling/measure";
|
|
2
|
+
// disableMeasurements();
|
|
3
|
+
|
|
4
|
+
import { isNode, list } from "socket-function/src/misc";
|
|
5
|
+
import { logErrors } from "../errors";
|
|
6
|
+
import { watchFilesAndTriggerHotReloading } from "socket-function/hot/HotReloadController";
|
|
7
|
+
import { Querysub } from "../4-querysub/QuerysubController";
|
|
8
|
+
import { red } from "socket-function/src/formatting/logColors";
|
|
9
|
+
import { PermissionsCheck } from "../4-querysub/permissions";
|
|
10
|
+
import { isDeploy } from "../3-path-functions/deployCheck";
|
|
11
|
+
import { formatTime } from "socket-function/src/formatting/format";
|
|
12
|
+
|
|
13
|
+
import { PromiseObj } from "../promise";
|
|
14
|
+
import { Benchmark } from "../diagnostics/benchmark";
|
|
15
|
+
import { formatStats, percent } from "socket-function/src/profiling/statsFormat";
|
|
16
|
+
import { cache } from "socket-function/src/caching";
|
|
17
|
+
import { atomic, atomicObjectWrite, proxyWatcher } from "../2-proxy/PathValueProxyWatcher";
|
|
18
|
+
import { fastHash } from "../misc/hash";
|
|
19
|
+
import { hslToRGB } from "../misc/color";
|
|
20
|
+
import { sat_data, sat_functions } from "../diagnostics/satSchema";
|
|
21
|
+
import { qreact } from "../4-dom/qreact";
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
// NOTE: In our first test of PathValueSerializer it is about 10X faster than JSONLACKS in parsing.
|
|
25
|
+
// - It will probably be even faster if we do lazy value deserialization
|
|
26
|
+
|
|
27
|
+
// async function test() {
|
|
28
|
+
// let testFile = "C:/Users/quent/shard/backups/querysub.com-4/PathFunctionRunner/lkddfcwz.lkddd8fv.lj9juidm.8b1s28.0.__gACTgA3gEFk1spi.YMm6Zg1AEejUtImU.json";
|
|
29
|
+
// //testFile = "C:/Users/quent/shard/backups/1-querysub.com/PathFunctionRunner/lj1z7won.lj1z5rrz.lj1z3oe0.2zy9m.0.json";
|
|
30
|
+
|
|
31
|
+
// await measureCode(async function test() {
|
|
32
|
+
// JSONLACKS.EXTENDED_PARSER = false;
|
|
33
|
+
|
|
34
|
+
// const testBuffer = measureBlock(function readFile() { return fs.readFileSync(testFile); });
|
|
35
|
+
// let objs = await measureBlock(async function JSONLACKSParse() { return await JSONLACKS.parseLines(testBuffer) as PathValue[]; });
|
|
36
|
+
|
|
37
|
+
// let newBuffer = await pathValueSerializer.serialize(objs, { noLocks: false, compress: true, });
|
|
38
|
+
// let objs2 = await pathValueSerializer.deserialize(newBuffer, {});
|
|
39
|
+
|
|
40
|
+
// console.log(`OLD ${formatNumber(testBuffer.length)} bytes, ${formatNumber(objs.length)} objects`);
|
|
41
|
+
// console.log(`NEW ${formatNumber(newBuffer.map(x => x.length).reduce((a, b) => a + b, 0))} bytes, ${formatNumber(objs2.length)} objects`);
|
|
42
|
+
|
|
43
|
+
// // for (let obj of objs2) {
|
|
44
|
+
// // pathValueSerializer.getPathValue(obj);
|
|
45
|
+
// // }
|
|
46
|
+
|
|
47
|
+
// // ALSO, make sure when we re-serialize, the second serialize is faster, because of the lazy objects (we will have to stop
|
|
48
|
+
// // getting all values first...)
|
|
49
|
+
// /*
|
|
50
|
+
// let newBuffer2 = await pathValueSerializer.serialize(objs2, { noLocks: true });
|
|
51
|
+
// let objs3 = await pathValueSerializer.deserialize(newBuffer2);
|
|
52
|
+
// console.log(`NEW2 ${formatNumber(newBuffer2.map(x => x.length).reduce((a, b) => a + b, 0))} bytes, ${formatNumber(objs3.length)} objects`);
|
|
53
|
+
// for (let obj of objs3) {
|
|
54
|
+
// pathValueSerializer.getPathValue(obj);
|
|
55
|
+
// }
|
|
56
|
+
// //*/
|
|
57
|
+
// }, { thresholdInTable: 0 });
|
|
58
|
+
// }
|
|
59
|
+
// test().catch(console.error).finally(() => process.exit());
|
|
60
|
+
|
|
61
|
+
/*
|
|
62
|
+
// Test passing around basic objects, and then buffers, references, etc
|
|
63
|
+
class TestControllerBase {
|
|
64
|
+
async returnValue<T>(obj: T) {
|
|
65
|
+
return obj;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
const TestController = SocketFunction.register(
|
|
69
|
+
"TestController-94c75a37-06db-4444-b5d0-416922f3adbc",
|
|
70
|
+
new TestControllerBase(),
|
|
71
|
+
() => ({
|
|
72
|
+
returnValue: {},
|
|
73
|
+
}),
|
|
74
|
+
);
|
|
75
|
+
|
|
76
|
+
async function main() {
|
|
77
|
+
let cborxInstance = new cborx.Encoder({ structuredClone: true });
|
|
78
|
+
SocketFunction.WIRE_SERIALIZER = {
|
|
79
|
+
serialize: async obj => [cborxInstance.encode(obj)],
|
|
80
|
+
deserialize: async ([buf]) => cborxInstance.decode(buf),
|
|
81
|
+
};
|
|
82
|
+
if (process.argv.includes("--server")) {
|
|
83
|
+
await SocketFunction.mount({
|
|
84
|
+
public: false,
|
|
85
|
+
port: 5051,
|
|
86
|
+
...await getThreadKeyCert(),
|
|
87
|
+
});
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
// Tests
|
|
93
|
+
// - string
|
|
94
|
+
// - number
|
|
95
|
+
// - object with strings and number
|
|
96
|
+
// - object with references
|
|
97
|
+
// - array of primitives/objects
|
|
98
|
+
// - array of primitives/objects/undefined/null
|
|
99
|
+
// - object with buffers / typed arrays
|
|
100
|
+
|
|
101
|
+
let serverNode = TestController.nodes[getNodeId("b77f134c680b3c537.bb752907afd3de60b.querysub.com", 5051)];
|
|
102
|
+
|
|
103
|
+
async function testString() {
|
|
104
|
+
let str = "test" + Date.now();
|
|
105
|
+
let result = await serverNode.returnValue(str);
|
|
106
|
+
if (result !== str) throw new Error(`Expected ${str}, got ${result}`);
|
|
107
|
+
}
|
|
108
|
+
async function testNumber() {
|
|
109
|
+
let num = Date.now();
|
|
110
|
+
let result = await serverNode.returnValue(num);
|
|
111
|
+
if (result !== num) throw new Error(`Expected ${num}, got ${result}`);
|
|
112
|
+
}
|
|
113
|
+
async function testObject() {
|
|
114
|
+
let obj = {
|
|
115
|
+
test: "test" + Date.now(),
|
|
116
|
+
num: Date.now(),
|
|
117
|
+
};
|
|
118
|
+
let result = await serverNode.returnValue(obj);
|
|
119
|
+
if (result.test !== obj.test) throw new Error(`Expected ${obj.test}, got ${result.test}`);
|
|
120
|
+
if (result.num !== obj.num) throw new Error(`Expected ${obj.num}, got ${result.num}`);
|
|
121
|
+
}
|
|
122
|
+
async function testObjectWithReferences() {
|
|
123
|
+
let objNested = { x: 5 };
|
|
124
|
+
let obj = {
|
|
125
|
+
obj0: objNested,
|
|
126
|
+
obj1: objNested,
|
|
127
|
+
obj2: { x: 5 },
|
|
128
|
+
};
|
|
129
|
+
let result = await serverNode.returnValue(obj);
|
|
130
|
+
if (result.obj0.x !== 5) throw new Error(`Expected ${objNested.x}, got ${result.obj0.x}`);
|
|
131
|
+
if (result.obj1.x !== 5) throw new Error(`Expected ${objNested.x}, got ${result.obj1.x}`);
|
|
132
|
+
if (result.obj2.x !== 5) throw new Error(`Expected ${objNested.x}, got ${result.obj2.x}`);
|
|
133
|
+
if (result.obj0 !== result.obj1) throw new Error(`Expected ${result.obj0}, got ${result.obj1}`);
|
|
134
|
+
if (result.obj0 === result.obj2) throw new Error(`Expected ${result.obj0} !== ${result.obj2}`);
|
|
135
|
+
}
|
|
136
|
+
async function testBasicArray() {
|
|
137
|
+
let arr = ["test" + Date.now(), Date.now()];
|
|
138
|
+
let result = await serverNode.returnValue(arr);
|
|
139
|
+
if (result[0] !== arr[0]) throw new Error(`Expected ${arr[0]}, got ${result[0]}`);
|
|
140
|
+
if (result[1] !== arr[1]) throw new Error(`Expected ${arr[1]}, got ${result[1]}`);
|
|
141
|
+
}
|
|
142
|
+
async function testComplexArray() {
|
|
143
|
+
let arr = [
|
|
144
|
+
"test" + Date.now(),
|
|
145
|
+
Date.now(),
|
|
146
|
+
undefined,
|
|
147
|
+
null
|
|
148
|
+
];
|
|
149
|
+
let result = await serverNode.returnValue(arr);
|
|
150
|
+
if (result.length !== arr.length) throw new Error(`Expected ${arr.length}, got ${result.length}`);
|
|
151
|
+
for (let i = 0; i < arr.length; i++) {
|
|
152
|
+
if (result[i] !== arr[i]) throw new Error(`Expected ${arr[i]}, got ${result[i]}`);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
async function testBuffersAndTypedArrays() {
|
|
157
|
+
let obj = {
|
|
158
|
+
test0: Buffer.from(new Float64Array(Array(1024).map(x => Math.random())).buffer),
|
|
159
|
+
test1: new Float64Array([1, 2]),
|
|
160
|
+
test2: new Uint8Array([1, 2]),
|
|
161
|
+
};
|
|
162
|
+
let result = await serverNode.returnValue(obj);
|
|
163
|
+
if (!Buffer.isBuffer(result.test0)) throw new Error(`Expected buffer, got ${result.test0}`);
|
|
164
|
+
if (!result.test0.equals(obj.test0)) throw new Error(`Expected ${obj.test0}, got ${result.test0}`);
|
|
165
|
+
if (!(result.test1 instanceof Float64Array)) throw new Error(`Expected Float64Array, got ${result.test1}`);
|
|
166
|
+
if (!(result.test2 instanceof Uint8Array)) throw new Error(`Expected Uint8Array, got ${result.test2}`);
|
|
167
|
+
if (result.test1[0] !== 1) throw new Error(`Expected 1, got ${result.test1[0]}`);
|
|
168
|
+
if (result.test1[1] !== 2) throw new Error(`Expected 2, got ${result.test1[1]}`);
|
|
169
|
+
if (result.test2[0] !== 1) throw new Error(`Expected 1, got ${result.test2[0]}`);
|
|
170
|
+
if (result.test2[1] !== 2) throw new Error(`Expected 2, got ${result.test2[1]}`);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
let tests: (() => Promise<void>)[] = [
|
|
174
|
+
testString,
|
|
175
|
+
testNumber,
|
|
176
|
+
testObject,
|
|
177
|
+
testObjectWithReferences,
|
|
178
|
+
testBasicArray,
|
|
179
|
+
testComplexArray,
|
|
180
|
+
testBuffersAndTypedArrays,
|
|
181
|
+
];
|
|
182
|
+
for (let test of tests) {
|
|
183
|
+
try {
|
|
184
|
+
await test();
|
|
185
|
+
} catch (e: any) {
|
|
186
|
+
console.error(`Failed test ${test.name}, ${e.message}`);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
process.exit();
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
logErrors(main());
|
|
193
|
+
*/
|
|
194
|
+
|
|
195
|
+
// async function main() {
|
|
196
|
+
// // Ah, well... we probably won't be reading massive objects anyways. So...
|
|
197
|
+
// // just using cborx with structuredClone is probably good enough?
|
|
198
|
+
|
|
199
|
+
// // let testFile = "C:/Users/quent/shard/backups/querysub.com-4/PathFunctionRunner/lkddfcwz.lkddd8fv.lj9juidm.8b1s28.0.__gACTgA3gEFk1spi.YMm6Zg1AEejUtImU.json";
|
|
200
|
+
// // //testFile = "C:/Users/quent/shard/backups/1-querysub.com/PathFunctionRunner/lj1z7won.lj1z5rrz.lj1z3oe0.2zy9m.0.json";
|
|
201
|
+
|
|
202
|
+
// // const testBuffer = fs.readFileSync(testFile);
|
|
203
|
+
// // let objs = await JSONLACKS.parseLines(testBuffer);
|
|
204
|
+
|
|
205
|
+
// // objs = [
|
|
206
|
+
// // {
|
|
207
|
+
// // test: Buffer.from(new Float64Array(Array(1024 * 1024 * 64).map(x => Math.random())).buffer)
|
|
208
|
+
// // },
|
|
209
|
+
// // {
|
|
210
|
+
// // test: Buffer.from(new Float64Array(Array(1024 * 1024 * 64).map(x => Math.random())).buffer)
|
|
211
|
+
// // },
|
|
212
|
+
// // {
|
|
213
|
+
// // test: Buffer.from(new Float64Array(Array(1024 * 1024 * 64).map(x => Math.random())).buffer)
|
|
214
|
+
// // },
|
|
215
|
+
// // {
|
|
216
|
+
// // test: Buffer.from(new Float64Array(Array(1024 * 1024 * 64).map(x => Math.random())).buffer)
|
|
217
|
+
// // }
|
|
218
|
+
// // ];
|
|
219
|
+
|
|
220
|
+
// // console.log(`${formatNumber(testBuffer.length)} bytes, ${formatNumber(objs.length)} objects`);
|
|
221
|
+
|
|
222
|
+
// // await measureCode(async function runWithMsgpack() {
|
|
223
|
+
// // let binary = measureBlock(function encode() {
|
|
224
|
+
// // return msgpack.encode(objs);
|
|
225
|
+
// // });
|
|
226
|
+
// // let newObjs = measureBlock(function decode() {
|
|
227
|
+
// // return msgpack.decode(binary) as any;
|
|
228
|
+
// // });
|
|
229
|
+
// // console.log(`msgpack = ${formatNumber(binary.length)} bytes, count ${newObjs.length}`);
|
|
230
|
+
// // });
|
|
231
|
+
|
|
232
|
+
// // await measureCode(async function runWithCborx() {
|
|
233
|
+
// // let binary = measureBlock(function encode() {
|
|
234
|
+
// // return cborx.encode(objs);
|
|
235
|
+
// // });
|
|
236
|
+
// // let newObjs = measureBlock(function decode() {
|
|
237
|
+
// // return cborx.decode(binary);
|
|
238
|
+
// // });
|
|
239
|
+
// // console.log(`cborx = ${formatNumber(binary.length)} bytes, count ${newObjs.length}`);
|
|
240
|
+
// // });
|
|
241
|
+
|
|
242
|
+
// // await measureCode(async function runWithCborxStructured() {
|
|
243
|
+
// // let encoder = new cborx.Encoder({ structuredClone: true });
|
|
244
|
+
// // let binary = measureBlock(function encode() {
|
|
245
|
+
// // return encoder.encode(objs);
|
|
246
|
+
// // });
|
|
247
|
+
// // let newObjs = measureBlock(function decode() {
|
|
248
|
+
// // return encoder.decode(binary);
|
|
249
|
+
// // });
|
|
250
|
+
// // console.log(`cborx structured = ${formatNumber(binary.length)} bytes, count ${newObjs.length}`);
|
|
251
|
+
// // });
|
|
252
|
+
|
|
253
|
+
|
|
254
|
+
// // let archives = getArchives("test");
|
|
255
|
+
|
|
256
|
+
// // await archives.set("folder/a.txt", Buffer.from("test" + Date.now()));
|
|
257
|
+
// // await archives.set("folder/b.txt", Buffer.from("test" + Date.now()));
|
|
258
|
+
// // await archives.set("folder/nested/1.txt", Buffer.from("test" + Date.now()));
|
|
259
|
+
|
|
260
|
+
// // console.log("all files", await archives.find(""));
|
|
261
|
+
// // console.log("root folders", await archives.find("", { shallow: true, type: "folders" }));
|
|
262
|
+
// // console.log("all folders", await archives.find("", { type: "folders" }));
|
|
263
|
+
// // console.log("nested files", await archives.find("folder/", { shallow: true, type: "files" }));
|
|
264
|
+
// // console.log("nested folders", await archives.find("folder/", { shallow: true, type: "folders" }));
|
|
265
|
+
|
|
266
|
+
// // process.exit();
|
|
267
|
+
|
|
268
|
+
// // await archives.set("nested/testFile.txt", Buffer.from("test" + Date.now()));
|
|
269
|
+
// // console.log("testResult", (await archives.get("nested/testFile.txt"))?.toString());
|
|
270
|
+
// // let info = await archives.getInfo("nested/testFile.txt");
|
|
271
|
+
// // console.log("info", info);
|
|
272
|
+
// // console.log("files", await archives.find("nested/"));
|
|
273
|
+
// // await archives.del("nested/testFile.txt");
|
|
274
|
+
// // console.log("files", await archives.find("nested/"));
|
|
275
|
+
// // console.log("testResult", (await archives.get("nested/testFile.txt"))?.toString());
|
|
276
|
+
|
|
277
|
+
// // SocketFunction.silent = false;
|
|
278
|
+
// // await SocketFunction.mount({
|
|
279
|
+
// // public: false,
|
|
280
|
+
// // port: 0,
|
|
281
|
+
// // ...await getThreadKeyCert(),
|
|
282
|
+
// // });
|
|
283
|
+
// // watchNodeIds(nodeIds => {
|
|
284
|
+
// // console.log(`Node ids changed at ${new Date().toISOString()}`);
|
|
285
|
+
// // for (let id of nodeIds) {
|
|
286
|
+
// // console.log(` ${id}`);
|
|
287
|
+
// // }
|
|
288
|
+
// // console.log();
|
|
289
|
+
// // });
|
|
290
|
+
// }
|
|
291
|
+
|
|
292
|
+
// logErrors(main());
|
|
293
|
+
|
|
294
|
+
|
|
295
|
+
|
|
296
|
+
|
|
297
|
+
//*
|
|
298
|
+
|
|
299
|
+
|
|
300
|
+
// let { data, functions } = Querysub.createSchema<{
|
|
301
|
+
// ownedValues: {
|
|
302
|
+
// [key: string]: string;
|
|
303
|
+
// },
|
|
304
|
+
// values: {
|
|
305
|
+
// [index: number]: {
|
|
306
|
+
// sum: number;
|
|
307
|
+
// lastUpdated: number;
|
|
308
|
+
// lastUpdatedBy: string;
|
|
309
|
+
// }
|
|
310
|
+
// };
|
|
311
|
+
// }>()({
|
|
312
|
+
// domainName: "querysub.com",
|
|
313
|
+
// functions: {
|
|
314
|
+
// setValues(indexes: number[], value?: number) {
|
|
315
|
+
// for (let index of indexes) {
|
|
316
|
+
// let newValue = value ?? (data().values[index].sum + 1);
|
|
317
|
+
// data().values[index] = {
|
|
318
|
+
// sum: newValue,
|
|
319
|
+
// lastUpdated: Querysub.now(),
|
|
320
|
+
// lastUpdatedBy: Querysub.getCallerMachineId(),
|
|
321
|
+
// };
|
|
322
|
+
// }
|
|
323
|
+
// },
|
|
324
|
+
// setOwnedValue(key: string, value: string) {
|
|
325
|
+
// data().ownedValues[key] = value;
|
|
326
|
+
// }
|
|
327
|
+
// },
|
|
328
|
+
// module,
|
|
329
|
+
// moduleId: "test",
|
|
330
|
+
// functionMetadata: {},
|
|
331
|
+
// permissions: {
|
|
332
|
+
// PERMISSIONS: isRegisteredUserCheck,
|
|
333
|
+
// ownedValues: {
|
|
334
|
+
// ["*"]: {
|
|
335
|
+
// PERMISSIONS: (config) => {
|
|
336
|
+
// return config.pathWildcards?.[0] === config.callerMachineId;
|
|
337
|
+
// },
|
|
338
|
+
// }
|
|
339
|
+
// }
|
|
340
|
+
// }
|
|
341
|
+
// });
|
|
342
|
+
|
|
343
|
+
function isRegisteredUserCheck(): boolean {
|
|
344
|
+
let allowed = Querysub.getCallerIP() === "127.0.0.1";
|
|
345
|
+
if (!allowed) {
|
|
346
|
+
console.log(red(`Permission denied to IP ${JSON.stringify(Querysub.getCallerIP())}`));
|
|
347
|
+
}
|
|
348
|
+
return allowed;
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
|
|
352
|
+
|
|
353
|
+
const INDEX_EXTENT = 300 * 300;
|
|
354
|
+
//const INDEX_EXTENT = 100 * 100;
|
|
355
|
+
|
|
356
|
+
let getNodeHue = cache((nodeId: string) => {
|
|
357
|
+
return fastHash(nodeId) % 360;
|
|
358
|
+
});
|
|
359
|
+
|
|
360
|
+
|
|
361
|
+
class Page extends qreact.Component {
|
|
362
|
+
|
|
363
|
+
state = {
|
|
364
|
+
results: atomicObjectWrite([]) as string[],
|
|
365
|
+
canvas: undefined as undefined | {
|
|
366
|
+
value: HTMLCanvasElement;
|
|
367
|
+
context: CanvasRenderingContext2D;
|
|
368
|
+
},
|
|
369
|
+
writeTime: 0,
|
|
370
|
+
key: "",
|
|
371
|
+
};
|
|
372
|
+
|
|
373
|
+
onUnmount = new PromiseObj();
|
|
374
|
+
componentDidMount(): void {
|
|
375
|
+
let index = 0;
|
|
376
|
+
// NOTE: This ends up being a lot slower, due to the massive overhead of having a watcher
|
|
377
|
+
// with so many watched paths.
|
|
378
|
+
// setInterval(() => {
|
|
379
|
+
// functions.setValues([index++]);
|
|
380
|
+
// }, 100);
|
|
381
|
+
}
|
|
382
|
+
componentWillUnmount(): void {
|
|
383
|
+
this.onUnmount.resolve();
|
|
384
|
+
}
|
|
385
|
+
render() {
|
|
386
|
+
let canvasObj = atomic(this.state.canvas);
|
|
387
|
+
if (canvasObj) {
|
|
388
|
+
let watcher = proxyWatcher.getTriggeredWatcher();
|
|
389
|
+
watcher.pendingWatches.paths = new Set(watcher.lastWatches.paths);
|
|
390
|
+
watcher.pendingWatches.parentPaths = new Set(watcher.lastWatches.parentPaths);
|
|
391
|
+
if (watcher.pendingWatches.paths.size < 1000) {
|
|
392
|
+
for (let v = 0; v < INDEX_EXTENT; v++) {
|
|
393
|
+
sat_data().values[v];
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
let changes = watcher.triggeredByChanges;
|
|
398
|
+
let indexesChanged = new Set<number>();
|
|
399
|
+
if (changes && changes.paths.size < 1000) {
|
|
400
|
+
for (let path of changes?.paths) {
|
|
401
|
+
if (path.startsWith(".,querysub._com.,PathFunctionRunner.,saturationTest.,Data.,values.,")) {
|
|
402
|
+
indexesChanged.add(Number(path.split(".,").at(-2)));
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
} else {
|
|
406
|
+
for (let v = 0; v < INDEX_EXTENT; v++) {
|
|
407
|
+
indexesChanged.add(v);
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
let { value: canvas, context } = canvasObj;
|
|
411
|
+
let imageData = context.getImageData(0, 0, canvas.width, canvas.height);
|
|
412
|
+
let imageArray = imageData.data;
|
|
413
|
+
for (let v of indexesChanged) {
|
|
414
|
+
let i = v * 4;
|
|
415
|
+
let obj = sat_data().values[v];
|
|
416
|
+
let baseSum = Number(obj);
|
|
417
|
+
let sum = Number(baseSum) % 3;
|
|
418
|
+
|
|
419
|
+
let hue = 180;
|
|
420
|
+
let saturation = (0.5 + sum / 3 * 0.5) * 100;
|
|
421
|
+
let lightness = (0.5 + sum / 3 * 0.5) * 100;
|
|
422
|
+
if (!baseSum) {
|
|
423
|
+
lightness = 100;
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
let rgb = hslToRGB({ h: hue, s: saturation, l: lightness });
|
|
427
|
+
|
|
428
|
+
imageArray[i + 0] = rgb.r;
|
|
429
|
+
imageArray[i + 1] = rgb.g;
|
|
430
|
+
imageArray[i + 2] = rgb.b;
|
|
431
|
+
imageArray[i + 3] = 255;
|
|
432
|
+
}
|
|
433
|
+
context.putImageData(imageData, 0, 0);
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
|
|
437
|
+
return (
|
|
438
|
+
<div>
|
|
439
|
+
<div>Calls {formatStats(Benchmark.getLiveCallStats(), { noColor: true })}</div>
|
|
440
|
+
<div>Rate: {Math.round(Benchmark.getLiveRate() * 1000 * 10) / 10}/s</div>
|
|
441
|
+
<div>Saturated: {percent(Benchmark.saturatedFraction())}</div>
|
|
442
|
+
<div>Predict {Benchmark.predictCount}, received {Benchmark.receivedCount}</div>
|
|
443
|
+
<div>Open {Benchmark.overlapRate.openCount}, time waiting {Benchmark.overlapRate.finishedTime}</div>
|
|
444
|
+
<div>Machine Id {Querysub.getSelfMachineId()}</div>
|
|
445
|
+
{/* <div>
|
|
446
|
+
<label>
|
|
447
|
+
Key <input value={this.state.key} onChange={e => this.state.key = e.currentTarget.value} />
|
|
448
|
+
</label>
|
|
449
|
+
<div>
|
|
450
|
+
Value: <input
|
|
451
|
+
value={data().ownedValues[this.state.key]}
|
|
452
|
+
onChange={e => functions.setOwnedValue(this.state.key, e.currentTarget.value)}
|
|
453
|
+
/>
|
|
454
|
+
</div>
|
|
455
|
+
</div>
|
|
456
|
+
<div>
|
|
457
|
+
Owned values keys (should be empty) {Object.keys(data().ownedValues).join(", ")}
|
|
458
|
+
</div> */}
|
|
459
|
+
<div style={{ display: "flex", gap: 10 }}>
|
|
460
|
+
<button onClick={() => {
|
|
461
|
+
sat_functions.setValues([0]);
|
|
462
|
+
}}>
|
|
463
|
+
Single write
|
|
464
|
+
</button>
|
|
465
|
+
<button onClick={() => {
|
|
466
|
+
//functions.setValues(list(INDEX_EXTENT));
|
|
467
|
+
setImmediate(async () => {
|
|
468
|
+
let time = Date.now();
|
|
469
|
+
let call = sat_functions.setValues(list(INDEX_EXTENT), 0);
|
|
470
|
+
//let call = functions.setValues(list(10 * 1000), 0);
|
|
471
|
+
await Benchmark.waitForCallToFinish(call);
|
|
472
|
+
time = Date.now() - time;
|
|
473
|
+
Querysub.serviceWriteDetached(() => {
|
|
474
|
+
this.state.writeTime = time;
|
|
475
|
+
});
|
|
476
|
+
});
|
|
477
|
+
}}>
|
|
478
|
+
Value Fill
|
|
479
|
+
</button>
|
|
480
|
+
<div>
|
|
481
|
+
Write time: {formatTime(this.state.writeTime)}
|
|
482
|
+
</div>
|
|
483
|
+
</div>
|
|
484
|
+
<div>
|
|
485
|
+
<canvas
|
|
486
|
+
width={Math.ceil(Math.sqrt(INDEX_EXTENT))}
|
|
487
|
+
height={Math.ceil(Math.sqrt(INDEX_EXTENT))}
|
|
488
|
+
style={{
|
|
489
|
+
border: "1px solid black",
|
|
490
|
+
zoom: 800 / Math.sqrt(INDEX_EXTENT),
|
|
491
|
+
imageRendering: "pixelated",
|
|
492
|
+
}}
|
|
493
|
+
ref={canvas => {
|
|
494
|
+
if (canvas && canvas !== this.state.canvas?.value) {
|
|
495
|
+
this.state.canvas = atomicObjectWrite({
|
|
496
|
+
value: canvas,
|
|
497
|
+
context: canvas.getContext("2d")!,
|
|
498
|
+
});
|
|
499
|
+
}
|
|
500
|
+
}}
|
|
501
|
+
/>
|
|
502
|
+
</div>
|
|
503
|
+
<pre>
|
|
504
|
+
{this.state.results.map(result => <div>{result || <> </>}</div>)}
|
|
505
|
+
</pre>
|
|
506
|
+
</div>
|
|
507
|
+
);
|
|
508
|
+
}
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
async function browserMain() {
|
|
512
|
+
if (isNode()) return;
|
|
513
|
+
|
|
514
|
+
watchFilesAndTriggerHotReloading();
|
|
515
|
+
|
|
516
|
+
//Querysub.debug();
|
|
517
|
+
// ClientWatcher.DEBUG_READS = true;
|
|
518
|
+
// ClientWatcher.DEBUG_WRITES = true;
|
|
519
|
+
// Querysub.DEBUG_CALLS = true;
|
|
520
|
+
|
|
521
|
+
qreact.render(qreact.createElement(Page, {}), document.getElementById("main")!);
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
async function main() {
|
|
525
|
+
if (!isNode()) return;
|
|
526
|
+
if (isDeploy()) return;
|
|
527
|
+
if (module.hotreload) return;
|
|
528
|
+
const edgePort = 5050;
|
|
529
|
+
PermissionsCheck.DEBUG = true;
|
|
530
|
+
// ClientWatcher.DEBUG_READS = true;
|
|
531
|
+
// ClientWatcher.DEBUG_WRITES = true;
|
|
532
|
+
//debugCoreMode();
|
|
533
|
+
|
|
534
|
+
//SocketFunction.silent = false;
|
|
535
|
+
Error.stackTraceLimit = 20;
|
|
536
|
+
|
|
537
|
+
await Querysub.hostServer({
|
|
538
|
+
trustedDomains: ["querysub.com"],
|
|
539
|
+
port: edgePort,
|
|
540
|
+
rootPath: __dirname + "/../../",
|
|
541
|
+
clientsideEntryPoint: "./src/test/test.tsx",
|
|
542
|
+
hotReload: true,
|
|
543
|
+
});
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
module.hotreload = isNode() && process.argv[1].includes("PathFunctionRunnerMain.ts");
|
|
547
|
+
module.noserverhotreload = false;
|
|
548
|
+
|
|
549
|
+
logErrors(main());
|
|
550
|
+
logErrors(browserMain());
|
|
551
|
+
|
|
552
|
+
//*/
|
package/src/zip.ts
ADDED
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { isNode } from "socket-function/src/misc";
|
|
2
|
+
import { measureBlock, measureFnc } from "socket-function/src/profiling/measure";
|
|
3
|
+
import zlib from "zlib";
|
|
4
|
+
import * as pako from "pako";
|
|
5
|
+
|
|
6
|
+
import { setFlag } from "socket-function/require/compileFlags";
|
|
7
|
+
import { unzipThreaded } from "./zipThreaded";
|
|
8
|
+
import debugbreak from "debugbreak";
|
|
9
|
+
import { formatNumber } from "socket-function/src/formatting/format";
|
|
10
|
+
import { runInSerial } from "socket-function/src/batching";
|
|
11
|
+
setFlag(require, "pako", "allowclient", true);
|
|
12
|
+
|
|
13
|
+
export class Zip {
|
|
14
|
+
@measureFnc
|
|
15
|
+
public static async gzip(buffer: Buffer, level?: number): Promise<Buffer> {
|
|
16
|
+
if (isNode()) {
|
|
17
|
+
return new Promise((resolve, reject) => {
|
|
18
|
+
zlib.gzip(buffer, { level }, (err: any, result: Buffer) => {
|
|
19
|
+
if (err) reject(err);
|
|
20
|
+
else resolve(result);
|
|
21
|
+
});
|
|
22
|
+
});
|
|
23
|
+
} else {
|
|
24
|
+
// @ts-ignore
|
|
25
|
+
return await doStream(new CompressionStream("gzip"), buffer);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
@measureFnc
|
|
29
|
+
public static async gunzip(buffer: Buffer): Promise<Buffer> {
|
|
30
|
+
return Zip.gunzipUntracked(buffer);
|
|
31
|
+
}
|
|
32
|
+
// A base function, so we can avoid instrumentation for batch calls
|
|
33
|
+
public static async gunzipUntracked(buffer: Buffer): Promise<Buffer> {
|
|
34
|
+
if (isNode()) {
|
|
35
|
+
let test = await unzipThreaded(buffer);
|
|
36
|
+
// let test2 = await new Promise<Buffer>((resolve, reject) => {
|
|
37
|
+
// zlib.gunzip(buffer, (err: any, result: Buffer) => {
|
|
38
|
+
// if (err) reject(err);
|
|
39
|
+
// else resolve(result);
|
|
40
|
+
// });
|
|
41
|
+
// });
|
|
42
|
+
// if (test.length !== test2.length) {
|
|
43
|
+
// debugbreak(2);
|
|
44
|
+
// debugger;
|
|
45
|
+
// }
|
|
46
|
+
// for (let i = 0; i < test.length; i++) {
|
|
47
|
+
// if (test[i] !== test2[i]) {
|
|
48
|
+
// debugbreak(2);
|
|
49
|
+
// debugger;
|
|
50
|
+
// }
|
|
51
|
+
// }
|
|
52
|
+
|
|
53
|
+
return test;
|
|
54
|
+
} else {
|
|
55
|
+
// NOTE: pako seems to be faster, at least clientside.
|
|
56
|
+
// TIMING: 700ms vs 1200ms
|
|
57
|
+
// - This might just be faster for small files.
|
|
58
|
+
return Buffer.from(pako.inflate(buffer));
|
|
59
|
+
// @ts-ignore
|
|
60
|
+
// return await doStream(new DecompressionStream("gzip"), buffer);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
@measureFnc
|
|
65
|
+
public static async gunzipBatch(buffers: Buffer[]): Promise<Buffer[]> {
|
|
66
|
+
let time = Date.now();
|
|
67
|
+
buffers = await Promise.all(buffers.map(Zip.gunzipUntracked));
|
|
68
|
+
time = Date.now() - time;
|
|
69
|
+
let totalSize = buffers.reduce((acc, buffer) => acc + buffer.length, 0);
|
|
70
|
+
//console.log(`Gunzip ${formatNumber(totalSize)}B at ${formatNumber(totalSize / time * 1000)}B/s`);
|
|
71
|
+
return buffers;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
async function doStream(stream: GenericTransformStream, buffer: Buffer): Promise<Buffer> {
|
|
76
|
+
let reader = stream.readable.getReader();
|
|
77
|
+
let writer = stream.writable.getWriter();
|
|
78
|
+
let writePromise = writer.write(buffer);
|
|
79
|
+
let closePromise = writer.close();
|
|
80
|
+
|
|
81
|
+
let outputBuffers: Buffer[] = [];
|
|
82
|
+
while (true) {
|
|
83
|
+
let { value, done } = await reader.read();
|
|
84
|
+
if (done) {
|
|
85
|
+
await writePromise;
|
|
86
|
+
await closePromise;
|
|
87
|
+
return Buffer.concat(outputBuffers);
|
|
88
|
+
}
|
|
89
|
+
outputBuffers.push(Buffer.from(value));
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
}
|