@naman_deep_singh/communication-core 1.0.0

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.
Files changed (134) hide show
  1. package/README.md +345 -0
  2. package/dist/cjs/abstract/BaseCircuitBreaker.js +253 -0
  3. package/dist/cjs/abstract/BaseClient.js +298 -0
  4. package/dist/cjs/abstract/BaseCompressionManager.js +377 -0
  5. package/dist/cjs/abstract/BaseConnectionPool.js +543 -0
  6. package/dist/cjs/abstract/BaseInterceptor.js +235 -0
  7. package/dist/cjs/abstract/BaseLoadBalancer.js +269 -0
  8. package/dist/cjs/abstract/BaseProtocol.js +269 -0
  9. package/dist/cjs/abstract/BaseRetryStrategy.js +255 -0
  10. package/dist/cjs/abstract/BaseSerializer.js +341 -0
  11. package/dist/cjs/abstract/BaseServiceDiscoverer.js +254 -0
  12. package/dist/cjs/abstract/BaseTimeoutManager.js +295 -0
  13. package/dist/cjs/abstract/index.js +25 -0
  14. package/dist/cjs/errors/CircuitBreakerError.js +16 -0
  15. package/dist/cjs/errors/CommunicationError.js +15 -0
  16. package/dist/cjs/errors/ConnectionError.js +15 -0
  17. package/dist/cjs/errors/DiscoveryError.js +15 -0
  18. package/dist/cjs/errors/LoadBalancerError.js +15 -0
  19. package/dist/cjs/errors/ProtocolError.js +15 -0
  20. package/dist/cjs/errors/RetryError.js +16 -0
  21. package/dist/cjs/errors/SerializationError.js +15 -0
  22. package/dist/cjs/errors/ServiceUnavailableError.js +15 -0
  23. package/dist/cjs/errors/TimeoutError.js +16 -0
  24. package/dist/cjs/errors/communicationErrorCodes.js +35 -0
  25. package/dist/cjs/errors/index.js +31 -0
  26. package/dist/cjs/index.js +38 -0
  27. package/dist/cjs/interfaces/CircuitBreaker.interface.js +6 -0
  28. package/dist/cjs/interfaces/Client.interface.js +6 -0
  29. package/dist/cjs/interfaces/Compression.interface.js +6 -0
  30. package/dist/cjs/interfaces/ConnectionPool.interface.js +6 -0
  31. package/dist/cjs/interfaces/Interceptor.interface.js +6 -0
  32. package/dist/cjs/interfaces/LoadBalancer.interface.js +2 -0
  33. package/dist/cjs/interfaces/Protocol.interface.js +6 -0
  34. package/dist/cjs/interfaces/RetryStrategy.interface.js +6 -0
  35. package/dist/cjs/interfaces/Serializer.interface.js +2 -0
  36. package/dist/cjs/interfaces/ServiceDiscovery.interface.js +6 -0
  37. package/dist/cjs/interfaces/Timeout.interface.js +6 -0
  38. package/dist/cjs/interfaces/index.js +6 -0
  39. package/dist/cjs/types/config.js +6 -0
  40. package/dist/cjs/types/events.js +6 -0
  41. package/dist/cjs/types/index.js +6 -0
  42. package/dist/cjs/types/request.js +6 -0
  43. package/dist/cjs/types/response.js +6 -0
  44. package/dist/cjs/types/service.js +6 -0
  45. package/dist/cjs/utils.js +200 -0
  46. package/dist/esm/abstract/BaseCircuitBreaker.js +249 -0
  47. package/dist/esm/abstract/BaseClient.js +294 -0
  48. package/dist/esm/abstract/BaseCompressionManager.js +373 -0
  49. package/dist/esm/abstract/BaseConnectionPool.js +539 -0
  50. package/dist/esm/abstract/BaseInterceptor.js +231 -0
  51. package/dist/esm/abstract/BaseLoadBalancer.js +265 -0
  52. package/dist/esm/abstract/BaseProtocol.js +265 -0
  53. package/dist/esm/abstract/BaseRetryStrategy.js +251 -0
  54. package/dist/esm/abstract/BaseSerializer.js +337 -0
  55. package/dist/esm/abstract/BaseServiceDiscoverer.js +250 -0
  56. package/dist/esm/abstract/BaseTimeoutManager.js +291 -0
  57. package/dist/esm/abstract/index.js +11 -0
  58. package/dist/esm/errors/CircuitBreakerError.js +12 -0
  59. package/dist/esm/errors/CommunicationError.js +11 -0
  60. package/dist/esm/errors/ConnectionError.js +11 -0
  61. package/dist/esm/errors/DiscoveryError.js +11 -0
  62. package/dist/esm/errors/LoadBalancerError.js +11 -0
  63. package/dist/esm/errors/ProtocolError.js +11 -0
  64. package/dist/esm/errors/RetryError.js +12 -0
  65. package/dist/esm/errors/SerializationError.js +11 -0
  66. package/dist/esm/errors/ServiceUnavailableError.js +11 -0
  67. package/dist/esm/errors/TimeoutError.js +12 -0
  68. package/dist/esm/errors/communicationErrorCodes.js +32 -0
  69. package/dist/esm/errors/index.js +17 -0
  70. package/dist/esm/index.js +18 -0
  71. package/dist/esm/interfaces/CircuitBreaker.interface.js +5 -0
  72. package/dist/esm/interfaces/Client.interface.js +5 -0
  73. package/dist/esm/interfaces/Compression.interface.js +5 -0
  74. package/dist/esm/interfaces/ConnectionPool.interface.js +5 -0
  75. package/dist/esm/interfaces/Interceptor.interface.js +5 -0
  76. package/dist/esm/interfaces/LoadBalancer.interface.js +1 -0
  77. package/dist/esm/interfaces/Protocol.interface.js +5 -0
  78. package/dist/esm/interfaces/RetryStrategy.interface.js +5 -0
  79. package/dist/esm/interfaces/Serializer.interface.js +1 -0
  80. package/dist/esm/interfaces/ServiceDiscovery.interface.js +5 -0
  81. package/dist/esm/interfaces/Timeout.interface.js +5 -0
  82. package/dist/esm/interfaces/index.js +5 -0
  83. package/dist/esm/types/config.js +5 -0
  84. package/dist/esm/types/events.js +5 -0
  85. package/dist/esm/types/index.js +5 -0
  86. package/dist/esm/types/request.js +5 -0
  87. package/dist/esm/types/response.js +5 -0
  88. package/dist/esm/types/service.js +5 -0
  89. package/dist/esm/utils.js +193 -0
  90. package/dist/types/abstract/BaseCircuitBreaker.d.ts +167 -0
  91. package/dist/types/abstract/BaseClient.d.ts +197 -0
  92. package/dist/types/abstract/BaseCompressionManager.d.ts +180 -0
  93. package/dist/types/abstract/BaseConnectionPool.d.ts +210 -0
  94. package/dist/types/abstract/BaseInterceptor.d.ts +150 -0
  95. package/dist/types/abstract/BaseLoadBalancer.d.ts +167 -0
  96. package/dist/types/abstract/BaseProtocol.d.ts +163 -0
  97. package/dist/types/abstract/BaseRetryStrategy.d.ts +130 -0
  98. package/dist/types/abstract/BaseSerializer.d.ts +181 -0
  99. package/dist/types/abstract/BaseServiceDiscoverer.d.ts +161 -0
  100. package/dist/types/abstract/BaseTimeoutManager.d.ts +145 -0
  101. package/dist/types/abstract/index.d.ts +11 -0
  102. package/dist/types/errors/CircuitBreakerError.d.ts +8 -0
  103. package/dist/types/errors/CommunicationError.d.ts +10 -0
  104. package/dist/types/errors/ConnectionError.d.ts +9 -0
  105. package/dist/types/errors/DiscoveryError.d.ts +9 -0
  106. package/dist/types/errors/LoadBalancerError.d.ts +9 -0
  107. package/dist/types/errors/ProtocolError.d.ts +9 -0
  108. package/dist/types/errors/RetryError.d.ts +11 -0
  109. package/dist/types/errors/SerializationError.d.ts +9 -0
  110. package/dist/types/errors/ServiceUnavailableError.d.ts +12 -0
  111. package/dist/types/errors/TimeoutError.d.ts +11 -0
  112. package/dist/types/errors/communicationErrorCodes.d.ts +27 -0
  113. package/dist/types/errors/index.d.ts +11 -0
  114. package/dist/types/index.d.ts +13 -0
  115. package/dist/types/interfaces/CircuitBreaker.interface.d.ts +150 -0
  116. package/dist/types/interfaces/Client.interface.d.ts +153 -0
  117. package/dist/types/interfaces/Compression.interface.d.ts +190 -0
  118. package/dist/types/interfaces/ConnectionPool.interface.d.ts +191 -0
  119. package/dist/types/interfaces/Interceptor.interface.d.ts +220 -0
  120. package/dist/types/interfaces/LoadBalancer.interface.d.ts +153 -0
  121. package/dist/types/interfaces/Protocol.interface.d.ts +117 -0
  122. package/dist/types/interfaces/RetryStrategy.interface.d.ts +160 -0
  123. package/dist/types/interfaces/Serializer.interface.d.ts +176 -0
  124. package/dist/types/interfaces/ServiceDiscovery.interface.d.ts +189 -0
  125. package/dist/types/interfaces/Timeout.interface.d.ts +135 -0
  126. package/dist/types/interfaces/index.d.ts +15 -0
  127. package/dist/types/types/config.d.ts +540 -0
  128. package/dist/types/types/events.d.ts +204 -0
  129. package/dist/types/types/index.d.ts +9 -0
  130. package/dist/types/types/request.d.ts +143 -0
  131. package/dist/types/types/response.d.ts +155 -0
  132. package/dist/types/types/service.d.ts +279 -0
  133. package/dist/types/utils.d.ts +179 -0
  134. package/package.json +88 -0
@@ -0,0 +1,341 @@
1
+ "use strict";
2
+ /**
3
+ * Abstract base serializer implementation
4
+ * @packageDocumentation
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.BaseSerializer = void 0;
8
+ const CommunicationError_js_1 = require("../errors/CommunicationError.js");
9
+ const communicationErrorCodes_js_1 = require("../errors/communicationErrorCodes.js");
10
+ /**
11
+ * Abstract base serializer implementation
12
+ * Provides common functionality for all serializer implementations
13
+ */
14
+ class BaseSerializer {
15
+ /**
16
+ * Create a new base serializer instance
17
+ * @param name Serializer name
18
+ * @param config Serializer configuration
19
+ */
20
+ constructor(name, config) {
21
+ /** Format handlers registry */
22
+ this.formatHandlers = new Map();
23
+ /** Serializer statistics */
24
+ this.stats = {
25
+ totalSerializations: 0,
26
+ totalDeserializations: 0,
27
+ serializationErrors: 0,
28
+ deserializationErrors: 0,
29
+ averageSerializationTime: 0,
30
+ averageDeserializationTime: 0,
31
+ formatUsage: {},
32
+ };
33
+ this.name = name;
34
+ this.config = { ...config };
35
+ this.supportedFormats = this.initializeSupportedFormats();
36
+ this.defaultFormat = this.supportedFormats[0] || 'json';
37
+ this.initialize();
38
+ }
39
+ /**
40
+ * Initialize serializer
41
+ */
42
+ initialize() {
43
+ // Register default format handlers
44
+ this.registerDefaultHandlers();
45
+ }
46
+ /**
47
+ * Perform serialization with timing and error handling
48
+ * @param data Data to serialize
49
+ * @param context Serialization context
50
+ * @param handler Serialization handler
51
+ * @returns Serialized data
52
+ */
53
+ performSerialization(data, context, handler) {
54
+ const startTime = Date.now();
55
+ const format = context.format;
56
+ try {
57
+ // Transform data if needed
58
+ const transformedData = this.transformData(data, 'serialize');
59
+ // Perform serialization
60
+ const result = handler(transformedData, context);
61
+ // Update statistics
62
+ this.updateSerializationStats(true, Date.now() - startTime, format);
63
+ return result;
64
+ }
65
+ catch (error) {
66
+ // Update error statistics
67
+ this.updateSerializationStats(false, Date.now() - startTime, format);
68
+ throw new CommunicationError_js_1.CommunicationError(communicationErrorCodes_js_1.COMMUNICATION_ERROR_CODES.SERIALIZATION_ERROR, 500, {
69
+ message: `Serialization failed for format: ${format}`,
70
+ format,
71
+ originalError: error instanceof Error ? error.message : String(error),
72
+ });
73
+ }
74
+ }
75
+ /**
76
+ * Perform deserialization with timing and error handling
77
+ * @param data Data to deserialize
78
+ * @param context Deserialization context
79
+ * @param handler Deserialization handler
80
+ * @returns Deserialized data
81
+ */
82
+ performDeserialization(data, context, handler) {
83
+ const startTime = Date.now();
84
+ const format = context.format;
85
+ try {
86
+ // Perform deserialization
87
+ const result = handler(data, context);
88
+ // Transform data if needed
89
+ const transformedResult = this.transformData(result, 'deserialize');
90
+ // Update statistics
91
+ this.updateDeserializationStats(true, Date.now() - startTime, format);
92
+ return transformedResult;
93
+ }
94
+ catch (error) {
95
+ // Update error statistics
96
+ this.updateDeserializationStats(false, Date.now() - startTime, format);
97
+ throw new CommunicationError_js_1.CommunicationError(communicationErrorCodes_js_1.COMMUNICATION_ERROR_CODES.DESERIALIZATION_ERROR, 500, {
98
+ message: `Deserialization failed for format: ${format}`,
99
+ format,
100
+ originalError: error instanceof Error ? error.message : String(error),
101
+ });
102
+ }
103
+ }
104
+ /**
105
+ * Transform data (e.g., date parsing, bigint handling)
106
+ * @param data Data to transform
107
+ * @param direction 'serialize' or 'deserialize'
108
+ */
109
+ transformData(data, direction) {
110
+ if (data === null || data === undefined) {
111
+ return data;
112
+ }
113
+ // Handle dates based on configuration
114
+ if (this.config.dateParsing) {
115
+ data = this.transformDates(data, direction);
116
+ }
117
+ // Handle bigints based on configuration
118
+ if (this.config.bigIntParsing) {
119
+ data = this.transformBigInts(data, direction);
120
+ }
121
+ // Apply custom transformations
122
+ data = this.applyCustomTransformations(data, direction);
123
+ return data;
124
+ }
125
+ /**
126
+ * Transform dates based on configuration
127
+ * @param data Data containing dates
128
+ * @param direction Transformation direction
129
+ */
130
+ transformDates(data, direction) {
131
+ if (data instanceof Date) {
132
+ switch (this.config.dateParsing) {
133
+ case 'string':
134
+ return direction === 'serialize' ? data.toISOString() : data;
135
+ case 'timestamp':
136
+ return direction === 'serialize' ? data.getTime() : data;
137
+ default:
138
+ return data;
139
+ }
140
+ }
141
+ if (Array.isArray(data)) {
142
+ return data.map(item => this.transformDates(item, direction));
143
+ }
144
+ if (typeof data === 'object' && data !== null) {
145
+ const transformed = {};
146
+ for (const [key, value] of Object.entries(data)) {
147
+ transformed[key] = this.transformDates(value, direction);
148
+ }
149
+ return transformed;
150
+ }
151
+ return data;
152
+ }
153
+ /**
154
+ * Transform bigints based on configuration
155
+ * @param data Data containing bigints
156
+ * @param direction Transformation direction
157
+ */
158
+ transformBigInts(data, direction) {
159
+ if (typeof data === 'bigint') {
160
+ switch (this.config.bigIntParsing) {
161
+ case 'string':
162
+ return direction === 'serialize' ? data.toString() : data;
163
+ case 'number':
164
+ return direction === 'serialize' ? Number(data) : BigInt(data);
165
+ default:
166
+ return data;
167
+ }
168
+ }
169
+ if (Array.isArray(data)) {
170
+ return data.map(item => this.transformBigInts(item, direction));
171
+ }
172
+ if (typeof data === 'object' && data !== null) {
173
+ const transformed = {};
174
+ for (const [key, value] of Object.entries(data)) {
175
+ transformed[key] = this.transformBigInts(value, direction);
176
+ }
177
+ return transformed;
178
+ }
179
+ return data;
180
+ }
181
+ /**
182
+ * Apply custom transformations
183
+ * @param data Data to transform
184
+ * @param direction Transformation direction
185
+ */
186
+ applyCustomTransformations(data, direction) {
187
+ // Can be overridden by subclasses
188
+ return data;
189
+ }
190
+ /**
191
+ * Update serialization statistics
192
+ * @param success Whether serialization succeeded
193
+ * @param duration Serialization duration in milliseconds
194
+ * @param format Format used
195
+ */
196
+ updateSerializationStats(success, duration, format) {
197
+ this.stats.totalSerializations++;
198
+ this.stats.averageSerializationTime = ((this.stats.averageSerializationTime * (this.stats.totalSerializations - 1) + duration) /
199
+ this.stats.totalSerializations);
200
+ if (!success) {
201
+ this.stats.serializationErrors++;
202
+ }
203
+ // Update format usage
204
+ this.stats.formatUsage[format] = (this.stats.formatUsage[format] || 0) + 1;
205
+ }
206
+ /**
207
+ * Update deserialization statistics
208
+ * @param success Whether deserialization succeeded
209
+ * @param duration Deserialization duration in milliseconds
210
+ * @param format Format used
211
+ */
212
+ updateDeserializationStats(success, duration, format) {
213
+ this.stats.totalDeserializations++;
214
+ this.stats.averageDeserializationTime = ((this.stats.averageDeserializationTime * (this.stats.totalDeserializations - 1) + duration) /
215
+ this.stats.totalDeserializations);
216
+ if (!success) {
217
+ this.stats.deserializationErrors++;
218
+ }
219
+ // Update format usage
220
+ this.stats.formatUsage[format] = (this.stats.formatUsage[format] || 0) + 1;
221
+ }
222
+ /**
223
+ * Check if a format is supported
224
+ * @param format Format to check
225
+ */
226
+ supportsFormat(format) {
227
+ return this.supportedFormats.includes(format);
228
+ }
229
+ /**
230
+ * Get content type for a format
231
+ * @param format Format
232
+ * @returns Content type string
233
+ */
234
+ getContentType(format) {
235
+ const handler = this.formatHandlers.get(format);
236
+ if (handler?.contentType) {
237
+ return handler.contentType;
238
+ }
239
+ // Default content types
240
+ switch (format) {
241
+ case 'json':
242
+ return 'application/json';
243
+ case 'xml':
244
+ return 'application/xml';
245
+ case 'yaml':
246
+ return 'application/yaml';
247
+ case 'protobuf':
248
+ return 'application/protobuf';
249
+ case 'msgpack':
250
+ return 'application/msgpack';
251
+ default:
252
+ return 'application/octet-stream';
253
+ }
254
+ }
255
+ /**
256
+ * Get format from content type
257
+ * @param contentType Content type
258
+ * @returns Format or undefined if not recognized
259
+ */
260
+ getFormatFromContentType(contentType) {
261
+ const normalized = contentType.toLowerCase().split(';')[0].trim();
262
+ for (const [format, handler] of this.formatHandlers.entries()) {
263
+ if (handler.contentType && handler.contentType.toLowerCase() === normalized) {
264
+ return format;
265
+ }
266
+ }
267
+ // Check common content types
268
+ if (normalized.includes('json')) {
269
+ return 'json';
270
+ }
271
+ else if (normalized.includes('xml')) {
272
+ return 'xml';
273
+ }
274
+ else if (normalized.includes('yaml') || normalized.includes('yml')) {
275
+ return 'yaml';
276
+ }
277
+ else if (normalized.includes('protobuf')) {
278
+ return 'protobuf';
279
+ }
280
+ else if (normalized.includes('msgpack')) {
281
+ return 'msgpack';
282
+ }
283
+ return undefined;
284
+ }
285
+ /**
286
+ * Register a custom format handler
287
+ * @param format Format name
288
+ * @param handler Serialization/deserialization functions
289
+ */
290
+ registerFormat(format, handler) {
291
+ this.formatHandlers.set(format, handler);
292
+ if (!this.supportedFormats.includes(format)) {
293
+ this.supportedFormats.push(format);
294
+ }
295
+ }
296
+ /**
297
+ * Update serializer configuration
298
+ * @param config New configuration
299
+ */
300
+ updateConfig(config) {
301
+ this.config = { ...this.config, ...config };
302
+ }
303
+ /**
304
+ * Get serializer statistics
305
+ */
306
+ getStats() {
307
+ return { ...this.stats };
308
+ }
309
+ /**
310
+ * Reset serializer statistics
311
+ */
312
+ resetStats() {
313
+ this.stats = {
314
+ totalSerializations: 0,
315
+ totalDeserializations: 0,
316
+ serializationErrors: 0,
317
+ deserializationErrors: 0,
318
+ averageSerializationTime: 0,
319
+ averageDeserializationTime: 0,
320
+ formatUsage: {},
321
+ };
322
+ }
323
+ /**
324
+ * Health check for the serializer
325
+ */
326
+ healthCheck() {
327
+ const healthy = this.supportedFormats.length > 0;
328
+ return {
329
+ healthy,
330
+ message: healthy ? 'Serializer is operational' : 'No supported formats configured',
331
+ details: {
332
+ name: this.name,
333
+ supportedFormats: this.supportedFormats,
334
+ defaultFormat: this.defaultFormat,
335
+ registeredFormats: Array.from(this.formatHandlers.keys()),
336
+ statistics: this.getStats(),
337
+ },
338
+ };
339
+ }
340
+ }
341
+ exports.BaseSerializer = BaseSerializer;
@@ -0,0 +1,254 @@
1
+ "use strict";
2
+ /**
3
+ * Abstract base service discoverer implementation
4
+ * @packageDocumentation
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.BaseServiceDiscoverer = void 0;
8
+ /**
9
+ * Abstract base service discoverer implementation
10
+ * Provides common functionality for all service discovery implementations
11
+ */
12
+ class BaseServiceDiscoverer {
13
+ /**
14
+ * Create a new base service discoverer instance
15
+ * @param type Discovery type
16
+ * @param config Discovery configuration
17
+ */
18
+ constructor(type, config) {
19
+ /** Whether discovery is currently active */
20
+ this.isActive = false;
21
+ /** Total services discovered */
22
+ this.totalServicesDiscovered = 0;
23
+ /** Total instances discovered */
24
+ this.totalInstancesDiscovered = 0;
25
+ /** Service cache */
26
+ this.cache = new Map();
27
+ /** Cache timestamps */
28
+ this.cacheTimestamps = new Map();
29
+ /** Watch callbacks */
30
+ this.watchers = new Map();
31
+ /** Discovery statistics */
32
+ this.stats = {
33
+ totalResolves: 0,
34
+ totalWatches: 0,
35
+ cacheHits: 0,
36
+ cacheMisses: 0,
37
+ cacheHitRate: 0,
38
+ averageResolveTime: 0,
39
+ totalResolveTime: 0,
40
+ uptime: 0,
41
+ startTime: Date.now(),
42
+ };
43
+ this.type = type;
44
+ this.config = { ...config };
45
+ this.initialize();
46
+ }
47
+ /**
48
+ * Initialize service discoverer
49
+ */
50
+ initialize() {
51
+ // Can be overridden by subclasses
52
+ }
53
+ /**
54
+ * Resolve all instances for multiple services
55
+ * @param serviceNames Array of service names
56
+ * @returns Promise resolving to map of service names to instances
57
+ */
58
+ async resolveAll(serviceNames) {
59
+ const results = new Map();
60
+ for (const serviceName of serviceNames) {
61
+ try {
62
+ const result = await this.resolve(serviceName);
63
+ results.set(serviceName, result.instances);
64
+ }
65
+ catch (error) {
66
+ results.set(serviceName, []);
67
+ }
68
+ }
69
+ return results;
70
+ }
71
+ /**
72
+ * Watch for changes to service instances
73
+ * @param serviceName Service name to watch
74
+ * @param callback Callback function for changes
75
+ * @returns Unwatch function
76
+ */
77
+ watch(serviceName, callback) {
78
+ let watchers = this.watchers.get(serviceName);
79
+ if (!watchers) {
80
+ watchers = new Set();
81
+ this.watchers.set(serviceName, watchers);
82
+ }
83
+ watchers.add(callback);
84
+ this.stats.totalWatches++;
85
+ return () => {
86
+ watchers?.delete(callback);
87
+ if (watchers?.size === 0) {
88
+ this.watchers.delete(serviceName);
89
+ }
90
+ };
91
+ }
92
+ /**
93
+ * Stop watching a service
94
+ * @param serviceName Service name to stop watching
95
+ */
96
+ unwatch(serviceName) {
97
+ this.watchers.delete(serviceName);
98
+ }
99
+ /**
100
+ * Stop watching all services
101
+ */
102
+ unwatchAll() {
103
+ this.watchers.clear();
104
+ }
105
+ /**
106
+ * Get cached service instances
107
+ * @param serviceName Service name
108
+ * @returns Cached instances or empty array
109
+ */
110
+ getCachedInstances(serviceName) {
111
+ return this.cache.get(serviceName) || [];
112
+ }
113
+ /**
114
+ * Clear cache for a service
115
+ * @param serviceName Service name
116
+ */
117
+ clearCache(serviceName) {
118
+ if (serviceName) {
119
+ this.cache.delete(serviceName);
120
+ this.cacheTimestamps.delete(serviceName);
121
+ }
122
+ else {
123
+ this.cache.clear();
124
+ this.cacheTimestamps.clear();
125
+ }
126
+ }
127
+ /**
128
+ * Refresh cache for a service
129
+ * @param serviceName Service name
130
+ * @returns Promise resolving when cache is refreshed
131
+ */
132
+ async refreshCache(serviceName) {
133
+ if (serviceName) {
134
+ this.clearCache(serviceName);
135
+ await this.resolve(serviceName);
136
+ }
137
+ else {
138
+ const serviceNames = Array.from(this.cache.keys());
139
+ this.clearCache();
140
+ await this.resolveAll(serviceNames);
141
+ }
142
+ }
143
+ /**
144
+ * Check if cache is valid for a service
145
+ * @param serviceName Service name
146
+ * @returns True if cache is valid
147
+ */
148
+ isCacheValid(serviceName) {
149
+ if (!this.config.cache?.enabled)
150
+ return false;
151
+ const timestamp = this.cacheTimestamps.get(serviceName);
152
+ if (!timestamp)
153
+ return false;
154
+ const ttl = this.config.cache.ttl;
155
+ return (Date.now() - timestamp) < ttl;
156
+ }
157
+ /**
158
+ * Update cache for a service
159
+ * @param serviceName Service name
160
+ * @param instances Service instances
161
+ */
162
+ updateCache(serviceName, instances) {
163
+ if (this.config.cache?.enabled) {
164
+ this.cache.set(serviceName, instances);
165
+ this.cacheTimestamps.set(serviceName, Date.now());
166
+ }
167
+ }
168
+ /**
169
+ * Notify watchers of service changes
170
+ * @param serviceName Service name
171
+ * @param instances Updated instances
172
+ */
173
+ notifyWatchers(serviceName, instances) {
174
+ const watchers = this.watchers.get(serviceName);
175
+ if (watchers) {
176
+ for (const callback of watchers) {
177
+ try {
178
+ callback(instances);
179
+ }
180
+ catch (error) {
181
+ // Log error but continue
182
+ }
183
+ }
184
+ }
185
+ }
186
+ /**
187
+ * Get service discovery statistics
188
+ */
189
+ getStats() {
190
+ this.stats.uptime = Date.now() - this.stats.startTime;
191
+ this.stats.cacheHitRate = this.stats.totalResolves > 0
192
+ ? this.stats.cacheHits / this.stats.totalResolves
193
+ : 0;
194
+ return { ...this.stats };
195
+ }
196
+ /**
197
+ * Reset service discovery statistics
198
+ */
199
+ resetStats() {
200
+ this.stats = {
201
+ totalResolves: 0,
202
+ totalWatches: 0,
203
+ cacheHits: 0,
204
+ cacheMisses: 0,
205
+ cacheHitRate: 0,
206
+ averageResolveTime: 0,
207
+ totalResolveTime: 0,
208
+ uptime: 0,
209
+ startTime: Date.now(),
210
+ };
211
+ }
212
+ /**
213
+ * Update service discovery configuration
214
+ * @param config New configuration
215
+ */
216
+ updateConfig(config) {
217
+ this.config = { ...this.config, ...config };
218
+ }
219
+ /**
220
+ * Health check for the service discoverer itself
221
+ */
222
+ async healthCheckSelf() {
223
+ const healthy = this.isActive;
224
+ return {
225
+ healthy,
226
+ message: healthy ? 'Service discoverer is operational' : 'Service discoverer is not active',
227
+ details: {
228
+ type: this.type,
229
+ isActive: this.isActive,
230
+ totalServices: this.totalServicesDiscovered,
231
+ totalInstances: this.totalInstancesDiscovered,
232
+ cacheSize: this.cache.size,
233
+ watchersCount: this.watchers.size,
234
+ stats: this.getStats(),
235
+ },
236
+ };
237
+ }
238
+ /**
239
+ * Close/cleanup service discovery resources
240
+ */
241
+ async close() {
242
+ this.isActive = false;
243
+ this.unwatchAll();
244
+ this.clearCache();
245
+ await this.onClose();
246
+ }
247
+ /**
248
+ * Hook for cleanup logic
249
+ */
250
+ async onClose() {
251
+ // Can be overridden by subclasses
252
+ }
253
+ }
254
+ exports.BaseServiceDiscoverer = BaseServiceDiscoverer;