@nimee/initialize-ms 1.0.75 → 1.0.78

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.
@@ -5,6 +5,12 @@ declare class AppInitializer {
5
5
  server: any;
6
6
  private serviceName;
7
7
  initialize(server: any, serverType: string, serviceName: string, entryPointsInitializer: any, connectionString: string, dbConnection: any, blackFeatureList: Array<string>, port: number): Promise<void>;
8
+ /**
9
+ * Setup periodic health status logging (optional)
10
+ * Only active when LOG_HEALTH_STATUS=true and using V2 connection
11
+ */
12
+ private setupPeriodicHealthLogging;
8
13
  }
9
14
  export default AppInitializer;
10
15
  export { TracerCoralogix };
16
+ export { default as mongooseConnectionV2 } from "./mongooseConnectionV2";
package/dist/src/index.js CHANGED
@@ -1,4 +1,27 @@
1
1
  "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
2
25
  var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
26
  function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
27
  return new (P || (P = Promise))(function (resolve, reject) {
@@ -12,7 +35,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
12
35
  return (mod && mod.__esModule) ? mod : { "default": mod };
13
36
  };
14
37
  Object.defineProperty(exports, "__esModule", { value: true });
15
- exports.TracerCoralogix = void 0;
38
+ exports.mongooseConnectionV2 = exports.TracerCoralogix = void 0;
16
39
  const tracerCoralogix_1 = __importDefault(require("./tracerCoralogix"));
17
40
  exports.TracerCoralogix = tracerCoralogix_1.default;
18
41
  if (process.env.NODE_ENV !== "local" && process.env.NODE_ENV !== "dev") {
@@ -44,8 +67,9 @@ if (process.env.NODE_ENV !== "local" && process.env.NODE_ENV !== "dev") {
44
67
  const fastify_1 = __importDefault(require("./fastify"));
45
68
  const logger_1 = __importDefault(require("@nimee/logger"));
46
69
  const error_handler_1 = require("@nimee/error-handler");
47
- const health_1 = __importDefault(require("@nimee/health"));
70
+ const health_1 = __importStar(require("@nimee/health"));
48
71
  const metrics_1 = require("@nimee/metrics");
72
+ const mongooseConnectionV2_1 = __importDefault(require("./mongooseConnectionV2"));
49
73
  class AppInitializer {
50
74
  initialize(server, serverType, serviceName, entryPointsInitializer, connectionString, dbConnection, blackFeatureList, port) {
51
75
  return __awaiter(this, void 0, void 0, function* () {
@@ -69,13 +93,31 @@ class AppInitializer {
69
93
  // await redisService.initRedisConnection(this.serviceName, `${this.serviceName}_`);
70
94
  }
71
95
  error_handler_1.errorHandler.registerAndHandleAllErrors(this.server);
72
- // Initialize health service with MongoDB health checker
73
- const healthService = new health_1.default(this.server, undefined);
74
- if (dbConnection && !blackFeatureList.includes("mongo")) {
75
- healthService.setMongoHealthChecker(() => dbConnection.isHealthy());
96
+ // Store httpServer reference for HealthServiceV2
97
+ this.httpServer = this.server.server;
98
+ // Choose health service version based on blacklist
99
+ if (blackFeatureList.includes("healthV1")) {
100
+ // Use enhanced HealthServiceV2 with MongoDB health checks
101
+ logger_1.default.info(`[${this.serviceName}] Setting up HealthServiceV2 with MongoDB monitoring`);
102
+ const healthServiceV2 = new health_1.HealthServiceV2(this.server, this.httpServer, {
103
+ livenessPath: "/liveness",
104
+ readinessPath: "/readiness",
105
+ healthPath: "/health",
106
+ includeDbCheck: true,
107
+ dbTimeout: 5000
108
+ });
109
+ healthServiceV2.start(this.serviceName);
110
+ // Use defaultMetricsExporter for consistent Prometheus metrics
111
+ metrics_1.defaultMetricsExporter.collectDefaultMetricsAndExport(this.server, "/metrics", 2000, process.env.logLevel);
112
+ // Setup periodic health logging if enabled
113
+ this.setupPeriodicHealthLogging();
114
+ }
115
+ else {
116
+ // Use default HealthService V1 (backward compatible)
117
+ logger_1.default.info(`[${this.serviceName}] Setting up default HealthService V1`);
118
+ yield new health_1.default(this.server, undefined).start(this.serviceName);
119
+ metrics_1.defaultMetricsExporter.collectDefaultMetricsAndExport(this.server, "/metrics", 2000, process.env.logLevel);
76
120
  }
77
- yield healthService.start(this.serviceName);
78
- metrics_1.defaultMetricsExporter.collectDefaultMetricsAndExport(this.server, "/metrics", 2000, process.env.logLevel);
79
121
  if (entryPointsInitializer) {
80
122
  const allEntryPointInitializers = [entryPointsInitializer];
81
123
  allEntryPointInitializers.forEach((entryPointInitializer) => {
@@ -88,6 +130,38 @@ class AppInitializer {
88
130
  yield fastify.listen(port);
89
131
  });
90
132
  }
133
+ /**
134
+ * Setup periodic health status logging (optional)
135
+ * Only active when LOG_HEALTH_STATUS=true and using V2 connection
136
+ */
137
+ setupPeriodicHealthLogging() {
138
+ if (process.env.LOG_HEALTH_STATUS === "true") {
139
+ logger_1.default.info(`[${this.serviceName}] Enabling periodic health status logging (every 60s)`);
140
+ setInterval(() => __awaiter(this, void 0, void 0, function* () {
141
+ try {
142
+ const isHealthy = yield mongooseConnectionV2_1.default.isHealthy();
143
+ const state = mongooseConnectionV2_1.default.getConnectionState();
144
+ // Always log health status for monitoring
145
+ logger_1.default.info(`[${this.serviceName}] Health check result: ${JSON.stringify({
146
+ healthy: isHealthy,
147
+ readyState: state.readyState,
148
+ readyStateText: state.readyStateText,
149
+ retryCount: state.retryCount,
150
+ timestamp: new Date().toISOString()
151
+ })}`);
152
+ // Still warn if unhealthy
153
+ if (!isHealthy || state.readyState !== 1) {
154
+ logger_1.default.warn(`[${this.serviceName}] MongoDB is unhealthy!`);
155
+ }
156
+ }
157
+ catch (error) {
158
+ logger_1.default.error(`[${this.serviceName}] Health check error: ${JSON.stringify(error)}`);
159
+ }
160
+ }), 60000); // Check every minute
161
+ }
162
+ }
91
163
  }
92
164
  exports.default = AppInitializer;
165
+ var mongooseConnectionV2_2 = require("./mongooseConnectionV2");
166
+ Object.defineProperty(exports, "mongooseConnectionV2", { enumerable: true, get: function () { return __importDefault(mongooseConnectionV2_2).default; } });
93
167
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"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"}
@@ -17,9 +17,6 @@ const mongoose_1 = __importDefault(require("mongoose"));
17
17
  const logger_1 = __importDefault(require("@nimee/logger"));
18
18
  let connectionIntance;
19
19
  class MongooseConnection {
20
- constructor() {
21
- this.disconnectionTime = null;
22
- }
23
20
  static getDefaultInstance() {
24
21
  if (!connectionIntance) {
25
22
  connectionIntance = new MongooseConnection();
@@ -29,8 +26,6 @@ class MongooseConnection {
29
26
  connectToDB(connectionString, serviceName) {
30
27
  return __awaiter(this, void 0, void 0, function* () {
31
28
  try {
32
- this.serviceName = serviceName;
33
- this.connectionString = connectionString;
34
29
  if (this.db) {
35
30
  logger_1.default.info("Mongo already Connected");
36
31
  return this.db;
@@ -40,59 +35,12 @@ class MongooseConnection {
40
35
  });
41
36
  logger_1.default.info(`Connected successfully to mongo server from ${serviceName}`);
42
37
  this.db = mongoose_1.default.connection;
43
- this.setupConnectionEventListeners();
44
38
  }
45
39
  catch (error) {
46
40
  throw new error_handler_1.CustomError(`${serviceName}_mongoose_connection_failed`, 400, `connectToDb from ${serviceName} with error ${error.message}`, error);
47
41
  }
48
42
  });
49
43
  }
50
- setupConnectionEventListeners() {
51
- if (!this.db)
52
- return;
53
- this.db.on("connected", () => {
54
- logger_1.default.info(`MongoDB connected for ${this.serviceName}`);
55
- this.disconnectionTime = null;
56
- });
57
- this.db.on("disconnected", () => {
58
- logger_1.default.warn(`MongoDB disconnected for ${this.serviceName}`);
59
- this.disconnectionTime = new Date();
60
- });
61
- this.db.on("error", (error) => {
62
- logger_1.default.error(`MongoDB connection error for ${this.serviceName}:`, error);
63
- this.disconnectionTime = new Date();
64
- });
65
- this.db.on("reconnected", () => {
66
- logger_1.default.info(`MongoDB reconnected for ${this.serviceName}`);
67
- this.disconnectionTime = null;
68
- });
69
- }
70
- isHealthy() {
71
- if (!this.db)
72
- return false;
73
- // Check if connected
74
- if (this.db.readyState === 1)
75
- return true;
76
- // If disconnected, check if it's been less than the grace period
77
- if (this.db.readyState === 0 && this.disconnectionTime) {
78
- const timeSinceDisconnection = Date.now() - this.disconnectionTime.getTime();
79
- const gracePeriodMinutes = parseInt(process.env.MONGO_GRACE_PERIOD_MINUTES || "5", 10);
80
- const gracePeriodMs = gracePeriodMinutes * 60 * 1000;
81
- return timeSinceDisconnection < gracePeriodMs;
82
- }
83
- return false;
84
- }
85
- getConnectionStatus() {
86
- if (!this.db) {
87
- return { connected: false };
88
- }
89
- const connected = this.db.readyState === 1;
90
- if (!connected && this.disconnectionTime) {
91
- const timeSinceDisconnection = Date.now() - this.disconnectionTime.getTime();
92
- return { connected, timeSinceDisconnection };
93
- }
94
- return { connected };
95
- }
96
44
  }
97
45
  exports.default = MongooseConnection.getDefaultInstance();
98
46
  //# sourceMappingURL=mongooseConnection.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"mongooseConnection.js","sourceRoot":"","sources":["../../src/mongooseConnection.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"mongooseConnection.js","sourceRoot":"","sources":["../../src/mongooseConnection.ts"],"names":[],"mappings":";;;;;;;;;;;;;;AAAA,wDAAiE;AACjE,wDAAgD;AAChD,2DAAmC;AACnC,IAAI,iBAAsB,CAAC;AAE3B,MAAM,kBAAkB;IAEtB,MAAM,CAAC,kBAAkB;QACvB,IAAI,CAAC,iBAAiB,EAAE,CAAC;YACvB,iBAAiB,GAAG,IAAI,kBAAkB,EAAE,CAAC;QAC/C,CAAC;QAED,OAAO,iBAAiB,CAAC;IAC3B,CAAC;IACK,WAAW,CAAC,gBAAwB,EAAE,WAAmB;;YAC7D,IAAI,CAAC;gBACH,IAAI,IAAI,CAAC,EAAE,EAAE,CAAC;oBACZ,gBAAM,CAAC,IAAI,CAAC,yBAAyB,CAAC,CAAC;oBACvC,OAAO,IAAI,CAAC,EAAE,CAAC;gBACjB,CAAC;gBAED,MAAM,kBAAQ,CAAC,OAAO,CAAC,gBAAgB,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,UAAU,KAAK;oBACnG,4BAAY,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;gBAClC,CAAC,CAAC,CAAC;gBACH,gBAAM,CAAC,IAAI,CAAC,+CAA+C,WAAW,EAAE,CAAC,CAAC;gBAE1E,IAAI,CAAC,EAAE,GAAG,kBAAQ,CAAC,UAAU,CAAC;YAChC,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,MAAM,IAAI,2BAAW,CACnB,GAAG,WAAW,6BAA6B,EAC3C,GAAG,EACH,oBAAoB,WAAW,eAAe,KAAK,CAAC,OAAO,EAAE,EAC7D,KAAK,CACN,CAAC;YACJ,CAAC;QACH,CAAC;KAAA;CACF;AACD,kBAAe,kBAAkB,CAAC,kBAAkB,EAAE,CAAC"}
@@ -0,0 +1,87 @@
1
+ /// <reference types="mongoose/types/aggregate" />
2
+ /// <reference types="mongoose/types/callback" />
3
+ /// <reference types="mongoose/types/collection" />
4
+ /// <reference types="mongoose/types/connection" />
5
+ /// <reference types="mongoose/types/cursor" />
6
+ /// <reference types="mongoose/types/document" />
7
+ /// <reference types="mongoose/types/error" />
8
+ /// <reference types="mongoose/types/expressions" />
9
+ /// <reference types="mongoose/types/helpers" />
10
+ /// <reference types="mongoose/types/middlewares" />
11
+ /// <reference types="mongoose/types/indexes" />
12
+ /// <reference types="mongoose/types/models" />
13
+ /// <reference types="mongoose/types/mongooseoptions" />
14
+ /// <reference types="mongoose/types/pipelinestage" />
15
+ /// <reference types="mongoose/types/populate" />
16
+ /// <reference types="mongoose/types/query" />
17
+ /// <reference types="mongoose/types/schemaoptions" />
18
+ /// <reference types="mongoose/types/session" />
19
+ /// <reference types="mongoose/types/types" />
20
+ /// <reference types="mongoose/types/utility" />
21
+ /// <reference types="mongoose/types/validation" />
22
+ /// <reference types="mongoose/types/virtuals" />
23
+ /// <reference types="mongoose/types/schematypes" />
24
+ /// <reference types="mongoose/types/inferschematype" />
25
+ /// <reference types="mongoose/types/inferrawdoctype" />
26
+ import { Connection } from "mongoose";
27
+ interface ConnectionConfig {
28
+ maxRetries?: number;
29
+ retryDelay?: number;
30
+ healthCheckInterval?: number;
31
+ enableHealthCheck?: boolean;
32
+ }
33
+ declare class MongooseConnection {
34
+ private db;
35
+ private connectionString;
36
+ private serviceName;
37
+ private isConnecting;
38
+ private retryCount;
39
+ private healthCheckInterval;
40
+ private config;
41
+ static getDefaultInstance(): MongooseConnection;
42
+ /**
43
+ * Get production-ready Mongoose connection options
44
+ */
45
+ private getConnectionOptions;
46
+ /**
47
+ * Setup connection event handlers for monitoring and recovery
48
+ */
49
+ private setupEventHandlers;
50
+ /**
51
+ * Handle disconnection with exponential backoff retry
52
+ */
53
+ private handleDisconnection;
54
+ /**
55
+ * Reconnect to MongoDB
56
+ */
57
+ private reconnect;
58
+ /**
59
+ * Start health check monitoring
60
+ */
61
+ private startHealthCheck;
62
+ /**
63
+ * Graceful shutdown
64
+ */
65
+ private gracefulShutdown;
66
+ /**
67
+ * Connect to MongoDB with enhanced error handling and retry logic
68
+ */
69
+ connectToDB(connectionString: string, serviceName: string, config?: ConnectionConfig): Promise<Connection>;
70
+ /**
71
+ * Get current connection state
72
+ */
73
+ getConnectionState(): {
74
+ isConnected: boolean;
75
+ readyState: number;
76
+ readyStateText: string;
77
+ retryCount: number;
78
+ host?: string;
79
+ port?: number;
80
+ };
81
+ /**
82
+ * Check if database is healthy
83
+ */
84
+ isHealthy(): Promise<boolean>;
85
+ }
86
+ declare const _default: MongooseConnection;
87
+ export default _default;
@@ -0,0 +1,292 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ var __importDefault = (this && this.__importDefault) || function (mod) {
12
+ return (mod && mod.__esModule) ? mod : { "default": mod };
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ const error_handler_1 = require("@nimee/error-handler");
16
+ const mongoose_1 = __importDefault(require("mongoose"));
17
+ const logger_1 = __importDefault(require("@nimee/logger"));
18
+ let connectionInstance;
19
+ class MongooseConnection {
20
+ constructor() {
21
+ this.db = null;
22
+ this.connectionString = "";
23
+ this.serviceName = "";
24
+ this.isConnecting = false;
25
+ this.retryCount = 0;
26
+ this.healthCheckInterval = null;
27
+ this.config = {
28
+ maxRetries: 10,
29
+ retryDelay: 5000,
30
+ healthCheckInterval: 30000,
31
+ enableHealthCheck: true
32
+ };
33
+ }
34
+ static getDefaultInstance() {
35
+ if (!connectionInstance) {
36
+ connectionInstance = new MongooseConnection();
37
+ }
38
+ return connectionInstance;
39
+ }
40
+ /**
41
+ * Get production-ready Mongoose connection options
42
+ */
43
+ getConnectionOptions() {
44
+ return {
45
+ // Connection pool settings
46
+ maxPoolSize: parseInt(process.env.MONGO_MAX_POOL_SIZE || "100"),
47
+ minPoolSize: parseInt(process.env.MONGO_MIN_POOL_SIZE || "10"),
48
+ // Timeout settings
49
+ serverSelectionTimeoutMS: parseInt(process.env.MONGO_SERVER_SELECTION_TIMEOUT || "30000"),
50
+ socketTimeoutMS: parseInt(process.env.MONGO_SOCKET_TIMEOUT || "45000"),
51
+ connectTimeoutMS: parseInt(process.env.MONGO_CONNECT_TIMEOUT || "30000"),
52
+ // Retry settings
53
+ retryWrites: true,
54
+ retryReads: true,
55
+ // Index management
56
+ autoIndex: process.env.NODE_ENV !== "production", // Disable in production
57
+ autoCreate: true,
58
+ // Connection monitoring
59
+ heartbeatFrequencyMS: parseInt(process.env.MONGO_HEARTBEAT_FREQUENCY || "10000"),
60
+ // Buffer settings
61
+ bufferCommands: false, // Don't buffer commands when disconnected
62
+ // Write concern
63
+ w: "majority",
64
+ journal: true,
65
+ };
66
+ }
67
+ /**
68
+ * Setup connection event handlers for monitoring and recovery
69
+ */
70
+ setupEventHandlers() {
71
+ mongoose_1.default.connection.on("connected", () => {
72
+ logger_1.default.info(`[${this.serviceName}] MongoDB connected successfully`);
73
+ this.retryCount = 0;
74
+ });
75
+ mongoose_1.default.connection.on("disconnected", () => {
76
+ logger_1.default.warn(`[${this.serviceName}] MongoDB disconnected`);
77
+ if (!this.isConnecting) {
78
+ this.handleDisconnection();
79
+ }
80
+ });
81
+ mongoose_1.default.connection.on("error", (error) => {
82
+ logger_1.default.error(`[${this.serviceName}] MongoDB connection error:`, error);
83
+ if (error.name === "MongoNetworkError" || error.name === "MongoServerError") {
84
+ this.handleDisconnection();
85
+ }
86
+ });
87
+ mongoose_1.default.connection.on("reconnected", () => {
88
+ logger_1.default.info(`[${this.serviceName}] MongoDB reconnected successfully`);
89
+ this.retryCount = 0;
90
+ });
91
+ // Monitor replica set changes
92
+ mongoose_1.default.connection.on("reconnectFailed", () => {
93
+ logger_1.default.error(`[${this.serviceName}] MongoDB reconnection failed`);
94
+ this.handleDisconnection();
95
+ });
96
+ // Handle process termination
97
+ process.on("SIGINT", () => __awaiter(this, void 0, void 0, function* () {
98
+ yield this.gracefulShutdown("SIGINT");
99
+ }));
100
+ process.on("SIGTERM", () => __awaiter(this, void 0, void 0, function* () {
101
+ yield this.gracefulShutdown("SIGTERM");
102
+ }));
103
+ }
104
+ /**
105
+ * Handle disconnection with exponential backoff retry
106
+ */
107
+ handleDisconnection() {
108
+ return __awaiter(this, void 0, void 0, function* () {
109
+ if (this.isConnecting) {
110
+ return;
111
+ }
112
+ if (this.retryCount >= (this.config.maxRetries || 10)) {
113
+ logger_1.default.error(`[${this.serviceName}] Max retry attempts (${this.config.maxRetries}) reached. Giving up.`);
114
+ process.exit(1); // Exit to allow container orchestration to restart
115
+ }
116
+ this.isConnecting = true;
117
+ this.retryCount++;
118
+ // Exponential backoff with jitter
119
+ const delay = Math.min((this.config.retryDelay || 5000) * Math.pow(2, this.retryCount - 1) + Math.random() * 1000, 60000 // Max 60 seconds
120
+ );
121
+ logger_1.default.info(`[${this.serviceName}] Attempting to reconnect (attempt ${this.retryCount}/${this.config.maxRetries}) in ${delay}ms...`);
122
+ setTimeout(() => __awaiter(this, void 0, void 0, function* () {
123
+ try {
124
+ yield this.reconnect();
125
+ this.isConnecting = false;
126
+ }
127
+ catch (error) {
128
+ logger_1.default.error(`[${this.serviceName}] Reconnection attempt ${this.retryCount} failed: ${JSON.stringify(error)}`);
129
+ this.isConnecting = false;
130
+ this.handleDisconnection();
131
+ }
132
+ }), delay);
133
+ });
134
+ }
135
+ /**
136
+ * Reconnect to MongoDB
137
+ */
138
+ reconnect() {
139
+ return __awaiter(this, void 0, void 0, function* () {
140
+ try {
141
+ // Close existing connection if any
142
+ if (mongoose_1.default.connection.readyState !== 0) {
143
+ yield mongoose_1.default.connection.close();
144
+ }
145
+ // Attempt reconnection
146
+ yield mongoose_1.default.connect(this.connectionString, this.getConnectionOptions());
147
+ logger_1.default.info(`[${this.serviceName}] Successfully reconnected to MongoDB`);
148
+ this.db = mongoose_1.default.connection;
149
+ }
150
+ catch (error) {
151
+ throw new error_handler_1.CustomError(`${this.serviceName}_reconnection_failed`, 500, `Failed to reconnect to MongoDB: ${error.message}`, error);
152
+ }
153
+ });
154
+ }
155
+ /**
156
+ * Start health check monitoring
157
+ */
158
+ startHealthCheck() {
159
+ if (!this.config.enableHealthCheck) {
160
+ return;
161
+ }
162
+ // Clear existing interval if any
163
+ if (this.healthCheckInterval) {
164
+ clearInterval(this.healthCheckInterval);
165
+ }
166
+ this.healthCheckInterval = setInterval(() => __awaiter(this, void 0, void 0, function* () {
167
+ var _a;
168
+ try {
169
+ if (mongoose_1.default.connection.readyState !== 1) {
170
+ logger_1.default.warn(`[${this.serviceName}] MongoDB health check failed - readyState: ${mongoose_1.default.connection.readyState}`);
171
+ this.handleDisconnection();
172
+ return;
173
+ }
174
+ // Ping the database
175
+ const adminDb = (_a = mongoose_1.default.connection.db) === null || _a === void 0 ? void 0 : _a.admin();
176
+ if (adminDb) {
177
+ const result = yield adminDb.ping();
178
+ if ((result === null || result === void 0 ? void 0 : result.ok) !== 1) {
179
+ logger_1.default.warn(`[${this.serviceName}] MongoDB ping failed`);
180
+ this.handleDisconnection();
181
+ }
182
+ }
183
+ }
184
+ catch (error) {
185
+ logger_1.default.error(`[${this.serviceName}] Health check error: ${JSON.stringify(error)}`);
186
+ this.handleDisconnection();
187
+ }
188
+ }), this.config.healthCheckInterval || 30000);
189
+ }
190
+ /**
191
+ * Graceful shutdown
192
+ */
193
+ gracefulShutdown(signal) {
194
+ return __awaiter(this, void 0, void 0, function* () {
195
+ logger_1.default.info(`[${this.serviceName}] Received ${signal}, starting graceful shutdown...`);
196
+ // Stop health checks
197
+ if (this.healthCheckInterval) {
198
+ clearInterval(this.healthCheckInterval);
199
+ }
200
+ try {
201
+ yield mongoose_1.default.connection.close();
202
+ logger_1.default.info(`[${this.serviceName}] MongoDB connection closed gracefully`);
203
+ process.exit(0);
204
+ }
205
+ catch (error) {
206
+ logger_1.default.error(`[${this.serviceName}] Error during graceful shutdown: ${JSON.stringify(error)}`);
207
+ process.exit(1);
208
+ }
209
+ });
210
+ }
211
+ /**
212
+ * Connect to MongoDB with enhanced error handling and retry logic
213
+ */
214
+ connectToDB(connectionString, serviceName, config) {
215
+ return __awaiter(this, void 0, void 0, function* () {
216
+ try {
217
+ // Merge custom config with defaults
218
+ if (config) {
219
+ this.config = Object.assign(Object.assign({}, this.config), config);
220
+ }
221
+ // Check if already connected
222
+ if (this.db && mongoose_1.default.connection.readyState === 1) {
223
+ logger_1.default.info(`[${serviceName}] MongoDB already connected`);
224
+ return this.db;
225
+ }
226
+ this.connectionString = connectionString;
227
+ this.serviceName = serviceName;
228
+ // Setup event handlers before connecting
229
+ this.setupEventHandlers();
230
+ // Attempt connection
231
+ logger_1.default.info(`[${serviceName}] Connecting to MongoDB...`);
232
+ yield mongoose_1.default.connect(connectionString, this.getConnectionOptions());
233
+ logger_1.default.info(`[${serviceName}] Connected successfully to MongoDB (last 10 chars: ${connectionString.slice(-10)})`);
234
+ this.db = mongoose_1.default.connection;
235
+ // Start health check monitoring
236
+ this.startHealthCheck();
237
+ return this.db;
238
+ }
239
+ catch (error) {
240
+ logger_1.default.error(`[${serviceName}] Initial connection failed: ${JSON.stringify(error)}`);
241
+ // Start retry mechanism
242
+ this.handleDisconnection();
243
+ throw new error_handler_1.CustomError(`${serviceName}_mongoose_connection_failed`, 500, `Failed to connect to MongoDB: ${error.message}`, error);
244
+ }
245
+ });
246
+ }
247
+ /**
248
+ * Get current connection state
249
+ */
250
+ getConnectionState() {
251
+ const readyStates = {
252
+ 0: "disconnected",
253
+ 1: "connected",
254
+ 2: "connecting",
255
+ 3: "disconnecting"
256
+ };
257
+ return {
258
+ isConnected: mongoose_1.default.connection.readyState === 1,
259
+ readyState: mongoose_1.default.connection.readyState,
260
+ readyStateText: readyStates[mongoose_1.default.connection.readyState] || "unknown",
261
+ retryCount: this.retryCount,
262
+ host: mongoose_1.default.connection.host,
263
+ port: mongoose_1.default.connection.port
264
+ };
265
+ }
266
+ /**
267
+ * Check if database is healthy
268
+ */
269
+ isHealthy() {
270
+ var _a;
271
+ return __awaiter(this, void 0, void 0, function* () {
272
+ try {
273
+ if (mongoose_1.default.connection.readyState !== 1) {
274
+ return false;
275
+ }
276
+ // Try to ping the database
277
+ const adminDb = (_a = mongoose_1.default.connection.db) === null || _a === void 0 ? void 0 : _a.admin();
278
+ if (adminDb) {
279
+ const result = yield adminDb.ping();
280
+ return (result === null || result === void 0 ? void 0 : result.ok) === 1;
281
+ }
282
+ return false;
283
+ }
284
+ catch (error) {
285
+ logger_1.default.error(`Health check failed: ${JSON.stringify(error)}`);
286
+ return false;
287
+ }
288
+ });
289
+ }
290
+ }
291
+ exports.default = MongooseConnection.getDefaultInstance();
292
+ //# sourceMappingURL=mongooseConnectionV2.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mongooseConnectionV2.js","sourceRoot":"","sources":["../../src/mongooseConnectionV2.ts"],"names":[],"mappings":";;;;;;;;;;;;;;AAAA,wDAAmD;AACnD,wDAAgE;AAChE,2DAAmC;AAEnC,IAAI,kBAAsC,CAAC;AAS3C,MAAM,kBAAkB;IAAxB;QACU,OAAE,GAAsB,IAAI,CAAC;QAC7B,qBAAgB,GAAW,EAAE,CAAC;QAC9B,gBAAW,GAAW,EAAE,CAAC;QACzB,iBAAY,GAAY,KAAK,CAAC;QAC9B,eAAU,GAAW,CAAC,CAAC;QACvB,wBAAmB,GAA0B,IAAI,CAAC;QAClD,WAAM,GAAqB;YACjC,UAAU,EAAE,EAAE;YACd,UAAU,EAAE,IAAI;YAChB,mBAAmB,EAAE,KAAK;YAC1B,iBAAiB,EAAE,IAAI;SACxB,CAAC;IAsTJ,CAAC;IApTC,MAAM,CAAC,kBAAkB;QACvB,IAAI,CAAC,kBAAkB,EAAE,CAAC;YACxB,kBAAkB,GAAG,IAAI,kBAAkB,EAAE,CAAC;QAChD,CAAC;QACD,OAAO,kBAAkB,CAAC;IAC5B,CAAC;IAED;;OAEG;IACK,oBAAoB;QAC1B,OAAO;YACL,2BAA2B;YAC3B,WAAW,EAAE,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,mBAAmB,IAAI,KAAK,CAAC;YAC/D,WAAW,EAAE,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,mBAAmB,IAAI,IAAI,CAAC;YAE9D,mBAAmB;YACnB,wBAAwB,EAAE,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,8BAA8B,IAAI,OAAO,CAAC;YACzF,eAAe,EAAE,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,oBAAoB,IAAI,OAAO,CAAC;YACtE,gBAAgB,EAAE,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,qBAAqB,IAAI,OAAO,CAAC;YAExE,iBAAiB;YACjB,WAAW,EAAE,IAAI;YACjB,UAAU,EAAE,IAAI;YAEhB,mBAAmB;YACnB,SAAS,EAAE,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,YAAY,EAAE,wBAAwB;YAC1E,UAAU,EAAE,IAAI;YAEhB,wBAAwB;YACxB,oBAAoB,EAAE,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,yBAAyB,IAAI,OAAO,CAAC;YAEhF,kBAAkB;YAClB,cAAc,EAAE,KAAK,EAAE,0CAA0C;YAEjE,gBAAgB;YAChB,CAAC,EAAE,UAAU;YACb,OAAO,EAAE,IAAI;SACd,CAAC;IACJ,CAAC;IAED;;OAEG;IACK,kBAAkB;QACxB,kBAAQ,CAAC,UAAU,CAAC,EAAE,CAAC,WAAW,EAAE,GAAG,EAAE;YACvC,gBAAM,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,WAAW,kCAAkC,CAAC,CAAC;YACpE,IAAI,CAAC,UAAU,GAAG,CAAC,CAAC;QACtB,CAAC,CAAC,CAAC;QAEH,kBAAQ,CAAC,UAAU,CAAC,EAAE,CAAC,cAAc,EAAE,GAAG,EAAE;YAC1C,gBAAM,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,WAAW,wBAAwB,CAAC,CAAC;YAC1D,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,CAAC;gBACvB,IAAI,CAAC,mBAAmB,EAAE,CAAC;YAC7B,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,kBAAQ,CAAC,UAAU,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE;YACxC,gBAAM,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC,WAAW,6BAA6B,EAAE,KAAK,CAAC,CAAC;YACvE,IAAI,KAAK,CAAC,IAAI,KAAK,mBAAmB,IAAI,KAAK,CAAC,IAAI,KAAK,kBAAkB,EAAE,CAAC;gBAC5E,IAAI,CAAC,mBAAmB,EAAE,CAAC;YAC7B,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,kBAAQ,CAAC,UAAU,CAAC,EAAE,CAAC,aAAa,EAAE,GAAG,EAAE;YACzC,gBAAM,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,WAAW,oCAAoC,CAAC,CAAC;YACtE,IAAI,CAAC,UAAU,GAAG,CAAC,CAAC;QACtB,CAAC,CAAC,CAAC;QAEH,8BAA8B;QAC9B,kBAAQ,CAAC,UAAU,CAAC,EAAE,CAAC,iBAAiB,EAAE,GAAG,EAAE;YAC7C,gBAAM,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC,WAAW,+BAA+B,CAAC,CAAC;YAClE,IAAI,CAAC,mBAAmB,EAAE,CAAC;QAC7B,CAAC,CAAC,CAAC;QAEH,6BAA6B;QAC7B,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,GAAS,EAAE;YAC9B,MAAM,IAAI,CAAC,gBAAgB,CAAC,QAAQ,CAAC,CAAC;QACxC,CAAC,CAAA,CAAC,CAAC;QAEH,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,GAAS,EAAE;YAC/B,MAAM,IAAI,CAAC,gBAAgB,CAAC,SAAS,CAAC,CAAC;QACzC,CAAC,CAAA,CAAC,CAAC;IACL,CAAC;IAED;;OAEG;IACW,mBAAmB;;YAC/B,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;gBACtB,OAAO;YACT,CAAC;YAED,IAAI,IAAI,CAAC,UAAU,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,UAAU,IAAI,EAAE,CAAC,EAAE,CAAC;gBACtD,gBAAM,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC,WAAW,yBAAyB,IAAI,CAAC,MAAM,CAAC,UAAU,uBAAuB,CAAC,CAAC;gBACzG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,mDAAmD;YACtE,CAAC;YAED,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC;YACzB,IAAI,CAAC,UAAU,EAAE,CAAC;YAElB,kCAAkC;YAClC,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CACpB,CAAC,IAAI,CAAC,MAAM,CAAC,UAAU,IAAI,IAAI,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,UAAU,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,GAAG,IAAI,EAC1F,KAAK,CAAC,iBAAiB;aACxB,CAAC;YAEF,gBAAM,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,WAAW,sCAAsC,IAAI,CAAC,UAAU,IAAI,IAAI,CAAC,MAAM,CAAC,UAAU,QAAQ,KAAK,OAAO,CAAC,CAAC;YAErI,UAAU,CAAC,GAAS,EAAE;gBACpB,IAAI,CAAC;oBACH,MAAM,IAAI,CAAC,SAAS,EAAE,CAAC;oBACvB,IAAI,CAAC,YAAY,GAAG,KAAK,CAAC;gBAC5B,CAAC;gBAAC,OAAO,KAAK,EAAE,CAAC;oBACf,gBAAM,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC,WAAW,0BAA0B,IAAI,CAAC,UAAU,YAAY,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;oBAC/G,IAAI,CAAC,YAAY,GAAG,KAAK,CAAC;oBAC1B,IAAI,CAAC,mBAAmB,EAAE,CAAC;gBAC7B,CAAC;YACH,CAAC,CAAA,EAAE,KAAK,CAAC,CAAC;QACZ,CAAC;KAAA;IAED;;OAEG;IACW,SAAS;;YACrB,IAAI,CAAC;gBACH,mCAAmC;gBACnC,IAAI,kBAAQ,CAAC,UAAU,CAAC,UAAU,KAAK,CAAC,EAAE,CAAC;oBACzC,MAAM,kBAAQ,CAAC,UAAU,CAAC,KAAK,EAAE,CAAC;gBACpC,CAAC;gBAED,uBAAuB;gBACvB,MAAM,kBAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,gBAAgB,EAAE,IAAI,CAAC,oBAAoB,EAAE,CAAC,CAAC;gBAC3E,gBAAM,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,WAAW,uCAAuC,CAAC,CAAC;gBACzE,IAAI,CAAC,EAAE,GAAG,kBAAQ,CAAC,UAAU,CAAC;YAChC,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,MAAM,IAAI,2BAAW,CACnB,GAAG,IAAI,CAAC,WAAW,sBAAsB,EACzC,GAAG,EACH,mCAAmC,KAAK,CAAC,OAAO,EAAE,EAClD,KAAK,CACN,CAAC;YACJ,CAAC;QACH,CAAC;KAAA;IAED;;OAEG;IACK,gBAAgB;QACtB,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,iBAAiB,EAAE,CAAC;YACnC,OAAO;QACT,CAAC;QAED,iCAAiC;QACjC,IAAI,IAAI,CAAC,mBAAmB,EAAE,CAAC;YAC7B,aAAa,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC;QAC1C,CAAC;QAED,IAAI,CAAC,mBAAmB,GAAG,WAAW,CAAC,GAAS,EAAE;;YAChD,IAAI,CAAC;gBACH,IAAI,kBAAQ,CAAC,UAAU,CAAC,UAAU,KAAK,CAAC,EAAE,CAAC;oBACzC,gBAAM,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,WAAW,+CAA+C,kBAAQ,CAAC,UAAU,CAAC,UAAU,EAAE,CAAC,CAAC;oBACjH,IAAI,CAAC,mBAAmB,EAAE,CAAC;oBAC3B,OAAO;gBACT,CAAC;gBAED,oBAAoB;gBACpB,MAAM,OAAO,GAAG,MAAA,kBAAQ,CAAC,UAAU,CAAC,EAAE,0CAAE,KAAK,EAAE,CAAC;gBAChD,IAAI,OAAO,EAAE,CAAC;oBACZ,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,IAAI,EAAE,CAAC;oBACpC,IAAI,CAAA,MAAM,aAAN,MAAM,uBAAN,MAAM,CAAE,EAAE,MAAK,CAAC,EAAE,CAAC;wBACrB,gBAAM,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,WAAW,uBAAuB,CAAC,CAAC;wBACzD,IAAI,CAAC,mBAAmB,EAAE,CAAC;oBAC7B,CAAC;gBACH,CAAC;YACH,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,gBAAM,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC,WAAW,yBAAyB,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;gBACnF,IAAI,CAAC,mBAAmB,EAAE,CAAC;YAC7B,CAAC;QACH,CAAC,CAAA,EAAE,IAAI,CAAC,MAAM,CAAC,mBAAmB,IAAI,KAAK,CAAC,CAAC;IAC/C,CAAC;IAED;;OAEG;IACW,gBAAgB,CAAC,MAAc;;YAC3C,gBAAM,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,WAAW,cAAc,MAAM,iCAAiC,CAAC,CAAC;YAEvF,qBAAqB;YACrB,IAAI,IAAI,CAAC,mBAAmB,EAAE,CAAC;gBAC7B,aAAa,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC;YAC1C,CAAC;YAED,IAAI,CAAC;gBACH,MAAM,kBAAQ,CAAC,UAAU,CAAC,KAAK,EAAE,CAAC;gBAClC,gBAAM,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,WAAW,wCAAwC,CAAC,CAAC;gBAC1E,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAClB,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,gBAAM,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC,WAAW,qCAAqC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;gBAC/F,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAClB,CAAC;QACH,CAAC;KAAA;IAED;;OAEG;IACG,WAAW,CACf,gBAAwB,EACxB,WAAmB,EACnB,MAAyB;;YAEzB,IAAI,CAAC;gBACH,oCAAoC;gBACpC,IAAI,MAAM,EAAE,CAAC;oBACX,IAAI,CAAC,MAAM,mCAAQ,IAAI,CAAC,MAAM,GAAK,MAAM,CAAE,CAAC;gBAC9C,CAAC;gBAED,6BAA6B;gBAC7B,IAAI,IAAI,CAAC,EAAE,IAAI,kBAAQ,CAAC,UAAU,CAAC,UAAU,KAAK,CAAC,EAAE,CAAC;oBACpD,gBAAM,CAAC,IAAI,CAAC,IAAI,WAAW,6BAA6B,CAAC,CAAC;oBAC1D,OAAO,IAAI,CAAC,EAAE,CAAC;gBACjB,CAAC;gBAED,IAAI,CAAC,gBAAgB,GAAG,gBAAgB,CAAC;gBACzC,IAAI,CAAC,WAAW,GAAG,WAAW,CAAC;gBAE/B,yCAAyC;gBACzC,IAAI,CAAC,kBAAkB,EAAE,CAAC;gBAE1B,qBAAqB;gBACrB,gBAAM,CAAC,IAAI,CAAC,IAAI,WAAW,4BAA4B,CAAC,CAAC;gBACzD,MAAM,kBAAQ,CAAC,OAAO,CAAC,gBAAgB,EAAE,IAAI,CAAC,oBAAoB,EAAE,CAAC,CAAC;gBAEtE,gBAAM,CAAC,IAAI,CACT,IAAI,WAAW,uDAAuD,gBAAgB,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,GAAG,CACrG,CAAC;gBAEF,IAAI,CAAC,EAAE,GAAG,kBAAQ,CAAC,UAAU,CAAC;gBAE9B,gCAAgC;gBAChC,IAAI,CAAC,gBAAgB,EAAE,CAAC;gBAExB,OAAO,IAAI,CAAC,EAAE,CAAC;YACjB,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,gBAAM,CAAC,KAAK,CAAC,IAAI,WAAW,gCAAgC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;gBAErF,wBAAwB;gBACxB,IAAI,CAAC,mBAAmB,EAAE,CAAC;gBAE3B,MAAM,IAAI,2BAAW,CACnB,GAAG,WAAW,6BAA6B,EAC3C,GAAG,EACH,iCAAiC,KAAK,CAAC,OAAO,EAAE,EAChD,KAAK,CACN,CAAC;YACJ,CAAC;QACH,CAAC;KAAA;IAED;;OAEG;IACH,kBAAkB;QAQhB,MAAM,WAAW,GAAG;YAClB,CAAC,EAAE,cAAc;YACjB,CAAC,EAAE,WAAW;YACd,CAAC,EAAE,YAAY;YACf,CAAC,EAAE,eAAe;SACnB,CAAC;QAEF,OAAO;YACL,WAAW,EAAE,kBAAQ,CAAC,UAAU,CAAC,UAAU,KAAK,CAAC;YACjD,UAAU,EAAE,kBAAQ,CAAC,UAAU,CAAC,UAAU;YAC1C,cAAc,EAAE,WAAW,CAAC,kBAAQ,CAAC,UAAU,CAAC,UAAsC,CAAC,IAAI,SAAS;YACpG,UAAU,EAAE,IAAI,CAAC,UAAU;YAC3B,IAAI,EAAE,kBAAQ,CAAC,UAAU,CAAC,IAAI;YAC9B,IAAI,EAAE,kBAAQ,CAAC,UAAU,CAAC,IAAI;SAC/B,CAAC;IACJ,CAAC;IAED;;OAEG;IACG,SAAS;;;YACb,IAAI,CAAC;gBACH,IAAI,kBAAQ,CAAC,UAAU,CAAC,UAAU,KAAK,CAAC,EAAE,CAAC;oBACzC,OAAO,KAAK,CAAC;gBACf,CAAC;gBAED,2BAA2B;gBAC3B,MAAM,OAAO,GAAG,MAAA,kBAAQ,CAAC,UAAU,CAAC,EAAE,0CAAE,KAAK,EAAE,CAAC;gBAChD,IAAI,OAAO,EAAE,CAAC;oBACZ,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,IAAI,EAAE,CAAC;oBACpC,OAAO,CAAA,MAAM,aAAN,MAAM,uBAAN,MAAM,CAAE,EAAE,MAAK,CAAC,CAAC;gBAC1B,CAAC;gBAED,OAAO,KAAK,CAAC;YACf,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,gBAAM,CAAC,KAAK,CAAC,wBAAwB,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;gBAC9D,OAAO,KAAK,CAAC;YACf,CAAC;;KACF;CACF;AAED,kBAAe,kBAAkB,CAAC,kBAAkB,EAAE,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nimee/initialize-ms",
3
- "version": "1.0.75",
3
+ "version": "1.0.78",
4
4
  "description": "init behavior for each ms",
5
5
  "main": "dist/src/index.js",
6
6
  "author": "dan goldberg",
@@ -35,7 +35,7 @@
35
35
  "@fastify/swagger": "^8.1.0",
36
36
  "@fastify/swagger-ui": "^1.3.0",
37
37
  "@nimee/error-handler": "^0.0.12",
38
- "@nimee/health": "2.1.4",
38
+ "@nimee/health": "2.1.5",
39
39
  "@nimee/logger": "^1.0.27",
40
40
  "@nimee/metrics": "2.0.14",
41
41
  "@opentelemetry/api": "^1.7.0",
@@ -49,6 +49,6 @@
49
49
  "@opentelemetry/sdk-trace-base": "^1.20.0",
50
50
  "@opentelemetry/sdk-trace-node": "^1.21.0",
51
51
  "fastify": "4.24.3",
52
- "mongoose": "6.2.10"
52
+ "mongoose": "^8.19.2"
53
53
  }
54
54
  }
package/src/index.ts CHANGED
@@ -28,8 +28,9 @@ if (process.env.NODE_ENV !== "local" && process.env.NODE_ENV !== "dev") {
28
28
  import ServerInitializerFastify from "./fastify";
29
29
  import logger from "@nimee/logger";
30
30
  import { errorHandler } from "@nimee/error-handler";
31
- import HealthService from "@nimee/health";
31
+ import HealthService, { HealthServiceV2 } from "@nimee/health";
32
32
  import { defaultMetricsExporter } from "@nimee/metrics";
33
+ import mongooseConnectionV2 from "./mongooseConnectionV2";
33
34
 
34
35
  class AppInitializer {
35
36
  public httpServer: any;
@@ -66,14 +67,35 @@ class AppInitializer {
66
67
  }
67
68
  errorHandler.registerAndHandleAllErrors(this.server);
68
69
 
69
- // Initialize health service with MongoDB health checker
70
- const healthService = new HealthService(this.server, undefined);
71
- if (dbConnection && !blackFeatureList.includes("mongo")) {
72
- healthService.setMongoHealthChecker(() => dbConnection.isHealthy());
73
- }
74
- await healthService.start(this.serviceName);
70
+ // Store httpServer reference for HealthServiceV2
71
+ this.httpServer = this.server.server;
75
72
 
76
- defaultMetricsExporter.collectDefaultMetricsAndExport(this.server, "/metrics", 2000, process.env.logLevel);
73
+ // Choose health service version based on blacklist
74
+ if (blackFeatureList.includes("healthV1")) {
75
+ // Use enhanced HealthServiceV2 with MongoDB health checks
76
+ logger.info(`[${this.serviceName}] Setting up HealthServiceV2 with MongoDB monitoring`);
77
+ const healthServiceV2 = new HealthServiceV2(
78
+ this.server,
79
+ this.httpServer,
80
+ {
81
+ livenessPath: "/liveness",
82
+ readinessPath: "/readiness",
83
+ healthPath: "/health",
84
+ includeDbCheck: true,
85
+ dbTimeout: 5000
86
+ }
87
+ );
88
+ healthServiceV2.start(this.serviceName);
89
+ // Use defaultMetricsExporter for consistent Prometheus metrics
90
+ defaultMetricsExporter.collectDefaultMetricsAndExport(this.server, "/metrics", 2000, process.env.logLevel);
91
+ // Setup periodic health logging if enabled
92
+ this.setupPeriodicHealthLogging();
93
+ } else {
94
+ // Use default HealthService V1 (backward compatible)
95
+ logger.info(`[${this.serviceName}] Setting up default HealthService V1`);
96
+ await new HealthService(this.server, undefined).start(this.serviceName);
97
+ defaultMetricsExporter.collectDefaultMetricsAndExport(this.server, "/metrics", 2000, process.env.logLevel);
98
+ }
77
99
 
78
100
  if (entryPointsInitializer) {
79
101
  const allEntryPointInitializers = [entryPointsInitializer];
@@ -85,7 +107,40 @@ class AppInitializer {
85
107
  }
86
108
  if (serverType) await fastify.listen(port);
87
109
  }
110
+
111
+ /**
112
+ * Setup periodic health status logging (optional)
113
+ * Only active when LOG_HEALTH_STATUS=true and using V2 connection
114
+ */
115
+ private setupPeriodicHealthLogging() {
116
+ if (process.env.LOG_HEALTH_STATUS === "true") {
117
+ logger.info(`[${this.serviceName}] Enabling periodic health status logging (every 60s)`);
118
+ setInterval(async () => {
119
+ try {
120
+ const isHealthy = await mongooseConnectionV2.isHealthy();
121
+ const state = mongooseConnectionV2.getConnectionState();
122
+
123
+ // Always log health status for monitoring
124
+ logger.info(`[${this.serviceName}] Health check result: ${JSON.stringify({
125
+ healthy: isHealthy,
126
+ readyState: state.readyState,
127
+ readyStateText: state.readyStateText,
128
+ retryCount: state.retryCount,
129
+ timestamp: new Date().toISOString()
130
+ })}`);
131
+
132
+ // Still warn if unhealthy
133
+ if (!isHealthy || state.readyState !== 1) {
134
+ logger.warn(`[${this.serviceName}] MongoDB is unhealthy!`);
135
+ }
136
+ } catch (error) {
137
+ logger.error(`[${this.serviceName}] Health check error: ${JSON.stringify(error)}`);
138
+ }
139
+ }, 60000); // Check every minute
140
+ }
141
+ }
88
142
  }
89
143
 
90
144
  export default AppInitializer;
91
145
  export { TracerCoralogix };
146
+ export { default as mongooseConnectionV2 } from "./mongooseConnectionV2";
@@ -5,10 +5,6 @@ let connectionIntance: any;
5
5
 
6
6
  class MongooseConnection {
7
7
  db: Connection;
8
- private serviceName: string;
9
- private disconnectionTime: Date | null = null;
10
- private connectionString: string;
11
-
12
8
  static getDefaultInstance() {
13
9
  if (!connectionIntance) {
14
10
  connectionIntance = new MongooseConnection();
@@ -16,12 +12,8 @@ class MongooseConnection {
16
12
 
17
13
  return connectionIntance;
18
14
  }
19
-
20
15
  async connectToDB(connectionString: string, serviceName: string) {
21
16
  try {
22
- this.serviceName = serviceName;
23
- this.connectionString = connectionString;
24
-
25
17
  if (this.db) {
26
18
  logger.info("Mongo already Connected");
27
19
  return this.db;
@@ -33,7 +25,6 @@ class MongooseConnection {
33
25
  logger.info(`Connected successfully to mongo server from ${serviceName}`);
34
26
 
35
27
  this.db = mongoose.connection;
36
- this.setupConnectionEventListeners();
37
28
  } catch (error) {
38
29
  throw new CustomError(
39
30
  `${serviceName}_mongoose_connection_failed`,
@@ -43,61 +34,5 @@ class MongooseConnection {
43
34
  );
44
35
  }
45
36
  }
46
-
47
- private setupConnectionEventListeners() {
48
- if (!this.db) return;
49
-
50
- this.db.on("connected", () => {
51
- logger.info(`MongoDB connected for ${this.serviceName}`);
52
- this.disconnectionTime = null;
53
- });
54
-
55
- this.db.on("disconnected", () => {
56
- logger.warn(`MongoDB disconnected for ${this.serviceName}`);
57
- this.disconnectionTime = new Date();
58
- });
59
-
60
- this.db.on("error", (error) => {
61
- logger.error(`MongoDB connection error for ${this.serviceName}:`, error);
62
- this.disconnectionTime = new Date();
63
- });
64
-
65
- this.db.on("reconnected", () => {
66
- logger.info(`MongoDB reconnected for ${this.serviceName}`);
67
- this.disconnectionTime = null;
68
- });
69
- }
70
-
71
- isHealthy(): boolean {
72
- if (!this.db) return false;
73
-
74
- // Check if connected
75
- if (this.db.readyState === 1) return true;
76
-
77
- // If disconnected, check if it's been less than the grace period
78
- if (this.db.readyState === 0 && this.disconnectionTime) {
79
- const timeSinceDisconnection = Date.now() - this.disconnectionTime.getTime();
80
- const gracePeriodMinutes = parseInt(process.env.MONGO_GRACE_PERIOD_MINUTES || "5", 10);
81
- const gracePeriodMs = gracePeriodMinutes * 60 * 1000;
82
- return timeSinceDisconnection < gracePeriodMs;
83
- }
84
-
85
- return false;
86
- }
87
-
88
- getConnectionStatus(): { connected: boolean; timeSinceDisconnection?: number } {
89
- if (!this.db) {
90
- return { connected: false };
91
- }
92
-
93
- const connected = this.db.readyState === 1;
94
-
95
- if (!connected && this.disconnectionTime) {
96
- const timeSinceDisconnection = Date.now() - this.disconnectionTime.getTime();
97
- return { connected, timeSinceDisconnection };
98
- }
99
-
100
- return { connected };
101
- }
102
37
  }
103
38
  export default MongooseConnection.getDefaultInstance();
@@ -0,0 +1,338 @@
1
+ import { CustomError } from "@nimee/error-handler";
2
+ import mongoose, { Connection, ConnectOptions } from "mongoose";
3
+ import logger from "@nimee/logger";
4
+
5
+ let connectionInstance: MongooseConnection;
6
+
7
+ interface ConnectionConfig {
8
+ maxRetries?: number;
9
+ retryDelay?: number;
10
+ healthCheckInterval?: number;
11
+ enableHealthCheck?: boolean;
12
+ }
13
+
14
+ class MongooseConnection {
15
+ private db: Connection | null = null;
16
+ private connectionString: string = "";
17
+ private serviceName: string = "";
18
+ private isConnecting: boolean = false;
19
+ private retryCount: number = 0;
20
+ private healthCheckInterval: NodeJS.Timeout | null = null;
21
+ private config: ConnectionConfig = {
22
+ maxRetries: 10,
23
+ retryDelay: 5000,
24
+ healthCheckInterval: 30000,
25
+ enableHealthCheck: true
26
+ };
27
+
28
+ static getDefaultInstance(): MongooseConnection {
29
+ if (!connectionInstance) {
30
+ connectionInstance = new MongooseConnection();
31
+ }
32
+ return connectionInstance;
33
+ }
34
+
35
+ /**
36
+ * Get production-ready Mongoose connection options
37
+ */
38
+ private getConnectionOptions(): ConnectOptions {
39
+ return {
40
+ // Connection pool settings
41
+ maxPoolSize: parseInt(process.env.MONGO_MAX_POOL_SIZE || "100"),
42
+ minPoolSize: parseInt(process.env.MONGO_MIN_POOL_SIZE || "10"),
43
+
44
+ // Timeout settings
45
+ serverSelectionTimeoutMS: parseInt(process.env.MONGO_SERVER_SELECTION_TIMEOUT || "30000"),
46
+ socketTimeoutMS: parseInt(process.env.MONGO_SOCKET_TIMEOUT || "45000"),
47
+ connectTimeoutMS: parseInt(process.env.MONGO_CONNECT_TIMEOUT || "30000"),
48
+
49
+ // Retry settings
50
+ retryWrites: true,
51
+ retryReads: true,
52
+
53
+ // Index management
54
+ autoIndex: process.env.NODE_ENV !== "production", // Disable in production
55
+ autoCreate: true,
56
+
57
+ // Connection monitoring
58
+ heartbeatFrequencyMS: parseInt(process.env.MONGO_HEARTBEAT_FREQUENCY || "10000"),
59
+
60
+ // Buffer settings
61
+ bufferCommands: false, // Don't buffer commands when disconnected
62
+
63
+ // Write concern
64
+ w: "majority",
65
+ journal: true,
66
+ };
67
+ }
68
+
69
+ /**
70
+ * Setup connection event handlers for monitoring and recovery
71
+ */
72
+ private setupEventHandlers(): void {
73
+ mongoose.connection.on("connected", () => {
74
+ logger.info(`[${this.serviceName}] MongoDB connected successfully`);
75
+ this.retryCount = 0;
76
+ });
77
+
78
+ mongoose.connection.on("disconnected", () => {
79
+ logger.warn(`[${this.serviceName}] MongoDB disconnected`);
80
+ if (!this.isConnecting) {
81
+ this.handleDisconnection();
82
+ }
83
+ });
84
+
85
+ mongoose.connection.on("error", (error) => {
86
+ logger.error(`[${this.serviceName}] MongoDB connection error:`, error);
87
+ if (error.name === "MongoNetworkError" || error.name === "MongoServerError") {
88
+ this.handleDisconnection();
89
+ }
90
+ });
91
+
92
+ mongoose.connection.on("reconnected", () => {
93
+ logger.info(`[${this.serviceName}] MongoDB reconnected successfully`);
94
+ this.retryCount = 0;
95
+ });
96
+
97
+ // Monitor replica set changes
98
+ mongoose.connection.on("reconnectFailed", () => {
99
+ logger.error(`[${this.serviceName}] MongoDB reconnection failed`);
100
+ this.handleDisconnection();
101
+ });
102
+
103
+ // Handle process termination
104
+ process.on("SIGINT", async () => {
105
+ await this.gracefulShutdown("SIGINT");
106
+ });
107
+
108
+ process.on("SIGTERM", async () => {
109
+ await this.gracefulShutdown("SIGTERM");
110
+ });
111
+ }
112
+
113
+ /**
114
+ * Handle disconnection with exponential backoff retry
115
+ */
116
+ private async handleDisconnection(): Promise<void> {
117
+ if (this.isConnecting) {
118
+ return;
119
+ }
120
+
121
+ if (this.retryCount >= (this.config.maxRetries || 10)) {
122
+ logger.error(`[${this.serviceName}] Max retry attempts (${this.config.maxRetries}) reached. Giving up.`);
123
+ process.exit(1); // Exit to allow container orchestration to restart
124
+ }
125
+
126
+ this.isConnecting = true;
127
+ this.retryCount++;
128
+
129
+ // Exponential backoff with jitter
130
+ const delay = Math.min(
131
+ (this.config.retryDelay || 5000) * Math.pow(2, this.retryCount - 1) + Math.random() * 1000,
132
+ 60000 // Max 60 seconds
133
+ );
134
+
135
+ logger.info(`[${this.serviceName}] Attempting to reconnect (attempt ${this.retryCount}/${this.config.maxRetries}) in ${delay}ms...`);
136
+
137
+ setTimeout(async () => {
138
+ try {
139
+ await this.reconnect();
140
+ this.isConnecting = false;
141
+ } catch (error) {
142
+ logger.error(`[${this.serviceName}] Reconnection attempt ${this.retryCount} failed: ${JSON.stringify(error)}`);
143
+ this.isConnecting = false;
144
+ this.handleDisconnection();
145
+ }
146
+ }, delay);
147
+ }
148
+
149
+ /**
150
+ * Reconnect to MongoDB
151
+ */
152
+ private async reconnect(): Promise<void> {
153
+ try {
154
+ // Close existing connection if any
155
+ if (mongoose.connection.readyState !== 0) {
156
+ await mongoose.connection.close();
157
+ }
158
+
159
+ // Attempt reconnection
160
+ await mongoose.connect(this.connectionString, this.getConnectionOptions());
161
+ logger.info(`[${this.serviceName}] Successfully reconnected to MongoDB`);
162
+ this.db = mongoose.connection;
163
+ } catch (error) {
164
+ throw new CustomError(
165
+ `${this.serviceName}_reconnection_failed`,
166
+ 500,
167
+ `Failed to reconnect to MongoDB: ${error.message}`,
168
+ error
169
+ );
170
+ }
171
+ }
172
+
173
+ /**
174
+ * Start health check monitoring
175
+ */
176
+ private startHealthCheck(): void {
177
+ if (!this.config.enableHealthCheck) {
178
+ return;
179
+ }
180
+
181
+ // Clear existing interval if any
182
+ if (this.healthCheckInterval) {
183
+ clearInterval(this.healthCheckInterval);
184
+ }
185
+
186
+ this.healthCheckInterval = setInterval(async () => {
187
+ try {
188
+ if (mongoose.connection.readyState !== 1) {
189
+ logger.warn(`[${this.serviceName}] MongoDB health check failed - readyState: ${mongoose.connection.readyState}`);
190
+ this.handleDisconnection();
191
+ return;
192
+ }
193
+
194
+ // Ping the database
195
+ const adminDb = mongoose.connection.db?.admin();
196
+ if (adminDb) {
197
+ const result = await adminDb.ping();
198
+ if (result?.ok !== 1) {
199
+ logger.warn(`[${this.serviceName}] MongoDB ping failed`);
200
+ this.handleDisconnection();
201
+ }
202
+ }
203
+ } catch (error) {
204
+ logger.error(`[${this.serviceName}] Health check error: ${JSON.stringify(error)}`);
205
+ this.handleDisconnection();
206
+ }
207
+ }, this.config.healthCheckInterval || 30000);
208
+ }
209
+
210
+ /**
211
+ * Graceful shutdown
212
+ */
213
+ private async gracefulShutdown(signal: string): Promise<void> {
214
+ logger.info(`[${this.serviceName}] Received ${signal}, starting graceful shutdown...`);
215
+
216
+ // Stop health checks
217
+ if (this.healthCheckInterval) {
218
+ clearInterval(this.healthCheckInterval);
219
+ }
220
+
221
+ try {
222
+ await mongoose.connection.close();
223
+ logger.info(`[${this.serviceName}] MongoDB connection closed gracefully`);
224
+ process.exit(0);
225
+ } catch (error) {
226
+ logger.error(`[${this.serviceName}] Error during graceful shutdown: ${JSON.stringify(error)}`);
227
+ process.exit(1);
228
+ }
229
+ }
230
+
231
+ /**
232
+ * Connect to MongoDB with enhanced error handling and retry logic
233
+ */
234
+ async connectToDB(
235
+ connectionString: string,
236
+ serviceName: string,
237
+ config?: ConnectionConfig
238
+ ): Promise<Connection> {
239
+ try {
240
+ // Merge custom config with defaults
241
+ if (config) {
242
+ this.config = { ...this.config, ...config };
243
+ }
244
+
245
+ // Check if already connected
246
+ if (this.db && mongoose.connection.readyState === 1) {
247
+ logger.info(`[${serviceName}] MongoDB already connected`);
248
+ return this.db;
249
+ }
250
+
251
+ this.connectionString = connectionString;
252
+ this.serviceName = serviceName;
253
+
254
+ // Setup event handlers before connecting
255
+ this.setupEventHandlers();
256
+
257
+ // Attempt connection
258
+ logger.info(`[${serviceName}] Connecting to MongoDB...`);
259
+ await mongoose.connect(connectionString, this.getConnectionOptions());
260
+
261
+ logger.info(
262
+ `[${serviceName}] Connected successfully to MongoDB (last 10 chars: ${connectionString.slice(-10)})`
263
+ );
264
+
265
+ this.db = mongoose.connection;
266
+
267
+ // Start health check monitoring
268
+ this.startHealthCheck();
269
+
270
+ return this.db;
271
+ } catch (error) {
272
+ logger.error(`[${serviceName}] Initial connection failed: ${JSON.stringify(error)}`);
273
+
274
+ // Start retry mechanism
275
+ this.handleDisconnection();
276
+
277
+ throw new CustomError(
278
+ `${serviceName}_mongoose_connection_failed`,
279
+ 500,
280
+ `Failed to connect to MongoDB: ${error.message}`,
281
+ error
282
+ );
283
+ }
284
+ }
285
+
286
+ /**
287
+ * Get current connection state
288
+ */
289
+ getConnectionState(): {
290
+ isConnected: boolean;
291
+ readyState: number;
292
+ readyStateText: string;
293
+ retryCount: number;
294
+ host?: string;
295
+ port?: number;
296
+ } {
297
+ const readyStates = {
298
+ 0: "disconnected",
299
+ 1: "connected",
300
+ 2: "connecting",
301
+ 3: "disconnecting"
302
+ };
303
+
304
+ return {
305
+ isConnected: mongoose.connection.readyState === 1,
306
+ readyState: mongoose.connection.readyState,
307
+ readyStateText: readyStates[mongoose.connection.readyState as keyof typeof readyStates] || "unknown",
308
+ retryCount: this.retryCount,
309
+ host: mongoose.connection.host,
310
+ port: mongoose.connection.port
311
+ };
312
+ }
313
+
314
+ /**
315
+ * Check if database is healthy
316
+ */
317
+ async isHealthy(): Promise<boolean> {
318
+ try {
319
+ if (mongoose.connection.readyState !== 1) {
320
+ return false;
321
+ }
322
+
323
+ // Try to ping the database
324
+ const adminDb = mongoose.connection.db?.admin();
325
+ if (adminDb) {
326
+ const result = await adminDb.ping();
327
+ return result?.ok === 1;
328
+ }
329
+
330
+ return false;
331
+ } catch (error) {
332
+ logger.error(`Health check failed: ${JSON.stringify(error)}`);
333
+ return false;
334
+ }
335
+ }
336
+ }
337
+
338
+ export default MongooseConnection.getDefaultInstance();
@@ -1,12 +0,0 @@
1
- declare class Tracer {
2
- private provider;
3
- init({ serviceName, url, environment, basicAuth, helios, }: {
4
- serviceName: string;
5
- url: string;
6
- environment: string;
7
- basicAuth: string;
8
- helios: any;
9
- }): void;
10
- }
11
- declare const _default: Tracer;
12
- export default _default;
@@ -1,55 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- const exporter_trace_otlp_grpc_1 = require("@opentelemetry/exporter-trace-otlp-grpc");
7
- const sdk_trace_node_1 = require("@opentelemetry/sdk-trace-node");
8
- const grpc = require("@grpc/grpc-js");
9
- const logger_1 = __importDefault(require("@nimee/logger"));
10
- class Tracer {
11
- init({ serviceName, url, environment, basicAuth, helios, }) {
12
- try {
13
- const metadata = new grpc.Metadata();
14
- // after "Basic", comes the output of:
15
- // echo -n username:password | base64 -w 0
16
- metadata.set("authorization", basicAuth);
17
- const exporter = new exporter_trace_otlp_grpc_1.OTLPTraceExporter({
18
- url: url,
19
- credentials: grpc.credentials.createSsl(),
20
- metadata,
21
- });
22
- this.provider = helios;
23
- // this.provider = new BasicTracerProvider({
24
- // resource: new Resource({
25
- // [SemanticResourceAttributes.SERVICE_NAME]: serviceName,
26
- // [SemanticResourceAttributes.SERVICE_VERSION]: "1.0.0",
27
- // [SemanticResourceAttributes.DEPLOYMENT_ENVIRONMENT]: environment,
28
- // [SemanticResourceAttributes.TELEMETRY_SDK_LANGUAGE]: "node",
29
- // }),
30
- // });
31
- // export spans to console (useful for debugging)s
32
- // this.provider.addSpanProcessor(new SimpleSpanProcessor(new ConsoleSpanExporter()));
33
- // export spans to opentelemetry collector
34
- this.provider.addSpanProcessor(new sdk_trace_node_1.SimpleSpanProcessor(exporter));
35
- // this.provider.register();
36
- // this.sdk = new NodeSDK({
37
- // traceExporter: exporter,
38
- // instrumentations: [
39
- // getNodeAutoInstrumentations({
40
- // // Lets disable fs for now, otherwise we cannot see the traces we want,
41
- // // You can disable or enable instrumentation as needed
42
- // "@opentelemetry/instrumentation-fs": { enabled: false },
43
- // }),
44
- // ],
45
- // });
46
- // this.sdk.start();
47
- logger_1.default.info(`The tracer has been initialized with the service name: ${serviceName} and node environment: ${environment}`);
48
- }
49
- catch (e) {
50
- logger_1.default.error(`Failed to initialize the trace with error: ${e}`);
51
- }
52
- }
53
- }
54
- exports.default = new Tracer();
55
- //# sourceMappingURL=tracer.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"tracer.js","sourceRoot":"","sources":["../../src/tracer.ts"],"names":[],"mappings":";;;;;AAAA,sFAA4E;AAC5E,kEAAoE;AACpE,MAAM,IAAI,GAAG,OAAO,CAAC,eAAe,CAAC,CAAC;AAEtC,2DAAmC;AACnC,MAAM,MAAM;IAGH,IAAI,CAAC,EACV,WAAW,EACX,GAAG,EACH,WAAW,EACX,SAAS,EACT,MAAM,GAOP;QACC,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YACrC,sCAAsC;YACtC,0CAA0C;YAC1C,QAAQ,CAAC,GAAG,CAAC,eAAe,EAAE,SAAS,CAAC,CAAC;YAEzC,MAAM,QAAQ,GAAG,IAAI,4CAAiB,CAAC;gBACrC,GAAG,EAAE,GAAG;gBACR,WAAW,EAAE,IAAI,CAAC,WAAW,CAAC,SAAS,EAAE;gBACzC,QAAQ;aACT,CAAC,CAAC;YACH,IAAI,CAAC,QAAQ,GAAG,MAAM,CAAC;YAEvB,4CAA4C;YAC5C,6BAA6B;YAC7B,8DAA8D;YAC9D,6DAA6D;YAC7D,wEAAwE;YACxE,mEAAmE;YACnE,QAAQ;YACR,MAAM;YACN,kDAAkD;YAClD,sFAAsF;YACtF,0CAA0C;YAC1C,IAAI,CAAC,QAAQ,CAAC,gBAAgB,CAAC,IAAI,oCAAmB,CAAC,QAAQ,CAAC,CAAC,CAAC;YAClE,4BAA4B;YAC5B,2BAA2B;YAC3B,6BAA6B;YAC7B,wBAAwB;YACxB,oCAAoC;YACpC,gFAAgF;YAChF,+DAA+D;YAC/D,iEAAiE;YACjE,UAAU;YACV,OAAO;YACP,MAAM;YAEN,oBAAoB;YAEpB,gBAAM,CAAC,IAAI,CAAC,0DAA0D,WAAW,0BAA0B,WAAW,EAAE,CAAC,CAAC;QAC5H,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,gBAAM,CAAC,KAAK,CAAC,8CAA8C,CAAC,EAAE,CAAC,CAAC;QAClE,CAAC;IACH,CAAC;CACF;AAED,kBAAe,IAAI,MAAM,EAAE,CAAC"}