querysub 0.344.0 → 0.346.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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "querysub",
3
- "version": "0.344.0",
3
+ "version": "0.346.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",
@@ -51,7 +51,7 @@
51
51
  "js-sha512": "^0.9.0",
52
52
  "node-forge": "https://github.com/sliftist/forge#e618181b469b07bdc70b968b0391beb8ef5fecd6",
53
53
  "pako": "^2.1.0",
54
- "socket-function": "^0.152.0",
54
+ "socket-function": "^0.153.0",
55
55
  "terser": "^5.31.0",
56
56
  "typesafecss": "^0.23.0",
57
57
  "yaml": "^2.5.0",
@@ -1636,6 +1636,7 @@ export class PathValueProxyWatcher {
1636
1636
  // The calls have to happen after our local writes. This is because they are likely to
1637
1637
  // influence the local writes, and we don't want our local writes to be always invalidated
1638
1638
  call.runAtTime = getNextTime();
1639
+ call.fromProxy = watcher.debugName;
1639
1640
  logErrors(runCall(call, metadata));
1640
1641
  watcher.options.onCallCommit?.(call, metadata);
1641
1642
  }
@@ -121,7 +121,7 @@ export function interceptCallsBase<T>(
121
121
  }
122
122
  interceptCalls.declare(interceptCallsBase);
123
123
 
124
-
124
+ /** Writes the function call allowing interceptors to capture it (vs runCall which just runs it). */
125
125
  export function writeFunctionCall(config: {
126
126
  domainName: string;
127
127
  moduleId: string;
@@ -91,6 +91,9 @@ export interface CallSpec {
91
91
  callerIP: string;
92
92
  runAtTime: Time;
93
93
 
94
+ // Not just used for debugging, also used to add special proxy-related warnings.
95
+ fromProxy?: string;
96
+
94
97
  filterable?: Filterable;
95
98
  }
96
99
  export function debugCallSpec(spec: CallSpec): string {
@@ -48,6 +48,9 @@ export type FunctionMetadata<F = unknown> = {
48
48
  */
49
49
  delayCommit?: boolean;
50
50
 
51
+ /** By default, we try to finish calls in the start order when using Querysub.commitAsync, unless the caller explicitly says not to. However, if this is set, then we won't have this call finish or cause other calls to be finished in the start order. This makes locking less safe, but can be useful for long-running functions that shouldn't block other functions and which the order doesn't matter. */
52
+ noFinishInStartOrder?: boolean;
53
+
51
54
  /** Too many locks can lag the server, and eventually cause crashes. Consider using Querysub.noLocks(() => ...) around code that is accessing too many values, assuming you don't want to lock them. However, if absolutely required, you can override max locks to allow as many locks to be created as you want until the server crashses... */
52
55
  maxLocksOverride?: number;
53
56
  };
@@ -363,7 +366,7 @@ export function syncSchema<Schema>(schema?: Schema2): SyncSchemaResult<Schema> {
363
366
  moduleId,
364
367
  functionId: name,
365
368
  args,
366
- metadata,
369
+ metadata: metadata
367
370
  });
368
371
  }, {
369
372
  debug() {
@@ -18,6 +18,8 @@ import { Button } from "../library-components/Button";
18
18
  import { updateRootDiscoveryLocation } from "../-f-node-discovery/NodeDiscovery";
19
19
 
20
20
  const SWITCH_SERVER_TIMEOUT = timeInSecond * 15;
21
+ const MAX_DISPLAY_INTERVAL = timeInMinute * 5;
22
+ const FINAL_DELAY = timeInSecond * 30;
21
23
 
22
24
  let lastHashServer = "";
23
25
  export function startEdgeNotifier() {
@@ -61,113 +63,105 @@ const notifyClients = throttleFunction(timeInMinute, async function notifyClient
61
63
  // Track current notification state
62
64
  let currentNotification: { close: () => void } | null = null;
63
65
  let curHash = "";
66
+ let lastShownTime = 0;
64
67
  function onLiveHashChange(liveHash: string, refreshThresholdTime: number) {
65
68
  console.log(blue(`Received client liveHash ${liveHash}, prev hash: ${curHash}`));
66
69
  if (liveHash === curHash) return;
67
70
  let prevHash = curHash;
68
71
  // Don't notify the user right away. Hopefully they refresh naturally, and we never have to notify them at all!
69
72
  // Also, refresh BEFORE the server dies, not exactly when it is about to die
70
- let notifyIntervals = [0.4, 0.75, 0.95];
73
+ let delays = [0.4, 0.75, 1].map(x => delay(x * refreshThresholdTime));
74
+
71
75
  console.log(blue(`Client liveHash changed ${liveHash}, prev hash: ${prevHash}`));
72
- // If we are replacing an already existing notification, don't show immediately
73
- let skipFirst = false;
74
- if (currentNotification) {
75
- currentNotification.close();
76
- currentNotification = null;
77
- skipFirst = true;
78
- }
79
- curHash = liveHash;
80
76
 
81
- let duration = refreshThresholdTime - Date.now();
77
+ curHash = liveHash;
82
78
 
83
79
  // Start notification loop
84
80
  void (async () => {
85
81
  // Show notifications at intervals
86
- for (let i = 0; i < notifyIntervals.length - 1; i++) {
82
+ for (let delayTime of delays) {
83
+ await delayTime;
87
84
  // Don't show if a newer notification is active
88
85
  if (curHash !== liveHash) return;
89
86
 
90
- let waitDuration = (notifyIntervals[i + 1] - notifyIntervals[i]) * duration;
91
- // If the duration is short, and it's not the last one, skip it
92
- if (i < notifyIntervals.length - 2 && waitDuration <= 30 * 1000) continue;
93
-
94
87
  // Update the URL override for manual refreshes
95
88
  if (!liveHash.startsWith("forced")) {
96
89
  Querysub.localCommit(() => {
97
90
  liveHashOverrideURL.value = { liveHash, time: Date.now() };
98
91
  });
99
92
  }
100
- if (!skipFirst) {
101
- if (currentNotification) {
102
- currentNotification.close();
103
- currentNotification = null;
104
- }
105
- // Show notification modal
106
- let nextNotification = {
107
- close: showModal({
108
- onClose: () => {
109
- if (currentNotification !== nextNotification) return;
110
- currentNotification = null;
111
- },
112
- content: (
113
- <div
114
- title={`Live Hash: ${liveHash}, prev hash: ${prevHash}`}
115
- className={
116
- css.vbox(10).pad(20)
117
- .hsla(0, 0, 0, 0.8)
118
- .position("fixed")
119
- .bottom(10)
120
- .right(10)
121
- .zIndex(1000)
122
- + " keepModalsOpen"
123
- }
124
- >
125
- <div className={css.vbox(10).maxWidth(250)}>
126
- <h3 className={css.margin(0)}>Server Update Available</h3>
127
- <div>The server has been updated. Please refresh the page to ensure you don't experience compatibility issues.</div>
128
- {i !== notifyIntervals.length - 2 && <div>This notification will be shown again at {formatNiceDateTime(Date.now() + waitDuration)}</div>}
129
- {i === notifyIntervals.length - 2 && <div>The page will automatically refresh at {formatNiceDateTime(Date.now() + waitDuration)}</div>}
130
- </div>
131
- <div className={css.hbox(10).justifyContent("flex-end")}>
132
- <button
133
- className={css.pad(8, 16).hsl(200, 50, 50).color("white").pointer}
134
- onClick={(e) => {
135
- if (!liveHash.startsWith("forced")) {
136
- Querysub.localCommit(() => {
137
- liveHashOverrideURL.value = { liveHash, time: Date.now() };
138
- });
139
- }
140
- window.location.reload();
141
- }}
142
- >
143
- Refresh Now
144
- </button>
145
- <button
146
- className={css.pad(8, 16).pointer}
147
- onClick={(e) => {
148
- if (currentNotification) {
149
- currentNotification.close();
150
- currentNotification = null;
151
- }
152
- }}
153
- >
154
- Dismiss
155
- </button>
156
- </div>
157
- </div>
158
- )
159
- }).close
160
- };
161
- currentNotification = nextNotification;
162
- }
163
- skipFirst = false;
164
93
 
165
- console.log(red(`Notify again in ${formatTime(waitDuration)}`));
166
- await delay(waitDuration);
94
+ let timeSinceLastShown = Date.now() - lastShownTime;
95
+ let isLastDelay = delayTime === delays.at(-1);
96
+ if (timeSinceLastShown < MAX_DISPLAY_INTERVAL && !isLastDelay) continue;
97
+
98
+ lastShownTime = Date.now();
99
+
100
+ if (currentNotification) {
101
+ currentNotification.close();
102
+ currentNotification = null;
103
+ }
104
+ // Show notification modal
105
+ let nextNotification = {
106
+ close: showModal({
107
+ onClose: () => {
108
+ if (currentNotification !== nextNotification) return;
109
+ currentNotification = null;
110
+ },
111
+ content: (
112
+ <div
113
+ title={`Live Hash: ${liveHash}, prev hash: ${prevHash}`}
114
+ className={
115
+ css.vbox(10).pad(20)
116
+ .hsla(0, 0, 0, 0.8)
117
+ .position("fixed")
118
+ .bottom(10)
119
+ .right(10)
120
+ .zIndex(1000)
121
+ + " keepModalsOpen"
122
+ }
123
+ >
124
+ <div className={css.vbox(10).maxWidth(250)}>
125
+ <h3 className={css.margin(0)}>Server Update Available</h3>
126
+ <div>The server has been updated. Please refresh the page to ensure you don't experience compatibility issues.</div>
127
+ {isLastDelay && <div>The page will automatically refresh shortly</div>}
128
+ </div>
129
+ <div className={css.hbox(10).justifyContent("flex-end")}>
130
+ <button
131
+ className={css.pad(8, 16).hsl(200, 50, 50).color("white").pointer}
132
+ onClick={(e) => {
133
+ if (!liveHash.startsWith("forced")) {
134
+ Querysub.localCommit(() => {
135
+ liveHashOverrideURL.value = { liveHash, time: Date.now() };
136
+ });
137
+ }
138
+ window.location.reload();
139
+ }}
140
+ >
141
+ Refresh Now
142
+ </button>
143
+ <button
144
+ className={css.pad(8, 16).pointer}
145
+ onClick={(e) => {
146
+ if (currentNotification) {
147
+ currentNotification.close();
148
+ currentNotification = null;
149
+ }
150
+ }}
151
+ >
152
+ Dismiss
153
+ </button>
154
+ </div>
155
+ </div>
156
+ )
157
+ }).close
158
+ };
159
+ currentNotification = nextNotification;
167
160
  }
168
161
 
169
162
  // Only force refresh if this is still the current notification
170
- if (curHash === liveHash) {
163
+ if (curHash === liveHash && currentNotification) {
164
+ await delay(FINAL_DELAY);
171
165
  window.location.reload();
172
166
  }
173
167
  })();
@@ -418,7 +418,7 @@ export function getCallWrites(config: {
418
418
 
419
419
  let finishInStartOrder: number | boolean | undefined;
420
420
 
421
- if (config.useFinishReordering) {
421
+ if (config.useFinishReordering && !config.metadata?.noFinishInStartOrder && call.fromProxy) {
422
422
  let triggerCaller = getCurrentCallCreationProxy();
423
423
  if (!triggerCaller) {
424
424
  require("debugbreak")(2);