querysub 0.427.0 → 0.429.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.427.0",
3
+ "version": "0.429.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",
@@ -18,8 +18,8 @@ import { getAllAuthoritySpec, getEmptyAuthoritySpec } from "./PathRouterServerAu
18
18
 
19
19
  setImmediate(() => import("../3-path-functions/syncSchema"));
20
20
 
21
- let NETWORK_POLL_INTERVAL = timeInMinute * 5;
22
- let CALL_TIMEOUT = isPublic() ? timeInSecond * 20 : timeInSecond * 3;
21
+ let NETWORK_POLL_INTERVAL = timeInMinute * 1;
22
+ let CALL_TIMEOUT = timeInSecond * 5;
23
23
 
24
24
  export type AuthorityEntry = {
25
25
  nodeId: string;
@@ -10,6 +10,7 @@ import { measureFnc } from "socket-function/src/profiling/measure";
10
10
  import { getRoutingOverride, hasPrefixHash } from "./PathRouterRouteOverride";
11
11
  import { sha256 } from "js-sha256";
12
12
  import { rangesOverlap, removeRange } from "../rangeMath";
13
+ import { decodeParentFilter } from "./hackedPackedPathParentFiltering";
13
14
 
14
15
 
15
16
  // Cases
@@ -57,6 +58,19 @@ function matchesPrefix(matcher: PrefixMatcher, path: string): boolean {
57
58
  return false;
58
59
  }
59
60
  }
61
+ if (getPathIndex(path, matcher.childKeyIndex) === undefined) return false;
62
+ return true;
63
+ }
64
+ // Checks if they're asking for the exact prefix, which would mean that the children would be the direct children of this prefix matcher.
65
+ function isPrefixParent(matcher: PrefixMatcher, path: string): boolean {
66
+ if (!path.startsWith(matcher.prefix)) return false;
67
+ let partsA = getPathFromStr(matcher.originalPrefix);
68
+ let partsB = getPathFromStr(path);
69
+ for (let i = 0; i < partsA.length; i++) {
70
+ // Empty string is wildcard
71
+ if (partsA[i] === "") continue;
72
+ if (partsB[i] !== partsA[i]) return false;
73
+ }
60
74
  return true;
61
75
  }
62
76
  /** Empty string path part becomes a wildcard */
@@ -535,11 +549,17 @@ export class PathRouter {
535
549
  range: { start: number; end: number };
536
550
  }[];
537
551
  } {
552
+ let parentRange = decodeParentFilter(path) || {
553
+ start: 0,
554
+ end: 1,
555
+ };
556
+ path = hack_stripPackedPath(path);
538
557
  let preferredNodeIds = new Set(config?.preferredNodeIds ?? []);
539
558
 
540
559
  // If a prefix is a parent of path, then it is the same as matching just the path directly
541
560
  // (If our prefix directly equals one of the other matches, then it's more complicated, As then, the child keys of path are what is hashed, and so all the children will have different routes, so we might match multiple nodes. The same thing if we're matching the remaining case, in which case it's a full path hash, so the child key matters, and again, different routes).
542
561
  // - The different route case is how the FuntionRunner works, and without it large databases couldn't run functions. However, most applications won't directly use it.
562
+ // NOTE: The only own nodes flag is actually so we can access this before the topology finishes synchronizing. Because we want to be able to call get child read nodes from path value core for some really basic stuff. It also is what the caller wants, but that's not a good enough reason to add this check. The reason we have this check is because without it, the topology won't have finished synchronizing and startup won't work.
543
563
  let allSources = config?.onlyOwnNodes ? [{ nodeId: getOwnNodeId(), authoritySpec: authorityLookup.getOurSpec() }] : authorityLookup.getTopologySync();
544
564
  // Prefer our own node
545
565
  sort(allSources, x => isOwnNodeId(x.nodeId) ? -1 : 1);
@@ -549,14 +569,13 @@ export class PathRouter {
549
569
 
550
570
 
551
571
  // Direct prefix. This happens for things like calls and functions, it requires more advanced routing as it means we're going to route between multiple servers, but... it is important
552
- let hasPrefix = allSources.filter(x => x.authoritySpec.prefixes.some(y => y.prefix === path)).map(x => x.authoritySpec);
572
+ let hasPrefix = allSources.filter(x => x.authoritySpec.prefixes.some(y => isPrefixParent(y, path))).map(x => x.authoritySpec);
553
573
  if (hasPrefix.length > 0) {
554
574
  shuffle(hasPrefix, Math.random());
555
575
  sort(hasPrefix, x => preferredNodeIds.has(x.nodeId) ? -1 : 1);
556
576
 
557
577
  let missingRanges: { start: number; end: number }[] = [{
558
- start: 0,
559
- end: 1,
578
+ ...parentRange
560
579
  }];
561
580
  let usedParts: {
562
581
  nodeId: string;
@@ -585,7 +604,7 @@ export class PathRouter {
585
604
  let nestedMatches = allSources.filter(x => {
586
605
  // There's nested prefixes, so if we match any prefix explicitly, we can't just take one of the previous prefixes because that isn't how the hashing will work.
587
606
  // - This happens if it's a direct match, but one of the shards is down, in which case we can't get a full match.
588
- if (x.authoritySpec.prefixes.some(y => y.prefix === path)) return false;
607
+ if (x.authoritySpec.prefixes.some(y => isPrefixParent(y, path))) return false;
589
608
 
590
609
  // If our path, which we're going to read the children of, is the child of another path, then it means in that other path, the child key will be known to us constant, and so we're going to match exactly one authority.
591
610
  return (
@@ -617,8 +636,7 @@ export class PathRouter {
617
636
  sort(fullPathMatches, x => preferredNodeIds.has(x.nodeId) ? -1 : 1);
618
637
  sort(allSources, x => isOwnNodeId(x.nodeId) ? -1 : 1);
619
638
  let missingRanges: { start: number; end: number }[] = [{
620
- start: 0,
621
- end: 1,
639
+ ...parentRange
622
640
  }];
623
641
  let usedParts: {
624
642
  nodeId: string;
@@ -645,8 +663,6 @@ export class PathRouter {
645
663
  }
646
664
 
647
665
 
648
-
649
-
650
666
  if (!config?.onlyOwnNodes) {
651
667
  // TODO: We could maybe match a partial match. However, even that is suspect. The site being partially broken is almost worse than it being completely broken. We should just get ALL the shards running again...
652
668
 
@@ -609,11 +609,12 @@ class AuthorityPathValueStorage {
609
609
  return false;
610
610
  }
611
611
  public isParentSynced(path: string) {
612
+ let originalPath = path;
612
613
  let range = decodeParentFilter(path);
613
614
  path = hack_stripPackedPath(path);
614
615
  if (PathRouter.isLocalPath(path)) return true;
615
616
 
616
- let synced = this.parentsSynced.get(path);
617
+ let synced = this.parentsSynced.get(originalPath) || this.parentsSynced.get(path);
617
618
  if (synced === true) return true;
618
619
  // See if the ranges received so far cover the requested range. If we only request a partial range, then this will always be the case. We'll never fully synchronize the path.
619
620
  if (synced && range) {
@@ -626,24 +627,11 @@ class AuthorityPathValueStorage {
626
627
 
627
628
  // Self authority check
628
629
  {
629
- let nodes = PathRouter.getChildReadNodes(path, { onlyOwnNodes: true });
630
- if (nodes.nodes.length > 0) {
631
- if (nodes.nodes.every(x => isOwnNodeId(x.nodeId))) {
632
- // If it's not a partial 30 and we're self authority, we're always going to be self authority, so we can just cache it in the lookup.
633
- this.parentsSynced.set(path, true);
634
- return true;
635
- }
636
- // Might be a partial authority
637
- if (range) {
638
- let selfNodes = nodes.nodes.filter(x => isOwnNodeId(x.nodeId));
639
- let missingRanges: { start: number; end: number }[] = [{ start: range.start, end: range.end }];
640
- for (let range of selfNodes) {
641
- removeRange(missingRanges, range.range);
642
- }
643
- if (missingRanges.length === 0) {
644
- return true;
645
- }
646
- }
630
+ let nodes = PathRouter.getChildReadNodes(originalPath, { onlyOwnNodes: true });
631
+ if (nodes.nodes.length > 0 && nodes.nodes.every(x => isOwnNodeId(x.nodeId))) {
632
+ // If we're the self authority of it, it's not going to change, so we can just cache it safely.
633
+ this.parentsSynced.set(originalPath, true);
634
+ return true;
647
635
  }
648
636
  }
649
637
 
@@ -1121,4 +1109,5 @@ setImmediate(() => {
1121
1109
  export { pathValueArchives };
1122
1110
 
1123
1111
  (globalThis as any).core = module.exports;
1112
+ (globalThis as any).authorityStorage = authorityStorage;
1124
1113
  (globalThis as any).SocketFunction = SocketFunction;
@@ -486,7 +486,6 @@ export class RemoteWatcher {
486
486
  auditLog("Asking to watch parent path", { path, authorityId, targetNodeThreadId: debugNodeThread(authorityId) });
487
487
  }
488
488
  }
489
-
490
489
  logErrors(RemoteWatcher.REMOTE_WATCH_FUNCTION(config, authorityId));
491
490
  }
492
491
  });