threadforge 0.1.1 → 0.2.1

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 (358) hide show
  1. package/README.md +52 -20
  2. package/bin/forge.js +2 -1058
  3. package/bin/host-commands.d.ts +2 -0
  4. package/bin/host-commands.d.ts.map +1 -0
  5. package/bin/host-commands.js +7 -8
  6. package/bin/platform-commands.d.ts +2 -0
  7. package/bin/platform-commands.d.ts.map +1 -0
  8. package/bin/platform-commands.js +118 -36
  9. package/dist/cli/base-command.d.ts +12 -0
  10. package/dist/cli/base-command.d.ts.map +1 -0
  11. package/dist/cli/base-command.js +25 -0
  12. package/dist/cli/base-command.js.map +1 -0
  13. package/dist/cli/commands/build.d.ts +10 -0
  14. package/dist/cli/commands/build.d.ts.map +1 -0
  15. package/dist/cli/commands/build.js +110 -0
  16. package/dist/cli/commands/build.js.map +1 -0
  17. package/dist/cli/commands/deploy.d.ts +12 -0
  18. package/dist/cli/commands/deploy.d.ts.map +1 -0
  19. package/dist/cli/commands/deploy.js +143 -0
  20. package/dist/cli/commands/deploy.js.map +1 -0
  21. package/dist/cli/commands/dev.d.ts +10 -0
  22. package/dist/cli/commands/dev.d.ts.map +1 -0
  23. package/dist/cli/commands/dev.js +138 -0
  24. package/dist/cli/commands/dev.js.map +1 -0
  25. package/dist/cli/commands/generate.d.ts +10 -0
  26. package/dist/cli/commands/generate.d.ts.map +1 -0
  27. package/dist/cli/commands/generate.js +76 -0
  28. package/dist/cli/commands/generate.js.map +1 -0
  29. package/dist/cli/commands/host.d.ts +8 -0
  30. package/dist/cli/commands/host.d.ts.map +1 -0
  31. package/dist/cli/commands/host.js +20 -0
  32. package/dist/cli/commands/host.js.map +1 -0
  33. package/dist/cli/commands/init.d.ts +16 -0
  34. package/dist/cli/commands/init.d.ts.map +1 -0
  35. package/dist/cli/commands/init.js +246 -0
  36. package/dist/cli/commands/init.js.map +1 -0
  37. package/dist/cli/commands/platform.d.ts +8 -0
  38. package/dist/cli/commands/platform.d.ts.map +1 -0
  39. package/dist/cli/commands/platform.js +20 -0
  40. package/dist/cli/commands/platform.js.map +1 -0
  41. package/dist/cli/commands/restart.d.ts +8 -0
  42. package/dist/cli/commands/restart.d.ts.map +1 -0
  43. package/dist/cli/commands/restart.js +13 -0
  44. package/dist/cli/commands/restart.js.map +1 -0
  45. package/dist/cli/commands/scaffold/frontend.d.ts +10 -0
  46. package/dist/cli/commands/scaffold/frontend.d.ts.map +1 -0
  47. package/dist/cli/commands/scaffold/frontend.js +130 -0
  48. package/dist/cli/commands/scaffold/frontend.js.map +1 -0
  49. package/dist/cli/commands/scaffold/react.d.ts +7 -0
  50. package/dist/cli/commands/scaffold/react.d.ts.map +1 -0
  51. package/dist/cli/commands/scaffold/react.js +12 -0
  52. package/dist/cli/commands/scaffold/react.js.map +1 -0
  53. package/dist/cli/commands/scale.d.ts +8 -0
  54. package/dist/cli/commands/scale.d.ts.map +1 -0
  55. package/dist/cli/commands/scale.js +13 -0
  56. package/dist/cli/commands/scale.js.map +1 -0
  57. package/dist/cli/commands/start.d.ts +10 -0
  58. package/dist/cli/commands/start.d.ts.map +1 -0
  59. package/dist/cli/commands/start.js +71 -0
  60. package/dist/cli/commands/start.js.map +1 -0
  61. package/dist/cli/commands/status.d.ts +11 -0
  62. package/dist/cli/commands/status.d.ts.map +1 -0
  63. package/dist/cli/commands/status.js +60 -0
  64. package/dist/cli/commands/status.js.map +1 -0
  65. package/dist/cli/commands/stop.d.ts +10 -0
  66. package/dist/cli/commands/stop.d.ts.map +1 -0
  67. package/dist/cli/commands/stop.js +89 -0
  68. package/dist/cli/commands/stop.js.map +1 -0
  69. package/dist/cli/util/config-discovery.d.ts +8 -0
  70. package/dist/cli/util/config-discovery.d.ts.map +1 -0
  71. package/dist/cli/util/config-discovery.js +70 -0
  72. package/dist/cli/util/config-discovery.js.map +1 -0
  73. package/dist/cli/util/config-patcher.d.ts +17 -0
  74. package/dist/cli/util/config-patcher.d.ts.map +1 -0
  75. package/dist/cli/util/config-patcher.js +439 -0
  76. package/dist/cli/util/config-patcher.js.map +1 -0
  77. package/dist/cli/util/frontend-dev.d.ts +8 -0
  78. package/dist/cli/util/frontend-dev.d.ts.map +1 -0
  79. package/dist/cli/util/frontend-dev.js +117 -0
  80. package/dist/cli/util/frontend-dev.js.map +1 -0
  81. package/dist/cli/util/process.d.ts +5 -0
  82. package/dist/cli/util/process.d.ts.map +1 -0
  83. package/dist/cli/util/process.js +17 -0
  84. package/dist/cli/util/process.js.map +1 -0
  85. package/dist/cli/util/templates.d.ts +10 -0
  86. package/dist/cli/util/templates.d.ts.map +1 -0
  87. package/dist/cli/util/templates.js +157 -0
  88. package/dist/cli/util/templates.js.map +1 -0
  89. package/dist/core/AlertSink.d.ts +83 -0
  90. package/dist/core/AlertSink.d.ts.map +1 -0
  91. package/dist/core/AlertSink.js +126 -0
  92. package/dist/core/AlertSink.js.map +1 -0
  93. package/dist/core/DirectMessageBus.d.ts +88 -0
  94. package/dist/core/DirectMessageBus.d.ts.map +1 -0
  95. package/dist/core/DirectMessageBus.js +352 -0
  96. package/dist/core/DirectMessageBus.js.map +1 -0
  97. package/dist/core/EndpointResolver.d.ts +111 -0
  98. package/dist/core/EndpointResolver.d.ts.map +1 -0
  99. package/dist/core/EndpointResolver.js +336 -0
  100. package/dist/core/EndpointResolver.js.map +1 -0
  101. package/dist/core/ForgeContext.d.ts +221 -0
  102. package/dist/core/ForgeContext.d.ts.map +1 -0
  103. package/dist/core/ForgeContext.js +1169 -0
  104. package/dist/core/ForgeContext.js.map +1 -0
  105. package/dist/core/ForgeEndpoints.d.ts +71 -0
  106. package/dist/core/ForgeEndpoints.d.ts.map +1 -0
  107. package/dist/core/ForgeEndpoints.js +442 -0
  108. package/dist/core/ForgeEndpoints.js.map +1 -0
  109. package/dist/core/ForgeHost.d.ts +82 -0
  110. package/dist/core/ForgeHost.d.ts.map +1 -0
  111. package/dist/core/ForgeHost.js +107 -0
  112. package/dist/core/ForgeHost.js.map +1 -0
  113. package/dist/core/ForgePlatform.d.ts +96 -0
  114. package/dist/core/ForgePlatform.d.ts.map +1 -0
  115. package/dist/core/ForgePlatform.js +136 -0
  116. package/dist/core/ForgePlatform.js.map +1 -0
  117. package/dist/core/ForgeWebSocket.d.ts +56 -0
  118. package/dist/core/ForgeWebSocket.d.ts.map +1 -0
  119. package/dist/core/ForgeWebSocket.js +415 -0
  120. package/dist/core/ForgeWebSocket.js.map +1 -0
  121. package/dist/core/Ingress.d.ts +329 -0
  122. package/dist/core/Ingress.d.ts.map +1 -0
  123. package/dist/core/Ingress.js +694 -0
  124. package/dist/core/Ingress.js.map +1 -0
  125. package/dist/core/Interceptors.d.ts +134 -0
  126. package/dist/core/Interceptors.d.ts.map +1 -0
  127. package/dist/core/Interceptors.js +416 -0
  128. package/dist/core/Interceptors.js.map +1 -0
  129. package/dist/core/Logger.d.ts +20 -0
  130. package/dist/core/Logger.d.ts.map +1 -0
  131. package/dist/core/Logger.js +77 -0
  132. package/dist/core/Logger.js.map +1 -0
  133. package/dist/core/MessageBus.d.ts +15 -0
  134. package/dist/core/MessageBus.d.ts.map +1 -0
  135. package/dist/core/MessageBus.js +18 -0
  136. package/dist/core/MessageBus.js.map +1 -0
  137. package/dist/core/Prometheus.d.ts +80 -0
  138. package/dist/core/Prometheus.d.ts.map +1 -0
  139. package/dist/core/Prometheus.js +332 -0
  140. package/dist/core/Prometheus.js.map +1 -0
  141. package/dist/core/RequestContext.d.ts +214 -0
  142. package/dist/core/RequestContext.d.ts.map +1 -0
  143. package/dist/core/RequestContext.js +556 -0
  144. package/dist/core/RequestContext.js.map +1 -0
  145. package/dist/core/Router.d.ts +45 -0
  146. package/dist/core/Router.d.ts.map +1 -0
  147. package/dist/core/Router.js +285 -0
  148. package/dist/core/Router.js.map +1 -0
  149. package/dist/core/RoutingStrategy.d.ts +116 -0
  150. package/dist/core/RoutingStrategy.d.ts.map +1 -0
  151. package/dist/core/RoutingStrategy.js +306 -0
  152. package/dist/core/RoutingStrategy.js.map +1 -0
  153. package/dist/core/RpcConfig.d.ts +72 -0
  154. package/dist/core/RpcConfig.d.ts.map +1 -0
  155. package/dist/core/RpcConfig.js +127 -0
  156. package/dist/core/RpcConfig.js.map +1 -0
  157. package/dist/core/SignatureCache.d.ts +81 -0
  158. package/dist/core/SignatureCache.d.ts.map +1 -0
  159. package/dist/core/SignatureCache.js +172 -0
  160. package/dist/core/SignatureCache.js.map +1 -0
  161. package/dist/core/StaticFileServer.d.ts +34 -0
  162. package/dist/core/StaticFileServer.d.ts.map +1 -0
  163. package/dist/core/StaticFileServer.js +497 -0
  164. package/dist/core/StaticFileServer.js.map +1 -0
  165. package/dist/core/Supervisor.d.ts +198 -0
  166. package/dist/core/Supervisor.d.ts.map +1 -0
  167. package/dist/core/Supervisor.js +1418 -0
  168. package/dist/core/Supervisor.js.map +1 -0
  169. package/dist/core/ThreadAllocator.d.ts +52 -0
  170. package/dist/core/ThreadAllocator.d.ts.map +1 -0
  171. package/dist/core/ThreadAllocator.js +174 -0
  172. package/dist/core/ThreadAllocator.js.map +1 -0
  173. package/dist/core/WorkerChannelManager.d.ts +130 -0
  174. package/dist/core/WorkerChannelManager.d.ts.map +1 -0
  175. package/dist/core/WorkerChannelManager.js +956 -0
  176. package/dist/core/WorkerChannelManager.js.map +1 -0
  177. package/dist/core/config-enums.d.ts +41 -0
  178. package/dist/core/config-enums.d.ts.map +1 -0
  179. package/dist/core/config-enums.js +59 -0
  180. package/dist/core/config-enums.js.map +1 -0
  181. package/dist/core/config.d.ts +159 -0
  182. package/dist/core/config.d.ts.map +1 -0
  183. package/dist/core/config.js +694 -0
  184. package/dist/core/config.js.map +1 -0
  185. package/dist/core/host-config.d.ts +146 -0
  186. package/dist/core/host-config.d.ts.map +1 -0
  187. package/dist/core/host-config.js +312 -0
  188. package/dist/core/host-config.js.map +1 -0
  189. package/dist/core/ipc-errors.d.ts +27 -0
  190. package/dist/core/ipc-errors.d.ts.map +1 -0
  191. package/dist/core/ipc-errors.js +36 -0
  192. package/dist/core/ipc-errors.js.map +1 -0
  193. package/dist/core/network-utils.d.ts +35 -0
  194. package/dist/core/network-utils.d.ts.map +1 -0
  195. package/dist/core/network-utils.js +145 -0
  196. package/dist/core/network-utils.js.map +1 -0
  197. package/dist/core/platform-config.d.ts +142 -0
  198. package/dist/core/platform-config.d.ts.map +1 -0
  199. package/dist/core/platform-config.js +299 -0
  200. package/dist/core/platform-config.js.map +1 -0
  201. package/dist/decorators/ServiceProxy.d.ts +175 -0
  202. package/dist/decorators/ServiceProxy.d.ts.map +1 -0
  203. package/dist/decorators/ServiceProxy.js +969 -0
  204. package/dist/decorators/ServiceProxy.js.map +1 -0
  205. package/dist/decorators/index.d.ts +146 -0
  206. package/dist/decorators/index.d.ts.map +1 -0
  207. package/dist/decorators/index.js +545 -0
  208. package/dist/decorators/index.js.map +1 -0
  209. package/dist/deploy/NginxGenerator.d.ts +165 -0
  210. package/dist/deploy/NginxGenerator.d.ts.map +1 -0
  211. package/dist/deploy/NginxGenerator.js +781 -0
  212. package/dist/deploy/NginxGenerator.js.map +1 -0
  213. package/dist/deploy/PlatformManifestGenerator.d.ts +43 -0
  214. package/dist/deploy/PlatformManifestGenerator.d.ts.map +1 -0
  215. package/dist/deploy/PlatformManifestGenerator.js +80 -0
  216. package/dist/deploy/PlatformManifestGenerator.js.map +1 -0
  217. package/dist/deploy/RouteManifestGenerator.d.ts +42 -0
  218. package/dist/deploy/RouteManifestGenerator.d.ts.map +1 -0
  219. package/dist/deploy/RouteManifestGenerator.js +105 -0
  220. package/dist/deploy/RouteManifestGenerator.js.map +1 -0
  221. package/dist/deploy/index.d.ts +210 -0
  222. package/dist/deploy/index.d.ts.map +1 -0
  223. package/dist/deploy/index.js +918 -0
  224. package/dist/deploy/index.js.map +1 -0
  225. package/dist/frontend/FrontendDevLifecycle.d.ts +26 -0
  226. package/dist/frontend/FrontendDevLifecycle.d.ts.map +1 -0
  227. package/dist/frontend/FrontendDevLifecycle.js +60 -0
  228. package/dist/frontend/FrontendDevLifecycle.js.map +1 -0
  229. package/dist/frontend/FrontendPluginOrchestrator.d.ts +64 -0
  230. package/dist/frontend/FrontendPluginOrchestrator.d.ts.map +1 -0
  231. package/dist/frontend/FrontendPluginOrchestrator.js +167 -0
  232. package/dist/frontend/FrontendPluginOrchestrator.js.map +1 -0
  233. package/dist/frontend/SiteResolver.d.ts +33 -0
  234. package/dist/frontend/SiteResolver.d.ts.map +1 -0
  235. package/dist/frontend/SiteResolver.js +53 -0
  236. package/dist/frontend/SiteResolver.js.map +1 -0
  237. package/dist/frontend/StaticMountRegistry.d.ts +36 -0
  238. package/dist/frontend/StaticMountRegistry.d.ts.map +1 -0
  239. package/dist/frontend/StaticMountRegistry.js +94 -0
  240. package/dist/frontend/StaticMountRegistry.js.map +1 -0
  241. package/dist/frontend/index.d.ts +7 -0
  242. package/dist/frontend/index.d.ts.map +1 -0
  243. package/{src → dist}/frontend/index.js +4 -2
  244. package/dist/frontend/index.js.map +1 -0
  245. package/dist/frontend/pathUtils.d.ts +8 -0
  246. package/dist/frontend/pathUtils.d.ts.map +1 -0
  247. package/dist/frontend/pathUtils.js +17 -0
  248. package/dist/frontend/pathUtils.js.map +1 -0
  249. package/dist/frontend/plugins/index.d.ts +2 -0
  250. package/dist/frontend/plugins/index.d.ts.map +1 -0
  251. package/{src → dist}/frontend/plugins/index.js +1 -1
  252. package/dist/frontend/plugins/index.js.map +1 -0
  253. package/dist/frontend/plugins/viteFrontend.d.ts +51 -0
  254. package/dist/frontend/plugins/viteFrontend.d.ts.map +1 -0
  255. package/dist/frontend/plugins/viteFrontend.js +134 -0
  256. package/dist/frontend/plugins/viteFrontend.js.map +1 -0
  257. package/dist/frontend/types.d.ts +25 -0
  258. package/dist/frontend/types.d.ts.map +1 -0
  259. package/dist/frontend/types.js +2 -0
  260. package/dist/frontend/types.js.map +1 -0
  261. package/dist/index.d.ts +17 -0
  262. package/dist/index.d.ts.map +1 -0
  263. package/dist/index.js +32 -0
  264. package/dist/index.js.map +1 -0
  265. package/dist/internals.d.ts +21 -0
  266. package/dist/internals.d.ts.map +1 -0
  267. package/{src → dist}/internals.js +12 -14
  268. package/dist/internals.js.map +1 -0
  269. package/dist/plugins/PluginManager.d.ts +209 -0
  270. package/dist/plugins/PluginManager.d.ts.map +1 -0
  271. package/dist/plugins/PluginManager.js +365 -0
  272. package/dist/plugins/PluginManager.js.map +1 -0
  273. package/dist/plugins/ScopedPostgres.d.ts +78 -0
  274. package/dist/plugins/ScopedPostgres.d.ts.map +1 -0
  275. package/dist/plugins/ScopedPostgres.js +190 -0
  276. package/dist/plugins/ScopedPostgres.js.map +1 -0
  277. package/dist/plugins/ScopedRedis.d.ts +88 -0
  278. package/dist/plugins/ScopedRedis.d.ts.map +1 -0
  279. package/dist/plugins/ScopedRedis.js +169 -0
  280. package/dist/plugins/ScopedRedis.js.map +1 -0
  281. package/dist/plugins/index.d.ts +289 -0
  282. package/dist/plugins/index.d.ts.map +1 -0
  283. package/dist/plugins/index.js +1942 -0
  284. package/dist/plugins/index.js.map +1 -0
  285. package/dist/plugins/types.d.ts +59 -0
  286. package/dist/plugins/types.d.ts.map +1 -0
  287. package/dist/plugins/types.js +2 -0
  288. package/dist/plugins/types.js.map +1 -0
  289. package/dist/registry/ServiceRegistry.d.ts +305 -0
  290. package/dist/registry/ServiceRegistry.d.ts.map +1 -0
  291. package/dist/registry/ServiceRegistry.js +735 -0
  292. package/dist/registry/ServiceRegistry.js.map +1 -0
  293. package/dist/scaling/ScaleAdvisor.d.ts +214 -0
  294. package/dist/scaling/ScaleAdvisor.d.ts.map +1 -0
  295. package/dist/scaling/ScaleAdvisor.js +526 -0
  296. package/dist/scaling/ScaleAdvisor.js.map +1 -0
  297. package/dist/services/Service.d.ts +164 -0
  298. package/dist/services/Service.d.ts.map +1 -0
  299. package/dist/services/Service.js +106 -0
  300. package/dist/services/Service.js.map +1 -0
  301. package/dist/services/worker-bootstrap.d.ts +15 -0
  302. package/dist/services/worker-bootstrap.d.ts.map +1 -0
  303. package/dist/services/worker-bootstrap.js +744 -0
  304. package/dist/services/worker-bootstrap.js.map +1 -0
  305. package/dist/templates/auth-service.d.ts +42 -0
  306. package/dist/templates/auth-service.d.ts.map +1 -0
  307. package/dist/templates/auth-service.js +54 -0
  308. package/dist/templates/auth-service.js.map +1 -0
  309. package/dist/templates/identity-service.d.ts +50 -0
  310. package/dist/templates/identity-service.d.ts.map +1 -0
  311. package/dist/templates/identity-service.js +62 -0
  312. package/dist/templates/identity-service.js.map +1 -0
  313. package/dist/types/contract.d.ts +120 -0
  314. package/dist/types/contract.d.ts.map +1 -0
  315. package/dist/types/contract.js +69 -0
  316. package/dist/types/contract.js.map +1 -0
  317. package/package.json +78 -20
  318. package/src/core/DirectMessageBus.js +0 -364
  319. package/src/core/EndpointResolver.js +0 -259
  320. package/src/core/ForgeContext.js +0 -2236
  321. package/src/core/ForgeHost.js +0 -122
  322. package/src/core/ForgePlatform.js +0 -145
  323. package/src/core/Ingress.js +0 -768
  324. package/src/core/Interceptors.js +0 -420
  325. package/src/core/MessageBus.js +0 -321
  326. package/src/core/Prometheus.js +0 -305
  327. package/src/core/RequestContext.js +0 -413
  328. package/src/core/RoutingStrategy.js +0 -330
  329. package/src/core/Supervisor.js +0 -1349
  330. package/src/core/ThreadAllocator.js +0 -196
  331. package/src/core/WorkerChannelManager.js +0 -879
  332. package/src/core/config.js +0 -637
  333. package/src/core/host-config.js +0 -311
  334. package/src/core/network-utils.js +0 -166
  335. package/src/core/platform-config.js +0 -308
  336. package/src/decorators/ServiceProxy.js +0 -904
  337. package/src/decorators/index.js +0 -571
  338. package/src/deploy/NginxGenerator.js +0 -865
  339. package/src/deploy/PlatformManifestGenerator.js +0 -96
  340. package/src/deploy/RouteManifestGenerator.js +0 -112
  341. package/src/deploy/index.js +0 -984
  342. package/src/frontend/FrontendDevLifecycle.js +0 -65
  343. package/src/frontend/FrontendPluginOrchestrator.js +0 -187
  344. package/src/frontend/SiteResolver.js +0 -63
  345. package/src/frontend/StaticMountRegistry.js +0 -90
  346. package/src/frontend/plugins/viteFrontend.js +0 -79
  347. package/src/frontend/types.js +0 -35
  348. package/src/index.js +0 -58
  349. package/src/plugins/PluginManager.js +0 -537
  350. package/src/plugins/ScopedPostgres.js +0 -192
  351. package/src/plugins/ScopedRedis.js +0 -142
  352. package/src/plugins/index.js +0 -1756
  353. package/src/registry/ServiceRegistry.js +0 -797
  354. package/src/scaling/ScaleAdvisor.js +0 -442
  355. package/src/services/Service.js +0 -195
  356. package/src/services/worker-bootstrap.js +0 -679
  357. package/src/templates/auth-service.js +0 -65
  358. package/src/templates/identity-service.js +0 -75
@@ -0,0 +1,352 @@
1
+ import crypto from "node:crypto";
2
+ import { EventEmitter } from "node:events";
3
+ import fs from "node:fs";
4
+ import os from "node:os";
5
+ import path from "node:path";
6
+ import { isExpectedIpcError } from "./ipc-errors.js";
7
+ const EXIT_SOCKET_DIRS = new Set();
8
+ let EXIT_CLEANUP_INSTALLED = false;
9
+ function cleanupSocketDir(socketDir) {
10
+ try {
11
+ if (fs.existsSync(socketDir)) {
12
+ for (const f of fs.readdirSync(socketDir)) {
13
+ try {
14
+ fs.unlinkSync(path.join(socketDir, f));
15
+ }
16
+ catch {
17
+ /* ignore: cleanup — socket file may already be removed */
18
+ }
19
+ }
20
+ try {
21
+ fs.rmdirSync(socketDir);
22
+ }
23
+ catch {
24
+ /* ignore: cleanup — directory may already be removed or non-empty */
25
+ }
26
+ }
27
+ }
28
+ catch {
29
+ /* ignore: cleanup — best-effort removal of socket directory */
30
+ }
31
+ }
32
+ function installExitCleanupHook() {
33
+ if (EXIT_CLEANUP_INSTALLED)
34
+ return;
35
+ EXIT_CLEANUP_INSTALLED = true;
36
+ process.once("exit", () => {
37
+ for (const socketDir of EXIT_SOCKET_DIRS) {
38
+ cleanupSocketDir(socketDir);
39
+ }
40
+ EXIT_SOCKET_DIRS.clear();
41
+ });
42
+ }
43
+ function isWorkerSendable(worker) {
44
+ if (!worker)
45
+ return false;
46
+ if (typeof worker.isDead === "function" && worker.isDead())
47
+ return false;
48
+ if (typeof worker.isConnected === "function" && !worker.isConnected())
49
+ return false;
50
+ if (worker.process?.connected === false)
51
+ return false;
52
+ return true;
53
+ }
54
+ /**
55
+ * DirectMessageBus — Unix Domain Socket Mesh (Supervisor Side)
56
+ *
57
+ * The fundamental problem: cluster.Worker.send() can only transfer
58
+ * sockets/servers, not MessagePort objects. So we can't use MessageChannel
59
+ * for direct worker-to-worker communication in cluster mode.
60
+ *
61
+ * Solution: Each worker opens a Unix domain socket server. Workers connect
62
+ * directly to each other via these sockets. The supervisor only tells
63
+ * workers WHERE to connect (socket paths), then gets out of the way.
64
+ *
65
+ * Architecture:
66
+ *
67
+ * SETUP (supervisor involved briefly):
68
+ * 1. Each worker starts a UDS server at /tmp/forge-{pid}/{service}-{worker}.sock
69
+ * 2. Worker reports its socket path to supervisor via IPC
70
+ * 3. Supervisor broadcasts the full socket registry to all workers
71
+ * 4. Workers establish direct connections to each other
72
+ *
73
+ * RUNTIME (supervisor NOT involved in message routing):
74
+ * Worker A ──UDS──► Worker B (direct, length-prefixed JSON)
75
+ * Worker B ──UDS──► Worker A
76
+ *
77
+ * Supervisor only handles:
78
+ * - Socket path registry distribution (one-time + on new workers)
79
+ * - Health checks (periodic pull, not per-message)
80
+ * - Worker lifecycle (restart, scale)
81
+ */
82
+ export class DirectMessageBus extends EventEmitter {
83
+ workers;
84
+ socketRegistry;
85
+ _registeredWorkerIds;
86
+ _workerErrorHandlers;
87
+ _connections;
88
+ _socketDir;
89
+ _broadcastTimer;
90
+ constructor() {
91
+ super();
92
+ this.workers = new Map();
93
+ this.socketRegistry = new Map();
94
+ this._registeredWorkerIds = new Set();
95
+ this._workerErrorHandlers = new WeakMap();
96
+ this._connections = new Map();
97
+ // S-IPC-2: Random suffix prevents socket path prediction
98
+ this._socketDir = path.join(os.tmpdir(), `forge-${process.pid}-${crypto.randomBytes(4).toString("hex")}`);
99
+ this._broadcastTimer = null;
100
+ try {
101
+ fs.mkdirSync(this._socketDir, { recursive: true });
102
+ }
103
+ catch (e) {
104
+ if (e.code !== "EEXIST")
105
+ console.error("[DirectMessageBus] mkdirSync failed:", e.message);
106
+ }
107
+ EXIT_SOCKET_DIRS.add(this._socketDir);
108
+ installExitCleanupHook();
109
+ }
110
+ get socketDir() {
111
+ return this._socketDir;
112
+ }
113
+ /**
114
+ * Register a worker. Tell it to start a UDS server, then
115
+ * broadcast the updated registry to all workers.
116
+ */
117
+ registerWorker(serviceName, worker, mode = "cluster") {
118
+ if (!this.workers.has(serviceName)) {
119
+ this.workers.set(serviceName, []);
120
+ }
121
+ const workerId = mode === "cluster" ? worker.id : worker.threadId;
122
+ const entry = {
123
+ id: workerId,
124
+ worker,
125
+ mode,
126
+ socketPath: null,
127
+ };
128
+ this.workers.get(serviceName).push(entry);
129
+ // Attach one shared error listener per worker so late IPC channel errors
130
+ // during churn don't surface as unhandled EventEmitter errors.
131
+ if (!this._workerErrorHandlers.has(worker)) {
132
+ const errorHandler = (err) => {
133
+ if (!isExpectedIpcError(err)) {
134
+ console.error("[DirectMessageBus] Worker error:", err?.message ?? err);
135
+ }
136
+ };
137
+ this._workerErrorHandlers.set(worker, errorHandler);
138
+ worker.on("error", errorHandler);
139
+ }
140
+ entry._errorHandler = this._workerErrorHandlers.get(worker);
141
+ // Prevent duplicate message listener registration
142
+ // If workerId is already registered (e.g., crashed worker's ID reused), clean up stale listeners
143
+ if (this._registeredWorkerIds.has(workerId)) {
144
+ // Find and clean up stale entry with this workerId across all services
145
+ for (const [svcName, entries] of this.workers) {
146
+ const staleIdx = entries.findIndex((e) => e.id === workerId && e.worker !== worker);
147
+ if (staleIdx !== -1) {
148
+ const stale = entries[staleIdx];
149
+ if (stale._messageHandler)
150
+ stale.worker.off("message", stale._messageHandler);
151
+ if (stale.socketPath) {
152
+ try {
153
+ fs.unlinkSync(stale.socketPath);
154
+ }
155
+ catch {
156
+ /* ignore: cleanup — stale socket may already be removed */
157
+ }
158
+ this.socketRegistry.delete(`${svcName}:${workerId}`);
159
+ }
160
+ entries.splice(staleIdx, 1);
161
+ if (entries.length === 0)
162
+ this.workers.delete(svcName);
163
+ }
164
+ }
165
+ this._registeredWorkerIds.delete(workerId);
166
+ }
167
+ this._registeredWorkerIds.add(workerId);
168
+ // Listen for supervisor-level IPC from this worker
169
+ const messageHandler = (msg) => {
170
+ const forgeMsg = msg;
171
+ if (!forgeMsg || !forgeMsg.type)
172
+ return;
173
+ switch (forgeMsg.type) {
174
+ case "forge:socket-ready":
175
+ // In colocated groups a worker may host multiple services, each with its
176
+ // own socket. Ignore ready messages for sibling services on this entry.
177
+ if (forgeMsg.serviceName && forgeMsg.serviceName !== serviceName)
178
+ break;
179
+ entry.socketPath = forgeMsg.socketPath;
180
+ this.socketRegistry.set(`${serviceName}:${forgeMsg.workerId}`, forgeMsg.socketPath);
181
+ this._scheduleBroadcast();
182
+ break;
183
+ case "forge:worker-ready":
184
+ this._sendInitSocket(worker, serviceName, entry.id);
185
+ this._sendRegistryTo(worker);
186
+ break;
187
+ case "forge:channel-ready": {
188
+ // CR-IPC-9: Track established connections
189
+ const workerKey = `${serviceName}:${entry.id}`;
190
+ if (!this._connections.has(workerKey)) {
191
+ this._connections.set(workerKey, new Set());
192
+ }
193
+ if (forgeMsg.peerKey) {
194
+ this._connections.get(workerKey).add(forgeMsg.peerKey);
195
+ }
196
+ break;
197
+ }
198
+ case "forge:metric":
199
+ case "forge:log":
200
+ case "forge:health-response": {
201
+ const eventName = forgeMsg.type.replace("forge:", "");
202
+ this.emit(eventName, { service: serviceName, ...forgeMsg });
203
+ break;
204
+ }
205
+ }
206
+ };
207
+ entry._messageHandler = messageHandler;
208
+ worker.on("message", messageHandler);
209
+ // Tell the new worker to start its UDS server
210
+ this._sendInitSocket(worker, serviceName, entry.id);
211
+ this._sendRegistryTo(worker);
212
+ }
213
+ _scheduleBroadcast() {
214
+ // CR-IPC-5: Don't cancel existing timer — let the first registration broadcast on schedule
215
+ if (this._broadcastTimer)
216
+ return;
217
+ this._broadcastTimer = setTimeout(() => {
218
+ this._broadcastTimer = null;
219
+ this._broadcastRegistry();
220
+ }, 50 + Math.floor(Math.random() * 50));
221
+ // SUP-M3: Don't keep the process alive during shutdown
222
+ this._broadcastTimer.unref();
223
+ }
224
+ _sendInitSocket(worker, serviceName, workerId) {
225
+ if (!isWorkerSendable(worker))
226
+ return;
227
+ try {
228
+ worker.send({
229
+ type: "forge:init-socket",
230
+ socketDir: this._socketDir,
231
+ serviceName,
232
+ workerId,
233
+ });
234
+ }
235
+ catch (e) {
236
+ if (!isExpectedIpcError(e)) {
237
+ console.error("[DirectMessageBus] Failed to send init-socket:", e.message);
238
+ }
239
+ }
240
+ }
241
+ _sendRegistryTo(worker) {
242
+ if (!isWorkerSendable(worker))
243
+ return;
244
+ try {
245
+ const msg = {
246
+ type: "forge:socket-registry",
247
+ registry: Object.fromEntries(this.socketRegistry),
248
+ };
249
+ // S-IPC-1: Include cluster secret for handshake authentication
250
+ const secret = process.env.FORGE_CLUSTER_SECRET;
251
+ if (secret) {
252
+ msg.secret = secret;
253
+ }
254
+ worker.send(msg);
255
+ }
256
+ catch (e) {
257
+ if (!isExpectedIpcError(e)) {
258
+ console.error("[DirectMessageBus] Failed to send registry:", e.message);
259
+ }
260
+ }
261
+ }
262
+ _broadcastRegistry() {
263
+ for (const [, workers] of this.workers) {
264
+ for (const entry of workers) {
265
+ this._sendRegistryTo(entry.worker);
266
+ }
267
+ }
268
+ }
269
+ unregisterWorker(serviceName, workerId, options = {}) {
270
+ const workers = this.workers.get(serviceName);
271
+ if (!workers)
272
+ return;
273
+ const idx = workers.findIndex((w) => w.id === workerId);
274
+ if (idx === -1)
275
+ return;
276
+ const entry = workers[idx];
277
+ if (entry._messageHandler) {
278
+ entry.worker.off("message", entry._messageHandler);
279
+ }
280
+ if (entry.socketPath) {
281
+ try {
282
+ fs.unlinkSync(entry.socketPath);
283
+ }
284
+ catch (e) {
285
+ if (e.code !== "ENOENT")
286
+ console.error("[DirectMessageBus] unlink failed:", e.message);
287
+ }
288
+ this.socketRegistry.delete(`${serviceName}:${workerId}`);
289
+ }
290
+ workers.splice(idx, 1);
291
+ // Clean up the registered worker ID tracking
292
+ this._registeredWorkerIds.delete(workerId);
293
+ if (workers.length === 0) {
294
+ this.workers.delete(serviceName);
295
+ }
296
+ if (!options.suppressBroadcast && this.workers.size > 0) {
297
+ this._broadcastRegistry();
298
+ }
299
+ }
300
+ unregisterService(serviceName) {
301
+ const workers = [...(this.workers.get(serviceName) ?? [])];
302
+ for (const w of workers) {
303
+ this.unregisterWorker(serviceName, w.id);
304
+ }
305
+ }
306
+ requestHealthChecks() {
307
+ for (const [, workers] of this.workers) {
308
+ for (const entry of workers) {
309
+ if (!isWorkerSendable(entry.worker))
310
+ continue;
311
+ try {
312
+ entry.worker.send({ type: "forge:health-check", timestamp: Date.now() });
313
+ }
314
+ catch (err) {
315
+ if (!isExpectedIpcError(err)) {
316
+ console.error("[DirectMessageBus] Failed to send health-check:", err.message);
317
+ }
318
+ }
319
+ }
320
+ }
321
+ }
322
+ stats() {
323
+ const result = {};
324
+ for (const [name, workers] of this.workers) {
325
+ result[name] = {
326
+ workerCount: workers.length,
327
+ ids: workers.map((w) => w.id),
328
+ directSockets: workers.filter((w) => w.socketPath).length,
329
+ };
330
+ }
331
+ return result;
332
+ }
333
+ /**
334
+ * CR-IPC-9: Get the connection matrix for debugging.
335
+ */
336
+ getConnectionMatrix() {
337
+ const result = {};
338
+ for (const [key, peers] of this._connections) {
339
+ result[key] = [...peers];
340
+ }
341
+ return result;
342
+ }
343
+ cleanup() {
344
+ if (this._broadcastTimer) {
345
+ clearTimeout(this._broadcastTimer);
346
+ this._broadcastTimer = null;
347
+ }
348
+ cleanupSocketDir(this._socketDir);
349
+ EXIT_SOCKET_DIRS.delete(this._socketDir);
350
+ }
351
+ }
352
+ //# sourceMappingURL=DirectMessageBus.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DirectMessageBus.js","sourceRoot":"","sources":["../../src/core/DirectMessageBus.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,aAAa,CAAC;AACjC,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,kBAAkB,EAAkB,MAAM,iBAAiB,CAAC;AAyCrE,MAAM,gBAAgB,GAAgB,IAAI,GAAG,EAAE,CAAC;AAChD,IAAI,sBAAsB,GAAG,KAAK,CAAC;AAEnC,SAAS,gBAAgB,CAAC,SAAiB;IACzC,IAAI,CAAC;QACH,IAAI,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;YAC7B,KAAK,MAAM,CAAC,IAAI,EAAE,CAAC,WAAW,CAAC,SAAS,CAAC,EAAE,CAAC;gBAC1C,IAAI,CAAC;oBACH,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,CAAC;gBACzC,CAAC;gBAAC,MAAM,CAAC;oBACP,0DAA0D;gBAC5D,CAAC;YACH,CAAC;YACD,IAAI,CAAC;gBACH,EAAE,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC;YAC1B,CAAC;YAAC,MAAM,CAAC;gBACP,qEAAqE;YACvE,CAAC;QACH,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,+DAA+D;IACjE,CAAC;AACH,CAAC;AAED,SAAS,sBAAsB;IAC7B,IAAI,sBAAsB;QAAE,OAAO;IACnC,sBAAsB,GAAG,IAAI,CAAC;IAC9B,OAAO,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,EAAE;QACxB,KAAK,MAAM,SAAS,IAAI,gBAAgB,EAAE,CAAC;YACzC,gBAAgB,CAAC,SAAS,CAAC,CAAC;QAC9B,CAAC;QACD,gBAAgB,CAAC,KAAK,EAAE,CAAC;IAC3B,CAAC,CAAC,CAAC;AACL,CAAC;AAED,SAAS,gBAAgB,CAAC,MAAqC;IAC7D,IAAI,CAAC,MAAM;QAAE,OAAO,KAAK,CAAC;IAC1B,IAAI,OAAO,MAAM,CAAC,MAAM,KAAK,UAAU,IAAI,MAAM,CAAC,MAAM,EAAE;QAAE,OAAO,KAAK,CAAC;IACzE,IAAI,OAAO,MAAM,CAAC,WAAW,KAAK,UAAU,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE;QAAE,OAAO,KAAK,CAAC;IACpF,IAAI,MAAM,CAAC,OAAO,EAAE,SAAS,KAAK,KAAK;QAAE,OAAO,KAAK,CAAC;IACtD,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,MAAM,OAAO,gBAAiB,SAAQ,YAAY;IAChD,OAAO,CAA6B;IACpC,cAAc,CAAsB;IACpC,oBAAoB,CAAc;IAClC,oBAAoB,CAA8C;IAClE,YAAY,CAA2B;IACvC,UAAU,CAAS;IACnB,eAAe,CAAuC;IAEtD;QACE,KAAK,EAAE,CAAC;QAER,IAAI,CAAC,OAAO,GAAG,IAAI,GAAG,EAAE,CAAC;QACzB,IAAI,CAAC,cAAc,GAAG,IAAI,GAAG,EAAE,CAAC;QAChC,IAAI,CAAC,oBAAoB,GAAG,IAAI,GAAG,EAAE,CAAC;QACtC,IAAI,CAAC,oBAAoB,GAAG,IAAI,OAAO,EAAE,CAAC;QAC1C,IAAI,CAAC,YAAY,GAAG,IAAI,GAAG,EAAE,CAAC;QAE9B,yDAAyD;QACzD,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,SAAS,OAAO,CAAC,GAAG,IAAI,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAC1G,IAAI,CAAC,eAAe,GAAG,IAAI,CAAC;QAC5B,IAAI,CAAC;YACH,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACrD,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,IAAK,CAAe,CAAC,IAAI,KAAK,QAAQ;gBACpC,OAAO,CAAC,KAAK,CAAC,sCAAsC,EAAG,CAAW,CAAC,OAAO,CAAC,CAAC;QAChF,CAAC;QACD,gBAAgB,CAAC,GAAG,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QACtC,sBAAsB,EAAE,CAAC;IAC3B,CAAC;IAED,IAAI,SAAS;QACX,OAAO,IAAI,CAAC,UAAU,CAAC;IACzB,CAAC;IAED;;;OAGG;IACH,cAAc,CAAC,WAAmB,EAAE,MAAkB,EAAE,OAAe,SAAS;QAC9E,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,EAAE,CAAC;YACnC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC;QACpC,CAAC;QAED,MAAM,QAAQ,GAAG,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,EAAG,CAAC,CAAC,CAAC,MAAM,CAAC,QAAS,CAAC;QAEpE,MAAM,KAAK,GAAgB;YACzB,EAAE,EAAE,QAAQ;YACZ,MAAM;YACN,IAAI;YACJ,UAAU,EAAE,IAAI;SACjB,CAAC;QAEF,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,WAAW,CAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAE3C,yEAAyE;QACzE,+DAA+D;QAC/D,IAAI,CAAC,IAAI,CAAC,oBAAoB,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;YAC3C,MAAM,YAAY,GAAG,CAAC,GAAY,EAAQ,EAAE;gBAC1C,IAAI,CAAC,kBAAkB,CAAC,GAAG,CAAC,EAAE,CAAC;oBAC7B,OAAO,CAAC,KAAK,CAAC,kCAAkC,EAAG,GAAa,EAAE,OAAO,IAAI,GAAG,CAAC,CAAC;gBACpF,CAAC;YACH,CAAC,CAAC;YACF,IAAI,CAAC,oBAAoB,CAAC,GAAG,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;YACpD,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,YAA4C,CAAC,CAAC;QACnE,CAAC;QACD,KAAK,CAAC,aAAa,GAAG,IAAI,CAAC,oBAAoB,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QAE5D,kDAAkD;QAClD,iGAAiG;QACjG,IAAI,IAAI,CAAC,oBAAoB,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC5C,uEAAuE;YACvE,KAAK,MAAM,CAAC,OAAO,EAAE,OAAO,CAAC,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;gBAC9C,MAAM,QAAQ,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,QAAQ,IAAI,CAAC,CAAC,MAAM,KAAK,MAAM,CAAC,CAAC;gBACpF,IAAI,QAAQ,KAAK,CAAC,CAAC,EAAE,CAAC;oBACpB,MAAM,KAAK,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;oBAChC,IAAI,KAAK,CAAC,eAAe;wBAAE,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,SAAS,EAAE,KAAK,CAAC,eAA+C,CAAC,CAAC;oBAC9G,IAAI,KAAK,CAAC,UAAU,EAAE,CAAC;wBACrB,IAAI,CAAC;4BACH,EAAE,CAAC,UAAU,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;wBAClC,CAAC;wBAAC,MAAM,CAAC;4BACP,2DAA2D;wBAC7D,CAAC;wBACD,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,GAAG,OAAO,IAAI,QAAQ,EAAE,CAAC,CAAC;oBACvD,CAAC;oBACD,OAAO,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC;oBAC5B,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;wBAAE,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;gBACzD,CAAC;YACH,CAAC;YACD,IAAI,CAAC,oBAAoB,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QAC7C,CAAC;QACD,IAAI,CAAC,oBAAoB,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAExC,mDAAmD;QACnD,MAAM,cAAc,GAAG,CAAC,GAAY,EAAQ,EAAE;YAC5C,MAAM,QAAQ,GAAG,GAAmB,CAAC;YACrC,IAAI,CAAC,QAAQ,IAAI,CAAC,QAAQ,CAAC,IAAI;gBAAE,OAAO;YAExC,QAAQ,QAAQ,CAAC,IAAI,EAAE,CAAC;gBACtB,KAAK,oBAAoB;oBACvB,yEAAyE;oBACzE,wEAAwE;oBACxE,IAAI,QAAQ,CAAC,WAAW,IAAI,QAAQ,CAAC,WAAW,KAAK,WAAW;wBAAE,MAAM;oBACxE,KAAK,CAAC,UAAU,GAAG,QAAQ,CAAC,UAAW,CAAC;oBACxC,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,GAAG,WAAW,IAAI,QAAQ,CAAC,QAAQ,EAAE,EAAE,QAAQ,CAAC,UAAW,CAAC,CAAC;oBACrF,IAAI,CAAC,kBAAkB,EAAE,CAAC;oBAC1B,MAAM;gBAER,KAAK,oBAAoB;oBACvB,IAAI,CAAC,eAAe,CAAC,MAAM,EAAE,WAAW,EAAE,KAAK,CAAC,EAAE,CAAC,CAAC;oBACpD,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC,CAAC;oBAC7B,MAAM;gBAER,KAAK,qBAAqB,CAAC,CAAC,CAAC;oBAC3B,0CAA0C;oBAC1C,MAAM,SAAS,GAAG,GAAG,WAAW,IAAI,KAAK,CAAC,EAAE,EAAE,CAAC;oBAC/C,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC;wBACtC,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,SAAS,EAAE,IAAI,GAAG,EAAE,CAAC,CAAC;oBAC9C,CAAC;oBACD,IAAI,QAAQ,CAAC,OAAO,EAAE,CAAC;wBACrB,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,SAAS,CAAE,CAAC,GAAG,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;oBAC1D,CAAC;oBACD,MAAM;gBACR,CAAC;gBAED,KAAK,cAAc,CAAC;gBACpB,KAAK,WAAW,CAAC;gBACjB,KAAK,uBAAuB,CAAC,CAAC,CAAC;oBAC7B,MAAM,SAAS,GAAG,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;oBACtD,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,EAAE,OAAO,EAAE,WAAW,EAAE,GAAG,QAAQ,EAAE,CAAC,CAAC;oBAC5D,MAAM;gBACR,CAAC;YACH,CAAC;QACH,CAAC,CAAC;QACF,KAAK,CAAC,eAAe,GAAG,cAAc,CAAC;QACvC,MAAM,CAAC,EAAE,CAAC,SAAS,EAAE,cAA8C,CAAC,CAAC;QAErE,8CAA8C;QAC9C,IAAI,CAAC,eAAe,CAAC,MAAM,EAAE,WAAW,EAAE,KAAK,CAAC,EAAE,CAAC,CAAC;QACpD,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC,CAAC;IAC/B,CAAC;IAED,kBAAkB;QAChB,2FAA2F;QAC3F,IAAI,IAAI,CAAC,eAAe;YAAE,OAAO;QACjC,IAAI,CAAC,eAAe,GAAG,UAAU,CAC/B,GAAG,EAAE;YACH,IAAI,CAAC,eAAe,GAAG,IAAI,CAAC;YAC5B,IAAI,CAAC,kBAAkB,EAAE,CAAC;QAC5B,CAAC,EACD,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,EAAE,CAAC,CACpC,CAAC;QACF,uDAAuD;QACvD,IAAI,CAAC,eAAe,CAAC,KAAK,EAAE,CAAC;IAC/B,CAAC;IAED,eAAe,CAAC,MAAkB,EAAE,WAAmB,EAAE,QAAgB;QACvE,IAAI,CAAC,gBAAgB,CAAC,MAAM,CAAC;YAAE,OAAO;QACtC,IAAI,CAAC;YACH,MAAM,CAAC,IAAI,CAAC;gBACV,IAAI,EAAE,mBAAmB;gBACzB,SAAS,EAAE,IAAI,CAAC,UAAU;gBAC1B,WAAW;gBACX,QAAQ;aACT,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,IAAI,CAAC,kBAAkB,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC3B,OAAO,CAAC,KAAK,CAAC,gDAAgD,EAAG,CAAW,CAAC,OAAO,CAAC,CAAC;YACxF,CAAC;QACH,CAAC;IACH,CAAC;IAED,eAAe,CAAC,MAAkB;QAChC,IAAI,CAAC,gBAAgB,CAAC,MAAM,CAAC;YAAE,OAAO;QACtC,IAAI,CAAC;YACH,MAAM,GAAG,GAA4B;gBACnC,IAAI,EAAE,uBAAuB;gBAC7B,QAAQ,EAAE,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,cAAc,CAAC;aAClD,CAAC;YACF,+DAA+D;YAC/D,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC;YAChD,IAAI,MAAM,EAAE,CAAC;gBACX,GAAG,CAAC,MAAM,GAAG,MAAM,CAAC;YACtB,CAAC;YACD,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACnB,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,IAAI,CAAC,kBAAkB,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC3B,OAAO,CAAC,KAAK,CAAC,6CAA6C,EAAG,CAAW,CAAC,OAAO,CAAC,CAAC;YACrF,CAAC;QACH,CAAC;IACH,CAAC;IAED,kBAAkB;QAChB,KAAK,MAAM,CAAC,EAAE,OAAO,CAAC,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YACvC,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;gBAC5B,IAAI,CAAC,eAAe,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;YACrC,CAAC;QACH,CAAC;IACH,CAAC;IAED,gBAAgB,CAAC,WAAmB,EAAE,QAAgB,EAAE,UAA6B,EAAE;QACrF,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;QAC9C,IAAI,CAAC,OAAO;YAAE,OAAO;QAErB,MAAM,GAAG,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,QAAQ,CAAC,CAAC;QACxD,IAAI,GAAG,KAAK,CAAC,CAAC;YAAE,OAAO;QAEvB,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;QAC3B,IAAI,KAAK,CAAC,eAAe,EAAE,CAAC;YAC1B,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,SAAS,EAAE,KAAK,CAAC,eAA+C,CAAC,CAAC;QACrF,CAAC;QACD,IAAI,KAAK,CAAC,UAAU,EAAE,CAAC;YACrB,IAAI,CAAC;gBACH,EAAE,CAAC,UAAU,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;YAClC,CAAC;YAAC,OAAO,CAAC,EAAE,CAAC;gBACX,IAAK,CAAe,CAAC,IAAI,KAAK,QAAQ;oBACpC,OAAO,CAAC,KAAK,CAAC,mCAAmC,EAAG,CAAW,CAAC,OAAO,CAAC,CAAC;YAC7E,CAAC;YACD,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,GAAG,WAAW,IAAI,QAAQ,EAAE,CAAC,CAAC;QAC3D,CAAC;QACD,OAAO,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;QAEvB,6CAA6C;QAC7C,IAAI,CAAC,oBAAoB,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QAE3C,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACzB,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;QACnC,CAAC;QAED,IAAI,CAAC,OAAO,CAAC,iBAAiB,IAAI,IAAI,CAAC,OAAO,CAAC,IAAI,GAAG,CAAC,EAAE,CAAC;YACxD,IAAI,CAAC,kBAAkB,EAAE,CAAC;QAC5B,CAAC;IACH,CAAC;IAED,iBAAiB,CAAC,WAAmB;QACnC,MAAM,OAAO,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;QAC3D,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;YACxB,IAAI,CAAC,gBAAgB,CAAC,WAAW,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;QAC3C,CAAC;IACH,CAAC;IAED,mBAAmB;QACjB,KAAK,MAAM,CAAC,EAAE,OAAO,CAAC,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YACvC,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;gBAC5B,IAAI,CAAC,gBAAgB,CAAC,KAAK,CAAC,MAAM,CAAC;oBAAE,SAAS;gBAC9C,IAAI,CAAC;oBACH,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,oBAAoB,EAAE,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;gBAC3E,CAAC;gBAAC,OAAO,GAAG,EAAE,CAAC;oBACb,IAAI,CAAC,kBAAkB,CAAC,GAAG,CAAC,EAAE,CAAC;wBAC7B,OAAO,CAAC,KAAK,CAAC,iDAAiD,EAAG,GAAa,CAAC,OAAO,CAAC,CAAC;oBAC3F,CAAC;gBACH,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAED,KAAK;QACH,MAAM,MAAM,GAAiC,EAAE,CAAC;QAChD,KAAK,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YAC3C,MAAM,CAAC,IAAI,CAAC,GAAG;gBACb,WAAW,EAAE,OAAO,CAAC,MAAM;gBAC3B,GAAG,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC7B,aAAa,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,MAAM;aAC1D,CAAC;QACJ,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC;IAED;;OAEG;IACH,mBAAmB;QACjB,MAAM,MAAM,GAA6B,EAAE,CAAC;QAC5C,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;YAC7C,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,CAAC;QAC3B,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,OAAO;QACL,IAAI,IAAI,CAAC,eAAe,EAAE,CAAC;YACzB,YAAY,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;YACnC,IAAI,CAAC,eAAe,GAAG,IAAI,CAAC;QAC9B,CAAC;QACD,gBAAgB,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAClC,gBAAgB,CAAC,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IAC3C,CAAC;CACF"}
@@ -0,0 +1,111 @@
1
+ interface Endpoint {
2
+ host: string;
3
+ port: number;
4
+ remote: boolean;
5
+ }
6
+ interface EndpointInput {
7
+ host: string;
8
+ port: number;
9
+ remote?: boolean;
10
+ }
11
+ interface WrappedEntry {
12
+ key: string;
13
+ host: string;
14
+ port: number;
15
+ remote: boolean;
16
+ }
17
+ interface RoutingStrategy {
18
+ pick(entries: WrappedEntry[], callContext?: unknown): WrappedEntry | WrappedEntry[] | null;
19
+ acquire?(endpointKey: string): void;
20
+ release?(endpointKey: string): void;
21
+ }
22
+ export declare class EndpointResolver {
23
+ private _endpoints;
24
+ private _counters;
25
+ private _strategies;
26
+ private _wrappedCache;
27
+ private _healthStatus;
28
+ private _failureCounts;
29
+ private _failureThreshold;
30
+ constructor();
31
+ /**
32
+ * Set a routing strategy for a specific service.
33
+ * When set, resolve() delegates to the strategy's pick() method
34
+ * instead of using built-in round-robin.
35
+ *
36
+ * The strategy must implement pick(entries, callContext) where entries
37
+ * are wrapped as { key: "host:port", host, port, remote }.
38
+ */
39
+ setStrategy(serviceName: string, strategy: RoutingStrategy): void;
40
+ /**
41
+ * Create an EndpointResolver from environment variables.
42
+ *
43
+ * Parses FORGE_SERVICE_ENDPOINTS first (full endpoint map with host/port/remote).
44
+ * Falls back to FORGE_SERVICE_PORTS (localhost-only port map) when endpoints
45
+ * aren't available.
46
+ */
47
+ static fromEnv(): EndpointResolver;
48
+ /**
49
+ * Resolve an endpoint for a service.
50
+ * Delegates to a configured RoutingStrategy when available,
51
+ * otherwise round-robins across instances.
52
+ */
53
+ resolve(serviceName: string, callContext?: unknown): Endpoint | Endpoint[] | null;
54
+ /**
55
+ * Get all endpoints for a service (used for broadcast/event delivery).
56
+ */
57
+ all(serviceName: string): Endpoint[];
58
+ /**
59
+ * Add or update an endpoint for a service.
60
+ * Used by dynamic registry discovery.
61
+ */
62
+ set(serviceName: string, endpoint: EndpointInput): void;
63
+ /**
64
+ * Remove a specific instance of a service.
65
+ * Used when a remote node goes down.
66
+ */
67
+ remove(serviceName: string, host: string, port: number): void;
68
+ /**
69
+ * COR-C1: Acquire a pending slot for a resolved endpoint.
70
+ * Delegates to the service's routing strategy if it supports acquire().
71
+ * Must be paired with releaseEndpoint() in a finally block.
72
+ */
73
+ acquireEndpoint(serviceName: string, endpointKey: string): void;
74
+ /**
75
+ * COR-C1: Release a pending slot for a resolved endpoint.
76
+ * Delegates to the service's routing strategy if it supports release().
77
+ */
78
+ releaseEndpoint(serviceName: string, endpointKey: string): void;
79
+ /**
80
+ * REG-H2: Update health status for a specific endpoint.
81
+ * Called when the Supervisor pushes health updates or on connection failure feedback.
82
+ */
83
+ setHealthStatus(host: string, port: number, status: 'healthy' | 'degraded' | 'unhealthy' | 'draining'): void;
84
+ /**
85
+ * REG-H2: Get the health status of a specific endpoint.
86
+ */
87
+ getHealthStatus(host: string, port: number): string;
88
+ /**
89
+ * REG-M2: Record a connection failure for an endpoint.
90
+ * After _failureThreshold consecutive failures, the endpoint is marked unhealthy.
91
+ * Returns the current consecutive failure count.
92
+ */
93
+ recordFailure(host: string, port: number): number;
94
+ /**
95
+ * REG-M2: Record a successful connection to an endpoint.
96
+ * Resets the consecutive failure counter and marks the endpoint healthy.
97
+ */
98
+ recordSuccess(host: string, port: number): void;
99
+ /**
100
+ * Check if a service has any known endpoints.
101
+ */
102
+ has(serviceName: string): boolean;
103
+ /**
104
+ * REG-H1: Apply a full endpoint map update (pushed from Supervisor).
105
+ * Merges new/updated endpoints and removes stale ones not present in the update.
106
+ * Only updates remote endpoints to avoid overwriting local colocated/UDS entries.
107
+ */
108
+ applyEndpointUpdate(endpointMap: Record<string, unknown>): void;
109
+ }
110
+ export {};
111
+ //# sourceMappingURL=EndpointResolver.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"EndpointResolver.d.ts","sourceRoot":"","sources":["../../src/core/EndpointResolver.ts"],"names":[],"mappings":"AAaA,UAAU,QAAQ;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,OAAO,CAAC;CACjB;AAED,UAAU,aAAa;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,UAAU,YAAY;IACpB,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,OAAO,CAAC;CACjB;AAED,UAAU,eAAe;IACvB,IAAI,CAAC,OAAO,EAAE,YAAY,EAAE,EAAE,WAAW,CAAC,EAAE,OAAO,GAAG,YAAY,GAAG,YAAY,EAAE,GAAG,IAAI,CAAC;IAC3F,OAAO,CAAC,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IACpC,OAAO,CAAC,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;CACrC;AAWD,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,UAAU,CAA0B;IAC5C,OAAO,CAAC,SAAS,CAAsB;IACvC,OAAO,CAAC,WAAW,CAA+B;IAElD,OAAO,CAAC,aAAa,CAA8B;IAEnD,OAAO,CAAC,aAAa,CAAiE;IAEtF,OAAO,CAAC,cAAc,CAAsB;IAE5C,OAAO,CAAC,iBAAiB,CAAS;;IAYlC;;;;;;;OAOG;IACH,WAAW,CAAC,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,eAAe,GAAG,IAAI;IAOjE;;;;;;OAMG;IACH,MAAM,CAAC,OAAO,IAAI,gBAAgB;IAkDlC;;;;OAIG;IACH,OAAO,CAAC,WAAW,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,OAAO,GAAG,QAAQ,GAAG,QAAQ,EAAE,GAAG,IAAI;IAoDjF;;OAEG;IACH,GAAG,CAAC,WAAW,EAAE,MAAM,GAAG,QAAQ,EAAE;IAIpC;;;OAGG;IACH,GAAG,CAAC,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,aAAa,GAAG,IAAI;IAuBvD;;;OAGG;IACH,MAAM,CAAC,WAAW,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI;IAiB7D;;;;OAIG;IACH,eAAe,CAAC,WAAW,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,IAAI;IAO/D;;;OAGG;IACH,eAAe,CAAC,WAAW,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,IAAI;IAO/D;;;OAGG;IACH,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,GAAG,UAAU,GAAG,WAAW,GAAG,UAAU,GAAG,IAAI;IAW5G;;OAEG;IACH,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM;IAInD;;;;OAIG;IACH,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM;IAWjD;;;OAGG;IACH,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI;IAW/C;;OAEG;IACH,GAAG,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO;IAKjC;;;;OAIG;IACH,mBAAmB,CAAC,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;CA+BhE"}