@resolveio/server-lib 20.14.15 → 20.14.17

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.
@@ -49,6 +49,7 @@ export declare class SubscriptionManager {
49
49
  private readonly LATENCY_UPDATE_INTERVAL;
50
50
  private readonly LATENCY_UPDATE_THRESHOLD_MS;
51
51
  private readonly LATENCY_DEBUG_THRESHOLD_MS;
52
+ private readonly PUBLICATION_DEBUG_THRESHOLD_MS;
52
53
  private _invalidationDebounceTimers;
53
54
  private _invalidationPendingTimestamps;
54
55
  private _pendingInvalidations;
@@ -92,6 +93,11 @@ export declare class SubscriptionManager {
92
93
  private queueFullResync;
93
94
  private fullResyncSubscriptions;
94
95
  private tailOpLog;
96
+ private packCachePayload;
97
+ private decodeCachePayload;
98
+ private getCacheBuffer;
99
+ private shouldCachePayload;
100
+ private buffersEqual;
95
101
  private processSubscription;
96
102
  private sendDataToOne;
97
103
  private sendDataToAll;
@@ -74,6 +74,7 @@ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
74
74
  Object.defineProperty(exports, "__esModule", { value: true });
75
75
  exports.SubscriptionManager = void 0;
76
76
  var NodeCache = require("node-cache");
77
+ var msgpackr_1 = require("msgpackr");
77
78
  var flag_collection_1 = require("../collections/flag.collection");
78
79
  var logged_in_users_collection_1 = require("../collections/logged-in-users.collection");
79
80
  var app_status_1 = require("../publications/app-status");
@@ -160,6 +161,7 @@ var SubscriptionManager = /** @class */ (function () {
160
161
  // Minimum time difference between two latency updates for the same user
161
162
  this.LATENCY_UPDATE_THRESHOLD_MS = 30000;
162
163
  this.LATENCY_DEBUG_THRESHOLD_MS = 1000;
164
+ this.PUBLICATION_DEBUG_THRESHOLD_MS = 300;
163
165
  // private currentPerfomanceMonitor: CurrentPerformanceMonitor[] = [];
164
166
  // private idPerformance: number = 0;
165
167
  // private performanceThread;
@@ -1678,6 +1680,108 @@ var SubscriptionManager = /** @class */ (function () {
1678
1680
  });
1679
1681
  });
1680
1682
  };
1683
+ SubscriptionManager.prototype.packCachePayload = function (data) {
1684
+ if (data === undefined) {
1685
+ return null;
1686
+ }
1687
+ try {
1688
+ var packed = (0, msgpackr_1.pack)(data);
1689
+ return Buffer.isBuffer(packed) ? packed : Buffer.from(packed);
1690
+ }
1691
+ catch (err) {
1692
+ if (this._enableDebug) {
1693
+ console.log(new Date(), 'Sub Cache', 'Pack Failed', (err === null || err === void 0 ? void 0 : err.message) || err);
1694
+ }
1695
+ return null;
1696
+ }
1697
+ };
1698
+ SubscriptionManager.prototype.decodeCachePayload = function (raw) {
1699
+ if (!raw) {
1700
+ return null;
1701
+ }
1702
+ if (Buffer.isBuffer(raw)) {
1703
+ try {
1704
+ return (0, msgpackr_1.unpack)(raw);
1705
+ }
1706
+ catch (err) {
1707
+ if (this._enableDebug) {
1708
+ console.log(new Date(), 'Sub Cache', 'Unpack Failed', (err === null || err === void 0 ? void 0 : err.message) || err);
1709
+ }
1710
+ return null;
1711
+ }
1712
+ }
1713
+ if (raw instanceof Uint8Array) {
1714
+ try {
1715
+ return (0, msgpackr_1.unpack)(raw);
1716
+ }
1717
+ catch (err) {
1718
+ if (this._enableDebug) {
1719
+ console.log(new Date(), 'Sub Cache', 'Unpack Failed', (err === null || err === void 0 ? void 0 : err.message) || err);
1720
+ }
1721
+ return null;
1722
+ }
1723
+ }
1724
+ if (raw instanceof ArrayBuffer) {
1725
+ try {
1726
+ return (0, msgpackr_1.unpack)(new Uint8Array(raw));
1727
+ }
1728
+ catch (err) {
1729
+ if (this._enableDebug) {
1730
+ console.log(new Date(), 'Sub Cache', 'Unpack Failed', (err === null || err === void 0 ? void 0 : err.message) || err);
1731
+ }
1732
+ return null;
1733
+ }
1734
+ }
1735
+ // Treat legacy string caches as invalid to avoid JSON parsing in the hot path.
1736
+ if (typeof raw === 'string') {
1737
+ return null;
1738
+ }
1739
+ return raw;
1740
+ };
1741
+ SubscriptionManager.prototype.getCacheBuffer = function (raw) {
1742
+ if (!raw) {
1743
+ return null;
1744
+ }
1745
+ if (Buffer.isBuffer(raw)) {
1746
+ return raw;
1747
+ }
1748
+ if (raw instanceof Uint8Array) {
1749
+ return Buffer.from(raw);
1750
+ }
1751
+ if (raw instanceof ArrayBuffer) {
1752
+ return Buffer.from(new Uint8Array(raw));
1753
+ }
1754
+ return null;
1755
+ };
1756
+ SubscriptionManager.prototype.shouldCachePayload = function (sub, payload) {
1757
+ if (!payload || payload.byteLength >= 1000000) {
1758
+ return false;
1759
+ }
1760
+ if (sub.collections.includes('logs')) {
1761
+ return false;
1762
+ }
1763
+ if (sub.collections.find(function (a) { return a.endsWith('.versions'); })) {
1764
+ return false;
1765
+ }
1766
+ if (sub.collections.find(function (a) { return a.startsWith('monitor-'); })) {
1767
+ return false;
1768
+ }
1769
+ return true;
1770
+ };
1771
+ SubscriptionManager.prototype.buffersEqual = function (a, b) {
1772
+ if (!a || !b) {
1773
+ return false;
1774
+ }
1775
+ if (a.byteLength !== b.byteLength) {
1776
+ return false;
1777
+ }
1778
+ for (var index = 0; index < a.byteLength; index++) {
1779
+ if (a[index] !== b[index]) {
1780
+ return false;
1781
+ }
1782
+ }
1783
+ return true;
1784
+ };
1681
1785
  SubscriptionManager.prototype.processSubscription = function (sub, ws, messageId) {
1682
1786
  return __awaiter(this, void 0, void 0, function () {
1683
1787
  var cacheData, serverRes, _a;
@@ -1689,7 +1793,10 @@ var SubscriptionManager = /** @class */ (function () {
1689
1793
  _b.label = 1;
1690
1794
  case 1:
1691
1795
  _b.trys.push([1, 2, , 4]);
1692
- cacheData = JSON.parse(this._nodeCache.get(sub.cacheId), common_1.dateReviver);
1796
+ cacheData = this.decodeCachePayload(this._nodeCache.get(sub.cacheId));
1797
+ if (cacheData === null || cacheData === undefined) {
1798
+ throw new Error('cache-miss');
1799
+ }
1693
1800
  serverRes = {
1694
1801
  messageId: messageId,
1695
1802
  hasError: false,
@@ -1739,12 +1846,13 @@ var SubscriptionManager = /** @class */ (function () {
1739
1846
  };
1740
1847
  SubscriptionManager.prototype.sendDataToOne = function (ws, messageId, sub, collection, type) {
1741
1848
  return __awaiter(this, void 0, void 0, function () {
1742
- var monitor, dependencySnapshot, res, execution, serverRes, err_1, _a, normalizedError, correlationId, serverRes, errorPayload;
1849
+ var startMs, monitor, dependencySnapshot, res, execution, serverRes, err_1, _a, normalizedError, correlationId, serverRes, errorPayload, durationMs;
1743
1850
  var _this = this;
1744
1851
  var _b;
1745
1852
  return __generator(this, function (_c) {
1746
1853
  switch (_c.label) {
1747
1854
  case 0:
1855
+ startMs = Date.now();
1748
1856
  monitor = this._monitorManagerFunction.startMonitorFunction('User Specific Publication', sub.publication, '', '', sub.subscriptionData);
1749
1857
  _c.label = 1;
1750
1858
  case 1:
@@ -1811,7 +1919,22 @@ var SubscriptionManager = /** @class */ (function () {
1811
1919
  case 4:
1812
1920
  _c.sent();
1813
1921
  return [3 /*break*/, 7];
1814
- case 5: return [4 /*yield*/, this._monitorManagerFunction.finishMonitorFunction(monitor)];
1922
+ case 5:
1923
+ durationMs = Date.now() - startMs;
1924
+ if (durationMs >= this.PUBLICATION_DEBUG_THRESHOLD_MS) {
1925
+ console.log(new Date(), '[Slow Publication]', {
1926
+ durationMs: durationMs,
1927
+ publication: sub.publication,
1928
+ type: type,
1929
+ collection: collection,
1930
+ userSpecific: true,
1931
+ id_user: ws['id_user'] || null,
1932
+ id_ws: ws['id_socket'] || null,
1933
+ clients: sub.clients ? sub.clients.length : 0,
1934
+ subscriptionData: sub.subscriptionData
1935
+ });
1936
+ }
1937
+ return [4 /*yield*/, this._monitorManagerFunction.finishMonitorFunction(monitor)];
1815
1938
  case 6:
1816
1939
  _c.sent();
1817
1940
  return [7 /*endfinally*/];
@@ -1823,7 +1946,7 @@ var SubscriptionManager = /** @class */ (function () {
1823
1946
  // Fetch pub once, send to all clients linked to this pub
1824
1947
  SubscriptionManager.prototype.sendDataToAll = function (sub, collection, type) {
1825
1948
  return __awaiter(this, void 0, void 0, function () {
1826
- 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, normalizedError, correlationId, _f, _g, client, ws, serverRes, errorPayload;
1949
+ var subIndex, startMs, monitor, res, dependencySnapshot, execution, packedRes, shouldCache, cachedBuffer, isSame, _a, _b, client, ws, serverRes, _c, _d, client, ws, serverRes, nodeCacheSize, deleteCount, subArr, zz, err_2, _e, normalizedError, correlationId, _f, _g, client, ws, serverRes, errorPayload, durationMs;
1827
1950
  var e_6, _h, e_7, _j, e_8, _k;
1828
1951
  var _this = this;
1829
1952
  var _l;
@@ -1841,7 +1964,9 @@ var SubscriptionManager = /** @class */ (function () {
1841
1964
  }
1842
1965
  return [2 /*return*/];
1843
1966
  case 1:
1967
+ startMs = Date.now();
1844
1968
  monitor = this._monitorManagerFunction.startMonitorFunction('Publication', sub.publication, '', '', sub.subscriptionData);
1969
+ res = void 0;
1845
1970
  dependencySnapshot = void 0;
1846
1971
  _m.label = 2;
1847
1972
  case 2:
@@ -1858,69 +1983,51 @@ var SubscriptionManager = /** @class */ (function () {
1858
1983
  })];
1859
1984
  case 3:
1860
1985
  execution = _m.sent();
1861
- res_1 = execution.result;
1986
+ res = execution.result;
1862
1987
  dependencySnapshot = execution.snapshot;
1863
1988
  this.updateSubscriptionDependencies(sub, dependencySnapshot);
1989
+ packedRes = this.packCachePayload(res);
1990
+ shouldCache = this.shouldCachePayload(sub, packedRes);
1864
1991
  if (sub.cacheId) {
1865
- try {
1866
- cacheData = JSON.parse(this._nodeCache.get(sub.cacheId), common_1.dateReviver);
1867
- if (JSON.stringify(cacheData) !== JSON.stringify(res_1)) {
1868
- try {
1869
- for (_a = __values(sub.clients), _b = _a.next(); !_b.done; _b = _a.next()) {
1870
- client = _b.value;
1871
- ws = this._websocketManager.getWebSocket(client.id_socket);
1872
- if (ws && ws.readyState === ws.OPEN) {
1873
- serverRes = {
1874
- messageId: client.messageId,
1875
- hasError: false,
1876
- data: res_1
1877
- };
1878
- this.sendWS(ws, serverRes);
1879
- }
1880
- }
1881
- }
1882
- catch (e_6_1) { e_6 = { error: e_6_1 }; }
1883
- finally {
1884
- try {
1885
- if (_b && !_b.done && (_h = _a.return)) _h.call(_a);
1992
+ cachedBuffer = this.getCacheBuffer(this._nodeCache.get(sub.cacheId));
1993
+ isSame = this.buffersEqual(cachedBuffer, packedRes);
1994
+ if (!isSame) {
1995
+ try {
1996
+ for (_a = __values(sub.clients), _b = _a.next(); !_b.done; _b = _a.next()) {
1997
+ client = _b.value;
1998
+ ws = this._websocketManager.getWebSocket(client.id_socket);
1999
+ if (ws && ws.readyState === ws.OPEN) {
2000
+ serverRes = {
2001
+ messageId: client.messageId,
2002
+ hasError: false,
2003
+ data: res
2004
+ };
2005
+ this.sendWS(ws, serverRes);
1886
2006
  }
1887
- finally { if (e_6) throw e_6.error; }
1888
- }
1889
- this._nodeCache.del(sub.cacheId);
1890
- if ((0, common_1.getBinarySize)(JSON.stringify(res_1)) < 1000000 &&
1891
- !sub.collections.includes('logs') &&
1892
- !sub.collections.find(function (a) { return a.endsWith('.versions'); }) &&
1893
- !sub.collections.find(function (a) { return a.startsWith('monitor-'); })) {
1894
- this._nodeCache.set(sub.cacheId, JSON.stringify(res_1));
1895
- }
1896
- else {
1897
- sub.cacheId = 0;
1898
2007
  }
1899
2008
  }
1900
- }
1901
- catch (_o) {
1902
- sub.clients.map(function (client) {
1903
- var ws = _this._websocketManager.getWebSocket(client.id_socket);
1904
- if (ws && ws.readyState === ws.OPEN) {
1905
- var serverRes = {
1906
- messageId: client.messageId,
1907
- hasError: false,
1908
- data: res_1
1909
- };
1910
- _this.sendWS(ws, serverRes);
2009
+ catch (e_6_1) { e_6 = { error: e_6_1 }; }
2010
+ finally {
2011
+ try {
2012
+ if (_b && !_b.done && (_h = _a.return)) _h.call(_a);
1911
2013
  }
1912
- });
2014
+ finally { if (e_6) throw e_6.error; }
2015
+ }
1913
2016
  this._nodeCache.del(sub.cacheId);
1914
- if ((0, common_1.getBinarySize)(JSON.stringify(res_1)) < 1000000 &&
1915
- !sub.collections.includes('logs') &&
1916
- !sub.collections.find(function (a) { return a.endsWith('.versions'); }) &&
1917
- !sub.collections.find(function (a) { return a.startsWith('monitor-'); })) {
1918
- this._nodeCache.set(sub.cacheId, JSON.stringify(res_1));
2017
+ if (shouldCache) {
2018
+ this._nodeCache.set(sub.cacheId, packedRes);
1919
2019
  }
1920
2020
  else {
1921
2021
  sub.cacheId = 0;
1922
2022
  }
1923
2023
  }
2024
+ else if (!cachedBuffer && shouldCache) {
2025
+ this._nodeCache.set(sub.cacheId, packedRes);
2026
+ }
2027
+ else if (!shouldCache) {
2028
+ this._nodeCache.del(sub.cacheId);
2029
+ sub.cacheId = 0;
2030
+ }
1924
2031
  }
1925
2032
  else {
1926
2033
  try {
@@ -1931,7 +2038,7 @@ var SubscriptionManager = /** @class */ (function () {
1931
2038
  serverRes = {
1932
2039
  messageId: client.messageId,
1933
2040
  hasError: false,
1934
- data: res_1
2041
+ data: res
1935
2042
  };
1936
2043
  this.sendWS(ws, serverRes);
1937
2044
  }
@@ -1944,12 +2051,9 @@ var SubscriptionManager = /** @class */ (function () {
1944
2051
  }
1945
2052
  finally { if (e_7) throw e_7.error; }
1946
2053
  }
1947
- if ((0, common_1.getBinarySize)(JSON.stringify(res_1)) < 1000000 &&
1948
- !sub.collections.includes('logs') &&
1949
- !sub.collections.find(function (a) { return a.endsWith('.versions'); }) &&
1950
- !sub.collections.find(function (a) { return a.startsWith('monitor-'); })) {
2054
+ if (shouldCache) {
1951
2055
  sub.cacheId = this._cacheId++;
1952
- this._nodeCache.set(sub.cacheId, JSON.stringify(res_1));
2056
+ this._nodeCache.set(sub.cacheId, packedRes);
1953
2057
  nodeCacheSize = this._nodeCache.getStats().vsize;
1954
2058
  if (nodeCacheSize > this._heapLimit) {
1955
2059
  deleteCount = 0;
@@ -2035,7 +2139,21 @@ var SubscriptionManager = /** @class */ (function () {
2035
2139
  case 5:
2036
2140
  _m.sent();
2037
2141
  return [3 /*break*/, 8];
2038
- case 6: return [4 /*yield*/, this._monitorManagerFunction.finishMonitorFunction(monitor)];
2142
+ case 6:
2143
+ durationMs = Date.now() - startMs;
2144
+ if (durationMs >= this.PUBLICATION_DEBUG_THRESHOLD_MS) {
2145
+ console.log(new Date(), '[Slow Publication]', {
2146
+ durationMs: durationMs,
2147
+ publication: sub.publication,
2148
+ type: type,
2149
+ collection: collection,
2150
+ userSpecific: false,
2151
+ clients: sub.clients ? sub.clients.length : 0,
2152
+ cacheId: sub.cacheId || 0,
2153
+ subscriptionData: sub.subscriptionData
2154
+ });
2155
+ }
2156
+ return [4 /*yield*/, this._monitorManagerFunction.finishMonitorFunction(monitor)];
2039
2157
  case 7:
2040
2158
  _m.sent();
2041
2159
  return [7 /*endfinally*/];