@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.
- package/README.md +345 -0
- package/dist/cjs/abstract/BaseCircuitBreaker.js +253 -0
- package/dist/cjs/abstract/BaseClient.js +298 -0
- package/dist/cjs/abstract/BaseCompressionManager.js +377 -0
- package/dist/cjs/abstract/BaseConnectionPool.js +543 -0
- package/dist/cjs/abstract/BaseInterceptor.js +235 -0
- package/dist/cjs/abstract/BaseLoadBalancer.js +269 -0
- package/dist/cjs/abstract/BaseProtocol.js +269 -0
- package/dist/cjs/abstract/BaseRetryStrategy.js +255 -0
- package/dist/cjs/abstract/BaseSerializer.js +341 -0
- package/dist/cjs/abstract/BaseServiceDiscoverer.js +254 -0
- package/dist/cjs/abstract/BaseTimeoutManager.js +295 -0
- package/dist/cjs/abstract/index.js +25 -0
- package/dist/cjs/errors/CircuitBreakerError.js +16 -0
- package/dist/cjs/errors/CommunicationError.js +15 -0
- package/dist/cjs/errors/ConnectionError.js +15 -0
- package/dist/cjs/errors/DiscoveryError.js +15 -0
- package/dist/cjs/errors/LoadBalancerError.js +15 -0
- package/dist/cjs/errors/ProtocolError.js +15 -0
- package/dist/cjs/errors/RetryError.js +16 -0
- package/dist/cjs/errors/SerializationError.js +15 -0
- package/dist/cjs/errors/ServiceUnavailableError.js +15 -0
- package/dist/cjs/errors/TimeoutError.js +16 -0
- package/dist/cjs/errors/communicationErrorCodes.js +35 -0
- package/dist/cjs/errors/index.js +31 -0
- package/dist/cjs/index.js +38 -0
- package/dist/cjs/interfaces/CircuitBreaker.interface.js +6 -0
- package/dist/cjs/interfaces/Client.interface.js +6 -0
- package/dist/cjs/interfaces/Compression.interface.js +6 -0
- package/dist/cjs/interfaces/ConnectionPool.interface.js +6 -0
- package/dist/cjs/interfaces/Interceptor.interface.js +6 -0
- package/dist/cjs/interfaces/LoadBalancer.interface.js +2 -0
- package/dist/cjs/interfaces/Protocol.interface.js +6 -0
- package/dist/cjs/interfaces/RetryStrategy.interface.js +6 -0
- package/dist/cjs/interfaces/Serializer.interface.js +2 -0
- package/dist/cjs/interfaces/ServiceDiscovery.interface.js +6 -0
- package/dist/cjs/interfaces/Timeout.interface.js +6 -0
- package/dist/cjs/interfaces/index.js +6 -0
- package/dist/cjs/types/config.js +6 -0
- package/dist/cjs/types/events.js +6 -0
- package/dist/cjs/types/index.js +6 -0
- package/dist/cjs/types/request.js +6 -0
- package/dist/cjs/types/response.js +6 -0
- package/dist/cjs/types/service.js +6 -0
- package/dist/cjs/utils.js +200 -0
- package/dist/esm/abstract/BaseCircuitBreaker.js +249 -0
- package/dist/esm/abstract/BaseClient.js +294 -0
- package/dist/esm/abstract/BaseCompressionManager.js +373 -0
- package/dist/esm/abstract/BaseConnectionPool.js +539 -0
- package/dist/esm/abstract/BaseInterceptor.js +231 -0
- package/dist/esm/abstract/BaseLoadBalancer.js +265 -0
- package/dist/esm/abstract/BaseProtocol.js +265 -0
- package/dist/esm/abstract/BaseRetryStrategy.js +251 -0
- package/dist/esm/abstract/BaseSerializer.js +337 -0
- package/dist/esm/abstract/BaseServiceDiscoverer.js +250 -0
- package/dist/esm/abstract/BaseTimeoutManager.js +291 -0
- package/dist/esm/abstract/index.js +11 -0
- package/dist/esm/errors/CircuitBreakerError.js +12 -0
- package/dist/esm/errors/CommunicationError.js +11 -0
- package/dist/esm/errors/ConnectionError.js +11 -0
- package/dist/esm/errors/DiscoveryError.js +11 -0
- package/dist/esm/errors/LoadBalancerError.js +11 -0
- package/dist/esm/errors/ProtocolError.js +11 -0
- package/dist/esm/errors/RetryError.js +12 -0
- package/dist/esm/errors/SerializationError.js +11 -0
- package/dist/esm/errors/ServiceUnavailableError.js +11 -0
- package/dist/esm/errors/TimeoutError.js +12 -0
- package/dist/esm/errors/communicationErrorCodes.js +32 -0
- package/dist/esm/errors/index.js +17 -0
- package/dist/esm/index.js +18 -0
- package/dist/esm/interfaces/CircuitBreaker.interface.js +5 -0
- package/dist/esm/interfaces/Client.interface.js +5 -0
- package/dist/esm/interfaces/Compression.interface.js +5 -0
- package/dist/esm/interfaces/ConnectionPool.interface.js +5 -0
- package/dist/esm/interfaces/Interceptor.interface.js +5 -0
- package/dist/esm/interfaces/LoadBalancer.interface.js +1 -0
- package/dist/esm/interfaces/Protocol.interface.js +5 -0
- package/dist/esm/interfaces/RetryStrategy.interface.js +5 -0
- package/dist/esm/interfaces/Serializer.interface.js +1 -0
- package/dist/esm/interfaces/ServiceDiscovery.interface.js +5 -0
- package/dist/esm/interfaces/Timeout.interface.js +5 -0
- package/dist/esm/interfaces/index.js +5 -0
- package/dist/esm/types/config.js +5 -0
- package/dist/esm/types/events.js +5 -0
- package/dist/esm/types/index.js +5 -0
- package/dist/esm/types/request.js +5 -0
- package/dist/esm/types/response.js +5 -0
- package/dist/esm/types/service.js +5 -0
- package/dist/esm/utils.js +193 -0
- package/dist/types/abstract/BaseCircuitBreaker.d.ts +167 -0
- package/dist/types/abstract/BaseClient.d.ts +197 -0
- package/dist/types/abstract/BaseCompressionManager.d.ts +180 -0
- package/dist/types/abstract/BaseConnectionPool.d.ts +210 -0
- package/dist/types/abstract/BaseInterceptor.d.ts +150 -0
- package/dist/types/abstract/BaseLoadBalancer.d.ts +167 -0
- package/dist/types/abstract/BaseProtocol.d.ts +163 -0
- package/dist/types/abstract/BaseRetryStrategy.d.ts +130 -0
- package/dist/types/abstract/BaseSerializer.d.ts +181 -0
- package/dist/types/abstract/BaseServiceDiscoverer.d.ts +161 -0
- package/dist/types/abstract/BaseTimeoutManager.d.ts +145 -0
- package/dist/types/abstract/index.d.ts +11 -0
- package/dist/types/errors/CircuitBreakerError.d.ts +8 -0
- package/dist/types/errors/CommunicationError.d.ts +10 -0
- package/dist/types/errors/ConnectionError.d.ts +9 -0
- package/dist/types/errors/DiscoveryError.d.ts +9 -0
- package/dist/types/errors/LoadBalancerError.d.ts +9 -0
- package/dist/types/errors/ProtocolError.d.ts +9 -0
- package/dist/types/errors/RetryError.d.ts +11 -0
- package/dist/types/errors/SerializationError.d.ts +9 -0
- package/dist/types/errors/ServiceUnavailableError.d.ts +12 -0
- package/dist/types/errors/TimeoutError.d.ts +11 -0
- package/dist/types/errors/communicationErrorCodes.d.ts +27 -0
- package/dist/types/errors/index.d.ts +11 -0
- package/dist/types/index.d.ts +13 -0
- package/dist/types/interfaces/CircuitBreaker.interface.d.ts +150 -0
- package/dist/types/interfaces/Client.interface.d.ts +153 -0
- package/dist/types/interfaces/Compression.interface.d.ts +190 -0
- package/dist/types/interfaces/ConnectionPool.interface.d.ts +191 -0
- package/dist/types/interfaces/Interceptor.interface.d.ts +220 -0
- package/dist/types/interfaces/LoadBalancer.interface.d.ts +153 -0
- package/dist/types/interfaces/Protocol.interface.d.ts +117 -0
- package/dist/types/interfaces/RetryStrategy.interface.d.ts +160 -0
- package/dist/types/interfaces/Serializer.interface.d.ts +176 -0
- package/dist/types/interfaces/ServiceDiscovery.interface.d.ts +189 -0
- package/dist/types/interfaces/Timeout.interface.d.ts +135 -0
- package/dist/types/interfaces/index.d.ts +15 -0
- package/dist/types/types/config.d.ts +540 -0
- package/dist/types/types/events.d.ts +204 -0
- package/dist/types/types/index.d.ts +9 -0
- package/dist/types/types/request.d.ts +143 -0
- package/dist/types/types/response.d.ts +155 -0
- package/dist/types/types/service.d.ts +279 -0
- package/dist/types/utils.d.ts +179 -0
- package/package.json +88 -0
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Abstract base interceptor implementation
|
|
4
|
+
* @packageDocumentation
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.BaseInterceptor = void 0;
|
|
8
|
+
/**
|
|
9
|
+
* Abstract base interceptor implementation
|
|
10
|
+
* Provides common functionality for all interceptor implementations
|
|
11
|
+
*/
|
|
12
|
+
class BaseInterceptor {
|
|
13
|
+
/**
|
|
14
|
+
* Create a new base interceptor instance
|
|
15
|
+
* @param name Interceptor name
|
|
16
|
+
* @param options Interceptor options
|
|
17
|
+
*/
|
|
18
|
+
constructor(name, options) {
|
|
19
|
+
/** Whether interceptor is enabled */
|
|
20
|
+
this.enabled = true;
|
|
21
|
+
/** Interceptor statistics */
|
|
22
|
+
this.stats = {
|
|
23
|
+
totalRequests: 0,
|
|
24
|
+
totalResponses: 0,
|
|
25
|
+
totalErrors: 0,
|
|
26
|
+
modifications: 0,
|
|
27
|
+
totalProcessingTime: 0,
|
|
28
|
+
averageProcessingTime: 0,
|
|
29
|
+
};
|
|
30
|
+
/** Configuration */
|
|
31
|
+
this.config = {};
|
|
32
|
+
this.name = name;
|
|
33
|
+
this.version = options?.version || '1.0.0';
|
|
34
|
+
this.description = options?.description;
|
|
35
|
+
this.enabled = options?.enabled ?? true;
|
|
36
|
+
// Set default order if not provided
|
|
37
|
+
this.order = options?.order || {
|
|
38
|
+
request: 0,
|
|
39
|
+
response: 0,
|
|
40
|
+
error: 0
|
|
41
|
+
};
|
|
42
|
+
this.config = { ...options };
|
|
43
|
+
// Call setup instead of initialize to avoid confusion with interface method
|
|
44
|
+
this.setup(options);
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Setup interceptor (internal initialization)
|
|
48
|
+
* @param options Initialization options
|
|
49
|
+
*/
|
|
50
|
+
setup(options) {
|
|
51
|
+
// Can be overridden by subclasses
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Initialize interceptor (called when added to client/protocol)
|
|
55
|
+
* @param options Initialization options
|
|
56
|
+
*/
|
|
57
|
+
initialize(options) {
|
|
58
|
+
// Can be overridden by subclasses
|
|
59
|
+
this.config = { ...this.config, ...options };
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Cleanup interceptor (called when removed from client/protocol)
|
|
63
|
+
*/
|
|
64
|
+
cleanup() {
|
|
65
|
+
// Can be overridden by subclasses
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Get interceptor configuration
|
|
69
|
+
*/
|
|
70
|
+
getConfig() {
|
|
71
|
+
return { ...this.config };
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Update interceptor configuration
|
|
75
|
+
* @param config New configuration
|
|
76
|
+
*/
|
|
77
|
+
updateConfig(config) {
|
|
78
|
+
this.config = { ...this.config, ...config };
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Health check for the interceptor
|
|
82
|
+
*/
|
|
83
|
+
healthCheck() {
|
|
84
|
+
const healthy = this.enabled && !this.stats.lastError;
|
|
85
|
+
return {
|
|
86
|
+
healthy,
|
|
87
|
+
message: healthy ? 'Interceptor is operational' : 'Interceptor has errors',
|
|
88
|
+
details: {
|
|
89
|
+
name: this.name,
|
|
90
|
+
enabled: this.enabled,
|
|
91
|
+
lastError: this.stats.lastError,
|
|
92
|
+
statistics: this.getStats(),
|
|
93
|
+
},
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Get interceptor statistics
|
|
98
|
+
*/
|
|
99
|
+
getStats() {
|
|
100
|
+
return { ...this.stats };
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Reset interceptor statistics
|
|
104
|
+
*/
|
|
105
|
+
resetStats() {
|
|
106
|
+
this.stats = {
|
|
107
|
+
totalRequests: 0,
|
|
108
|
+
totalResponses: 0,
|
|
109
|
+
totalErrors: 0,
|
|
110
|
+
modifications: 0,
|
|
111
|
+
totalProcessingTime: 0,
|
|
112
|
+
averageProcessingTime: 0,
|
|
113
|
+
};
|
|
114
|
+
this.lastProcessingTime = undefined;
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Execute request interception with timing and error handling
|
|
118
|
+
* @param request Original request
|
|
119
|
+
* @param context Request context
|
|
120
|
+
* @returns Modified request or original if not modified
|
|
121
|
+
*/
|
|
122
|
+
async executeOnRequest(request, context) {
|
|
123
|
+
if (!this.enabled || !this.onRequest) {
|
|
124
|
+
return request;
|
|
125
|
+
}
|
|
126
|
+
const startTime = Date.now();
|
|
127
|
+
try {
|
|
128
|
+
const result = await this.onRequest(request, context);
|
|
129
|
+
const processingTime = Date.now() - startTime;
|
|
130
|
+
this.updateRequestStats(processingTime, result !== undefined);
|
|
131
|
+
this.lastProcessingTime = processingTime;
|
|
132
|
+
return result !== undefined ? result : request;
|
|
133
|
+
}
|
|
134
|
+
catch (error) {
|
|
135
|
+
this.stats.lastError = error instanceof Error ? error.message : String(error);
|
|
136
|
+
this.stats.totalErrors++;
|
|
137
|
+
throw error;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Execute response interception with timing and error handling
|
|
142
|
+
* @param response Original response
|
|
143
|
+
* @param context Request context
|
|
144
|
+
* @returns Modified response or original if not modified
|
|
145
|
+
*/
|
|
146
|
+
async executeOnResponse(response, context) {
|
|
147
|
+
if (!this.enabled || !this.onResponse) {
|
|
148
|
+
return response;
|
|
149
|
+
}
|
|
150
|
+
const startTime = Date.now();
|
|
151
|
+
try {
|
|
152
|
+
const result = await this.onResponse(response, context);
|
|
153
|
+
const processingTime = Date.now() - startTime;
|
|
154
|
+
this.updateResponseStats(processingTime, result !== undefined);
|
|
155
|
+
this.lastProcessingTime = processingTime;
|
|
156
|
+
return result !== undefined ? result : response;
|
|
157
|
+
}
|
|
158
|
+
catch (error) {
|
|
159
|
+
this.stats.lastError = error instanceof Error ? error.message : String(error);
|
|
160
|
+
this.stats.totalErrors++;
|
|
161
|
+
throw error;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Execute error interception with timing and error handling
|
|
166
|
+
* @param error Original error
|
|
167
|
+
* @param context Request context
|
|
168
|
+
* @returns Modified error or response, or original error if not modified
|
|
169
|
+
*/
|
|
170
|
+
async executeOnError(error, context) {
|
|
171
|
+
if (!this.enabled || !this.onError) {
|
|
172
|
+
return error;
|
|
173
|
+
}
|
|
174
|
+
const startTime = Date.now();
|
|
175
|
+
try {
|
|
176
|
+
const result = await this.onError(error, context);
|
|
177
|
+
const processingTime = Date.now() - startTime;
|
|
178
|
+
this.updateErrorStats(processingTime, result !== undefined);
|
|
179
|
+
this.lastProcessingTime = processingTime;
|
|
180
|
+
if (result === undefined) {
|
|
181
|
+
return error;
|
|
182
|
+
}
|
|
183
|
+
return result;
|
|
184
|
+
}
|
|
185
|
+
catch (interceptorError) {
|
|
186
|
+
this.stats.lastError = interceptorError instanceof Error ? interceptorError.message : String(interceptorError);
|
|
187
|
+
this.stats.totalErrors++;
|
|
188
|
+
// If interceptor itself fails, return the original error
|
|
189
|
+
return error;
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* Update request statistics
|
|
194
|
+
* @param processingTime Processing time in milliseconds
|
|
195
|
+
* @param modified Whether request was modified
|
|
196
|
+
*/
|
|
197
|
+
updateRequestStats(processingTime, modified) {
|
|
198
|
+
this.stats.totalRequests++;
|
|
199
|
+
this.stats.totalProcessingTime += processingTime;
|
|
200
|
+
this.stats.averageProcessingTime = this.stats.totalProcessingTime /
|
|
201
|
+
(this.stats.totalRequests + this.stats.totalResponses + this.stats.totalErrors);
|
|
202
|
+
if (modified) {
|
|
203
|
+
this.stats.modifications++;
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* Update response statistics
|
|
208
|
+
* @param processingTime Processing time in milliseconds
|
|
209
|
+
* @param modified Whether response was modified
|
|
210
|
+
*/
|
|
211
|
+
updateResponseStats(processingTime, modified) {
|
|
212
|
+
this.stats.totalResponses++;
|
|
213
|
+
this.stats.totalProcessingTime += processingTime;
|
|
214
|
+
this.stats.averageProcessingTime = this.stats.totalProcessingTime /
|
|
215
|
+
(this.stats.totalRequests + this.stats.totalResponses + this.stats.totalErrors);
|
|
216
|
+
if (modified) {
|
|
217
|
+
this.stats.modifications++;
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
/**
|
|
221
|
+
* Update error statistics
|
|
222
|
+
* @param processingTime Processing time in milliseconds
|
|
223
|
+
* @param modified Whether error was modified
|
|
224
|
+
*/
|
|
225
|
+
updateErrorStats(processingTime, modified) {
|
|
226
|
+
this.stats.totalErrors++;
|
|
227
|
+
this.stats.totalProcessingTime += processingTime;
|
|
228
|
+
this.stats.averageProcessingTime = this.stats.totalProcessingTime /
|
|
229
|
+
(this.stats.totalRequests + this.stats.totalResponses + this.stats.totalErrors);
|
|
230
|
+
if (modified) {
|
|
231
|
+
this.stats.modifications++;
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
exports.BaseInterceptor = BaseInterceptor;
|
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Abstract base load balancer implementation
|
|
4
|
+
* @packageDocumentation
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.BaseLoadBalancer = void 0;
|
|
8
|
+
/**
|
|
9
|
+
* Abstract base load balancer implementation
|
|
10
|
+
* Provides common functionality for all load balancing strategy implementations
|
|
11
|
+
*/
|
|
12
|
+
class BaseLoadBalancer {
|
|
13
|
+
/**
|
|
14
|
+
* Create a new base load balancer instance
|
|
15
|
+
* @param name Load balancer name
|
|
16
|
+
* @param config Load balancer configuration
|
|
17
|
+
*/
|
|
18
|
+
constructor(name, config) {
|
|
19
|
+
/** Total selections made */
|
|
20
|
+
this.totalSelections = 0;
|
|
21
|
+
/** Instance statistics */
|
|
22
|
+
this.instanceStats = new Map();
|
|
23
|
+
/** Load balancer statistics */
|
|
24
|
+
this.stats = {
|
|
25
|
+
totalSelections: 0,
|
|
26
|
+
successfulSelections: 0,
|
|
27
|
+
failedSelections: 0,
|
|
28
|
+
averageSelectionTime: 0,
|
|
29
|
+
instanceStats: {},
|
|
30
|
+
};
|
|
31
|
+
this.name = name;
|
|
32
|
+
this.config = { ...config };
|
|
33
|
+
this.initialize();
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Initialize load balancer
|
|
37
|
+
*/
|
|
38
|
+
initialize() {
|
|
39
|
+
// Can be overridden by subclasses
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Select multiple service instances
|
|
43
|
+
* @param instances Available service instances
|
|
44
|
+
* @param count Number of instances to select
|
|
45
|
+
* @param context Selection context
|
|
46
|
+
* @returns Selected service instances
|
|
47
|
+
*/
|
|
48
|
+
selectMultiple(instances, count, context) {
|
|
49
|
+
const selected = [];
|
|
50
|
+
const available = [...instances];
|
|
51
|
+
for (let i = 0; i < count && available.length > 0; i++) {
|
|
52
|
+
const instance = this.select(available, context);
|
|
53
|
+
selected.push(instance);
|
|
54
|
+
// Remove selected instance from available pool
|
|
55
|
+
const index = available.findIndex(inst => inst.id === instance.id);
|
|
56
|
+
if (index !== -1) {
|
|
57
|
+
available.splice(index, 1);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
return selected;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Update instance statistics (for adaptive strategies)
|
|
64
|
+
* @param instance Service instance
|
|
65
|
+
* @param success Whether the request was successful
|
|
66
|
+
* @param responseTime Response time in milliseconds
|
|
67
|
+
*/
|
|
68
|
+
updateStats(instance, success, responseTime) {
|
|
69
|
+
const instanceId = instance.id;
|
|
70
|
+
const now = Date.now();
|
|
71
|
+
let stats = this.instanceStats.get(instanceId);
|
|
72
|
+
if (!stats) {
|
|
73
|
+
stats = {
|
|
74
|
+
selections: 0,
|
|
75
|
+
successes: 0,
|
|
76
|
+
failures: 0,
|
|
77
|
+
totalResponseTime: 0,
|
|
78
|
+
averageResponseTime: undefined,
|
|
79
|
+
lastSelected: undefined,
|
|
80
|
+
};
|
|
81
|
+
this.instanceStats.set(instanceId, stats);
|
|
82
|
+
}
|
|
83
|
+
stats.selections++;
|
|
84
|
+
stats.lastSelected = now;
|
|
85
|
+
if (success) {
|
|
86
|
+
stats.successes++;
|
|
87
|
+
if (responseTime !== undefined) {
|
|
88
|
+
stats.totalResponseTime += responseTime;
|
|
89
|
+
stats.averageResponseTime = stats.totalResponseTime / stats.selections;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
else {
|
|
93
|
+
stats.failures++;
|
|
94
|
+
}
|
|
95
|
+
// Update aggregate stats
|
|
96
|
+
this.updateAggregateStats(instanceId, stats);
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Update aggregate statistics
|
|
100
|
+
* @param instanceId Instance ID
|
|
101
|
+
* @param instanceStats Instance statistics
|
|
102
|
+
*/
|
|
103
|
+
updateAggregateStats(instanceId, instanceStats) {
|
|
104
|
+
this.stats.instanceStats[instanceId] = {
|
|
105
|
+
selections: instanceStats.selections,
|
|
106
|
+
successes: instanceStats.successes,
|
|
107
|
+
failures: instanceStats.failures,
|
|
108
|
+
averageResponseTime: instanceStats.averageResponseTime,
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Reset instance statistics
|
|
113
|
+
* @param instanceId Optional instance ID to reset, or reset all
|
|
114
|
+
*/
|
|
115
|
+
resetStats(instanceId) {
|
|
116
|
+
if (instanceId) {
|
|
117
|
+
this.instanceStats.delete(instanceId);
|
|
118
|
+
delete this.stats.instanceStats[instanceId];
|
|
119
|
+
}
|
|
120
|
+
else {
|
|
121
|
+
this.instanceStats.clear();
|
|
122
|
+
this.stats.instanceStats = {};
|
|
123
|
+
this.totalSelections = 0;
|
|
124
|
+
this.lastSelectionTime = undefined;
|
|
125
|
+
this.stats.totalSelections = 0;
|
|
126
|
+
this.stats.successfulSelections = 0;
|
|
127
|
+
this.stats.failedSelections = 0;
|
|
128
|
+
this.stats.averageSelectionTime = 0;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Get instance statistics
|
|
133
|
+
* @param instanceId Optional instance ID to get stats for
|
|
134
|
+
*/
|
|
135
|
+
getStats(instanceId) {
|
|
136
|
+
if (instanceId) {
|
|
137
|
+
const stats = this.instanceStats.get(instanceId);
|
|
138
|
+
return stats ? { ...stats, instanceId } : {};
|
|
139
|
+
}
|
|
140
|
+
return {
|
|
141
|
+
...this.stats,
|
|
142
|
+
totalSelections: this.totalSelections,
|
|
143
|
+
lastSelectionTime: this.lastSelectionTime,
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Check if an instance is currently eligible for selection
|
|
148
|
+
* @param instance Service instance to check
|
|
149
|
+
*/
|
|
150
|
+
isEligible(instance) {
|
|
151
|
+
// Default eligibility: instance must be healthy
|
|
152
|
+
if (instance.status !== 'healthy') {
|
|
153
|
+
return false;
|
|
154
|
+
}
|
|
155
|
+
// Check if instance is within weight limits (if weighted strategy)
|
|
156
|
+
if (this.config.weights) {
|
|
157
|
+
const weight = this.config.weights[instance.id];
|
|
158
|
+
if (weight !== undefined && weight <= 0) {
|
|
159
|
+
return false;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
return true;
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Filter instances based on eligibility
|
|
166
|
+
* @param instances Instances to filter
|
|
167
|
+
*/
|
|
168
|
+
filterEligible(instances) {
|
|
169
|
+
return instances.filter(instance => this.isEligible(instance));
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Sort instances by selection priority
|
|
173
|
+
* @param instances Instances to sort
|
|
174
|
+
*/
|
|
175
|
+
sortByPriority(instances) {
|
|
176
|
+
// Default: no sorting, return as-is
|
|
177
|
+
return [...instances];
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* Get instance weight
|
|
181
|
+
* @param instance Service instance
|
|
182
|
+
* @returns Instance weight
|
|
183
|
+
*/
|
|
184
|
+
getInstanceWeight(instance) {
|
|
185
|
+
if (this.config.weights && this.config.weights[instance.id]) {
|
|
186
|
+
return this.config.weights[instance.id];
|
|
187
|
+
}
|
|
188
|
+
if (instance.weight !== undefined) {
|
|
189
|
+
return instance.weight;
|
|
190
|
+
}
|
|
191
|
+
return 1; // Default weight
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* Record selection
|
|
195
|
+
* @param instance Selected instance
|
|
196
|
+
* @param selectionTime Selection time in milliseconds
|
|
197
|
+
*/
|
|
198
|
+
recordSelection(instance, selectionTime) {
|
|
199
|
+
this.totalSelections++;
|
|
200
|
+
this.lastSelectionTime = Date.now();
|
|
201
|
+
this.stats.totalSelections++;
|
|
202
|
+
// Update average selection time
|
|
203
|
+
this.stats.averageSelectionTime = ((this.stats.averageSelectionTime * (this.stats.totalSelections - 1) + selectionTime) /
|
|
204
|
+
this.stats.totalSelections);
|
|
205
|
+
// Update instance stats
|
|
206
|
+
this.updateStats(instance, true);
|
|
207
|
+
}
|
|
208
|
+
/**
|
|
209
|
+
* Create selection result
|
|
210
|
+
* @param instance Selected instance
|
|
211
|
+
* @param instances Available instances
|
|
212
|
+
* @param selectionTime Selection time in milliseconds
|
|
213
|
+
* @returns Selection result
|
|
214
|
+
*/
|
|
215
|
+
createSelectionResult(instance, instances, selectionTime) {
|
|
216
|
+
return {
|
|
217
|
+
selectedInstance: instance,
|
|
218
|
+
availableInstances: instances,
|
|
219
|
+
timestamp: Date.now(),
|
|
220
|
+
selectionDuration: selectionTime,
|
|
221
|
+
metadata: {
|
|
222
|
+
strategy: this.name,
|
|
223
|
+
totalSelections: this.totalSelections,
|
|
224
|
+
},
|
|
225
|
+
};
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* Update load balancer configuration
|
|
229
|
+
* @param config New configuration
|
|
230
|
+
*/
|
|
231
|
+
updateConfig(config) {
|
|
232
|
+
this.config = { ...this.config, ...config };
|
|
233
|
+
}
|
|
234
|
+
/**
|
|
235
|
+
* Get load balancer statistics
|
|
236
|
+
*/
|
|
237
|
+
getStrategyStats() {
|
|
238
|
+
return { ...this.stats };
|
|
239
|
+
}
|
|
240
|
+
/**
|
|
241
|
+
* Reset load balancer statistics
|
|
242
|
+
*/
|
|
243
|
+
resetStrategyStats() {
|
|
244
|
+
this.stats = {
|
|
245
|
+
totalSelections: 0,
|
|
246
|
+
successfulSelections: 0,
|
|
247
|
+
failedSelections: 0,
|
|
248
|
+
averageSelectionTime: 0,
|
|
249
|
+
instanceStats: {},
|
|
250
|
+
};
|
|
251
|
+
}
|
|
252
|
+
/**
|
|
253
|
+
* Health check for the load balancer
|
|
254
|
+
*/
|
|
255
|
+
healthCheck() {
|
|
256
|
+
const healthy = true; // Load balancer is always healthy
|
|
257
|
+
return {
|
|
258
|
+
healthy,
|
|
259
|
+
message: 'Load balancer is operational',
|
|
260
|
+
details: {
|
|
261
|
+
name: this.name,
|
|
262
|
+
totalSelections: this.totalSelections,
|
|
263
|
+
instanceCount: this.instanceStats.size,
|
|
264
|
+
config: this.config,
|
|
265
|
+
},
|
|
266
|
+
};
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
exports.BaseLoadBalancer = BaseLoadBalancer;
|