querysub 0.437.0 → 0.439.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 (81) hide show
  1. package/.eslintrc.js +50 -50
  2. package/bin/deploy.js +0 -0
  3. package/bin/function.js +0 -0
  4. package/bin/server.js +0 -0
  5. package/costsBenefits.txt +115 -115
  6. package/deploy.ts +2 -2
  7. package/package.json +2 -2
  8. package/spec.txt +1192 -1192
  9. package/src/-a-archives/archives.ts +202 -202
  10. package/src/-a-archives/archivesDisk.ts +454 -454
  11. package/src/-a-auth/certs.ts +540 -540
  12. package/src/-a-auth/node-forge-ed25519.d.ts +16 -16
  13. package/src/-b-authorities/dnsAuthority.ts +138 -138
  14. package/src/-c-identity/IdentityController.ts +258 -258
  15. package/src/-d-trust/NetworkTrust2.ts +180 -180
  16. package/src/-e-certs/EdgeCertController.ts +252 -252
  17. package/src/-e-certs/certAuthority.ts +201 -201
  18. package/src/-f-node-discovery/NodeDiscovery.ts +640 -640
  19. package/src/-g-core-values/NodeCapabilities.ts +200 -200
  20. package/src/-h-path-value-serialize/stringSerializer.ts +175 -175
  21. package/src/0-path-value-core/PathValueCommitter.ts +468 -468
  22. package/src/0-path-value-core/PathValueController.ts +0 -2
  23. package/src/0-path-value-core/archiveLocks/archiveSnapshots.ts +37 -1
  24. package/src/0-path-value-core/pathValueCore.ts +12 -0
  25. package/src/2-proxy/PathValueProxyWatcher.ts +2542 -2542
  26. package/src/2-proxy/TransactionDelayer.ts +94 -94
  27. package/src/2-proxy/pathDatabaseProxyBase.ts +36 -36
  28. package/src/2-proxy/pathValueProxy.ts +159 -159
  29. package/src/3-path-functions/PathFunctionRunner.ts +24 -13
  30. package/src/3-path-functions/PathFunctionRunnerMain.ts +87 -87
  31. package/src/3-path-functions/pathFunctionLoader.ts +516 -516
  32. package/src/3-path-functions/tests/rejectTest.ts +76 -76
  33. package/src/4-deploy/deployCheck.ts +6 -6
  34. package/src/4-dom/css.tsx +29 -29
  35. package/src/4-dom/cssTypes.d.ts +211 -211
  36. package/src/4-dom/qreact.tsx +2799 -2799
  37. package/src/4-dom/qreactTest.tsx +410 -410
  38. package/src/4-querysub/permissions.ts +335 -335
  39. package/src/4-querysub/querysubPrediction.ts +483 -483
  40. package/src/5-diagnostics/qreactDebug.tsx +400 -346
  41. package/src/TestController.ts +34 -34
  42. package/src/bits.ts +104 -104
  43. package/src/buffers.ts +69 -69
  44. package/src/diagnostics/ActionsHistory.ts +57 -57
  45. package/src/diagnostics/PathDistributionInfo.tsx +9 -1
  46. package/src/diagnostics/listenOnDebugger.ts +71 -71
  47. package/src/diagnostics/logs/IndexedLogs/BufferUnitIndex.ts +1 -1
  48. package/src/diagnostics/logs/diskLogger.ts +6 -0
  49. package/src/diagnostics/misc-pages/SnapshotViewer.tsx +78 -1
  50. package/src/diagnostics/periodic.ts +111 -111
  51. package/src/diagnostics/trackResources.ts +91 -91
  52. package/src/diagnostics/watchdog.ts +120 -120
  53. package/src/errors.ts +133 -133
  54. package/src/forceProduction.ts +2 -2
  55. package/src/fs.ts +80 -80
  56. package/src/functional/diff.ts +857 -857
  57. package/src/functional/promiseCache.ts +78 -78
  58. package/src/functional/random.ts +8 -8
  59. package/src/functional/stats.ts +60 -60
  60. package/src/heapDumps.ts +665 -665
  61. package/src/https.ts +1 -1
  62. package/src/library-components/AspectSizedComponent.tsx +87 -87
  63. package/src/library-components/ButtonSelector.tsx +64 -64
  64. package/src/library-components/DropdownCustom.tsx +150 -150
  65. package/src/library-components/DropdownSelector.tsx +31 -31
  66. package/src/library-components/InlinePopup.tsx +66 -66
  67. package/src/library-components/uncaughtToast.tsx +2 -0
  68. package/src/misc/color.ts +29 -29
  69. package/src/misc/hash.ts +83 -83
  70. package/src/misc/ipPong.js +13 -13
  71. package/src/misc/networking.ts +1 -1
  72. package/src/misc/random.ts +44 -44
  73. package/src/misc.ts +196 -196
  74. package/src/path.ts +255 -255
  75. package/src/persistentLocalStore.ts +41 -41
  76. package/src/promise.ts +14 -14
  77. package/src/storage/fileSystemPointer.ts +71 -71
  78. package/src/test/heapProcess.ts +35 -35
  79. package/src/zip.ts +15 -15
  80. package/tsconfig.json +26 -26
  81. package/yarnSpec.txt +56 -56
@@ -1,201 +1,201 @@
1
- /*
2
- Find nodes that implement a specific controller.
3
- */
4
-
5
- import { SocketFunction } from "socket-function/SocketFunction";
6
- import { SocketRegistered } from "socket-function/SocketFunctionTypes";
7
- import { errorToUndefined, errorToUndefinedSilent, timeoutToUndefinedSilent } from "../errors";
8
- import { getAllNodeIds, isNodeIdOnOwnMachineId } from "../-f-node-discovery/NodeDiscovery";
9
- import { green, red, yellow } from "socket-function/src/formatting/logColors";
10
- import { shuffle } from "../misc/random";
11
- import { delay } from "socket-function/src/batching";
12
- import debugbreak from "debugbreak";
13
- import { formatTime } from "socket-function/src/formatting/format";
14
- import type { DebugFunctionShardInfo } from "../3-path-functions/PathFunctionRunner";
15
- import { requiresNetworkTrustHook } from "../-d-trust/NetworkTrust2";
16
- import { isNoNetwork } from "../config";
17
- import { getDebuggerUrl } from "../diagnostics/listenOnDebugger";
18
- import { hackDevtoolsWebsocketForward } from "./oneTimeForward";
19
- import { getOwnMachineId, decodeNodeId, decodeNodeIdAssert, getMachineId } from "../-a-auth/certs";
20
- import { sort } from "socket-function/src/misc";
21
- import { getPathStr2 } from "../path";
22
- import { PromiseObj } from "../promise";
23
- import { getTrueTimeOffset } from "socket-function/time/trueTimeShim";
24
- setImmediate(() => {
25
- import("../diagnostics/MachineThreadInfo");
26
- });
27
-
28
- let controllerNodeIdCache = new Map<string, string | Promise<string | undefined>>();
29
-
30
- // NOTE: If this becomes slow (because we are just trying all servers), we could start to store capabilities
31
- // in PersistedStorage. However, I don't think it will be a problem for quite some time.
32
- export async function getControllerNodeId(
33
- controller: SocketRegistered<{}>,
34
- quiet = false,
35
- retryCount = 1,
36
- initialTime = Date.now(),
37
- ): Promise<string | undefined> {
38
- let cached = controllerNodeIdCache.get(controller._classGuid);
39
- if (cached && typeof cached !== "string") {
40
- cached = await cached;
41
- }
42
- // TODO: We are relying on is node connected to do a lot of work here. If the node's connected, but somehow doesn't work, we can get in an unrecoverable state, even if there are plenty of other working nodes.
43
- if (cached && !SocketFunction.isNodeConnected(cached)) {
44
- controllerNodeIdCache.delete(controller._classGuid);
45
- cached = undefined;
46
- }
47
- if (cached) return cached;
48
- let promise = getInternal(retryCount);
49
- controllerNodeIdCache.set(controller._classGuid, promise);
50
- return promise;
51
-
52
- async function getInternal(retryCount: number) {
53
- let nodeIdsToTest = await getAllNodeIds();
54
- // Shuffle, so we aren't always using the same node!
55
- nodeIdsToTest = shuffle(nodeIdsToTest, Date.now());
56
- let resolvedNode = new PromiseObj<string>();
57
-
58
- if (!quiet) {
59
- console.log(`Checking ${nodeIdsToTest.length} nodes for capability ${controller._classGuid}`);
60
- }
61
- let allFinished = Promise.all(nodeIdsToTest.map(async nodeId => {
62
- if (await doesNodeExposeController(nodeId, controller)) {
63
- if (!quiet) {
64
- let duration = Date.now() - initialTime;
65
- console.log(green(`Resolved capability ${controller._classGuid} with node ${nodeId}, in ${formatTime(duration)}`));
66
- }
67
- resolvedNode.resolve(nodeId);
68
- }
69
- }));
70
- let result = await Promise.race([allFinished, resolvedNode.promise]);
71
- if (typeof result === "string") {
72
- return result;
73
- }
74
-
75
- if (retryCount > 0) {
76
- if (!quiet) {
77
- console.log(`Did not find capability in ${nodeIdsToTest.length} nodes, retrying... ${controller._classGuid}`);
78
- }
79
- await delay(2000);
80
- return getInternal(retryCount - 1);
81
- }
82
- if (!quiet) {
83
- console.warn(yellow(`Could not find a node that exposes controller ${controller._classGuid}, tried: ${JSON.stringify(nodeIdsToTest)}`));
84
- }
85
- return undefined;
86
- }
87
- }
88
-
89
- export async function getControllerNodeIdList(
90
- controller: SocketRegistered<{}>,
91
- ): Promise<{ nodeId: string; entryPoint: string }[]> {
92
- let nodeIdsToTest = await getAllNodeIds();
93
- let passedNodeIds = new Map<string, { machineId: string; entryPoint: string }>();
94
- await Promise.all(nodeIdsToTest.map(async nodeId => {
95
- let result = await doesNodeExposeController(nodeId, controller);
96
- if (result) {
97
- let entryPoint = await NodeCapabilitiesController.nodes[nodeId].getEntryPoint();
98
- passedNodeIds.set(nodeId, {
99
- machineId: getMachineId(nodeId),
100
- entryPoint,
101
- });
102
- }
103
- }));
104
-
105
- let results = Array.from(passedNodeIds.entries());
106
- // Prefer localhost connections as they're faster.
107
- sort(results, (x) => isNodeIdOnOwnMachineId(x[0]) ? 0 : 1);
108
- let lookup = new Map<string, { nodeId: string; entryPoint: string }>();
109
- for (let x of results) {
110
- let key = getPathStr2(x[1].machineId, decodeNodeIdAssert(x[0]).port.toString());
111
- if (key in lookup) continue;
112
- lookup.set(key, { nodeId: x[0], entryPoint: x[1].entryPoint });
113
- }
114
-
115
- return Array.from(lookup.values());
116
- }
117
-
118
-
119
- export async function doesNodeExposeController(reconnectNodeId: string, controller: SocketRegistered<{}>): Promise<boolean> {
120
- let exposedControllers = await timeoutToUndefinedSilent(10_000, NodeCapabilitiesController.nodes[reconnectNodeId].getExposedControllers());
121
-
122
- if (exposedControllers?.includes(controller._classGuid)) {
123
- return true;
124
- }
125
- return false;
126
- }
127
-
128
- const startupTime = Date.now();
129
- class NodeCapabilitiesControllerBase {
130
- public async getExposedControllers() {
131
- return Array.from(SocketFunction.exposedClasses);
132
- }
133
- public async getEntryPoint() {
134
- return process.argv[1];
135
- }
136
- public async getStartupTime() {
137
- return startupTime;
138
- }
139
- public async getMemoryUsage() {
140
- return process.memoryUsage();
141
- }
142
- public async getFunctionRunnerShards() {
143
- return getFunctionRunnerShards();
144
- }
145
-
146
- public async getTrueTimeOffset() {
147
- return getTrueTimeOffset();
148
- }
149
-
150
- public async getInspectURL() {
151
- return await getDebuggerUrl();
152
- }
153
-
154
- public async exposeExternalDebugPortOnce(forExternalIP: string) {
155
- // https://notdevtools.com/devtools/inspector.html?experiments=true&v8only=true&ws=127.0.0.1:62448/22895aed-f8da-4dfb-8d50-e432a9c2d827
156
- let debugURL = await this.getInspectURL();
157
-
158
- const outerUrl = new URL(debugURL);
159
- const wsParam = outerUrl.searchParams.get("ws");
160
- if (!wsParam) throw new Error("No ws parameter found");
161
-
162
- // Add ws:// protocol to make it parseable by URL
163
- const innerUrl = new URL(`ws://${wsParam}`);
164
- const port = innerUrl.port;
165
- if (!port) throw new Error("No port found");
166
-
167
- const portNumber = parseInt(port, 10);
168
- if (isNaN(portNumber)) throw new Error("Invalid port number");
169
-
170
- let { externalPort, cancel } = await hackDevtoolsWebsocketForward({ internalPort: portNumber, externalIP: forExternalIP });
171
- lastExposed?.();
172
- lastExposed = cancel;
173
- return { externalPort, internalPort: portNumber, internalInspectURL: debugURL };
174
- }
175
- }
176
- let lastExposed: (() => void) | undefined;
177
-
178
-
179
- let getFunctionRunnerShards = () => [] as DebugFunctionShardInfo[];
180
- export function set_debug_getFunctionRunnerShards(fnc: () => DebugFunctionShardInfo[]) {
181
- getFunctionRunnerShards = fnc;
182
- }
183
-
184
- export const NodeCapabilitiesController = SocketFunction.register(
185
- "NodeCapabilitiesController-399b7067-75c3-4d92-8be3-8470bde32d3c",
186
- new NodeCapabilitiesControllerBase(),
187
- () => ({
188
- getExposedControllers: {},
189
- getEntryPoint: {},
190
- getStartupTime: {},
191
- getMemoryUsage: {},
192
- getFunctionRunnerShards: {},
193
- getTrueTimeOffset: {},
194
- getInspectURL: { hooks: [requiresNetworkTrustHook] },
195
- exposeExternalDebugPortOnce: { hooks: [requiresNetworkTrustHook] },
196
- }),
197
- () => ({
198
- // I think assert is management user didn't exist when we wrote these functions, and so we just made them public. But now that it does exist, we might as well use it. Servers will count as management users anyway, and I don't see any reason a non-management user or a non-server needs to access any of these functions.
199
- hooks: [(require("../diagnostics/managementPages") as typeof import("../diagnostics/managementPages")).assertIsManagementUser],
200
- })
1
+ /*
2
+ Find nodes that implement a specific controller.
3
+ */
4
+
5
+ import { SocketFunction } from "socket-function/SocketFunction";
6
+ import { SocketRegistered } from "socket-function/SocketFunctionTypes";
7
+ import { errorToUndefined, errorToUndefinedSilent, timeoutToUndefinedSilent } from "../errors";
8
+ import { getAllNodeIds, isNodeIdOnOwnMachineId } from "../-f-node-discovery/NodeDiscovery";
9
+ import { green, red, yellow } from "socket-function/src/formatting/logColors";
10
+ import { shuffle } from "../misc/random";
11
+ import { delay } from "socket-function/src/batching";
12
+ import debugbreak from "debugbreak";
13
+ import { formatTime } from "socket-function/src/formatting/format";
14
+ import type { DebugFunctionShardInfo } from "../3-path-functions/PathFunctionRunner";
15
+ import { requiresNetworkTrustHook } from "../-d-trust/NetworkTrust2";
16
+ import { isNoNetwork } from "../config";
17
+ import { getDebuggerUrl } from "../diagnostics/listenOnDebugger";
18
+ import { hackDevtoolsWebsocketForward } from "./oneTimeForward";
19
+ import { getOwnMachineId, decodeNodeId, decodeNodeIdAssert, getMachineId } from "../-a-auth/certs";
20
+ import { sort } from "socket-function/src/misc";
21
+ import { getPathStr2 } from "../path";
22
+ import { PromiseObj } from "../promise";
23
+ import { getTrueTimeOffset } from "socket-function/time/trueTimeShim";
24
+ setImmediate(() => {
25
+ import("../diagnostics/MachineThreadInfo");
26
+ });
27
+
28
+ let controllerNodeIdCache = new Map<string, string | Promise<string | undefined>>();
29
+
30
+ // NOTE: If this becomes slow (because we are just trying all servers), we could start to store capabilities
31
+ // in PersistedStorage. However, I don't think it will be a problem for quite some time.
32
+ export async function getControllerNodeId(
33
+ controller: SocketRegistered<{}>,
34
+ quiet = false,
35
+ retryCount = 1,
36
+ initialTime = Date.now(),
37
+ ): Promise<string | undefined> {
38
+ let cached = controllerNodeIdCache.get(controller._classGuid);
39
+ if (cached && typeof cached !== "string") {
40
+ cached = await cached;
41
+ }
42
+ // TODO: We are relying on is node connected to do a lot of work here. If the node's connected, but somehow doesn't work, we can get in an unrecoverable state, even if there are plenty of other working nodes.
43
+ if (cached && !SocketFunction.isNodeConnected(cached)) {
44
+ controllerNodeIdCache.delete(controller._classGuid);
45
+ cached = undefined;
46
+ }
47
+ if (cached) return cached;
48
+ let promise = getInternal(retryCount);
49
+ controllerNodeIdCache.set(controller._classGuid, promise);
50
+ return promise;
51
+
52
+ async function getInternal(retryCount: number) {
53
+ let nodeIdsToTest = await getAllNodeIds();
54
+ // Shuffle, so we aren't always using the same node!
55
+ nodeIdsToTest = shuffle(nodeIdsToTest, Date.now());
56
+ let resolvedNode = new PromiseObj<string>();
57
+
58
+ if (!quiet) {
59
+ console.log(`Checking ${nodeIdsToTest.length} nodes for capability ${controller._classGuid}`);
60
+ }
61
+ let allFinished = Promise.all(nodeIdsToTest.map(async nodeId => {
62
+ if (await doesNodeExposeController(nodeId, controller)) {
63
+ if (!quiet) {
64
+ let duration = Date.now() - initialTime;
65
+ console.log(green(`Resolved capability ${controller._classGuid} with node ${nodeId}, in ${formatTime(duration)}`));
66
+ }
67
+ resolvedNode.resolve(nodeId);
68
+ }
69
+ }));
70
+ let result = await Promise.race([allFinished, resolvedNode.promise]);
71
+ if (typeof result === "string") {
72
+ return result;
73
+ }
74
+
75
+ if (retryCount > 0) {
76
+ if (!quiet) {
77
+ console.log(`Did not find capability in ${nodeIdsToTest.length} nodes, retrying... ${controller._classGuid}`);
78
+ }
79
+ await delay(2000);
80
+ return getInternal(retryCount - 1);
81
+ }
82
+ if (!quiet) {
83
+ console.warn(yellow(`Could not find a node that exposes controller ${controller._classGuid}, tried: ${JSON.stringify(nodeIdsToTest)}`));
84
+ }
85
+ return undefined;
86
+ }
87
+ }
88
+
89
+ export async function getControllerNodeIdList(
90
+ controller: SocketRegistered<{}>,
91
+ ): Promise<{ nodeId: string; entryPoint: string }[]> {
92
+ let nodeIdsToTest = await getAllNodeIds();
93
+ let passedNodeIds = new Map<string, { machineId: string; entryPoint: string }>();
94
+ await Promise.all(nodeIdsToTest.map(async nodeId => {
95
+ let result = await doesNodeExposeController(nodeId, controller);
96
+ if (result) {
97
+ let entryPoint = await NodeCapabilitiesController.nodes[nodeId].getEntryPoint();
98
+ passedNodeIds.set(nodeId, {
99
+ machineId: getMachineId(nodeId),
100
+ entryPoint,
101
+ });
102
+ }
103
+ }));
104
+
105
+ let results = Array.from(passedNodeIds.entries());
106
+ // Prefer localhost connections as they're faster.
107
+ sort(results, (x) => isNodeIdOnOwnMachineId(x[0]) ? 0 : 1);
108
+ let lookup = new Map<string, { nodeId: string; entryPoint: string }>();
109
+ for (let x of results) {
110
+ let key = getPathStr2(x[1].machineId, decodeNodeIdAssert(x[0]).port.toString());
111
+ if (key in lookup) continue;
112
+ lookup.set(key, { nodeId: x[0], entryPoint: x[1].entryPoint });
113
+ }
114
+
115
+ return Array.from(lookup.values());
116
+ }
117
+
118
+
119
+ export async function doesNodeExposeController(reconnectNodeId: string, controller: SocketRegistered<{}>): Promise<boolean> {
120
+ let exposedControllers = await timeoutToUndefinedSilent(10_000, NodeCapabilitiesController.nodes[reconnectNodeId].getExposedControllers());
121
+
122
+ if (exposedControllers?.includes(controller._classGuid)) {
123
+ return true;
124
+ }
125
+ return false;
126
+ }
127
+
128
+ const startupTime = Date.now();
129
+ class NodeCapabilitiesControllerBase {
130
+ public async getExposedControllers() {
131
+ return Array.from(SocketFunction.exposedClasses);
132
+ }
133
+ public async getEntryPoint() {
134
+ return process.argv[1];
135
+ }
136
+ public async getStartupTime() {
137
+ return startupTime;
138
+ }
139
+ public async getMemoryUsage() {
140
+ return process.memoryUsage();
141
+ }
142
+ public async getFunctionRunnerShards() {
143
+ return getFunctionRunnerShards();
144
+ }
145
+
146
+ public async getTrueTimeOffset() {
147
+ return getTrueTimeOffset();
148
+ }
149
+
150
+ public async getInspectURL() {
151
+ return await getDebuggerUrl();
152
+ }
153
+
154
+ public async exposeExternalDebugPortOnce(forExternalIP: string) {
155
+ // https://notdevtools.com/devtools/inspector.html?experiments=true&v8only=true&ws=127.0.0.1:62448/22895aed-f8da-4dfb-8d50-e432a9c2d827
156
+ let debugURL = await this.getInspectURL();
157
+
158
+ const outerUrl = new URL(debugURL);
159
+ const wsParam = outerUrl.searchParams.get("ws");
160
+ if (!wsParam) throw new Error("No ws parameter found");
161
+
162
+ // Add ws:// protocol to make it parseable by URL
163
+ const innerUrl = new URL(`ws://${wsParam}`);
164
+ const port = innerUrl.port;
165
+ if (!port) throw new Error("No port found");
166
+
167
+ const portNumber = parseInt(port, 10);
168
+ if (isNaN(portNumber)) throw new Error("Invalid port number");
169
+
170
+ let { externalPort, cancel } = await hackDevtoolsWebsocketForward({ internalPort: portNumber, externalIP: forExternalIP });
171
+ lastExposed?.();
172
+ lastExposed = cancel;
173
+ return { externalPort, internalPort: portNumber, internalInspectURL: debugURL };
174
+ }
175
+ }
176
+ let lastExposed: (() => void) | undefined;
177
+
178
+
179
+ let getFunctionRunnerShards = () => [] as DebugFunctionShardInfo[];
180
+ export function set_debug_getFunctionRunnerShards(fnc: () => DebugFunctionShardInfo[]) {
181
+ getFunctionRunnerShards = fnc;
182
+ }
183
+
184
+ export const NodeCapabilitiesController = SocketFunction.register(
185
+ "NodeCapabilitiesController-399b7067-75c3-4d92-8be3-8470bde32d3c",
186
+ new NodeCapabilitiesControllerBase(),
187
+ () => ({
188
+ getExposedControllers: {},
189
+ getEntryPoint: {},
190
+ getStartupTime: {},
191
+ getMemoryUsage: {},
192
+ getFunctionRunnerShards: {},
193
+ getTrueTimeOffset: {},
194
+ getInspectURL: { hooks: [requiresNetworkTrustHook] },
195
+ exposeExternalDebugPortOnce: { hooks: [requiresNetworkTrustHook] },
196
+ }),
197
+ () => ({
198
+ // I think assert is management user didn't exist when we wrote these functions, and so we just made them public. But now that it does exist, we might as well use it. Servers will count as management users anyway, and I don't see any reason a non-management user or a non-server needs to access any of these functions.
199
+ hooks: [(require("../diagnostics/managementPages") as typeof import("../diagnostics/managementPages")).assertIsManagementUser],
200
+ })
201
201
  );