@resolveio/server-lib 20.10.1 → 20.10.2

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.
@@ -108,6 +108,52 @@ var report_builder_1 = require("../methods/report-builder");
108
108
  var support_1 = require("../methods/support");
109
109
  var resolveio_server_app_1 = require("../resolveio-server-app");
110
110
  var common_1 = require("../util/common");
111
+ var error_tracking_1 = require("../util/error-tracking");
112
+ function appendCorrelationIdToSubject(subject, correlationId) {
113
+ if (!correlationId) {
114
+ return subject;
115
+ }
116
+ var correlationTag = "[".concat(correlationId, "]");
117
+ if (subject && subject.includes(correlationTag)) {
118
+ return subject;
119
+ }
120
+ return "".concat(subject, " ").concat(correlationTag).trim();
121
+ }
122
+ function createEmailOccurrence(subject, text, html, meta) {
123
+ return {
124
+ _id: (0, common_1.objectIdHexString)(),
125
+ createdAt: new Date(),
126
+ subject: subject,
127
+ text: text,
128
+ html: html,
129
+ meta: meta
130
+ };
131
+ }
132
+ function formatGroupedEmailContent(correlationId, occurrences) {
133
+ var lines = [];
134
+ lines.push("Correlation ID: ".concat(correlationId));
135
+ occurrences.forEach(function (occurrence, index) {
136
+ var timestamp = occurrence.createdAt instanceof Date ? occurrence.createdAt.toISOString() : new Date(occurrence.createdAt).toISOString();
137
+ lines.push('');
138
+ lines.push("Occurrence #".concat(index + 1, " (").concat(timestamp, ")"));
139
+ lines.push("Subject: ".concat(occurrence.subject));
140
+ if (occurrence.text) {
141
+ lines.push(occurrence.text);
142
+ }
143
+ });
144
+ var htmlSections = occurrences.map(function (occurrence, index) {
145
+ var timestamp = occurrence.createdAt instanceof Date ? occurrence.createdAt.toISOString() : new Date(occurrence.createdAt).toISOString();
146
+ var escapedText = occurrence.text ? occurrence.text.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;') : '';
147
+ return "<div><h4>Occurrence #".concat(index + 1, " (").concat(timestamp, ")</h4><p><strong>Subject:</strong> ").concat(occurrence.subject, "</p>").concat(escapedText ? "<pre>".concat(escapedText, "</pre>") : '', "</div>");
148
+ });
149
+ var html = __spreadArray([
150
+ "<p><strong>Correlation ID:</strong> ".concat(correlationId, "</p>")
151
+ ], __read(htmlSections), false).join('');
152
+ return {
153
+ text: lines.join('\n'),
154
+ html: html
155
+ };
156
+ }
111
157
  var AWS = /** @class */ (function () {
112
158
  function AWS() {
113
159
  this._s3 = null;
@@ -163,6 +209,7 @@ var MethodManager = /** @class */ (function () {
163
209
  this._isWorkerInstance = false;
164
210
  this.emailQueue = new Set(); // Set to store pending email IDs
165
211
  this.isEmailProcessing = false;
212
+ this._emailProcessingDelayMs = 5000;
166
213
  this._debugcallMethodHits = 0;
167
214
  this._debugCallMethodHits = 0;
168
215
  this._debugCallMethodCronJobHits = 0;
@@ -304,74 +351,120 @@ var MethodManager = /** @class */ (function () {
304
351
  methodData[_i - 1] = arguments[_i];
305
352
  }
306
353
  return __awaiter(this, void 0, void 0, function () {
307
- var valObj, valKeys, rootKeys, i, err_1, monitor, res, err_2;
308
- var _a;
309
- return __generator(this, function (_b) {
310
- switch (_b.label) {
354
+ var existingCorrelationId, correlationId, execute;
355
+ var _this = this;
356
+ return __generator(this, function (_a) {
357
+ switch (_a.label) {
311
358
  case 0:
312
359
  this._debugCallMethodCronJobHits += 1;
313
- if (!!this._methods[method]) return [3 /*break*/, 2];
314
- console.log('No Method: ' + method);
315
- return [4 /*yield*/, this.sendEmail('dev@resolveio.com', 'SERVER - Error Detected - ' + resolveio_server_app_1.ResolveIOServer.getServerConfig()['CLIENT_NAME'], 'No Method: ' + method)];
316
- case 1:
317
- _b.sent();
318
- throw new Error('No Method: ' + method);
319
- case 2:
320
- if (!((methodData.length > 1 || methodData[0]) && !this._methods[method].skipValidation)) return [3 /*break*/, 10];
321
- if (!!this._methods[method].check) return [3 /*break*/, 4];
322
- console.error(new Date(), 'No Check Function For Cron Method ' + method);
323
- return [4 /*yield*/, this.sendEmail('dev@resolveio.com', 'SERVER - Error Detected - ' + resolveio_server_app_1.ResolveIOServer.getServerConfig()['CLIENT_NAME'], 'No Check Function For Cron Method ' + method)];
324
- case 3:
325
- _b.sent();
326
- throw new Error('No Check Function For Cron Method ' + method);
327
- case 4:
328
- if (!!this._methods[method].check._schema) return [3 /*break*/, 6];
329
- console.error(new Date(), 'No Check Schema For Cron Method ' + method);
330
- return [4 /*yield*/, this.sendEmail('dev@resolveio.com', 'SERVER - Error Detected - ' + resolveio_server_app_1.ResolveIOServer.getServerConfig()['CLIENT_NAME'], 'No Check Function For Cron Method ' + method)];
331
- case 5:
332
- _b.sent();
333
- throw new Error('No Check Schema For Cron Method ' + method);
334
- case 6:
335
- valObj = {};
336
- valKeys = Object.keys(this._methods[method].check._schema);
337
- rootKeys = valKeys.filter(function (a) { return !a.includes('.'); });
338
- for (i = 0; i < methodData.length; i++) {
339
- valObj[rootKeys[i]] = methodData[i];
340
- }
341
- _b.label = 7;
342
- case 7:
343
- _b.trys.push([7, 8, , 10]);
344
- this._methods[method].check.validate(valObj);
345
- return [3 /*break*/, 10];
346
- case 8:
347
- err_1 = _b.sent();
348
- console.error(new Date(), 'Error in Cron Method Check (' + method + ')', err_1);
349
- return [4 /*yield*/, this.sendEmail('dev@resolveio.com', 'SERVER - Error Detected - ' + resolveio_server_app_1.ResolveIOServer.getServerConfig()['CLIENT_NAME'], 'Match Error On Cron Method ' + method + '\n\nData Being Checked\n' + JSON.stringify(valObj, null, 2) + '\n\nErrors\n' + JSON.stringify(err_1, null, 2))];
350
- case 9:
351
- _b.sent();
352
- err_1.message = "".concat(new Date().toISOString(), " - Error in Cron Method Check (").concat(method, "): ").concat(err_1.message);
353
- throw err_1;
354
- case 10:
355
- monitor = this._monitorManagerFunction.startMonitorFunction('Cron Method', method, '', '', methodData);
356
- _b.label = 11;
357
- case 11:
358
- _b.trys.push([11, 13, 15, 17]);
359
- return [4 /*yield*/, (_a = this._methods[method].function).call.apply(_a, __spreadArray([Object.assign({}, this, MethodManager.prototype, { id_user: '', user: '', id_ws: '' })], __read(methodData), false))];
360
- case 12:
361
- res = _b.sent();
362
- return [2 /*return*/, res];
363
- case 13:
364
- err_2 = _b.sent();
365
- return [4 /*yield*/, this.sendEmail('dev@resolveio.com', 'SERVER - Error Detected - ' + resolveio_server_app_1.ResolveIOServer.getServerConfig()['CLIENT_NAME'], 'Error Detected During Cron Method ' + method + ' - (callMethodCron)\n\nData \n' + JSON.stringify(methodData, null, 2) + '\n\nErrors\n' + JSON.stringify(err_2, null, 2))];
366
- case 14:
367
- _b.sent();
368
- err_2.message = "".concat(new Date().toISOString(), " - Error in Cron Method (").concat(method, "): ").concat(err_2.message);
369
- throw err_2;
370
- case 15: return [4 /*yield*/, this._monitorManagerFunction.finishMonitorFunction(monitor)];
371
- case 16:
372
- _b.sent();
373
- return [7 /*endfinally*/];
374
- case 17: return [2 /*return*/];
360
+ existingCorrelationId = (0, error_tracking_1.getCorrelationId)();
361
+ correlationId = existingCorrelationId || (0, common_1.objectIdHexString)();
362
+ execute = function () { return __awaiter(_this, void 0, void 0, function () {
363
+ var cronMethod, valObj, valKeys, rootKeys, i, err_1, _a, normalizedError, resolvedCorrelationId, monitor, res, err_2, _b, normalizedError, resolvedCorrelationId;
364
+ var _c;
365
+ return __generator(this, function (_d) {
366
+ switch (_d.label) {
367
+ case 0:
368
+ cronMethod = this._methods[method];
369
+ if (!!cronMethod) return [3 /*break*/, 2];
370
+ console.log('No Method: ' + method);
371
+ return [4 /*yield*/, this.sendEmail('dev@resolveio.com', 'SERVER - Error Detected - ' + resolveio_server_app_1.ResolveIOServer.getServerConfig()['CLIENT_NAME'], 'No Method: ' + method, null, null, null, null, false, false, {
372
+ correlationId: correlationId,
373
+ meta: {
374
+ context: 'callMethodCron',
375
+ method: method
376
+ }
377
+ })];
378
+ case 1:
379
+ _d.sent();
380
+ throw new Error('No Method: ' + method);
381
+ case 2:
382
+ if (!((methodData.length > 1 || methodData[0]) && !cronMethod.skipValidation)) return [3 /*break*/, 10];
383
+ if (!!cronMethod.check) return [3 /*break*/, 4];
384
+ console.error(new Date(), 'No Check Function For Cron Method ' + method);
385
+ return [4 /*yield*/, this.sendEmail('dev@resolveio.com', 'SERVER - Error Detected - ' + resolveio_server_app_1.ResolveIOServer.getServerConfig()['CLIENT_NAME'], 'No Check Function For Cron Method ' + method, null, null, null, null, false, false, {
386
+ correlationId: correlationId,
387
+ meta: {
388
+ context: 'callMethodCron-validation',
389
+ method: method
390
+ }
391
+ })];
392
+ case 3:
393
+ _d.sent();
394
+ throw new Error('No Check Function For Cron Method ' + method);
395
+ case 4:
396
+ if (!!cronMethod.check._schema) return [3 /*break*/, 6];
397
+ console.error(new Date(), 'No Check Schema For Cron Method ' + method);
398
+ return [4 /*yield*/, this.sendEmail('dev@resolveio.com', 'SERVER - Error Detected - ' + resolveio_server_app_1.ResolveIOServer.getServerConfig()['CLIENT_NAME'], 'No Check Function For Cron Method ' + method, null, null, null, null, false, false, {
399
+ correlationId: correlationId,
400
+ meta: {
401
+ context: 'callMethodCron-validation',
402
+ method: method
403
+ }
404
+ })];
405
+ case 5:
406
+ _d.sent();
407
+ throw new Error('No Check Schema For Cron Method ' + method);
408
+ case 6:
409
+ valObj = {};
410
+ valKeys = Object.keys(cronMethod.check._schema);
411
+ rootKeys = valKeys.filter(function (a) { return !a.includes('.'); });
412
+ for (i = 0; i < methodData.length; i++) {
413
+ valObj[rootKeys[i]] = methodData[i];
414
+ }
415
+ _d.label = 7;
416
+ case 7:
417
+ _d.trys.push([7, 8, , 10]);
418
+ cronMethod.check.validate(valObj);
419
+ return [3 /*break*/, 10];
420
+ case 8:
421
+ err_1 = _d.sent();
422
+ console.error(new Date(), 'Error in Cron Method Check (' + method + ')', err_1);
423
+ _a = (0, error_tracking_1.ensureErrorWithCorrelation)(err_1, correlationId), normalizedError = _a.error, resolvedCorrelationId = _a.correlationId;
424
+ return [4 /*yield*/, this.sendEmail('dev@resolveio.com', 'SERVER - Error Detected - ' + resolveio_server_app_1.ResolveIOServer.getServerConfig()['CLIENT_NAME'], 'Match Error On Cron Method ' + method + '\n\nData Being Checked\n' + JSON.stringify(valObj, null, 2) + '\n\nErrors\n' + JSON.stringify(normalizedError, null, 2), null, null, null, null, false, false, {
425
+ correlationId: resolvedCorrelationId,
426
+ meta: {
427
+ context: 'callMethodCron-validation-error',
428
+ method: method
429
+ }
430
+ })];
431
+ case 9:
432
+ _d.sent();
433
+ normalizedError.message = "".concat(new Date().toISOString(), " - Error in Cron Method Check (").concat(method, "): ").concat(normalizedError.message);
434
+ throw normalizedError;
435
+ case 10:
436
+ monitor = this._monitorManagerFunction.startMonitorFunction('Cron Method', method, '', '', methodData);
437
+ _d.label = 11;
438
+ case 11:
439
+ _d.trys.push([11, 13, 15, 17]);
440
+ return [4 /*yield*/, (_c = cronMethod.function).call.apply(_c, __spreadArray([Object.assign({}, this, MethodManager.prototype, { id_user: '', user: '', id_ws: '' })], __read(methodData), false))];
441
+ case 12:
442
+ res = _d.sent();
443
+ return [2 /*return*/, res];
444
+ case 13:
445
+ err_2 = _d.sent();
446
+ _b = (0, error_tracking_1.ensureErrorWithCorrelation)(err_2, correlationId), normalizedError = _b.error, resolvedCorrelationId = _b.correlationId;
447
+ return [4 /*yield*/, this.sendEmail('dev@resolveio.com', 'SERVER - Error Detected - ' + resolveio_server_app_1.ResolveIOServer.getServerConfig()['CLIENT_NAME'], 'Error Detected During Cron Method ' + method + ' - (callMethodCron)\n\nData \n' + JSON.stringify(methodData, null, 2) + '\n\nErrors\n' + JSON.stringify(normalizedError, null, 2), null, null, null, null, false, false, {
448
+ correlationId: resolvedCorrelationId,
449
+ meta: {
450
+ context: 'callMethodCron-execution',
451
+ method: method
452
+ }
453
+ })];
454
+ case 14:
455
+ _d.sent();
456
+ normalizedError.message = "".concat(new Date().toISOString(), " - Error in Cron Method (").concat(method, "): ").concat(normalizedError.message);
457
+ throw normalizedError;
458
+ case 15: return [4 /*yield*/, this._monitorManagerFunction.finishMonitorFunction(monitor)];
459
+ case 16:
460
+ _d.sent();
461
+ return [7 /*endfinally*/];
462
+ case 17: return [2 /*return*/];
463
+ }
464
+ });
465
+ }); };
466
+ return [4 /*yield*/, (0, error_tracking_1.runWithCorrelationContext)(correlationId, execute)];
467
+ case 1: return [2 /*return*/, _a.sent()];
375
468
  }
376
469
  });
377
470
  });
@@ -383,13 +476,33 @@ var MethodManager = /** @class */ (function () {
383
476
  methodData[_i - 1] = arguments[_i];
384
477
  }
385
478
  return __awaiter(this, void 0, void 0, function () {
386
- var method, functionMethodData, session, monitor_2, monitor, res, err_3;
387
- var _a;
479
+ var existingCorrelationId, correlationId;
388
480
  var _this = this;
389
- return __generator(this, function (_b) {
390
- switch (_b.label) {
481
+ return __generator(this, function (_a) {
482
+ switch (_a.label) {
391
483
  case 0:
392
484
  this._debugcallMethodHits += 1;
485
+ existingCorrelationId = (0, error_tracking_1.getCorrelationId)();
486
+ correlationId = existingCorrelationId || (0, common_1.objectIdHexString)();
487
+ return [4 /*yield*/, (0, error_tracking_1.runWithCorrelationContext)(correlationId, function () { return __awaiter(_this, void 0, void 0, function () { return __generator(this, function (_a) {
488
+ switch (_a.label) {
489
+ case 0: return [4 /*yield*/, this.callMethodInternal(correlationId, methodName, methodData)];
490
+ case 1: return [2 /*return*/, _a.sent()];
491
+ }
492
+ }); }); })];
493
+ case 1: return [2 /*return*/, _a.sent()];
494
+ }
495
+ });
496
+ });
497
+ };
498
+ MethodManager.prototype.callMethodInternal = function (correlationId, methodName, methodData) {
499
+ return __awaiter(this, void 0, void 0, function () {
500
+ var method, functionMethodData, session, monitor_2, monitor, res, err_3, _a, normalizedError, resolvedCorrelationId;
501
+ var _b;
502
+ var _this = this;
503
+ return __generator(this, function (_c) {
504
+ switch (_c.label) {
505
+ case 0:
393
506
  method = this.getMethod(methodName);
394
507
  if (!method) {
395
508
  console.log('No Method: ' + methodName);
@@ -421,7 +534,8 @@ var MethodManager = /** @class */ (function () {
421
534
  id_user: this['id_user'] || '',
422
535
  user: this['user'] || '',
423
536
  messageId: 0,
424
- route: ''
537
+ route: '',
538
+ correlationId: correlationId
425
539
  }
426
540
  });
427
541
  return [3 /*break*/, 3];
@@ -438,14 +552,15 @@ var MethodManager = /** @class */ (function () {
438
552
  route: '',
439
553
  client: 'ResolveIO',
440
554
  instance: 'backend.resolveio.com',
441
- instance_index: process.env.NODE_APP_INSTANCE || ''
555
+ instance_index: process.env.NODE_APP_INSTANCE || '',
556
+ correlationId: correlationId
442
557
  })];
443
558
  case 2:
444
- _b.sent();
445
- _b.label = 3;
559
+ _c.sent();
560
+ _c.label = 3;
446
561
  case 3:
447
562
  ;
448
- _b.label = 4;
563
+ _c.label = 4;
449
564
  case 4:
450
565
  functionMethodData = typeof (methodData[methodData.length - 1]) === 'function' ? methodData.slice(0, -1) : methodData;
451
566
  session = resolveio_server_app_1.ResolveIOServer.getMongoManager().getSession();
@@ -460,50 +575,68 @@ var MethodManager = /** @class */ (function () {
460
575
  !methodName.startsWith('log'))) return [3 /*break*/, 5];
461
576
  monitor_2 = null;
462
577
  return [2 /*return*/, resolveio_server_app_1.ResolveIOServer.getMongoManager().oneTimeTransaction(function () { return __awaiter(_this, void 0, void 0, function () {
463
- var res, err_4;
464
- var _a;
465
- return __generator(this, function (_b) {
466
- switch (_b.label) {
578
+ var res, err_4, _a, normalizedError, resolvedCorrelationId;
579
+ var _b;
580
+ return __generator(this, function (_c) {
581
+ switch (_c.label) {
467
582
  case 0:
468
583
  // console.log(new Date(), 'Calling Method - New Session', methodName);
469
584
  monitor_2 = this._monitorManagerFunction.startMonitorFunction('Method', methodName, this['user'] || '', '', functionMethodData);
470
- _b.label = 1;
585
+ _c.label = 1;
471
586
  case 1:
472
- _b.trys.push([1, 3, 7, 9]);
473
- return [4 /*yield*/, (_a = method.function).call.apply(_a, __spreadArray([Object.assign({}, this, MethodManager.prototype)], __read(functionMethodData), false))];
587
+ _c.trys.push([1, 3, 7, 9]);
588
+ return [4 /*yield*/, (_b = method.function).call.apply(_b, __spreadArray([Object.assign({}, this, MethodManager.prototype)], __read(functionMethodData), false))];
474
589
  case 2:
475
- res = _b.sent();
590
+ res = _c.sent();
476
591
  if (methodData[methodData.length - 1] && typeof (methodData[methodData.length - 1]) === 'function') {
477
592
  methodData[methodData.length - 1](null, res);
478
593
  }
479
594
  return [2 /*return*/, res];
480
595
  case 3:
481
- err_4 = _b.sent();
596
+ err_4 = _c.sent();
482
597
  if (err_4.code === 112 || err_4.codeName === 'WriteConflict' || err_4.code === 251 || err_4.codeName === 'NoSuchTransaction') {
483
598
  throw err_4; // Write error, retry
484
599
  }
600
+ _a = (0, error_tracking_1.ensureErrorWithCorrelation)(err_4, correlationId), normalizedError = _a.error, resolvedCorrelationId = _a.correlationId;
485
601
  console.log(JSON.stringify([new Date(), 'Error Method Manager - Run Method - New Session', methodName, {
486
- code: err_4.code,
487
- codeName: err_4.codeName,
488
- message: err_4.message,
489
- stack: err_4.stack
602
+ code: normalizedError.code,
603
+ codeName: normalizedError.codeName,
604
+ message: normalizedError.message,
605
+ stack: normalizedError.stack,
606
+ correlationId: resolvedCorrelationId
490
607
  }], null, 2));
491
- return [4 /*yield*/, this.sendEmail('dev@resolveio.com', 'SERVER - Error Detected - ' + resolveio_server_app_1.ResolveIOServer.getServerConfig()['CLIENT_NAME'], 'Error Detected During Method ' + methodName + ' - (callMethod)\n\nData \n' + JSON.stringify(methodData, null, 2) + '\n\nErrors\n' + JSON.stringify(err_4, null, 2))];
608
+ return [4 /*yield*/, this.sendEmail('dev@resolveio.com', 'SERVER - Error Detected - ' + resolveio_server_app_1.ResolveIOServer.getServerConfig()['CLIENT_NAME'], 'Error Detected During Method ' + methodName + ' - (callMethod)\n\nData \n' + JSON.stringify(methodData, null, 2) + '\n\nErrors\n' + JSON.stringify(normalizedError, null, 2), null, null, null, null, false, false, {
609
+ correlationId: resolvedCorrelationId,
610
+ meta: {
611
+ context: 'callMethod-new-session',
612
+ methodName: methodName
613
+ }
614
+ })];
492
615
  case 4:
493
- _b.sent();
494
- err_4.message = "".concat(new Date().toISOString(), " - Error in Method With Session (").concat(methodName, ") - New Session: ").concat(err_4.message);
616
+ _c.sent();
617
+ normalizedError.message = "".concat(new Date().toISOString(), " - Error in Method With Session (").concat(methodName, ") - New Session: ").concat(normalizedError.message);
495
618
  if (methodData[methodData.length - 1] && typeof (methodData[methodData.length - 1]) === 'function') {
496
- methodData[methodData.length - 1](err_4, null);
619
+ methodData[methodData.length - 1](normalizedError, null);
497
620
  }
498
621
  if (!!process.env.IS_WORKER_INSTANCE) return [3 /*break*/, 6];
499
- return [4 /*yield*/, this.callMethod('insertErrorLog', "Error in Method: ".concat(methodName, " - ").concat(JSON.stringify(methodData, null, 2)))];
622
+ return [4 /*yield*/, this.callMethod('insertErrorLog', "Error in Method: ".concat(methodName), {
623
+ method: methodName,
624
+ methodData: methodData,
625
+ error: {
626
+ message: normalizedError.message,
627
+ stack: normalizedError.stack,
628
+ code: normalizedError.code,
629
+ codeName: normalizedError.codeName
630
+ },
631
+ correlationId: resolvedCorrelationId
632
+ })];
500
633
  case 5:
501
- _b.sent();
502
- _b.label = 6;
503
- case 6: throw err_4;
634
+ _c.sent();
635
+ _c.label = 6;
636
+ case 6: throw normalizedError;
504
637
  case 7: return [4 /*yield*/, this._monitorManagerFunction.finishMonitorFunction(monitor_2)];
505
638
  case 8:
506
- _b.sent();
639
+ _c.sent();
507
640
  return [7 /*endfinally*/];
508
641
  case 9: return [2 /*return*/];
509
642
  }
@@ -511,43 +644,61 @@ var MethodManager = /** @class */ (function () {
511
644
  }); })];
512
645
  case 5:
513
646
  monitor = this._monitorManagerFunction.startMonitorFunction('Method', methodName, this['user'] || '', '', functionMethodData);
514
- _b.label = 6;
647
+ _c.label = 6;
515
648
  case 6:
516
- _b.trys.push([6, 8, 12, 14]);
517
- return [4 /*yield*/, (_a = method.function).call.apply(_a, __spreadArray([Object.assign({}, this, MethodManager.prototype)], __read(functionMethodData), false))];
649
+ _c.trys.push([6, 8, 12, 14]);
650
+ return [4 /*yield*/, (_b = method.function).call.apply(_b, __spreadArray([Object.assign({}, this, MethodManager.prototype)], __read(functionMethodData), false))];
518
651
  case 7:
519
- res = _b.sent();
652
+ res = _c.sent();
520
653
  if (methodData[methodData.length - 1] && typeof (methodData[methodData.length - 1]) === 'function') {
521
654
  methodData[methodData.length - 1](null, res);
522
655
  }
523
656
  return [2 /*return*/, res];
524
657
  case 8:
525
- err_3 = _b.sent();
658
+ err_3 = _c.sent();
526
659
  if (err_3.code === 112 || err_3.codeName === 'WriteConflict' || err_3.code === 251 || err_3.codeName === 'NoSuchTransaction') {
527
660
  throw err_3; // Write error, retry
528
661
  }
662
+ _a = (0, error_tracking_1.ensureErrorWithCorrelation)(err_3, correlationId), normalizedError = _a.error, resolvedCorrelationId = _a.correlationId;
529
663
  console.log(JSON.stringify([new Date(), 'Error Method Manager - Run Method - Existing Session', methodName, {
530
- code: err_3.code,
531
- codeName: err_3.codeName,
532
- message: err_3.message,
533
- stack: err_3.stack
664
+ code: normalizedError.code,
665
+ codeName: normalizedError.codeName,
666
+ message: normalizedError.message,
667
+ stack: normalizedError.stack,
668
+ correlationId: resolvedCorrelationId
534
669
  }], null, 2));
535
- return [4 /*yield*/, this.sendEmail('dev@resolveio.com', 'SERVER - Error Detected - ' + resolveio_server_app_1.ResolveIOServer.getServerConfig()['CLIENT_NAME'], 'Error Detected During Method ' + methodName + ' - (callMethod)\n\nData \n' + JSON.stringify(methodData, null, 2) + '\n\nErrors\n' + JSON.stringify(err_3, null, 2))];
670
+ return [4 /*yield*/, this.sendEmail('dev@resolveio.com', 'SERVER - Error Detected - ' + resolveio_server_app_1.ResolveIOServer.getServerConfig()['CLIENT_NAME'], 'Error Detected During Method ' + methodName + ' - (callMethod)\n\nData \n' + JSON.stringify(methodData, null, 2) + '\n\nErrors\n' + JSON.stringify(normalizedError, null, 2), null, null, null, null, false, false, {
671
+ correlationId: resolvedCorrelationId,
672
+ meta: {
673
+ context: 'callMethod-existing-session',
674
+ methodName: methodName
675
+ }
676
+ })];
536
677
  case 9:
537
- _b.sent();
538
- err_3.message = "".concat(new Date().toISOString(), " - Error in Method (").concat(methodName, ") - Existing Session: ").concat(err_3.message);
678
+ _c.sent();
679
+ normalizedError.message = "".concat(new Date().toISOString(), " - Error in Method (").concat(methodName, ") - Existing Session: ").concat(normalizedError.message);
539
680
  if (methodData[methodData.length - 1] && typeof (methodData[methodData.length - 1]) === 'function') {
540
- methodData[methodData.length - 1](err_3, null);
681
+ methodData[methodData.length - 1](normalizedError, null);
541
682
  }
542
683
  if (!!process.env.IS_WORKER_INSTANCE) return [3 /*break*/, 11];
543
- return [4 /*yield*/, this.callMethod('insertErrorLog', "Error in Method: ".concat(methodName, " - ").concat(JSON.stringify(methodData, null, 2)))];
684
+ return [4 /*yield*/, this.callMethod('insertErrorLog', "Error in Method: ".concat(methodName), {
685
+ method: methodName,
686
+ methodData: methodData,
687
+ error: {
688
+ message: normalizedError.message,
689
+ stack: normalizedError.stack,
690
+ code: normalizedError.code,
691
+ codeName: normalizedError.codeName
692
+ },
693
+ correlationId: resolvedCorrelationId
694
+ })];
544
695
  case 10:
545
- _b.sent();
546
- _b.label = 11;
547
- case 11: throw err_3;
696
+ _c.sent();
697
+ _c.label = 11;
698
+ case 11: throw normalizedError;
548
699
  case 12: return [4 /*yield*/, this._monitorManagerFunction.finishMonitorFunction(monitor)];
549
700
  case 13:
550
- _b.sent();
701
+ _c.sent();
551
702
  return [7 /*endfinally*/];
552
703
  case 14: return [2 /*return*/];
553
704
  }
@@ -643,48 +794,76 @@ var MethodManager = /** @class */ (function () {
643
794
  case 1:
644
795
  _a.trys.push([1, 5, 6, 9]);
645
796
  _loop_1 = function () {
646
- var emailId, emailHistory, validAttachments, attachmentError, _b, _c, att, response, arrayBuffer, buffer, maxSize, err_6, e_2_1, mailOptions;
797
+ var emailId, pendingEmail, queuedAt, timeSinceQueued, remainingDelay, emailHistory, validAttachments, attachmentError, _b, _c, att, response, arrayBuffer, buffer, maxSize, err_6, e_2_1, mailOptions;
647
798
  var e_2, _d;
648
799
  return __generator(this, function (_e) {
649
800
  switch (_e.label) {
650
801
  case 0:
651
802
  emailId = this_1.emailQueue.values().next().value;
652
803
  this_1.emailQueue.delete(emailId);
653
- return [4 /*yield*/, email_history_collection_1.EmailHistories.findOneAndUpdate({
804
+ return [4 /*yield*/, email_history_collection_1.EmailHistories.findOne({
654
805
  _id: emailId,
655
806
  status: 'pending',
656
- }, {
657
- $set: { status: 'processing', processingAt: new Date() },
658
807
  })];
659
808
  case 1:
809
+ pendingEmail = _e.sent();
810
+ if (!pendingEmail) {
811
+ return [2 /*return*/, "continue"];
812
+ }
813
+ queuedAt = void 0;
814
+ if (pendingEmail.date instanceof Date) {
815
+ queuedAt = pendingEmail.date;
816
+ }
817
+ else if (pendingEmail.createdAt instanceof Date) {
818
+ queuedAt = pendingEmail.createdAt;
819
+ }
820
+ else {
821
+ queuedAt = new Date();
822
+ }
823
+ timeSinceQueued = Date.now() - queuedAt.getTime();
824
+ remainingDelay = this_1._emailProcessingDelayMs - timeSinceQueued;
825
+ if (!(remainingDelay > 0)) return [3 /*break*/, 3];
826
+ // eslint-disable-next-line no-restricted-syntax
827
+ return [4 /*yield*/, new Promise(function (resolve) { return setTimeout(resolve, remainingDelay); })];
828
+ case 2:
829
+ // eslint-disable-next-line no-restricted-syntax
830
+ _e.sent();
831
+ _e.label = 3;
832
+ case 3: return [4 /*yield*/, email_history_collection_1.EmailHistories.findOneAndUpdate({
833
+ _id: emailId,
834
+ status: 'pending',
835
+ }, {
836
+ $set: { status: 'processing', processingAt: new Date() },
837
+ })];
838
+ case 4:
660
839
  emailHistory = _e.sent();
661
840
  if (!emailHistory) {
662
841
  return [2 /*return*/, "continue"];
663
842
  }
664
- if (!(emailHistory.attachments && emailHistory.attachments.length > 0)) return [3 /*break*/, 15];
843
+ if (!(emailHistory.attachments && emailHistory.attachments.length > 0)) return [3 /*break*/, 18];
665
844
  validAttachments = [];
666
845
  attachmentError = false;
667
- _e.label = 2;
668
- case 2:
669
- _e.trys.push([2, 12, 13, 14]);
846
+ _e.label = 5;
847
+ case 5:
848
+ _e.trys.push([5, 15, 16, 17]);
670
849
  _b = (e_2 = void 0, __values(emailHistory.attachments)), _c = _b.next();
671
- _e.label = 3;
672
- case 3:
673
- if (!!_c.done) return [3 /*break*/, 11];
850
+ _e.label = 6;
851
+ case 6:
852
+ if (!!_c.done) return [3 /*break*/, 14];
674
853
  att = _c.value;
675
- if (!(att.path && att.path.startsWith('http'))) return [3 /*break*/, 9];
676
- _e.label = 4;
677
- case 4:
678
- _e.trys.push([4, 7, , 8]);
854
+ if (!(att.path && att.path.startsWith('http'))) return [3 /*break*/, 12];
855
+ _e.label = 7;
856
+ case 7:
857
+ _e.trys.push([7, 10, , 11]);
679
858
  return [4 /*yield*/, fetch(att.path)];
680
- case 5:
859
+ case 8:
681
860
  response = _e.sent();
682
861
  if (!response.ok) {
683
862
  attachmentError = true;
684
- return [3 /*break*/, 10];
863
+ return [3 /*break*/, 13];
685
864
  }
686
865
  return [4 /*yield*/, response.arrayBuffer()];
687
- case 6:
866
+ case 9:
688
867
  arrayBuffer = _e.sent();
689
868
  buffer = Buffer.from(arrayBuffer);
690
869
  maxSize = 20 * 1024 * 1024;
@@ -694,31 +873,31 @@ var MethodManager = /** @class */ (function () {
694
873
  delete att.path;
695
874
  validAttachments.push(att);
696
875
  }
697
- return [3 /*break*/, 8];
698
- case 7:
876
+ return [3 /*break*/, 11];
877
+ case 10:
699
878
  err_6 = _e.sent();
700
879
  console.error('Failed to fetch attachment:', err_6);
701
880
  attachmentError = true;
702
- return [3 /*break*/, 8];
703
- case 8: return [3 /*break*/, 10];
704
- case 9:
881
+ return [3 /*break*/, 11];
882
+ case 11: return [3 /*break*/, 13];
883
+ case 12:
705
884
  validAttachments.push(att);
706
- _e.label = 10;
707
- case 10:
885
+ _e.label = 13;
886
+ case 13:
708
887
  _c = _b.next();
709
- return [3 /*break*/, 3];
710
- case 11: return [3 /*break*/, 14];
711
- case 12:
888
+ return [3 /*break*/, 6];
889
+ case 14: return [3 /*break*/, 17];
890
+ case 15:
712
891
  e_2_1 = _e.sent();
713
892
  e_2 = { error: e_2_1 };
714
- return [3 /*break*/, 14];
715
- case 13:
893
+ return [3 /*break*/, 17];
894
+ case 16:
716
895
  try {
717
896
  if (_c && !_c.done && (_d = _b.return)) _d.call(_b);
718
897
  }
719
898
  finally { if (e_2) throw e_2.error; }
720
899
  return [7 /*endfinally*/];
721
- case 14:
900
+ case 17:
722
901
  emailHistory.attachments = validAttachments;
723
902
  if (attachmentError) {
724
903
  emailHistory.text =
@@ -728,8 +907,8 @@ var MethodManager = /** @class */ (function () {
728
907
  (typeof emailHistory.html === 'string' ? emailHistory.html : '') +
729
908
  '<p>Could not load attachments.</p>';
730
909
  }
731
- _e.label = 15;
732
- case 15:
910
+ _e.label = 18;
911
+ case 18:
733
912
  mailOptions = {
734
913
  replyTo: emailHistory.reply_to || (resolveio_server_app_1.ResolveIOServer.getServerConfig()['MAIL_REPLY_TO'] || undefined),
735
914
  from: emailHistory.send_from || resolveio_server_app_1.ResolveIOServer.getServerConfig().MAIL_FROM,
@@ -825,7 +1004,7 @@ var MethodManager = /** @class */ (function () {
825
1004
  // Wait for at least one second before sending the next email
826
1005
  // eslint-disable-next-line no-restricted-syntax
827
1006
  return [4 /*yield*/, new Promise(function (resolve) { return setTimeout(resolve, 1000); })];
828
- case 16:
1007
+ case 19:
829
1008
  // Wait for at least one second before sending the next email
830
1009
  // eslint-disable-next-line no-restricted-syntax
831
1010
  _e.sent();
@@ -879,13 +1058,60 @@ var MethodManager = /** @class */ (function () {
879
1058
  return value;
880
1059
  };
881
1060
  };
882
- MethodManager.prototype.sendEmail = function (sendTo, subject, text, html, attachments, send_from, reply_to, force_ses, local_override) {
1061
+ MethodManager.prototype.tryMergeEmailOccurrence = function (email, subject, correlationId, occurrence, meta) {
1062
+ return __awaiter(this, void 0, void 0, function () {
1063
+ var existing, normalizedOccurrences, _a, aggregatedText, aggregatedHtml, updated;
1064
+ return __generator(this, function (_b) {
1065
+ switch (_b.label) {
1066
+ case 0: return [4 /*yield*/, email_history_collection_1.EmailHistories.findOne({
1067
+ email: email,
1068
+ correlationId: correlationId,
1069
+ status: 'pending'
1070
+ }, { sort: { date: 1 } })];
1071
+ case 1:
1072
+ existing = _b.sent();
1073
+ if (!existing) {
1074
+ return [2 /*return*/, null];
1075
+ }
1076
+ normalizedOccurrences = Array.isArray(existing.occurrences) && existing.occurrences.length
1077
+ ? existing.occurrences.map(function (item) { return ({
1078
+ _id: item._id || (0, common_1.objectIdHexString)(),
1079
+ createdAt: item.createdAt instanceof Date ? item.createdAt : new Date(item.createdAt),
1080
+ subject: item.subject || existing.subject || '',
1081
+ text: item.text,
1082
+ html: item.html,
1083
+ meta: item.meta
1084
+ }); })
1085
+ : [createEmailOccurrence(existing.subject || '', typeof existing.text === 'string' ? existing.text : undefined, typeof existing.html === 'string' ? existing.html : undefined, existing.meta)];
1086
+ normalizedOccurrences.push(occurrence);
1087
+ _a = formatGroupedEmailContent(correlationId, normalizedOccurrences), aggregatedText = _a.text, aggregatedHtml = _a.html;
1088
+ return [4 /*yield*/, email_history_collection_1.EmailHistories.findOneAndUpdate({
1089
+ _id: existing._id,
1090
+ status: 'pending'
1091
+ }, {
1092
+ $set: {
1093
+ subject: subject,
1094
+ text: aggregatedText,
1095
+ html: aggregatedHtml,
1096
+ occurrences: normalizedOccurrences,
1097
+ meta: meta || existing.meta,
1098
+ updatedAt: new Date()
1099
+ }
1100
+ }, { returnDocument: 'after' })];
1101
+ case 2:
1102
+ updated = _b.sent();
1103
+ return [2 /*return*/, updated || null];
1104
+ }
1105
+ });
1106
+ });
1107
+ };
1108
+ MethodManager.prototype.sendEmail = function (sendTo, subject, text, html, attachments, send_from, reply_to, force_ses, local_override, options) {
883
1109
  if (force_ses === void 0) { force_ses = false; }
884
1110
  if (local_override === void 0) { local_override = false; }
885
1111
  return __awaiter(this, void 0, void 0, function () {
886
- var emailHistory, history_1, err_7;
887
- return __generator(this, function (_a) {
888
- switch (_a.label) {
1112
+ var normalizedSubject, correlationId, finalSubject, groupByCorrelationId, normalizedText, normalizedHtml, occurrence, allowGrouping, normalizedAttachments, merged, emailHistory, _a, aggregatedText, aggregatedHtml, history_1, err_7;
1113
+ return __generator(this, function (_b) {
1114
+ switch (_b.label) {
889
1115
  case 0:
890
1116
  // Modify sendTo in development environments
891
1117
  if ((resolveio_server_app_1.ResolveIOServer.getServerConfig()['ROOT_URL'].match(/https:\/\/dev\./) ||
@@ -894,17 +1120,27 @@ var MethodManager = /** @class */ (function () {
894
1120
  !sendTo.match(/\@resolveio\.com/)) {
895
1121
  sendTo = 'dev@resolveio.com';
896
1122
  }
897
- if (!sendTo) return [3 /*break*/, 7];
1123
+ normalizedSubject = subject || '';
1124
+ correlationId = options === null || options === void 0 ? void 0 : options.correlationId;
1125
+ finalSubject = appendCorrelationIdToSubject(normalizedSubject, correlationId);
1126
+ groupByCorrelationId = !!correlationId;
1127
+ normalizedText = typeof text === 'string' ? text : '';
1128
+ normalizedHtml = typeof html === 'string' ? html : '';
1129
+ occurrence = groupByCorrelationId
1130
+ ? createEmailOccurrence(normalizedSubject, normalizedText, normalizedHtml, options === null || options === void 0 ? void 0 : options.meta)
1131
+ : null;
1132
+ allowGrouping = groupByCorrelationId;
1133
+ if (!sendTo) return [3 /*break*/, 9];
898
1134
  if (!(resolveio_server_app_1.ResolveIOServer.getServerConfig()['ROOT_URL'] !== 'http://localhost:4200' ||
899
- local_override)) return [3 /*break*/, 5];
900
- if (!attachments) {
901
- attachments = [];
1135
+ local_override)) return [3 /*break*/, 7];
1136
+ normalizedAttachments = [];
1137
+ if (Array.isArray(attachments)) {
1138
+ normalizedAttachments = attachments.slice();
902
1139
  }
903
- if (!Array.isArray(attachments)) {
904
- attachments = [attachments];
1140
+ else if (attachments) {
1141
+ normalizedAttachments = [attachments];
905
1142
  }
906
- // Process attachments before saving
907
- attachments = attachments.map(function (att) {
1143
+ normalizedAttachments = normalizedAttachments.map(function (att) {
908
1144
  var newAtt = __assign({}, att);
909
1145
  if (Buffer.isBuffer(newAtt.content)) {
910
1146
  newAtt.content = newAtt.content.toString('base64');
@@ -912,6 +1148,18 @@ var MethodManager = /** @class */ (function () {
912
1148
  }
913
1149
  return newAtt;
914
1150
  });
1151
+ if (normalizedAttachments.length > 0) {
1152
+ allowGrouping = false;
1153
+ }
1154
+ if (!(allowGrouping && occurrence && correlationId)) return [3 /*break*/, 2];
1155
+ return [4 /*yield*/, this.tryMergeEmailOccurrence(sendTo, finalSubject, correlationId, occurrence, options === null || options === void 0 ? void 0 : options.meta)];
1156
+ case 1:
1157
+ merged = _b.sent();
1158
+ if (merged) {
1159
+ return [2 /*return*/, merged];
1160
+ }
1161
+ _b.label = 2;
1162
+ case 2:
915
1163
  emailHistory = {
916
1164
  _id: (0, common_1.objectIdHexString)(),
917
1165
  __v: 0,
@@ -919,35 +1167,53 @@ var MethodManager = /** @class */ (function () {
919
1167
  id_user: this['id_user'] || '',
920
1168
  user: this['user'] || '',
921
1169
  email: sendTo,
922
- subject: subject || '',
923
- text: text || '',
924
- html: html || '',
925
- attachments: attachments || [],
1170
+ subject: finalSubject,
1171
+ text: normalizedText,
1172
+ html: normalizedHtml,
1173
+ attachments: normalizedAttachments,
926
1174
  send_from: send_from || '',
927
1175
  reply_to: reply_to || '',
928
1176
  status: 'pending',
929
1177
  error: '',
930
1178
  force_ses: force_ses
931
1179
  };
932
- _a.label = 1;
933
- case 1:
934
- _a.trys.push([1, 3, , 4]);
1180
+ if (allowGrouping && occurrence && correlationId) {
1181
+ _a = formatGroupedEmailContent(correlationId, [occurrence]), aggregatedText = _a.text, aggregatedHtml = _a.html;
1182
+ emailHistory.text = aggregatedText;
1183
+ emailHistory.html = aggregatedHtml;
1184
+ emailHistory.occurrences = [occurrence];
1185
+ emailHistory.correlationId = correlationId;
1186
+ if (options === null || options === void 0 ? void 0 : options.meta) {
1187
+ emailHistory.meta = options.meta;
1188
+ }
1189
+ }
1190
+ else {
1191
+ if (correlationId) {
1192
+ emailHistory.correlationId = correlationId;
1193
+ }
1194
+ if (options === null || options === void 0 ? void 0 : options.meta) {
1195
+ emailHistory.meta = options.meta;
1196
+ }
1197
+ }
1198
+ _b.label = 3;
1199
+ case 3:
1200
+ _b.trys.push([3, 5, , 6]);
935
1201
  return [4 /*yield*/, email_history_collection_1.EmailHistories.insertOne(emailHistory)];
936
- case 2:
937
- history_1 = _a.sent();
1202
+ case 4:
1203
+ history_1 = _b.sent();
938
1204
  return [2 /*return*/, history_1];
939
- case 3:
940
- err_7 = _a.sent();
1205
+ case 5:
1206
+ err_7 = _b.sent();
941
1207
  console.error('Failed to queue email:', err_7);
942
1208
  err_7.message = "Failed to queue email: ".concat(err_7.message);
943
1209
  throw err_7;
944
- case 4: return [3 /*break*/, 6];
945
- case 5:
946
- console.log('Send email', sendTo, subject, text, html, attachments, send_from, force_ses);
947
- return [2 /*return*/, true];
948
1210
  case 6: return [3 /*break*/, 8];
949
- case 7: return [2 /*return*/, true];
950
- case 8: return [2 /*return*/];
1211
+ case 7:
1212
+ console.log('Send email', sendTo, finalSubject, normalizedText, normalizedHtml, attachments, send_from, force_ses, correlationId);
1213
+ return [2 /*return*/, true];
1214
+ case 8: return [3 /*break*/, 10];
1215
+ case 9: return [2 /*return*/, true];
1216
+ case 10: return [2 /*return*/];
951
1217
  }
952
1218
  });
953
1219
  });