@resolveio/server-lib 20.9.6 → 20.9.8
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/managers/mongo.manager.js +22 -6
- package/managers/mongo.manager.js.map +1 -1
- package/managers/subscription.manager.d.ts +4 -0
- package/managers/subscription.manager.js +123 -13
- package/managers/subscription.manager.js.map +1 -1
- package/models/subscription.model.d.ts +2 -0
- package/models/subscription.model.js.map +1 -1
- package/package.json +1 -1
- package/util/subscription-dependency-context.d.ts +7 -0
- package/util/subscription-dependency-context.js +117 -44
- package/util/subscription-dependency-context.js.map +1 -1
|
@@ -35,6 +35,7 @@ export declare class SubscriptionManager {
|
|
|
35
35
|
private readonly LATENCY_UPDATE_THRESHOLD_MS;
|
|
36
36
|
private _invalidationDebounceTimers;
|
|
37
37
|
private _invalidationPendingTimestamps;
|
|
38
|
+
private _pendingInvalidations;
|
|
38
39
|
private readonly DEBOUNCE_DELAY;
|
|
39
40
|
private readonly MAX_WAIT_TIME;
|
|
40
41
|
constructor();
|
|
@@ -66,8 +67,11 @@ export declare class SubscriptionManager {
|
|
|
66
67
|
private convertDocumentIdForQuery;
|
|
67
68
|
private documentMatchesFilter;
|
|
68
69
|
private shouldInvalidateSubscription;
|
|
70
|
+
private shouldInvalidateSubscriptionForEvents;
|
|
71
|
+
private shouldForceRequeryOnInsert;
|
|
69
72
|
private sendWS;
|
|
70
73
|
getEnableDebug(): boolean;
|
|
71
74
|
private dependencyDebug;
|
|
75
|
+
private summarizeEvents;
|
|
72
76
|
private logDependencySnapshot;
|
|
73
77
|
}
|
|
@@ -139,6 +139,7 @@ var SubscriptionManager = /** @class */ (function () {
|
|
|
139
139
|
// private performanceThread;
|
|
140
140
|
this._invalidationDebounceTimers = new Map();
|
|
141
141
|
this._invalidationPendingTimestamps = new Map();
|
|
142
|
+
this._pendingInvalidations = new Map();
|
|
142
143
|
this.DEBOUNCE_DELAY = 100; // 100ms debounce window
|
|
143
144
|
this.MAX_WAIT_TIME = 500; // 500ms maximum delay
|
|
144
145
|
}
|
|
@@ -341,11 +342,17 @@ var SubscriptionManager = /** @class */ (function () {
|
|
|
341
342
|
};
|
|
342
343
|
SubscriptionManager.prototype.invalidatePubsCache = function (collection, type, documentId) {
|
|
343
344
|
return __awaiter(this, void 0, void 0, function () {
|
|
344
|
-
var debounceKey, now, firstInvalidationTime, waitedTooLong;
|
|
345
|
+
var queue, debounceKey, now, firstInvalidationTime, waitedTooLong;
|
|
345
346
|
var _this = this;
|
|
346
347
|
return __generator(this, function (_a) {
|
|
347
348
|
switch (_a.label) {
|
|
348
349
|
case 0:
|
|
350
|
+
queue = this._pendingInvalidations.get(collection);
|
|
351
|
+
if (!queue) {
|
|
352
|
+
queue = { events: [] };
|
|
353
|
+
this._pendingInvalidations.set(collection, queue);
|
|
354
|
+
}
|
|
355
|
+
queue.events.push({ type: type, documentId: documentId });
|
|
349
356
|
debounceKey = collection;
|
|
350
357
|
now = Date.now();
|
|
351
358
|
firstInvalidationTime = this._invalidationPendingTimestamps.get(debounceKey) || now;
|
|
@@ -358,7 +365,7 @@ var SubscriptionManager = /** @class */ (function () {
|
|
|
358
365
|
if (!waitedTooLong) return [3 /*break*/, 2];
|
|
359
366
|
// Immediate execution path
|
|
360
367
|
this._invalidationPendingTimestamps.delete(debounceKey);
|
|
361
|
-
return [4 /*yield*/, this._executeInvalidation(collection
|
|
368
|
+
return [4 /*yield*/, this._executeInvalidation(collection)];
|
|
362
369
|
case 1:
|
|
363
370
|
_a.sent();
|
|
364
371
|
return [3 /*break*/, 3];
|
|
@@ -369,7 +376,7 @@ var SubscriptionManager = /** @class */ (function () {
|
|
|
369
376
|
switch (_a.label) {
|
|
370
377
|
case 0:
|
|
371
378
|
this._invalidationPendingTimestamps.delete(debounceKey);
|
|
372
|
-
return [4 /*yield*/, this._executeInvalidation(collection
|
|
379
|
+
return [4 /*yield*/, this._executeInvalidation(collection)];
|
|
373
380
|
case 1:
|
|
374
381
|
_a.sent();
|
|
375
382
|
return [2 /*return*/];
|
|
@@ -382,9 +389,9 @@ var SubscriptionManager = /** @class */ (function () {
|
|
|
382
389
|
});
|
|
383
390
|
});
|
|
384
391
|
};
|
|
385
|
-
SubscriptionManager.prototype._executeInvalidation = function (collection
|
|
392
|
+
SubscriptionManager.prototype._executeInvalidation = function (collection) {
|
|
386
393
|
return __awaiter(this, void 0, void 0, function () {
|
|
387
|
-
var
|
|
394
|
+
var queued, events, collSubs, collSubs_1, collSubs_1_1, sub, batchType, _a, _b, client, ws, _c, e_1_1, e_2_1;
|
|
388
395
|
var e_2, _d, e_1, _e;
|
|
389
396
|
return __generator(this, function (_f) {
|
|
390
397
|
switch (_f.label) {
|
|
@@ -394,10 +401,15 @@ var SubscriptionManager = /** @class */ (function () {
|
|
|
394
401
|
clearTimeout(this._invalidationDebounceTimers.get(collection));
|
|
395
402
|
this._invalidationDebounceTimers.delete(collection);
|
|
396
403
|
}
|
|
404
|
+
queued = this._pendingInvalidations.get(collection);
|
|
405
|
+
this._pendingInvalidations.delete(collection);
|
|
406
|
+
if (!queued || !queued.events.length) {
|
|
407
|
+
return [2 /*return*/];
|
|
408
|
+
}
|
|
409
|
+
events = queued.events;
|
|
397
410
|
// Original invalidation logic
|
|
398
411
|
resolveio_server_app_1.ResolveIOServer.getMongoManager().invalidateQueryCache(collection);
|
|
399
412
|
collSubs = this._subscriptions.filter(function (a) { return a.collections.includes(collection); });
|
|
400
|
-
normalizedDocumentId = this.normalizeDocumentId(documentId);
|
|
401
413
|
_f.label = 1;
|
|
402
414
|
case 1:
|
|
403
415
|
_f.trys.push([1, 18, 19, 20]);
|
|
@@ -409,18 +421,19 @@ var SubscriptionManager = /** @class */ (function () {
|
|
|
409
421
|
if (this._enableDebug) {
|
|
410
422
|
console.log(new Date(), 'Invalidate Sub', sub.publication, sub.running, sub.runAgain);
|
|
411
423
|
}
|
|
412
|
-
return [4 /*yield*/, this.
|
|
424
|
+
return [4 /*yield*/, this.shouldInvalidateSubscriptionForEvents(sub, collection, events)];
|
|
413
425
|
case 3:
|
|
414
426
|
if (!(_f.sent())) {
|
|
415
427
|
return [3 /*break*/, 16];
|
|
416
428
|
}
|
|
417
429
|
if (sub.running) {
|
|
418
430
|
sub.runAgain = true;
|
|
419
|
-
this.dependencyDebug('Subscription busy, scheduling rerun', { publication: sub.publication, collection: collection,
|
|
431
|
+
this.dependencyDebug('Subscription busy, scheduling rerun', { publication: sub.publication, collection: collection, events: this.summarizeEvents(events) });
|
|
420
432
|
return [3 /*break*/, 16];
|
|
421
433
|
}
|
|
434
|
+
batchType = events.length === 1 ? events[0].type : events.map(function (event) { return event.type; }).join(',');
|
|
422
435
|
if (!this._publications[sub.publication].user_specific) return [3 /*break*/, 14];
|
|
423
|
-
this.dependencyDebug('Triggering user-specific invalidation', { publication: sub.publication, collection: collection,
|
|
436
|
+
this.dependencyDebug('Triggering user-specific invalidation', { publication: sub.publication, collection: collection, events: this.summarizeEvents(events), clientCount: sub.clients.length });
|
|
424
437
|
_f.label = 4;
|
|
425
438
|
case 4:
|
|
426
439
|
_f.trys.push([4, 11, 12, 13]);
|
|
@@ -434,7 +447,7 @@ var SubscriptionManager = /** @class */ (function () {
|
|
|
434
447
|
_f.label = 6;
|
|
435
448
|
case 6:
|
|
436
449
|
_f.trys.push([6, 8, , 9]);
|
|
437
|
-
return [4 /*yield*/, this.sendDataToOneWithRetry(ws, client.messageId, sub, collection,
|
|
450
|
+
return [4 /*yield*/, this.sendDataToOneWithRetry(ws, client.messageId, sub, collection, batchType)];
|
|
438
451
|
case 7:
|
|
439
452
|
_f.sent();
|
|
440
453
|
return [3 /*break*/, 9];
|
|
@@ -457,8 +470,8 @@ var SubscriptionManager = /** @class */ (function () {
|
|
|
457
470
|
return [7 /*endfinally*/];
|
|
458
471
|
case 13: return [3 /*break*/, 16];
|
|
459
472
|
case 14:
|
|
460
|
-
this.dependencyDebug('Triggering broadcast invalidation', { publication: sub.publication, collection: collection,
|
|
461
|
-
return [4 /*yield*/, this.sendDataToAllWithRetry(sub, collection,
|
|
473
|
+
this.dependencyDebug('Triggering broadcast invalidation', { publication: sub.publication, collection: collection, events: this.summarizeEvents(events), clientCount: sub.clients.length });
|
|
474
|
+
return [4 /*yield*/, this.sendDataToAllWithRetry(sub, collection, batchType)];
|
|
462
475
|
case 15:
|
|
463
476
|
_f.sent();
|
|
464
477
|
_f.label = 16;
|
|
@@ -719,7 +732,8 @@ var SubscriptionManager = /** @class */ (function () {
|
|
|
719
732
|
runAgain: false,
|
|
720
733
|
collectionDependencies: new Map(),
|
|
721
734
|
collectionFilters: new Map(),
|
|
722
|
-
watchAllCollections: new Set()
|
|
735
|
+
watchAllCollections: new Set(),
|
|
736
|
+
collectionQueryMeta: new Map()
|
|
723
737
|
});
|
|
724
738
|
}
|
|
725
739
|
if (!sub) {
|
|
@@ -1355,6 +1369,9 @@ var SubscriptionManager = /** @class */ (function () {
|
|
|
1355
1369
|
if (!sub.watchAllCollections) {
|
|
1356
1370
|
sub.watchAllCollections = new Set();
|
|
1357
1371
|
}
|
|
1372
|
+
if (!sub.collectionQueryMeta) {
|
|
1373
|
+
sub.collectionQueryMeta = new Map();
|
|
1374
|
+
}
|
|
1358
1375
|
};
|
|
1359
1376
|
SubscriptionManager.prototype.updateSubscriptionDependencies = function (sub, snapshot) {
|
|
1360
1377
|
this.ensureDependencyContainers(sub);
|
|
@@ -1362,12 +1379,14 @@ var SubscriptionManager = /** @class */ (function () {
|
|
|
1362
1379
|
sub.collectionDependencies.clear();
|
|
1363
1380
|
sub.collectionFilters.clear();
|
|
1364
1381
|
sub.watchAllCollections.clear();
|
|
1382
|
+
sub.collectionQueryMeta.clear();
|
|
1365
1383
|
this.dependencyDebug('Cleared dependency snapshot', { publication: sub.publication });
|
|
1366
1384
|
return;
|
|
1367
1385
|
}
|
|
1368
1386
|
sub.collectionDependencies = snapshot.dependencies;
|
|
1369
1387
|
sub.collectionFilters = snapshot.filters;
|
|
1370
1388
|
sub.watchAllCollections = snapshot.watchAllCollections;
|
|
1389
|
+
sub.collectionQueryMeta = snapshot.queryMetadata;
|
|
1371
1390
|
this.logDependencySnapshot(sub, 'Snapshot updated');
|
|
1372
1391
|
};
|
|
1373
1392
|
SubscriptionManager.prototype.normalizeDocumentId = function (rawId) {
|
|
@@ -1491,6 +1510,81 @@ var SubscriptionManager = /** @class */ (function () {
|
|
|
1491
1510
|
});
|
|
1492
1511
|
});
|
|
1493
1512
|
};
|
|
1513
|
+
SubscriptionManager.prototype.shouldInvalidateSubscriptionForEvents = function (sub, collection, events) {
|
|
1514
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
1515
|
+
var sawInsert, events_1, events_1_1, event_1, normalizedDocumentId, e_7_1, relevantMeta;
|
|
1516
|
+
var e_7, _a;
|
|
1517
|
+
return __generator(this, function (_b) {
|
|
1518
|
+
switch (_b.label) {
|
|
1519
|
+
case 0:
|
|
1520
|
+
sawInsert = false;
|
|
1521
|
+
_b.label = 1;
|
|
1522
|
+
case 1:
|
|
1523
|
+
_b.trys.push([1, 6, 7, 8]);
|
|
1524
|
+
events_1 = __values(events), events_1_1 = events_1.next();
|
|
1525
|
+
_b.label = 2;
|
|
1526
|
+
case 2:
|
|
1527
|
+
if (!!events_1_1.done) return [3 /*break*/, 5];
|
|
1528
|
+
event_1 = events_1_1.value;
|
|
1529
|
+
normalizedDocumentId = this.normalizeDocumentId(event_1.documentId);
|
|
1530
|
+
if (event_1.type === 'insert') {
|
|
1531
|
+
sawInsert = true;
|
|
1532
|
+
}
|
|
1533
|
+
return [4 /*yield*/, this.shouldInvalidateSubscription(sub, collection, event_1.type, normalizedDocumentId)];
|
|
1534
|
+
case 3:
|
|
1535
|
+
if (_b.sent()) {
|
|
1536
|
+
return [2 /*return*/, true];
|
|
1537
|
+
}
|
|
1538
|
+
_b.label = 4;
|
|
1539
|
+
case 4:
|
|
1540
|
+
events_1_1 = events_1.next();
|
|
1541
|
+
return [3 /*break*/, 2];
|
|
1542
|
+
case 5: return [3 /*break*/, 8];
|
|
1543
|
+
case 6:
|
|
1544
|
+
e_7_1 = _b.sent();
|
|
1545
|
+
e_7 = { error: e_7_1 };
|
|
1546
|
+
return [3 /*break*/, 8];
|
|
1547
|
+
case 7:
|
|
1548
|
+
try {
|
|
1549
|
+
if (events_1_1 && !events_1_1.done && (_a = events_1.return)) _a.call(events_1);
|
|
1550
|
+
}
|
|
1551
|
+
finally { if (e_7) throw e_7.error; }
|
|
1552
|
+
return [7 /*endfinally*/];
|
|
1553
|
+
case 8:
|
|
1554
|
+
if (sawInsert) {
|
|
1555
|
+
relevantMeta = this.shouldForceRequeryOnInsert(sub, collection);
|
|
1556
|
+
if (relevantMeta === null || relevantMeta === void 0 ? void 0 : relevantMeta.length) {
|
|
1557
|
+
this.dependencyDebug('Invalidate due to pagination metadata', {
|
|
1558
|
+
publication: sub.publication,
|
|
1559
|
+
collection: collection,
|
|
1560
|
+
events: this.summarizeEvents(events),
|
|
1561
|
+
queryMeta: relevantMeta.slice(0, 5)
|
|
1562
|
+
});
|
|
1563
|
+
return [2 /*return*/, true];
|
|
1564
|
+
}
|
|
1565
|
+
}
|
|
1566
|
+
return [2 /*return*/, false];
|
|
1567
|
+
}
|
|
1568
|
+
});
|
|
1569
|
+
});
|
|
1570
|
+
};
|
|
1571
|
+
SubscriptionManager.prototype.shouldForceRequeryOnInsert = function (sub, collection) {
|
|
1572
|
+
var _a;
|
|
1573
|
+
this.ensureDependencyContainers(sub);
|
|
1574
|
+
var metaList = (_a = sub.collectionQueryMeta) === null || _a === void 0 ? void 0 : _a.get(collection);
|
|
1575
|
+
if (!metaList || !metaList.length) {
|
|
1576
|
+
return null;
|
|
1577
|
+
}
|
|
1578
|
+
var relevantMeta = metaList.filter(function (meta) {
|
|
1579
|
+
if (!meta) {
|
|
1580
|
+
return false;
|
|
1581
|
+
}
|
|
1582
|
+
var limitUsed = typeof meta.limit === 'number' && meta.limit > 0;
|
|
1583
|
+
var skipUsed = typeof meta.skip === 'number' && meta.skip > 0;
|
|
1584
|
+
return limitUsed || skipUsed;
|
|
1585
|
+
});
|
|
1586
|
+
return relevantMeta.length ? relevantMeta : null;
|
|
1587
|
+
};
|
|
1494
1588
|
SubscriptionManager.prototype.sendWS = function (ws, data) {
|
|
1495
1589
|
this._websocketManager.send(ws, data);
|
|
1496
1590
|
};
|
|
@@ -1508,6 +1602,13 @@ var SubscriptionManager = /** @class */ (function () {
|
|
|
1508
1602
|
console.log(new Date(), '[Dependency Debug]', message);
|
|
1509
1603
|
}
|
|
1510
1604
|
};
|
|
1605
|
+
SubscriptionManager.prototype.summarizeEvents = function (events) {
|
|
1606
|
+
var _this = this;
|
|
1607
|
+
return events.map(function (event) { return ({
|
|
1608
|
+
type: event.type,
|
|
1609
|
+
documentId: _this.normalizeDocumentId(event.documentId)
|
|
1610
|
+
}); });
|
|
1611
|
+
};
|
|
1511
1612
|
SubscriptionManager.prototype.logDependencySnapshot = function (sub, context) {
|
|
1512
1613
|
if (!this._enableDependencyDebug) {
|
|
1513
1614
|
return;
|
|
@@ -1528,12 +1629,21 @@ var SubscriptionManager = /** @class */ (function () {
|
|
|
1528
1629
|
count: filters.length
|
|
1529
1630
|
});
|
|
1530
1631
|
});
|
|
1632
|
+
var queryMetaSummary = Array.from(sub.collectionQueryMeta.entries()).map(function (_a) {
|
|
1633
|
+
var _b = __read(_a, 2), collectionName = _b[0], metaList = _b[1];
|
|
1634
|
+
return ({
|
|
1635
|
+
collection: collectionName,
|
|
1636
|
+
count: metaList.length,
|
|
1637
|
+
meta: metaList.slice(0, 5)
|
|
1638
|
+
});
|
|
1639
|
+
});
|
|
1531
1640
|
var watchAll = Array.from(sub.watchAllCollections || []);
|
|
1532
1641
|
this.dependencyDebug('Dependency snapshot updated', {
|
|
1533
1642
|
context: context,
|
|
1534
1643
|
publication: sub.publication,
|
|
1535
1644
|
dependencies: dependencySummary,
|
|
1536
1645
|
collectionsWithFilters: filterSummary,
|
|
1646
|
+
collectionsWithMeta: queryMetaSummary,
|
|
1537
1647
|
watchAll: watchAll
|
|
1538
1648
|
});
|
|
1539
1649
|
};
|