@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,193 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Utilities integration with @naman_deep_singh/utils package
|
|
3
|
+
* @packageDocumentation
|
|
4
|
+
*/
|
|
5
|
+
import { Compression, GenericPool, TimeoutManager } from '@naman_deep_singh/utils';
|
|
6
|
+
/**
|
|
7
|
+
* Base connection implementation that satisfies both interfaces
|
|
8
|
+
*/
|
|
9
|
+
export class BaseConnection {
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Timeout utilities wrapper
|
|
13
|
+
*/
|
|
14
|
+
export class TimeoutUtils {
|
|
15
|
+
/**
|
|
16
|
+
* Execute with timeout
|
|
17
|
+
*/
|
|
18
|
+
static async withTimeout(promise, timeoutMs, errorMessage) {
|
|
19
|
+
return TimeoutManager.withTimeout(promise, timeoutMs, errorMessage);
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Create delay
|
|
23
|
+
*/
|
|
24
|
+
static async delay(ms) {
|
|
25
|
+
return TimeoutManager.delay(ms);
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Retry with timeout
|
|
29
|
+
*/
|
|
30
|
+
static async retryWithTimeout(fn, options) {
|
|
31
|
+
return TimeoutManager.retryWithTimeout(fn, options);
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Create a timeout promise
|
|
35
|
+
*/
|
|
36
|
+
static createTimeout(timeoutMs, message) {
|
|
37
|
+
return new Promise((_, reject) => {
|
|
38
|
+
setTimeout(() => {
|
|
39
|
+
reject(new Error(message || `Timeout after ${timeoutMs}ms`));
|
|
40
|
+
}, timeoutMs);
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Create an abort signal for timeout
|
|
45
|
+
*/
|
|
46
|
+
static createAbortSignal(timeoutMs) {
|
|
47
|
+
const controller = new AbortController();
|
|
48
|
+
setTimeout(() => controller.abort(), timeoutMs);
|
|
49
|
+
return controller.signal;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Race promises with timeout
|
|
53
|
+
*/
|
|
54
|
+
static async raceWithTimeout(promises, timeoutMs, errorMessage) {
|
|
55
|
+
const timeoutPromise = this.createTimeout(timeoutMs, errorMessage);
|
|
56
|
+
return Promise.race([...promises, timeoutPromise]);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Connection pool wrapper
|
|
61
|
+
*/
|
|
62
|
+
export class ConnectionPoolUtils {
|
|
63
|
+
/**
|
|
64
|
+
* Create a generic connection pool
|
|
65
|
+
*/
|
|
66
|
+
static createPool(config) {
|
|
67
|
+
return new GenericPool({
|
|
68
|
+
name: config.name,
|
|
69
|
+
minConnections: config.minConnections,
|
|
70
|
+
maxConnections: config.maxConnections,
|
|
71
|
+
createConnection: config.createConnection,
|
|
72
|
+
validateConnection: config.validateConnection,
|
|
73
|
+
idleTimeoutMs: config.idleTimeout,
|
|
74
|
+
maxLifetimeMs: config.maxLifetime,
|
|
75
|
+
acquireTimeoutMs: config.acquireTimeout,
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Create a simple pool with basic configuration
|
|
80
|
+
*/
|
|
81
|
+
static createSimplePool(name, createConnection, options) {
|
|
82
|
+
return new GenericPool({
|
|
83
|
+
name,
|
|
84
|
+
minConnections: options?.minConnections,
|
|
85
|
+
maxConnections: options?.maxConnections,
|
|
86
|
+
createConnection,
|
|
87
|
+
idleTimeoutMs: options?.idleTimeout,
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Create an adapter to convert property-based isHealthy to function-based
|
|
92
|
+
*/
|
|
93
|
+
static createConnectionAdapter(connection, closeFn = async () => { }, healthCheckFn = async () => true, resetFn = async () => { }) {
|
|
94
|
+
// Handle isHealthy conversion
|
|
95
|
+
const getIsHealthy = () => {
|
|
96
|
+
if (typeof connection.isHealthy === 'function') {
|
|
97
|
+
return connection.isHealthy();
|
|
98
|
+
}
|
|
99
|
+
return connection.isHealthy ?? true;
|
|
100
|
+
};
|
|
101
|
+
return {
|
|
102
|
+
id: connection.id || `conn-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,
|
|
103
|
+
// isHealthy must be a function
|
|
104
|
+
isHealthy: getIsHealthy,
|
|
105
|
+
createdAt: connection.createdAt || Date.now(),
|
|
106
|
+
lastUsedAt: connection.lastUsedAt || Date.now(),
|
|
107
|
+
usageCount: connection.usageCount || 0,
|
|
108
|
+
metadata: connection.metadata || {},
|
|
109
|
+
close: closeFn,
|
|
110
|
+
healthCheck: healthCheckFn,
|
|
111
|
+
reset: resetFn,
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Compression utilities wrapper
|
|
117
|
+
*/
|
|
118
|
+
export class CompressionUtils {
|
|
119
|
+
/**
|
|
120
|
+
* Compress data
|
|
121
|
+
*/
|
|
122
|
+
static async compress(data, options) {
|
|
123
|
+
const result = await Compression.compress(Buffer.from(data), {
|
|
124
|
+
algorithm: options?.algorithm || 'gzip',
|
|
125
|
+
level: options?.level || 6,
|
|
126
|
+
});
|
|
127
|
+
return Buffer.from(result);
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Decompress data
|
|
131
|
+
*/
|
|
132
|
+
static async decompress(data, options) {
|
|
133
|
+
const result = await Compression.decompress(Buffer.from(data), {
|
|
134
|
+
algorithm: options?.algorithm || 'gzip',
|
|
135
|
+
});
|
|
136
|
+
return Buffer.from(result);
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Compress data with metrics
|
|
140
|
+
*/
|
|
141
|
+
static async compressWithMetrics(data, options) {
|
|
142
|
+
const startTime = Date.now();
|
|
143
|
+
const originalSize = Buffer.from(data).length;
|
|
144
|
+
const compressed = await Compression.compress(Buffer.from(data), {
|
|
145
|
+
algorithm: options?.algorithm || 'gzip',
|
|
146
|
+
level: options?.level || 6,
|
|
147
|
+
});
|
|
148
|
+
const compressionTime = Date.now() - startTime;
|
|
149
|
+
const compressedSize = compressed.length;
|
|
150
|
+
const compressionRatio = compressedSize / originalSize;
|
|
151
|
+
return {
|
|
152
|
+
data: Buffer.from(compressed),
|
|
153
|
+
originalSize,
|
|
154
|
+
compressedSize,
|
|
155
|
+
compressionRatio,
|
|
156
|
+
compressionTime,
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Get optimal compression level based on data size
|
|
161
|
+
*/
|
|
162
|
+
static getOptimalLevel(dataSize) {
|
|
163
|
+
if (dataSize < 1024)
|
|
164
|
+
return 1; // Small data, fast compression
|
|
165
|
+
if (dataSize < 10240)
|
|
166
|
+
return 6; // Medium data, balanced
|
|
167
|
+
return 9; // Large data, best compression
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Estimate compression ratio for data type
|
|
171
|
+
*/
|
|
172
|
+
static estimateCompressionRatio(contentType) {
|
|
173
|
+
if (!contentType)
|
|
174
|
+
return 0.7;
|
|
175
|
+
const type = contentType.toLowerCase();
|
|
176
|
+
if (type.includes('json') || type.includes('xml'))
|
|
177
|
+
return 0.3;
|
|
178
|
+
if (type.includes('text'))
|
|
179
|
+
return 0.4;
|
|
180
|
+
if (type.includes('image') || type.includes('video'))
|
|
181
|
+
return 0.95;
|
|
182
|
+
return 0.7;
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* Compression algorithm type
|
|
187
|
+
*/
|
|
188
|
+
CompressionUtils.Algorithm = {
|
|
189
|
+
GZIP: 'gzip',
|
|
190
|
+
DEFLATE: 'deflate',
|
|
191
|
+
BROTLI: 'brotli',
|
|
192
|
+
NONE: 'none',
|
|
193
|
+
};
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Abstract base circuit breaker implementation
|
|
3
|
+
* @packageDocumentation
|
|
4
|
+
*/
|
|
5
|
+
import type { CommunicationErrorType } from '../errors/CommunicationError.js';
|
|
6
|
+
import type { ICircuitBreaker } from '../interfaces/CircuitBreaker.interface.js';
|
|
7
|
+
import type { CircuitBreakerConfig } from '../types/config.js';
|
|
8
|
+
/**
|
|
9
|
+
* Abstract base circuit breaker implementation
|
|
10
|
+
* Provides common functionality for all circuit breaker implementations
|
|
11
|
+
*/
|
|
12
|
+
export declare abstract class BaseCircuitBreaker implements ICircuitBreaker {
|
|
13
|
+
/** Circuit breaker name */
|
|
14
|
+
readonly name: string;
|
|
15
|
+
/** Current state */
|
|
16
|
+
state: 'closed' | 'open' | 'half-open';
|
|
17
|
+
/** Circuit breaker configuration */
|
|
18
|
+
config: CircuitBreakerConfig;
|
|
19
|
+
/** Failure count */
|
|
20
|
+
failureCount: number;
|
|
21
|
+
/** Success count */
|
|
22
|
+
successCount: number;
|
|
23
|
+
/** Last failure timestamp */
|
|
24
|
+
lastFailureTime?: number;
|
|
25
|
+
/** Last success timestamp */
|
|
26
|
+
lastSuccessTime?: number;
|
|
27
|
+
/** Time when circuit will attempt to reset */
|
|
28
|
+
nextResetTime?: number;
|
|
29
|
+
/** Circuit breaker statistics */
|
|
30
|
+
protected stats: {
|
|
31
|
+
totalExecutions: number;
|
|
32
|
+
totalSuccesses: number;
|
|
33
|
+
totalFailures: number;
|
|
34
|
+
successRate: number;
|
|
35
|
+
failureRate: number;
|
|
36
|
+
totalTimeOpen: number;
|
|
37
|
+
totalTimeClosed: number;
|
|
38
|
+
lastStateChange: number;
|
|
39
|
+
};
|
|
40
|
+
/** Time when current state was entered */
|
|
41
|
+
protected stateEnteredTime: number;
|
|
42
|
+
/**
|
|
43
|
+
* Create a new base circuit breaker instance
|
|
44
|
+
* @param name Circuit breaker name
|
|
45
|
+
* @param config Circuit breaker configuration
|
|
46
|
+
*/
|
|
47
|
+
constructor(name: string, config: CircuitBreakerConfig);
|
|
48
|
+
/**
|
|
49
|
+
* Initialize circuit breaker
|
|
50
|
+
*/
|
|
51
|
+
protected initialize(): void;
|
|
52
|
+
/**
|
|
53
|
+
* Execute a function with circuit breaker protection
|
|
54
|
+
* @param fn Function to execute
|
|
55
|
+
* @returns Promise resolving to function result
|
|
56
|
+
* @throws {CommunicationError} If circuit is open or function fails
|
|
57
|
+
*/
|
|
58
|
+
abstract execute<T>(fn: () => Promise<T>): Promise<T>;
|
|
59
|
+
/**
|
|
60
|
+
* Execute a function with circuit breaker protection and context
|
|
61
|
+
* @param fn Function to execute
|
|
62
|
+
* @param context Execution context
|
|
63
|
+
* @returns Promise resolving to function result
|
|
64
|
+
*/
|
|
65
|
+
abstract executeWithContext<T, C = unknown>(fn: (context: C) => Promise<T>, context: C): Promise<T>;
|
|
66
|
+
/**
|
|
67
|
+
* Check if circuit breaker should allow execution
|
|
68
|
+
* @returns True if execution is allowed
|
|
69
|
+
*/
|
|
70
|
+
protected shouldAllowExecution(): boolean;
|
|
71
|
+
/**
|
|
72
|
+
* Transition circuit breaker to closed state
|
|
73
|
+
*/
|
|
74
|
+
protected transitionToClosed(): void;
|
|
75
|
+
/**
|
|
76
|
+
* Transition circuit breaker to open state
|
|
77
|
+
* @param error Optional error that caused the transition
|
|
78
|
+
*/
|
|
79
|
+
protected transitionToOpen(error?: CommunicationErrorType): void;
|
|
80
|
+
/**
|
|
81
|
+
* Transition circuit breaker to half-open state
|
|
82
|
+
*/
|
|
83
|
+
protected transitionToHalfOpen(): void;
|
|
84
|
+
/**
|
|
85
|
+
* Update state timing statistics
|
|
86
|
+
* @param previousState Previous state
|
|
87
|
+
*/
|
|
88
|
+
protected updateStateTime(previousState: string): void;
|
|
89
|
+
/**
|
|
90
|
+
* Hook for state changes
|
|
91
|
+
* @param newState New state
|
|
92
|
+
* @param previousState Previous state
|
|
93
|
+
* @param error Optional error that caused state change
|
|
94
|
+
*/
|
|
95
|
+
protected onStateChange(newState: string, previousState: string, error?: CommunicationErrorType): void;
|
|
96
|
+
/**
|
|
97
|
+
* Check if failure threshold is reached
|
|
98
|
+
* @returns True if failure threshold reached
|
|
99
|
+
*/
|
|
100
|
+
protected isFailureThresholdReached(): boolean;
|
|
101
|
+
/**
|
|
102
|
+
* Check if success threshold is reached
|
|
103
|
+
* @returns True if success threshold reached
|
|
104
|
+
*/
|
|
105
|
+
protected isSuccessThresholdReached(): boolean;
|
|
106
|
+
/**
|
|
107
|
+
* Manually trip the circuit breaker to open state
|
|
108
|
+
* @param error Error that caused the trip
|
|
109
|
+
*/
|
|
110
|
+
trip(error?: CommunicationErrorType): void;
|
|
111
|
+
/**
|
|
112
|
+
* Manually reset the circuit breaker to closed state
|
|
113
|
+
*/
|
|
114
|
+
reset(): void;
|
|
115
|
+
/**
|
|
116
|
+
* Check if circuit breaker is currently open
|
|
117
|
+
*/
|
|
118
|
+
isOpen(): boolean;
|
|
119
|
+
/**
|
|
120
|
+
* Check if circuit breaker is currently closed
|
|
121
|
+
*/
|
|
122
|
+
isClosed(): boolean;
|
|
123
|
+
/**
|
|
124
|
+
* Check if circuit breaker is in half-open state
|
|
125
|
+
*/
|
|
126
|
+
isHalfOpen(): boolean;
|
|
127
|
+
/**
|
|
128
|
+
* Record a successful execution
|
|
129
|
+
*/
|
|
130
|
+
recordSuccess(): void;
|
|
131
|
+
/**
|
|
132
|
+
* Record a failed execution
|
|
133
|
+
* @param error Error that occurred
|
|
134
|
+
*/
|
|
135
|
+
recordFailure(error: CommunicationErrorType): void;
|
|
136
|
+
/**
|
|
137
|
+
* Get circuit breaker statistics
|
|
138
|
+
*/
|
|
139
|
+
getStats(): {
|
|
140
|
+
totalExecutions: number;
|
|
141
|
+
totalSuccesses: number;
|
|
142
|
+
totalFailures: number;
|
|
143
|
+
successRate: number;
|
|
144
|
+
failureRate: number;
|
|
145
|
+
totalTimeOpen: number;
|
|
146
|
+
totalTimeClosed: number;
|
|
147
|
+
lastStateChange: number;
|
|
148
|
+
};
|
|
149
|
+
/**
|
|
150
|
+
* Reset circuit breaker statistics
|
|
151
|
+
*/
|
|
152
|
+
resetStats(): void;
|
|
153
|
+
/**
|
|
154
|
+
* Update circuit breaker configuration
|
|
155
|
+
* @param config New configuration
|
|
156
|
+
*/
|
|
157
|
+
updateConfig(config: Partial<CircuitBreakerConfig>): void;
|
|
158
|
+
/**
|
|
159
|
+
* Health check for the circuit breaker
|
|
160
|
+
*/
|
|
161
|
+
healthCheck(): {
|
|
162
|
+
healthy: boolean;
|
|
163
|
+
state: 'closed' | 'open' | 'half-open';
|
|
164
|
+
message?: string;
|
|
165
|
+
details?: Record<string, unknown>;
|
|
166
|
+
};
|
|
167
|
+
}
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Abstract base client implementation
|
|
3
|
+
* @packageDocumentation
|
|
4
|
+
*/
|
|
5
|
+
import type { ICircuitBreaker } from '../interfaces/CircuitBreaker.interface.js';
|
|
6
|
+
import type { IClient } from '../interfaces/Client.interface.js';
|
|
7
|
+
import type { IInterceptor } from '../interfaces/Interceptor.interface.js';
|
|
8
|
+
import type { ILoadBalanceStrategy } from '../interfaces/LoadBalancer.interface.js';
|
|
9
|
+
import type { IProtocol } from '../interfaces/Protocol.interface.js';
|
|
10
|
+
import type { IRetryStrategy } from '../interfaces/RetryStrategy.interface.js';
|
|
11
|
+
import type { IServiceDiscoverer } from '../interfaces/ServiceDiscovery.interface.js';
|
|
12
|
+
import type { ClientConfig } from '../types/config.js';
|
|
13
|
+
import type { Request, RequestOptions } from '../types/request.js';
|
|
14
|
+
import type { Response } from '../types/response.js';
|
|
15
|
+
import type { ServiceInstance } from '../types/service.js';
|
|
16
|
+
/**
|
|
17
|
+
* Abstract base client implementation
|
|
18
|
+
* Provides common functionality for all client implementations
|
|
19
|
+
*/
|
|
20
|
+
export declare abstract class BaseClient<TRequest = Request, TResponse = Response> implements IClient {
|
|
21
|
+
/** Client configuration */
|
|
22
|
+
readonly config: ClientConfig;
|
|
23
|
+
/** Client name/identifier */
|
|
24
|
+
readonly name: string;
|
|
25
|
+
/** Service name this client communicates with */
|
|
26
|
+
readonly serviceName: string;
|
|
27
|
+
/** Protocol being used */
|
|
28
|
+
readonly protocol: IProtocol;
|
|
29
|
+
/** Service discovery instance */
|
|
30
|
+
protected serviceDiscoverer?: IServiceDiscoverer;
|
|
31
|
+
/** Load balancer instance */
|
|
32
|
+
protected loadBalancer?: ILoadBalanceStrategy;
|
|
33
|
+
/** Circuit breaker instance */
|
|
34
|
+
protected circuitBreaker?: ICircuitBreaker;
|
|
35
|
+
/** Retry strategy instance */
|
|
36
|
+
protected retryStrategy?: IRetryStrategy;
|
|
37
|
+
/** Client interceptors */
|
|
38
|
+
protected interceptors: IInterceptor[];
|
|
39
|
+
/** Cached service instances */
|
|
40
|
+
protected cachedInstances: ServiceInstance[];
|
|
41
|
+
/** Last cache refresh time */
|
|
42
|
+
protected lastCacheRefresh?: number;
|
|
43
|
+
/** Client metrics */
|
|
44
|
+
protected metrics: Record<string, unknown>;
|
|
45
|
+
/** Client start time */
|
|
46
|
+
protected readonly startTime: number;
|
|
47
|
+
/** Total calls made */
|
|
48
|
+
protected totalCalls: number;
|
|
49
|
+
/** Successful calls */
|
|
50
|
+
protected successfulCalls: number;
|
|
51
|
+
/** Failed calls */
|
|
52
|
+
protected failedCalls: number;
|
|
53
|
+
/**
|
|
54
|
+
* Create a new base client instance
|
|
55
|
+
* @param serviceName Service name to communicate with
|
|
56
|
+
* @param config Client configuration
|
|
57
|
+
* @param protocol Protocol instance
|
|
58
|
+
*/
|
|
59
|
+
constructor(serviceName: string, config: ClientConfig, protocol: IProtocol);
|
|
60
|
+
/**
|
|
61
|
+
* Initialize client components
|
|
62
|
+
*/
|
|
63
|
+
protected initializeComponents(): void;
|
|
64
|
+
/**
|
|
65
|
+
* Make a request to a service endpoint
|
|
66
|
+
* @param endpoint Service endpoint/path
|
|
67
|
+
* @param data Request data
|
|
68
|
+
* @param options Request options
|
|
69
|
+
* @returns Promise resolving to the response
|
|
70
|
+
* @throws {CommunicationError} If the request fails
|
|
71
|
+
*/
|
|
72
|
+
abstract call<T = unknown>(endpoint: string, data?: unknown, options?: RequestOptions): Promise<Response<T>>;
|
|
73
|
+
/**
|
|
74
|
+
* Make a request with full control over request object
|
|
75
|
+
* @param request Complete request object
|
|
76
|
+
* @returns Promise resolving to the response
|
|
77
|
+
*/
|
|
78
|
+
abstract request<T = unknown>(request: Request): Promise<Response<T>>;
|
|
79
|
+
/**
|
|
80
|
+
* Build request from endpoint and data
|
|
81
|
+
* @param endpoint Service endpoint
|
|
82
|
+
* @param data Request data
|
|
83
|
+
* @param options Request options
|
|
84
|
+
* @returns Built request object
|
|
85
|
+
*/
|
|
86
|
+
protected abstract buildRequest(endpoint: string, data?: unknown, options?: RequestOptions): TRequest;
|
|
87
|
+
/**
|
|
88
|
+
* Parse response to standard format
|
|
89
|
+
* @param response Protocol response
|
|
90
|
+
* @returns Standardized response
|
|
91
|
+
*/
|
|
92
|
+
protected abstract parseResponse<T>(response: TResponse): Response<T>;
|
|
93
|
+
/**
|
|
94
|
+
* Get service discovery instance
|
|
95
|
+
*/
|
|
96
|
+
getServiceDiscoverer(): IServiceDiscoverer | undefined;
|
|
97
|
+
/**
|
|
98
|
+
* Get load balancer instance
|
|
99
|
+
*/
|
|
100
|
+
getLoadBalancer(): ILoadBalanceStrategy | undefined;
|
|
101
|
+
/**
|
|
102
|
+
* Get circuit breaker instance
|
|
103
|
+
*/
|
|
104
|
+
getCircuitBreaker(): ICircuitBreaker | undefined;
|
|
105
|
+
/**
|
|
106
|
+
* Get retry strategy instance
|
|
107
|
+
*/
|
|
108
|
+
getRetryStrategy(): IRetryStrategy | undefined;
|
|
109
|
+
/**
|
|
110
|
+
* Add an interceptor to the client
|
|
111
|
+
* @param interceptor IInterceptor to add
|
|
112
|
+
*/
|
|
113
|
+
addInterceptor(interceptor: IInterceptor): void;
|
|
114
|
+
/**
|
|
115
|
+
* Hook for interceptor addition
|
|
116
|
+
* @param interceptor Added interceptor
|
|
117
|
+
*/
|
|
118
|
+
protected onInterceptorAdded(interceptor: IInterceptor): void;
|
|
119
|
+
/**
|
|
120
|
+
* Remove an interceptor from the client
|
|
121
|
+
* @param interceptorId IInterceptor identifier
|
|
122
|
+
*/
|
|
123
|
+
removeInterceptor(interceptorId: string): void;
|
|
124
|
+
/**
|
|
125
|
+
* Hook for interceptor removal
|
|
126
|
+
* @param interceptorId Removed interceptor ID
|
|
127
|
+
*/
|
|
128
|
+
protected onInterceptorRemoved(interceptorId: string): void;
|
|
129
|
+
/**
|
|
130
|
+
* Get all interceptors
|
|
131
|
+
*/
|
|
132
|
+
getInterceptors(): IInterceptor[];
|
|
133
|
+
/**
|
|
134
|
+
* Clear all interceptors
|
|
135
|
+
*/
|
|
136
|
+
clearInterceptors(): void;
|
|
137
|
+
/**
|
|
138
|
+
* Hook for interceptors cleared
|
|
139
|
+
*/
|
|
140
|
+
protected onInterceptorsCleared(): void;
|
|
141
|
+
/**
|
|
142
|
+
* Discover service instances
|
|
143
|
+
* @returns Promise resolving to service instances
|
|
144
|
+
*/
|
|
145
|
+
discoverService(): Promise<ServiceInstance[]>;
|
|
146
|
+
/**
|
|
147
|
+
* Get current service instances (cached)
|
|
148
|
+
*/
|
|
149
|
+
getServiceInstances(): ServiceInstance[];
|
|
150
|
+
/**
|
|
151
|
+
* Refresh service instances cache
|
|
152
|
+
*/
|
|
153
|
+
refreshServiceInstances(): Promise<void>;
|
|
154
|
+
/**
|
|
155
|
+
* Select a service instance using load balancer
|
|
156
|
+
* @param instances Available instances
|
|
157
|
+
* @returns Selected instance
|
|
158
|
+
*/
|
|
159
|
+
protected selectInstance(instances: ServiceInstance[]): ServiceInstance;
|
|
160
|
+
/**
|
|
161
|
+
* Update client metrics
|
|
162
|
+
* @param success Whether call was successful
|
|
163
|
+
* @param duration Call duration in milliseconds
|
|
164
|
+
*/
|
|
165
|
+
protected updateMetrics(success: boolean, duration: number): void;
|
|
166
|
+
/**
|
|
167
|
+
* Calculate average response time
|
|
168
|
+
* @param newDuration New call duration
|
|
169
|
+
* @returns Average response time
|
|
170
|
+
*/
|
|
171
|
+
private calculateAverageResponseTime;
|
|
172
|
+
/**
|
|
173
|
+
* Health check for the client
|
|
174
|
+
* @returns Promise resolving to health status
|
|
175
|
+
*/
|
|
176
|
+
healthCheck(): Promise<{
|
|
177
|
+
healthy: boolean;
|
|
178
|
+
message?: string;
|
|
179
|
+
details?: Record<string, unknown>;
|
|
180
|
+
}>;
|
|
181
|
+
/**
|
|
182
|
+
* Get client metrics
|
|
183
|
+
*/
|
|
184
|
+
getMetrics(): Record<string, unknown>;
|
|
185
|
+
/**
|
|
186
|
+
* Reset client metrics
|
|
187
|
+
*/
|
|
188
|
+
resetMetrics(): void;
|
|
189
|
+
/**
|
|
190
|
+
* Close/cleanup client resources
|
|
191
|
+
*/
|
|
192
|
+
close(): Promise<void>;
|
|
193
|
+
/**
|
|
194
|
+
* Hook for client close
|
|
195
|
+
*/
|
|
196
|
+
protected onClose(): void;
|
|
197
|
+
}
|