querysub 0.130.0 → 0.131.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/-0-hooks/hooks.ts +16 -1
- package/src/-f-node-discovery/NodeDiscovery.ts +1 -1
- package/src/3-path-functions/PathFunctionRunner.ts +2 -2
- package/src/4-deploy/deploySchema.ts +1 -33
- package/src/4-deploy/edgeBootstrap.ts +45 -15
- package/src/4-deploy/edgeClientWatcher.tsx +187 -0
- package/src/4-deploy/edgeNodes.ts +5 -24
- package/src/4-querysub/Querysub.ts +3 -0
- package/src/library-components/URLParam.ts +12 -8
package/package.json
CHANGED
package/src/-0-hooks/hooks.ts
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import type { EdgeNodeConfig } from "../4-deploy/edgeNodes";
|
|
2
|
+
import type { ExtraMetadata } from "../5-diagnostics/nodeMetadata";
|
|
3
|
+
|
|
1
4
|
// Hooks, to allow function implementations to be declared after their first call
|
|
2
5
|
// (so static calls work).
|
|
3
6
|
|
|
@@ -89,7 +92,6 @@ export const onTimeProfile = createHookFunction<
|
|
|
89
92
|
) => void
|
|
90
93
|
>("onTimeProfile");
|
|
91
94
|
|
|
92
|
-
import type { ExtraMetadata } from "../5-diagnostics/nodeMetadata";
|
|
93
95
|
export const registerNodeMetadata = createHookFunction<
|
|
94
96
|
(
|
|
95
97
|
metadata: ExtraMetadata
|
|
@@ -116,3 +118,16 @@ export const logNodeStateStats = createHookFunction<
|
|
|
116
118
|
export const isManagementUser = createHookFunctionReturn<
|
|
117
119
|
() => Promise<boolean>
|
|
118
120
|
>("isManagementUser");
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
declare global {
|
|
125
|
+
var BOOTED_EDGE_NODE: EdgeNodeConfig | undefined;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
export function getBootedEdgeNode(): EdgeNodeConfig {
|
|
130
|
+
let edgeNode = globalThis.BOOTED_EDGE_NODE;
|
|
131
|
+
if (!edgeNode) throw new Error(`No edge node booted? This should be impossible.`);
|
|
132
|
+
return edgeNode;
|
|
133
|
+
}
|
|
@@ -23,7 +23,7 @@ import dns from "dns/promises";
|
|
|
23
23
|
import { isDefined } from "../misc";
|
|
24
24
|
import { diskLog, noDiskLogPrefix } from "../diagnostics/logs/diskLogger";
|
|
25
25
|
import { getDebuggerUrl } from "../diagnostics/listenOnDebugger";
|
|
26
|
-
import { getBootedEdgeNode } from "
|
|
26
|
+
import { getBootedEdgeNode } from "../-0-hooks/hooks";
|
|
27
27
|
|
|
28
28
|
let HEARTBEAT_INTERVAL = timeInMinute * 2;
|
|
29
29
|
// Interval which we check other heartbeats
|
|
@@ -665,9 +665,9 @@ export async function preloadFunctions(specs: FunctionSpec[]) {
|
|
|
665
665
|
let nodeIds = await getControllerNodeIdList(FunctionPreloadController);
|
|
666
666
|
await Promise.allSettled(nodeIds.map(async nodeId => {
|
|
667
667
|
let controller = FunctionPreloadController.nodes[nodeId.nodeId];
|
|
668
|
-
console.log(blue(`Preloading functions on ${nodeId}`));
|
|
668
|
+
console.log(blue(`Preloading functions on ${String(nodeId)}`));
|
|
669
669
|
await errorToUndefined(controller.preloadFunctions(specs));
|
|
670
|
-
console.log(blue(`Finished preloading functions on ${nodeId}`));
|
|
670
|
+
console.log(blue(`Finished preloading functions on ${String(nodeId)}`));
|
|
671
671
|
}));
|
|
672
672
|
}
|
|
673
673
|
|
|
@@ -38,36 +38,4 @@ export function setLiveDeployedHash(config: {
|
|
|
38
38
|
deploySchema()[getDomain()].deploy.history[nextId()] = hashObj;
|
|
39
39
|
},
|
|
40
40
|
});
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
//todonext
|
|
44
|
-
// - Function to dynamically deploy edge service based on hash (try on old hashes)
|
|
45
|
-
// - Watch live hash, and when it changes, deploy new edge service
|
|
46
|
-
// - Add flag to deploy script which sets it (with all the flags, so we can just deploy it)
|
|
47
|
-
// - Update edge node code to pass live hash, and try to connect to a service with that
|
|
48
|
-
|
|
49
|
-
//todonext
|
|
50
|
-
/*
|
|
51
|
-
Force client refresh mechanism / update notification ON `yarn deploy`
|
|
52
|
-
- deployonlycode / deployonlyui / deploynotifyforced
|
|
53
|
-
- OH! Actually...
|
|
54
|
-
- This HAS to use a synced value!
|
|
55
|
-
- Add a new synced value which specifies the UI hash!
|
|
56
|
-
- THEN! Have front-end servers dynamically launch this services with this hash when it's set (loading the code and then serving the specific path, with the hash, etc)
|
|
57
|
-
- Also, serve this to clients!
|
|
58
|
-
- Clients will watch this value (normally, like any other value), and notify the user when it is out of date, letting them ignore it, but eventually forcing a refresh
|
|
59
|
-
- AND, support preloading it
|
|
60
|
-
- So our order will be
|
|
61
|
-
(git push)
|
|
62
|
-
preload functions
|
|
63
|
-
preload UI
|
|
64
|
-
atomically set function hashes + ui hashes
|
|
65
|
-
clients are notified they should refresh
|
|
66
|
-
new clients use services with the latest hash (which servers are already hosting)
|
|
67
|
-
functions will run this hash
|
|
68
|
-
- Ah, also... add a flag which tells us NOT to use the service HTML cache
|
|
69
|
-
- Remove it when used
|
|
70
|
-
- Required on refresh, otherwise we might refresh and use an outdated service
|
|
71
|
-
|
|
72
|
-
ALSO, have FunctionRunner watch the hash using the get/watch mechanism (for preloading, as it will dynamically load the code depending on what is really deployed anyways...)
|
|
73
|
-
*/
|
|
41
|
+
}
|
|
@@ -3,23 +3,17 @@ import { isServer } from "../config2";
|
|
|
3
3
|
import { EdgeNodeConfig, EdgeNodesIndex } from "./edgeNodes";
|
|
4
4
|
import { timeInMinute, timeInSecond } from "socket-function/src/misc";
|
|
5
5
|
import { measureBlock } from "socket-function/src/profiling/measure";
|
|
6
|
+
import { URLParam } from "../library-components/URLParam";
|
|
6
7
|
|
|
7
8
|
module.hotreload = true;
|
|
8
9
|
module.noserverhotreload = false;
|
|
9
10
|
|
|
11
|
+
const liveHashOverrideParam = "liveHashOverride";
|
|
12
|
+
export const liveHashOverrideURL = new URLParam(liveHashOverrideParam, undefined as undefined | {
|
|
13
|
+
liveHash: string;
|
|
14
|
+
time: number;
|
|
15
|
+
});
|
|
10
16
|
|
|
11
|
-
declare global {
|
|
12
|
-
var BOOTED_EDGE_NODE: EdgeNodeConfig | undefined;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
export function getBootedEdgeNode(): EdgeNodeConfig {
|
|
17
|
-
if (isServer()) throw new Error(`getBootedEdgeNode is not available on the server`);
|
|
18
|
-
|
|
19
|
-
let edgeNode = globalThis.BOOTED_EDGE_NODE;
|
|
20
|
-
if (!edgeNode) throw new Error(`No edge node booted? This should be impossible.`);
|
|
21
|
-
return edgeNode;
|
|
22
|
-
}
|
|
23
17
|
|
|
24
18
|
let getCachedConfig = cache(async (url: string): Promise<EdgeNodesIndex | undefined> => {
|
|
25
19
|
setTimeout(() => {
|
|
@@ -217,6 +211,26 @@ async function edgeNodeFunction(config: {
|
|
|
217
211
|
|
|
218
212
|
let cachedConfig = config.cachedConfig;
|
|
219
213
|
|
|
214
|
+
let liveHashOverride = "";
|
|
215
|
+
let liveHashOverrideExpiryTime = 0;
|
|
216
|
+
|
|
217
|
+
const liveHashOverrideParam2: typeof liveHashOverrideParam = "liveHashOverride";
|
|
218
|
+
let searchParams = new URLSearchParams(document.location.search);
|
|
219
|
+
let liveHashOverrideObj = searchParams.get(liveHashOverrideParam2);
|
|
220
|
+
// JUST use it on the first loop, so if we can't find any matches, we ignore it.
|
|
221
|
+
if (liveHashOverrideObj) {
|
|
222
|
+
try {
|
|
223
|
+
let liveHashOverrideObject = JSON.parse(liveHashOverrideObj);
|
|
224
|
+
liveHashOverrideExpiryTime = liveHashOverrideObject.time + 1000 * 30;
|
|
225
|
+
liveHashOverride = liveHashOverrideObject.liveHash;
|
|
226
|
+
} catch (e: any) {
|
|
227
|
+
console.error(`Error parsing liveHashOverride ${liveHashOverride}: ${e.stack}`);
|
|
228
|
+
}
|
|
229
|
+
// Remove it from the search params
|
|
230
|
+
searchParams.delete(liveHashOverrideParam2);
|
|
231
|
+
document.location.search = searchParams.toString();
|
|
232
|
+
}
|
|
233
|
+
|
|
220
234
|
let progressUI = createProgressUI();
|
|
221
235
|
progressUI.setMessage("Finding available server...");
|
|
222
236
|
while (true) {
|
|
@@ -226,9 +240,12 @@ async function edgeNodeFunction(config: {
|
|
|
226
240
|
} catch (e) {
|
|
227
241
|
console.error(e);
|
|
228
242
|
}
|
|
229
|
-
progressUI.setMessage("No available servers, retrying
|
|
230
|
-
|
|
231
|
-
|
|
243
|
+
progressUI.setMessage("No available servers, retrying soon");
|
|
244
|
+
let time = 1000 * 15;
|
|
245
|
+
if (Date.now() < liveHashOverrideExpiryTime) {
|
|
246
|
+
time = 1000 * 3;
|
|
247
|
+
}
|
|
248
|
+
await new Promise(resolve => setTimeout(resolve, time));
|
|
232
249
|
}
|
|
233
250
|
progressUI.stop();
|
|
234
251
|
|
|
@@ -260,6 +277,16 @@ async function edgeNodeFunction(config: {
|
|
|
260
277
|
async function getEdgeNodeConfig(): Promise<EdgeNodeConfig> {
|
|
261
278
|
let edgeIndex = cachedConfig || await (await fetch(config.edgeNodeConfigURL)).json() as EdgeNodesIndex;
|
|
262
279
|
cachedConfig = undefined;
|
|
280
|
+
let liveHashForced = false;
|
|
281
|
+
if (Date.now() < liveHashOverrideExpiryTime) {
|
|
282
|
+
liveHashForced = true;
|
|
283
|
+
edgeIndex.liveHash = liveHashOverride;
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
// export const liveHashOverrideURL = new URLParam(liveHashOverrideParam, undefined as undefined | {
|
|
287
|
+
// liveHash: string;
|
|
288
|
+
// time: number;
|
|
289
|
+
// });
|
|
263
290
|
|
|
264
291
|
console.group(`Found edge nodes`);
|
|
265
292
|
|
|
@@ -309,6 +336,9 @@ async function edgeNodeFunction(config: {
|
|
|
309
336
|
|
|
310
337
|
let liveNodes = edgeNodes.filter(x => x.gitHash === edgeIndex.liveHash);
|
|
311
338
|
if (liveNodes.length === 0) {
|
|
339
|
+
if (liveHashForced) {
|
|
340
|
+
throw new Error(`Could not find any live nodes (${edgeIndex.liveHash}), and the live hash is forced.`);
|
|
341
|
+
}
|
|
312
342
|
let latestHash = edgeNodes[0].gitHash;
|
|
313
343
|
console.warn(`Could not find any live nodes (${edgeIndex.liveHash}), falling back to latest hash: ${latestHash}`);
|
|
314
344
|
liveNodes = edgeNodes.filter(x => x.gitHash === latestHash);
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
import { SocketFunction } from "socket-function/SocketFunction";
|
|
2
|
+
import { Querysub } from "../4-querysub/QuerysubController";
|
|
3
|
+
import { deploySchema } from "./deploySchema";
|
|
4
|
+
import { getDomain } from "../config";
|
|
5
|
+
import { throttleFunction, timeInMinute } from "socket-function/src/misc";
|
|
6
|
+
import { isNode } from "typesafecss";
|
|
7
|
+
import { logErrors, timeoutToError } from "../errors";
|
|
8
|
+
import { blue, red } from "socket-function/src/formatting/logColors";
|
|
9
|
+
import { showModal } from "../5-diagnostics/Modal";
|
|
10
|
+
import { qreact } from "../4-dom/qreact";
|
|
11
|
+
import { liveHashOverrideURL } from "./edgeBootstrap";
|
|
12
|
+
import { css } from "typesafecss";
|
|
13
|
+
import { formatTime } from "socket-function/src/formatting/format";
|
|
14
|
+
import { delay } from "socket-function/src/batching";
|
|
15
|
+
|
|
16
|
+
export function startEdgeNotifier() {
|
|
17
|
+
SocketFunction.expose(EdgeNotifierController);
|
|
18
|
+
let lastHash = "";
|
|
19
|
+
Querysub.createWatcher(() => {
|
|
20
|
+
let liveHash = deploySchema()[getDomain()].deploy.live.hash;
|
|
21
|
+
if (!Querysub.isAllSynced()) return;
|
|
22
|
+
if (liveHash === lastHash) return;
|
|
23
|
+
let refreshThresholdTime = deploySchema()[getDomain()].deploy.live.refreshThresholdTime;
|
|
24
|
+
lastHash = liveHash;
|
|
25
|
+
void notifyClients(liveHash, refreshThresholdTime);
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
let watchingClientNodes = new Set<string>();
|
|
30
|
+
const notifyClients = throttleFunction(100, async function notifyClients(liveHash: string, refreshThresholdTime: number) {
|
|
31
|
+
await Promise.allSettled(Array.from(watchingClientNodes).map(async clientNodeId => {
|
|
32
|
+
try {
|
|
33
|
+
await timeoutToError(5000, EdgeNotifierClientController.nodes[clientNodeId].onLiveHashChange(liveHash, refreshThresholdTime), () => new Error(`Timeout for watch updates on node ${clientNodeId}`));
|
|
34
|
+
} catch (e) {
|
|
35
|
+
console.log(blue(`Client unwatching liveHash ${clientNodeId}`), e);
|
|
36
|
+
watchingClientNodes.delete(clientNodeId);
|
|
37
|
+
}
|
|
38
|
+
}));
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
// Track current notification state
|
|
42
|
+
let currentNotification: { close: () => void } | null = null;
|
|
43
|
+
let curHash = "";
|
|
44
|
+
function onLiveHashChange(liveHash: string, refreshThresholdTime: number) {
|
|
45
|
+
let notifyIntervals = [0, 0.1, 0.5, 1];
|
|
46
|
+
console.log(blue(`Client liveHash changed ${liveHash}`));
|
|
47
|
+
let skipFirst = false;
|
|
48
|
+
if (currentNotification) {
|
|
49
|
+
currentNotification.close();
|
|
50
|
+
currentNotification = null;
|
|
51
|
+
skipFirst = true;
|
|
52
|
+
}
|
|
53
|
+
curHash = liveHash;
|
|
54
|
+
|
|
55
|
+
// Start notification loop
|
|
56
|
+
void (async () => {
|
|
57
|
+
// Show notifications at intervals
|
|
58
|
+
for (let i = 0; i < notifyIntervals.length; i++) {
|
|
59
|
+
// Don't show if a newer notification is active
|
|
60
|
+
if (curHash !== liveHash) return;
|
|
61
|
+
|
|
62
|
+
let waitDuration = (notifyIntervals[i + 1] - notifyIntervals[i]) * refreshThresholdTime;
|
|
63
|
+
if (i >= notifyIntervals.length - 1 && waitDuration <= 30 * 1000) continue;
|
|
64
|
+
|
|
65
|
+
// Update the URL override for manual refreshes
|
|
66
|
+
Querysub.localCommit(() => {
|
|
67
|
+
liveHashOverrideURL.value = { liveHash, time: Date.now() };
|
|
68
|
+
});
|
|
69
|
+
if (!skipFirst) {
|
|
70
|
+
// Show notification modal
|
|
71
|
+
currentNotification = {
|
|
72
|
+
close: showModal({
|
|
73
|
+
content: (
|
|
74
|
+
<div
|
|
75
|
+
title={`Live Hash: ${liveHash}`}
|
|
76
|
+
className={
|
|
77
|
+
css.vbox(10).pad(20)
|
|
78
|
+
.hsla(0, 0, 0, 0.8)
|
|
79
|
+
.position("fixed")
|
|
80
|
+
.bottom(10)
|
|
81
|
+
.right(10)
|
|
82
|
+
.zIndex(1000)
|
|
83
|
+
}
|
|
84
|
+
onClick={() => {
|
|
85
|
+
if (currentNotification) {
|
|
86
|
+
currentNotification.close();
|
|
87
|
+
currentNotification = null;
|
|
88
|
+
}
|
|
89
|
+
}}
|
|
90
|
+
>
|
|
91
|
+
<div className={css.vbox(10).maxWidth(250)}>
|
|
92
|
+
<h3 className={css.margin(0)}>Server Update Available</h3>
|
|
93
|
+
<div>The server has been updated. Please refresh the page to ensure you don't experience incompatibility issues.</div>
|
|
94
|
+
</div>
|
|
95
|
+
<div className={css.hbox(10).justifyContent("flex-end")}>
|
|
96
|
+
<button
|
|
97
|
+
className={css.pad(8, 16).hsl(200, 50, 50).color("white").pointer}
|
|
98
|
+
onClick={() => {
|
|
99
|
+
Querysub.localCommit(() => {
|
|
100
|
+
liveHashOverrideURL.value = { liveHash, time: Date.now() };
|
|
101
|
+
});
|
|
102
|
+
window.location.reload();
|
|
103
|
+
}}
|
|
104
|
+
>
|
|
105
|
+
Refresh Now
|
|
106
|
+
</button>
|
|
107
|
+
<button
|
|
108
|
+
className={css.pad(8, 16).pointer}
|
|
109
|
+
onClick={() => {
|
|
110
|
+
if (currentNotification) {
|
|
111
|
+
currentNotification.close();
|
|
112
|
+
currentNotification = null;
|
|
113
|
+
}
|
|
114
|
+
}}
|
|
115
|
+
>
|
|
116
|
+
Dismiss
|
|
117
|
+
</button>
|
|
118
|
+
</div>
|
|
119
|
+
</div>
|
|
120
|
+
)
|
|
121
|
+
}).close
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
skipFirst = false;
|
|
125
|
+
|
|
126
|
+
console.log(red(`Notify again in ${formatTime(waitDuration)}`));
|
|
127
|
+
await delay(waitDuration);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
console.log(red(`Force refresh after 30 seconds`));
|
|
131
|
+
await delay(30 * 1000);
|
|
132
|
+
|
|
133
|
+
// Only force refresh if this is still the current notification
|
|
134
|
+
if (curHash === liveHash) {
|
|
135
|
+
window.location.reload();
|
|
136
|
+
}
|
|
137
|
+
})();
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
const EdgeNotifierClientController = SocketFunction.register(
|
|
141
|
+
"EdgeNotifierClientController-ed122e41-6ad2-4161-9492-a3f8414bd4f0",
|
|
142
|
+
new class EdgeNotifierClient {
|
|
143
|
+
public async onLiveHashChange(liveHash: string, refreshThresholdTime: number) {
|
|
144
|
+
onLiveHashChange(liveHash, refreshThresholdTime);
|
|
145
|
+
}
|
|
146
|
+
},
|
|
147
|
+
() => ({
|
|
148
|
+
onLiveHashChange: {},
|
|
149
|
+
}),
|
|
150
|
+
() => ({}),
|
|
151
|
+
{
|
|
152
|
+
noAutoExpose: true,
|
|
153
|
+
}
|
|
154
|
+
);
|
|
155
|
+
|
|
156
|
+
if (!isNode()) {
|
|
157
|
+
setImmediate(() => {
|
|
158
|
+
void Querysub.optionalStartupWait().finally(() => {
|
|
159
|
+
logErrors(EdgeNotifierController.nodes[SocketFunction.browserNodeId()].watchUpdates());
|
|
160
|
+
});
|
|
161
|
+
SocketFunction.expose(EdgeNotifierClientController);
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
class EdgeNotifierControllerBase {
|
|
166
|
+
public async watchUpdates() {
|
|
167
|
+
let nodeId = SocketFunction.getCaller().nodeId;
|
|
168
|
+
console.log(blue(`Client watching liveHash ${nodeId}`));
|
|
169
|
+
watchingClientNodes.add(nodeId);
|
|
170
|
+
Querysub.onNextDisconnect(nodeId, () => {
|
|
171
|
+
watchingClientNodes.delete(nodeId);
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
const EdgeNotifierController = SocketFunction.register(
|
|
177
|
+
"EdgeNotifierController-b11fbbf0-ef5e-4ba3-80ae-d5b1b8124f2d",
|
|
178
|
+
new EdgeNotifierControllerBase(),
|
|
179
|
+
() => ({
|
|
180
|
+
watchUpdates: {},
|
|
181
|
+
}),
|
|
182
|
+
() => ({}),
|
|
183
|
+
{
|
|
184
|
+
noAutoExpose: true,
|
|
185
|
+
}
|
|
186
|
+
);
|
|
187
|
+
|
|
@@ -24,6 +24,7 @@ import { deploySchema } from "./deploySchema";
|
|
|
24
24
|
import { proxyWatcher } from "../2-proxy/PathValueProxyWatcher";
|
|
25
25
|
import { Querysub } from "../4-querysub/QuerysubController";
|
|
26
26
|
import { onEdgeNodesChanged } from "./edgeBootstrap";
|
|
27
|
+
import { startEdgeNotifier } from "./edgeClientWatcher";
|
|
27
28
|
|
|
28
29
|
const UPDATE_POLL_INTERVAL = timeInMinute;
|
|
29
30
|
const DEAD_NODE_COUNT_THRESHOLD = 15;
|
|
@@ -177,8 +178,6 @@ const loadEntryPointsByHash = runInSerial(async function loadEntryPointsByHash(c
|
|
|
177
178
|
await edgeNodeStorage.set(getNextNodePath(), Buffer.from(JSON.stringify(edgeNodeConfig)));
|
|
178
179
|
console.log(magenta(`Deployed edge node`), edgeNodeConfig);
|
|
179
180
|
|
|
180
|
-
SocketFunction.expose(EdgeNodeController);
|
|
181
|
-
|
|
182
181
|
await updateEdgeNodesFile();
|
|
183
182
|
|
|
184
183
|
onEdgeNodesChanged();
|
|
@@ -196,6 +195,8 @@ export const getEdgeNodeConfigURL = lazy(async () => {
|
|
|
196
195
|
const startUpdateLoop = lazy(async () => {
|
|
197
196
|
await getEdgeNodeConfigURL();
|
|
198
197
|
await runInfinitePollCallAtStart(UPDATE_POLL_INTERVAL, updateLoop);
|
|
198
|
+
SocketFunction.expose(EdgeNodeController);
|
|
199
|
+
startEdgeNotifier();
|
|
199
200
|
});
|
|
200
201
|
|
|
201
202
|
async function updateLoop() {
|
|
@@ -272,9 +273,9 @@ export async function preloadUI(hash: string) {
|
|
|
272
273
|
let nodeIds = await getControllerNodeIdList(EdgeNodeController);
|
|
273
274
|
await Promise.allSettled(nodeIds.map(async nodeId => {
|
|
274
275
|
let controller = EdgeNodeController.nodes[nodeId.nodeId];
|
|
275
|
-
console.log(blue(`Preloading UI on ${nodeId}, hash: ${hash}`));
|
|
276
|
+
console.log(blue(`Preloading UI on ${String(nodeId)}, hash: ${hash}`));
|
|
276
277
|
await errorToUndefined(controller.preloadUI({ hash }));
|
|
277
|
-
console.log(blue(`Finished preloading UI on ${nodeId}`));
|
|
278
|
+
console.log(blue(`Finished preloading UI on ${String(nodeId)}`));
|
|
278
279
|
}));
|
|
279
280
|
}
|
|
280
281
|
|
|
@@ -309,23 +310,3 @@ const EdgeNodeController = SocketFunction.register(
|
|
|
309
310
|
}
|
|
310
311
|
);
|
|
311
312
|
|
|
312
|
-
// async function main() {
|
|
313
|
-
// await loadEntryPointsByHash({
|
|
314
|
-
// host: "127-0-0-1.querysub.com:1111",
|
|
315
|
-
// entryPaths: ["./src/browser.ts"],
|
|
316
|
-
// hash: "7b1eb4934d5bdfe6d0f7076049c4b7decad4e645",
|
|
317
|
-
// });
|
|
318
|
-
// }
|
|
319
|
-
// main().catch(console.error).finally(() => process.exit());
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
//todonext
|
|
324
|
-
// 3) Verify the deploy code works on the live site
|
|
325
|
-
// - I think it isn't? But maybe we just need to do-update again
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
// 7) Client live hash watch code + notify + refresh + flag to ignore the baked in live hash + edge node
|
|
329
|
-
// - Test by pushing, deploying, and then we should immediately see a notify to refresh
|
|
330
|
-
|
|
331
|
-
// 8) VERIFY writing and permissions still works
|
|
@@ -290,6 +290,9 @@ export class Querysub {
|
|
|
290
290
|
public static isAllSynced = Querysub.allSynced;
|
|
291
291
|
public static isAnyUnsynced = Querysub.anyUnsynced;
|
|
292
292
|
|
|
293
|
+
public static onNextDisconnect = SocketFunction.onNextDisconnect;
|
|
294
|
+
public static isNodeConnected = SocketFunction.isNodeConnected;
|
|
295
|
+
|
|
293
296
|
public static pathHasAnyWatchers(get: () => unknown) {
|
|
294
297
|
return clientWatcher.pathHasAnyWatchers(getProxyPath(get));
|
|
295
298
|
}
|
|
@@ -63,11 +63,13 @@ export function createURLSync<T>(urlKey: string, defaultValue: T, config?: {
|
|
|
63
63
|
if (config?.storage === "localStorage") {
|
|
64
64
|
localStorageKeys.add(urlKey);
|
|
65
65
|
}
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
66
|
+
setImmediate(() => {
|
|
67
|
+
Querysub.localCommit(() => {
|
|
68
|
+
data().defaults[urlKey] = defaultValue;
|
|
69
|
+
if (!(urlKey in loadSearchCache)) {
|
|
70
|
+
data().params[urlKey] = deepCloneJSON(defaultValue);
|
|
71
|
+
}
|
|
72
|
+
});
|
|
71
73
|
});
|
|
72
74
|
function deleteKeys(obj: any) {
|
|
73
75
|
if (!canHaveChildren(obj)) return;
|
|
@@ -222,9 +224,11 @@ function watchURLForUpdates() {
|
|
|
222
224
|
}
|
|
223
225
|
|
|
224
226
|
if (!isNode()) {
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
227
|
+
setImmediate(() => {
|
|
228
|
+
loadParamsFromURL();
|
|
229
|
+
watchURLForUpdates();
|
|
230
|
+
syncStateToURL();
|
|
231
|
+
});
|
|
228
232
|
}
|
|
229
233
|
|
|
230
234
|
export function parseSearchString(search: string): { [key: string]: unknown } {
|