postchain-client 2.0.4 → 2.1.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 +9 -7
- package/built/cjs/index.js +235 -118
- package/built/cjs/index.js.map +1 -1
- package/built/esm/index.js +19045 -17598
- package/built/esm/index.js.map +1 -1
- package/built/mocks/handlers.d.ts +8 -8
- package/built/mocks/handlers.js +4 -2
- package/built/mocks/handlers.js.map +1 -1
- package/built/mocks/servers.d.ts +1 -1
- package/built/resources/testData.d.ts +1 -2
- package/built/src/ICCF/IccfProofTxMaterialBuilder.d.ts +0 -1
- package/built/src/ICCF/IccfProofTxMaterialBuilder.js +3 -2
- package/built/src/ICCF/IccfProofTxMaterialBuilder.js.map +1 -1
- package/built/src/ICCF/error.d.ts +0 -1
- package/built/src/ICCF/interfaces.d.ts +0 -1
- package/built/src/ICCF/types.d.ts +0 -1
- package/built/src/ICCF/utils.d.ts +0 -1
- package/built/src/ICCF/utils.js +3 -1
- package/built/src/ICCF/utils.js.map +1 -1
- package/built/src/blockchainClient/blockchainClient.js +10 -10
- package/built/src/blockchainClient/blockchainClient.js.map +1 -1
- package/built/src/blockchainClient/errors.d.ts +0 -1
- package/built/src/blockchainClient/failoverStrategies.d.ts +5 -4
- package/built/src/blockchainClient/failoverStrategies.js +93 -55
- package/built/src/blockchainClient/failoverStrategies.js.map +1 -1
- package/built/src/blockchainClient/httpUtil.d.ts +0 -1
- package/built/src/blockchainClient/httpUtil.js +7 -2
- package/built/src/blockchainClient/httpUtil.js.map +1 -1
- package/built/src/blockchainClient/interface.d.ts +0 -1
- package/built/src/blockchainClient/nodeManager.d.ts +10 -7
- package/built/src/blockchainClient/nodeManager.js +47 -20
- package/built/src/blockchainClient/nodeManager.js.map +1 -1
- package/built/src/blockchainClient/requestWithFailoverStrategy.d.ts +0 -1
- package/built/src/blockchainClient/requestWithFailoverStrategy.js +2 -2
- package/built/src/blockchainClient/requestWithFailoverStrategy.js.map +1 -1
- package/built/src/blockchainClient/types.d.ts +2 -1
- package/built/src/blockchainClient/utils.d.ts +1 -2
- package/built/src/blockchainClient/utils.js +20 -15
- package/built/src/blockchainClient/utils.js.map +1 -1
- package/built/src/blockchainClient/validation/anchoringTransaction.d.ts +6 -7
- package/built/src/blockchainClient/validation/blockIdentifier.d.ts +2 -2
- package/built/src/blockchainClient/validation/blockIdentifier.js +4 -4
- package/built/src/blockchainClient/validation/blockIdentifier.js.map +1 -1
- package/built/src/blockchainClient/validation/bufferSchema.d.ts +1 -2
- package/built/src/blockchainClient/validation/networkSettings.d.ts +2 -2
- package/built/src/blockchainClient/validation/networkSettings.js +2 -2
- package/built/src/blockchainClient/validation/networkSettings.js.map +1 -1
- package/built/src/blockchainClient/validation/signMethod.d.ts +12 -13
- package/built/src/blockchainClient/validation/txRid.d.ts +1 -2
- package/built/src/encryption/encryption.d.ts +0 -1
- package/built/src/encryption/errors.d.ts +0 -1
- package/built/src/encryption/types.d.ts +0 -1
- package/built/src/formatter.d.ts +1 -2
- package/built/src/formatter.js +3 -4
- package/built/src/formatter.js.map +1 -1
- package/built/src/gtv/index.d.ts +1 -2
- package/built/src/gtv/types.d.ts +0 -1
- package/built/src/gtx/gtx.d.ts +0 -1
- package/built/src/gtx/gtx.js +2 -1
- package/built/src/gtx/gtx.js.map +1 -1
- package/built/src/gtx/serialization.d.ts +0 -1
- package/built/src/gtx/types.d.ts +0 -1
- package/built/src/utils/bufferUtils.d.ts +6 -0
- package/built/src/utils/bufferUtils.js +9 -0
- package/built/src/utils/bufferUtils.js.map +1 -0
- package/built/src/utils/calculateTransactionRid.d.ts +0 -1
- package/built/src/utils/decodeTransactionToGtx.d.ts +0 -1
- package/built/src/utils/encodeTransaction.d.ts +0 -1
- package/built/src/utils/http-utils.d.ts +19 -0
- package/built/src/utils/http-utils.js +36 -0
- package/built/src/utils/http-utils.js.map +1 -0
- package/built/test/common/mocks.d.ts +23 -24
- package/built/test/common/setups.d.ts +3 -4
- package/built/test/common/signatures.d.ts +9 -10
- package/built/test/common/validationMocks.d.ts +2 -3
- package/built/test/integration/clientQuery.test.js.map +1 -1
- package/built/test/integration/clientSendTransaction.test.js +1 -1
- package/built/test/integration/clientSendTransaction.test.js.map +1 -1
- package/built/test/integration/createClientIntegration.test.js +5 -21
- package/built/test/integration/createClientIntegration.test.js.map +1 -1
- package/built/test/integration/failoverStrategiesWithSmartTimeouts.test.d.ts +1 -0
- package/built/test/integration/failoverStrategiesWithSmartTimeouts.test.js +140 -0
- package/built/test/integration/failoverStrategiesWithSmartTimeouts.test.js.map +1 -0
- package/built/test/manual/iccfManually.test.js +2 -2
- package/built/test/manual/iccfManually.test.js.map +1 -1
- package/built/test/pcctf/helpers.js +2 -2
- package/built/test/pcctf/helpers.js.map +1 -1
- package/built/test/unit/ICCF/iccf.test.js +7 -4
- package/built/test/unit/ICCF/iccf.test.js.map +1 -1
- package/built/test/unit/ICCF/iccfProofMaterialBuilder.test.js +2 -2
- package/built/test/unit/failoverStrategies.test.js +36 -15
- package/built/test/unit/failoverStrategies.test.js.map +1 -1
- package/built/test/unit/networkErrorDetection.test.d.ts +1 -0
- package/built/test/unit/networkErrorDetection.test.js +433 -0
- package/built/test/unit/networkErrorDetection.test.js.map +1 -0
- package/built/test/unit/nodeMananger.test.js +3 -2
- package/built/test/unit/nodeMananger.test.js.map +1 -1
- package/built/test/unit/smartTimeouts.test.d.ts +1 -0
- package/built/test/unit/smartTimeouts.test.js +296 -0
- package/built/test/unit/smartTimeouts.test.js.map +1 -0
- package/built/test/unit/stickyNode.test.js +13 -13
- package/built/test/unit/stickyNode.test.js.map +1 -1
- package/built/test/unit/universalNodeRecovery.test.d.ts +1 -0
- package/built/test/unit/universalNodeRecovery.test.js +283 -0
- package/built/test/unit/universalNodeRecovery.test.js.map +1 -0
- package/built/umd/index.js +19070 -17625
- package/built/umd/index.js.map +1 -1
- package/changelog.md +31 -1
- package/package.json +11 -8
|
@@ -0,0 +1,296 @@
|
|
|
1
|
+
import { createNodeManager } from "../../src/blockchainClient/nodeManager";
|
|
2
|
+
describe("Smart Timeouts", () => {
|
|
3
|
+
beforeEach(() => {
|
|
4
|
+
jest.clearAllMocks();
|
|
5
|
+
jest.useFakeTimers();
|
|
6
|
+
});
|
|
7
|
+
afterEach(() => {
|
|
8
|
+
jest.useRealTimers();
|
|
9
|
+
});
|
|
10
|
+
describe("Network Error Timeout Calculations", () => {
|
|
11
|
+
it("should apply 5 minute timeout for DNS resolution errors (ENOTFOUND)", () => {
|
|
12
|
+
const nodeManager = createNodeManager({
|
|
13
|
+
nodeUrls: ["node1", "node2"],
|
|
14
|
+
unavailableDuration: 5000, // Default
|
|
15
|
+
});
|
|
16
|
+
// Simulate DNS error - this would typically be handled by failover strategies
|
|
17
|
+
// but we're testing the timeout calculation concept
|
|
18
|
+
nodeManager.makeNodeUnavailable("node1", 5 * 60 * 1000); // 5 minutes for DNS
|
|
19
|
+
expect(nodeManager.nodes[0].isAvailable()).toBe(false);
|
|
20
|
+
// Fast forward 4 minutes and 59 seconds - should still be unavailable
|
|
21
|
+
jest.advanceTimersByTime(4 * 60 * 1000 + 59 * 1000);
|
|
22
|
+
expect(nodeManager.nodes[0].isAvailable()).toBe(false);
|
|
23
|
+
// Fast forward 1 more second - should now be available
|
|
24
|
+
jest.advanceTimersByTime(1000);
|
|
25
|
+
expect(nodeManager.nodes[0].isAvailable()).toBe(true);
|
|
26
|
+
});
|
|
27
|
+
it("should apply 5 minute timeout for connection refused errors (ECONNREFUSED)", () => {
|
|
28
|
+
const nodeManager = createNodeManager({
|
|
29
|
+
nodeUrls: ["node1", "node2"],
|
|
30
|
+
unavailableDuration: 5000,
|
|
31
|
+
});
|
|
32
|
+
// Simulate connection refused error
|
|
33
|
+
nodeManager.makeNodeUnavailable("node1", 5 * 60 * 1000); // 5 minutes
|
|
34
|
+
expect(nodeManager.nodes[0].isAvailable()).toBe(false);
|
|
35
|
+
// Fast forward 4 minutes and 59 seconds
|
|
36
|
+
jest.advanceTimersByTime(4 * 60 * 1000 + 59 * 1000);
|
|
37
|
+
expect(nodeManager.nodes[0].isAvailable()).toBe(false);
|
|
38
|
+
// Fast forward 1 more second
|
|
39
|
+
jest.advanceTimersByTime(1000);
|
|
40
|
+
expect(nodeManager.nodes[0].isAvailable()).toBe(true);
|
|
41
|
+
});
|
|
42
|
+
});
|
|
43
|
+
describe("HTTP Status Code Timeout Calculations", () => {
|
|
44
|
+
it("should apply 10 second timeout for 500 Internal Server Error", () => {
|
|
45
|
+
const nodeManager = createNodeManager({
|
|
46
|
+
nodeUrls: ["node1", "node2"],
|
|
47
|
+
unavailableDuration: 5000,
|
|
48
|
+
});
|
|
49
|
+
// Simulate 500 error timeout
|
|
50
|
+
nodeManager.makeNodeUnavailable("node1", 10 * 1000); // 10 seconds
|
|
51
|
+
expect(nodeManager.nodes[0].isAvailable()).toBe(false);
|
|
52
|
+
// Fast forward 9 seconds
|
|
53
|
+
jest.advanceTimersByTime(9 * 1000);
|
|
54
|
+
expect(nodeManager.nodes[0].isAvailable()).toBe(false);
|
|
55
|
+
// Fast forward 1 more second
|
|
56
|
+
jest.advanceTimersByTime(1000);
|
|
57
|
+
expect(nodeManager.nodes[0].isAvailable()).toBe(true);
|
|
58
|
+
});
|
|
59
|
+
it("should apply 30 second timeout for 502 Bad Gateway", () => {
|
|
60
|
+
const nodeManager = createNodeManager({
|
|
61
|
+
nodeUrls: ["node1", "node2"],
|
|
62
|
+
unavailableDuration: 5000,
|
|
63
|
+
});
|
|
64
|
+
// Simulate 502 error timeout
|
|
65
|
+
nodeManager.makeNodeUnavailable("node1", 30 * 1000); // 30 seconds
|
|
66
|
+
expect(nodeManager.nodes[0].isAvailable()).toBe(false);
|
|
67
|
+
// Fast forward 29 seconds
|
|
68
|
+
jest.advanceTimersByTime(29 * 1000);
|
|
69
|
+
expect(nodeManager.nodes[0].isAvailable()).toBe(false);
|
|
70
|
+
// Fast forward 1 more second
|
|
71
|
+
jest.advanceTimersByTime(1000);
|
|
72
|
+
expect(nodeManager.nodes[0].isAvailable()).toBe(true);
|
|
73
|
+
});
|
|
74
|
+
it("should apply 2 second timeout for 503 Service Unavailable", () => {
|
|
75
|
+
const nodeManager = createNodeManager({
|
|
76
|
+
nodeUrls: ["node1", "node2"],
|
|
77
|
+
unavailableDuration: 5000,
|
|
78
|
+
});
|
|
79
|
+
// Simulate 503 error timeout (load balancer overload)
|
|
80
|
+
nodeManager.makeNodeUnavailable("node1", 2 * 1000); // 2 seconds
|
|
81
|
+
expect(nodeManager.nodes[0].isAvailable()).toBe(false);
|
|
82
|
+
// Fast forward 1.9 seconds
|
|
83
|
+
jest.advanceTimersByTime(1900);
|
|
84
|
+
expect(nodeManager.nodes[0].isAvailable()).toBe(false);
|
|
85
|
+
// Fast forward 0.1 more seconds
|
|
86
|
+
jest.advanceTimersByTime(100);
|
|
87
|
+
expect(nodeManager.nodes[0].isAvailable()).toBe(true);
|
|
88
|
+
});
|
|
89
|
+
it("should apply 60 second timeout for 504 Gateway Timeout", () => {
|
|
90
|
+
const nodeManager = createNodeManager({
|
|
91
|
+
nodeUrls: ["node1", "node2"],
|
|
92
|
+
unavailableDuration: 5000,
|
|
93
|
+
});
|
|
94
|
+
// Simulate 504 error timeout
|
|
95
|
+
nodeManager.makeNodeUnavailable("node1", 60 * 1000); // 60 seconds
|
|
96
|
+
expect(nodeManager.nodes[0].isAvailable()).toBe(false);
|
|
97
|
+
// Fast forward 59 seconds
|
|
98
|
+
jest.advanceTimersByTime(59 * 1000);
|
|
99
|
+
expect(nodeManager.nodes[0].isAvailable()).toBe(false);
|
|
100
|
+
// Fast forward 1 more second
|
|
101
|
+
jest.advanceTimersByTime(1000);
|
|
102
|
+
expect(nodeManager.nodes[0].isAvailable()).toBe(true);
|
|
103
|
+
});
|
|
104
|
+
it("should apply default 5 second timeout for other HTTP errors", () => {
|
|
105
|
+
const nodeManager = createNodeManager({
|
|
106
|
+
nodeUrls: ["node1", "node2"],
|
|
107
|
+
unavailableDuration: 5000,
|
|
108
|
+
});
|
|
109
|
+
// Use default timeout for unknown error
|
|
110
|
+
nodeManager.makeNodeUnavailable("node1", 5 * 1000); // 5 seconds default
|
|
111
|
+
expect(nodeManager.nodes[0].isAvailable()).toBe(false);
|
|
112
|
+
// Fast forward 4 seconds
|
|
113
|
+
jest.advanceTimersByTime(4 * 1000);
|
|
114
|
+
expect(nodeManager.nodes[0].isAvailable()).toBe(false);
|
|
115
|
+
// Fast forward 1 more second
|
|
116
|
+
jest.advanceTimersByTime(1000);
|
|
117
|
+
expect(nodeManager.nodes[0].isAvailable()).toBe(true);
|
|
118
|
+
});
|
|
119
|
+
});
|
|
120
|
+
describe("Custom Timeout Duration Handling", () => {
|
|
121
|
+
it("should respect custom unavailableDuration from nodeManager config", () => {
|
|
122
|
+
const customDuration = 15000; // 15 seconds
|
|
123
|
+
const nodeManager = createNodeManager({
|
|
124
|
+
nodeUrls: ["node1", "node2"],
|
|
125
|
+
unavailableDuration: customDuration,
|
|
126
|
+
});
|
|
127
|
+
// Make node unavailable without specifying duration (should use default)
|
|
128
|
+
nodeManager.makeNodeUnavailable("node1");
|
|
129
|
+
expect(nodeManager.nodes[0].isAvailable()).toBe(false);
|
|
130
|
+
// Fast forward default duration - 1 second
|
|
131
|
+
jest.advanceTimersByTime(customDuration - 1000);
|
|
132
|
+
expect(nodeManager.nodes[0].isAvailable()).toBe(false);
|
|
133
|
+
// Fast forward remaining time
|
|
134
|
+
jest.advanceTimersByTime(1000);
|
|
135
|
+
expect(nodeManager.nodes[0].isAvailable()).toBe(true);
|
|
136
|
+
});
|
|
137
|
+
it("should override default duration when explicit duration is provided", () => {
|
|
138
|
+
const nodeManager = createNodeManager({
|
|
139
|
+
nodeUrls: ["node1", "node2"],
|
|
140
|
+
unavailableDuration: 5000, // Default 5 seconds
|
|
141
|
+
});
|
|
142
|
+
const customDuration = 20000; // Override with 20 seconds
|
|
143
|
+
nodeManager.makeNodeUnavailable("node1", customDuration);
|
|
144
|
+
expect(nodeManager.nodes[0].isAvailable()).toBe(false);
|
|
145
|
+
// Fast forward default duration - should still be unavailable
|
|
146
|
+
jest.advanceTimersByTime(5000);
|
|
147
|
+
expect(nodeManager.nodes[0].isAvailable()).toBe(false);
|
|
148
|
+
// Fast forward to just before custom duration
|
|
149
|
+
jest.advanceTimersByTime(15000 - 1000);
|
|
150
|
+
expect(nodeManager.nodes[0].isAvailable()).toBe(false);
|
|
151
|
+
// Fast forward remaining time
|
|
152
|
+
jest.advanceTimersByTime(1000);
|
|
153
|
+
expect(nodeManager.nodes[0].isAvailable()).toBe(true);
|
|
154
|
+
});
|
|
155
|
+
});
|
|
156
|
+
describe("Multiple Node Timeout Management", () => {
|
|
157
|
+
it("should handle different timeout durations for different nodes", () => {
|
|
158
|
+
const nodeManager = createNodeManager({
|
|
159
|
+
nodeUrls: ["node1", "node2", "node3", "node4", "node5"],
|
|
160
|
+
unavailableDuration: 5000,
|
|
161
|
+
});
|
|
162
|
+
// Set different timeouts for nodes, keeping enough available to avoid recovery
|
|
163
|
+
// With 5 nodes, recovery threshold = 5 - Math.floor(2 * (5-1) / 3) = 5 - 2 = 3
|
|
164
|
+
// Keep 3 nodes available to stay at threshold (won't trigger recovery)
|
|
165
|
+
nodeManager.makeNodeUnavailable("node1", 2000); // 2 seconds
|
|
166
|
+
nodeManager.makeNodeUnavailable("node2", 5000); // 5 seconds
|
|
167
|
+
// node3, node4, node5 stay available (3 >= 3 threshold)
|
|
168
|
+
expect(nodeManager.getAvailableNodes()).toHaveLength(3);
|
|
169
|
+
const availableInitially = nodeManager
|
|
170
|
+
.getAvailableNodes()
|
|
171
|
+
.map(n => n.url)
|
|
172
|
+
.sort();
|
|
173
|
+
expect(availableInitially).toEqual(["node3", "node4", "node5"]);
|
|
174
|
+
// After 2 seconds, node1 recovers - should have 4 available
|
|
175
|
+
jest.advanceTimersByTime(2000);
|
|
176
|
+
expect(nodeManager.getAvailableNodes()).toHaveLength(4);
|
|
177
|
+
const availableAfter2s = nodeManager
|
|
178
|
+
.getAvailableNodes()
|
|
179
|
+
.map(n => n.url)
|
|
180
|
+
.sort();
|
|
181
|
+
expect(availableAfter2s).toEqual(["node1", "node3", "node4", "node5"]);
|
|
182
|
+
// After 5 seconds total, node2 recovers - should have all 5 available
|
|
183
|
+
jest.advanceTimersByTime(3000);
|
|
184
|
+
expect(nodeManager.getAvailableNodes()).toHaveLength(5);
|
|
185
|
+
});
|
|
186
|
+
it("should handle concurrent node failures with different recovery times", () => {
|
|
187
|
+
const nodeManager = createNodeManager({
|
|
188
|
+
nodeUrls: ["node1", "node2", "node3", "node4"],
|
|
189
|
+
unavailableDuration: 5000,
|
|
190
|
+
});
|
|
191
|
+
// Simulate different types of failures occurring at different times
|
|
192
|
+
nodeManager.makeNodeUnavailable("node1", 2000); // Quick recovery
|
|
193
|
+
jest.advanceTimersByTime(1000);
|
|
194
|
+
nodeManager.makeNodeUnavailable("node2", 5000); // Medium recovery
|
|
195
|
+
jest.advanceTimersByTime(1000);
|
|
196
|
+
nodeManager.makeNodeUnavailable("node3", 10000); // Slow recovery
|
|
197
|
+
// At this point (2 seconds from start):
|
|
198
|
+
// - node1 should be recovered
|
|
199
|
+
// - node2 still has 4 seconds left
|
|
200
|
+
// - node3 still has 8 seconds left
|
|
201
|
+
// - node4 was never made unavailable
|
|
202
|
+
const availableNodes = nodeManager.getAvailableNodes();
|
|
203
|
+
expect(availableNodes).toHaveLength(2);
|
|
204
|
+
const availableUrls = availableNodes.map(n => n.url).sort();
|
|
205
|
+
expect(availableUrls).toEqual(["node1", "node4"]);
|
|
206
|
+
});
|
|
207
|
+
});
|
|
208
|
+
describe("Timeout Precision and Edge Cases", () => {
|
|
209
|
+
it("should handle very short timeout durations precisely", () => {
|
|
210
|
+
const nodeManager = createNodeManager({
|
|
211
|
+
nodeUrls: ["node1"],
|
|
212
|
+
unavailableDuration: 5000,
|
|
213
|
+
});
|
|
214
|
+
nodeManager.makeNodeUnavailable("node1", 100); // 100ms timeout
|
|
215
|
+
expect(nodeManager.nodes[0].isAvailable()).toBe(false);
|
|
216
|
+
// Fast forward 99ms - should still be unavailable
|
|
217
|
+
jest.advanceTimersByTime(99);
|
|
218
|
+
expect(nodeManager.nodes[0].isAvailable()).toBe(false);
|
|
219
|
+
// Fast forward 1ms - should now be available
|
|
220
|
+
jest.advanceTimersByTime(1);
|
|
221
|
+
expect(nodeManager.nodes[0].isAvailable()).toBe(true);
|
|
222
|
+
});
|
|
223
|
+
it("should handle zero timeout duration", () => {
|
|
224
|
+
const nodeManager = createNodeManager({
|
|
225
|
+
nodeUrls: ["node1"],
|
|
226
|
+
unavailableDuration: 5000,
|
|
227
|
+
});
|
|
228
|
+
nodeManager.makeNodeUnavailable("node1", 0);
|
|
229
|
+
// Should be immediately available
|
|
230
|
+
expect(nodeManager.nodes[0].isAvailable()).toBe(true);
|
|
231
|
+
});
|
|
232
|
+
it("should handle negative timeout duration gracefully", () => {
|
|
233
|
+
const nodeManager = createNodeManager({
|
|
234
|
+
nodeUrls: ["node1"],
|
|
235
|
+
unavailableDuration: 5000,
|
|
236
|
+
});
|
|
237
|
+
nodeManager.makeNodeUnavailable("node1", -1000);
|
|
238
|
+
// Should be immediately available
|
|
239
|
+
expect(nodeManager.nodes[0].isAvailable()).toBe(true);
|
|
240
|
+
});
|
|
241
|
+
it("should maintain timeout state across multiple getAvailableNodes calls", () => {
|
|
242
|
+
const nodeManager = createNodeManager({
|
|
243
|
+
nodeUrls: ["node1", "node2"],
|
|
244
|
+
unavailableDuration: 5000,
|
|
245
|
+
});
|
|
246
|
+
nodeManager.makeNodeUnavailable("node1", 10000);
|
|
247
|
+
// Multiple calls should return consistent results
|
|
248
|
+
expect(nodeManager.getAvailableNodes()).toHaveLength(1);
|
|
249
|
+
expect(nodeManager.getAvailableNodes()).toHaveLength(1);
|
|
250
|
+
expect(nodeManager.getAvailableNodes()).toHaveLength(1);
|
|
251
|
+
// Fast forward time
|
|
252
|
+
jest.advanceTimersByTime(10000);
|
|
253
|
+
// Now all calls should show both nodes available
|
|
254
|
+
expect(nodeManager.getAvailableNodes()).toHaveLength(2);
|
|
255
|
+
expect(nodeManager.getAvailableNodes()).toHaveLength(2);
|
|
256
|
+
});
|
|
257
|
+
});
|
|
258
|
+
describe("Timeout Interaction with Recovery", () => {
|
|
259
|
+
it("should reset timeouts during universal recovery", () => {
|
|
260
|
+
const nodeUrls = ["node1", "node2", "node3", "node4"];
|
|
261
|
+
const nodeManager = createNodeManager({
|
|
262
|
+
nodeUrls,
|
|
263
|
+
unavailableDuration: 5000,
|
|
264
|
+
});
|
|
265
|
+
// Make nodes unavailable with long timeouts
|
|
266
|
+
nodeManager.makeNodeUnavailable("node1", 60000); // 1 minute
|
|
267
|
+
nodeManager.makeNodeUnavailable("node2", 60000); // 1 minute
|
|
268
|
+
nodeManager.makeNodeUnavailable("node3", 60000); // 1 minute
|
|
269
|
+
// This should trigger universal recovery, making all nodes available
|
|
270
|
+
const availableNodes = nodeManager.getAvailableNodes();
|
|
271
|
+
expect(availableNodes).toHaveLength(4);
|
|
272
|
+
// All nodes should be immediately available after recovery
|
|
273
|
+
nodeUrls.forEach(url => {
|
|
274
|
+
const node = nodeManager.nodes.find(n => n.url === url);
|
|
275
|
+
expect(node === null || node === void 0 ? void 0 : node.isAvailable()).toBe(true);
|
|
276
|
+
});
|
|
277
|
+
});
|
|
278
|
+
it("should handle timeout expiration during recovery process", () => {
|
|
279
|
+
const nodeUrls = ["node1", "node2", "node3"];
|
|
280
|
+
const nodeManager = createNodeManager({
|
|
281
|
+
nodeUrls,
|
|
282
|
+
unavailableDuration: 5000,
|
|
283
|
+
});
|
|
284
|
+
// Make 2 nodes unavailable with short timeouts
|
|
285
|
+
nodeManager.makeNodeUnavailable("node1", 1000);
|
|
286
|
+
nodeManager.makeNodeUnavailable("node2", 1000);
|
|
287
|
+
// Initially only 1 node available (below BFT threshold for 3 nodes)
|
|
288
|
+
expect(nodeManager.getAvailableNodes()).toHaveLength(3); // Recovery triggered
|
|
289
|
+
// Fast forward past original timeouts
|
|
290
|
+
jest.advanceTimersByTime(2000);
|
|
291
|
+
// Should still have all nodes available due to recovery
|
|
292
|
+
expect(nodeManager.getAvailableNodes()).toHaveLength(3);
|
|
293
|
+
});
|
|
294
|
+
});
|
|
295
|
+
});
|
|
296
|
+
//# sourceMappingURL=smartTimeouts.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"smartTimeouts.test.js","sourceRoot":"","sources":["../../../test/unit/smartTimeouts.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -32,13 +32,13 @@ describe("Sticky node feature", () => {
|
|
|
32
32
|
attemptInterval: 100,
|
|
33
33
|
unreachableDuration: 5000,
|
|
34
34
|
};
|
|
35
|
-
const
|
|
36
|
-
const failedResponse = { error: null, statusCode:
|
|
35
|
+
const successfulResponse = { error: null, statusCode: 200, rspBody: "" };
|
|
36
|
+
const failedResponse = { error: null, statusCode: 400, rspBody: "" };
|
|
37
37
|
it("should NOT retain a node when sticky node is disabled.", () => __awaiter(void 0, void 0, void 0, function* () {
|
|
38
38
|
mockHandleRequest
|
|
39
|
-
.mockResolvedValueOnce(
|
|
40
|
-
.mockResolvedValueOnce(
|
|
41
|
-
.mockResolvedValueOnce(
|
|
39
|
+
.mockResolvedValueOnce(successfulResponse)
|
|
40
|
+
.mockResolvedValueOnce(successfulResponse)
|
|
41
|
+
.mockResolvedValueOnce(successfulResponse);
|
|
42
42
|
const nodeManager = createNodeManager({
|
|
43
43
|
nodeUrls: endpointUrlPool,
|
|
44
44
|
useStickyNode: false,
|
|
@@ -49,7 +49,7 @@ describe("Sticky node feature", () => {
|
|
|
49
49
|
method: Method.GET,
|
|
50
50
|
path: "/path",
|
|
51
51
|
config: Object.assign(Object.assign({}, retryRequestConfig), { nodeManager }),
|
|
52
|
-
|
|
52
|
+
useNextNodeOnError: true,
|
|
53
53
|
});
|
|
54
54
|
}
|
|
55
55
|
const requestNodes = mockHandleRequest.mock.calls.map(call => call[2]);
|
|
@@ -57,9 +57,9 @@ describe("Sticky node feature", () => {
|
|
|
57
57
|
}));
|
|
58
58
|
it("should be possible to retain the same node in between requests.", () => __awaiter(void 0, void 0, void 0, function* () {
|
|
59
59
|
mockHandleRequest
|
|
60
|
-
.mockResolvedValueOnce(
|
|
61
|
-
.mockResolvedValueOnce(
|
|
62
|
-
.mockResolvedValueOnce(
|
|
60
|
+
.mockResolvedValueOnce(successfulResponse)
|
|
61
|
+
.mockResolvedValueOnce(successfulResponse)
|
|
62
|
+
.mockResolvedValueOnce(successfulResponse);
|
|
63
63
|
const nodeManager = createNodeManager({
|
|
64
64
|
nodeUrls: endpointUrlPool,
|
|
65
65
|
useStickyNode: true,
|
|
@@ -70,7 +70,7 @@ describe("Sticky node feature", () => {
|
|
|
70
70
|
method: Method.GET,
|
|
71
71
|
path: "/path",
|
|
72
72
|
config: Object.assign(Object.assign({}, retryRequestConfig), { nodeManager }),
|
|
73
|
-
|
|
73
|
+
useNextNodeOnError: true,
|
|
74
74
|
});
|
|
75
75
|
}
|
|
76
76
|
const selectedStickyNode = mockHandleRequest.mock.calls[0][2];
|
|
@@ -83,10 +83,10 @@ describe("Sticky node feature", () => {
|
|
|
83
83
|
.mockResolvedValueOnce(failedResponse)
|
|
84
84
|
.mockResolvedValueOnce(failedResponse)
|
|
85
85
|
.mockResolvedValueOnce(failedResponse)
|
|
86
|
-
.mockResolvedValueOnce(
|
|
86
|
+
.mockResolvedValueOnce(successfulResponse)
|
|
87
87
|
.mockResolvedValueOnce(failedResponse)
|
|
88
88
|
.mockResolvedValueOnce(failedResponse)
|
|
89
|
-
.mockResolvedValueOnce(
|
|
89
|
+
.mockResolvedValueOnce(successfulResponse);
|
|
90
90
|
const nodeManager = createNodeManager({
|
|
91
91
|
nodeUrls: endpointUrlPool,
|
|
92
92
|
useStickyNode: true,
|
|
@@ -97,7 +97,7 @@ describe("Sticky node feature", () => {
|
|
|
97
97
|
method: Method.GET,
|
|
98
98
|
path: "/path",
|
|
99
99
|
config: Object.assign(Object.assign({}, retryRequestConfig), { nodeManager }),
|
|
100
|
-
|
|
100
|
+
useNextNodeOnError: true,
|
|
101
101
|
});
|
|
102
102
|
}
|
|
103
103
|
const nodeOfRequest = mockHandleRequest.mock.calls.map(call => call[2]);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stickyNode.test.js","sourceRoot":"","sources":["../../../test/unit/stickyNode.test.ts"],"names":[],"mappings":";;;;;;;;;AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,EAAE,MAAM,kCAAkC,CAAC;AAC5E,OAAO,EAAE,YAAY,EAAE,MAAM,+CAA+C,CAAC;AAC7E,OAAO,EAAE,aAAa,EAAE,MAAM,qCAAqC,CAAC;AACpE,OAAO,EAAE,iBAAiB,EAAE,MAAM,wCAAwC,CAAC;AAC3E,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAE/C,IAAI,CAAC,IAAI,CAAC,qCAAqC,EAAE,GAAG,EAAE,CAAC,CAAC;IACtD,aAAa,EAAE,IAAI,CAAC,EAAE,EAAE;CACzB,CAAC,CAAC,CAAC;AAEJ,MAAM,iBAAiB,GAAG,aAA0B,CAAC;AAErD,QAAQ,CAAC,qBAAqB,EAAE,GAAG,EAAE;IACnC,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,CAAC,aAAa,EAAE,CAAC;QACrB,IAAI,CAAC,eAAe,EAAE,CAAC;IACzB,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,mBAAmB,EAAE,GAAG,EAAE;QACjC,MAAM,eAAe,GAAG,YAAY,CAAC;QAErC,MAAM,kBAAkB,GAAG;YACzB,YAAY,EAAE,eAAe,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,EAAE,GAAG,EAAE,aAAa,EAAE,CAAC,EAAE,CAAC,CAAC;YACrE,gBAAgB,EAAE,gBAAgB,CAAC,cAAc;YACjD,eAAe,EAAE,CAAC;YAClB,kBAAkB,EAAE,CAAC;YACrB,mBAAmB,EAAE,CAAC;YACtB,eAAe,EAAE,GAAG;YACpB,mBAAmB,EAAE,IAAI;SAC1B,CAAC;QACF,MAAM,
|
|
1
|
+
{"version":3,"file":"stickyNode.test.js","sourceRoot":"","sources":["../../../test/unit/stickyNode.test.ts"],"names":[],"mappings":";;;;;;;;;AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,EAAE,MAAM,kCAAkC,CAAC;AAC5E,OAAO,EAAE,YAAY,EAAE,MAAM,+CAA+C,CAAC;AAC7E,OAAO,EAAE,aAAa,EAAE,MAAM,qCAAqC,CAAC;AACpE,OAAO,EAAE,iBAAiB,EAAE,MAAM,wCAAwC,CAAC;AAC3E,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAE/C,IAAI,CAAC,IAAI,CAAC,qCAAqC,EAAE,GAAG,EAAE,CAAC,CAAC;IACtD,aAAa,EAAE,IAAI,CAAC,EAAE,EAAE;CACzB,CAAC,CAAC,CAAC;AAEJ,MAAM,iBAAiB,GAAG,aAA0B,CAAC;AAErD,QAAQ,CAAC,qBAAqB,EAAE,GAAG,EAAE;IACnC,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,CAAC,aAAa,EAAE,CAAC;QACrB,IAAI,CAAC,eAAe,EAAE,CAAC;IACzB,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,mBAAmB,EAAE,GAAG,EAAE;QACjC,MAAM,eAAe,GAAG,YAAY,CAAC;QAErC,MAAM,kBAAkB,GAAG;YACzB,YAAY,EAAE,eAAe,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,EAAE,GAAG,EAAE,aAAa,EAAE,CAAC,EAAE,CAAC,CAAC;YACrE,gBAAgB,EAAE,gBAAgB,CAAC,cAAc;YACjD,eAAe,EAAE,CAAC;YAClB,kBAAkB,EAAE,CAAC;YACrB,mBAAmB,EAAE,CAAC;YACtB,eAAe,EAAE,GAAG;YACpB,mBAAmB,EAAE,IAAI;SAC1B,CAAC;QACF,MAAM,kBAAkB,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,UAAU,EAAE,GAAG,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC;QACzE,MAAM,cAAc,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,UAAU,EAAE,GAAG,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC;QAErE,EAAE,CAAC,wDAAwD,EAAE,GAAS,EAAE;YACtE,iBAAiB;iBACd,qBAAqB,CAAC,kBAAkB,CAAC;iBACzC,qBAAqB,CAAC,kBAAkB,CAAC;iBACzC,qBAAqB,CAAC,kBAAkB,CAAC,CAAC;YAE7C,MAAM,WAAW,GAAG,iBAAiB,CAAC;gBACpC,QAAQ,EAAE,eAAe;gBACzB,aAAa,EAAE,KAAK;gBACpB,mBAAmB,EAAE,IAAI;aAC1B,CAAC,CAAC;YAEH,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;gBAC3B,MAAM,YAAY,CAAC;oBACjB,MAAM,EAAE,MAAM,CAAC,GAAG;oBAClB,IAAI,EAAE,OAAO;oBACb,MAAM,kCACD,kBAAkB,KACrB,WAAW,GACZ;oBACD,kBAAkB,EAAE,IAAI;iBACzB,CAAC,CAAC;YACL,CAAC;YAED,MAAM,YAAY,GAAG,iBAAiB,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;YAEvE,MAAM,CAAC,YAAY,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,KAAK,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC3E,CAAC,CAAA,CAAC,CAAC;QAEH,EAAE,CAAC,iEAAiE,EAAE,GAAS,EAAE;YAC/E,iBAAiB;iBACd,qBAAqB,CAAC,kBAAkB,CAAC;iBACzC,qBAAqB,CAAC,kBAAkB,CAAC;iBACzC,qBAAqB,CAAC,kBAAkB,CAAC,CAAC;YAE7C,MAAM,WAAW,GAAG,iBAAiB,CAAC;gBACpC,QAAQ,EAAE,eAAe;gBACzB,aAAa,EAAE,IAAI;gBACnB,mBAAmB,EAAE,IAAI;aAC1B,CAAC,CAAC;YAEH,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;gBAC3B,MAAM,YAAY,CAAC;oBACjB,MAAM,EAAE,MAAM,CAAC,GAAG;oBAClB,IAAI,EAAE,OAAO;oBACb,MAAM,kCACD,kBAAkB,KACrB,WAAW,GACZ;oBACD,kBAAkB,EAAE,IAAI;iBACzB,CAAC,CAAC;YACL,CAAC;YAED,MAAM,kBAAkB,GAAG,iBAAiB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YAE9D,MAAM,CAAC,iBAAiB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC;YACpE,MAAM,CAAC,iBAAiB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC;YACpE,MAAM,CAAC,iBAAiB,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC;QACrD,CAAC,CAAA,CAAC,CAAC;QAEH,EAAE,CAAC,0DAA0D,EAAE,GAAS,EAAE;YACxE,iBAAiB;iBACd,qBAAqB,CAAC,cAAc,CAAC;iBACrC,qBAAqB,CAAC,cAAc,CAAC;iBACrC,qBAAqB,CAAC,cAAc,CAAC;iBACrC,qBAAqB,CAAC,kBAAkB,CAAC;iBACzC,qBAAqB,CAAC,cAAc,CAAC;iBACrC,qBAAqB,CAAC,cAAc,CAAC;iBACrC,qBAAqB,CAAC,kBAAkB,CAAC,CAAC;YAE7C,MAAM,WAAW,GAAG,iBAAiB,CAAC;gBACpC,QAAQ,EAAE,eAAe;gBACzB,aAAa,EAAE,IAAI;gBACnB,mBAAmB,EAAE,IAAI;aAC1B,CAAC,CAAC;YAEH,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;gBAC3B,MAAM,YAAY,CAAC;oBACjB,MAAM,EAAE,MAAM,CAAC,GAAG;oBAClB,IAAI,EAAE,OAAO;oBACb,MAAM,kCACD,kBAAkB,KACrB,WAAW,GACZ;oBACD,kBAAkB,EAAE,IAAI;iBACzB,CAAC,CAAC;YACL,CAAC;YAED,MAAM,aAAa,GAAa,iBAAiB,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;YAElF,MAAM,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,6EAA6E;YAC9H,MAAM,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,qEAAqE;YAC1H,MAAM,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,mFAAmF;YACpI,MAAM,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,oEAAoE;YACrH,MAAM,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,0EAA0E;YAC3H,MAAM,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,+CAA+C;YACpG,MAAM,CAAC,iBAAiB,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC;QACrD,CAAC,CAAA,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|