querysub 0.472.0 → 0.474.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 +2 -2
- package/src/-a-archives/archivesBackBlaze.ts +13 -8
- package/src/-c-identity/IdentityController.ts +3 -2
- package/src/-f-node-discovery/NodeDiscovery.ts +31 -12
- package/src/1-path-client/RemoteWatcher.ts +1 -1
- package/src/2-proxy/PathValueProxyWatcher.ts +1 -1
- package/src/4-querysub/Querysub.ts +1 -1
- package/src/4-querysub/querysubPrediction.ts +1 -0
- package/src/config.ts +7 -0
- package/src/user-implementation/UserPage.tsx +1 -1
- package/src/user-implementation/userData.ts +2 -3
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "querysub",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.474.0",
|
|
4
4
|
"main": "index.js",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"note1": "note on node-forge fork, see https://github.com/digitalbazaar/forge/issues/744 for details",
|
|
@@ -66,7 +66,7 @@
|
|
|
66
66
|
"node-forge": "https://github.com/sliftist/forge#e618181b469b07bdc70b968b0391beb8ef5fecd6",
|
|
67
67
|
"pako": "^2.1.0",
|
|
68
68
|
"peggy": "^5.0.6",
|
|
69
|
-
"socket-function": "^1.1.
|
|
69
|
+
"socket-function": "^1.1.36",
|
|
70
70
|
"terser": "^5.31.0",
|
|
71
71
|
"typesafecss": "^0.29.0",
|
|
72
72
|
"yaml": "^2.5.0",
|
|
@@ -505,6 +505,8 @@ export class ArchivesBackblaze {
|
|
|
505
505
|
return api;
|
|
506
506
|
});
|
|
507
507
|
|
|
508
|
+
private currentReset: Promise<void> | undefined;
|
|
509
|
+
|
|
508
510
|
// Keep track of when we last reset because of a 503
|
|
509
511
|
private last503Reset = 0;
|
|
510
512
|
// IMPORTANT! We must always CATCH AROUND the apiRetryLogic, NEVER inside of fnc. Otherwise we won't
|
|
@@ -532,14 +534,17 @@ export class ArchivesBackblaze {
|
|
|
532
534
|
) && Date.now() - this.last503Reset > 60 * 1000) {
|
|
533
535
|
console.error(`[${context}] 503 error, waiting and resetting: ${err.message}`);
|
|
534
536
|
this.log(`[${context}] 503 error, waiting and resetting: ${err.message}`);
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
537
|
+
this.currentReset = this.currentReset || (async () => {
|
|
538
|
+
await delay(10 * 1000);
|
|
539
|
+
// We check again in case, and in the very likely case that this is being run in parallel, we only want to reset once.
|
|
540
|
+
if (Date.now() - this.last503Reset > 60 * 1000) {
|
|
541
|
+
this.log(`[${context}] Resetting getAPI and getBucketAPI: ${err.message}`);
|
|
542
|
+
this.last503Reset = Date.now();
|
|
543
|
+
getAPI.reset();
|
|
544
|
+
this.getBucketAPI.reset();
|
|
545
|
+
}
|
|
546
|
+
})().finally(() => this.currentReset = undefined);
|
|
547
|
+
await this.currentReset;
|
|
543
548
|
return this.apiRetryLogic(context, fnc, retries - 1);
|
|
544
549
|
}
|
|
545
550
|
|
|
@@ -20,6 +20,7 @@ import { red } from "socket-function/src/formatting/logColors";
|
|
|
20
20
|
import { isNode } from "typesafecss";
|
|
21
21
|
import { areNodeIdsEqual, getOwnNodeId, getOwnThreadId } from "../-f-node-discovery/NodeDiscovery";
|
|
22
22
|
import { timeInMinute } from "socket-function/src/misc";
|
|
23
|
+
import { isClient, isServer } from "../config2";
|
|
23
24
|
|
|
24
25
|
// NOTE: This used to be small, but we cache this, so it would mean a node on startup would time out, and then we would refuse to talk to it ever again. So... this can't be small
|
|
25
26
|
const MAX_CHANGE_IDENTITY_TIMEOUT = timeInMinute * 5;
|
|
@@ -239,8 +240,8 @@ const changeIdentityOnce = cacheWeak(async function changeIdentityOnce(connectio
|
|
|
239
240
|
cert: threadKeyCert.cert.toString(),
|
|
240
241
|
certIssuer: issuer.cert.toString(),
|
|
241
242
|
mountedPort: getNodeIdLocation(SocketFunction.mountedNodeId)?.port,
|
|
242
|
-
debugEntryPoint:
|
|
243
|
-
clientIsNode:
|
|
243
|
+
debugEntryPoint: isServer() ? process.argv[1] : "browser",
|
|
244
|
+
clientIsNode: isServer(),
|
|
244
245
|
};
|
|
245
246
|
let signature = sign(threadKeyCert, payload);
|
|
246
247
|
await timeoutToError(
|
|
@@ -229,6 +229,7 @@ function onNodesChanged() {
|
|
|
229
229
|
}
|
|
230
230
|
|
|
231
231
|
let rootDiscoveryNodeId = "";
|
|
232
|
+
/** IMPORTANT! This domain import is the querysub server. Usually this is going to be a local development server. However, you can use Node Discovery and use whatever Node you want. You don't need to know the node's machine ID. You just need to know its address. */
|
|
232
233
|
export function configRootDiscoveryLocation(config: {
|
|
233
234
|
domain: string;
|
|
234
235
|
port: number;
|
|
@@ -337,11 +338,13 @@ async function syncArchives() {
|
|
|
337
338
|
console.info(`Synced node ids from archives`, { nodeIds });
|
|
338
339
|
await setNodeIds(nodeIds);
|
|
339
340
|
} else {
|
|
340
|
-
if (isNoNetwork() || !isNode()) {
|
|
341
|
+
if (isNoNetwork() || !isNode() || rootDiscoveryNodeId) {
|
|
341
342
|
// NOTE: If no network, our trust source might be different, so we can't talk to regular nodes,
|
|
342
343
|
// and instead have to only talk to HTTP nodes
|
|
343
344
|
await setNodeIds([getBrowserUrlNode()]);
|
|
344
345
|
} else {
|
|
346
|
+
// NOTE: I don't think this pathway works. But in theory it should it should be possible for us in nodejs to automatically choose the server we want to talk to. In practice, it probably doesn't matter right now, as we're mostly just using this for development, in which case we want to force it to use the local server anyway, which will set root discovery node ID.
|
|
347
|
+
|
|
345
348
|
// If on the network, NetworkTrust2 should sync the trusted machines from backblaze, so we should be
|
|
346
349
|
// able to talk to any nodes.
|
|
347
350
|
// - If they user is using --client they only want to talk to querysub nodes. There might be multiple,
|
|
@@ -575,17 +578,33 @@ if (isServer()) {
|
|
|
575
578
|
} else {
|
|
576
579
|
|
|
577
580
|
if (isNode()) {
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
581
|
+
if (rootDiscoveryNodeId) {
|
|
582
|
+
let nodes = [rootDiscoveryNodeId];
|
|
583
|
+
allNodeIds2 = new Set(nodes);
|
|
584
|
+
discoveryReady.resolve();
|
|
585
|
+
nodeBroadcasted.resolve();
|
|
586
|
+
|
|
587
|
+
// NOTE: We run into TLS issues (as in, our servers use self signed certs), if we try to talk to just
|
|
588
|
+
// any node, so... we better just talk to the edge node
|
|
589
|
+
// - We COULD probably just use some special domain (maybe JUST the machine domain?), with limited wildcard
|
|
590
|
+
// certs (I think we can only wildcard a single depth anyways), and A records for the machines too...
|
|
591
|
+
// but... having all traffic route through an edge node is probably better anyways...
|
|
592
|
+
nodeOverrides = nodes;
|
|
593
|
+
|
|
594
|
+
} else {
|
|
595
|
+
// NOTE: I don't think this pathway works. But in theory it should it should be possible for us in nodejs to automatically choose the server we want to talk to. In practice, it probably doesn't matter right now, as we're mostly just using this for development, in which case we want to force it to use the local server anyway, which will set root discovery node ID.
|
|
596
|
+
discoveryReady.resolve();
|
|
597
|
+
nodeBroadcasted.resolve();
|
|
598
|
+
// Just get the archives, syncing again if we haven't synced in a while
|
|
599
|
+
let lastGetTime = 0;
|
|
600
|
+
beforeGetNodeAllId = async () => {
|
|
601
|
+
let lastGetThreshold = lastGetTime + CLIENTSIDE_POLL_RATE;
|
|
602
|
+
if (Date.now() > lastGetThreshold) {
|
|
603
|
+
lastGetTime = Date.now();
|
|
604
|
+
await syncArchives();
|
|
605
|
+
}
|
|
606
|
+
};
|
|
607
|
+
}
|
|
589
608
|
} else {
|
|
590
609
|
setImmediate(() => {
|
|
591
610
|
let edgeNode = getBootedEdgeNode();
|
|
@@ -111,7 +111,7 @@ export class RemoteWatcher {
|
|
|
111
111
|
// NOTE: We keep around the old authorities in routing (for a few minutes), so if a new node doesn't start,
|
|
112
112
|
// we will match the disconnected node again. This means we have a few minutes to start another server.
|
|
113
113
|
// TODO: Retry instead of throwing
|
|
114
|
-
console.log(yellow(`Trying to find new authority for disconnected watches ${paths.length} paths and ${parentPaths.length} parent paths`));
|
|
114
|
+
console.log(yellow(`Trying to find new authority for disconnected watches ${paths.length} paths and ${parentPaths.length} parent paths`), { authorityId });
|
|
115
115
|
logErrors(this.tryToReconnectNow());
|
|
116
116
|
})());
|
|
117
117
|
// Reconnection is our loop running again, maybe matching the same nodeId, and then using it again.
|
|
@@ -1664,7 +1664,7 @@ export class PathValueProxyWatcher {
|
|
|
1664
1664
|
|
|
1665
1665
|
let maxLocks = watcher.options.maxLocksOverride || DEFAULT_MAX_LOCKS;
|
|
1666
1666
|
if (locks.length > maxLocks) {
|
|
1667
|
-
throw new Error(`Too many locks for ${watcher.debugName} (${locks.length} > ${maxLocks}). Use Querysub.noLocks(() => ...) around code that is accessing too many values, assuming you don't want to lock them. You can override max locks with maxLocksOverride (in options / functionMetadata). Some locks are ${JSON.stringify(locks.slice(-10).map(x => ({ path: x.path, startTime: x.startTime, endTime: x.endTime })))}.`);
|
|
1667
|
+
throw new Error(`Too many locks for ${watcher.debugName} (${locks.length} > ${maxLocks}). Use Querysub.noLocks(() => ...) around code that is accessing too many values, assuming you don't want to lock them. You can override max locks with maxLocksOverride (in options / functionMetadata). Some write keys (which will be lost) are: ${JSON.stringify(Array.from(watcher.pendingWrites.keys()).slice(-10))}. Some locks are ${JSON.stringify(locks.slice(-10).map(x => ({ path: x.path, startTime: x.startTime, endTime: x.endTime })))}.`);
|
|
1668
1668
|
}
|
|
1669
1669
|
|
|
1670
1670
|
|
|
@@ -1053,7 +1053,7 @@ export class Querysub {
|
|
|
1053
1053
|
|
|
1054
1054
|
public static async hostService(name: string, port = 0) {
|
|
1055
1055
|
if (isClient()) {
|
|
1056
|
-
throw new Error(`--client processes cannot host a service. Either stop passing --client and keep the process on the network and trusted, or stop calling hostServer and call Querysub.configRootDiscoveryLocation instead
|
|
1056
|
+
throw new Error(`--client processes cannot host a service. Either stop passing --client and keep the process on the network and trusted, or stop calling hostServer and call Querysub.configRootDiscoveryLocation instead. You MUST provide configRootDiscoveryLocation a valid nodeId. Which means either you do server selection manually, or if you are developing, just point it to "127-0-0-1.${getDomain()}:your local port here"`);
|
|
1057
1057
|
}
|
|
1058
1058
|
let times: {
|
|
1059
1059
|
name: string;
|
|
@@ -403,6 +403,7 @@ function getFunctionSpec(call: CallSpec): FunctionSpec | undefined {
|
|
|
403
403
|
ModuleId: call.ModuleId,
|
|
404
404
|
FunctionId: call.FunctionId,
|
|
405
405
|
});
|
|
406
|
+
if (!obj && !Querysub.isAllSynced()) return undefined;
|
|
406
407
|
if (!obj) throw new Error(`Function not referenced in deploy.ts ${call.DomainName}.${call.ModuleId}.${call.FunctionId}`);
|
|
407
408
|
setGitURLMapping({ spec: obj.functionSpec, resolvedPath: obj.modulePath });
|
|
408
409
|
return obj.functionSpec;
|
package/src/config.ts
CHANGED
|
@@ -5,6 +5,7 @@ import { MaybePromise } from "socket-function/src/types";
|
|
|
5
5
|
import { parseArgsFactory } from "./misc/rawParams";
|
|
6
6
|
import { lazy } from "socket-function/src/caching";
|
|
7
7
|
import fs from "fs";
|
|
8
|
+
import { SocketFunction } from "socket-function/SocketFunction";
|
|
8
9
|
|
|
9
10
|
export const serverPort = 11748;
|
|
10
11
|
|
|
@@ -35,6 +36,12 @@ let yargObj = parseArgsFactory()
|
|
|
35
36
|
.argv
|
|
36
37
|
;
|
|
37
38
|
|
|
39
|
+
if (isNode()) {
|
|
40
|
+
if (yargObj.client) {
|
|
41
|
+
SocketFunction.ENABLE_CLIENT_MODE = true;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
38
45
|
export function getRawFncFilter() {
|
|
39
46
|
return yargObj.fncfilter;
|
|
40
47
|
}
|
|
@@ -70,7 +70,7 @@ export class UserPage extends qreact.Component {
|
|
|
70
70
|
`}
|
|
71
71
|
</style>
|
|
72
72
|
<div class={css.vbox(20)}>
|
|
73
|
-
<div class={css.fontSize(28)}>User Configuration {
|
|
73
|
+
<div class={css.fontSize(28)}>User Configuration {<span>({userId})</span>}</div>
|
|
74
74
|
{userObj.userId !== userId && <div class={css.fontSize(16)}>(Used does not exist)</div>}
|
|
75
75
|
<div class={css.vbox(4)}>
|
|
76
76
|
<div><b>Email</b> {userObj.email}</div>
|
|
@@ -532,7 +532,7 @@ export function getCurrentUser(config?: { ignoreImpersonate?: boolean; }): strin
|
|
|
532
532
|
let impersonate = !config?.ignoreImpersonate && impersonateURL.value;
|
|
533
533
|
if (impersonate) return impersonate;
|
|
534
534
|
}
|
|
535
|
-
if (isNode() && Querysub.
|
|
535
|
+
if (isNode() && Querysub.getCallerIPAllowUndefined() === "127.0.0.1" && isRecovery()) {
|
|
536
536
|
return "local";
|
|
537
537
|
}
|
|
538
538
|
const machineId = Querysub.getCallerMachineId();
|
|
@@ -1121,13 +1121,12 @@ function unbanUser(config: { userId: string }) {
|
|
|
1121
1121
|
}
|
|
1122
1122
|
|
|
1123
1123
|
/** Adds the current machine to the shared "service" account, which otherwise is impossible to login as. */
|
|
1124
|
-
export async function
|
|
1124
|
+
export async function nodeJSLoginToUser(userId: string) {
|
|
1125
1125
|
const machineId = Querysub.getOwnMachineId();
|
|
1126
1126
|
const ips = [await getExternalIP(), "127.0.0.1", "10.0.0.1"];
|
|
1127
1127
|
let now = Date.now();
|
|
1128
1128
|
|
|
1129
1129
|
await Querysub.commitSynced(() => {
|
|
1130
|
-
const userId = "service";
|
|
1131
1130
|
if (!(userId in data().users)) {
|
|
1132
1131
|
data().users[userId] = {
|
|
1133
1132
|
userId,
|