@resolveio/server-lib 20.14.33 → 20.14.34

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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@resolveio/server-lib",
3
- "version": "20.14.33",
3
+ "version": "20.14.34",
4
4
  "description": "",
5
5
  "scripts": {
6
6
  "package": "./build_package.sh",
package/server-app.d.ts CHANGED
@@ -29,6 +29,13 @@ export declare class ResolveIOMainServer {
29
29
  private _workerServerManager;
30
30
  private _httpServerClosePromise;
31
31
  private _websocketServerClosePromise;
32
+ private _wsConnectDebug;
33
+ private _perfDebug;
34
+ private _perfDebugIntervalMs;
35
+ private _perfDebugTimer;
36
+ private _perfDebugLastCpu;
37
+ private _perfDebugLastTs;
38
+ private _eventLoopHistogram;
32
39
  private _serverStartTime;
33
40
  private _lastErrorMsg;
34
41
  private _debugMsgRecv;
@@ -68,6 +75,12 @@ export declare class ResolveIOMainServer {
68
75
  private decodeBufferPayload;
69
76
  private parseTextFallback;
70
77
  private looksLikeTextPayload;
78
+ private resolveConnectDebug;
79
+ private resolvePerfDebug;
80
+ private parsePositiveInt;
81
+ private startPerfDebug;
82
+ private parseDebugFlag;
83
+ private logConnectDebug;
71
84
  private triggerClientHeartbeat;
72
85
  private shouldDeferHeartbeat;
73
86
  private handleClientMessage;
package/server-app.js CHANGED
@@ -79,6 +79,7 @@ var http_1 = require("http");
79
79
  var jwt = require("jsonwebtoken");
80
80
  var moment = require("moment-timezone");
81
81
  var msgpackr_1 = require("msgpackr");
82
+ var perf_hooks_1 = require("perf_hooks");
82
83
  var url_1 = require("url");
83
84
  var WebSocket = require("ws");
84
85
  var log_collection_1 = require("./collections/log.collection");
@@ -109,6 +110,13 @@ var ResolveIOMainServer = /** @class */ (function () {
109
110
  this._clientRoutes = [];
110
111
  this._httpServerClosePromise = null;
111
112
  this._websocketServerClosePromise = null;
113
+ this._wsConnectDebug = false;
114
+ this._perfDebug = false;
115
+ this._perfDebugIntervalMs = 2000;
116
+ this._perfDebugTimer = null;
117
+ this._perfDebugLastCpu = null;
118
+ this._perfDebugLastTs = 0;
119
+ this._eventLoopHistogram = null;
112
120
  this._lastErrorMsg = null;
113
121
  this._debugMsgRecv = 0;
114
122
  this._debugMsgQueue = 0;
@@ -143,11 +151,14 @@ var ResolveIOMainServer = /** @class */ (function () {
143
151
  case 0:
144
152
  this._serverStartTime = new Date();
145
153
  this._lastErrorMsg = null;
154
+ this._wsConnectDebug = this.resolveConnectDebug();
155
+ this._perfDebug = this.resolvePerfDebug();
146
156
  _a = this;
147
157
  return [4 /*yield*/, monitor_manager_1.MonitorManager.create()];
148
158
  case 1:
149
159
  _a._monitorManager = _b.sent();
150
160
  this._monitorManagerFunction = new monitor_manager_1.MonitorManagerFunction();
161
+ this.startPerfDebug();
151
162
  // Check for workers and decide what to start
152
163
  this._isWorkersEnabled = process.env.IS_WORKERS_ENABLED === 'true';
153
164
  this._isWorkerInstance = process.env.IS_WORKER_INSTANCE === 'true';
@@ -762,8 +773,9 @@ var ResolveIOMainServer = /** @class */ (function () {
762
773
  this._serverWSS.on('connection', function (ws, req) { return __awaiter(_this, void 0, void 0, function () {
763
774
  var workerId_1, workerIndex, workerInstance, rootUrl, requestUrl, workerIndexForLog, workerInstanceForLog, interval_1, lastComm_1, missedPongs_1, heartbeatIntervalMs, maxMissedPongs_1, maxSilenceMs_1;
764
775
  var _this = this;
765
- return __generator(this, function (_a) {
766
- switch (_a.label) {
776
+ var _a, _b;
777
+ return __generator(this, function (_c) {
778
+ switch (_c.label) {
767
779
  case 0:
768
780
  if (!(req.url && req.url.includes('workerToken='))) return [3 /*break*/, 1];
769
781
  workerId_1 = (0, common_1.objectIdHexString)();
@@ -778,7 +790,7 @@ var ResolveIOMainServer = /** @class */ (function () {
778
790
  workerIndex = requestUrl.searchParams.get('workerIndex');
779
791
  workerInstance = requestUrl.searchParams.get('workerInstance');
780
792
  }
781
- catch (_b) {
793
+ catch (_d) {
782
794
  workerIndex = null;
783
795
  workerInstance = null;
784
796
  }
@@ -885,9 +897,17 @@ var ResolveIOMainServer = /** @class */ (function () {
885
897
  ws['user_readonly'] = req['user_readonly'];
886
898
  ws['doc_user'] = req['doc_user'];
887
899
  this._websocketManager.addWebSocket(ws);
900
+ this.logConnectDebug('WS client connected', {
901
+ id_socket: ws['id_socket'],
902
+ id_user: ws['id_user'],
903
+ user: ws['user'],
904
+ url: req === null || req === void 0 ? void 0 : req.url,
905
+ ip: (_a = req === null || req === void 0 ? void 0 : req.socket) === null || _a === void 0 ? void 0 : _a.remoteAddress,
906
+ origin: (_b = req === null || req === void 0 ? void 0 : req.headers) === null || _b === void 0 ? void 0 : _b.origin
907
+ });
888
908
  return [4 /*yield*/, this._subscriptionManager.createLoggedInUser(ws['id_socket'])];
889
909
  case 2:
890
- _a.sent();
910
+ _c.sent();
891
911
  setTimeout(function () { return __awaiter(_this, void 0, void 0, function () {
892
912
  return __generator(this, function (_a) {
893
913
  switch (_a.label) {
@@ -994,14 +1014,20 @@ var ResolveIOMainServer = /** @class */ (function () {
994
1014
  .on('close', function () { return __awaiter(_this, void 0, void 0, function () {
995
1015
  return __generator(this, function (_a) {
996
1016
  switch (_a.label) {
997
- case 0: return [4 /*yield*/, this.unsubscribeWS(ws)];
1017
+ case 0:
1018
+ this.logConnectDebug('WS client closed', {
1019
+ id_socket: ws['id_socket'],
1020
+ id_user: ws['id_user'],
1021
+ user: ws['user']
1022
+ });
1023
+ return [4 /*yield*/, this.unsubscribeWS(ws)];
998
1024
  case 1:
999
1025
  _a.sent();
1000
1026
  return [2 /*return*/];
1001
1027
  }
1002
1028
  });
1003
1029
  }); });
1004
- _a.label = 3;
1030
+ _c.label = 3;
1005
1031
  case 3: return [2 /*return*/];
1006
1032
  }
1007
1033
  });
@@ -1087,6 +1113,11 @@ var ResolveIOMainServer = /** @class */ (function () {
1087
1113
  // If the top level is not an array, let's skip
1088
1114
  if (!Array.isArray(socketData[0])) {
1089
1115
  console.log('Invalid message format (expected array of arrays)', socketData);
1116
+ this.logConnectDebug('Invalid message format', {
1117
+ id_socket: ws ? ws['id_socket'] : null,
1118
+ user: ws ? ws['user'] : null,
1119
+ preview: Array.isArray(socketData) ? socketData.slice(0, 3) : socketData
1120
+ });
1090
1121
  return [2 /*return*/];
1091
1122
  }
1092
1123
  _b.label = 1;
@@ -1164,6 +1195,103 @@ var ResolveIOMainServer = /** @class */ (function () {
1164
1195
  var first = trimmed[0];
1165
1196
  return first === '[' || first === '{' || first === '"' || first === 'p' || first === 'P';
1166
1197
  };
1198
+ ResolveIOMainServer.prototype.resolveConnectDebug = function () {
1199
+ var _a, _b, _c;
1200
+ var config = resolveio_server_app_1.ResolveIOServer.getServerConfig ? resolveio_server_app_1.ResolveIOServer.getServerConfig() : null;
1201
+ var raw = (_c = (_b = (_a = process.env.WS_CONNECT_DEBUG) !== null && _a !== void 0 ? _a : process.env.CONNECT_DEBUG) !== null && _b !== void 0 ? _b : config === null || config === void 0 ? void 0 : config['WS_CONNECT_DEBUG']) !== null && _c !== void 0 ? _c : config === null || config === void 0 ? void 0 : config['CONNECT_DEBUG'];
1202
+ return this.parseDebugFlag(raw);
1203
+ };
1204
+ ResolveIOMainServer.prototype.resolvePerfDebug = function () {
1205
+ var _a, _b, _c;
1206
+ var config = resolveio_server_app_1.ResolveIOServer.getServerConfig ? resolveio_server_app_1.ResolveIOServer.getServerConfig() : null;
1207
+ var raw = (_c = (_b = (_a = process.env.PERF_DEBUG) !== null && _a !== void 0 ? _a : process.env.CPU_DEBUG) !== null && _b !== void 0 ? _b : config === null || config === void 0 ? void 0 : config['PERF_DEBUG']) !== null && _c !== void 0 ? _c : config === null || config === void 0 ? void 0 : config['CPU_DEBUG'];
1208
+ return this.parseDebugFlag(raw);
1209
+ };
1210
+ ResolveIOMainServer.prototype.parsePositiveInt = function (value, fallback) {
1211
+ var parsed = parseInt(value !== null && value !== void 0 ? value : '', 10);
1212
+ if (Number.isNaN(parsed) || parsed <= 0) {
1213
+ return fallback;
1214
+ }
1215
+ return parsed;
1216
+ };
1217
+ ResolveIOMainServer.prototype.startPerfDebug = function () {
1218
+ var _this = this;
1219
+ var _a;
1220
+ if (!this._perfDebug || this._perfDebugTimer) {
1221
+ return;
1222
+ }
1223
+ this._perfDebugIntervalMs = this.parsePositiveInt((_a = process.env.PERF_DEBUG_INTERVAL_MS) !== null && _a !== void 0 ? _a : process.env.CPU_DEBUG_INTERVAL_MS, this._perfDebugIntervalMs);
1224
+ this._perfDebugLastCpu = process.cpuUsage();
1225
+ this._perfDebugLastTs = Date.now();
1226
+ this._eventLoopHistogram = (0, perf_hooks_1.monitorEventLoopDelay)({ resolution: 20 });
1227
+ this._eventLoopHistogram.enable();
1228
+ this._perfDebugTimer = setInterval(function () {
1229
+ var now = Date.now();
1230
+ var elapsedMs = now - _this._perfDebugLastTs;
1231
+ var cpuDiff = _this._perfDebugLastCpu ? process.cpuUsage(_this._perfDebugLastCpu) : process.cpuUsage();
1232
+ var cpuMs = (cpuDiff.user + cpuDiff.system) / 1000;
1233
+ var cpuPct = elapsedMs > 0 ? (cpuMs / elapsedMs) * 100 : 0;
1234
+ var mem = process.memoryUsage();
1235
+ var heapUsedMb = (0, common_1.round)((mem.heapUsed / 1024 / 1024) * 10) / 10;
1236
+ var rssMb = (0, common_1.round)((mem.rss / 1024 / 1024) * 10) / 10;
1237
+ var handles = typeof process._getActiveHandles === 'function'
1238
+ ? process._getActiveHandles().length
1239
+ : null;
1240
+ var requests = typeof process._getActiveRequests === 'function'
1241
+ ? process._getActiveRequests().length
1242
+ : null;
1243
+ var histogram = _this._eventLoopHistogram;
1244
+ var eventLoop = histogram ? {
1245
+ meanMs: (0, common_1.round)((histogram.mean / 1e6) * 100) / 100,
1246
+ p50Ms: (0, common_1.round)((histogram.percentile(50) / 1e6) * 100) / 100,
1247
+ p95Ms: (0, common_1.round)((histogram.percentile(95) / 1e6) * 100) / 100,
1248
+ p99Ms: (0, common_1.round)((histogram.percentile(99) / 1e6) * 100) / 100,
1249
+ maxMs: (0, common_1.round)((histogram.max / 1e6) * 100) / 100
1250
+ } : null;
1251
+ histogram === null || histogram === void 0 ? void 0 : histogram.reset();
1252
+ console.log(new Date(), '[Perf Debug]', JSON.stringify({
1253
+ cpuPct: (0, common_1.round)(cpuPct * 10) / 10,
1254
+ cpuMs: (0, common_1.round)(cpuMs),
1255
+ elapsedMs: elapsedMs,
1256
+ eventLoop: eventLoop,
1257
+ heapUsedMb: heapUsedMb,
1258
+ rssMb: rssMb,
1259
+ activeHandles: handles,
1260
+ activeRequests: requests,
1261
+ msgRecv: _this._debugMsgRecv,
1262
+ msgQueue: _this._debugMsgQueue
1263
+ }));
1264
+ _this._perfDebugLastCpu = process.cpuUsage();
1265
+ _this._perfDebugLastTs = now;
1266
+ }, this._perfDebugIntervalMs);
1267
+ };
1268
+ ResolveIOMainServer.prototype.parseDebugFlag = function (value) {
1269
+ if (value === true) {
1270
+ return true;
1271
+ }
1272
+ if (value === false || value === null || value === undefined) {
1273
+ return false;
1274
+ }
1275
+ if (typeof value === 'number') {
1276
+ return value === 1;
1277
+ }
1278
+ if (typeof value === 'string') {
1279
+ var normalized = value.trim().toLowerCase();
1280
+ return ['1', 'true', 'yes', 'y', 'on'].includes(normalized);
1281
+ }
1282
+ return false;
1283
+ };
1284
+ ResolveIOMainServer.prototype.logConnectDebug = function (message, details) {
1285
+ if (!this._wsConnectDebug) {
1286
+ return;
1287
+ }
1288
+ if (details) {
1289
+ console.log(new Date(), '[Connect Debug]', message, JSON.stringify(details));
1290
+ }
1291
+ else {
1292
+ console.log(new Date(), '[Connect Debug]', message);
1293
+ }
1294
+ };
1167
1295
  ResolveIOMainServer.prototype.triggerClientHeartbeat = function (ws) {
1168
1296
  return __awaiter(this, void 0, void 0, function () {
1169
1297
  var err_1;
@@ -1240,6 +1368,15 @@ var ResolveIOMainServer = /** @class */ (function () {
1240
1368
  if (!(type === 'subscription')) return [3 /*break*/, 4];
1241
1369
  subType = msg[4];
1242
1370
  pub = msg[5];
1371
+ this.logConnectDebug('Subscription message', {
1372
+ subType: subType,
1373
+ publication: pub,
1374
+ messageId: messageId,
1375
+ messageRoute: messageRoute_1,
1376
+ args: Math.max(0, msg.length - 6),
1377
+ id_socket: ws ? ws['id_socket'] : null,
1378
+ user: ws ? ws['user'] : null
1379
+ });
1243
1380
  if (!(subType === 'sub')) return [3 /*break*/, 2];
1244
1381
  return [4 /*yield*/, this._subscriptionManager.subscribe(messageRoute_1, messageDate, ws, messageId, pub, msg.slice(6))];
1245
1382
  case 1:
@@ -1533,6 +1670,11 @@ var ResolveIOMainServer = /** @class */ (function () {
1533
1670
  if (this._subscriptionManager && this._methodManager.getEnableDebug()) {
1534
1671
  console.log(new Date(), 'Server App', 'Unsub WS', ws['user'], ws['id_socket']);
1535
1672
  }
1673
+ this.logConnectDebug('WS unsubscribe', {
1674
+ id_socket: ws ? ws['id_socket'] : null,
1675
+ id_user: ws ? ws['id_user'] : null,
1676
+ user: ws ? ws['user'] : null
1677
+ });
1536
1678
  return [4 /*yield*/, this._subscriptionManager.unsubscribeAll(ws)];
1537
1679
  case 1:
1538
1680
  _a.sent();