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