querysub 0.146.0 → 0.148.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
|
@@ -580,8 +580,10 @@ class AuthorityPathValueStorage {
|
|
|
580
580
|
childPaths.add(path);
|
|
581
581
|
}
|
|
582
582
|
|
|
583
|
-
/** Called by PathWatcher / ourself when paths are unwatched / destroyed
|
|
584
|
-
|
|
583
|
+
/** Called by PathWatcher / ourself when paths are unwatched / destroyed, to free memory.
|
|
584
|
+
* NOOPS if we are the authority of the path.
|
|
585
|
+
*/
|
|
586
|
+
public destroyPath(path: string) {
|
|
585
587
|
// If we are the authority we:
|
|
586
588
|
// 1) Need to maintain the values for other nodes
|
|
587
589
|
// 2) Don't need to worry about the values getting out of date,
|
|
@@ -1096,7 +1098,7 @@ class AuthorityPathValueStorage {
|
|
|
1096
1098
|
|
|
1097
1099
|
if (pathsToClear.size > 0) {
|
|
1098
1100
|
for (let path of pathsToClear) {
|
|
1099
|
-
this.
|
|
1101
|
+
this.destroyPath(path);
|
|
1100
1102
|
// I'm not sure if removing it as a parent is needed, or... maybe it is needed,
|
|
1101
1103
|
// and this isn't enough of a check?
|
|
1102
1104
|
this.markParentPathAsUnwatched(path);
|
|
@@ -1322,27 +1324,6 @@ class PathWatcher {
|
|
|
1322
1324
|
|
|
1323
1325
|
let pathsWatched = this.watchersToPaths.get(callback);
|
|
1324
1326
|
|
|
1325
|
-
for (let path of config.paths) {
|
|
1326
|
-
if (pathsWatched) {
|
|
1327
|
-
pathsWatched.paths.delete(path);
|
|
1328
|
-
}
|
|
1329
|
-
|
|
1330
|
-
let watchers = this.watchers.get(path);
|
|
1331
|
-
if (!watchers) continue;
|
|
1332
|
-
watchers.watchers.delete(callback);
|
|
1333
|
-
if (watchers.watchers.size === 0) {
|
|
1334
|
-
this.watchers.delete(path);
|
|
1335
|
-
|
|
1336
|
-
let parentPath = getParentPathStr(path);
|
|
1337
|
-
let parentWatchers = this.watcherParentToPath.get(parentPath);
|
|
1338
|
-
if (parentWatchers) {
|
|
1339
|
-
parentWatchers.delete(path);
|
|
1340
|
-
}
|
|
1341
|
-
|
|
1342
|
-
fullyUnwatched.paths.push(path);
|
|
1343
|
-
authorityStorage.markPathAsUnwatched(path);
|
|
1344
|
-
}
|
|
1345
|
-
}
|
|
1346
1327
|
for (let path of config.parentPaths) {
|
|
1347
1328
|
if (pathsWatched) {
|
|
1348
1329
|
pathsWatched.parents.delete(path);
|
|
@@ -1364,6 +1345,46 @@ class PathWatcher {
|
|
|
1364
1345
|
|
|
1365
1346
|
if (watchersObj.size === 0) {
|
|
1366
1347
|
this.parentWatchers.delete(unpackedPath);
|
|
1348
|
+
|
|
1349
|
+
let childPaths = authorityStorage.getPathsFromParent(unpackedPath);
|
|
1350
|
+
// Destroy values that now have no watchers (no value watchers, and now no parent watcher
|
|
1351
|
+
if (childPaths) {
|
|
1352
|
+
for (let childPath of childPaths) {
|
|
1353
|
+
if (!this.watchers.has(childPath)) {
|
|
1354
|
+
authorityStorage.destroyPath(childPath);
|
|
1355
|
+
}
|
|
1356
|
+
}
|
|
1357
|
+
}
|
|
1358
|
+
}
|
|
1359
|
+
}
|
|
1360
|
+
}
|
|
1361
|
+
|
|
1362
|
+
// NOTE: Unwatch parents, then values, as parent paths might keep alive value path watches.
|
|
1363
|
+
for (let path of config.paths) {
|
|
1364
|
+
if (pathsWatched) {
|
|
1365
|
+
pathsWatched.paths.delete(path);
|
|
1366
|
+
}
|
|
1367
|
+
|
|
1368
|
+
let watchers = this.watchers.get(path);
|
|
1369
|
+
if (!watchers) continue;
|
|
1370
|
+
watchers.watchers.delete(callback);
|
|
1371
|
+
if (watchers.watchers.size === 0) {
|
|
1372
|
+
this.watchers.delete(path);
|
|
1373
|
+
|
|
1374
|
+
let parentPath = getParentPathStr(path);
|
|
1375
|
+
let parentWatchers = this.watcherParentToPath.get(parentPath);
|
|
1376
|
+
if (parentWatchers) {
|
|
1377
|
+
parentWatchers.delete(path);
|
|
1378
|
+
}
|
|
1379
|
+
|
|
1380
|
+
fullyUnwatched.paths.push(path);
|
|
1381
|
+
// NOTE: If the parent is being watched, don't destroy the value.
|
|
1382
|
+
// - The fact that we only do the check here does mean that if the path is unwatched
|
|
1383
|
+
// first and then later the parent path is unwatched we will fail to properly destroy
|
|
1384
|
+
// the path. However, in practice, either both are unwatched at the same time, or more
|
|
1385
|
+
// likely, the value watch only goes away because it's made redundant by the parent watch.
|
|
1386
|
+
if (!this.parentWatchers.has(parentPath)) {
|
|
1387
|
+
authorityStorage.destroyPath(path);
|
|
1367
1388
|
}
|
|
1368
1389
|
}
|
|
1369
1390
|
}
|
|
@@ -367,8 +367,8 @@ async function edgeNodeFunction(config: {
|
|
|
367
367
|
let PARALLEL_FACTOR = 3;
|
|
368
368
|
for (let i = 0; i < edgeNodes.length; i += PARALLEL_FACTOR) {
|
|
369
369
|
let node = await new Promise<EdgeNodeConfig | undefined>(resolve => {
|
|
370
|
+
let finished = 0;
|
|
370
371
|
for (let j = 0; j < PARALLEL_FACTOR; j++) {
|
|
371
|
-
let finished = 0;
|
|
372
372
|
((async () => {
|
|
373
373
|
try {
|
|
374
374
|
let node = edgeNodes[i + j];
|
|
@@ -422,11 +422,6 @@ function predictCall(config: {
|
|
|
422
422
|
logErrors(predictPromise);
|
|
423
423
|
|
|
424
424
|
let didCancel = false;
|
|
425
|
-
// ALWAYS reject the prediction eventually, in case the function runner server is down.
|
|
426
|
-
// - ALSO, once it goes back up, the write will be too far in the future, and our lock won't be rejected.
|
|
427
|
-
// And don't really want endTime to be infinitely in the future, as then cleanup code has a harder time
|
|
428
|
-
// removing the lock, as then in theory it can always be rejected, no matter how long we wait.
|
|
429
|
-
setTimeout(rejectPrediction, Querysub.PREDICTION_MAX_LIFESPAN);
|
|
430
425
|
function rejectPrediction() {
|
|
431
426
|
if (didCancel) return;
|
|
432
427
|
didCancel = true;
|
|
@@ -439,9 +434,18 @@ function predictCall(config: {
|
|
|
439
434
|
reason: "prediction timeout rejected",
|
|
440
435
|
}]);
|
|
441
436
|
}
|
|
442
|
-
|
|
443
|
-
|
|
437
|
+
|
|
438
|
+
setTimeout(cleanupPrediction, Querysub.PREDICTION_MAX_LIFESPAN);
|
|
439
|
+
function cleanupPrediction() {
|
|
444
440
|
if (didCancel) return;
|
|
441
|
+
|
|
442
|
+
// ALWAYS reject the prediction, in case the function runner server is down.
|
|
443
|
+
// - ALSO, once it goes back up, the write likely will be too far in the future, so our lock won't be rejected,
|
|
444
|
+
// will will cause the bad value to stick around.
|
|
445
|
+
// We could fix this with an endTime infinitely in the future, but then the lock can never be GCed,
|
|
446
|
+
// which create a memory leak.
|
|
447
|
+
rejectPrediction();
|
|
448
|
+
|
|
445
449
|
if (Querysub.AUDIT_PREDICTIONS && predictions) {
|
|
446
450
|
const afterTime = { time: call.runAtTime.time, version: Number.MAX_SAFE_INTEGER, creatorId: 0 };
|
|
447
451
|
// Clone predictions, to strip symbols
|