@olane/o-node 0.7.12-alpha.3 → 0.7.12-alpha.30

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 (254) hide show
  1. package/dist/o-core/src/connection/o-response.d.ts +12 -0
  2. package/dist/o-core/src/connection/o-response.d.ts.map +1 -0
  3. package/dist/o-core/src/connection/o-response.js +18 -0
  4. package/dist/o-core/src/error/enums/codes.error.d.ts +20 -0
  5. package/dist/o-core/src/error/enums/codes.error.d.ts.map +1 -0
  6. package/dist/o-core/src/error/enums/codes.error.js +20 -0
  7. package/dist/o-core/src/error/interfaces/o-error.interface.d.ts +6 -0
  8. package/dist/o-core/src/error/interfaces/o-error.interface.d.ts.map +1 -0
  9. package/dist/o-core/src/error/interfaces/o-error.interface.js +1 -0
  10. package/dist/o-core/src/error/o-error.d.ts +15 -0
  11. package/dist/o-core/src/error/o-error.d.ts.map +1 -0
  12. package/dist/o-core/src/error/o-error.js +27 -0
  13. package/dist/o-core/src/streaming/index.d.ts +11 -0
  14. package/dist/o-core/src/streaming/index.d.ts.map +1 -0
  15. package/dist/o-core/src/streaming/index.js +14 -0
  16. package/dist/o-core/src/streaming/protocol-builder.d.ts +62 -0
  17. package/dist/o-core/src/streaming/protocol-builder.d.ts.map +1 -0
  18. package/dist/o-core/src/streaming/protocol-builder.js +93 -0
  19. package/dist/o-core/src/streaming/stream-config.d.ts +36 -0
  20. package/dist/o-core/src/streaming/stream-config.d.ts.map +1 -0
  21. package/dist/o-core/src/streaming/stream-config.js +19 -0
  22. package/dist/o-core/src/streaming/stream-handler.base.d.ts +85 -0
  23. package/dist/o-core/src/streaming/stream-handler.base.d.ts.map +1 -0
  24. package/dist/o-core/src/streaming/stream-handler.base.js +112 -0
  25. package/dist/o-core/src/streaming/stream-transport.interface.d.ts +61 -0
  26. package/dist/o-core/src/streaming/stream-transport.interface.d.ts.map +1 -0
  27. package/dist/o-core/src/streaming/stream-transport.interface.js +10 -0
  28. package/dist/o-core/src/utils/streaming.utils.d.ts +22 -0
  29. package/dist/o-core/src/utils/streaming.utils.d.ts.map +1 -0
  30. package/dist/o-core/src/utils/streaming.utils.js +45 -0
  31. package/dist/o-node/src/connection/index.d.ts +5 -0
  32. package/dist/o-node/src/connection/index.d.ts.map +1 -0
  33. package/dist/o-node/src/connection/index.js +4 -0
  34. package/dist/o-node/src/connection/interfaces/o-node-connection-manager.config.d.ts +6 -0
  35. package/dist/o-node/src/connection/interfaces/o-node-connection-manager.config.d.ts.map +1 -0
  36. package/dist/o-node/src/connection/interfaces/o-node-connection-manager.config.js +1 -0
  37. package/dist/o-node/src/connection/interfaces/o-node-connection.config.d.ts +6 -0
  38. package/dist/o-node/src/connection/interfaces/o-node-connection.config.d.ts.map +1 -0
  39. package/dist/o-node/src/connection/interfaces/o-node-connection.config.js +1 -0
  40. package/dist/o-node/src/connection/o-node-connection.d.ts +13 -0
  41. package/dist/o-node/src/connection/o-node-connection.d.ts.map +1 -0
  42. package/dist/o-node/src/connection/o-node-connection.js +80 -0
  43. package/dist/o-node/src/connection/o-node-connection.manager.d.ts +19 -0
  44. package/dist/o-node/src/connection/o-node-connection.manager.d.ts.map +1 -0
  45. package/dist/o-node/src/connection/o-node-connection.manager.js +93 -0
  46. package/dist/o-node/src/connection/o-stream.request.d.ts +11 -0
  47. package/dist/o-node/src/connection/o-stream.request.d.ts.map +1 -0
  48. package/dist/o-node/src/connection/o-stream.request.js +7 -0
  49. package/dist/o-node/src/index.d.ts +11 -0
  50. package/dist/o-node/src/index.d.ts.map +1 -0
  51. package/dist/o-node/src/index.js +10 -0
  52. package/dist/o-node/src/interfaces/i-heartbeatable-node.d.ts +49 -0
  53. package/dist/o-node/src/interfaces/i-heartbeatable-node.d.ts.map +1 -0
  54. package/dist/o-node/src/interfaces/i-heartbeatable-node.js +1 -0
  55. package/dist/o-node/src/interfaces/i-reconnectable-node.d.ts +46 -0
  56. package/dist/o-node/src/interfaces/i-reconnectable-node.d.ts.map +1 -0
  57. package/dist/o-node/src/interfaces/i-reconnectable-node.js +1 -0
  58. package/dist/o-node/src/interfaces/o-node.config.d.ts +66 -0
  59. package/dist/o-node/src/interfaces/o-node.config.d.ts.map +1 -0
  60. package/dist/o-node/src/interfaces/o-node.config.js +1 -0
  61. package/dist/o-node/src/interfaces/o-node.tool-config.d.ts +4 -0
  62. package/dist/o-node/src/interfaces/o-node.tool-config.d.ts.map +1 -0
  63. package/dist/o-node/src/interfaces/o-node.tool-config.js +1 -0
  64. package/dist/o-node/src/lib/network-activity.lib.d.ts +1 -0
  65. package/dist/o-node/src/lib/network-activity.lib.d.ts.map +1 -0
  66. package/dist/o-node/src/lib/network-activity.lib.js +34 -0
  67. package/dist/o-node/src/managers/o-connection-heartbeat.manager.d.ts +62 -0
  68. package/dist/o-node/src/managers/o-connection-heartbeat.manager.d.ts.map +1 -0
  69. package/dist/o-node/src/managers/o-connection-heartbeat.manager.js +213 -0
  70. package/dist/o-node/src/managers/o-reconnection.manager.d.ts +51 -0
  71. package/dist/o-node/src/managers/o-reconnection.manager.d.ts.map +1 -0
  72. package/dist/o-node/src/managers/o-reconnection.manager.js +266 -0
  73. package/dist/o-node/src/nodes/client.node.d.ts +7 -0
  74. package/dist/o-node/src/nodes/client.node.d.ts.map +1 -0
  75. package/dist/o-node/src/nodes/client.node.js +16 -0
  76. package/dist/o-node/src/nodes/index.d.ts +4 -0
  77. package/dist/o-node/src/nodes/index.d.ts.map +1 -0
  78. package/dist/o-node/src/nodes/index.js +3 -0
  79. package/dist/o-node/src/nodes/server.node.d.ts +7 -0
  80. package/dist/o-node/src/nodes/server.node.d.ts.map +1 -0
  81. package/dist/o-node/src/nodes/server.node.js +20 -0
  82. package/dist/o-node/src/nodes/websocket.node.d.ts +7 -0
  83. package/dist/o-node/src/nodes/websocket.node.d.ts.map +1 -0
  84. package/dist/o-node/src/nodes/websocket.node.js +18 -0
  85. package/dist/o-node/src/o-node.d.ts +73 -0
  86. package/dist/o-node/src/o-node.d.ts.map +1 -0
  87. package/dist/o-node/src/o-node.hierarchy-manager.d.ts +15 -0
  88. package/dist/o-node/src/o-node.hierarchy-manager.d.ts.map +1 -0
  89. package/dist/o-node/src/o-node.hierarchy-manager.js +15 -0
  90. package/dist/o-node/src/o-node.js +414 -0
  91. package/dist/o-node/src/o-node.notification-manager.d.ts +52 -0
  92. package/dist/o-node/src/o-node.notification-manager.d.ts.map +1 -0
  93. package/dist/o-node/src/o-node.notification-manager.js +185 -0
  94. package/dist/o-node/src/o-node.tool.d.ts +18 -0
  95. package/dist/o-node/src/o-node.tool.d.ts.map +1 -0
  96. package/dist/o-node/src/o-node.tool.js +90 -0
  97. package/dist/o-node/src/router/index.d.ts +6 -0
  98. package/dist/o-node/src/router/index.d.ts.map +1 -0
  99. package/dist/o-node/src/router/index.js +5 -0
  100. package/dist/o-node/src/router/interfaces/o-node-router.config.d.ts +3 -0
  101. package/dist/o-node/src/router/interfaces/o-node-router.config.d.ts.map +1 -0
  102. package/dist/o-node/src/router/interfaces/o-node-router.config.js +1 -0
  103. package/dist/o-node/src/router/interfaces/o-node-router.response.d.ts +8 -0
  104. package/dist/o-node/src/router/interfaces/o-node-router.response.d.ts.map +1 -0
  105. package/dist/o-node/src/router/interfaces/o-node-router.response.js +1 -0
  106. package/dist/o-node/src/router/o-node.address.d.ts +18 -0
  107. package/dist/o-node/src/router/o-node.address.d.ts.map +1 -0
  108. package/dist/o-node/src/router/o-node.address.js +29 -0
  109. package/dist/o-node/src/router/o-node.router.d.ts +45 -0
  110. package/dist/o-node/src/router/o-node.router.d.ts.map +1 -0
  111. package/dist/o-node/src/router/o-node.router.js +135 -0
  112. package/dist/o-node/src/router/o-node.routing-policy.d.ts +30 -0
  113. package/dist/o-node/src/router/o-node.routing-policy.d.ts.map +1 -0
  114. package/dist/o-node/src/router/o-node.routing-policy.js +57 -0
  115. package/dist/o-node/src/router/o-node.transport.d.ts +11 -0
  116. package/dist/o-node/src/router/o-node.transport.d.ts.map +1 -0
  117. package/dist/o-node/src/router/o-node.transport.js +18 -0
  118. package/dist/o-node/src/router/resolvers/index.d.ts +4 -0
  119. package/dist/o-node/src/router/resolvers/index.d.ts.map +1 -0
  120. package/dist/o-node/src/router/resolvers/index.js +3 -0
  121. package/dist/o-node/src/router/resolvers/o-node.leader-resolver-fallback.d.ts +8 -0
  122. package/dist/o-node/src/router/resolvers/o-node.leader-resolver-fallback.d.ts.map +1 -0
  123. package/dist/o-node/src/router/resolvers/o-node.leader-resolver-fallback.js +35 -0
  124. package/dist/{src/router/resolvers/o-node.child-resolver.d.ts → o-node/src/router/resolvers/o-node.resolver.d.ts} +2 -2
  125. package/dist/o-node/src/router/resolvers/o-node.resolver.d.ts.map +1 -0
  126. package/dist/o-node/src/router/resolvers/o-node.resolver.js +41 -0
  127. package/dist/o-node/src/router/resolvers/o-node.search-resolver.d.ts +170 -0
  128. package/dist/o-node/src/router/resolvers/o-node.search-resolver.d.ts.map +1 -0
  129. package/dist/o-node/src/router/resolvers/o-node.search-resolver.js +285 -0
  130. package/dist/o-node/src/router/route.request.d.ts +14 -0
  131. package/dist/o-node/src/router/route.request.d.ts.map +1 -0
  132. package/dist/o-node/src/router/route.request.js +1 -0
  133. package/dist/o-node/src/streaming/index.d.ts +10 -0
  134. package/dist/o-node/src/streaming/index.d.ts.map +1 -0
  135. package/dist/o-node/src/streaming/index.js +12 -0
  136. package/dist/o-node/src/streaming/libp2p-stream-transport.d.ts +50 -0
  137. package/dist/o-node/src/streaming/libp2p-stream-transport.d.ts.map +1 -0
  138. package/dist/o-node/src/streaming/libp2p-stream-transport.js +137 -0
  139. package/dist/o-node/src/streaming/node-stream-handler.d.ts +65 -0
  140. package/dist/o-node/src/streaming/node-stream-handler.d.ts.map +1 -0
  141. package/dist/o-node/src/streaming/node-stream-handler.js +101 -0
  142. package/dist/o-node/src/utils/circuit-breaker.d.ts +107 -0
  143. package/dist/o-node/src/utils/circuit-breaker.d.ts.map +1 -0
  144. package/dist/o-node/src/utils/circuit-breaker.js +175 -0
  145. package/dist/o-node/src/utils/index.d.ts +5 -0
  146. package/dist/o-node/src/utils/index.d.ts.map +1 -0
  147. package/dist/o-node/src/utils/index.js +4 -0
  148. package/dist/o-node/src/utils/leader-request-wrapper.d.ts +66 -0
  149. package/dist/o-node/src/utils/leader-request-wrapper.d.ts.map +1 -0
  150. package/dist/o-node/src/utils/leader-request-wrapper.js +160 -0
  151. package/dist/o-node/src/utils/network.utils.d.ts +20 -0
  152. package/dist/o-node/src/utils/network.utils.d.ts.map +1 -0
  153. package/dist/o-node/src/utils/network.utils.js +74 -0
  154. package/dist/o-node/src/utils/stream.utils.d.ts +6 -0
  155. package/dist/o-node/src/utils/stream.utils.d.ts.map +1 -0
  156. package/dist/o-node/src/utils/stream.utils.js +27 -0
  157. package/dist/o-node/test/circuit-breaker.test.d.ts +2 -0
  158. package/dist/o-node/test/circuit-breaker.test.d.ts.map +1 -0
  159. package/dist/o-node/test/circuit-breaker.test.js +262 -0
  160. package/dist/o-node/test/leader-request-wrapper.test.d.ts +1 -0
  161. package/dist/o-node/test/leader-request-wrapper.test.d.ts.map +1 -0
  162. package/dist/o-node/test/leader-request-wrapper.test.js +246 -0
  163. package/dist/o-node/test/o-node.spec.d.ts +2 -0
  164. package/dist/o-node/test/o-node.spec.d.ts.map +1 -0
  165. package/dist/o-node/test/o-node.spec.js +20 -0
  166. package/dist/o-node/test/search-resolver.spec.d.ts +2 -0
  167. package/dist/o-node/test/search-resolver.spec.d.ts.map +1 -0
  168. package/dist/o-node/test/search-resolver.spec.js +693 -0
  169. package/dist/src/connection/o-node-connection.d.ts +1 -2
  170. package/dist/src/connection/o-node-connection.d.ts.map +1 -1
  171. package/dist/src/connection/o-node-connection.js +25 -18
  172. package/dist/src/connection/o-node-connection.manager.d.ts +3 -1
  173. package/dist/src/connection/o-node-connection.manager.d.ts.map +1 -1
  174. package/dist/src/connection/o-node-connection.manager.js +45 -20
  175. package/dist/src/connection/o-stream.request.d.ts +11 -0
  176. package/dist/src/connection/o-stream.request.d.ts.map +1 -0
  177. package/dist/src/connection/o-stream.request.js +7 -0
  178. package/dist/src/index.d.ts +2 -1
  179. package/dist/src/index.d.ts.map +1 -1
  180. package/dist/src/index.js +2 -1
  181. package/dist/src/interfaces/i-heartbeatable-node.d.ts +49 -0
  182. package/dist/src/interfaces/i-heartbeatable-node.d.ts.map +1 -0
  183. package/dist/src/interfaces/i-heartbeatable-node.js +1 -0
  184. package/dist/src/interfaces/i-reconnectable-node.d.ts +46 -0
  185. package/dist/src/interfaces/i-reconnectable-node.d.ts.map +1 -0
  186. package/dist/src/interfaces/i-reconnectable-node.js +1 -0
  187. package/dist/src/interfaces/o-node.config.d.ts +42 -0
  188. package/dist/src/interfaces/o-node.config.d.ts.map +1 -1
  189. package/dist/src/managers/o-connection-heartbeat.manager.d.ts +62 -0
  190. package/dist/src/managers/o-connection-heartbeat.manager.d.ts.map +1 -0
  191. package/dist/src/managers/o-connection-heartbeat.manager.js +213 -0
  192. package/dist/src/managers/o-reconnection.manager.d.ts +51 -0
  193. package/dist/src/managers/o-reconnection.manager.d.ts.map +1 -0
  194. package/dist/src/managers/o-reconnection.manager.js +266 -0
  195. package/dist/src/o-node.d.ts +20 -2
  196. package/dist/src/o-node.d.ts.map +1 -1
  197. package/dist/src/o-node.js +161 -32
  198. package/dist/src/o-node.notification-manager.d.ts +52 -0
  199. package/dist/src/o-node.notification-manager.d.ts.map +1 -0
  200. package/dist/src/o-node.notification-manager.js +185 -0
  201. package/dist/src/o-node.tool.d.ts.map +1 -1
  202. package/dist/src/o-node.tool.js +29 -22
  203. package/dist/src/router/o-node.router.d.ts +1 -0
  204. package/dist/src/router/o-node.router.d.ts.map +1 -1
  205. package/dist/src/router/o-node.router.js +61 -5
  206. package/dist/src/router/o-node.routing-policy.d.ts.map +1 -1
  207. package/dist/src/router/o-node.routing-policy.js +7 -2
  208. package/dist/src/router/resolvers/o-node.resolver.d.ts.map +1 -1
  209. package/dist/src/router/resolvers/o-node.resolver.js +5 -1
  210. package/dist/src/router/resolvers/o-node.search-resolver.d.ts.map +1 -1
  211. package/dist/src/router/resolvers/o-node.search-resolver.js +40 -10
  212. package/dist/src/streaming/index.d.ts +10 -0
  213. package/dist/src/streaming/index.d.ts.map +1 -0
  214. package/dist/src/streaming/index.js +12 -0
  215. package/dist/src/streaming/libp2p-stream-transport.d.ts +50 -0
  216. package/dist/src/streaming/libp2p-stream-transport.d.ts.map +1 -0
  217. package/dist/src/streaming/libp2p-stream-transport.js +137 -0
  218. package/dist/src/streaming/node-stream-handler.d.ts +65 -0
  219. package/dist/src/streaming/node-stream-handler.d.ts.map +1 -0
  220. package/dist/src/streaming/node-stream-handler.js +101 -0
  221. package/dist/src/streaming/o-node-streaming-client.d.ts +33 -0
  222. package/dist/src/streaming/o-node-streaming-client.d.ts.map +1 -0
  223. package/dist/src/streaming/o-node-streaming-client.js +130 -0
  224. package/dist/src/utils/circuit-breaker.d.ts +107 -0
  225. package/dist/src/utils/circuit-breaker.d.ts.map +1 -0
  226. package/dist/src/utils/circuit-breaker.js +175 -0
  227. package/dist/src/utils/circuit-breaker.test.d.ts +2 -0
  228. package/dist/src/utils/circuit-breaker.test.d.ts.map +1 -0
  229. package/dist/src/utils/circuit-breaker.test.js +262 -0
  230. package/dist/src/utils/index.d.ts +3 -0
  231. package/dist/src/utils/index.d.ts.map +1 -0
  232. package/dist/src/utils/index.js +2 -0
  233. package/dist/src/utils/leader-request-wrapper.d.ts +66 -0
  234. package/dist/src/utils/leader-request-wrapper.d.ts.map +1 -0
  235. package/dist/src/utils/leader-request-wrapper.js +160 -0
  236. package/dist/src/utils/leader-request-wrapper.test.d.ts +1 -0
  237. package/dist/src/utils/leader-request-wrapper.test.d.ts.map +1 -0
  238. package/dist/src/utils/leader-request-wrapper.test.js +246 -0
  239. package/dist/src/utils/stream.utils.d.ts +6 -0
  240. package/dist/src/utils/stream.utils.d.ts.map +1 -0
  241. package/dist/src/utils/stream.utils.js +31 -0
  242. package/dist/test/circuit-breaker.test.d.ts +2 -0
  243. package/dist/test/circuit-breaker.test.d.ts.map +1 -0
  244. package/dist/test/circuit-breaker.test.js +262 -0
  245. package/dist/test/helpers/test-node.tool.d.ts +15 -0
  246. package/dist/test/helpers/test-node.tool.d.ts.map +1 -0
  247. package/dist/test/helpers/test-node.tool.js +27 -0
  248. package/dist/test/leader-request-wrapper.test.d.ts +1 -0
  249. package/dist/test/leader-request-wrapper.test.d.ts.map +1 -0
  250. package/dist/test/leader-request-wrapper.test.js +246 -0
  251. package/dist/test/search-resolver.spec.js +79 -0
  252. package/package.json +6 -6
  253. package/dist/src/router/resolvers/o-node.child-resolver.d.ts.map +0 -1
  254. package/dist/src/router/resolvers/o-node.child-resolver.js +0 -58
@@ -0,0 +1,246 @@
1
+ "use strict";
2
+ // import { expect } from 'chai';
3
+ // import { LeaderRequestWrapper } from './leader-request-wrapper.js';
4
+ // import { oAddress } from '@olane/o-core';
5
+ // import { CircuitState } from './circuit-breaker.js';
6
+ // describe('LeaderRequestWrapper with Circuit Breaker', () => {
7
+ // let wrapper: LeaderRequestWrapper;
8
+ // const leaderAddress = new oAddress('o://leader');
9
+ // const registryAddress = new oAddress('o://registry');
10
+ // const regularAddress = new oAddress('o://some-service');
11
+ // beforeEach(() => {
12
+ // wrapper = new LeaderRequestWrapper({
13
+ // enabled: true,
14
+ // maxAttempts: 5,
15
+ // baseDelayMs: 10,
16
+ // maxDelayMs: 100,
17
+ // timeoutMs: 1000,
18
+ // circuitBreaker: {
19
+ // enabled: true,
20
+ // failureThreshold: 3,
21
+ // openTimeoutMs: 500,
22
+ // halfOpenMaxAttempts: 1,
23
+ // },
24
+ // });
25
+ // });
26
+ // describe('Circuit Breaker Integration', () => {
27
+ // it('should execute request successfully and record success', async () => {
28
+ // const mockRequest = vi.fn().mockResolvedValue('success');
29
+ // const result = await wrapper.execute(mockRequest, leaderAddress);
30
+ // expect(result).toBe('success');
31
+ // expect(mockRequest).toHaveBeenCalledTimes(1);
32
+ // const stats = wrapper.getCircuitBreakerStats();
33
+ // expect(stats.leader.totalSuccesses).toBe(1);
34
+ // expect(stats.leader.state).toBe(CircuitState.CLOSED);
35
+ // });
36
+ // it('should record failures in circuit breaker', async () => {
37
+ // const mockRequest = vi.fn().mockRejectedValue(new Error('Service down'));
38
+ // await expect(
39
+ // wrapper.execute(mockRequest, leaderAddress),
40
+ // ).rejects.toThrow();
41
+ // const stats = wrapper.getCircuitBreakerStats();
42
+ // expect(stats.leader.totalFailures).toBeGreaterThan(0);
43
+ // expect(stats.leader.consecutiveFailures).toBeGreaterThan(0);
44
+ // });
45
+ // it('should open circuit after threshold failures', async () => {
46
+ // const mockRequest = vi.fn().mockRejectedValue(new Error('Service down'));
47
+ // // Attempt request multiple times to trigger circuit breaker
48
+ // await expect(
49
+ // wrapper.execute(mockRequest, leaderAddress),
50
+ // ).rejects.toThrow();
51
+ // const stats = wrapper.getCircuitBreakerStats();
52
+ // expect(stats.leader.state).toBe(CircuitState.OPEN);
53
+ // });
54
+ // it('should fast-fail when circuit is open', async () => {
55
+ // const mockRequest = vi.fn().mockRejectedValue(new Error('Service down'));
56
+ // // First request to open circuit
57
+ // await expect(
58
+ // wrapper.execute(mockRequest, leaderAddress),
59
+ // ).rejects.toThrow();
60
+ // // Reset mock to verify it's not called
61
+ // mockRequest.mockClear();
62
+ // // Second request should fast-fail
63
+ // await expect(wrapper.execute(mockRequest, leaderAddress)).rejects.toThrow(
64
+ // /Circuit breaker is OPEN/,
65
+ // );
66
+ // // Request function should not have been called
67
+ // expect(mockRequest).not.toHaveBeenCalled();
68
+ // });
69
+ // it('should stop retrying when circuit opens mid-retry', async () => {
70
+ // let callCount = 0;
71
+ // const mockRequest = vi.fn().mockImplementation(() => {
72
+ // callCount++;
73
+ // throw new Error('Service down');
74
+ // });
75
+ // await expect(
76
+ // wrapper.execute(mockRequest, leaderAddress),
77
+ // ).rejects.toThrow();
78
+ // // Should have stopped retrying after circuit opened
79
+ // expect(callCount).toBeLessThan(5); // Less than maxAttempts
80
+ // expect(callCount).toBeGreaterThanOrEqual(3); // At least threshold attempts
81
+ // });
82
+ // it('should track separate circuits for leader and registry', async () => {
83
+ // const failingRequest = vi
84
+ // .fn()
85
+ // .mockRejectedValue(new Error('Service down'));
86
+ // // Fail leader requests
87
+ // await expect(
88
+ // wrapper.execute(failingRequest, leaderAddress),
89
+ // ).rejects.toThrow();
90
+ // const stats = wrapper.getCircuitBreakerStats();
91
+ // expect(stats.leader.state).toBe(CircuitState.OPEN);
92
+ // expect(stats.registry.state).toBe(CircuitState.CLOSED);
93
+ // });
94
+ // it('should allow recovery after timeout in HALF_OPEN state', async () => {
95
+ // const mockRequest = vi
96
+ // .fn()
97
+ // .mockRejectedValueOnce(new Error('Service down'))
98
+ // .mockResolvedValue('recovered');
99
+ // // Open circuit
100
+ // await expect(
101
+ // wrapper.execute(mockRequest, leaderAddress),
102
+ // ).rejects.toThrow();
103
+ // expect(wrapper.getCircuitBreakerStats().leader.state).toBe(
104
+ // CircuitState.OPEN,
105
+ // );
106
+ // // Wait for circuit to attempt recovery
107
+ // await new Promise((resolve) => setTimeout(resolve, 600));
108
+ // // Should succeed and close circuit
109
+ // const result = await wrapper.execute(mockRequest, leaderAddress);
110
+ // expect(result).toBe('recovered');
111
+ // expect(wrapper.getCircuitBreakerStats().leader.state).toBe(
112
+ // CircuitState.CLOSED,
113
+ // );
114
+ // });
115
+ // });
116
+ // describe('Non-Leader Addresses', () => {
117
+ // it('should not use circuit breaker for non-leader addresses', async () => {
118
+ // const mockRequest = vi.fn().mockRejectedValue(new Error('Service down'));
119
+ // await expect(
120
+ // wrapper.execute(mockRequest, regularAddress),
121
+ // ).rejects.toThrow('Service down');
122
+ // // Should execute directly without retry
123
+ // expect(mockRequest).toHaveBeenCalledTimes(1);
124
+ // // Should not affect circuit breaker stats
125
+ // const stats = wrapper.getCircuitBreakerStats();
126
+ // expect(stats.leader.totalFailures).toBe(0);
127
+ // expect(stats.registry.totalFailures).toBe(0);
128
+ // });
129
+ // it('should execute successful requests directly', async () => {
130
+ // const mockRequest = vi.fn().mockResolvedValue('success');
131
+ // const result = await wrapper.execute(mockRequest, regularAddress);
132
+ // expect(result).toBe('success');
133
+ // expect(mockRequest).toHaveBeenCalledTimes(1);
134
+ // });
135
+ // });
136
+ // describe('Timeout Handling', () => {
137
+ // it('should timeout long-running requests', async () => {
138
+ // const longRequest = vi.fn().mockImplementation(
139
+ // () =>
140
+ // new Promise((resolve) => {
141
+ // setTimeout(() => resolve('too-late'), 2000);
142
+ // }),
143
+ // );
144
+ // await expect(wrapper.execute(longRequest, leaderAddress)).rejects.toThrow(
145
+ // /timeout/,
146
+ // );
147
+ // });
148
+ // it('should record timeout as failure in circuit breaker', async () => {
149
+ // const longRequest = vi.fn().mockImplementation(
150
+ // () =>
151
+ // new Promise((resolve) => {
152
+ // setTimeout(() => resolve('too-late'), 2000);
153
+ // }),
154
+ // );
155
+ // await expect(
156
+ // wrapper.execute(longRequest, leaderAddress),
157
+ // ).rejects.toThrow();
158
+ // const stats = wrapper.getCircuitBreakerStats();
159
+ // expect(stats.leader.totalFailures).toBeGreaterThan(0);
160
+ // });
161
+ // });
162
+ // describe('Configuration', () => {
163
+ // it('should bypass retry when disabled', async () => {
164
+ // const disabledWrapper = new LeaderRequestWrapper({
165
+ // enabled: false,
166
+ // maxAttempts: 5,
167
+ // baseDelayMs: 10,
168
+ // maxDelayMs: 100,
169
+ // timeoutMs: 1000,
170
+ // });
171
+ // const mockRequest = vi.fn().mockRejectedValue(new Error('Fail'));
172
+ // await expect(
173
+ // disabledWrapper.execute(mockRequest, leaderAddress),
174
+ // ).rejects.toThrow('Fail');
175
+ // // Should only call once (no retry)
176
+ // expect(mockRequest).toHaveBeenCalledTimes(1);
177
+ // });
178
+ // it('should allow circuit breaker to be disabled', async () => {
179
+ // const noBreakerWrapper = new LeaderRequestWrapper({
180
+ // enabled: true,
181
+ // maxAttempts: 3,
182
+ // baseDelayMs: 10,
183
+ // maxDelayMs: 100,
184
+ // timeoutMs: 1000,
185
+ // circuitBreaker: {
186
+ // enabled: false,
187
+ // failureThreshold: 3,
188
+ // openTimeoutMs: 500,
189
+ // halfOpenMaxAttempts: 1,
190
+ // },
191
+ // });
192
+ // let callCount = 0;
193
+ // const mockRequest = vi.fn().mockImplementation(() => {
194
+ // callCount++;
195
+ // throw new Error('Fail');
196
+ // });
197
+ // await expect(
198
+ // noBreakerWrapper.execute(mockRequest, leaderAddress),
199
+ // ).rejects.toThrow();
200
+ // // Should retry all attempts even with failures
201
+ // expect(callCount).toBe(3);
202
+ // });
203
+ // });
204
+ // describe('Manual Reset', () => {
205
+ // it('should reset circuit breakers manually', async () => {
206
+ // const mockRequest = vi.fn().mockRejectedValue(new Error('Service down'));
207
+ // // Open circuit
208
+ // await expect(
209
+ // wrapper.execute(mockRequest, leaderAddress),
210
+ // ).rejects.toThrow();
211
+ // expect(wrapper.getCircuitBreakerStats().leader.state).toBe(
212
+ // CircuitState.OPEN,
213
+ // );
214
+ // // Reset
215
+ // wrapper.resetCircuitBreakers();
216
+ // expect(wrapper.getCircuitBreakerStats().leader.state).toBe(
217
+ // CircuitState.CLOSED,
218
+ // );
219
+ // expect(wrapper.getCircuitBreakerStats().registry.state).toBe(
220
+ // CircuitState.CLOSED,
221
+ // );
222
+ // });
223
+ // });
224
+ // describe('Registry Address', () => {
225
+ // it('should use separate circuit breaker for registry', async () => {
226
+ // const mockRequest = vi.fn().mockRejectedValue(new Error('Registry down'));
227
+ // await expect(
228
+ // wrapper.execute(mockRequest, registryAddress),
229
+ // ).rejects.toThrow();
230
+ // const stats = wrapper.getCircuitBreakerStats();
231
+ // expect(stats.registry.totalFailures).toBeGreaterThan(0);
232
+ // expect(stats.registry.state).toBe(CircuitState.OPEN);
233
+ // expect(stats.leader.state).toBe(CircuitState.CLOSED);
234
+ // });
235
+ // });
236
+ // describe('Statistics', () => {
237
+ // it('should provide circuit breaker statistics', () => {
238
+ // const stats = wrapper.getCircuitBreakerStats();
239
+ // expect(stats).toHaveProperty('leader');
240
+ // expect(stats).toHaveProperty('registry');
241
+ // expect(stats.leader).toHaveProperty('state');
242
+ // expect(stats.leader).toHaveProperty('consecutiveFailures');
243
+ // expect(stats.registry).toHaveProperty('state');
244
+ // });
245
+ // });
246
+ // });
@@ -515,6 +515,85 @@ describe('oSearchResolver', () => {
515
515
  }
516
516
  });
517
517
  });
518
+ describe('Address duplication bug fix', () => {
519
+ it('should NOT duplicate path segments when registry returns full hierarchical address', async () => {
520
+ // This test verifies the fix for the bug where o://services/embeddings-text
521
+ // was being resolved to o://leader/services/embeddings-text/services/embeddings-text
522
+ const address = new oNodeAddress('o://services/embeddings-text');
523
+ mockNode.use = async () => createResponse({
524
+ data: [
525
+ {
526
+ address: 'o://leader/services/embeddings-text',
527
+ staticAddress: 'o://embeddings-text',
528
+ transports: [
529
+ {
530
+ value: '/ip4/127.0.0.1/tcp/6001',
531
+ type: TransportType.LIBP2P,
532
+ },
533
+ ],
534
+ },
535
+ ],
536
+ });
537
+ const result = await resolver.resolve({
538
+ address,
539
+ targetAddress: address,
540
+ node: mockNode,
541
+ request: createRouterRequest(),
542
+ });
543
+ // Should be o://leader/services/embeddings-text, NOT o://leader/services/embeddings-text/embeddings-text
544
+ expect(result.targetAddress.value).to.equal('o://leader/services/embeddings-text');
545
+ });
546
+ it('should NOT duplicate when calling via static address', async () => {
547
+ const address = new oNodeAddress('o://embeddings-text');
548
+ mockNode.use = async () => createResponse({
549
+ data: [
550
+ {
551
+ address: 'o://leader/services/embeddings-text',
552
+ staticAddress: 'o://embeddings-text',
553
+ transports: [
554
+ {
555
+ value: '/ip4/127.0.0.1/tcp/6001',
556
+ type: TransportType.LIBP2P,
557
+ },
558
+ ],
559
+ },
560
+ ],
561
+ });
562
+ const result = await resolver.resolve({
563
+ address,
564
+ targetAddress: address,
565
+ node: mockNode,
566
+ request: createRouterRequest(),
567
+ });
568
+ expect(result.targetAddress.value).to.equal('o://leader/services/embeddings-text');
569
+ });
570
+ it('should still append legitimate extra params beyond the service name', async () => {
571
+ // If someone calls o://embeddings-text/custom/path, we should preserve /custom/path
572
+ const address = new oNodeAddress('o://embeddings-text/custom/path');
573
+ mockNode.use = async () => createResponse({
574
+ data: [
575
+ {
576
+ address: 'o://leader/services/embeddings-text',
577
+ staticAddress: 'o://embeddings-text',
578
+ transports: [
579
+ {
580
+ value: '/ip4/127.0.0.1/tcp/6001',
581
+ type: TransportType.LIBP2P,
582
+ },
583
+ ],
584
+ },
585
+ ],
586
+ });
587
+ const result = await resolver.resolve({
588
+ address,
589
+ targetAddress: address,
590
+ node: mockNode,
591
+ request: createRouterRequest(),
592
+ });
593
+ // Should append the extra /custom/path
594
+ expect(result.targetAddress.value).to.equal('o://leader/services/embeddings-text/custom/path');
595
+ });
596
+ });
518
597
  describe('Edge cases', () => {
519
598
  it('should handle address with long nested paths', async () => {
520
599
  const address = new oNodeAddress('o://leader/a/b/c/d/e/f');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@olane/o-node",
3
- "version": "0.7.12-alpha.3",
3
+ "version": "0.7.12-alpha.30",
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.3",
58
- "@olane/o-core": "0.7.12-alpha.3",
59
- "@olane/o-protocol": "^0.7.12-alpha.3",
60
- "@olane/o-tool": "0.7.12-alpha.3",
57
+ "@olane/o-config": "0.7.12-alpha.30",
58
+ "@olane/o-core": "0.7.12-alpha.30",
59
+ "@olane/o-protocol": "0.7.12-alpha.30",
60
+ "@olane/o-tool": "0.7.12-alpha.30",
61
61
  "debug": "^4.4.1",
62
62
  "dotenv": "^16.5.0"
63
63
  },
64
- "gitHead": "5c05e5f248001abc38f34c77bd97c9a325231503"
64
+ "gitHead": "066e6bda19e79a744779a797664481476b0ea655"
65
65
  }
@@ -1 +0,0 @@
1
- {"version":3,"file":"o-node.child-resolver.d.ts","sourceRoot":"","sources":["../../../../src/router/resolvers/o-node.child-resolver.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,gBAAgB,EAEhB,aAAa,EAEd,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAEpD,OAAO,EAAE,mBAAmB,EAAE,MAAM,yCAAyC,CAAC;AAC9E,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAE/C,qBAAa,kBAAmB,SAAQ,gBAAgB;IAC1C,SAAS,CAAC,QAAQ,CAAC,OAAO,EAAE,YAAY;gBAArB,OAAO,EAAE,YAAY;IAIpD,IAAI,mBAAmB,IAAI,aAAa,EAAE,CAEzC;IAEK,OAAO,CAAC,YAAY,EAAE,cAAc,GAAG,OAAO,CAAC,mBAAmB,CAAC;CA4D1E"}
@@ -1,58 +0,0 @@
1
- import { oAddressResolver, TransportType, } from '@olane/o-core';
2
- export class oNodeChildResolver extends oAddressResolver {
3
- constructor(address) {
4
- super(address);
5
- this.address = address;
6
- }
7
- get supportedTransports() {
8
- return [TransportType.LIBP2P];
9
- }
10
- async resolve(routeRequest) {
11
- const { address, node, request } = routeRequest;
12
- if (!node) {
13
- return {
14
- nextHopAddress: address,
15
- targetAddress: address,
16
- requestOverride: request,
17
- };
18
- }
19
- // if we are the same address, return the address
20
- if (address.toStaticAddress().equals(node.address.toStaticAddress())) {
21
- return {
22
- nextHopAddress: node.address,
23
- targetAddress: node.address,
24
- requestOverride: request,
25
- };
26
- }
27
- // get the next node & check for child address existence
28
- const remainingPath = address.protocol.replace(node.address.protocol + '/', '');
29
- // ensure this is going down in the hierarchy
30
- if (remainingPath === address.protocol && node.isLeader === false) {
31
- return {
32
- nextHopAddress: node.address,
33
- targetAddress: address,
34
- requestOverride: request,
35
- };
36
- }
37
- // static resolver
38
- this.logger.debug(`[${node?.address}]: Next node: ${address.toString()}`);
39
- const childAddress = node?.hierarchyManager.getChild(address);
40
- this.logger.debug(`[${node?.address}]: Children: ${node?.hierarchyManager.children.map((c) => c.toString()).join(', ')}`);
41
- this.logger.debug(`[${node?.address}]: Resolving address: ${address.toString()} and child address: ${childAddress?.toString()}`);
42
- this.logger.debug('Child transports: ' +
43
- childAddress?.transports.map((t) => t.toString()).join(', '));
44
- // get the child address from hierarchy (which includes transports)
45
- if (childAddress) {
46
- return {
47
- nextHopAddress: childAddress,
48
- targetAddress: address,
49
- requestOverride: request,
50
- };
51
- }
52
- return {
53
- nextHopAddress: address,
54
- targetAddress: address,
55
- requestOverride: request,
56
- };
57
- }
58
- }