@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,265 @@
1
+ /**
2
+ * Abstract base protocol implementation
3
+ * @packageDocumentation
4
+ */
5
+ import { CommunicationError } from '../errors/CommunicationError.js';
6
+ /**
7
+ * Abstract base protocol implementation
8
+ * Provides common functionality for all protocol implementations
9
+ */
10
+ export class BaseProtocol {
11
+ /**
12
+ * Create a new base protocol instance
13
+ * @param name Protocol name
14
+ * @param config Protocol configuration
15
+ */
16
+ constructor(name, config) {
17
+ /** Protocol interceptors */
18
+ this.interceptors = [];
19
+ /** Protocol metrics */
20
+ this.metrics = {};
21
+ /** Whether protocol is connected (for stateful protocols) */
22
+ this.connected = false;
23
+ /** Protocol start time */
24
+ this.startTime = Date.now();
25
+ /** Total requests sent */
26
+ this.totalRequests = 0;
27
+ /** Total successful requests */
28
+ this.successfulRequests = 0;
29
+ /** Total failed requests */
30
+ this.failedRequests = 0;
31
+ this.name = name;
32
+ this.config = { ...config };
33
+ this.version = config.options?.version || '1.0.0';
34
+ }
35
+ /**
36
+ * Configure the protocol with new settings
37
+ * @param config Configuration object
38
+ */
39
+ configure(config) {
40
+ this.config = { ...this.config, ...config };
41
+ this.onConfigure(config);
42
+ }
43
+ /**
44
+ * Hook for protocol configuration changes
45
+ * @param newConfig New configuration
46
+ */
47
+ onConfigure(newConfig) {
48
+ // Can be overridden by subclasses
49
+ }
50
+ /**
51
+ * Connect to the service (for stateful protocols)
52
+ * @returns Promise that resolves when connected
53
+ */
54
+ async connect() {
55
+ this.connected = true;
56
+ await this.onConnect?.();
57
+ }
58
+ /**
59
+ * Hook for connection logic
60
+ */
61
+ async onConnect() {
62
+ // Can be overridden by subclasses
63
+ }
64
+ /**
65
+ * Disconnect from the service (for stateful protocols)
66
+ * @returns Promise that resolves when disconnected
67
+ */
68
+ async disconnect() {
69
+ this.connected = false;
70
+ await this.onDisconnect?.();
71
+ }
72
+ /**
73
+ * Hook for disconnection logic
74
+ */
75
+ async onDisconnect() {
76
+ // Can be overridden by subclasses
77
+ }
78
+ /**
79
+ * Check if the protocol is currently connected
80
+ * @returns True if connected, false otherwise
81
+ */
82
+ isConnected() {
83
+ return this.connected;
84
+ }
85
+ /**
86
+ * Add an interceptor to the protocol
87
+ * @param interceptor Interceptor to add
88
+ */
89
+ addInterceptor(interceptor) {
90
+ this.interceptors.push(interceptor);
91
+ interceptor.initialize?.({ protocol: this.name });
92
+ this.onInterceptorAdded(interceptor);
93
+ }
94
+ /**
95
+ * Hook for interceptor addition
96
+ * @param interceptor Added interceptor
97
+ */
98
+ onInterceptorAdded(interceptor) {
99
+ // Can be overridden by subclasses
100
+ }
101
+ /**
102
+ * Remove an interceptor from the protocol
103
+ * @param interceptorId Interceptor identifier
104
+ */
105
+ removeInterceptor(interceptorId) {
106
+ const index = this.interceptors.findIndex(i => i.name === interceptorId);
107
+ if (index !== -1) {
108
+ const interceptor = this.interceptors[index];
109
+ interceptor.cleanup?.();
110
+ this.interceptors.splice(index, 1);
111
+ this.onInterceptorRemoved(interceptorId);
112
+ }
113
+ }
114
+ /**
115
+ * Hook for interceptor removal
116
+ * @param interceptorId Removed interceptor ID
117
+ */
118
+ onInterceptorRemoved(interceptorId) {
119
+ // Can be overridden by subclasses
120
+ }
121
+ /**
122
+ * Get all interceptors
123
+ */
124
+ getInterceptors() {
125
+ return [...this.interceptors];
126
+ }
127
+ /**
128
+ * Execute request interceptors
129
+ * @param request Original request
130
+ * @param context Request context
131
+ * @returns Modified request
132
+ */
133
+ async executeRequestInterceptors(request, context) {
134
+ let modifiedRequest = request;
135
+ for (const interceptor of this.interceptors) {
136
+ if (interceptor.enabled && interceptor.onRequest) {
137
+ const result = await interceptor.onRequest(modifiedRequest, context);
138
+ if (result !== undefined) {
139
+ modifiedRequest = result;
140
+ }
141
+ }
142
+ }
143
+ return modifiedRequest;
144
+ }
145
+ /**
146
+ * Execute response interceptors
147
+ * @param response Original response
148
+ * @param context Request context
149
+ * @returns Modified response
150
+ */
151
+ async executeResponseInterceptors(response, context) {
152
+ let modifiedResponse = response;
153
+ for (const interceptor of this.interceptors) {
154
+ if (interceptor.enabled && interceptor.onResponse) {
155
+ const result = await interceptor.onResponse(modifiedResponse, context);
156
+ if (result !== undefined) {
157
+ modifiedResponse = result;
158
+ }
159
+ }
160
+ }
161
+ return modifiedResponse;
162
+ }
163
+ /**
164
+ * Execute error interceptors
165
+ * @param error Original error
166
+ * @param context Request context
167
+ * @returns Modified error or response
168
+ */
169
+ async executeErrorInterceptors(error, context) {
170
+ let result = error;
171
+ for (const interceptor of this.interceptors) {
172
+ if (interceptor.enabled && interceptor.onError) {
173
+ const interceptorResult = await interceptor.onError(result instanceof CommunicationError ? result : error, context);
174
+ if (interceptorResult !== undefined) {
175
+ result = interceptorResult;
176
+ }
177
+ }
178
+ }
179
+ return result;
180
+ }
181
+ /**
182
+ * Update request metrics
183
+ * @param success Whether request was successful
184
+ * @param duration Request duration in milliseconds
185
+ */
186
+ updateMetrics(success, duration) {
187
+ this.totalRequests++;
188
+ if (success) {
189
+ this.successfulRequests++;
190
+ }
191
+ else {
192
+ this.failedRequests++;
193
+ }
194
+ this.metrics = {
195
+ ...this.metrics,
196
+ totalRequests: this.totalRequests,
197
+ successfulRequests: this.successfulRequests,
198
+ failedRequests: this.failedRequests,
199
+ successRate: this.totalRequests > 0 ? this.successfulRequests / this.totalRequests : 0,
200
+ averageResponseTime: this.calculateAverageResponseTime(duration),
201
+ uptime: Date.now() - this.startTime,
202
+ };
203
+ }
204
+ /**
205
+ * Calculate average response time
206
+ * @param newDuration New request duration
207
+ * @returns Average response time
208
+ */
209
+ calculateAverageResponseTime(newDuration) {
210
+ const currentAverage = this.metrics.averageResponseTime || 0;
211
+ const totalDuration = currentAverage * (this.totalRequests - 1) + newDuration;
212
+ return totalDuration / this.totalRequests;
213
+ }
214
+ /**
215
+ * Get protocol metrics
216
+ */
217
+ getMetrics() {
218
+ return { ...this.metrics };
219
+ }
220
+ /**
221
+ * Reset protocol metrics
222
+ */
223
+ resetMetrics() {
224
+ this.totalRequests = 0;
225
+ this.successfulRequests = 0;
226
+ this.failedRequests = 0;
227
+ this.metrics = {
228
+ uptime: Date.now() - this.startTime,
229
+ };
230
+ }
231
+ /**
232
+ * Health check for the protocol
233
+ * @returns Promise resolving to health status
234
+ */
235
+ async healthCheck() {
236
+ const healthy = this.connected !== false;
237
+ return {
238
+ healthy,
239
+ message: healthy ? 'Protocol is healthy' : 'Protocol is not connected',
240
+ details: {
241
+ name: this.name,
242
+ version: this.version,
243
+ connected: this.connected,
244
+ totalRequests: this.totalRequests,
245
+ successRate: this.metrics.successRate,
246
+ uptime: this.metrics.uptime,
247
+ },
248
+ };
249
+ }
250
+ /**
251
+ * Create request context
252
+ * @param request Request object
253
+ * @param attempt Attempt number
254
+ * @returns Request context
255
+ */
256
+ createRequestContext(request, attempt = 1) {
257
+ return {
258
+ protocol: this.name,
259
+ requestId: request.id || `req_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
260
+ attempt,
261
+ startTime: Date.now(),
262
+ isRetry: attempt > 1,
263
+ };
264
+ }
265
+ }
@@ -0,0 +1,251 @@
1
+ /**
2
+ * Abstract base retry strategy implementation
3
+ * @packageDocumentation
4
+ */
5
+ /**
6
+ * Abstract base retry strategy implementation
7
+ * Provides common functionality for all retry strategy implementations
8
+ */
9
+ export class BaseRetryStrategy {
10
+ /**
11
+ * Create a new base retry strategy instance
12
+ * @param name Strategy name
13
+ * @param config Strategy configuration
14
+ */
15
+ constructor(name, config) {
16
+ /** Total retry attempts made */
17
+ this.totalAttempts = 0;
18
+ /** Successful retries */
19
+ this.successfulRetries = 0;
20
+ /** Failed retries */
21
+ this.failedRetries = 0;
22
+ /** Retry statistics */
23
+ this.stats = {
24
+ totalExecutions: 0,
25
+ totalAttempts: 0,
26
+ successfulRetries: 0,
27
+ failedRetries: 0,
28
+ successRate: 0,
29
+ averageAttempts: 0,
30
+ averageDelay: 0,
31
+ totalTimeSpent: 0,
32
+ };
33
+ this.name = name;
34
+ this.config = { ...config };
35
+ this.initialize();
36
+ }
37
+ /**
38
+ * Initialize retry strategy
39
+ */
40
+ initialize() {
41
+ // Can be overridden by subclasses
42
+ }
43
+ /**
44
+ * Determine if a retry should be attempted
45
+ * @param error Error that occurred
46
+ * @param context Current retry context
47
+ * @returns Retry decision
48
+ */
49
+ shouldRetry(error, context) {
50
+ // Check max attempts
51
+ if (context.attempt >= context.maxAttempts) {
52
+ return {
53
+ shouldRetry: false,
54
+ reason: 'Max attempts reached',
55
+ };
56
+ }
57
+ // Check retry on status codes (for HTTP errors)
58
+ if (error.statusCode && this.config.retryOnStatus?.includes(error.statusCode)) {
59
+ return {
60
+ shouldRetry: true,
61
+ delay: this.calculateDelay(context.attempt, context),
62
+ reason: `Status code ${error.statusCode} is retryable`,
63
+ };
64
+ }
65
+ // Check retry on error types
66
+ if (this.config.retryOnErrors?.includes(error.code)) {
67
+ return {
68
+ shouldRetry: true,
69
+ delay: this.calculateDelay(context.attempt, context),
70
+ reason: `Error code ${error.code} is retryable`,
71
+ };
72
+ }
73
+ // Check if error is retryable based on type
74
+ if (this.isRetryableError(error)) {
75
+ return {
76
+ shouldRetry: true,
77
+ delay: this.calculateDelay(context.attempt, context),
78
+ reason: 'Error is retryable',
79
+ };
80
+ }
81
+ return {
82
+ shouldRetry: false,
83
+ reason: 'Error is not retryable',
84
+ };
85
+ }
86
+ /**
87
+ * Check if an error is retryable
88
+ * @param error Error to check
89
+ * @returns True if error is retryable
90
+ */
91
+ isRetryableError(error) {
92
+ // Default implementation: retry on network errors, timeouts, and 5xx errors
93
+ const networkErrors = ['ECONNREFUSED', 'ECONNRESET', 'ETIMEDOUT', 'ENOTFOUND'];
94
+ const timeoutErrors = ['TIMEOUT', 'TIMEOUT_EXCEEDED'];
95
+ return (networkErrors.some(code => error.code?.includes(code)) ||
96
+ timeoutErrors.some(code => error.code?.includes(code)) ||
97
+ (error?.statusCode >= 500 && error?.statusCode < 600));
98
+ }
99
+ /**
100
+ * Calculate delay for next retry attempt
101
+ * @param attempt Current attempt number
102
+ * @param context Current retry context
103
+ * @returns Delay in milliseconds
104
+ */
105
+ calculateDelay(attempt, context) {
106
+ const backoff = this.config?.backoff || {};
107
+ const strategy = this.config.backoffStrategy || 'exponential';
108
+ switch (strategy) {
109
+ case 'fixed':
110
+ return backoff.initialDelay || 1000;
111
+ case 'exponential':
112
+ const baseDelay = backoff.initialDelay || 100;
113
+ const multiplier = backoff.multiplier || 2;
114
+ return Math.min(baseDelay * Math.pow(multiplier, attempt - 1), backoff.maxDelay || 30000);
115
+ case 'linear':
116
+ const linearDelay = backoff.initialDelay || 100;
117
+ const increment = backoff.multiplier || 1000;
118
+ return Math.min(linearDelay + (increment * (attempt - 1)), backoff.maxDelay || 30000);
119
+ case 'jitter':
120
+ const jitterDelay = backoff.initialDelay || 100;
121
+ const jitterMultiplier = backoff.multiplier || 2;
122
+ const base = jitterDelay * Math.pow(jitterMultiplier, attempt - 1);
123
+ const jitter = backoff.jitter || 0.3;
124
+ const jitterValue = base * jitter * Math.random();
125
+ return Math.min(base + jitterValue, backoff.maxDelay || 30000);
126
+ case 'fibonacci':
127
+ const fibDelay = backoff.initialDelay || 100;
128
+ let a = 0, b = 1;
129
+ for (let i = 0; i < attempt; i++) {
130
+ [a, b] = [b, a + b];
131
+ }
132
+ return Math.min(fibDelay * a, backoff.maxDelay || 30000);
133
+ default:
134
+ // Custom strategy or fallback
135
+ if (backoff.custom) {
136
+ return backoff.custom(attempt);
137
+ }
138
+ return backoff.initialDelay || 1000;
139
+ }
140
+ }
141
+ /**
142
+ * Create retry context
143
+ * @param initialContext Initial context values
144
+ * @returns Complete retry context
145
+ */
146
+ createRetryContext(initialContext) {
147
+ const defaultContext = {
148
+ attempt: 1,
149
+ maxAttempts: this.config.maxAttempts || 3,
150
+ lastError: undefined,
151
+ startTime: Date.now(),
152
+ elapsedTime: 0,
153
+ data: new Map(),
154
+ isRetry: false,
155
+ };
156
+ return {
157
+ ...defaultContext,
158
+ ...initialContext,
159
+ };
160
+ }
161
+ /**
162
+ * Update retry context after attempt
163
+ * @param context Current context
164
+ * @param error Error from attempt (if any)
165
+ * @returns Updated context
166
+ */
167
+ updateRetryContext(context, error) {
168
+ return {
169
+ ...context,
170
+ attempt: context.attempt + 1,
171
+ lastError: error,
172
+ elapsedTime: Date.now() - context.startTime,
173
+ isRetry: context.attempt > 1,
174
+ };
175
+ }
176
+ /**
177
+ * Update retry statistics
178
+ * @param success Whether retry was successful
179
+ * @param attempts Number of attempts
180
+ * @param totalDelay Total delay time
181
+ */
182
+ updateStats(success, attempts, totalDelay) {
183
+ this.totalAttempts += attempts;
184
+ this.stats.totalExecutions++;
185
+ this.stats.totalAttempts += attempts;
186
+ this.stats.totalTimeSpent += totalDelay;
187
+ if (success) {
188
+ this.successfulRetries++;
189
+ this.stats.successfulRetries++;
190
+ }
191
+ else {
192
+ this.failedRetries++;
193
+ this.stats.failedRetries++;
194
+ }
195
+ // Update calculated stats
196
+ const totalExecutions = this.stats.totalExecutions;
197
+ const totalAttempts = this.stats.totalAttempts;
198
+ this.stats.successRate = totalExecutions > 0 ?
199
+ this.stats.successfulRetries / totalExecutions : 0;
200
+ this.stats.averageAttempts = totalExecutions > 0 ?
201
+ totalAttempts / totalExecutions : 0;
202
+ this.stats.averageDelay = totalAttempts > 0 ?
203
+ this.stats.totalTimeSpent / totalAttempts : 0;
204
+ }
205
+ /**
206
+ * Update retry strategy configuration
207
+ * @param config New configuration
208
+ */
209
+ updateConfig(config) {
210
+ this.config = { ...this.config, ...config };
211
+ }
212
+ /**
213
+ * Get retry strategy statistics
214
+ */
215
+ getStats() {
216
+ return { ...this.stats };
217
+ }
218
+ /**
219
+ * Reset retry strategy statistics
220
+ */
221
+ resetStats() {
222
+ this.totalAttempts = 0;
223
+ this.successfulRetries = 0;
224
+ this.failedRetries = 0;
225
+ this.stats = {
226
+ totalExecutions: 0,
227
+ totalAttempts: 0,
228
+ successfulRetries: 0,
229
+ failedRetries: 0,
230
+ successRate: 0,
231
+ averageAttempts: 0,
232
+ averageDelay: 0,
233
+ totalTimeSpent: 0,
234
+ };
235
+ }
236
+ /**
237
+ * Health check for the retry strategy
238
+ */
239
+ healthCheck() {
240
+ const healthy = true; // Retry strategy is always healthy
241
+ return {
242
+ healthy,
243
+ message: 'Retry strategy is operational',
244
+ details: {
245
+ name: this.name,
246
+ config: this.config,
247
+ statistics: this.getStats(),
248
+ },
249
+ };
250
+ }
251
+ }