@resolveio/server-lib 20.14.14 → 20.14.16

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/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");
@@ -118,6 +119,10 @@ var ResolveIOMainServer = /** @class */ (function () {
118
119
  this._clientHeartbeatIntervalMs = 20000;
119
120
  this._clientHeartbeatInitialDelayMs = 5000;
120
121
  this._clientHeartbeatBackpressureBytes = 5 * 1024 * 1024;
122
+ this._eventLoopLagIntervalMs = 500;
123
+ this._eventLoopLagThresholdMs = 300;
124
+ this._eventLoopDelayStatsIntervalMs = 10000;
125
+ this._slowHandlerThresholdMs = 200;
121
126
  }
122
127
  ResolveIOMainServer.create = function () {
123
128
  return __awaiter(this, void 0, void 0, function () {
@@ -159,6 +164,7 @@ var ResolveIOMainServer = /** @class */ (function () {
159
164
  _this._debugMsgQueue = 0;
160
165
  _this._debugMsgRecv = 0;
161
166
  }, 60000);
167
+ this.startEventLoopLagMonitor();
162
168
  process.removeAllListeners('unhandledRejection');
163
169
  process.on('unhandledRejection', function (error, rej) { return __awaiter(_this, void 0, void 0, function () {
164
170
  var _a, normalizedError, correlationId, errorDetails, diffTimeSec;
@@ -379,6 +385,76 @@ var ResolveIOMainServer = /** @class */ (function () {
379
385
  });
380
386
  });
381
387
  };
388
+ ResolveIOMainServer.prototype.startEventLoopLagMonitor = function () {
389
+ var _this = this;
390
+ var lastTick = Date.now();
391
+ var delayMonitor = (0, perf_hooks_1.monitorEventLoopDelay)({ resolution: 20 });
392
+ delayMonitor.enable();
393
+ var gcKindLabels = {};
394
+ var perfConstants = perf_hooks_1.performance === null || perf_hooks_1.performance === void 0 ? void 0 : perf_hooks_1.performance.constants;
395
+ if (perfConstants) {
396
+ if (typeof perfConstants.NODE_PERFORMANCE_GC_MAJOR !== 'undefined') {
397
+ gcKindLabels[perfConstants.NODE_PERFORMANCE_GC_MAJOR] = 'major';
398
+ }
399
+ if (typeof perfConstants.NODE_PERFORMANCE_GC_MINOR !== 'undefined') {
400
+ gcKindLabels[perfConstants.NODE_PERFORMANCE_GC_MINOR] = 'minor';
401
+ }
402
+ if (typeof perfConstants.NODE_PERFORMANCE_GC_INCREMENTAL !== 'undefined') {
403
+ gcKindLabels[perfConstants.NODE_PERFORMANCE_GC_INCREMENTAL] = 'incremental';
404
+ }
405
+ if (typeof perfConstants.NODE_PERFORMANCE_GC_WEAKCB !== 'undefined') {
406
+ gcKindLabels[perfConstants.NODE_PERFORMANCE_GC_WEAKCB] = 'weakcb';
407
+ }
408
+ }
409
+ var gcObserver = new perf_hooks_1.PerformanceObserver(function (list) {
410
+ var e_1, _a;
411
+ try {
412
+ for (var _b = __values(list.getEntries()), _c = _b.next(); !_c.done; _c = _b.next()) {
413
+ var entry = _c.value;
414
+ var kindLabel = gcKindLabels[entry.kind] || entry.kind;
415
+ console.log(new Date(), '[GC]', {
416
+ kind: kindLabel,
417
+ durationMs: (0, common_1.round)(entry.duration)
418
+ });
419
+ }
420
+ }
421
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
422
+ finally {
423
+ try {
424
+ if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
425
+ }
426
+ finally { if (e_1) throw e_1.error; }
427
+ }
428
+ });
429
+ gcObserver.observe({ entryTypes: ['gc'] });
430
+ setInterval(function () {
431
+ var now = Date.now();
432
+ var lagMs = now - lastTick - _this._eventLoopLagIntervalMs;
433
+ lastTick = now;
434
+ if (lagMs >= _this._eventLoopLagThresholdMs) {
435
+ var mem = process.memoryUsage();
436
+ console.log(new Date(), '[Event Loop Lag]', {
437
+ lagMs: (0, common_1.round)(lagMs),
438
+ rssMB: (0, common_1.round)(mem.rss / (1024 * 1024)),
439
+ heapUsedMB: (0, common_1.round)(mem.heapUsed / (1024 * 1024)),
440
+ heapTotalMB: (0, common_1.round)(mem.heapTotal / (1024 * 1024))
441
+ });
442
+ }
443
+ }, this._eventLoopLagIntervalMs);
444
+ setInterval(function () {
445
+ var p99Ms = (0, common_1.round)(delayMonitor.percentile(99) / 1e6);
446
+ var maxMs = (0, common_1.round)(delayMonitor.max / 1e6);
447
+ var meanMs = (0, common_1.round)(delayMonitor.mean / 1e6);
448
+ if (p99Ms >= _this._eventLoopLagThresholdMs || maxMs >= _this._eventLoopLagThresholdMs) {
449
+ console.log(new Date(), '[Event Loop Delay Stats]', {
450
+ p99Ms: p99Ms,
451
+ maxMs: maxMs,
452
+ meanMs: meanMs
453
+ });
454
+ }
455
+ delayMonitor.reset();
456
+ }, this._eventLoopDelayStatsIntervalMs);
457
+ };
382
458
  ResolveIOMainServer.prototype.shutdownNetworkServers = function () {
383
459
  return __awaiter(this, void 0, void 0, function () {
384
460
  return __generator(this, function (_a) {
@@ -911,7 +987,7 @@ var ResolveIOMainServer = /** @class */ (function () {
911
987
  }
912
988
  });
913
989
  ws.on('message', function (message) { return __awaiter(_this, void 0, void 0, function () {
914
- var socketData, usedBinary, bufferPayload, decodeResult, decodeResult, decodeResult, view, decodeResult, e_1, correlationId, context;
990
+ var socketData, usedBinary, bufferPayload, decodeResult, decodeResult, decodeResult, view, decodeResult, e_2, correlationId, context;
915
991
  return __generator(this, function (_a) {
916
992
  switch (_a.label) {
917
993
  case 0:
@@ -959,15 +1035,15 @@ var ResolveIOMainServer = /** @class */ (function () {
959
1035
  }
960
1036
  return [3 /*break*/, 4];
961
1037
  case 2:
962
- e_1 = _a.sent();
963
- console.log('Error - WS message parse', e_1);
1038
+ e_2 = _a.sent();
1039
+ console.log('Error - WS message parse', e_2);
964
1040
  correlationId = (0, common_1.objectIdHexString)();
965
1041
  context = {
966
1042
  rawBinary: bufferPayload ? bufferPayload.toString('base64') : undefined,
967
1043
  rawMessage: typeof message === 'string' ? message : undefined,
968
- error: e_1 instanceof Error ? { name: e_1.name, message: e_1.message, stack: e_1.stack } : e_1
1044
+ error: e_2 instanceof Error ? { name: e_2.name, message: e_2.message, stack: e_2.stack } : e_2
969
1045
  };
970
- return [4 /*yield*/, this.reportServerError('SERVER - JSON Parse Error - ' + resolveio_server_app_1.ResolveIOServer.getServerConfig()['CLIENT_NAME'], correlationId, context, { context: 'websocket-message-parse' }, 'error', e_1 instanceof Error ? e_1.stack : undefined)];
1046
+ return [4 /*yield*/, this.reportServerError('SERVER - JSON Parse Error - ' + resolveio_server_app_1.ResolveIOServer.getServerConfig()['CLIENT_NAME'], correlationId, context, { context: 'websocket-message-parse' }, 'error', e_2 instanceof Error ? e_2.stack : undefined)];
971
1047
  case 3:
972
1048
  _a.sent();
973
1049
  return [2 /*return*/];
@@ -1007,8 +1083,8 @@ var ResolveIOMainServer = /** @class */ (function () {
1007
1083
  }); });
1008
1084
  // Keep alive timer
1009
1085
  setInterval(function () { return __awaiter(_this, void 0, void 0, function () {
1010
- var _a, _b, ws, e_2_1;
1011
- var e_2, _c;
1086
+ var _a, _b, ws, e_3_1;
1087
+ var e_3, _c;
1012
1088
  return __generator(this, function (_d) {
1013
1089
  switch (_d.label) {
1014
1090
  case 0:
@@ -1049,14 +1125,14 @@ var ResolveIOMainServer = /** @class */ (function () {
1049
1125
  return [3 /*break*/, 1];
1050
1126
  case 9: return [3 /*break*/, 12];
1051
1127
  case 10:
1052
- e_2_1 = _d.sent();
1053
- e_2 = { error: e_2_1 };
1128
+ e_3_1 = _d.sent();
1129
+ e_3 = { error: e_3_1 };
1054
1130
  return [3 /*break*/, 12];
1055
1131
  case 11:
1056
1132
  try {
1057
1133
  if (_b && !_b.done && (_c = _a.return)) _c.call(_a);
1058
1134
  }
1059
- finally { if (e_2) throw e_2.error; }
1135
+ finally { if (e_3) throw e_3.error; }
1060
1136
  return [7 /*endfinally*/];
1061
1137
  case 12: return [2 /*return*/];
1062
1138
  }
@@ -1065,8 +1141,8 @@ var ResolveIOMainServer = /** @class */ (function () {
1065
1141
  };
1066
1142
  ResolveIOMainServer.prototype.processSocketMessage = function (ws, socketData) {
1067
1143
  return __awaiter(this, void 0, void 0, function () {
1068
- var socketData_1, socketData_1_1, message, e_3_1;
1069
- var e_3, _a;
1144
+ var socketData_1, socketData_1_1, message, e_4_1;
1145
+ var e_4, _a;
1070
1146
  return __generator(this, function (_b) {
1071
1147
  switch (_b.label) {
1072
1148
  case 0:
@@ -1105,14 +1181,14 @@ var ResolveIOMainServer = /** @class */ (function () {
1105
1181
  return [3 /*break*/, 2];
1106
1182
  case 5: return [3 /*break*/, 8];
1107
1183
  case 6:
1108
- e_3_1 = _b.sent();
1109
- e_3 = { error: e_3_1 };
1184
+ e_4_1 = _b.sent();
1185
+ e_4 = { error: e_4_1 };
1110
1186
  return [3 /*break*/, 8];
1111
1187
  case 7:
1112
1188
  try {
1113
1189
  if (socketData_1_1 && !socketData_1_1.done && (_a = socketData_1.return)) _a.call(socketData_1);
1114
1190
  }
1115
- finally { if (e_3) throw e_3.error; }
1191
+ finally { if (e_4) throw e_4.error; }
1116
1192
  return [7 /*endfinally*/];
1117
1193
  case 8: return [2 /*return*/];
1118
1194
  }
@@ -1223,32 +1299,43 @@ var ResolveIOMainServer = /** @class */ (function () {
1223
1299
  };
1224
1300
  ResolveIOMainServer.prototype.handleClientMessage = function (ws, msg) {
1225
1301
  return __awaiter(this, void 0, void 0, function () {
1226
- var messageRoute, messageDate, messageId, type, subType, pub, serverRes, offlineUpdates, i, update, data, updateRoute, updateDate, updateMessageId, updateType, method, serverResMethod, err_2, dataCopy, route, date, msgId, msgType, methodName, ack, method, forceWorker, targetWorkerIndex, hasWorkerForMethod, isExcludedFromWorker, errorRes, shouldDispatchToWorker, errorRes;
1302
+ var startMs, logRoute, logType, logDetail, messageRoute_1, messageDate, messageId, type, subType, pub, serverRes, offlineUpdates, i, update, data, updateRoute, updateDate, updateMessageId, updateType, method, serverResMethod, err_2, dataCopy, route, date, msgId, msgType, methodName, ack, method, forceWorker, targetWorkerIndex, hasWorkerForMethod, isExcludedFromWorker, errorRes, shouldDispatchToWorker, errorRes, durationMs;
1227
1303
  var _a;
1228
1304
  return __generator(this, function (_b) {
1229
1305
  switch (_b.label) {
1230
1306
  case 0:
1231
- messageRoute = msg[0];
1307
+ startMs = Date.now();
1308
+ logRoute = msg && msg[0];
1309
+ logType = null;
1310
+ logDetail = null;
1311
+ _b.label = 1;
1312
+ case 1:
1313
+ _b.trys.push([1, , 25, 26]);
1314
+ messageRoute_1 = msg[0];
1232
1315
  messageDate = msg[1];
1233
1316
  messageId = msg[2];
1234
1317
  type = msg[3];
1235
- if (!this.publicProgram && this._clientRoutes.some(function (a) { return messageRoute.includes(a); }) && !ws['doc_user'].roles.groups.some(function (a) { return a.views.some(function (b) { return messageRoute.includes(b) || b.includes(messageRoute); }); }) && !ws['doc_user'].roles.super_admin) {
1318
+ logRoute = messageRoute_1;
1319
+ logType = type;
1320
+ if (!this.publicProgram && this._clientRoutes.some(function (a) { return messageRoute_1.includes(a); }) && !ws['doc_user'].roles.groups.some(function (a) { return a.views.some(function (b) { return messageRoute_1.includes(b) || b.includes(messageRoute_1); }); }) && !ws['doc_user'].roles.super_admin) {
1236
1321
  return [2 /*return*/];
1237
1322
  }
1238
- if (!(type === 'subscription')) return [3 /*break*/, 4];
1323
+ if (!(type === 'subscription')) return [3 /*break*/, 5];
1239
1324
  subType = msg[4];
1240
1325
  pub = msg[5];
1241
- if (!(subType === 'sub')) return [3 /*break*/, 2];
1242
- return [4 /*yield*/, this._subscriptionManager.subscribe(messageRoute, messageDate, ws, messageId, pub, msg.slice(6))];
1243
- case 1:
1244
- _b.sent();
1245
- return [3 /*break*/, 3];
1326
+ logDetail = "".concat(subType, ":").concat(pub);
1327
+ if (!(subType === 'sub')) return [3 /*break*/, 3];
1328
+ return [4 /*yield*/, this._subscriptionManager.subscribe(messageRoute_1, messageDate, ws, messageId, pub, msg.slice(6))];
1246
1329
  case 2:
1247
- this._subscriptionManager.unsubscribe(messageRoute, messageDate, ws, messageId, pub, msg.slice(6));
1248
- _b.label = 3;
1249
- case 3: return [3 /*break*/, 23];
1250
- case 4:
1251
- if (!(!this.publicProgram && type === 'offline')) return [3 /*break*/, 16];
1330
+ _b.sent();
1331
+ return [3 /*break*/, 4];
1332
+ case 3:
1333
+ this._subscriptionManager.unsubscribe(messageRoute_1, messageDate, ws, messageId, pub, msg.slice(6));
1334
+ _b.label = 4;
1335
+ case 4: return [3 /*break*/, 24];
1336
+ case 5:
1337
+ if (!(!this.publicProgram && type === 'offline')) return [3 /*break*/, 17];
1338
+ logDetail = 'offline';
1252
1339
  serverRes = {
1253
1340
  messageId: messageId,
1254
1341
  hasError: false,
@@ -1259,10 +1346,11 @@ var ResolveIOMainServer = /** @class */ (function () {
1259
1346
  }
1260
1347
  this._offlineUpdates.push(ws);
1261
1348
  offlineUpdates = msg[4];
1349
+ logDetail = "offline:".concat(Array.isArray(offlineUpdates) ? offlineUpdates.length : 0);
1262
1350
  i = 0;
1263
- _b.label = 5;
1264
- case 5:
1265
- if (!(i < offlineUpdates.length)) return [3 /*break*/, 15];
1351
+ _b.label = 6;
1352
+ case 6:
1353
+ if (!(i < offlineUpdates.length)) return [3 /*break*/, 16];
1266
1354
  update = offlineUpdates[i];
1267
1355
  data = update.data;
1268
1356
  updateRoute = data.shift();
@@ -1279,11 +1367,11 @@ var ResolveIOMainServer = /** @class */ (function () {
1279
1367
  this._websocketManager.send(ws, serverResMethod);
1280
1368
  }
1281
1369
  if (method === 'insertDocument' && data[0] === 'driver-gps') {
1282
- return [3 /*break*/, 14];
1370
+ return [3 /*break*/, 15];
1283
1371
  }
1284
- if (!(method !== 'reportBuilderGetResults' && method !== 'reportBuilderGetDistinctValue' && method !== 'reportBuilderBuildTree' && method !== 'generatePDF' && method !== 'getWOOfflineData' && method !== 'countQuery' && method !== 'countWithQuery' && method !== 'countCollectionWithQuery' && method !== 'find' && method !== 'findOne' && method !== 'findWithOptions' && method !== 'getDrivers' && method !== 'processAirdropDistribution' && method !== 'qbHandleResponse')) return [3 /*break*/, 8];
1372
+ if (!(method !== 'reportBuilderGetResults' && method !== 'reportBuilderGetDistinctValue' && method !== 'reportBuilderBuildTree' && method !== 'generatePDF' && method !== 'getWOOfflineData' && method !== 'countQuery' && method !== 'countWithQuery' && method !== 'countCollectionWithQuery' && method !== 'find' && method !== 'findOne' && method !== 'findWithOptions' && method !== 'getDrivers' && method !== 'processAirdropDistribution' && method !== 'qbHandleResponse')) return [3 /*break*/, 9];
1285
1373
  if (!(resolveio_server_app_1.ResolveIOServer.getServerConfig()['ROOT_URL'] !== 'https://resolveio.com'
1286
- && resolveio_server_app_1.ResolveIOServer.getServerConfig()['ROOT_URL'] !== 'http://localhost:4200')) return [3 /*break*/, 6];
1374
+ && resolveio_server_app_1.ResolveIOServer.getServerConfig()['ROOT_URL'] !== 'http://localhost:4200')) return [3 /*break*/, 7];
1287
1375
  resolveio_server_app_1.ResolveIOServer.getLocalLogManager().writeLog({
1288
1376
  type: 'log',
1289
1377
  data: {
@@ -1297,12 +1385,12 @@ var ResolveIOMainServer = /** @class */ (function () {
1297
1385
  id_user: ws['id_user'] || '',
1298
1386
  user: ws['user'] || '',
1299
1387
  messageId: messageId,
1300
- route: messageRoute,
1388
+ route: messageRoute_1,
1301
1389
  instance_index: process.env.NODE_APP_INSTANCE || '0'
1302
1390
  }
1303
1391
  });
1304
- return [3 /*break*/, 8];
1305
- case 6: return [4 /*yield*/, log_collection_1.Logs.insertOne({
1392
+ return [3 /*break*/, 9];
1393
+ case 7: return [4 /*yield*/, log_collection_1.Logs.insertOne({
1306
1394
  _id: (0, common_1.objectIdHexString)(),
1307
1395
  type: 'client-request',
1308
1396
  collection: '',
@@ -1312,55 +1400,56 @@ var ResolveIOMainServer = /** @class */ (function () {
1312
1400
  id_user: ws['id_user'] || '',
1313
1401
  user: ws['user'] || '',
1314
1402
  messageId: messageId,
1315
- route: messageRoute,
1403
+ route: messageRoute_1,
1316
1404
  client: 'ResolveIO',
1317
1405
  instance: 'backend.resolveio.com',
1318
1406
  instance_index: process.env.NODE_APP_INSTANCE || '0'
1319
1407
  })];
1320
- case 7:
1321
- _b.sent();
1322
- _b.label = 8;
1323
1408
  case 8:
1324
- if (!this._methodManager._methods[method]) return [3 /*break*/, 13];
1409
+ _b.sent();
1325
1410
  _b.label = 9;
1326
1411
  case 9:
1327
- _b.trys.push([9, 11, , 12]);
1328
- return [4 /*yield*/, (_a = this._methodManager.callMethod).call.apply(_a, __spreadArray([Object.assign({}, this._methodManager, method_manager_1.MethodManager.prototype, { id_user: ws['id_user'], user: ws['user'], id_ws: ws['id_socket'] }), method], __read(data), false))];
1412
+ if (!this._methodManager._methods[method]) return [3 /*break*/, 14];
1413
+ _b.label = 10;
1329
1414
  case 10:
1330
- _b.sent();
1331
- return [3 /*break*/, 12];
1415
+ _b.trys.push([10, 12, , 13]);
1416
+ return [4 /*yield*/, (_a = this._methodManager.callMethod).call.apply(_a, __spreadArray([Object.assign({}, this._methodManager, method_manager_1.MethodManager.prototype, { id_user: ws['id_user'], user: ws['user'], id_ws: ws['id_socket'] }), method], __read(data), false))];
1332
1417
  case 11:
1418
+ _b.sent();
1419
+ return [3 /*break*/, 13];
1420
+ case 12:
1333
1421
  err_2 = _b.sent();
1334
1422
  console.log(new Date(), 'Offline Error', JSON.stringify(err_2, null, 2));
1335
- return [3 /*break*/, 12];
1336
- case 12:
1423
+ return [3 /*break*/, 13];
1424
+ case 13:
1337
1425
  if (method === 'updateDocumentOffline' || method === 'updateDocumentPropsOffline') {
1338
1426
  resolveio_server_app_1.ResolveIOServer.getMongoManager().invalidateQueryCache(data[0]);
1339
1427
  }
1340
- return [3 /*break*/, 14];
1341
- case 13:
1342
- console.log('Offline - Could not find method: ' + method);
1343
- _b.label = 14;
1428
+ return [3 /*break*/, 15];
1344
1429
  case 14:
1345
- i++;
1346
- return [3 /*break*/, 5];
1430
+ console.log('Offline - Could not find method: ' + method);
1431
+ _b.label = 15;
1347
1432
  case 15:
1348
- this._offlineUpdates.splice(this._offlineUpdates.map(function (a) { return a['id_socket']; }).indexOf(ws['id_socket']), 1);
1349
- return [3 /*break*/, 23];
1433
+ i++;
1434
+ return [3 /*break*/, 6];
1350
1435
  case 16:
1436
+ this._offlineUpdates.splice(this._offlineUpdates.map(function (a) { return a['id_socket']; }).indexOf(ws['id_socket']), 1);
1437
+ return [3 /*break*/, 24];
1438
+ case 17:
1351
1439
  dataCopy = __spreadArray([], __read(msg), false);
1352
1440
  route = dataCopy.shift();
1353
1441
  date = dataCopy.shift();
1354
1442
  msgId = dataCopy.shift();
1355
1443
  msgType = dataCopy.shift();
1356
- if (!(msgType === 'method')) return [3 /*break*/, 23];
1444
+ if (!(msgType === 'method')) return [3 /*break*/, 24];
1357
1445
  methodName = dataCopy.shift();
1446
+ logDetail = "method:".concat(methodName);
1358
1447
  if (ws['user_readonly']) {
1359
1448
  return [2 /*return*/];
1360
1449
  }
1361
- if (!(methodName !== 'reportBuilderGetResults' && methodName !== 'reportBuilderGetDistinctValue' && methodName !== 'reportBuilderBuildTree' && methodName !== 'generatePDF' && methodName !== 'getWOOfflineData' && methodName !== 'countQuery' && methodName !== 'countWithQuery' && methodName !== 'countCollectionWithQuery' && methodName !== 'find' && methodName !== 'findOne' && methodName !== 'findWithOptions' && methodName !== 'getDrivers' && methodName !== 'processAirdropDistribution')) return [3 /*break*/, 19];
1450
+ if (!(methodName !== 'reportBuilderGetResults' && methodName !== 'reportBuilderGetDistinctValue' && methodName !== 'reportBuilderBuildTree' && methodName !== 'generatePDF' && methodName !== 'getWOOfflineData' && methodName !== 'countQuery' && methodName !== 'countWithQuery' && methodName !== 'countCollectionWithQuery' && methodName !== 'find' && methodName !== 'findOne' && methodName !== 'findWithOptions' && methodName !== 'getDrivers' && methodName !== 'processAirdropDistribution')) return [3 /*break*/, 20];
1362
1451
  if (!(resolveio_server_app_1.ResolveIOServer.getServerConfig()['ROOT_URL'] !== 'https://resolveio.com'
1363
- && resolveio_server_app_1.ResolveIOServer.getServerConfig()['ROOT_URL'] !== 'http://localhost:4200')) return [3 /*break*/, 17];
1452
+ && resolveio_server_app_1.ResolveIOServer.getServerConfig()['ROOT_URL'] !== 'http://localhost:4200')) return [3 /*break*/, 18];
1364
1453
  resolveio_server_app_1.ResolveIOServer.getLocalLogManager().writeLog({
1365
1454
  type: 'log',
1366
1455
  data: {
@@ -1374,12 +1463,12 @@ var ResolveIOMainServer = /** @class */ (function () {
1374
1463
  id_user: ws['id_user'] || '',
1375
1464
  user: ws['user'] || '',
1376
1465
  messageId: messageId,
1377
- route: messageRoute,
1466
+ route: messageRoute_1,
1378
1467
  instance_index: process.env.NODE_APP_INSTANCE || '0'
1379
1468
  }
1380
1469
  });
1381
- return [3 /*break*/, 19];
1382
- case 17: return [4 /*yield*/, log_collection_1.Logs.insertOne({
1470
+ return [3 /*break*/, 20];
1471
+ case 18: return [4 /*yield*/, log_collection_1.Logs.insertOne({
1383
1472
  _id: (0, common_1.objectIdHexString)(),
1384
1473
  type: 'client-request',
1385
1474
  collection: '',
@@ -1389,15 +1478,15 @@ var ResolveIOMainServer = /** @class */ (function () {
1389
1478
  id_user: ws['id_user'] || '',
1390
1479
  user: ws['user'] || '',
1391
1480
  messageId: messageId,
1392
- route: messageRoute,
1481
+ route: messageRoute_1,
1393
1482
  client: 'ResolveIO',
1394
1483
  instance: 'backend.resolveio.com',
1395
1484
  instance_index: process.env.NODE_APP_INSTANCE || '0'
1396
1485
  })];
1397
- case 18:
1398
- _b.sent();
1399
- _b.label = 19;
1400
1486
  case 19:
1487
+ _b.sent();
1488
+ _b.label = 20;
1489
+ case 20:
1401
1490
  ack = {
1402
1491
  messageId: msgId,
1403
1492
  hasError: false,
@@ -1444,15 +1533,15 @@ var ResolveIOMainServer = /** @class */ (function () {
1444
1533
  this._workerDispatcherManager &&
1445
1534
  (hasWorkerForMethod || forceWorker) &&
1446
1535
  (forceWorker || !isExcludedFromWorker));
1447
- if (!shouldDispatchToWorker) return [3 /*break*/, 20];
1536
+ if (!shouldDispatchToWorker) return [3 /*break*/, 21];
1448
1537
  this._workerDispatcherManager.sendClientTask(msgId, methodName, dataCopy, {
1449
1538
  id_user: ws['id_user'],
1450
1539
  user: ws['user'],
1451
1540
  id_ws: ws['id_socket']
1452
1541
  });
1453
- return [3 /*break*/, 23];
1454
- case 20:
1455
- if (!(forceWorker && this._isWorkersEnabled)) return [3 /*break*/, 21];
1542
+ return [3 /*break*/, 24];
1543
+ case 21:
1544
+ if (!(forceWorker && this._isWorkersEnabled)) return [3 /*break*/, 22];
1456
1545
  errorRes = {
1457
1546
  messageId: msgId,
1458
1547
  hasError: true,
@@ -1461,15 +1550,30 @@ var ResolveIOMainServer = /** @class */ (function () {
1461
1550
  if (ws && ws.readyState === ws.OPEN) {
1462
1551
  this._websocketManager.send(ws, errorRes);
1463
1552
  }
1464
- return [3 /*break*/, 23];
1465
- case 21:
1553
+ return [3 /*break*/, 24];
1554
+ case 22:
1466
1555
  // No worker available: do method locally
1467
- return [4 /*yield*/, this.callMethodLocally(ws, msgId, methodName, dataCopy)];
1468
- case 22:
1556
+ return [4 /*yield*/, this.callMethodLocally(ws, msgId, methodName, dataCopy, messageRoute_1)];
1557
+ case 23:
1469
1558
  // No worker available: do method locally
1470
1559
  _b.sent();
1471
- _b.label = 23;
1472
- case 23: return [2 /*return*/];
1560
+ _b.label = 24;
1561
+ case 24: return [3 /*break*/, 26];
1562
+ case 25:
1563
+ durationMs = Date.now() - startMs;
1564
+ if (durationMs >= this._slowHandlerThresholdMs) {
1565
+ console.log(new Date(), '[Slow WS Message]', {
1566
+ durationMs: durationMs,
1567
+ route: logRoute,
1568
+ type: logType,
1569
+ detail: logDetail,
1570
+ id_user: ws['id_user'] || null,
1571
+ user: ws['user'] || null,
1572
+ id_ws: ws['id_socket'] || null
1573
+ });
1574
+ }
1575
+ return [7 /*endfinally*/];
1576
+ case 26: return [2 /*return*/];
1473
1577
  }
1474
1578
  });
1475
1579
  });
@@ -1477,9 +1581,9 @@ var ResolveIOMainServer = /** @class */ (function () {
1477
1581
  /**
1478
1582
  * callMethodLocally is your old approach for invoking the method in-process.
1479
1583
  */
1480
- ResolveIOMainServer.prototype.callMethodLocally = function (ws, messageId, method, params) {
1584
+ ResolveIOMainServer.prototype.callMethodLocally = function (ws, messageId, method, params, route) {
1481
1585
  return __awaiter(this, void 0, void 0, function () {
1482
- var serverRes, result, err_3;
1586
+ var serverRes, startMs, result, err_3, durationMs;
1483
1587
  var _a;
1484
1588
  return __generator(this, function (_b) {
1485
1589
  switch (_b.label) {
@@ -1489,9 +1593,10 @@ var ResolveIOMainServer = /** @class */ (function () {
1489
1593
  hasError: false,
1490
1594
  data: null
1491
1595
  };
1596
+ startMs = Date.now();
1492
1597
  _b.label = 1;
1493
1598
  case 1:
1494
- _b.trys.push([1, 3, , 4]);
1599
+ _b.trys.push([1, 3, 4, 5]);
1495
1600
  return [4 /*yield*/, (_a = this._methodManager.callMethod).call.apply(_a, __spreadArray([Object.assign({}, this._methodManager, method_manager_1.MethodManager.prototype, {
1496
1601
  id_user: ws['id_user'],
1497
1602
  user: ws['user'],
@@ -1501,13 +1606,26 @@ var ResolveIOMainServer = /** @class */ (function () {
1501
1606
  case 2:
1502
1607
  result = _b.sent();
1503
1608
  serverRes.data = result;
1504
- return [3 /*break*/, 4];
1609
+ return [3 /*break*/, 5];
1505
1610
  case 3:
1506
1611
  err_3 = _b.sent();
1507
1612
  serverRes.hasError = true;
1508
1613
  serverRes.data = err_3 || 'Unknown error';
1509
- return [3 /*break*/, 4];
1614
+ return [3 /*break*/, 5];
1510
1615
  case 4:
1616
+ durationMs = Date.now() - startMs;
1617
+ if (durationMs >= this._slowHandlerThresholdMs) {
1618
+ console.log(new Date(), '[Slow Local Method]', {
1619
+ durationMs: durationMs,
1620
+ method: method,
1621
+ route: route || null,
1622
+ id_user: ws['id_user'] || null,
1623
+ user: ws['user'] || null,
1624
+ id_ws: ws['id_socket'] || null
1625
+ });
1626
+ }
1627
+ return [7 /*endfinally*/];
1628
+ case 5:
1511
1629
  if (ws && ws.readyState === ws.OPEN) {
1512
1630
  this._websocketManager.send(ws, serverRes);
1513
1631
  }