querysub 0.126.0 → 0.127.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/package.json +1 -1
- package/src/3-path-functions/PathFunctionRunner.ts +39 -4
- package/src/3-path-functions/pathFunctionLoader.ts +0 -35
- package/src/4-deploy/deployMain.ts +23 -11
- package/src/4-deploy/deploySchema.ts +7 -1
- package/src/4-deploy/edgeNodes.ts +70 -19
- package/src/4-querysub/permissions.ts +0 -2
package/package.json
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { delay, runInfinitePoll } from "socket-function/src/batching";
|
|
2
2
|
import { cache } from "socket-function/src/caching";
|
|
3
|
-
import { magenta, red, yellow } from "socket-function/src/formatting/logColors";
|
|
3
|
+
import { blue, magenta, red, yellow } from "socket-function/src/formatting/logColors";
|
|
4
4
|
import { sha256HashBuffer, timeInHour } from "socket-function/src/misc";
|
|
5
5
|
import { measureFnc } from "socket-function/src/profiling/measure";
|
|
6
6
|
import { getLowUint32, getShortNumber } from "../bits";
|
|
7
7
|
import { registerDynamicResource } from "../diagnostics/trackResources";
|
|
8
|
-
import { logErrors } from "../errors";
|
|
8
|
+
import { errorToUndefined, logErrors } from "../errors";
|
|
9
9
|
import { getPathDepth, getPathFromStr, getPathIndex, trimPathStrToDepth } from "../path";
|
|
10
10
|
import { rawSchema } from "../2-proxy/pathDatabaseProxyBase";
|
|
11
11
|
import { ClientWatcher } from "../1-path-client/pathValueClientWatcher";
|
|
@@ -17,9 +17,11 @@ import debugbreak from "debugbreak";
|
|
|
17
17
|
import { parseArgs } from "./PathFunctionHelpers";
|
|
18
18
|
import { PERMISSIONS_FUNCTION_ID, getExportPath } from "./syncSchema";
|
|
19
19
|
import { formatTime } from "socket-function/src/formatting/format";
|
|
20
|
-
import { set_debug_getFunctionRunnerShards } from "../-g-core-values/NodeCapabilities";
|
|
20
|
+
import { getControllerNodeIdList, set_debug_getFunctionRunnerShards } from "../-g-core-values/NodeCapabilities";
|
|
21
21
|
import { diskLog } from "../diagnostics/logs/diskLogger";
|
|
22
22
|
import { FilterSelector, Filterable, doesMatch } from "../misc/filterable";
|
|
23
|
+
import { SocketFunction } from "socket-function/SocketFunction";
|
|
24
|
+
import { requiresNetworkTrustHook } from "../-d-trust/NetworkTrust2";
|
|
23
25
|
|
|
24
26
|
export const functionSchema = rawSchema<{
|
|
25
27
|
[domainName: string]: {
|
|
@@ -176,6 +178,7 @@ export class PathFunctionRunner {
|
|
|
176
178
|
PermissionsChecker: PermissionsCheckType | undefined;
|
|
177
179
|
filterSelector?: FilterSelector;
|
|
178
180
|
}) {
|
|
181
|
+
SocketFunction.expose(FunctionPreloadController);
|
|
179
182
|
debugFunctionRunnerShards.push({
|
|
180
183
|
domainName: config.domainName,
|
|
181
184
|
shardRange: config.shardRange,
|
|
@@ -655,4 +658,36 @@ export class PathFunctionRunner {
|
|
|
655
658
|
});
|
|
656
659
|
PathFunctionRunner.RUN_FINISH_COUNT++;
|
|
657
660
|
}
|
|
658
|
-
}
|
|
661
|
+
}
|
|
662
|
+
|
|
663
|
+
export async function preloadFunctions(specs: FunctionSpec[]) {
|
|
664
|
+
let nodeIds = await getControllerNodeIdList(FunctionPreloadController);
|
|
665
|
+
await Promise.allSettled(nodeIds.map(async nodeId => {
|
|
666
|
+
let controller = FunctionPreloadController.nodes[nodeId.nodeId];
|
|
667
|
+
console.log(blue(`Preloading functions on ${nodeId}`));
|
|
668
|
+
await errorToUndefined(controller.preloadFunctions(specs));
|
|
669
|
+
console.log(blue(`Finished preloading functions on ${nodeId}`));
|
|
670
|
+
}));
|
|
671
|
+
}
|
|
672
|
+
|
|
673
|
+
class FunctionPreloaderBase {
|
|
674
|
+
async preloadFunctions(specs: FunctionSpec[]) {
|
|
675
|
+
for (let spec of specs) {
|
|
676
|
+
await getModuleFromSpec(spec);
|
|
677
|
+
}
|
|
678
|
+
}
|
|
679
|
+
}
|
|
680
|
+
|
|
681
|
+
const FunctionPreloadController = SocketFunction.register(
|
|
682
|
+
"FunctionPreloader-c966a1a6-5d3f-4453-bd03-ae84b574ec00",
|
|
683
|
+
new FunctionPreloaderBase(),
|
|
684
|
+
() => ({
|
|
685
|
+
preloadFunctions: {},
|
|
686
|
+
}),
|
|
687
|
+
() => ({
|
|
688
|
+
hooks: [requiresNetworkTrustHook],
|
|
689
|
+
}),
|
|
690
|
+
{
|
|
691
|
+
noAutoExpose: true,
|
|
692
|
+
}
|
|
693
|
+
);
|
|
@@ -263,7 +263,6 @@ function getCallstackFiles(): string[] {
|
|
|
263
263
|
async function getModuleFromSpecBase(
|
|
264
264
|
spec: LoadFunctionSpec
|
|
265
265
|
): Promise<NodeJS.Module> {
|
|
266
|
-
everLoadedRepos.add(spec.gitURL);
|
|
267
266
|
let hotReloadPackagePath = "";
|
|
268
267
|
let path = gitURLRefMappings.get(getSpecKey(spec));
|
|
269
268
|
let deployPath = "";
|
|
@@ -459,37 +458,3 @@ async function executeCommand(command: string, args: string[], options?: {
|
|
|
459
458
|
});
|
|
460
459
|
});
|
|
461
460
|
}
|
|
462
|
-
|
|
463
|
-
// Helps us exclude non-function loaders (PathValueServer), which really shouldn't
|
|
464
|
-
// be loading code anyways!
|
|
465
|
-
let everLoadedRepos = new Set<string>();
|
|
466
|
-
|
|
467
|
-
export async function preloadFunctions(specs: FunctionSpec[]) {
|
|
468
|
-
let nodeIds = await getControllerNodeIdList(functionPreloadController);
|
|
469
|
-
await Promise.all(nodeIds.map(async nodeId => {
|
|
470
|
-
let controller = functionPreloadController.nodes[nodeId.nodeId];
|
|
471
|
-
console.log(blue(`Preloading functions on ${nodeId}`));
|
|
472
|
-
await errorToUndefined(controller.preloadFunctions(specs));
|
|
473
|
-
console.log(blue(`Finished preloading functions on ${nodeId}`));
|
|
474
|
-
}));
|
|
475
|
-
}
|
|
476
|
-
|
|
477
|
-
class FunctionPreloaderBase {
|
|
478
|
-
async preloadFunctions(specs: FunctionSpec[]) {
|
|
479
|
-
specs = specs.filter(spec => everLoadedRepos.has(spec.gitURL));
|
|
480
|
-
for (let spec of specs) {
|
|
481
|
-
await getModuleFromSpec(spec);
|
|
482
|
-
}
|
|
483
|
-
}
|
|
484
|
-
}
|
|
485
|
-
|
|
486
|
-
const functionPreloadController = SocketFunction.register(
|
|
487
|
-
"FunctionPreloader-c966a1a6-5d3f-4453-bd03-ae84b574ec00",
|
|
488
|
-
new FunctionPreloaderBase(),
|
|
489
|
-
() => ({
|
|
490
|
-
preloadFunctions: {},
|
|
491
|
-
}),
|
|
492
|
-
() => ({
|
|
493
|
-
hooks: [requiresNetworkTrustHook],
|
|
494
|
-
})
|
|
495
|
-
);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import "../inject";
|
|
2
2
|
|
|
3
|
-
import { FunctionSpec } from "../3-path-functions/PathFunctionRunner";
|
|
3
|
+
import { FunctionSpec, preloadFunctions } from "../3-path-functions/PathFunctionRunner";
|
|
4
4
|
import path from "path";
|
|
5
5
|
import { getExportPath, getSchemaObject, PERMISSIONS_FUNCTION_ID } from "../3-path-functions/syncSchema";
|
|
6
6
|
import { getModuleRelativePath } from "../3-path-functions/syncSchema";
|
|
@@ -15,17 +15,20 @@ import yargs from "yargs";
|
|
|
15
15
|
import { isPublic } from "../config";
|
|
16
16
|
import { deployBlock } from "./deployBlock";
|
|
17
17
|
import { LOCAL_DOMAIN } from "../0-path-value-core/PathController";
|
|
18
|
-
import { preloadFunctions } from "../3-path-functions/pathFunctionLoader";
|
|
19
18
|
import { magenta } from "socket-function/src/formatting/logColors";
|
|
20
19
|
import { getGitRef } from "./git";
|
|
21
20
|
import { getGitURL } from "./git";
|
|
22
21
|
import { setLiveDeployedHash } from "./deploySchema";
|
|
23
22
|
import { proxyWatcher } from "../2-proxy/PathValueProxyWatcher";
|
|
23
|
+
import debugbreak from "debugbreak";
|
|
24
|
+
import { timeInHour } from "socket-function/src/misc";
|
|
25
|
+
import { preloadUI } from "./edgeNodes";
|
|
24
26
|
|
|
25
|
-
//todonext;
|
|
26
|
-
// - deployonlycode / deployonlyui / deploynotifyforced
|
|
27
27
|
let yargObj = yargs(process.argv)
|
|
28
28
|
.option("domain", { type: "string", required: true, desc: "Domain to deploy to" })
|
|
29
|
+
.option("deployonlycode", { type: "boolean", desc: "Only deploy code, not ui" })
|
|
30
|
+
.option("deployonlyui", { type: "boolean", desc: "Only deploy ui, not code" })
|
|
31
|
+
.option("notifyrefreshdelay", { type: "number", default: timeInHour * 12, desc: "The time clients have to refresh their UI after a deploy." })
|
|
29
32
|
.argv
|
|
30
33
|
;
|
|
31
34
|
|
|
@@ -116,26 +119,35 @@ export async function deployMain() {
|
|
|
116
119
|
|
|
117
120
|
console.log();
|
|
118
121
|
console.log();
|
|
119
|
-
console.log(magenta(`Preloading ${currentFunctions.length} functions`));
|
|
120
|
-
await
|
|
122
|
+
console.log(magenta(`Preloading ${currentFunctions.length} functions & UI`));
|
|
123
|
+
await Promise.all([
|
|
124
|
+
preloadFunctions(currentFunctions),
|
|
125
|
+
preloadUI(gitRef),
|
|
126
|
+
]);
|
|
121
127
|
|
|
122
128
|
console.log();
|
|
123
129
|
console.log();
|
|
124
130
|
console.log(magenta(`Deploying ${currentFunctions.length} functions`));
|
|
125
131
|
|
|
132
|
+
let refreshThresholdTime = Date.now() + yargObj.notifyrefreshdelay;
|
|
133
|
+
|
|
134
|
+
debugbreak(2);
|
|
135
|
+
debugger;
|
|
126
136
|
//todonext;
|
|
127
|
-
//
|
|
137
|
+
// VERIFY that the nested commit functions run correctly WITH the correct (atomic) flags
|
|
128
138
|
await proxyWatcher.commitFunction({
|
|
129
139
|
debugName: "setLiveDeployedHash",
|
|
130
140
|
inlineNestedWatchers: true,
|
|
131
141
|
watchFunction: () => {
|
|
132
|
-
|
|
133
|
-
|
|
142
|
+
if (!yargObj.deployonlycode) {
|
|
143
|
+
void setLiveDeployedHash({ hash: gitRef, refreshThresholdTime, });
|
|
144
|
+
}
|
|
145
|
+
if (!yargObj.deployonlyui) {
|
|
146
|
+
void replaceFunctions({ domainName, functions: currentFunctions, });
|
|
147
|
+
}
|
|
134
148
|
},
|
|
135
149
|
});
|
|
136
150
|
|
|
137
|
-
await replaceFunctions({ domainName, functions: currentFunctions, });
|
|
138
|
-
|
|
139
151
|
console.log(magenta(`FINISHED DEPLOY`));
|
|
140
152
|
}
|
|
141
153
|
|
|
@@ -20,15 +20,21 @@ export const deploySchema = rawSchema<{
|
|
|
20
20
|
export interface DeployedHash {
|
|
21
21
|
hash: string;
|
|
22
22
|
time: number;
|
|
23
|
+
refreshThresholdTime: number;
|
|
23
24
|
}
|
|
24
25
|
|
|
25
26
|
|
|
26
|
-
export function setLiveDeployedHash(
|
|
27
|
+
export function setLiveDeployedHash(config: {
|
|
28
|
+
hash: string;
|
|
29
|
+
refreshThresholdTime: number;
|
|
30
|
+
}) {
|
|
31
|
+
const { hash, refreshThresholdTime } = config;
|
|
27
32
|
proxyWatcher.writeOnly({
|
|
28
33
|
watchFunction: function writeCall() {
|
|
29
34
|
let hashObj: DeployedHash = {
|
|
30
35
|
hash,
|
|
31
36
|
time: Date.now(),
|
|
37
|
+
refreshThresholdTime,
|
|
32
38
|
};
|
|
33
39
|
deploySchema()[getDomain()].deploy.live = hashObj;
|
|
34
40
|
deploySchema()[getDomain()].deploy.history[nextId()] = hashObj;
|
|
@@ -16,6 +16,10 @@ import { getGitRef, getGitURL } from "./git";
|
|
|
16
16
|
import { getModuleFromConfig } from "../3-path-functions/pathFunctionLoader";
|
|
17
17
|
import path from "path";
|
|
18
18
|
import debugbreak from "debugbreak";
|
|
19
|
+
import { requiresNetworkTrustHook } from "../-d-trust/NetworkTrust2";
|
|
20
|
+
import { getControllerNodeIdList } from "../-g-core-values/NodeCapabilities";
|
|
21
|
+
import { blue } from "socket-function/src/formatting/logColors";
|
|
22
|
+
import { errorToUndefined } from "../errors";
|
|
19
23
|
|
|
20
24
|
const UPDATE_POLL_INTERVAL = timeInMinute;
|
|
21
25
|
const DEAD_NODE_COUNT_THRESHOLD = 15;
|
|
@@ -51,6 +55,7 @@ export type EdgeNodesIndex = {
|
|
|
51
55
|
edgeNodes: EdgeNodeConfig[];
|
|
52
56
|
};
|
|
53
57
|
|
|
58
|
+
|
|
54
59
|
// IMPORTANT! The EdgeNodeConfig MUST be immutable, otherwise every node has to read every EdgeNodeConfig
|
|
55
60
|
// every poll, which is too much reading.
|
|
56
61
|
export type EdgeNodeConfig = {
|
|
@@ -127,24 +132,6 @@ async function loadEntryPointsByHash(config: {
|
|
|
127
132
|
FunctionId: "entryPoint",
|
|
128
133
|
});
|
|
129
134
|
|
|
130
|
-
//todonext;
|
|
131
|
-
// 3) Setup the deployMain code to set the live hash
|
|
132
|
-
// - Flags to decide what to set
|
|
133
|
-
// - Inside of replaceFunctions, via passing a callback function to it. The nested commits SHOULD
|
|
134
|
-
// just work?
|
|
135
|
-
// - IMPORTANT! Step through the code, to ensure the nested flags are set correctly. If not...
|
|
136
|
-
// update the proxy watcher to set them properly...
|
|
137
|
-
// - With all the flags (that only do one or the other)
|
|
138
|
-
// - Add preloading capability, so we can preload the hashes before we deploy
|
|
139
|
-
// 3) Dynamically watch the live hash, and load new hashes (deploying their services)
|
|
140
|
-
// - Test by pushing, deploying, and refreshing (we should prefer to latest service)
|
|
141
|
-
// 3.1) If local, DO NOT watch the live hash
|
|
142
|
-
// 5) Write the live hash to public backblaze, and have the client read it, and prefer that hash
|
|
143
|
-
// 6) Pass the live hash to the client with the edge node
|
|
144
|
-
// 7) Client live hash watch code + notify + refresh + flag to ignore the baked in live hash + edge node
|
|
145
|
-
// - Test by pushing, deploying, and then we should immediately see a notify to refresh
|
|
146
|
-
|
|
147
|
-
|
|
148
135
|
let depth = entryPaths[0].replaceAll("\\", "/").split("/").filter(x => x && x !== ".").length;
|
|
149
136
|
|
|
150
137
|
let firstPath = path.resolve(module.filename);
|
|
@@ -167,6 +154,8 @@ async function loadEntryPointsByHash(config: {
|
|
|
167
154
|
registeredEdgeNode = edgeNodeConfig;
|
|
168
155
|
|
|
169
156
|
await edgeNodeStorage.set(getNextNodePath(), Buffer.from(JSON.stringify(edgeNodeConfig)));
|
|
157
|
+
|
|
158
|
+
SocketFunction.expose(EdgeNodeController);
|
|
170
159
|
}
|
|
171
160
|
|
|
172
161
|
export const getEdgeNodeConfigURL = lazy(async () => {
|
|
@@ -244,6 +233,46 @@ async function updateEdgeNodesFile() {
|
|
|
244
233
|
await edgeNodeStorage.set("edge-nodes-index.json", Buffer.from(JSON.stringify(newEdgeNodeIndex)));
|
|
245
234
|
}
|
|
246
235
|
|
|
236
|
+
export async function preloadUI(hash: string) {
|
|
237
|
+
let nodeIds = await getControllerNodeIdList(EdgeNodeController);
|
|
238
|
+
await Promise.allSettled(nodeIds.map(async nodeId => {
|
|
239
|
+
let controller = EdgeNodeController.nodes[nodeId.nodeId];
|
|
240
|
+
console.log(blue(`Preloading functions on ${nodeId}`));
|
|
241
|
+
await errorToUndefined(controller.preloadUI({ hash }));
|
|
242
|
+
console.log(blue(`Finished preloading functions on ${nodeId}`));
|
|
243
|
+
}));
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
class EdgeNodeControllerBase {
|
|
247
|
+
public async preloadUI(config: {
|
|
248
|
+
hash: string;
|
|
249
|
+
}) {
|
|
250
|
+
const { hash } = config;
|
|
251
|
+
if (!registeredEdgeNode || !canHaveChildren(registeredEdgeNode)) {
|
|
252
|
+
throw new Error(`Somehow we have no registered edge node. How did we even expose this controller?`);
|
|
253
|
+
}
|
|
254
|
+
await loadEntryPointsByHash({
|
|
255
|
+
host: registeredEdgeNode.host,
|
|
256
|
+
entryPaths: registeredEdgeNode.entryPaths,
|
|
257
|
+
hash,
|
|
258
|
+
});
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
const EdgeNodeController = SocketFunction.register(
|
|
263
|
+
"EdgeNodeController-e0110af9-f8c4-42f3-ad11-633f8e43abdd",
|
|
264
|
+
new EdgeNodeControllerBase(),
|
|
265
|
+
() => ({
|
|
266
|
+
preloadUI: {},
|
|
267
|
+
}),
|
|
268
|
+
() => ({
|
|
269
|
+
hooks: [requiresNetworkTrustHook],
|
|
270
|
+
}),
|
|
271
|
+
{
|
|
272
|
+
noAutoExpose: true,
|
|
273
|
+
}
|
|
274
|
+
);
|
|
275
|
+
|
|
247
276
|
// async function main() {
|
|
248
277
|
// await loadEntryPointsByHash({
|
|
249
278
|
// host: "127-0-0-1.querysub.com:1111",
|
|
@@ -251,4 +280,26 @@ async function updateEdgeNodesFile() {
|
|
|
251
280
|
// hash: "7b1eb4934d5bdfe6d0f7076049c4b7decad4e645",
|
|
252
281
|
// });
|
|
253
282
|
// }
|
|
254
|
-
// main().catch(console.error).finally(() => process.exit());
|
|
283
|
+
// main().catch(console.error).finally(() => process.exit());
|
|
284
|
+
|
|
285
|
+
|
|
286
|
+
|
|
287
|
+
//todonext;
|
|
288
|
+
// 3) Setup the deployMain code to set the live hash
|
|
289
|
+
// - Flags to decide what to set
|
|
290
|
+
// - Inside of replaceFunctions, via passing a callback function to it. The nested commits SHOULD
|
|
291
|
+
// just work?
|
|
292
|
+
// - IMPORTANT! Step through the code, to ensure the nested flags are set correctly. If not...
|
|
293
|
+
// update the proxy watcher to set them properly...
|
|
294
|
+
// - With all the flags (that only do one or the other)
|
|
295
|
+
// - Add preloading capability, so we can preload the hashes before we deploy
|
|
296
|
+
|
|
297
|
+
// 3) Dynamically watch the live hash, and load new hashes (deploying their services)
|
|
298
|
+
// - Test by pushing, deploying, and refreshing (we should prefer to latest service)
|
|
299
|
+
// 3.1) If local, DO NOT watch the live hash
|
|
300
|
+
|
|
301
|
+
// 5) Write the live hash to public backblaze, and have the client read it, and prefer that hash
|
|
302
|
+
// 6) Pass the live hash to the client with the edge node
|
|
303
|
+
// 7) Client live hash watch code + notify + refresh + flag to ignore the baked in live hash + edge node
|
|
304
|
+
// - Test by pushing, deploying, and then we should immediately see a notify to refresh
|
|
305
|
+
// 8) VERIFY writing and permissions stillw orks
|
|
@@ -90,8 +90,6 @@ export class PermissionsCheck {
|
|
|
90
90
|
}>();
|
|
91
91
|
// IMPORTANT! This function USED TO BE a major hotspot for function evaluation, and so is heavily optimized.
|
|
92
92
|
public checkPermissions(path: string): { permissionsPath: string; allowed: boolean; } {
|
|
93
|
-
//todonext
|
|
94
|
-
//return { permissionsPath: path, allowed: true };
|
|
95
93
|
if (this.dead) throw new Error("PermissionsCheck MUST be used synchronously, after which it cannot be reused");
|
|
96
94
|
if (PermissionsCheck.skippingChecks) return { permissionsPath: rootPathStr, allowed: true };
|
|
97
95
|
|