@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.
@@ -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, type, documentId)];
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, type, documentId)];
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, type, documentId) {
392
+ SubscriptionManager.prototype._executeInvalidation = function (collection) {
386
393
  return __awaiter(this, void 0, void 0, function () {
387
- var collSubs, normalizedDocumentId, collSubs_1, collSubs_1_1, sub, _a, _b, client, ws, _c, e_1_1, e_2_1;
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.shouldInvalidateSubscription(sub, collection, type, normalizedDocumentId)];
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, type: type });
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, type: type, documentId: normalizedDocumentId, clientCount: sub.clients.length });
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, type)];
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, type: type, documentId: normalizedDocumentId, clientCount: sub.clients.length });
461
- return [4 /*yield*/, this.sendDataToAllWithRetry(sub, collection, type)];
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
  };