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

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
@@ -9,6 +9,9 @@ import { oNodeConnectionManager } from './connection/o-node-connection.manager.j
9
9
  import { oNodeResolver } from './router/resolvers/o-node.resolver.js';
10
10
  import { oMethodResolver, oToolBase } from '@olane/o-tool';
11
11
  import { oLeaderResolverFallback } from './router/index.js';
12
+ import { oNodeNotificationManager } from './o-node.notification-manager.js';
13
+ import { oConnectionHeartbeatManager } from './managers/o-connection-heartbeat.manager.js';
14
+ import { oReconnectionManager } from './managers/o-reconnection.manager.js';
12
15
  export class oNode extends oToolBase {
13
16
  constructor(config) {
14
17
  super(config);
@@ -43,6 +46,9 @@ export class oNode extends oToolBase {
43
46
  });
44
47
  this.router = new oNodeRouter();
45
48
  }
49
+ createNotificationManager() {
50
+ return new oNodeNotificationManager(this.p2pNode, this.hierarchyManager, this.address);
51
+ }
46
52
  get staticAddress() {
47
53
  return this.config.address;
48
54
  }
@@ -60,6 +66,30 @@ export class oNode extends oToolBase {
60
66
  this.logger.debug('Skipping unregistration, node is leader');
61
67
  return;
62
68
  }
69
+ // Notify parent we're stopping (best-effort, 2s timeout)
70
+ if (this.config.parent) {
71
+ try {
72
+ await Promise.race([
73
+ this.use(this.config.parent, {
74
+ method: 'notify',
75
+ params: {
76
+ eventType: 'node:stopping',
77
+ eventData: {
78
+ address: this.address.toString(),
79
+ reason: 'graceful_shutdown',
80
+ expectedDowntime: null,
81
+ },
82
+ source: this.address.toString(),
83
+ },
84
+ }),
85
+ new Promise((_, reject) => setTimeout(() => reject(new Error('timeout')), 2000)),
86
+ ]);
87
+ this.logger.debug('Notified parent of shutdown');
88
+ }
89
+ catch (error) {
90
+ this.logger.warn('Failed to notify parent (will be detected by heartbeat):', error instanceof Error ? error.message : error);
91
+ }
92
+ }
63
93
  if (!this.config.leader) {
64
94
  this.logger.debug('No leader found, skipping unregistration');
65
95
  return;
@@ -79,11 +109,21 @@ export class oNode extends oToolBase {
79
109
  this.logger.debug('Skipping parent registration, node is leader');
80
110
  return;
81
111
  }
112
+ if (!this.parent?.libp2pTransports?.length) {
113
+ this.logger.debug('Parent has no transports, waiting for reconnection & leader ack');
114
+ if (this.parent?.toString() === oAddress.leader().toString()) {
115
+ this.parent.setTransports(this.leader?.libp2pTransports || []);
116
+ }
117
+ else {
118
+ this.logger.debug('Waiting for parent and reconnecting...');
119
+ await this.reconnectionManager?.waitForParentAndReconnect();
120
+ }
121
+ }
82
122
  // if no parent transports, register with the parent to get them
83
123
  // TODO: should we remove the transports check to make this more consistent?
84
- if (this.config.parent && this.config.parent.transports.length === 0) {
85
- this.logger.debug('Registering node with parent...', this.config.parent);
86
- const parentRegistration = await this.use(this.config.parent, {
124
+ if (this.config.parent) {
125
+ this.logger.debug('Registering node with parent...', this.config.parent?.toString());
126
+ await this.use(this.config.parent, {
87
127
  method: 'child_register',
88
128
  params: {
89
129
  address: this.address.toString(),
@@ -92,11 +132,22 @@ export class oNode extends oToolBase {
92
132
  _token: this.config.joinToken,
93
133
  },
94
134
  });
95
- const { parentTransports } = parentRegistration.result.data;
96
- // update the parent transports
97
- this.config.parent.setTransports(parentTransports.map((t) => new oNodeTransport(t)));
98
135
  }
99
136
  }
137
+ async registerLeader() {
138
+ const address = oAddress.registry();
139
+ const params = {
140
+ method: 'commit',
141
+ params: {
142
+ peerId: this.peerId.toString(),
143
+ address: this.address.toString(),
144
+ protocols: this.p2pNode.getProtocols(),
145
+ transports: this.transports,
146
+ staticAddress: this.staticAddress.toString(),
147
+ },
148
+ };
149
+ await this.use(address, params);
150
+ }
100
151
  async register() {
101
152
  if (this.type === NodeType.LEADER) {
102
153
  this.logger.debug('Skipping registration, node is leader');
@@ -117,18 +168,7 @@ export class oNode extends oToolBase {
117
168
  this.logger.debug('Registering node with leader...');
118
169
  }
119
170
  await this.registerParent();
120
- const address = oAddress.registry();
121
- const params = {
122
- method: 'commit',
123
- params: {
124
- peerId: this.peerId.toString(),
125
- address: this.address.toString(),
126
- protocols: this.p2pNode.getProtocols(),
127
- transports: this.transports,
128
- staticAddress: this.staticAddress.toString(),
129
- },
130
- };
131
- await this.use(address, params);
171
+ await this.registerLeader();
132
172
  this.logger.debug('Registration successful');
133
173
  }
134
174
  extractMethod(address) {
@@ -136,11 +176,10 @@ export class oNode extends oToolBase {
136
176
  }
137
177
  async start() {
138
178
  await super.start();
139
- // await NetworkUtils.advertiseToNetwork(
140
- // this.address,
141
- // this.staticAddress,
142
- // this.p2pNode,
143
- // );
179
+ // Start heartbeat after node is running
180
+ if (this.connectionHeartbeatManager) {
181
+ await this.connectionHeartbeatManager.start();
182
+ }
144
183
  }
145
184
  async validateJoinRequest(request) {
146
185
  return true;
@@ -157,6 +196,7 @@ export class oNode extends oToolBase {
157
196
  listeners: (this.config.network?.listeners ||
158
197
  defaultLibp2pConfig.listeners ||
159
198
  []).concat(`/memory/${uuidv4()}`), // ensure we allow for local in-memory communication
199
+ prometheusRegistry: this.config.network?.prometheusRegistry,
160
200
  };
161
201
  // if the seed is provided, use it to generate the private key
162
202
  if (this.config.seed) {
@@ -190,12 +230,32 @@ export class oNode extends oToolBase {
190
230
  // ];
191
231
  // // let's make sure we only allow communication through the parent transports
192
232
  params.connectionGater = {
233
+ denyDialPeer: (peerId) => {
234
+ // we can call the leader
235
+ if (this.config.leader?.libp2pTransports.some((t) => t.toPeerId() === peerId.toString())) {
236
+ return false;
237
+ }
238
+ // we can call our parent
239
+ if (this.parentPeerId === peerId.toString()) {
240
+ return false;
241
+ }
242
+ // we can call our children
243
+ if (this.hierarchyManager.children.some((c) => c.libp2pTransports.some((t) => t.toPeerId() === peerId.toString()))) {
244
+ return false;
245
+ }
246
+ // check for standalone node
247
+ if (!this.config.parent && !this.config.leader) {
248
+ return false;
249
+ }
250
+ return true;
251
+ },
193
252
  // who can call us?
194
253
  denyInboundEncryptedConnection: (peerId, maConn) => {
195
254
  // deny all inbound connections unless they are from a parent transport
196
255
  if (this.parentPeerId === peerId.toString()) {
197
256
  return false;
198
257
  }
258
+ // allow connections from children (for ping)
199
259
  if (this.hierarchyManager.children.some((c) => c.libp2pTransports.some((t) => t.toPeerId() === peerId.toString()))) {
200
260
  return false;
201
261
  }
@@ -223,17 +283,13 @@ export class oNode extends oToolBase {
223
283
  this.p2pNode = await createNode(params);
224
284
  return this.p2pNode;
225
285
  }
226
- async connect(nextHopAddress, targetAddress) {
286
+ async connect(config) {
227
287
  if (!this.connectionManager) {
228
288
  this.logger.error('Connection manager not initialized');
229
289
  throw new Error('Node is not ready to connect to other nodes');
230
290
  }
231
291
  const connection = await this.connectionManager
232
- .connect({
233
- address: targetAddress,
234
- nextHopAddress,
235
- callerAddress: this.address,
236
- })
292
+ .connect(config)
237
293
  .catch((error) => {
238
294
  // TODO: we need to handle this better and document
239
295
  if (error.message === 'Can not dial self') {
@@ -246,6 +302,42 @@ export class oNode extends oToolBase {
246
302
  }
247
303
  return connection;
248
304
  }
305
+ async initConnectionManager() {
306
+ this.connectionManager = new oNodeConnectionManager({
307
+ p2pNode: this.p2pNode,
308
+ defaultReadTimeoutMs: this.config.connectionTimeouts?.readTimeoutMs,
309
+ defaultDrainTimeoutMs: this.config.connectionTimeouts?.drainTimeoutMs,
310
+ });
311
+ }
312
+ async initReconnectionManager() {
313
+ // Initialize reconnection manager
314
+ if (this.config.reconnection?.enabled !== false) {
315
+ this.reconnectionManager = new oReconnectionManager(this, {
316
+ enabled: true,
317
+ maxAttempts: this.config.reconnection?.maxAttempts ?? 10,
318
+ baseDelayMs: this.config.reconnection?.baseDelayMs ?? 5000,
319
+ maxDelayMs: this.config.reconnection?.maxDelayMs ?? 60000,
320
+ useLeaderFallback: this.config.reconnection?.useLeaderFallback ?? true,
321
+ parentDiscoveryIntervalMs: this.config.reconnection?.parentDiscoveryIntervalMs ?? 10000,
322
+ parentDiscoveryMaxDelayMs: this.config.reconnection?.parentDiscoveryMaxDelayMs ?? 60000,
323
+ });
324
+ }
325
+ }
326
+ async hookInitializeFinished() { }
327
+ async hookStartFinished() {
328
+ // Initialize connection heartbeat manager
329
+ this.connectionHeartbeatManager = new oConnectionHeartbeatManager(this, {
330
+ enabled: this.config.connectionHeartbeat?.enabled ?? true,
331
+ intervalMs: this.config.connectionHeartbeat?.intervalMs ?? 15000,
332
+ timeoutMs: this.config.connectionHeartbeat?.timeoutMs ?? 15000,
333
+ failureThreshold: this.config.connectionHeartbeat?.failureThreshold ?? 3,
334
+ checkChildren: this.config.connectionHeartbeat?.checkChildren ?? false,
335
+ checkParent: this.config.connectionHeartbeat?.checkParent ?? true,
336
+ checkLeader: true,
337
+ });
338
+ this.logger.info(`Connection heartbeat config: leader=${this.connectionHeartbeatManager.getConfig().checkLeader}, ` +
339
+ `parent=${this.connectionHeartbeatManager.getConfig().checkParent}`);
340
+ }
249
341
  async initialize() {
250
342
  this.logger.debug('Initializing node...');
251
343
  if (this.p2pNode && this.state !== NodeState.STOPPED) {
@@ -256,13 +348,13 @@ export class oNode extends oToolBase {
256
348
  }
257
349
  await this.createNode();
258
350
  await this.initializeRouter();
351
+ // need to wait until our libpp2 node is initialized before calling super.initialize
352
+ await super.initialize();
259
353
  this.logger.debug('Node initialized!', this.transports.map((t) => t.toString()));
260
354
  this.address.setTransports(this.transports);
261
355
  this.peerId = this.p2pNode.peerId;
262
356
  // initialize connection manager
263
- this.connectionManager = new oNodeConnectionManager({
264
- p2pNode: this.p2pNode,
265
- });
357
+ await this.initConnectionManager();
266
358
  // initialize address resolution
267
359
  this.router.addResolver(new oMethodResolver(this.address));
268
360
  this.router.addResolver(new oNodeResolver(this.address));
@@ -271,12 +363,49 @@ export class oNode extends oToolBase {
271
363
  this.logger.debug('Adding leader resolver fallback...');
272
364
  this.router.addResolver(new oLeaderResolverFallback(this.address));
273
365
  }
366
+ // initialize reconnection manager
367
+ await this.initReconnectionManager();
368
+ await this.hookInitializeFinished();
274
369
  }
370
+ /**
371
+ * Override use() to wrap leader/registry requests with retry logic
372
+ */
373
+ // async use(
374
+ // address: oAddress,
375
+ // data?: {
376
+ // method?: string;
377
+ // params?: { [key: string]: any };
378
+ // id?: string;
379
+ // },
380
+ // options?: UseOptions,
381
+ // ): Promise<any> {
382
+ // // Wrap leader/registry requests with retry logic
383
+ // return super.use(address, data, options),
384
+ // address,
385
+ // data?.method,
386
+ // }
275
387
  async teardown() {
388
+ // Stop heartbeat before parent teardown
389
+ if (this.connectionHeartbeatManager) {
390
+ await this.connectionHeartbeatManager.stop();
391
+ }
276
392
  await this.unregister();
277
393
  await super.teardown();
278
394
  if (this.p2pNode) {
279
395
  await this.p2pNode.stop();
280
396
  }
281
397
  }
398
+ // IHeartbeatableNode interface methods
399
+ getLeaders() {
400
+ return [this.leader];
401
+ }
402
+ getParents() {
403
+ return this.hierarchyManager.getParents();
404
+ }
405
+ getChildren() {
406
+ return this.hierarchyManager.getChildren();
407
+ }
408
+ removeChild(childAddress) {
409
+ this.hierarchyManager.removeChild(childAddress);
410
+ }
282
411
  }
@@ -0,0 +1,52 @@
1
+ import { Libp2p } from '@olane/o-config';
2
+ import { oNotificationManager } from '@olane/o-core';
3
+ import { oNodeAddress } from './router/o-node.address.js';
4
+ import { oNodeHierarchyManager } from './o-node.hierarchy-manager.js';
5
+ /**
6
+ * libp2p-specific implementation of oNotificationManager
7
+ * Wraps libp2p events and enriches them with Olane context
8
+ */
9
+ export declare class oNodeNotificationManager extends oNotificationManager {
10
+ private p2pNode;
11
+ private hierarchyManager;
12
+ private address;
13
+ constructor(p2pNode: Libp2p, hierarchyManager: oNodeHierarchyManager, address: oNodeAddress);
14
+ /**
15
+ * Wire up libp2p event listeners
16
+ */
17
+ protected setupListeners(): void;
18
+ /**
19
+ * Handle peer connect event from libp2p
20
+ */
21
+ private handlePeerConnect;
22
+ /**
23
+ * Handle peer disconnect event from libp2p
24
+ */
25
+ private handlePeerDisconnect;
26
+ /**
27
+ * Handle peer discovery event from libp2p
28
+ */
29
+ private handlePeerDiscovery;
30
+ /**
31
+ * Handle connection open event from libp2p
32
+ */
33
+ private handleConnectionOpen;
34
+ /**
35
+ * Handle connection close event from libp2p
36
+ */
37
+ private handleConnectionClose;
38
+ /**
39
+ * Try to resolve a libp2p peer ID to an Olane address
40
+ * Checks hierarchy manager for known peers
41
+ */
42
+ private peerIdToAddress;
43
+ /**
44
+ * Check if an address is a direct child
45
+ */
46
+ private isChild;
47
+ /**
48
+ * Check if an address is a parent
49
+ */
50
+ private isParent;
51
+ }
52
+ //# sourceMappingURL=o-node.notification-manager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"o-node.notification-manager.d.ts","sourceRoot":"","sources":["../../src/o-node.notification-manager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AACzC,OAAO,EACL,oBAAoB,EAQrB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAC1D,OAAO,EAAE,qBAAqB,EAAE,MAAM,+BAA+B,CAAC;AAEtE;;;GAGG;AACH,qBAAa,wBAAyB,SAAQ,oBAAoB;IAE9D,OAAO,CAAC,OAAO;IACf,OAAO,CAAC,gBAAgB;IACxB,OAAO,CAAC,OAAO;gBAFP,OAAO,EAAE,MAAM,EACf,gBAAgB,EAAE,qBAAqB,EACvC,OAAO,EAAE,YAAY;IAK/B;;OAEG;IACH,SAAS,CAAC,cAAc,IAAI,IAAI;IAgChC;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAkDzB;;OAEG;IACH,OAAO,CAAC,oBAAoB;IAoD5B;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAmB3B;;OAEG;IACH,OAAO,CAAC,oBAAoB;IAI5B;;OAEG;IACH,OAAO,CAAC,qBAAqB;IAI7B;;;OAGG;IACH,OAAO,CAAC,eAAe;IAkCvB;;OAEG;IACH,OAAO,CAAC,OAAO;IAMf;;OAEG;IACH,OAAO,CAAC,QAAQ;CAKjB"}
@@ -0,0 +1,185 @@
1
+ import { oNotificationManager, NodeConnectedEvent, NodeDisconnectedEvent, NodeDiscoveredEvent, ChildJoinedEvent, ChildLeftEvent, ParentConnectedEvent, ParentDisconnectedEvent, } from '@olane/o-core';
2
+ /**
3
+ * libp2p-specific implementation of oNotificationManager
4
+ * Wraps libp2p events and enriches them with Olane context
5
+ */
6
+ export class oNodeNotificationManager extends oNotificationManager {
7
+ constructor(p2pNode, hierarchyManager, address) {
8
+ super();
9
+ this.p2pNode = p2pNode;
10
+ this.hierarchyManager = hierarchyManager;
11
+ this.address = address;
12
+ }
13
+ /**
14
+ * Wire up libp2p event listeners
15
+ */
16
+ setupListeners() {
17
+ this.logger.debug('Setting up libp2p event listeners...');
18
+ // Peer connection events
19
+ this.p2pNode.addEventListener('peer:connect', this.handlePeerConnect.bind(this));
20
+ this.p2pNode.addEventListener('peer:disconnect', this.handlePeerDisconnect.bind(this));
21
+ // Peer discovery events
22
+ this.p2pNode.addEventListener('peer:discovery', this.handlePeerDiscovery.bind(this));
23
+ // Connection events
24
+ this.p2pNode.addEventListener('connection:open', this.handleConnectionOpen.bind(this));
25
+ this.p2pNode.addEventListener('connection:close', this.handleConnectionClose.bind(this));
26
+ this.logger.debug('libp2p event listeners configured');
27
+ }
28
+ /**
29
+ * Handle peer connect event from libp2p
30
+ */
31
+ handlePeerConnect(evt) {
32
+ const peerId = evt.detail;
33
+ // this.logger.debug(`Peer connected: ${peerId.toString()}`);
34
+ // Try to resolve peer ID to Olane address
35
+ const nodeAddress = this.peerIdToAddress(peerId.toString());
36
+ if (!nodeAddress) {
37
+ // this.logger.debug(
38
+ // `Could not resolve peer ID ${peerId.toString()} to address`,
39
+ // );
40
+ return;
41
+ }
42
+ // Emit generic node connected event
43
+ this.emit(new NodeConnectedEvent({
44
+ source: this.address,
45
+ nodeAddress,
46
+ connectionMetadata: {
47
+ peerId: peerId.toString(),
48
+ transport: 'libp2p',
49
+ },
50
+ }));
51
+ // Check if this is a child node
52
+ if (this.isChild(nodeAddress)) {
53
+ // this.logger.debug(`Child node connected: ${nodeAddress.toString()}`);
54
+ this.emit(new ChildJoinedEvent({
55
+ source: this.address,
56
+ childAddress: nodeAddress,
57
+ parentAddress: this.address,
58
+ }));
59
+ }
60
+ // Check if this is a parent node
61
+ if (this.isParent(nodeAddress)) {
62
+ // this.logger.debug(`Parent node connected: ${nodeAddress.toString()}`);
63
+ this.emit(new ParentConnectedEvent({
64
+ source: this.address,
65
+ parentAddress: nodeAddress,
66
+ }));
67
+ }
68
+ }
69
+ /**
70
+ * Handle peer disconnect event from libp2p
71
+ */
72
+ handlePeerDisconnect(evt) {
73
+ const peerId = evt.detail;
74
+ // this.logger.debug(`Peer disconnected: ${peerId.toString()}`);
75
+ // Try to resolve peer ID to Olane address
76
+ const nodeAddress = this.peerIdToAddress(peerId.toString());
77
+ if (!nodeAddress) {
78
+ // this.logger.debug(
79
+ // `Could not resolve peer ID ${peerId.toString()} to address`,
80
+ // );
81
+ return;
82
+ }
83
+ // Emit generic node disconnected event
84
+ this.emit(new NodeDisconnectedEvent({
85
+ source: this.address,
86
+ nodeAddress,
87
+ reason: 'peer_disconnected',
88
+ }));
89
+ // Check if this is a child node
90
+ if (this.isChild(nodeAddress)) {
91
+ this.logger.debug(`Child node disconnected: ${nodeAddress.toString()}`);
92
+ this.emit(new ChildLeftEvent({
93
+ source: this.address,
94
+ childAddress: nodeAddress,
95
+ parentAddress: this.address,
96
+ reason: 'peer_disconnected',
97
+ }));
98
+ // Optionally remove from hierarchy (auto-cleanup)
99
+ // this.hierarchyManager.removeChild(nodeAddress);
100
+ }
101
+ // Check if this is a parent node
102
+ if (this.isParent(nodeAddress)) {
103
+ this.logger.debug(`Parent node disconnected: ${nodeAddress.toString()}`);
104
+ this.emit(new ParentDisconnectedEvent({
105
+ source: this.address,
106
+ parentAddress: nodeAddress,
107
+ reason: 'peer_disconnected',
108
+ }));
109
+ }
110
+ }
111
+ /**
112
+ * Handle peer discovery event from libp2p
113
+ */
114
+ handlePeerDiscovery(evt) {
115
+ const peerInfo = evt.detail;
116
+ // this.logger.debug(`Peer discovered: ${peerInfo.id.toString()}`);
117
+ // Try to resolve peer ID to Olane address
118
+ const nodeAddress = this.peerIdToAddress(peerInfo.id.toString());
119
+ if (!nodeAddress) {
120
+ return;
121
+ }
122
+ this.emit(new NodeDiscoveredEvent({
123
+ source: this.address,
124
+ nodeAddress,
125
+ }));
126
+ }
127
+ /**
128
+ * Handle connection open event from libp2p
129
+ */
130
+ handleConnectionOpen(evt) {
131
+ // do nothing for now
132
+ }
133
+ /**
134
+ * Handle connection close event from libp2p
135
+ */
136
+ handleConnectionClose(evt) {
137
+ // do nothing for now
138
+ }
139
+ /**
140
+ * Try to resolve a libp2p peer ID to an Olane address
141
+ * Checks hierarchy manager for known peers
142
+ */
143
+ peerIdToAddress(peerId) {
144
+ // Check children
145
+ for (const child of this.hierarchyManager.children) {
146
+ const childTransports = child.transports;
147
+ for (const transport of childTransports) {
148
+ if (transport.toString().includes(peerId)) {
149
+ return child;
150
+ }
151
+ }
152
+ }
153
+ // Check parents
154
+ for (const parent of this.hierarchyManager.parents) {
155
+ const parentTransports = parent.transports;
156
+ for (const transport of parentTransports) {
157
+ if (transport.toString().includes(peerId)) {
158
+ return parent;
159
+ }
160
+ }
161
+ }
162
+ // Check leaders
163
+ for (const leader of this.hierarchyManager.leaders) {
164
+ const leaderTransports = leader.transports;
165
+ for (const transport of leaderTransports) {
166
+ if (transport.toString().includes(peerId)) {
167
+ return leader;
168
+ }
169
+ }
170
+ }
171
+ return null;
172
+ }
173
+ /**
174
+ * Check if an address is a direct child
175
+ */
176
+ isChild(address) {
177
+ return this.hierarchyManager.children.some((child) => child.toString() === address.toString());
178
+ }
179
+ /**
180
+ * Check if an address is a parent
181
+ */
182
+ isParent(address) {
183
+ return this.hierarchyManager.parents.some((parent) => parent.toString() === address.toString());
184
+ }
185
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"o-node.tool.d.ts","sourceRoot":"","sources":["../../src/o-node.tool.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,QAAQ,EAGR,QAAQ,EAET,MAAM,eAAe,CAAC;AAEvB,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AACrD,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;;AAGrD;;;;GAIG;AACH,qBAAa,SAAU,SAAQ,cAAkB;IACzC,cAAc,CAAC,OAAO,EAAE,QAAQ;IAQhC,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAW3B,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IA2CnE,cAAc,IAAI,OAAO,CAAC,GAAG,CAAC;IAQ9B,oBAAoB,CAAC,OAAO,EAAE,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC;CAa5D"}
1
+ {"version":3,"file":"o-node.tool.d.ts","sourceRoot":"","sources":["../../src/o-node.tool.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,QAAQ,EAGR,QAAQ,EAIT,MAAM,eAAe,CAAC;AAEvB,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AACrD,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;;AAIrD;;;;GAIG;AACH,qBAAa,SAAU,SAAQ,cAAkB;IACzC,cAAc,CAAC,OAAO,EAAE,QAAQ;IAQhC,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAW3B,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAuCnE,cAAc,IAAI,OAAO,CAAC,GAAG,CAAC;IAQ9B,oBAAoB,CAAC,OAAO,EAAE,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC;CA2B5D"}
@@ -1,7 +1,8 @@
1
- import { CoreUtils, oAddress, oError, oErrorCodes, oRequest, } from '@olane/o-core';
1
+ import { CoreUtils, oRequest, ResponseBuilder, ChildJoinedEvent, } from '@olane/o-core';
2
2
  import { oTool } from '@olane/o-tool';
3
3
  import { oServerNode } from './nodes/server.node.js';
4
4
  import { oNodeTransport } from './router/o-node.transport.js';
5
+ import { oNodeAddress } from './router/o-node.address.js';
5
6
  /**
6
7
  * oTool is a mixin that extends the base class and implements the oTool interface
7
8
  * @param Base - The base class to extend
@@ -24,35 +25,32 @@ export class oNodeTool extends oTool(oServerNode) {
24
25
  }
25
26
  }
26
27
  async handleStream(stream, connection) {
27
- stream.addEventListener('message', async (event) => {
28
+ // CRITICAL: Attach message listener immediately to prevent buffer overflow (libp2p v3)
29
+ // Per libp2p migration guide: "If no message event handler is added, streams will
30
+ // buffer incoming data until a pre-configured limit is reached, after which the stream will be reset."
31
+ const messageHandler = async (event) => {
28
32
  if (!event.data) {
29
33
  this.logger.warn('Malformed event data');
30
34
  return;
31
35
  }
32
36
  const requestConfig = await CoreUtils.processStream(event);
33
37
  const request = new oRequest(requestConfig);
34
- let success = true;
35
- const result = await this.execute(request, stream).catch((error) => {
36
- this.logger.error('Error executing tool: ', request.toString(), error, typeof error);
37
- success = false;
38
- const responseError = error instanceof oError
39
- ? error
40
- : new oError(oErrorCodes.UNKNOWN, error.message);
41
- return {
42
- error: responseError.toJSON(),
43
- };
44
- });
45
- if (success) {
46
- this.metrics.successCount++;
38
+ // Use ResponseBuilder with automatic error handling and metrics tracking
39
+ const responseBuilder = ResponseBuilder.create().withMetrics(this.metrics);
40
+ let response;
41
+ try {
42
+ const result = await this.execute(request, stream);
43
+ response = await responseBuilder.build(request, result, null);
47
44
  }
48
- else {
49
- this.metrics.errorCount++;
45
+ catch (error) {
46
+ this.logger.error('Error executing tool: ', request.toString(), error, typeof error);
47
+ response = await responseBuilder.buildError(request, error);
50
48
  }
51
- // compose the response & add the expected connection + request fields
52
- const response = CoreUtils.buildResponse(request, result, result?.error);
53
- // add the request method to the response
49
+ // Send the response
54
50
  await CoreUtils.sendResponse(response, stream);
55
- });
51
+ };
52
+ // Attach listener synchronously before any async operations
53
+ stream.addEventListener('message', messageHandler);
56
54
  }
57
55
  async _tool_identify() {
58
56
  return {
@@ -64,8 +62,17 @@ export class oNodeTool extends oTool(oServerNode) {
64
62
  async _tool_child_register(request) {
65
63
  this.logger.debug('Child register: ', request.params);
66
64
  const { address, transports } = request.params;
67
- const childAddress = new oAddress(address, transports.map((t) => new oNodeTransport(t)));
65
+ const childAddress = new oNodeAddress(address, transports.map((t) => new oNodeTransport(t)));
66
+ // Add child to hierarchy
68
67
  this.hierarchyManager.addChild(childAddress);
68
+ // Emit child joined event
69
+ if (this.notificationManager) {
70
+ this.notificationManager.emit(new ChildJoinedEvent({
71
+ source: this.address,
72
+ childAddress,
73
+ parentAddress: this.address,
74
+ }));
75
+ }
69
76
  return {
70
77
  message: `Child node registered with parent! ${childAddress.toString()}`,
71
78
  parentTransports: this.parentTransports.map((t) => t.toString()),
@@ -17,6 +17,7 @@ export declare class oNodeRouter extends oToolRouter {
17
17
  protected forward(address: oNodeAddress, request: oRouterRequest, node: oNode): Promise<any>;
18
18
  /**
19
19
  * Executes a request locally when routing to self.
20
+ * Now uses ResponseBuilder for consistency with useSelf() behavior.
20
21
  */
21
22
  private executeSelfRouting;
22
23
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"o-node.router.d.ts","sourceRoot":"","sources":["../../../src/router/o-node.router.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAML,cAAc,EACd,aAAa,EACd,MAAM,eAAe,CAAC;AACvB,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAK5C,qBAAa,WAAY,SAAQ,WAAW;IAC1C,OAAO,CAAC,aAAa,CAAqB;;IAO1C;;;;;;;;OAQG;cACa,OAAO,CACrB,OAAO,EAAE,YAAY,EACrB,OAAO,EAAE,cAAc,EACvB,IAAI,EAAE,KAAK,GACV,OAAO,CAAC,GAAG,CAAC;IA0Bf;;OAEG;YACW,kBAAkB;IAgBhC;;OAEG;IACH,OAAO,CAAC,oBAAoB;IAS5B;;OAEG;IACH,OAAO,CAAC,wBAAwB;IAUhC;;OAEG;YACW,eAAe;IA2B7B;;;OAGG;IACG,SAAS,CAAC,OAAO,EAAE,YAAY,EAAE,IAAI,EAAE,KAAK,GAAG,OAAO,CAAC,aAAa,CAAC;IAyB3E;;;OAGG;IACH,UAAU,CAAC,qBAAqB,EAAE,YAAY,EAAE,IAAI,EAAE,KAAK,GAAG,OAAO;CAGtE"}
1
+ {"version":3,"file":"o-node.router.d.ts","sourceRoot":"","sources":["../../../src/router/o-node.router.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAML,cAAc,EAGd,aAAa,EACd,MAAM,eAAe,CAAC;AACvB,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAO5C,qBAAa,WAAY,SAAQ,WAAW;IAC1C,OAAO,CAAC,aAAa,CAAqB;;IAO1C;;;;;;;;OAQG;cACa,OAAO,CACrB,OAAO,EAAE,YAAY,EACrB,OAAO,EAAE,cAAc,EACvB,IAAI,EAAE,KAAK,GACV,OAAO,CAAC,GAAG,CAAC;IA6Bf;;;OAGG;YACW,kBAAkB;IA8DhC;;OAEG;IACH,OAAO,CAAC,oBAAoB;IAS5B;;OAEG;IACH,OAAO,CAAC,wBAAwB;IAWhC;;OAEG;YACW,eAAe;IA2C7B;;;OAGG;IACG,SAAS,CAAC,OAAO,EAAE,YAAY,EAAE,IAAI,EAAE,KAAK,GAAG,OAAO,CAAC,aAAa,CAAC;IAyB3E;;;OAGG;IACH,UAAU,CAAC,qBAAqB,EAAE,YAAY,EAAE,IAAI,EAAE,KAAK,GAAG,OAAO;CAGtE"}