@olane/o-node 0.7.12-alpha.4 → 0.7.12-alpha.6
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/dist/src/connection/o-node-connection.d.ts.map +1 -1
- package/dist/src/connection/o-node-connection.js +8 -2
- package/dist/src/connection/o-node-connection.manager.d.ts +1 -1
- package/dist/src/connection/o-node-connection.manager.d.ts.map +1 -1
- package/dist/src/connection/o-node-connection.manager.js +39 -19
- package/dist/src/interfaces/i-reconnectable-node.d.ts +41 -0
- package/dist/src/interfaces/i-reconnectable-node.d.ts.map +1 -0
- package/dist/src/interfaces/i-reconnectable-node.js +1 -0
- package/dist/src/interfaces/o-node.config.d.ts +35 -0
- package/dist/src/interfaces/o-node.config.d.ts.map +1 -1
- package/dist/src/managers/o-connection-heartbeat.manager.d.ts +67 -0
- package/dist/src/managers/o-connection-heartbeat.manager.d.ts.map +1 -0
- package/dist/src/managers/o-connection-heartbeat.manager.js +223 -0
- package/dist/src/managers/o-reconnection.manager.d.ts +39 -0
- package/dist/src/managers/o-reconnection.manager.d.ts.map +1 -0
- package/dist/src/managers/o-reconnection.manager.js +150 -0
- package/dist/src/o-node.d.ts +18 -1
- package/dist/src/o-node.d.ts.map +1 -1
- package/dist/src/o-node.js +82 -0
- package/dist/src/o-node.notification-manager.d.ts +52 -0
- package/dist/src/o-node.notification-manager.d.ts.map +1 -0
- package/dist/src/o-node.notification-manager.js +183 -0
- package/dist/src/o-node.tool.d.ts.map +1 -1
- package/dist/src/o-node.tool.js +19 -4
- package/dist/src/utils/leader-request-wrapper.d.ts +45 -0
- package/dist/src/utils/leader-request-wrapper.d.ts.map +1 -0
- package/dist/src/utils/leader-request-wrapper.js +89 -0
- package/package.json +6 -6
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { oObject, oAddress } from '@olane/o-core';
|
|
2
|
+
export interface LeaderRetryConfig {
|
|
3
|
+
enabled: boolean;
|
|
4
|
+
maxAttempts: number;
|
|
5
|
+
baseDelayMs: number;
|
|
6
|
+
maxDelayMs: number;
|
|
7
|
+
timeoutMs: number;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Leader Request Wrapper
|
|
11
|
+
*
|
|
12
|
+
* Wraps requests to leader/registry with aggressive retry logic.
|
|
13
|
+
* Used when leader may be temporarily unavailable (healing, maintenance).
|
|
14
|
+
*
|
|
15
|
+
* Strategy:
|
|
16
|
+
* 1. Detect if request is to leader or registry
|
|
17
|
+
* 2. Apply retry logic with exponential backoff
|
|
18
|
+
* 3. Timeout individual attempts
|
|
19
|
+
* 4. Log retries for observability
|
|
20
|
+
*/
|
|
21
|
+
export declare class LeaderRequestWrapper extends oObject {
|
|
22
|
+
private config;
|
|
23
|
+
constructor(config: LeaderRetryConfig);
|
|
24
|
+
/**
|
|
25
|
+
* Check if address is a leader-related address that needs retry
|
|
26
|
+
*/
|
|
27
|
+
private isLeaderAddress;
|
|
28
|
+
/**
|
|
29
|
+
* Execute request with retry logic
|
|
30
|
+
*/
|
|
31
|
+
execute<T>(requestFn: () => Promise<T>, address: oAddress, context?: string): Promise<T>;
|
|
32
|
+
/**
|
|
33
|
+
* Calculate exponential backoff delay
|
|
34
|
+
*/
|
|
35
|
+
private calculateBackoffDelay;
|
|
36
|
+
/**
|
|
37
|
+
* Sleep utility
|
|
38
|
+
*/
|
|
39
|
+
private sleep;
|
|
40
|
+
/**
|
|
41
|
+
* Get current configuration
|
|
42
|
+
*/
|
|
43
|
+
getConfig(): LeaderRetryConfig;
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=leader-request-wrapper.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"leader-request-wrapper.d.ts","sourceRoot":"","sources":["../../../src/utils/leader-request-wrapper.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAuB,MAAM,eAAe,CAAC;AAEvE,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,OAAO,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;;;;;;GAWG;AACH,qBAAa,oBAAqB,SAAQ,OAAO;IACnC,OAAO,CAAC,MAAM;gBAAN,MAAM,EAAE,iBAAiB;IAI7C;;OAEG;IACH,OAAO,CAAC,eAAe;IAKvB;;OAEG;IACG,OAAO,CAAC,CAAC,EACb,SAAS,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EAC3B,OAAO,EAAE,QAAQ,EACjB,OAAO,CAAC,EAAE,MAAM,GACf,OAAO,CAAC,CAAC,CAAC;IAoEb;;OAEG;IACH,OAAO,CAAC,qBAAqB;IAK7B;;OAEG;IACH,OAAO,CAAC,KAAK;IAIb;;OAEG;IACH,SAAS,IAAI,iBAAiB;CAG/B"}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { oObject } from '@olane/o-core';
|
|
2
|
+
/**
|
|
3
|
+
* Leader Request Wrapper
|
|
4
|
+
*
|
|
5
|
+
* Wraps requests to leader/registry with aggressive retry logic.
|
|
6
|
+
* Used when leader may be temporarily unavailable (healing, maintenance).
|
|
7
|
+
*
|
|
8
|
+
* Strategy:
|
|
9
|
+
* 1. Detect if request is to leader or registry
|
|
10
|
+
* 2. Apply retry logic with exponential backoff
|
|
11
|
+
* 3. Timeout individual attempts
|
|
12
|
+
* 4. Log retries for observability
|
|
13
|
+
*/
|
|
14
|
+
export class LeaderRequestWrapper extends oObject {
|
|
15
|
+
constructor(config) {
|
|
16
|
+
super();
|
|
17
|
+
this.config = config;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Check if address is a leader-related address that needs retry
|
|
21
|
+
*/
|
|
22
|
+
isLeaderAddress(address) {
|
|
23
|
+
const addressStr = address.toString();
|
|
24
|
+
return addressStr === 'o://leader' || addressStr === 'o://registry';
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Execute request with retry logic
|
|
28
|
+
*/
|
|
29
|
+
async execute(requestFn, address, context) {
|
|
30
|
+
// If retry disabled or not a leader address, execute directly
|
|
31
|
+
if (!this.config.enabled || !this.isLeaderAddress(address)) {
|
|
32
|
+
return await requestFn();
|
|
33
|
+
}
|
|
34
|
+
let attempt = 0;
|
|
35
|
+
let lastError;
|
|
36
|
+
while (attempt < this.config.maxAttempts) {
|
|
37
|
+
attempt++;
|
|
38
|
+
try {
|
|
39
|
+
this.logger.debug(`Leader request attempt ${attempt}/${this.config.maxAttempts}` +
|
|
40
|
+
(context ? ` (${context})` : ''));
|
|
41
|
+
// Create timeout promise
|
|
42
|
+
const timeoutPromise = new Promise((_, reject) => {
|
|
43
|
+
setTimeout(() => reject(new Error(`Leader request timeout after ${this.config.timeoutMs}ms`)), this.config.timeoutMs);
|
|
44
|
+
});
|
|
45
|
+
// Race between request and timeout
|
|
46
|
+
const result = await Promise.race([requestFn(), timeoutPromise]);
|
|
47
|
+
// Success!
|
|
48
|
+
if (attempt > 1) {
|
|
49
|
+
this.logger.info(`Leader request succeeded after ${attempt} attempts` +
|
|
50
|
+
(context ? ` (${context})` : ''));
|
|
51
|
+
}
|
|
52
|
+
return result;
|
|
53
|
+
}
|
|
54
|
+
catch (error) {
|
|
55
|
+
lastError = error instanceof Error ? error : new Error(String(error));
|
|
56
|
+
this.logger.warn(`Leader request attempt ${attempt} failed: ${lastError.message}` +
|
|
57
|
+
(context ? ` (${context})` : ''));
|
|
58
|
+
if (attempt < this.config.maxAttempts) {
|
|
59
|
+
const delay = this.calculateBackoffDelay(attempt);
|
|
60
|
+
this.logger.debug(`Waiting ${delay}ms before next attempt...`);
|
|
61
|
+
await this.sleep(delay);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
// All attempts failed
|
|
66
|
+
this.logger.error(`Leader request failed after ${this.config.maxAttempts} attempts` +
|
|
67
|
+
(context ? ` (${context})` : ''));
|
|
68
|
+
throw lastError || new Error('Leader request failed');
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Calculate exponential backoff delay
|
|
72
|
+
*/
|
|
73
|
+
calculateBackoffDelay(attempt) {
|
|
74
|
+
const delay = this.config.baseDelayMs * Math.pow(2, attempt - 1);
|
|
75
|
+
return Math.min(delay, this.config.maxDelayMs);
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Sleep utility
|
|
79
|
+
*/
|
|
80
|
+
sleep(ms) {
|
|
81
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Get current configuration
|
|
85
|
+
*/
|
|
86
|
+
getConfig() {
|
|
87
|
+
return { ...this.config };
|
|
88
|
+
}
|
|
89
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@olane/o-node",
|
|
3
|
-
"version": "0.7.12-alpha.
|
|
3
|
+
"version": "0.7.12-alpha.6",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "dist/src/index.js",
|
|
6
6
|
"types": "dist/src/index.d.ts",
|
|
@@ -54,12 +54,12 @@
|
|
|
54
54
|
"typescript": "5.4.5"
|
|
55
55
|
},
|
|
56
56
|
"dependencies": {
|
|
57
|
-
"@olane/o-config": "0.7.12-alpha.
|
|
58
|
-
"@olane/o-core": "0.7.12-alpha.
|
|
59
|
-
"@olane/o-protocol": "0.7.12-alpha.
|
|
60
|
-
"@olane/o-tool": "0.7.12-alpha.
|
|
57
|
+
"@olane/o-config": "0.7.12-alpha.5",
|
|
58
|
+
"@olane/o-core": "0.7.12-alpha.6",
|
|
59
|
+
"@olane/o-protocol": "0.7.12-alpha.6",
|
|
60
|
+
"@olane/o-tool": "0.7.12-alpha.6",
|
|
61
61
|
"debug": "^4.4.1",
|
|
62
62
|
"dotenv": "^16.5.0"
|
|
63
63
|
},
|
|
64
|
-
"gitHead": "
|
|
64
|
+
"gitHead": "fad0400ec59d38b163bd996d967cd46c6a5a9e0a"
|
|
65
65
|
}
|