@resolveio/server-lib 20.9.3 → 20.9.5

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.
@@ -73,6 +73,7 @@ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
73
73
  };
74
74
  Object.defineProperty(exports, "__esModule", { value: true });
75
75
  exports.SubscriptionManager = void 0;
76
+ var mongodb_1 = require("mongodb");
76
77
  var NodeCache = require("node-cache");
77
78
  var os_1 = require("os");
78
79
  var flag_collection_1 = require("../collections/flag.collection");
@@ -92,6 +93,7 @@ var user_groups_1 = require("../publications/user-groups");
92
93
  var user_guides_1 = require("../publications/user-guides");
93
94
  var resolveio_server_app_1 = require("../resolveio-server-app");
94
95
  var common_1 = require("../util/common");
96
+ var subscription_dependency_context_1 = require("../util/subscription-dependency-context");
95
97
  var numCPUs = (0, os_1.cpus)().length;
96
98
  var v8 = require('v8');
97
99
  // interface CurrentPerformanceMonitor {
@@ -114,6 +116,7 @@ var SubscriptionManager = /** @class */ (function () {
114
116
  this._cacheId = 1;
115
117
  this._heapSize = v8.getHeapStatistics() / numCPUs;
116
118
  this._enableDebug = false;
119
+ this._enableDependencyDebug = false;
117
120
  this._debugOplogCollections = [];
118
121
  this._debugOplogHits = 0;
119
122
  this._debugSubCollections = [];
@@ -156,7 +159,7 @@ var SubscriptionManager = /** @class */ (function () {
156
159
  };
157
160
  SubscriptionManager.prototype.initialize = function (wss, serverConfig, monitorManagerFunction) {
158
161
  return __awaiter(this, void 0, void 0, function () {
159
- var flag;
162
+ var flag, dependencyFlag;
160
163
  var _this = this;
161
164
  return __generator(this, function (_a) {
162
165
  switch (_a.label) {
@@ -307,12 +310,21 @@ var SubscriptionManager = /** @class */ (function () {
307
310
  return [4 /*yield*/, flag_collection_1.Flags.findOne({ type: 'Enable Debug' })];
308
311
  case 2:
309
312
  flag = _a.sent();
313
+ return [4 /*yield*/, flag_collection_1.Flags.findOne({ type: 'Enable Dependency Debug' })];
314
+ case 3:
315
+ dependencyFlag = _a.sent();
310
316
  if (flag && flag.value) {
311
317
  this._enableDebug = true;
312
318
  }
313
319
  else {
314
320
  this._enableDebug = false;
315
321
  }
322
+ if (dependencyFlag && dependencyFlag.value) {
323
+ this._enableDependencyDebug = true;
324
+ }
325
+ else {
326
+ this._enableDependencyDebug = process.env.ENABLE_DEPENDENCY_DEBUG === 'true';
327
+ }
316
328
  this.setCacheLimit();
317
329
  return [2 /*return*/];
318
330
  }
@@ -327,7 +339,7 @@ var SubscriptionManager = /** @class */ (function () {
327
339
  this._heapLimit = this._heapSize * 0.3; // Use 50% of total heap size
328
340
  }
329
341
  };
330
- SubscriptionManager.prototype.invalidatePubsCache = function (collection, type) {
342
+ SubscriptionManager.prototype.invalidatePubsCache = function (collection, type, documentId) {
331
343
  return __awaiter(this, void 0, void 0, function () {
332
344
  var debounceKey, now, firstInvalidationTime, waitedTooLong;
333
345
  var _this = this;
@@ -346,7 +358,7 @@ var SubscriptionManager = /** @class */ (function () {
346
358
  if (!waitedTooLong) return [3 /*break*/, 2];
347
359
  // Immediate execution path
348
360
  this._invalidationPendingTimestamps.delete(debounceKey);
349
- return [4 /*yield*/, this._executeInvalidation(collection, type)];
361
+ return [4 /*yield*/, this._executeInvalidation(collection, type, documentId)];
350
362
  case 1:
351
363
  _a.sent();
352
364
  return [3 /*break*/, 3];
@@ -357,7 +369,7 @@ var SubscriptionManager = /** @class */ (function () {
357
369
  switch (_a.label) {
358
370
  case 0:
359
371
  this._invalidationPendingTimestamps.delete(debounceKey);
360
- return [4 /*yield*/, this._executeInvalidation(collection, type)];
372
+ return [4 /*yield*/, this._executeInvalidation(collection, type, documentId)];
361
373
  case 1:
362
374
  _a.sent();
363
375
  return [2 /*return*/];
@@ -370,9 +382,9 @@ var SubscriptionManager = /** @class */ (function () {
370
382
  });
371
383
  });
372
384
  };
373
- SubscriptionManager.prototype._executeInvalidation = function (collection, type) {
385
+ SubscriptionManager.prototype._executeInvalidation = function (collection, type, documentId) {
374
386
  return __awaiter(this, void 0, void 0, function () {
375
- var collSubs, collSubs_1, collSubs_1_1, sub, _a, _b, client, ws, _c, e_1_1, e_2_1;
387
+ var collSubs, normalizedDocumentId, collSubs_1, collSubs_1_1, sub, _a, _b, client, ws, _c, e_1_1, e_2_1;
376
388
  var e_2, _d, e_1, _e;
377
389
  return __generator(this, function (_f) {
378
390
  switch (_f.label) {
@@ -385,76 +397,86 @@ var SubscriptionManager = /** @class */ (function () {
385
397
  // Original invalidation logic
386
398
  resolveio_server_app_1.ResolveIOServer.getMongoManager().invalidateQueryCache(collection);
387
399
  collSubs = this._subscriptions.filter(function (a) { return a.collections.includes(collection); });
400
+ normalizedDocumentId = this.normalizeDocumentId(documentId);
388
401
  _f.label = 1;
389
402
  case 1:
390
- _f.trys.push([1, 17, 18, 19]);
403
+ _f.trys.push([1, 18, 19, 20]);
391
404
  collSubs_1 = __values(collSubs), collSubs_1_1 = collSubs_1.next();
392
405
  _f.label = 2;
393
406
  case 2:
394
- if (!!collSubs_1_1.done) return [3 /*break*/, 16];
407
+ if (!!collSubs_1_1.done) return [3 /*break*/, 17];
395
408
  sub = collSubs_1_1.value;
396
409
  if (this._enableDebug) {
397
410
  console.log(new Date(), 'Invalidate Sub', sub.publication, sub.running, sub.runAgain);
398
411
  }
412
+ return [4 /*yield*/, this.shouldInvalidateSubscription(sub, collection, type, normalizedDocumentId)];
413
+ case 3:
414
+ if (!(_f.sent())) {
415
+ return [3 /*break*/, 16];
416
+ }
399
417
  if (sub.running) {
400
418
  sub.runAgain = true;
401
- return [3 /*break*/, 15];
419
+ this.dependencyDebug('Subscription busy, scheduling rerun', { publication: sub.publication, collection: collection, type: type });
420
+ return [3 /*break*/, 16];
402
421
  }
403
- if (!this._publications[sub.publication].user_specific) return [3 /*break*/, 13];
404
- _f.label = 3;
405
- case 3:
406
- _f.trys.push([3, 10, 11, 12]);
407
- _a = (e_1 = void 0, __values(sub.clients)), _b = _a.next();
422
+ 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 });
408
424
  _f.label = 4;
409
425
  case 4:
410
- if (!!_b.done) return [3 /*break*/, 9];
411
- client = _b.value;
412
- ws = this._websocketManager.getWebSocket(client.id_socket);
413
- if (!((ws === null || ws === void 0 ? void 0 : ws.readyState) === ws.OPEN)) return [3 /*break*/, 8];
426
+ _f.trys.push([4, 11, 12, 13]);
427
+ _a = (e_1 = void 0, __values(sub.clients)), _b = _a.next();
414
428
  _f.label = 5;
415
429
  case 5:
416
- _f.trys.push([5, 7, , 8]);
417
- return [4 /*yield*/, this.sendDataToOneWithRetry(ws, client.messageId, sub, collection, type)];
430
+ if (!!_b.done) return [3 /*break*/, 10];
431
+ client = _b.value;
432
+ ws = this._websocketManager.getWebSocket(client.id_socket);
433
+ if (!((ws === null || ws === void 0 ? void 0 : ws.readyState) === ws.OPEN)) return [3 /*break*/, 9];
434
+ _f.label = 6;
418
435
  case 6:
419
- _f.sent();
420
- return [3 /*break*/, 8];
436
+ _f.trys.push([6, 8, , 9]);
437
+ return [4 /*yield*/, this.sendDataToOneWithRetry(ws, client.messageId, sub, collection, type)];
421
438
  case 7:
422
- _c = _f.sent();
423
- return [3 /*break*/, 8];
439
+ _f.sent();
440
+ return [3 /*break*/, 9];
424
441
  case 8:
442
+ _c = _f.sent();
443
+ return [3 /*break*/, 9];
444
+ case 9:
425
445
  _b = _a.next();
426
- return [3 /*break*/, 4];
427
- case 9: return [3 /*break*/, 12];
428
- case 10:
446
+ return [3 /*break*/, 5];
447
+ case 10: return [3 /*break*/, 13];
448
+ case 11:
429
449
  e_1_1 = _f.sent();
430
450
  e_1 = { error: e_1_1 };
431
- return [3 /*break*/, 12];
432
- case 11:
451
+ return [3 /*break*/, 13];
452
+ case 12:
433
453
  try {
434
454
  if (_b && !_b.done && (_e = _a.return)) _e.call(_a);
435
455
  }
436
456
  finally { if (e_1) throw e_1.error; }
437
457
  return [7 /*endfinally*/];
438
- case 12: return [3 /*break*/, 15];
439
- case 13: return [4 /*yield*/, this.sendDataToAllWithRetry(sub, collection, type)];
458
+ case 13: return [3 /*break*/, 16];
440
459
  case 14:
441
- _f.sent();
442
- _f.label = 15;
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)];
443
462
  case 15:
463
+ _f.sent();
464
+ _f.label = 16;
465
+ case 16:
444
466
  collSubs_1_1 = collSubs_1.next();
445
467
  return [3 /*break*/, 2];
446
- case 16: return [3 /*break*/, 19];
447
- case 17:
468
+ case 17: return [3 /*break*/, 20];
469
+ case 18:
448
470
  e_2_1 = _f.sent();
449
471
  e_2 = { error: e_2_1 };
450
- return [3 /*break*/, 19];
451
- case 18:
472
+ return [3 /*break*/, 20];
473
+ case 19:
452
474
  try {
453
475
  if (collSubs_1_1 && !collSubs_1_1.done && (_d = collSubs_1.return)) _d.call(collSubs_1);
454
476
  }
455
477
  finally { if (e_2) throw e_2.error; }
456
478
  return [7 /*endfinally*/];
457
- case 19: return [2 /*return*/];
479
+ case 20: return [2 /*return*/];
458
480
  }
459
481
  });
460
482
  });
@@ -694,12 +716,16 @@ var SubscriptionManager = /** @class */ (function () {
694
716
  }],
695
717
  cacheId: 0,
696
718
  running: false,
697
- runAgain: false
719
+ runAgain: false,
720
+ collectionDependencies: new Map(),
721
+ collectionFilters: new Map(),
722
+ watchAllCollections: new Set()
698
723
  });
699
724
  }
700
725
  if (!sub) {
701
726
  sub = this._subscriptions.find(function (a) { return a.publication === publication && a.subscriptionKey === subscriptionKey_1; });
702
727
  }
728
+ this.ensureDependencyContainers(sub);
703
729
  if (this._enableDebug) {
704
730
  console.log(new Date(), 'New Sub', sub.publication, sub.running, sub.runAgain, sub.clients.length);
705
731
  }
@@ -894,11 +920,11 @@ var SubscriptionManager = /** @class */ (function () {
894
920
  case 11:
895
921
  console.log(new Date(), 'oplog started');
896
922
  this._oplog$.on('change', function (doc) { return __awaiter(_this, void 0, void 0, function () {
897
- var collection, flag;
923
+ var collection, docId, flag, dependencyFlag;
898
924
  return __generator(this, function (_a) {
899
925
  switch (_a.label) {
900
926
  case 0:
901
- if (!doc.ns) return [3 /*break*/, 13];
927
+ if (!doc.ns) return [3 /*break*/, 14];
902
928
  if (this._enableDebug) {
903
929
  console.log(new Date(), 'Oplog Hit', doc.ns);
904
930
  }
@@ -915,17 +941,18 @@ var SubscriptionManager = /** @class */ (function () {
915
941
  }
916
942
  if (!collection) return [3 /*break*/, 10];
917
943
  this._debugOplogHits += 1;
944
+ docId = doc.documentKey && doc.documentKey['_id'] !== undefined ? doc.documentKey['_id'] : (doc['fullDocument'] && doc['fullDocument']['_id'] !== undefined ? doc['fullDocument']['_id'] : null);
918
945
  if (!(doc.operationType === 'insert')) return [3 /*break*/, 5];
919
946
  if (!(collection === 'support-tickets')) return [3 /*break*/, 2];
920
947
  if (!(this.serverConfig['ROOT_URL'] === 'https://resolveio.com')) return [3 /*break*/, 2];
921
948
  resolveio_server_app_1.ResolveIOServer.getMainServer().getMethodManager().callMethod.call(resolveio_server_app_1.ResolveIOServer.getMainServer().getMethodManager(), 'sendSupportTicketEmail', doc.documentKey['_id']);
922
- return [4 /*yield*/, this.invalidatePubsCache(collection, 'insert')];
949
+ return [4 /*yield*/, this.invalidatePubsCache(collection, 'insert', docId)];
923
950
  case 1:
924
951
  _a.sent();
925
952
  _a.label = 2;
926
953
  case 2:
927
954
  if (!(collection !== 'method-responses')) return [3 /*break*/, 4];
928
- return [4 /*yield*/, this.invalidatePubsCache(collection, 'insert')];
955
+ return [4 /*yield*/, this.invalidatePubsCache(collection, 'insert', docId)];
929
956
  case 3:
930
957
  _a.sent();
931
958
  _a.label = 4;
@@ -933,7 +960,7 @@ var SubscriptionManager = /** @class */ (function () {
933
960
  case 5:
934
961
  if (!(doc.operationType === 'update' || doc.operationType === 'replace')) return [3 /*break*/, 8];
935
962
  if (!(collection !== 'method-responses')) return [3 /*break*/, 7];
936
- return [4 /*yield*/, this.invalidatePubsCache(collection, 'update')];
963
+ return [4 /*yield*/, this.invalidatePubsCache(collection, 'update', docId)];
937
964
  case 6:
938
965
  _a.sent();
939
966
  _a.label = 7;
@@ -941,28 +968,37 @@ var SubscriptionManager = /** @class */ (function () {
941
968
  case 8:
942
969
  if (!(doc.operationType === 'delete')) return [3 /*break*/, 10];
943
970
  if (!(collection !== 'method-responses')) return [3 /*break*/, 10];
944
- return [4 /*yield*/, this.invalidatePubsCache(collection, 'delete')];
971
+ return [4 /*yield*/, this.invalidatePubsCache(collection, 'delete', docId)];
945
972
  case 9:
946
973
  _a.sent();
947
974
  _a.label = 10;
948
975
  case 10:
949
- if (!(collection === 'flags')) return [3 /*break*/, 12];
976
+ if (!(collection === 'flags')) return [3 /*break*/, 13];
950
977
  return [4 /*yield*/, flag_collection_1.Flags.findOne({ type: 'Enable Debug' })];
951
978
  case 11:
952
979
  flag = _a.sent();
980
+ return [4 /*yield*/, flag_collection_1.Flags.findOne({ type: 'Enable Dependency Debug' })];
981
+ case 12:
982
+ dependencyFlag = _a.sent();
953
983
  if (flag && flag.value) {
954
984
  this._enableDebug = true;
955
985
  }
956
986
  else {
957
987
  this._enableDebug = false;
958
988
  }
959
- _a.label = 12;
960
- case 12:
989
+ if (dependencyFlag && dependencyFlag.value) {
990
+ this._enableDependencyDebug = true;
991
+ }
992
+ else {
993
+ this._enableDependencyDebug = process.env.ENABLE_DEPENDENCY_DEBUG === 'true';
994
+ }
995
+ _a.label = 13;
996
+ case 13:
961
997
  lastResumeToken_1 = doc._id;
962
998
  if ((!process.env.NODE_APP_INSTANCE || process.env.NODE_APP_INSTANCE === '0') && (process.env.IS_WORKERS_ENABLED === 'false' || (process.env.IS_WORKER_INSTANCE === 'true' && process.env.WORKER_INDEX === '0'))) {
963
999
  }
964
- _a.label = 13;
965
- case 13: return [2 /*return*/];
1000
+ _a.label = 14;
1001
+ case 14: return [2 /*return*/];
966
1002
  }
967
1003
  });
968
1004
  }); });
@@ -1071,19 +1107,25 @@ var SubscriptionManager = /** @class */ (function () {
1071
1107
  };
1072
1108
  SubscriptionManager.prototype.sendDataToOne = function (ws, messageId, sub, collection, type) {
1073
1109
  return __awaiter(this, void 0, void 0, function () {
1074
- var monitor, res, serverRes, err_1, serverRes;
1075
- var _a;
1076
- return __generator(this, function (_b) {
1077
- switch (_b.label) {
1110
+ var monitor, dependencySnapshot, res, execution, serverRes, err_1, serverRes;
1111
+ var _this = this;
1112
+ return __generator(this, function (_a) {
1113
+ switch (_a.label) {
1078
1114
  case 0:
1079
1115
  monitor = this._monitorManagerFunction.startMonitorFunction('User Specific Publication', sub.publication, '', '', sub.subscriptionData);
1080
- _b.label = 1;
1116
+ _a.label = 1;
1081
1117
  case 1:
1082
- _b.trys.push([1, 3, 5, 7]);
1118
+ _a.trys.push([1, 3, 5, 7]);
1083
1119
  resolveio_server_app_1.ResolveIOServer.getMainServer().getMethodManager().callMethod.call(resolveio_server_app_1.ResolveIOServer.getMainServer().getMethodManager(), 'insertSubscriptionLog', type, sub.publication, collection, JSON.stringify(sub.subscriptionData));
1084
- return [4 /*yield*/, (_a = this._publications[sub.publication].function).call.apply(_a, __spreadArray([Object.assign({}, this, SubscriptionManager.prototype), ws['id_user']], __read(sub.subscriptionData), false))];
1120
+ return [4 /*yield*/, (0, subscription_dependency_context_1.withDependencyTracking)(function () {
1121
+ var _a;
1122
+ return (_a = _this._publications[sub.publication].function).call.apply(_a, __spreadArray([Object.assign({}, _this, SubscriptionManager.prototype), ws['id_user']], __read(sub.subscriptionData), false));
1123
+ })];
1085
1124
  case 2:
1086
- res = _b.sent();
1125
+ execution = _a.sent();
1126
+ res = execution.result;
1127
+ dependencySnapshot = execution.snapshot;
1128
+ this.updateSubscriptionDependencies(sub, dependencySnapshot);
1087
1129
  serverRes = {
1088
1130
  messageId: messageId,
1089
1131
  hasError: false,
@@ -1092,7 +1134,7 @@ var SubscriptionManager = /** @class */ (function () {
1092
1134
  this.sendWS(ws, serverRes);
1093
1135
  return [3 /*break*/, 7];
1094
1136
  case 3:
1095
- err_1 = _b.sent();
1137
+ err_1 = _a.sent();
1096
1138
  serverRes = {
1097
1139
  messageId: messageId,
1098
1140
  hasError: true,
@@ -1101,11 +1143,11 @@ var SubscriptionManager = /** @class */ (function () {
1101
1143
  this.sendWS(ws, serverRes);
1102
1144
  return [4 /*yield*/, resolveio_server_app_1.ResolveIOServer.getMainServer().getMethodManager().sendEmail('dev@resolveio.com', 'SERVER - Error Detected - ' + this.serverConfig['CLIENT_NAME'], 'Error Detected During Subscription ' + sub.publication + ' - (sendDataToOne - WS)\n\nData \n' + JSON.stringify(sub.subscriptionData, null, 2) + '\n\nErrors\n' + JSON.stringify(err_1, null, 2))];
1103
1145
  case 4:
1104
- _b.sent();
1146
+ _a.sent();
1105
1147
  return [3 /*break*/, 7];
1106
1148
  case 5: return [4 /*yield*/, this._monitorManagerFunction.finishMonitorFunction(monitor)];
1107
1149
  case 6:
1108
- _b.sent();
1150
+ _a.sent();
1109
1151
  return [7 /*endfinally*/];
1110
1152
  case 7: return [2 /*return*/];
1111
1153
  }
@@ -1115,11 +1157,11 @@ var SubscriptionManager = /** @class */ (function () {
1115
1157
  // Fetch pub once, send to all clients linked to this pub
1116
1158
  SubscriptionManager.prototype.sendDataToAll = function (sub, collection, type) {
1117
1159
  return __awaiter(this, void 0, void 0, function () {
1118
- var subIndex, monitor, res_1, cacheData, _a, _b, client, ws, serverRes, _c, _d, client, ws, serverRes, nodeCacheSize, deleteCount, subArr, zz, err_2, _e, _f, client, ws, serverRes;
1119
- var _g, e_3, _h, e_4, _j, e_5, _k;
1160
+ var subIndex, monitor, res_1, dependencySnapshot, execution, cacheData, _a, _b, client, ws, serverRes, _c, _d, client, ws, serverRes, nodeCacheSize, deleteCount, subArr, zz, err_2, _e, _f, client, ws, serverRes;
1161
+ var e_3, _g, e_4, _h, e_5, _j;
1120
1162
  var _this = this;
1121
- return __generator(this, function (_l) {
1122
- switch (_l.label) {
1163
+ return __generator(this, function (_k) {
1164
+ switch (_k.label) {
1123
1165
  case 0:
1124
1166
  if (!!sub.clients.length) return [3 /*break*/, 1];
1125
1167
  if (sub.cacheId) {
@@ -1133,15 +1175,22 @@ var SubscriptionManager = /** @class */ (function () {
1133
1175
  return [2 /*return*/];
1134
1176
  case 1:
1135
1177
  monitor = this._monitorManagerFunction.startMonitorFunction('Publication', sub.publication, '', '', sub.subscriptionData);
1136
- _l.label = 2;
1178
+ dependencySnapshot = void 0;
1179
+ _k.label = 2;
1137
1180
  case 2:
1138
- _l.trys.push([2, 4, 6, 8]);
1181
+ _k.trys.push([2, 4, 6, 8]);
1139
1182
  if (sub.publication !== 'superadminAPM' && sub.publication !== 'loggedInUsers') {
1140
1183
  resolveio_server_app_1.ResolveIOServer.getMainServer().getMethodManager().callMethod.call(resolveio_server_app_1.ResolveIOServer.getMainServer().getMethodManager(), 'insertSubscriptionLog', type, sub.publication, collection, JSON.stringify(sub.subscriptionData));
1141
1184
  }
1142
- return [4 /*yield*/, (_g = this._publications[sub.publication].function).call.apply(_g, __spreadArray([Object.assign({}, this, SubscriptionManager.prototype)], __read(sub.subscriptionData), false))];
1185
+ return [4 /*yield*/, (0, subscription_dependency_context_1.withDependencyTracking)(function () {
1186
+ var _a;
1187
+ return (_a = _this._publications[sub.publication].function).call.apply(_a, __spreadArray([Object.assign({}, _this, SubscriptionManager.prototype)], __read(sub.subscriptionData), false));
1188
+ })];
1143
1189
  case 3:
1144
- res_1 = _l.sent();
1190
+ execution = _k.sent();
1191
+ res_1 = execution.result;
1192
+ dependencySnapshot = execution.snapshot;
1193
+ this.updateSubscriptionDependencies(sub, dependencySnapshot);
1145
1194
  if (sub.cacheId) {
1146
1195
  try {
1147
1196
  cacheData = JSON.parse(this._nodeCache.get(sub.cacheId), common_1.dateReviver);
@@ -1163,7 +1212,7 @@ var SubscriptionManager = /** @class */ (function () {
1163
1212
  catch (e_3_1) { e_3 = { error: e_3_1 }; }
1164
1213
  finally {
1165
1214
  try {
1166
- if (_b && !_b.done && (_h = _a.return)) _h.call(_a);
1215
+ if (_b && !_b.done && (_g = _a.return)) _g.call(_a);
1167
1216
  }
1168
1217
  finally { if (e_3) throw e_3.error; }
1169
1218
  }
@@ -1179,7 +1228,7 @@ var SubscriptionManager = /** @class */ (function () {
1179
1228
  }
1180
1229
  }
1181
1230
  }
1182
- catch (_m) {
1231
+ catch (_l) {
1183
1232
  sub.clients.map(function (client) {
1184
1233
  var ws = _this._websocketManager.getWebSocket(client.id_socket);
1185
1234
  if (ws && ws.readyState === ws.OPEN) {
@@ -1221,7 +1270,7 @@ var SubscriptionManager = /** @class */ (function () {
1221
1270
  catch (e_4_1) { e_4 = { error: e_4_1 }; }
1222
1271
  finally {
1223
1272
  try {
1224
- if (_d && !_d.done && (_j = _c.return)) _j.call(_c);
1273
+ if (_d && !_d.done && (_h = _c.return)) _h.call(_c);
1225
1274
  }
1226
1275
  finally { if (e_4) throw e_4.error; }
1227
1276
  }
@@ -1261,7 +1310,7 @@ var SubscriptionManager = /** @class */ (function () {
1261
1310
  }
1262
1311
  return [3 /*break*/, 8];
1263
1312
  case 4:
1264
- err_2 = _l.sent();
1313
+ err_2 = _k.sent();
1265
1314
  try {
1266
1315
  for (_e = __values(sub.clients), _f = _e.next(); !_f.done; _f = _e.next()) {
1267
1316
  client = _f.value;
@@ -1279,29 +1328,215 @@ var SubscriptionManager = /** @class */ (function () {
1279
1328
  catch (e_5_1) { e_5 = { error: e_5_1 }; }
1280
1329
  finally {
1281
1330
  try {
1282
- if (_f && !_f.done && (_k = _e.return)) _k.call(_e);
1331
+ if (_f && !_f.done && (_j = _e.return)) _j.call(_e);
1283
1332
  }
1284
1333
  finally { if (e_5) throw e_5.error; }
1285
1334
  }
1286
1335
  return [4 /*yield*/, resolveio_server_app_1.ResolveIOServer.getMainServer().getMethodManager().sendEmail('dev@resolveio.com', 'SERVER - Error Detected - ' + this.serverConfig['CLIENT_NAME'], 'Error Detected During Subscription ' + sub.publication + ' - (sendPubData)\n\nData \n' + JSON.stringify(sub.subscriptionData, null, 2) + '\n\nErrors\n' + JSON.stringify(err_2, null, 2))];
1287
1336
  case 5:
1288
- _l.sent();
1337
+ _k.sent();
1289
1338
  return [3 /*break*/, 8];
1290
1339
  case 6: return [4 /*yield*/, this._monitorManagerFunction.finishMonitorFunction(monitor)];
1291
1340
  case 7:
1292
- _l.sent();
1341
+ _k.sent();
1293
1342
  return [7 /*endfinally*/];
1294
1343
  case 8: return [2 /*return*/];
1295
1344
  }
1296
1345
  });
1297
1346
  });
1298
1347
  };
1348
+ SubscriptionManager.prototype.ensureDependencyContainers = function (sub) {
1349
+ if (!sub.collectionDependencies) {
1350
+ sub.collectionDependencies = new Map();
1351
+ }
1352
+ if (!sub.collectionFilters) {
1353
+ sub.collectionFilters = new Map();
1354
+ }
1355
+ if (!sub.watchAllCollections) {
1356
+ sub.watchAllCollections = new Set();
1357
+ }
1358
+ };
1359
+ SubscriptionManager.prototype.updateSubscriptionDependencies = function (sub, snapshot) {
1360
+ this.ensureDependencyContainers(sub);
1361
+ if (!snapshot) {
1362
+ sub.collectionDependencies.clear();
1363
+ sub.collectionFilters.clear();
1364
+ sub.watchAllCollections.clear();
1365
+ this.dependencyDebug('Cleared dependency snapshot', { publication: sub.publication });
1366
+ return;
1367
+ }
1368
+ sub.collectionDependencies = snapshot.dependencies;
1369
+ sub.collectionFilters = snapshot.filters;
1370
+ sub.watchAllCollections = snapshot.watchAllCollections;
1371
+ this.logDependencySnapshot(sub, 'Snapshot updated');
1372
+ };
1373
+ SubscriptionManager.prototype.normalizeDocumentId = function (rawId) {
1374
+ if (rawId === null || rawId === undefined) {
1375
+ return null;
1376
+ }
1377
+ if (typeof rawId === 'string') {
1378
+ return rawId;
1379
+ }
1380
+ if (typeof rawId === 'object' && typeof rawId.toHexString === 'function') {
1381
+ return rawId.toHexString();
1382
+ }
1383
+ if (typeof (rawId === null || rawId === void 0 ? void 0 : rawId.toString) === 'function') {
1384
+ var str = rawId.toString();
1385
+ if (str && str !== '[object Object]') {
1386
+ return str;
1387
+ }
1388
+ }
1389
+ return null;
1390
+ };
1391
+ SubscriptionManager.prototype.convertDocumentIdForQuery = function (documentId) {
1392
+ if (!documentId) {
1393
+ return documentId;
1394
+ }
1395
+ if (/^[a-fA-F0-9]{24}$/.test(documentId)) {
1396
+ try {
1397
+ return new mongodb_1.ObjectId(documentId);
1398
+ }
1399
+ catch (_a) { }
1400
+ }
1401
+ return documentId;
1402
+ };
1403
+ SubscriptionManager.prototype.documentMatchesFilter = function (collection, documentId, filter) {
1404
+ return __awaiter(this, void 0, void 0, function () {
1405
+ var db, filterCopy, idValue, combinedFilter, doc, _a;
1406
+ return __generator(this, function (_b) {
1407
+ switch (_b.label) {
1408
+ case 0:
1409
+ _b.trys.push([0, 2, , 3]);
1410
+ db = resolveio_server_app_1.ResolveIOServer.getMainDB();
1411
+ filterCopy = (0, common_1.deepCopy)(filter) || {};
1412
+ idValue = this.convertDocumentIdForQuery(documentId);
1413
+ combinedFilter = {
1414
+ $and: [
1415
+ { _id: idValue },
1416
+ filterCopy
1417
+ ]
1418
+ };
1419
+ return [4 /*yield*/, db.collection(collection).findOne(combinedFilter)];
1420
+ case 1:
1421
+ doc = _b.sent();
1422
+ return [2 /*return*/, !!doc];
1423
+ case 2:
1424
+ _a = _b.sent();
1425
+ return [2 /*return*/, true];
1426
+ case 3: return [2 /*return*/];
1427
+ }
1428
+ });
1429
+ });
1430
+ };
1431
+ SubscriptionManager.prototype.shouldInvalidateSubscription = function (sub, collection, type, documentId) {
1432
+ return __awaiter(this, void 0, void 0, function () {
1433
+ var trackedIds, filters, filters_1, filters_1_1, filter, e_6_1;
1434
+ var e_6, _a;
1435
+ return __generator(this, function (_b) {
1436
+ switch (_b.label) {
1437
+ case 0:
1438
+ this.ensureDependencyContainers(sub);
1439
+ if (!documentId) {
1440
+ this.dependencyDebug('Invalidate due to missing documentId', { publication: sub.publication, collection: collection, type: type });
1441
+ return [2 /*return*/, true];
1442
+ }
1443
+ if (sub.watchAllCollections.has(collection)) {
1444
+ this.dependencyDebug('Invalidate due to watch-all collection', { publication: sub.publication, collection: collection, type: type });
1445
+ return [2 /*return*/, true];
1446
+ }
1447
+ trackedIds = sub.collectionDependencies.get(collection);
1448
+ if (trackedIds && trackedIds.has(documentId)) {
1449
+ this.dependencyDebug('Invalidate due to tracked id', { publication: sub.publication, collection: collection, type: type, documentId: documentId });
1450
+ return [2 /*return*/, true];
1451
+ }
1452
+ if (type === 'delete') {
1453
+ this.dependencyDebug('Skip invalidation on delete for unknown id', { publication: sub.publication, collection: collection, type: type, documentId: documentId });
1454
+ return [2 /*return*/, false];
1455
+ }
1456
+ filters = sub.collectionFilters.get(collection);
1457
+ if (!(filters && filters.length)) return [3 /*break*/, 8];
1458
+ _b.label = 1;
1459
+ case 1:
1460
+ _b.trys.push([1, 6, 7, 8]);
1461
+ filters_1 = __values(filters), filters_1_1 = filters_1.next();
1462
+ _b.label = 2;
1463
+ case 2:
1464
+ if (!!filters_1_1.done) return [3 /*break*/, 5];
1465
+ filter = filters_1_1.value;
1466
+ return [4 /*yield*/, this.documentMatchesFilter(collection, documentId, filter)];
1467
+ case 3:
1468
+ if (_b.sent()) {
1469
+ this.dependencyDebug('Invalidate due to filter match', { publication: sub.publication, collection: collection, type: type, documentId: documentId, filter: filter });
1470
+ return [2 /*return*/, true];
1471
+ }
1472
+ _b.label = 4;
1473
+ case 4:
1474
+ filters_1_1 = filters_1.next();
1475
+ return [3 /*break*/, 2];
1476
+ case 5: return [3 /*break*/, 8];
1477
+ case 6:
1478
+ e_6_1 = _b.sent();
1479
+ e_6 = { error: e_6_1 };
1480
+ return [3 /*break*/, 8];
1481
+ case 7:
1482
+ try {
1483
+ if (filters_1_1 && !filters_1_1.done && (_a = filters_1.return)) _a.call(filters_1);
1484
+ }
1485
+ finally { if (e_6) throw e_6.error; }
1486
+ return [7 /*endfinally*/];
1487
+ case 8:
1488
+ this.dependencyDebug('Skip invalidation after dependency checks', { publication: sub.publication, collection: collection, type: type, documentId: documentId });
1489
+ return [2 /*return*/, false];
1490
+ }
1491
+ });
1492
+ });
1493
+ };
1299
1494
  SubscriptionManager.prototype.sendWS = function (ws, data) {
1300
1495
  this._websocketManager.send(ws, data);
1301
1496
  };
1302
1497
  SubscriptionManager.prototype.getEnableDebug = function () {
1303
1498
  return this._enableDebug;
1304
1499
  };
1500
+ SubscriptionManager.prototype.dependencyDebug = function (message, details) {
1501
+ if (!this._enableDependencyDebug) {
1502
+ return;
1503
+ }
1504
+ if (details) {
1505
+ console.log(new Date(), '[Dependency Debug]', message, JSON.stringify(details, null, 2));
1506
+ }
1507
+ else {
1508
+ console.log(new Date(), '[Dependency Debug]', message);
1509
+ }
1510
+ };
1511
+ SubscriptionManager.prototype.logDependencySnapshot = function (sub, context) {
1512
+ if (!this._enableDependencyDebug) {
1513
+ return;
1514
+ }
1515
+ var dependencySummary = Array.from(sub.collectionDependencies.entries()).map(function (_a) {
1516
+ var _b = __read(_a, 2), collectionName = _b[0], ids = _b[1];
1517
+ var idList = Array.from(ids || []);
1518
+ return {
1519
+ collection: collectionName,
1520
+ count: idList.length,
1521
+ sample: idList.slice(0, 10)
1522
+ };
1523
+ });
1524
+ var filterSummary = Array.from(sub.collectionFilters.entries()).map(function (_a) {
1525
+ var _b = __read(_a, 2), collectionName = _b[0], filters = _b[1];
1526
+ return ({
1527
+ collection: collectionName,
1528
+ count: filters.length
1529
+ });
1530
+ });
1531
+ var watchAll = Array.from(sub.watchAllCollections || []);
1532
+ this.dependencyDebug('Dependency snapshot updated', {
1533
+ context: context,
1534
+ publication: sub.publication,
1535
+ dependencies: dependencySummary,
1536
+ collectionsWithFilters: filterSummary,
1537
+ watchAll: watchAll
1538
+ });
1539
+ };
1305
1540
  return SubscriptionManager;
1306
1541
  }());
1307
1542
  exports.SubscriptionManager = SubscriptionManager;