querysub 0.144.0 → 0.146.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.
|
|
3
|
+
"version": "0.146.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",
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
"node-forge": "https://github.com/sliftist/forge#e618181b469b07bdc70b968b0391beb8ef5fecd6",
|
|
25
25
|
"pako": "^2.1.0",
|
|
26
26
|
"preact": "^10.11.3",
|
|
27
|
-
"socket-function": "^0.
|
|
27
|
+
"socket-function": "^0.82.0",
|
|
28
28
|
"terser": "^5.31.0",
|
|
29
29
|
"typesafecss": "^0.6.3",
|
|
30
30
|
"yaml": "^2.5.0",
|
|
@@ -11,7 +11,7 @@ import { errorToUndefined, logErrors, timeoutToUndefined } from "../errors";
|
|
|
11
11
|
import { getPathFromStr } from "../path";
|
|
12
12
|
import { nodePathAuthority, pathValueAuthority2 } from "./NodePathAuthorities";
|
|
13
13
|
import { PathValueController } from "./PathValueController";
|
|
14
|
-
import { PathValue, MAX_ACCEPTED_CHANGE_AGE, lockWatcher, authorityStorage, writeValidStorage, WriteState, lockToCallback, pathWatcher, MAX_CHANGE_AGE, debugPathValue, debugPathValuePath, compareTime, epochTime, isOurPrediction } from "./pathValueCore";
|
|
14
|
+
import { PathValue, MAX_ACCEPTED_CHANGE_AGE, lockWatcher, authorityStorage, writeValidStorage, WriteState, lockToCallback, pathWatcher, MAX_CHANGE_AGE, debugPathValue, debugPathValuePath, compareTime, epochTime, isOurPrediction, timeHash } from "./pathValueCore";
|
|
15
15
|
import debugbreak from "debugbreak";
|
|
16
16
|
import { red } from "socket-function/src/formatting/logColors";
|
|
17
17
|
import { registerDynamicResource } from "../diagnostics/trackResources";
|
|
@@ -278,6 +278,23 @@ class PathValueCommitter {
|
|
|
278
278
|
// missing values (unless we are the authority). Otherwise bad rejected values can stick around,
|
|
279
279
|
// because they are newer, and our new source doesn't know we have them.
|
|
280
280
|
measureBlock(function resetOnInitialTrigger() {
|
|
281
|
+
let receivedValues = new Map<string, Set<string>>();
|
|
282
|
+
for (let batch of batched) {
|
|
283
|
+
for (let pathValue of batch.pathValues) {
|
|
284
|
+
let path = pathValue.path;
|
|
285
|
+
let hash = timeHash(pathValue.time);
|
|
286
|
+
let paths = receivedValues.get(path);
|
|
287
|
+
if (!paths) {
|
|
288
|
+
paths = new Set();
|
|
289
|
+
receivedValues.set(path, paths);
|
|
290
|
+
}
|
|
291
|
+
paths.add(hash);
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
// TODO: Ugh... rejections on initialSync might the wrong solution. I think we have to just remove the values,
|
|
296
|
+
// even though this makes debugging harder, in order to prevent the rejections from sticking around.
|
|
297
|
+
|
|
281
298
|
for (let batch of batched) {
|
|
282
299
|
if (!batch.initialTrigger) continue;
|
|
283
300
|
for (let pathValue of batch.pathValues) {
|
|
@@ -292,12 +309,24 @@ class PathValueCommitter {
|
|
|
292
309
|
// Only reset values after us, otherwise we might clear valid history that
|
|
293
310
|
// we JUST received.
|
|
294
311
|
if (compareTime(value.time, pathValue.time) <= 0) continue;
|
|
312
|
+
|
|
313
|
+
// If we just received it, accept it.
|
|
314
|
+
// - Otherwise we might reject a valid older value, and then when the newer value is rejected
|
|
315
|
+
// the server won't tell us about the older value again, and so we will think no values
|
|
316
|
+
// are accepted, when the older value IS accepted.
|
|
317
|
+
// BUG: In theory couldn't we receive an outdated value, then reconnect, then receive the correct
|
|
318
|
+
// value, and have them all batched together? In which case, we shouldn't accept the value.
|
|
319
|
+
// I'm not really sure how to fix this though. We kind of need to just handle adding the values
|
|
320
|
+
// and the rejections in order, instead of batching them, but that is much slower, and the race
|
|
321
|
+
// condition will likely be extremely rare (and only happen on disconnections anyways).
|
|
322
|
+
if (receivedValues.get(pathValue.path)?.has(timeHash(pathValue.time))) continue;
|
|
323
|
+
|
|
295
324
|
specialInitialParentCausedRejections.push({
|
|
296
325
|
path: value.path,
|
|
297
326
|
time: value.time,
|
|
298
327
|
isValid: false,
|
|
299
328
|
isTransparent: !!value.isTransparent,
|
|
300
|
-
reason: "future missing (initial trigger)",
|
|
329
|
+
reason: "future missing on resync (initial trigger)",
|
|
301
330
|
});
|
|
302
331
|
}
|
|
303
332
|
}
|
|
@@ -431,6 +460,13 @@ class PathValueCommitter {
|
|
|
431
460
|
|
|
432
461
|
let now = Date.now();
|
|
433
462
|
|
|
463
|
+
// NOTE: specialInitialParentCausedRejections is a bit dangerous, because it can reject golden values.
|
|
464
|
+
// This means we have to ingest it immediately, otherwise authorityStorage might gc path values
|
|
465
|
+
// (that are before a golden value), when rejections might remove that golden value.
|
|
466
|
+
if (specialInitialParentCausedRejections) {
|
|
467
|
+
this.ingestValidStates(specialInitialParentCausedRejections);
|
|
468
|
+
}
|
|
469
|
+
|
|
434
470
|
authorityStorage.ingestValues(pathValues, parentsSynced, parentSyncedSources);
|
|
435
471
|
|
|
436
472
|
// NOTE: This doesn't seem to be where we lag, so we aren't tracking it anymore.
|
|
@@ -440,7 +476,7 @@ class PathValueCommitter {
|
|
|
440
476
|
}
|
|
441
477
|
|
|
442
478
|
// NOTE: Also triggers rejections of watched paths
|
|
443
|
-
this.ingestValidStates(
|
|
479
|
+
this.ingestValidStates([], parentsSynced, undefined, pathValues, initialTriggers);
|
|
444
480
|
}
|
|
445
481
|
|
|
446
482
|
// NOTE: Technically, because we trigger all remotes any time a value changes, even
|
|
@@ -945,9 +945,10 @@ class AuthorityPathValueStorage {
|
|
|
945
945
|
// some values in memory...
|
|
946
946
|
|
|
947
947
|
let goldenTime = now - MAX_CHANGE_AGE;
|
|
948
|
-
// NOTE: Values with no locks are implicitly golden, as they can't be rejected
|
|
949
|
-
let firstGoldenIndex = values.findIndex(x => x.time.time < goldenTime || x.lockCount === 0);
|
|
948
|
+
// NOTE: Values with no locks are implicitly golden, as they can't be rejected
|
|
949
|
+
let firstGoldenIndex = values.findIndex(x => x.time.time < goldenTime && x.valid || x.lockCount === 0);
|
|
950
950
|
if (firstGoldenIndex < 0) return;
|
|
951
|
+
|
|
951
952
|
// Special case, everything is golden, and the latest value is undefined, and is behind the GC
|
|
952
953
|
// point, then delete everything, so constantly changing keys doesn't result in us leaking memory forever.
|
|
953
954
|
if (
|
|
@@ -987,9 +988,8 @@ class AuthorityPathValueStorage {
|
|
|
987
988
|
}
|
|
988
989
|
} else {
|
|
989
990
|
// Delete everything that is golden, except for the most recent VALID value.
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
for (let i = values.length - 1; i > validGoldenIndex; i--) {
|
|
991
|
+
if (firstGoldenIndex >= 0 && values.length > firstGoldenIndex) {
|
|
992
|
+
for (let i = values.length - 1; i > firstGoldenIndex; i--) {
|
|
993
993
|
let gced = values.pop();
|
|
994
994
|
if (!isCoreQuiet && gced) {
|
|
995
995
|
console.log(`GCing ${debugPathValuePath(gced)}`);
|
|
@@ -33,24 +33,30 @@ export class ActionsHistory {
|
|
|
33
33
|
}
|
|
34
34
|
public static OnRead(values: PathValue[]) {
|
|
35
35
|
if (ClientWatcher.DEBUG_READS && values.length > 0) {
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
36
|
+
values = values.filter(x => !x.path.startsWith(LOCAL_DOMAIN_PATH));
|
|
37
|
+
if (values.length > 0) {
|
|
38
|
+
let now = Date.now();
|
|
39
|
+
let oldest = Math.min(...values.map(x => x.time.time).filter(x => x), now);
|
|
40
|
+
group(ClientWatcher.DEBUG_READS_EXPANDED)(`(${now - epoch}ms, ${now}) Read count ${values.length}, ${(Date.now() - oldest).toFixed()}ms old`);
|
|
41
|
+
for (let value of values) {
|
|
42
|
+
console.log(blue(debugPathValuePath(value)), "===", pathValueSerializer.getPathValue(value), `(${value.valid ? "valid" : "invalid"})`);
|
|
43
|
+
}
|
|
44
|
+
console.groupEnd();
|
|
41
45
|
}
|
|
42
|
-
console.groupEnd();
|
|
43
46
|
}
|
|
44
47
|
if (!ActionsHistory.LOG_ACTION_HISTORY) return;
|
|
45
48
|
}
|
|
46
49
|
public static OnWrite(values: PathValue[]) {
|
|
47
50
|
if (ClientWatcher.DEBUG_WRITES) {
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
51
|
+
values = values.filter(x => !x.path.startsWith(LOCAL_DOMAIN_PATH));
|
|
52
|
+
if (values.length > 0) {
|
|
53
|
+
let now = Date.now();
|
|
54
|
+
group(ClientWatcher.DEBUG_WRITES_EXPANDED)(green(`(${now - epoch}ms, ${now}) Committing writes ${values.length}`));
|
|
55
|
+
for (let value of values) {
|
|
56
|
+
console.log(green(debugPathValuePath(value)), "=", pathValueSerializer.getPathValue(value), `(${value.valid ? "valid" : "invalid"})`);
|
|
57
|
+
}
|
|
58
|
+
console.groupEnd();
|
|
52
59
|
}
|
|
53
|
-
console.groupEnd();
|
|
54
60
|
}
|
|
55
61
|
if (!ActionsHistory.LOG_ACTION_HISTORY) return;
|
|
56
62
|
}
|