@zlink-systems/framework 0.26.0 → 0.27.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (521) hide show
  1. package/dist/.tsbuildinfo +1 -1
  2. package/dist/contracts/Common/CoreTypes.d.ts +6 -0
  3. package/dist/contracts/Common/CoreTypes.js +7 -0
  4. package/dist/contracts/Common/index.d.ts +1 -1
  5. package/dist/contracts/Common/index.js +0 -1
  6. package/dist/contracts/Configuration/InternalDefaults.d.ts +8 -0
  7. package/dist/contracts/Configuration/InternalDefaults.js +9 -1
  8. package/dist/contracts/Configuration/Registration.d.ts +13 -2
  9. package/dist/contracts/Configuration/Registration.js +58 -36
  10. package/dist/contracts/Configuration/RegistrationBuilderPolicy.d.ts +13 -1
  11. package/dist/contracts/Configuration/RegistrationBuilderPolicy.js +38 -1
  12. package/dist/contracts/Configuration/RegistrationBuilders.d.ts +2 -3
  13. package/dist/contracts/Configuration/RegistrationBuilders.js +27 -32
  14. package/dist/contracts/Configuration/RegistrationTypes.d.ts +1 -0
  15. package/dist/contracts/Configuration/RegistrationValidators.js +15 -12
  16. package/dist/contracts/Configuration/TimerRegistrationValidator.js +3 -2
  17. package/dist/contracts/Dispatch/ZLinkDispatchOptions.d.ts +1 -1
  18. package/dist/contracts/Handlers/JsonContract.js +10 -4
  19. package/dist/contracts/Locations/Authority.d.ts +1 -1
  20. package/dist/contracts/Locations/Authority.js +3 -2
  21. package/dist/contracts/Locations/Options.js +1 -1
  22. package/dist/contracts/Locations/Stores.d.ts +12 -0
  23. package/dist/contracts/Locations/Stores.js +9 -0
  24. package/dist/contracts/Spots/Contracts.d.ts +1 -1
  25. package/dist/internal.d.ts +4 -0
  26. package/dist/internal.js +15 -1
  27. package/dist/nest-integration.d.ts +4 -2
  28. package/dist/nest-integration.js +14 -4
  29. package/dist/runtime/abort.d.ts +1 -0
  30. package/dist/runtime/abort.js +8 -5
  31. package/dist/runtime/activation-admission.d.ts +1 -2
  32. package/dist/runtime/activation-admission.js +2 -6
  33. package/dist/runtime/actors/actor-authority-payload-codec.d.ts +1 -2
  34. package/dist/runtime/actors/actor-authority-payload-codec.js +34 -18
  35. package/dist/runtime/actors/actor-client.d.ts +2 -2
  36. package/dist/runtime/actors/actor-client.js +42 -143
  37. package/dist/runtime/actors/actor-context.d.ts +3 -5
  38. package/dist/runtime/actors/actor-context.js +13 -11
  39. package/dist/runtime/actors/actor-handoff.d.ts +4 -4
  40. package/dist/runtime/actors/actor-handoff.js +8 -8
  41. package/dist/runtime/actors/actor-lifecycle-snapshot.js +2 -1
  42. package/dist/runtime/actors/actor-local-native-join.d.ts +11 -6
  43. package/dist/runtime/actors/actor-local-native-join.js +83 -105
  44. package/dist/runtime/actors/actor-native-lookup.js +2 -8
  45. package/dist/runtime/actors/actor-packet-relay-wire.d.ts +3 -3
  46. package/dist/runtime/actors/actor-packet-relay-wire.js +5 -3
  47. package/dist/runtime/actors/actor-remote-joiner.d.ts +1 -1
  48. package/dist/runtime/actors/actor-remote-joiner.js +5 -9
  49. package/dist/runtime/actors/actor-remote-wire.js +5 -3
  50. package/dist/runtime/actors/actor-request-deadline.d.ts +3 -0
  51. package/dist/runtime/actors/actor-request-deadline.js +31 -0
  52. package/dist/runtime/actors/actor-retry-delay.js +2 -1
  53. package/dist/runtime/actors/actor-runtime-state.d.ts +9 -21
  54. package/dist/runtime/actors/actor-runtime-state.js +70 -187
  55. package/dist/runtime/actors/bound-session-wire.js +2 -7
  56. package/dist/runtime/actors/deferred-join-completion.d.ts +11 -6
  57. package/dist/runtime/actors/deferred-join-completion.js +1 -0
  58. package/dist/runtime/actors/index.d.ts +9 -7
  59. package/dist/runtime/actors/index.js +87 -69
  60. package/dist/runtime/actors/spot-actor-dispatch.d.ts +3 -3
  61. package/dist/runtime/actors/spot-actor-dispatch.js +25 -10
  62. package/dist/runtime/actors/transferred-actor-rollback.d.ts +3 -5
  63. package/dist/runtime/actors/transferred-actor-rollback.js +9 -42
  64. package/dist/runtime/admission.d.ts +2 -0
  65. package/dist/runtime/admission.js +7 -1
  66. package/dist/runtime/application-jobs/application-job-queue-scope.d.ts +1 -1
  67. package/dist/runtime/application-jobs/application-job-queue-scope.js +1 -1
  68. package/dist/runtime/backend/contracts/index.d.ts +6 -23
  69. package/dist/runtime/backend/mesh-actor-session-node-adapter.js +1 -17
  70. package/dist/runtime/backend/mesh-dispatch-pump.d.ts +1 -2
  71. package/dist/runtime/backend/mesh-dispatch-pump.js +95 -107
  72. package/dist/runtime/backend/node/node-backend-adapter-support.d.ts +1 -1
  73. package/dist/runtime/backend/node/node-backend-adapter-support.js +16 -6
  74. package/dist/runtime/backend/node/node-event-loop-poller.d.ts +2 -2
  75. package/dist/runtime/backend/node/node-event-loop-poller.js +6 -7
  76. package/dist/runtime/backend/node/node-monitor-backend-adapter.js +1 -0
  77. package/dist/runtime/backend/node/node-raw-binding-port.js +40 -16
  78. package/dist/runtime/backend/node/node-raw-mesh-backend.d.ts +14 -15
  79. package/dist/runtime/backend/node/node-raw-mesh-backend.js +146 -118
  80. package/dist/runtime/backend/node/node-socket-backend-adapter.js +3 -2
  81. package/dist/runtime/backend/raw-binding-port.d.ts +1 -1
  82. package/dist/runtime/backend/runtime-values.d.ts +4 -1
  83. package/dist/runtime/backend/runtime-values.js +2 -0
  84. package/dist/runtime/channels/channel-clients.d.ts +20 -8
  85. package/dist/runtime/channels/channel-clients.js +68 -52
  86. package/dist/runtime/channels/channel-envelope-inspection.js +2 -1
  87. package/dist/runtime/channels/channel-envelope.js +47 -29
  88. package/dist/runtime/channels/channel-outbound-operations.d.ts +3 -0
  89. package/dist/runtime/channels/channel-outbound-operations.js +9 -10
  90. package/dist/runtime/channels/channel-receive-loops.d.ts +8 -3
  91. package/dist/runtime/channels/channel-receive-loops.js +27 -6
  92. package/dist/runtime/channels/channel-runtime-lifecycle.d.ts +12 -1
  93. package/dist/runtime/channels/channel-runtime-lifecycle.js +48 -28
  94. package/dist/runtime/channels/channel-runtime-manager.js +5 -2
  95. package/dist/runtime/channels/channel-socket-options.js +3 -2
  96. package/dist/runtime/channels/channel-socket-registry.d.ts +14 -29
  97. package/dist/runtime/channels/channel-socket-registry.js +248 -174
  98. package/dist/runtime/channels/channel-transports.d.ts +11 -17
  99. package/dist/runtime/channels/channel-transports.js +68 -47
  100. package/dist/runtime/channels/client-server-location-runtime.d.ts +1 -1
  101. package/dist/runtime/channels/client-server-location-runtime.js +10 -11
  102. package/dist/runtime/channels/client-server-service-wire.d.ts +7 -2
  103. package/dist/runtime/channels/client-server-service-wire.js +32 -11
  104. package/dist/runtime/channels/dispatch-error-reporter.d.ts +1 -2
  105. package/dist/runtime/channels/dispatch-error-reporter.js +2 -1
  106. package/dist/runtime/channels/fanout-location-runtime.d.ts +16 -3
  107. package/dist/runtime/channels/fanout-location-runtime.js +130 -72
  108. package/dist/runtime/channels/spot-direct-envelope.d.ts +1 -0
  109. package/dist/runtime/channels/spot-direct-envelope.js +4 -3
  110. package/dist/runtime/channels/spot-node-route-transport.js +3 -2
  111. package/dist/runtime/diagnostics/diagnostic-text.d.ts +2 -0
  112. package/dist/runtime/diagnostics/diagnostic-text.js +7 -0
  113. package/dist/runtime/diagnostics/dispatch-error-details.d.ts +3 -0
  114. package/dist/runtime/diagnostics/dispatch-error-details.js +30 -2
  115. package/dist/runtime/diagnostics/flow-context.d.ts +6 -0
  116. package/dist/runtime/diagnostics/flow-context.js +16 -2
  117. package/dist/runtime/diagnostics/index.d.ts +4 -2
  118. package/dist/runtime/diagnostics/index.js +14 -4
  119. package/dist/runtime/diagnostics/message-flow.d.ts +1 -1
  120. package/dist/runtime/diagnostics/message-flow.js +10 -19
  121. package/dist/runtime/diagnostics/runtime-metrics.d.ts +94 -31
  122. package/dist/runtime/diagnostics/runtime-metrics.js +168 -105
  123. package/dist/runtime/diagnostics/runtime-observation-queue.js +3 -2
  124. package/dist/runtime/diagnostics/topology-runtime-projections.d.ts +2 -4
  125. package/dist/runtime/diagnostics/topology-runtime-projections.js +135 -154
  126. package/dist/runtime/disposal.d.ts +5 -0
  127. package/dist/runtime/disposal.js +22 -0
  128. package/dist/runtime/execution/index.d.ts +12 -9
  129. package/dist/runtime/execution/index.js +58 -14
  130. package/dist/runtime/execution/serial-execution-queue.d.ts +8 -2
  131. package/dist/runtime/execution/serial-execution-queue.js +54 -15
  132. package/dist/runtime/execution/state-lane.d.ts +8 -1
  133. package/dist/runtime/execution/state-lane.js +118 -3
  134. package/dist/runtime/foundation/actor-join-recovery-codec.d.ts +3 -0
  135. package/dist/runtime/foundation/actor-join-recovery-codec.js +15 -11
  136. package/dist/runtime/foundation/event-loop-resources.d.ts +2 -24
  137. package/dist/runtime/foundation/event-loop-resources.js +6 -119
  138. package/dist/runtime/foundation/operation-identity.d.ts +2 -0
  139. package/dist/runtime/foundation/operation-identity.js +9 -5
  140. package/dist/runtime/foundation/operation-registry.d.ts +5 -7
  141. package/dist/runtime/foundation/operation-registry.js +34 -44
  142. package/dist/runtime/foundation/raw-service-mesh-runtime.d.ts +8 -5
  143. package/dist/runtime/foundation/raw-service-mesh-runtime.js +62 -83
  144. package/dist/runtime/foundation/runtime-state-projections.d.ts +3 -1
  145. package/dist/runtime/foundation/runtime-state-projections.js +8 -0
  146. package/dist/runtime/foundation/service-authority-payload-codec.js +22 -12
  147. package/dist/runtime/foundation/service-discovery-registry.d.ts +4 -0
  148. package/dist/runtime/foundation/service-discovery-registry.js +22 -3
  149. package/dist/runtime/foundation/service-instance-activation-recovery-codec.js +8 -4
  150. package/dist/runtime/foundation/service-liveness-registry.js +2 -1
  151. package/dist/runtime/foundation/service-maintenance-runtime.d.ts +0 -1
  152. package/dist/runtime/foundation/service-maintenance-runtime.js +0 -6
  153. package/dist/runtime/foundation/service-metadata-codec.js +3 -3
  154. package/dist/runtime/foundation/service-relocation-aggregate-committer.d.ts +2 -5
  155. package/dist/runtime/foundation/service-relocation-aggregate-committer.js +1 -48
  156. package/dist/runtime/foundation/service-relocation-object-owner.js +3 -2
  157. package/dist/runtime/foundation/service-relocation-runtime.js +43 -32
  158. package/dist/runtime/foundation/service-runtime-contracts.d.ts +40 -8
  159. package/dist/runtime/foundation/service-runtime-contracts.js +25 -1
  160. package/dist/runtime/foundation/service-session-binding-ingress-port.d.ts +0 -12
  161. package/dist/runtime/foundation/service-stateful-registry.d.ts +2 -0
  162. package/dist/runtime/foundation/service-stateful-registry.js +10 -2
  163. package/dist/runtime/foundation/service-stateful-runtime.d.ts +26 -25
  164. package/dist/runtime/foundation/service-stateful-runtime.js +217 -204
  165. package/dist/runtime/foundation/service-stateful-wire-codec.d.ts +3 -3
  166. package/dist/runtime/foundation/service-stateful-wire-codec.js +89 -55
  167. package/dist/runtime/foundation/service-topology-registry.d.ts +0 -1
  168. package/dist/runtime/foundation/service-topology-registry.js +17 -32
  169. package/dist/runtime/foundation/service-wire-binary-primitives.d.ts +5 -0
  170. package/dist/runtime/foundation/service-wire-binary-primitives.js +6 -0
  171. package/dist/runtime/foundation/service-wire-codec.js +10 -8
  172. package/dist/runtime/foundation/service-wire-constants.generated.d.ts +1 -0
  173. package/dist/runtime/foundation/service-wire-constants.generated.js +2 -1
  174. package/dist/runtime/foundation/service-wire-m6a-codec.d.ts +2 -0
  175. package/dist/runtime/foundation/service-wire-m6a-codec.js +23 -13
  176. package/dist/runtime/framework-errors-internal.d.ts +2 -1
  177. package/dist/runtime/framework-errors-internal.js +343 -122
  178. package/dist/runtime/handlers/handler-instance-scope.d.ts +3 -1
  179. package/dist/runtime/handlers/handler-instance-scope.js +61 -74
  180. package/dist/runtime/host/actor-packet-relay.d.ts +9 -6
  181. package/dist/runtime/host/actor-packet-relay.js +48 -91
  182. package/dist/runtime/host/actor-placement-coordinator.js +7 -5
  183. package/dist/runtime/host/actor-runtime-options-factory.d.ts +2 -0
  184. package/dist/runtime/host/actor-runtime-options-factory.js +17 -4
  185. package/dist/runtime/host/actor-transfer-runtime.d.ts +16 -18
  186. package/dist/runtime/host/actor-transfer-runtime.js +143 -176
  187. package/dist/runtime/host/application-job-queue.js +16 -33
  188. package/dist/runtime/host/bound-session-relay.js +1 -1
  189. package/dist/runtime/host/channel-runtime-options-factory.js +1 -1
  190. package/dist/runtime/host/index.d.ts +14 -13
  191. package/dist/runtime/host/index.js +190 -157
  192. package/dist/runtime/host/instance-activation-authority.d.ts +2 -3
  193. package/dist/runtime/host/instance-activation-authority.js +17 -45
  194. package/dist/runtime/host/location-runtime-owner.d.ts +1 -1
  195. package/dist/runtime/host/location-runtime-owner.js +2 -2
  196. package/dist/runtime/host/remote-actor-join-receiver.d.ts +2 -2
  197. package/dist/runtime/host/remote-actor-join-receiver.js +1 -14
  198. package/dist/runtime/host/remote-actor-packet-target-store.d.ts +3 -2
  199. package/dist/runtime/host/remote-actor-packet-target-store.js +8 -47
  200. package/dist/runtime/host/remote-bound-session-relay.d.ts +2 -3
  201. package/dist/runtime/host/remote-bound-session-relay.js +7 -20
  202. package/dist/runtime/host/route-mesh-runtime.d.ts +13 -11
  203. package/dist/runtime/host/route-mesh-runtime.js +171 -252
  204. package/dist/runtime/host/runtime-shutdown.d.ts +2 -0
  205. package/dist/runtime/host/runtime-shutdown.js +18 -21
  206. package/dist/runtime/host/service-relocation-control.js +6 -1
  207. package/dist/runtime/host/service-relocation-host-runtime.d.ts +21 -30
  208. package/dist/runtime/host/service-relocation-host-runtime.js +508 -416
  209. package/dist/runtime/host/spot-address-transport.d.ts +2 -3
  210. package/dist/runtime/host/spot-address-transport.js +34 -136
  211. package/dist/runtime/host/spot-node-runtime-options-factory.d.ts +1 -1
  212. package/dist/runtime/host/spot-node-runtime-options-factory.js +3 -2
  213. package/dist/runtime/host/spot-runtime-options-factory.d.ts +4 -10
  214. package/dist/runtime/host/spot-runtime-options-factory.js +50 -14
  215. package/dist/runtime/host/user-spot-creation-coordinator.d.ts +3 -3
  216. package/dist/runtime/host/user-spot-creation-coordinator.js +11 -8
  217. package/dist/runtime/locations/aggregate-inventory-store.js +13 -10
  218. package/dist/runtime/locations/authority-key-codec.js +4 -3
  219. package/dist/runtime/locations/auto-connect-reconciler.d.ts +4 -0
  220. package/dist/runtime/locations/auto-connect-reconciler.js +37 -25
  221. package/dist/runtime/locations/creation-operation-id.js +6 -4
  222. package/dist/runtime/locations/domain-store-contract.d.ts +3 -3
  223. package/dist/runtime/locations/in-memory-authority-store.js +31 -15
  224. package/dist/runtime/locations/in-memory-location-store.d.ts +2 -2
  225. package/dist/runtime/locations/in-memory-location-store.js +17 -14
  226. package/dist/runtime/locations/in-memory-provider-location-store.d.ts +1 -0
  227. package/dist/runtime/locations/in-memory-provider-location-store.js +72 -22
  228. package/dist/runtime/locations/key-codec.js +3 -2
  229. package/dist/runtime/locations/lease-tracker.d.ts +3 -5
  230. package/dist/runtime/locations/lease-tracker.js +7 -11
  231. package/dist/runtime/locations/lifecycle.d.ts +4 -9
  232. package/dist/runtime/locations/lifecycle.js +2 -31
  233. package/dist/runtime/locations/location-store-failure.d.ts +2 -0
  234. package/dist/runtime/locations/location-store-failure.js +7 -0
  235. package/dist/runtime/locations/location-store-pages.d.ts +3 -0
  236. package/dist/runtime/locations/location-store-pages.js +13 -0
  237. package/dist/runtime/locations/location-store-repository.d.ts +5 -7
  238. package/dist/runtime/locations/location-store-repository.js +303 -332
  239. package/dist/runtime/locations/relocation-blob.js +18 -5
  240. package/dist/runtime/locations/resolvers.d.ts +5 -5
  241. package/dist/runtime/locations/resolvers.js +37 -28
  242. package/dist/runtime/locations/runtime.d.ts +5 -4
  243. package/dist/runtime/locations/runtime.js +123 -92
  244. package/dist/runtime/locations/spot-location-claims.d.ts +6 -0
  245. package/dist/runtime/locations/spot-location-claims.js +42 -1
  246. package/dist/runtime/messaging/payload-codec.js +26 -20
  247. package/dist/runtime/messaging/submission-result.d.ts +3 -0
  248. package/dist/runtime/messaging/submission-result.js +48 -0
  249. package/dist/runtime/protocol/service_wire_codec.generated.d.ts +1 -0
  250. package/dist/runtime/protocol/service_wire_codec.generated.js +12 -7
  251. package/dist/runtime/spots/formal-remote-actor-transfer-registry.d.ts +4 -1
  252. package/dist/runtime/spots/index.d.ts +14 -20
  253. package/dist/runtime/spots/index.js +302 -176
  254. package/dist/runtime/spots/spot-activation-registry.d.ts +3 -5
  255. package/dist/runtime/spots/spot-activation-registry.js +14 -50
  256. package/dist/runtime/spots/spot-activation-state.d.ts +1 -1
  257. package/dist/runtime/spots/spot-activation-state.js +2 -2
  258. package/dist/runtime/spots/spot-activation.d.ts +3 -4
  259. package/dist/runtime/spots/spot-activation.js +49 -32
  260. package/dist/runtime/spots/spot-actor-admission-coordinator.d.ts +1 -2
  261. package/dist/runtime/spots/spot-actor-admission-coordinator.js +3 -40
  262. package/dist/runtime/spots/spot-actor-join-dispatch.d.ts +10 -18
  263. package/dist/runtime/spots/spot-actor-join-dispatch.js +4 -52
  264. package/dist/runtime/spots/spot-actor-membership.d.ts +4 -6
  265. package/dist/runtime/spots/spot-actor-membership.js +22 -45
  266. package/dist/runtime/spots/spot-actor-packet-dispatch.d.ts +0 -1
  267. package/dist/runtime/spots/spot-actor-packet-dispatch.js +0 -9
  268. package/dist/runtime/spots/spot-actor-packet-relay-dispatch.d.ts +2 -2
  269. package/dist/runtime/spots/spot-actor-packet-relay-dispatch.js +1 -7
  270. package/dist/runtime/spots/spot-context.d.ts +2 -2
  271. package/dist/runtime/spots/spot-entry-activation.d.ts +2 -2
  272. package/dist/runtime/spots/spot-entry-activation.js +9 -20
  273. package/dist/runtime/spots/spot-lifecycle-metrics.js +3 -2
  274. package/dist/runtime/spots/spot-manager-public.d.ts +5 -6
  275. package/dist/runtime/spots/spot-manager-public.js +5 -4
  276. package/dist/runtime/spots/spot-node-autoconnect.js +22 -31
  277. package/dist/runtime/spots/spot-node-runtime-manager.d.ts +19 -18
  278. package/dist/runtime/spots/spot-node-runtime-manager.js +67 -72
  279. package/dist/runtime/spots/spot-outbound.d.ts +4 -3
  280. package/dist/runtime/spots/spot-outbound.js +9 -8
  281. package/dist/runtime/spots/spot-remote-codec.js +5 -3
  282. package/dist/runtime/spots/spot-route-packet-dispatch.d.ts +2 -2
  283. package/dist/runtime/spots/spot-route-packet-dispatch.js +8 -8
  284. package/dist/runtime/spots/spot-route-replies.d.ts +2 -2
  285. package/dist/runtime/spots/spot-route-replies.js +3 -1
  286. package/dist/runtime/spots/spot-routed-actor-admission.d.ts +3 -3
  287. package/dist/runtime/spots/spot-routed-actor-admission.js +3 -12
  288. package/dist/runtime/spots/spot-routed-frame-dispatch.d.ts +1 -2
  289. package/dist/runtime/spots/spot-routed-frame-dispatch.js +0 -1
  290. package/dist/runtime/spots/spot-routed-spot-packet-dispatch.d.ts +4 -0
  291. package/dist/runtime/spots/spot-routed-spot-packet-dispatch.js +65 -15
  292. package/dist/runtime/spots/spot-runtime-ports.d.ts +2 -16
  293. package/dist/runtime/spots/spot-serial-executor.js +2 -2
  294. package/dist/runtime/spots/spot-serial-turn-executor.d.ts +27 -7
  295. package/dist/runtime/spots/spot-serial-turn-executor.js +83 -11
  296. package/dist/runtime/spots/spot-timer.d.ts +3 -2
  297. package/dist/runtime/streams/actor-session-binding-registry.d.ts +16 -29
  298. package/dist/runtime/streams/actor-session-binding-registry.js +142 -212
  299. package/dist/runtime/streams/actor-session-binding-runtime-owner.d.ts +1 -4
  300. package/dist/runtime/streams/bound-actor-relay-sender.d.ts +6 -2
  301. package/dist/runtime/streams/bound-actor-relay-sender.js +57 -33
  302. package/dist/runtime/streams/bound-session-service.d.ts +7 -0
  303. package/dist/runtime/streams/bound-session-service.js +11 -1
  304. package/dist/runtime/streams/index.d.ts +14 -15
  305. package/dist/runtime/streams/index.js +20 -21
  306. package/dist/runtime/streams/managed-stream.d.ts +3 -0
  307. package/dist/runtime/streams/managed-stream.js +17 -8
  308. package/dist/runtime/streams/native-fallback-bound-session.js +1 -3
  309. package/dist/runtime/streams/protocol.d.ts +6 -33
  310. package/dist/runtime/streams/protocol.js +38 -110
  311. package/dist/runtime/streams/session-actor-coordinator.d.ts +2 -3
  312. package/dist/runtime/streams/session-actor-coordinator.js +12 -4
  313. package/dist/runtime/streams/session-calls.d.ts +1 -1
  314. package/dist/runtime/streams/session-calls.js +5 -4
  315. package/dist/runtime/streams/session-context.d.ts +6 -6
  316. package/dist/runtime/streams/session-context.js +22 -4
  317. package/dist/runtime/streams/session-requests.js +2 -1
  318. package/dist/runtime/streams/stream-binding-runtime-ports.d.ts +16 -1
  319. package/dist/runtime/streams/stream-frame-factory.js +2 -2
  320. package/dist/runtime/streams/stream-session-runtime.d.ts +10 -11
  321. package/dist/runtime/streams/stream-session-runtime.js +25 -33
  322. package/dist/runtime/workers/index.d.ts +2 -2
  323. package/dist/runtime/workers/index.js +5 -4
  324. package/package.json +3 -3
  325. package/src/contracts/Common/CoreTypes.ts +7 -0
  326. package/src/contracts/Common/index.ts +1 -1
  327. package/src/contracts/Configuration/InternalDefaults.ts +12 -0
  328. package/src/contracts/Configuration/Registration.ts +92 -48
  329. package/src/contracts/Configuration/RegistrationBuilderPolicy.ts +44 -2
  330. package/src/contracts/Configuration/RegistrationBuilders.ts +77 -68
  331. package/src/contracts/Configuration/RegistrationTypes.ts +1 -0
  332. package/src/contracts/Configuration/RegistrationValidators.ts +19 -13
  333. package/src/contracts/Configuration/TimerRegistrationValidator.ts +4 -2
  334. package/src/contracts/Dispatch/ZLinkDispatchOptions.ts +1 -0
  335. package/src/contracts/Handlers/JsonContract.ts +14 -4
  336. package/src/contracts/Locations/Authority.ts +7 -3
  337. package/src/contracts/Locations/Options.ts +1 -1
  338. package/src/contracts/Locations/Stores.ts +14 -0
  339. package/src/contracts/Spots/Contracts.ts +1 -1
  340. package/src/internal.ts +14 -0
  341. package/src/nest-integration.ts +28 -10
  342. package/src/runtime/abort.ts +6 -5
  343. package/src/runtime/activation-admission.ts +2 -8
  344. package/src/runtime/actors/actor-authority-payload-codec.ts +58 -20
  345. package/src/runtime/actors/actor-client.ts +77 -204
  346. package/src/runtime/actors/actor-context.ts +39 -33
  347. package/src/runtime/actors/actor-handoff.ts +24 -22
  348. package/src/runtime/actors/actor-lifecycle-snapshot.ts +2 -1
  349. package/src/runtime/actors/actor-local-native-join.ts +172 -174
  350. package/src/runtime/actors/actor-native-lookup.ts +2 -9
  351. package/src/runtime/actors/actor-packet-relay-wire.ts +18 -12
  352. package/src/runtime/actors/actor-remote-joiner.ts +9 -11
  353. package/src/runtime/actors/actor-remote-wire.ts +5 -3
  354. package/src/runtime/actors/actor-request-deadline.ts +49 -0
  355. package/src/runtime/actors/actor-retry-delay.ts +2 -1
  356. package/src/runtime/actors/actor-runtime-state.ts +85 -247
  357. package/src/runtime/actors/bound-session-wire.ts +2 -8
  358. package/src/runtime/actors/deferred-join-completion.ts +10 -6
  359. package/src/runtime/actors/index.ts +100 -79
  360. package/src/runtime/actors/spot-actor-dispatch.ts +60 -29
  361. package/src/runtime/actors/transferred-actor-rollback.ts +11 -62
  362. package/src/runtime/admission.ts +8 -1
  363. package/src/runtime/application-jobs/application-job-queue-scope.ts +4 -4
  364. package/src/runtime/backend/contracts/index.ts +13 -29
  365. package/src/runtime/backend/mesh-actor-session-node-adapter.ts +2 -18
  366. package/src/runtime/backend/mesh-dispatch-pump.ts +111 -117
  367. package/src/runtime/backend/node/node-backend-adapter-support.ts +23 -6
  368. package/src/runtime/backend/node/node-event-loop-poller.ts +8 -12
  369. package/src/runtime/backend/node/node-monitor-backend-adapter.ts +1 -0
  370. package/src/runtime/backend/node/node-raw-binding-port.ts +41 -20
  371. package/src/runtime/backend/node/node-raw-mesh-backend.ts +227 -170
  372. package/src/runtime/backend/node/node-socket-backend-adapter.ts +3 -2
  373. package/src/runtime/backend/raw-binding-port.ts +1 -1
  374. package/src/runtime/backend/runtime-values.ts +4 -1
  375. package/src/runtime/channels/channel-clients.ts +132 -85
  376. package/src/runtime/channels/channel-envelope-inspection.ts +2 -1
  377. package/src/runtime/channels/channel-envelope.ts +58 -29
  378. package/src/runtime/channels/channel-outbound-operations.ts +10 -23
  379. package/src/runtime/channels/channel-receive-loops.ts +39 -7
  380. package/src/runtime/channels/channel-runtime-lifecycle.ts +60 -27
  381. package/src/runtime/channels/channel-runtime-manager.ts +6 -2
  382. package/src/runtime/channels/channel-socket-options.ts +8 -2
  383. package/src/runtime/channels/channel-socket-registry.ts +301 -192
  384. package/src/runtime/channels/channel-transports.ts +161 -112
  385. package/src/runtime/channels/client-server-location-runtime.ts +17 -17
  386. package/src/runtime/channels/client-server-service-wire.ts +40 -12
  387. package/src/runtime/channels/dispatch-error-reporter.ts +7 -5
  388. package/src/runtime/channels/fanout-location-runtime.ts +172 -91
  389. package/src/runtime/channels/spot-direct-envelope.ts +1 -1
  390. package/src/runtime/channels/spot-node-route-transport.ts +5 -2
  391. package/src/runtime/diagnostics/diagnostic-text.ts +4 -0
  392. package/src/runtime/diagnostics/dispatch-error-details.ts +36 -1
  393. package/src/runtime/diagnostics/flow-context.ts +16 -2
  394. package/src/runtime/diagnostics/index.ts +27 -17
  395. package/src/runtime/diagnostics/message-flow.ts +15 -25
  396. package/src/runtime/diagnostics/runtime-metrics.ts +181 -113
  397. package/src/runtime/diagnostics/runtime-observation-queue.ts +3 -2
  398. package/src/runtime/diagnostics/topology-runtime-projections.ts +194 -162
  399. package/src/runtime/disposal.ts +19 -0
  400. package/src/runtime/execution/index.ts +60 -20
  401. package/src/runtime/execution/serial-execution-queue.ts +131 -18
  402. package/src/runtime/execution/state-lane.ts +142 -4
  403. package/src/runtime/foundation/actor-join-recovery-codec.ts +13 -8
  404. package/src/runtime/foundation/event-loop-resources.ts +5 -122
  405. package/src/runtime/foundation/operation-identity.ts +11 -5
  406. package/src/runtime/foundation/operation-registry.ts +33 -50
  407. package/src/runtime/foundation/raw-service-mesh-runtime.ts +110 -111
  408. package/src/runtime/foundation/runtime-state-projections.ts +9 -1
  409. package/src/runtime/foundation/service-authority-payload-codec.ts +31 -13
  410. package/src/runtime/foundation/service-discovery-registry.ts +32 -3
  411. package/src/runtime/foundation/service-instance-activation-recovery-codec.ts +12 -4
  412. package/src/runtime/foundation/service-liveness-registry.ts +2 -1
  413. package/src/runtime/foundation/service-maintenance-runtime.ts +0 -10
  414. package/src/runtime/foundation/service-metadata-codec.ts +2 -2
  415. package/src/runtime/foundation/service-relocation-aggregate-committer.ts +3 -66
  416. package/src/runtime/foundation/service-relocation-object-owner.ts +5 -2
  417. package/src/runtime/foundation/service-relocation-runtime.ts +57 -35
  418. package/src/runtime/foundation/service-runtime-contracts.ts +46 -10
  419. package/src/runtime/foundation/service-session-binding-ingress-port.ts +0 -17
  420. package/src/runtime/foundation/service-stateful-registry.ts +14 -2
  421. package/src/runtime/foundation/service-stateful-runtime.ts +322 -276
  422. package/src/runtime/foundation/service-stateful-wire-codec.ts +128 -80
  423. package/src/runtime/foundation/service-topology-registry.ts +23 -32
  424. package/src/runtime/foundation/service-wire-binary-primitives.ts +6 -0
  425. package/src/runtime/foundation/service-wire-codec.ts +15 -8
  426. package/src/runtime/foundation/service-wire-constants.generated.ts +1 -0
  427. package/src/runtime/foundation/service-wire-m6a-codec.ts +29 -15
  428. package/src/runtime/framework-errors-internal.ts +380 -134
  429. package/src/runtime/handlers/handler-instance-scope.ts +68 -95
  430. package/src/runtime/host/actor-packet-relay.ts +57 -147
  431. package/src/runtime/host/actor-placement-coordinator.ts +8 -5
  432. package/src/runtime/host/actor-runtime-options-factory.ts +27 -8
  433. package/src/runtime/host/actor-transfer-runtime.ts +180 -260
  434. package/src/runtime/host/application-job-queue.ts +28 -34
  435. package/src/runtime/host/bound-session-relay.ts +1 -2
  436. package/src/runtime/host/channel-runtime-options-factory.ts +1 -2
  437. package/src/runtime/host/index.ts +327 -296
  438. package/src/runtime/host/instance-activation-authority.ts +89 -109
  439. package/src/runtime/host/location-runtime-owner.ts +4 -2
  440. package/src/runtime/host/remote-actor-join-receiver.ts +3 -31
  441. package/src/runtime/host/remote-actor-packet-target-store.ts +17 -58
  442. package/src/runtime/host/remote-bound-session-relay.ts +8 -41
  443. package/src/runtime/host/route-mesh-runtime.ts +228 -271
  444. package/src/runtime/host/runtime-shutdown.ts +17 -21
  445. package/src/runtime/host/service-relocation-control.ts +14 -1
  446. package/src/runtime/host/service-relocation-host-runtime.ts +699 -561
  447. package/src/runtime/host/spot-address-transport.ts +73 -195
  448. package/src/runtime/host/spot-node-runtime-options-factory.ts +6 -3
  449. package/src/runtime/host/spot-runtime-options-factory.ts +73 -22
  450. package/src/runtime/host/user-spot-creation-coordinator.ts +36 -22
  451. package/src/runtime/locations/aggregate-inventory-store.ts +16 -13
  452. package/src/runtime/locations/authority-key-codec.ts +7 -3
  453. package/src/runtime/locations/auto-connect-reconciler.ts +39 -26
  454. package/src/runtime/locations/creation-operation-id.ts +6 -3
  455. package/src/runtime/locations/domain-store-contract.ts +12 -3
  456. package/src/runtime/locations/in-memory-authority-store.ts +44 -15
  457. package/src/runtime/locations/in-memory-location-store.ts +50 -39
  458. package/src/runtime/locations/in-memory-provider-location-store.ts +100 -25
  459. package/src/runtime/locations/key-codec.ts +3 -2
  460. package/src/runtime/locations/lease-tracker.ts +8 -14
  461. package/src/runtime/locations/lifecycle.ts +13 -43
  462. package/src/runtime/locations/location-store-failure.ts +4 -0
  463. package/src/runtime/locations/location-store-pages.ts +18 -0
  464. package/src/runtime/locations/location-store-repository.ts +450 -478
  465. package/src/runtime/locations/relocation-blob.ts +17 -6
  466. package/src/runtime/locations/resolvers.ts +75 -49
  467. package/src/runtime/locations/runtime.ts +220 -110
  468. package/src/runtime/locations/spot-location-claims.ts +58 -1
  469. package/src/runtime/messaging/payload-codec.ts +35 -24
  470. package/src/runtime/messaging/submission-result.ts +57 -1
  471. package/src/runtime/protocol/service_wire_codec.generated.ts +18 -8
  472. package/src/runtime/protocol/service_wire_pilot_codec.generated.ts +1 -1
  473. package/src/runtime/spots/formal-remote-actor-transfer-registry.ts +4 -1
  474. package/src/runtime/spots/index.ts +433 -229
  475. package/src/runtime/spots/spot-activation-registry.ts +30 -69
  476. package/src/runtime/spots/spot-activation-state.ts +2 -2
  477. package/src/runtime/spots/spot-activation.ts +67 -37
  478. package/src/runtime/spots/spot-actor-admission-coordinator.ts +5 -57
  479. package/src/runtime/spots/spot-actor-join-dispatch.ts +24 -77
  480. package/src/runtime/spots/spot-actor-membership.ts +40 -72
  481. package/src/runtime/spots/spot-actor-packet-dispatch.ts +0 -16
  482. package/src/runtime/spots/spot-actor-packet-relay-dispatch.ts +3 -15
  483. package/src/runtime/spots/spot-context.ts +3 -3
  484. package/src/runtime/spots/spot-entry-activation.ts +13 -30
  485. package/src/runtime/spots/spot-lifecycle-metrics.ts +3 -2
  486. package/src/runtime/spots/spot-manager-public.ts +21 -17
  487. package/src/runtime/spots/spot-node-autoconnect.ts +20 -26
  488. package/src/runtime/spots/spot-node-runtime-manager.ts +136 -125
  489. package/src/runtime/spots/spot-outbound.ts +45 -23
  490. package/src/runtime/spots/spot-remote-codec.ts +7 -3
  491. package/src/runtime/spots/spot-route-packet-dispatch.ts +25 -24
  492. package/src/runtime/spots/spot-route-replies.ts +6 -4
  493. package/src/runtime/spots/spot-routed-actor-admission.ts +13 -26
  494. package/src/runtime/spots/spot-routed-frame-dispatch.ts +2 -3
  495. package/src/runtime/spots/spot-routed-spot-packet-dispatch.ts +95 -22
  496. package/src/runtime/spots/spot-runtime-ports.ts +5 -27
  497. package/src/runtime/spots/spot-serial-executor.ts +2 -2
  498. package/src/runtime/spots/spot-serial-turn-executor.ts +112 -11
  499. package/src/runtime/spots/spot-timer.ts +3 -2
  500. package/src/runtime/streams/actor-session-binding-registry.ts +179 -269
  501. package/src/runtime/streams/actor-session-binding-runtime-owner.ts +0 -8
  502. package/src/runtime/streams/bound-actor-relay-sender.ts +89 -43
  503. package/src/runtime/streams/bound-session-service.ts +21 -1
  504. package/src/runtime/streams/index.ts +76 -64
  505. package/src/runtime/streams/managed-stream.ts +29 -10
  506. package/src/runtime/streams/native-fallback-bound-session.ts +1 -3
  507. package/src/runtime/streams/protocol.ts +34 -88
  508. package/src/runtime/streams/session-actor-coordinator.ts +17 -5
  509. package/src/runtime/streams/session-calls.ts +6 -5
  510. package/src/runtime/streams/session-context.ts +54 -10
  511. package/src/runtime/streams/session-requests.ts +2 -1
  512. package/src/runtime/streams/stream-binding-runtime-ports.ts +22 -1
  513. package/src/runtime/streams/stream-frame-factory.ts +2 -3
  514. package/src/runtime/streams/stream-session-runtime.ts +57 -59
  515. package/src/runtime/workers/index.ts +13 -12
  516. package/dist/runtime/actors/post-commit-actor-location.d.ts +0 -19
  517. package/dist/runtime/actors/post-commit-actor-location.js +0 -72
  518. package/dist/runtime/spots/spot-native-actor-join-admission.d.ts +0 -26
  519. package/dist/runtime/spots/spot-native-actor-join-admission.js +0 -106
  520. package/src/runtime/actors/post-commit-actor-location.ts +0 -121
  521. package/src/runtime/spots/spot-native-actor-join-admission.ts +0 -155
@@ -1,43 +1,58 @@
1
- import { ZLinkListenerRecords } from '../foundation/listener-records';
1
+ import { RuntimeDisposal } from '../disposal';
2
+ import { UINT64_MAX } from '@zlink-systems/stream-wire';
3
+ import { randomBytes, randomUUID } from 'node:crypto';
2
4
  import {
3
5
  ZLinkFrameworkRuntimeState,
4
6
  type RoutingId,
5
7
  type ZLinkClientServerServerDescriptor,
6
8
  type ZLinkFanoutPublisherDescriptor
7
9
  } from '../../contracts';
8
- import type { ZLinkChannelOptions } from '../../contracts/Configuration/RegistrationTypes';
9
- import { ZLinkSocketNativeEventType } from '../diagnostics/internal-event-contracts';
10
+ import { ZLINK_MAX_ROUTING_ID_BYTES } from '../../contracts/Common/CoreTypes';
11
+ import type { Message } from '../../contracts/Common/Message';
10
12
  import {
11
- buildAdvertisedEndpoint,
12
- ZLinkConfigurationException,
13
- type ZLinkFrameworkRegistration
14
- } from '../configuration';
13
+ isValidPublicWeight,
14
+ ZLINK_DEFAULT_PUBLIC_WEIGHT,
15
+ ZLINK_MAX_PUBLIC_WEIGHT
16
+ } from '../../contracts/Configuration/RegistrationBuilderPolicy';
17
+ import type { ZLinkChannelOptions } from '../../contracts/Configuration/RegistrationTypes';
18
+ import { attachEndpointConnections } from '../../contracts/Configuration/RuntimeEndpointConnections';
19
+ import { createAbortError, throwIfAborted } from '../abort';
15
20
  import type {
16
21
  ZLinkBackendContext,
17
22
  ZLinkBackendDealerSocket,
18
23
  ZLinkBackendPublisherSocket,
19
- ZLinkBackendRouterSocket,
20
24
  ZLinkBackendReadablePoller,
25
+ ZLinkBackendRouterSocket,
21
26
  ZLinkBackendSocketMonitor,
22
27
  ZLinkBackendSocketMonitorEvent,
23
28
  ZLinkBackendSubscriberSocket,
24
29
  ZLinkChannelBackendAdapter,
25
30
  ZLinkMonitoringBackendAdapter
26
31
  } from '../backend/contracts';
27
- import { throwIfAborted } from '../abort';
28
- import { attachEndpointConnections } from '../../contracts/Configuration/RuntimeEndpointConnections';
29
- import { ZLinkRouteMemberSnapshot } from './route-member-snapshot';
30
- import {
31
- ZLinkFrameworkInternalErrorKind,
32
- createInternalFrameworkException
33
- } from '../framework-errors-internal';
34
- import { randomBytes, randomUUID } from 'node:crypto';
35
32
  import { ZLinkBufferMessage as RuntimeMessage } from '../backend/runtime-message';
36
- import type { Message } from '../../contracts/Common/Message';
37
- import { ServiceDiscoveryRegistry } from '../foundation/service-discovery-registry';
33
+ import { isBackendRequestTimeoutError } from '../backend/runtime-values';
34
+ import {
35
+ buildAdvertisedEndpoint,
36
+ ZLinkConfigurationException,
37
+ type ZLinkFrameworkRegistration
38
+ } from '../configuration';
39
+ import { ZLinkSocketNativeEventType } from '../diagnostics/internal-event-contracts';
40
+ import { ZLinkListenerRecords } from '../foundation/listener-records';
38
41
  import { discoveryAvailabilityForRuntimeState } from '../foundation/runtime-state-projections';
42
+ import { ServiceDiscoveryRegistry } from '../foundation/service-discovery-registry';
43
+ import {
44
+ DEFAULT_SERVICE_PEER_TIMEOUT_MS,
45
+ DEFAULT_SERVICE_PROBE_INTERVAL_MS
46
+ } from '../foundation/service-liveness-registry';
39
47
  import { ServiceWireProtocolError } from '../foundation/service-wire-m6a-codec';
40
48
  import {
49
+ createInternalFrameworkException,
50
+ ZLinkFrameworkInternalErrorKind
51
+ } from '../framework-errors-internal';
52
+ import type { ApplicationJobQueue } from '../host/application-job-queue';
53
+ import type { ZLinkChannelEnvelopeHeader } from './channel-envelope';
54
+ import {
55
+ ClientServerRejectReason,
41
56
  decodeClientServerControl,
42
57
  encodeClientServerAdmit,
43
58
  encodeClientServerHello,
@@ -46,6 +61,7 @@ import {
46
61
  encodeClientServerReject,
47
62
  encodeClientServerUpdate,
48
63
  isClientServerControlFrame,
64
+ normalizeClientServerMessageLimit,
49
65
  type ZLinkClientServerAdmission
50
66
  } from './client-server-service-wire';
51
67
  import {
@@ -53,16 +69,13 @@ import {
53
69
  FANOUT_LIVENESS_TOPIC,
54
70
  inspectFanoutInbound
55
71
  } from './fanout-service-wire';
56
- import type { ZLinkChannelEnvelopeHeader } from './channel-envelope';
57
- import type { ApplicationJobQueue } from '../host/application-job-queue';
58
- import { isBackendRequestTimeoutError } from '../backend/runtime-values';
72
+ import { ZLinkRouteMemberSnapshot } from './route-member-snapshot';
59
73
 
60
74
  const MAX_LIFECYCLE_GENERATION = 0x7fff_ffff_ffff_ffffn;
61
- const CLIENT_SERVER_PROBE_INTERVAL_MS = 5_000;
62
- const CLIENT_SERVER_PEER_DEADLINE_MS = 15_000;
63
- const CLIENT_SERVER_READY_WAIT_CAP_MS = 5_000;
64
- const CLIENT_SERVER_READY_POLL_INTERVAL_MS = 5;
65
- const DEFAULT_REQUEST_TIMEOUT_MS = 30_000;
75
+ const CLIENT_SERVER_PROBE_INTERVAL_MS = DEFAULT_SERVICE_PROBE_INTERVAL_MS;
76
+ const CLIENT_SERVER_PEER_DEADLINE_MS = DEFAULT_SERVICE_PEER_TIMEOUT_MS;
77
+ const CLIENT_SERVER_LIVENESS_TICK_MS = 100;
78
+ const DEFAULT_SEND_TIMEOUT_MS = 1_000;
66
79
 
67
80
  export interface ZLinkClientServerServerSocketIdentity {
68
81
  readonly serverRid: string;
@@ -81,8 +94,8 @@ interface ClientServerPhysicalConnection {
81
94
  readonly channelName: string;
82
95
  readonly endpoint: string;
83
96
  readonly dealer: ZLinkBackendDealerSocket;
84
- readonly readablePoller: ZLinkBackendReadablePoller;
85
- readonly monitor: ZLinkBackendSocketMonitor;
97
+ readablePoller?: ZLinkBackendReadablePoller;
98
+ monitor?: ZLinkBackendSocketMonitor;
86
99
  readonly aliases: Set<string>;
87
100
  readonly callbacksByAlias: Map<string, ZLinkClientServerConnectionCallbacks>;
88
101
  physicalConnectionId: symbol;
@@ -103,7 +116,7 @@ interface FanoutPublisherConnection {
103
116
  readonly channelName: string;
104
117
  readonly endpoint: string;
105
118
  readonly subscriber: ZLinkBackendSubscriberSocket;
106
- readonly monitor: ZLinkBackendSocketMonitor;
119
+ monitor?: ZLinkBackendSocketMonitor;
107
120
  readonly callbacks: ZLinkFanoutConnectionCallbacks;
108
121
  readonly physicalConnectionId: symbol;
109
122
  transportReady: boolean;
@@ -155,14 +168,20 @@ export class ZLinkChannelSocketRegistry {
155
168
  outstandingProbeId?: bigint;
156
169
  }
157
170
  >();
158
- private readonly ownedMonitors = new Set<ZLinkBackendSocketMonitor>();
171
+ private readonly disposal = new RuntimeDisposal();
172
+ private readonly ownedResources = new Set<
173
+ | ZLinkBackendSocketMonitor
174
+ | ZLinkBackendReadablePoller
175
+ | ZLinkBackendDealerSocket
176
+ | ZLinkBackendSubscriberSocket
177
+ >();
159
178
  private readonly fanoutConnections = new Map<string, FanoutPublisherConnection>();
160
179
  private readonly fanoutPublisherNextBeacon = new Map<string, number>();
161
180
  private clientServerLivenessTimer?: NodeJS.Timeout;
162
181
  private nextClientServerProbeId = 1n;
163
182
  private readonly clientServerMonitorHandlers = new Map<
164
183
  string,
165
- Set<(event: ZLinkBackendSocketMonitorEvent) => void>
184
+ Set<(event?: ZLinkBackendSocketMonitorEvent) => void>
166
185
  >();
167
186
  private readonly fanoutMonitorHandlers = new Map<
168
187
  string,
@@ -184,10 +203,20 @@ export class ZLinkChannelSocketRegistry {
184
203
  this.listenerRecords = listenerRecords ?? new ZLinkListenerRecords();
185
204
  }
186
205
 
187
- async dispose(): Promise<void> {
206
+ dispose(): Promise<void> {
207
+ return this.disposal.run(() => this.disposeCore());
208
+ }
209
+
210
+ private async disposeCore(): Promise<void> {
211
+ this.clientServerDiscovery.dispose(
212
+ createInternalFrameworkException(
213
+ ZLinkFrameworkInternalErrorKind.RuntimeShutdown,
214
+ 'Channel sockets are shutting down.'
215
+ )
216
+ );
188
217
  const clientServerConnections = [...new Set(this.clientServerConnections.values())];
189
- const clientServerPollers = clientServerConnections.map(
190
- (connection) => connection.readablePoller
218
+ const clientServerPollers = clientServerConnections.flatMap((connection) =>
219
+ connection.readablePoller === undefined ? [] : [connection.readablePoller]
191
220
  );
192
221
  const sockets = [
193
222
  ...this.clientDealers.values(),
@@ -204,8 +233,6 @@ export class ZLinkChannelSocketRegistry {
204
233
  ...this.routeRouters.values()
205
234
  ]))
206
235
  this.unregisterReceiveFlowSocket(socket);
207
- this.clientDealers.clear();
208
- this.clientServerConnections.clear();
209
236
  this.clientServerReadyIdentities.clear();
210
237
  this.clientServerServerDescriptors.clear();
211
238
  this.clientServerPublicWeights.clear();
@@ -215,23 +242,37 @@ export class ZLinkChannelSocketRegistry {
215
242
  this.clientServerMonitorHandlers.clear();
216
243
  this.fanoutMonitorHandlers.clear();
217
244
  this.fanoutTopologyHandlers.clear();
218
- this.fanoutConnections.clear();
219
245
  this.fanoutPublisherNextBeacon.clear();
220
246
  if (this.clientServerLivenessTimer !== undefined) {
221
247
  clearInterval(this.clientServerLivenessTimer);
222
248
  this.clientServerLivenessTimer = undefined;
223
249
  }
224
- this.channelRouters.clear();
225
- this.publishers.clear();
226
- this.routeRouters.clear();
227
250
  this.routeMembers.clear();
228
- const monitors = [...this.ownedMonitors];
229
- this.ownedMonitors.clear();
230
- const cleanup = await Promise.allSettled([
231
- ...clientServerPollers.map((poller) => poller.dispose()),
232
- ...monitors.map((monitor) => monitor.dispose()),
233
- ...sockets.map((socket) => socket.dispose())
234
- ]);
251
+ const cleanup = await Promise.allSettled(
252
+ [...new Set([...clientServerPollers, ...this.ownedResources, ...sockets])].map(
253
+ async (resource) => {
254
+ await resource.dispose();
255
+ this.ownedResources.delete(resource as ZLinkBackendSocketMonitor);
256
+ for (const owners of [
257
+ this.clientDealers,
258
+ this.channelRouters,
259
+ this.publishers,
260
+ this.routeRouters
261
+ ]) {
262
+ for (const [name, owned] of owners) if (owned === resource) owners.delete(name);
263
+ }
264
+ for (const [name, owned] of this.clientServerConnections) {
265
+ if (owned.dealer === resource) this.clientServerConnections.delete(name);
266
+ if (owned.readablePoller === resource) owned.readablePoller = undefined;
267
+ if (owned.monitor === resource) owned.monitor = undefined;
268
+ }
269
+ for (const [name, owned] of this.fanoutConnections) {
270
+ if (owned.subscriber === resource) this.fanoutConnections.delete(name);
271
+ if (owned.monitor === resource) owned.monitor = undefined;
272
+ }
273
+ }
274
+ )
275
+ );
235
276
  const errors = cleanup
236
277
  .filter((result): result is PromiseRejectedResult => result.status === 'rejected')
237
278
  .map((result) => result.reason);
@@ -252,13 +293,16 @@ export class ZLinkChannelSocketRegistry {
252
293
  }
253
294
 
254
295
  const dealer = this.adapter.createDealerSocket(this.context);
296
+ this.clientDealers.set(channelName, dealer);
255
297
  this.registerReceiveFlowSocket(dealer);
256
298
  dealer.setChannelName(channelName);
257
299
  if (channel?.routingId !== undefined && channel.routingId.length > 0) {
258
300
  dealer.setRoutingId(deriveRoutingId(channel.routingId, 'dealer'));
259
301
  }
260
- applySocketConfig(dealer, client);
261
- this.clientDealers.set(channelName, dealer);
302
+ applySocketConfig(dealer, {
303
+ ...client,
304
+ sendTimeoutMs: configuredSendTimeoutMs(client.sendTimeoutMs)
305
+ });
262
306
  return dealer;
263
307
  }
264
308
 
@@ -279,6 +323,7 @@ export class ZLinkChannelSocketRegistry {
279
323
  }
280
324
 
281
325
  const router = this.adapter.createRouterSocket(this.context);
326
+ this.channelRouters.set(channelName, router);
282
327
  this.registerReceiveFlowSocket(router);
283
328
  router.setChannelName(channelName);
284
329
  const identity = this.clientServerIdentities.get(channelName) ?? {
@@ -287,14 +332,14 @@ export class ZLinkChannelSocketRegistry {
287
332
  };
288
333
  this.clientServerIdentities.set(channelName, identity);
289
334
  router.setRoutingId(identity.serverRid);
290
- const publicWeight = channel.server.weight ?? 100;
335
+ const publicWeight = channel.server.weight ?? ZLINK_DEFAULT_PUBLIC_WEIGHT;
291
336
  this.clientServerPublicWeights.set(channelName, publicWeight);
292
337
  router.peerWeight = rawAvailabilityWeight(publicWeight);
293
338
  applySocketConfig(router, channel.server);
294
339
  router.bind(channel.server.bind);
295
340
  if (this.monitoringAdapter !== undefined) {
296
341
  const monitor = this.monitoringAdapter.openSocketMonitor(router);
297
- this.ownedMonitors.add(monitor);
342
+ this.ownedResources.add(monitor);
298
343
  monitor.onEvent((event) => {
299
344
  if (event.routingId === undefined) return;
300
345
  if (
@@ -310,7 +355,6 @@ export class ZLinkChannelSocketRegistry {
310
355
  this.clientServerAdmittedClients.get(channelName)?.delete(routingId);
311
356
  });
312
357
  }
313
- this.channelRouters.set(channelName, router);
314
358
  const endpoint = advertisedEndpoint(
315
359
  router.lastEndpoint ?? channel.server.bind,
316
360
  channel.server.advertiseHost
@@ -358,7 +402,7 @@ export class ZLinkChannelSocketRegistry {
358
402
 
359
403
  clientServerServerWeight(channelName: string): number {
360
404
  this.channelRouter(channelName);
361
- return this.clientServerPublicWeights.get(channelName) ?? 100;
405
+ return this.clientServerPublicWeights.get(channelName) ?? ZLINK_DEFAULT_PUBLIC_WEIGHT;
362
406
  }
363
407
 
364
408
  setClientServerServerWeight(channelName: string, weight: number): void {
@@ -390,46 +434,38 @@ export class ZLinkChannelSocketRegistry {
390
434
  throw new ZLinkConfigurationException(`Channel client '${channelName}' is not registered.`);
391
435
  }
392
436
  const dealer = this.adapter.createDealerSocket(this.context);
393
- this.registerReceiveFlowSocket(dealer);
394
- dealer.setChannelName(channelName);
395
- dealer.setRoutingId(`cs-client-${randomUUID()}`);
396
- applySocketConfig(dealer, client);
397
- const cleanupDealer = (): void => {
398
- this.unregisterReceiveFlowSocket(dealer);
399
- void Promise.allSettled([dealer.dispose()]);
400
- };
401
- let readablePoller: ZLinkBackendReadablePoller;
402
- try {
403
- readablePoller = this.adapter.createReadablePoller(dealer);
404
- } catch (error) {
405
- cleanupDealer();
406
- throw error;
407
- }
408
- let monitor: ZLinkBackendSocketMonitor;
409
- try {
410
- monitor = this.monitoringAdapter.openSocketMonitor(dealer);
411
- } catch (error) {
412
- try {
413
- readablePoller.dispose();
414
- } finally {
415
- cleanupDealer();
416
- }
417
- throw error;
418
- }
419
- this.ownedMonitors.add(monitor);
420
437
  const connection: ClientServerPhysicalConnection = {
421
438
  channelName,
422
439
  endpoint,
423
440
  dealer,
424
- readablePoller,
425
- monitor,
426
441
  aliases: new Set([connectionId]),
427
442
  callbacksByAlias: new Map([[connectionId, callbacks]]),
428
443
  physicalConnectionId: Symbol(connectionId)
429
444
  };
430
- this.clientServerConnections.set(connectionId, connection);
431
- this.ensureClientServerLivenessTimer();
445
+ this.ownedResources.add(dealer);
446
+ const created: (
447
+ | ZLinkBackendSocketMonitor
448
+ | ZLinkBackendReadablePoller
449
+ | ZLinkBackendDealerSocket
450
+ | ZLinkBackendSubscriberSocket
451
+ )[] = [dealer];
432
452
  try {
453
+ this.clientServerConnections.set(connectionId, connection);
454
+ this.registerReceiveFlowSocket(dealer);
455
+ dealer.setChannelName(channelName);
456
+ dealer.setRoutingId(`cs-client-${randomUUID()}`);
457
+ applySocketConfig(dealer, {
458
+ ...client,
459
+ sendTimeoutMs: configuredSendTimeoutMs(client.sendTimeoutMs)
460
+ });
461
+ connection.readablePoller = this.adapter.createReadablePoller(dealer);
462
+ created.push(connection.readablePoller);
463
+ this.ownedResources.add(connection.readablePoller);
464
+ const monitor = this.monitoringAdapter.openSocketMonitor(dealer);
465
+ connection.monitor = monitor;
466
+ created.push(monitor);
467
+ this.ownedResources.add(monitor);
468
+ this.ensureClientServerLivenessTimer();
433
469
  monitor.onEvent((event) => {
434
470
  if (
435
471
  ![...connection.aliases].some(
@@ -464,24 +500,26 @@ export class ZLinkChannelSocketRegistry {
464
500
  }
465
501
  });
466
502
  dealer.connect(endpoint);
503
+ return dealer;
467
504
  } catch (error) {
468
505
  this.clientServerConnections.delete(connectionId);
469
- this.ownedMonitors.delete(monitor);
470
- try {
471
- readablePoller.dispose();
472
- } finally {
473
- cleanupDealer();
474
- void Promise.allSettled([monitor.dispose()]);
475
- }
506
+ this.unregisterReceiveFlowSocket(dealer);
507
+ void Promise.allSettled(
508
+ created.map(async (resource) => {
509
+ await resource.dispose();
510
+ this.ownedResources.delete(resource);
511
+ })
512
+ ).then((results) => {
513
+ for (const result of results)
514
+ if (result.status === 'rejected') this.oneWayFailureSink?.(result.reason);
515
+ });
476
516
  throw error;
477
517
  }
478
- return dealer;
479
518
  }
480
519
 
481
520
  async closeClientServerConnection(connectionId: string): Promise<void> {
482
521
  const current = this.clientServerConnections.get(connectionId);
483
522
  if (current === undefined) return;
484
- this.clientServerConnections.delete(connectionId);
485
523
  current.aliases.delete(connectionId);
486
524
  current.callbacksByAlias.delete(connectionId);
487
525
  const ready = this.clientServerReadyIdentities.get(connectionId);
@@ -507,8 +545,13 @@ export class ZLinkChannelSocketRegistry {
507
545
  });
508
546
  }
509
547
  }
510
- if (current.aliases.size > 0) return;
548
+ this.notifyClientServerTopology(current.channelName);
549
+ if (current.aliases.size > 0) {
550
+ this.clientServerConnections.delete(connectionId);
551
+ return;
552
+ }
511
553
  await this.disposeClientServerPhysical(connectionId, current);
554
+ this.clientServerConnections.delete(connectionId);
512
555
  }
513
556
 
514
557
  private async disposeClientServerPhysical(
@@ -518,12 +561,21 @@ export class ZLinkChannelSocketRegistry {
518
561
  try {
519
562
  current.dealer.disconnect(current.endpoint);
520
563
  } catch {
521
- // Disposal below is the terminal cleanup if the transport already closed.
564
+ // The socket close below releases an endpoint that is already disconnected.
522
565
  }
523
- this.ownedMonitors.delete(current.monitor);
524
566
  this.unregisterReceiveFlowSocket(current.dealer);
525
- current.readablePoller.dispose();
526
- const results = await Promise.allSettled([current.monitor.dispose(), current.dealer.dispose()]);
567
+ if (current.readablePoller !== undefined) {
568
+ current.readablePoller.dispose();
569
+ this.ownedResources.delete(current.readablePoller);
570
+ current.readablePoller = undefined;
571
+ }
572
+ const results = await Promise.allSettled([
573
+ current.monitor?.dispose(),
574
+ (async () => {
575
+ await current.dealer.dispose();
576
+ this.ownedResources.delete(current.dealer);
577
+ })()
578
+ ]);
527
579
  const errors = results
528
580
  .filter((result): result is PromiseRejectedResult => result.status === 'rejected')
529
581
  .map((result) => result.reason);
@@ -531,6 +583,7 @@ export class ZLinkChannelSocketRegistry {
531
583
  if (errors.length > 1) {
532
584
  throw new AggregateError(errors, `ClientServer connection '${connectionId}' cleanup failed.`);
533
585
  }
586
+ if (current.monitor !== undefined) this.ownedResources.delete(current.monitor);
534
587
  }
535
588
 
536
589
  admitClientServerConnection(
@@ -545,6 +598,7 @@ export class ZLinkChannelSocketRegistry {
545
598
  connection.readyConnectionId
546
599
  );
547
600
  if (admitted) connection.admittedDescriptor = descriptor;
601
+ this.notifyClientServerTopology(descriptor.channelName);
548
602
  return admitted;
549
603
  }
550
604
  const duplicateId = [...this.clientServerReadyIdentities].find(
@@ -582,6 +636,7 @@ export class ZLinkChannelSocketRegistry {
582
636
  connection.readyConnectionId = connectionId;
583
637
  connection.admittedDescriptor = descriptor;
584
638
  }
639
+ this.notifyClientServerTopology(descriptor.channelName);
585
640
  return admitted;
586
641
  }
587
642
 
@@ -605,6 +660,7 @@ export class ZLinkChannelSocketRegistry {
605
660
  connection.outstandingProbeId = undefined;
606
661
  }
607
662
  }
663
+ this.notifyClientServerTopology(channelName);
608
664
  return removed;
609
665
  }
610
666
 
@@ -636,52 +692,60 @@ export class ZLinkChannelSocketRegistry {
636
692
  return undefined;
637
693
  }
638
694
 
639
- /**
640
- * Resolves a ClientServer send target, waiting when the ready candidate set is still empty, as
641
- * `framework/doc/framework/common/spec/server/02-channel-transport/02-channel-messaging.ko.md` §3.2 requires: the call waits
642
- * at call time for a bounded period and then fails with no-target. The bound is the shorter of
643
- * the call's remaining deadline and five seconds, mirroring the .NET reference
644
- * `ZLinkClientServerClientRuntime.WaitForReadyAsync`. The wait lives here because this registry
645
- * owns ClientServer connections, admission and weighted selection. Sends have no per-call
646
- * timeout, so they use the Channel's request timeout.
647
- *
648
- * The wait only observes admission that is already in flight: it never opens or reconnects a
649
- * connection, so it cannot trigger the admission it waits for, and Framework startup keeps not
650
- * waiting for local ClientServer admission. It applies whenever nothing is selectable, including
651
- * candidate sets excluded by weight 0 or drain, because `selectClientServerDealer` filters the
652
- * same way the reference `SelectReady()` does.
653
- *
654
- * Every attempt yields to the event loop between polls. ClientServer admission completes on the
655
- * monitor drains that the backend poll timer pumps, so a synchronous wait would starve the
656
- * admission it is waiting for and burn the whole bound before failing anyway. That is this
657
- * execution model's form of the hazard the JVM mirror avoids by not holding the admission
658
- * monitor across its sleep.
659
- */
695
+ /** Observes discovery changes until the client DEALER admission deadline. */
660
696
  async awaitClientDealerForOutbound(
661
697
  channelName: string,
662
- signal?: AbortSignal,
663
- deadlineAtMs?: number
698
+ signal?: AbortSignal
664
699
  ): Promise<ZLinkBackendDealerSocket | undefined> {
665
- const startedAtMs = performance.now();
666
- const deadline = Math.min(
667
- deadlineAtMs ??
668
- startedAtMs +
669
- (this.registration.channels.get(channelName)?.requestTimeoutMs ??
670
- this.registration.requestTimeoutMs ??
671
- DEFAULT_REQUEST_TIMEOUT_MS),
672
- startedAtMs + CLIENT_SERVER_READY_WAIT_CAP_MS
673
- );
674
- for (;;) {
675
- this.drainSocketMonitors();
700
+ throwIfAborted(signal);
701
+ const select = (): ZLinkBackendDealerSocket | undefined => {
676
702
  const dealer = this.clientDealerForOutbound(channelName);
677
703
  if (dealer !== undefined) return dealer;
678
- const remainingMs = deadline - performance.now();
679
- if (remainingMs <= 0) return undefined;
680
- throwIfAborted(signal);
681
- await new Promise<void>((resolve) => {
682
- setTimeout(resolve, Math.min(CLIENT_SERVER_READY_POLL_INTERVAL_MS, remainingMs));
683
- });
684
- }
704
+ if (this.clientServerDiscovery.hasReadyClientServer(channelName)) {
705
+ throw createInternalFrameworkException(
706
+ ZLinkFrameworkInternalErrorKind.RouteNotConnected,
707
+ `Channel '${channelName}' has no eligible ClientServer member.`
708
+ );
709
+ }
710
+ return undefined;
711
+ };
712
+ const dealer = select();
713
+ if (dealer !== undefined) return dealer;
714
+ const sendTimeoutMs = configuredSendTimeoutMs(
715
+ this.registration.channels.get(channelName)?.client?.sendTimeoutMs
716
+ );
717
+ return new Promise((resolve, reject) => {
718
+ const cleanup = (): void => {
719
+ clearTimeout(deadline);
720
+ unsubscribe();
721
+ signal?.removeEventListener('abort', abort);
722
+ };
723
+ const abort = (): void => {
724
+ cleanup();
725
+ reject(createAbortError());
726
+ };
727
+ const changed = (error?: Error): void => {
728
+ try {
729
+ if (error !== undefined) throw error;
730
+ const selected = select();
731
+ if (selected === undefined) return;
732
+ cleanup();
733
+ resolve(selected);
734
+ } catch (error) {
735
+ cleanup();
736
+ reject(error);
737
+ }
738
+ };
739
+ const unsubscribe = this.clientServerDiscovery.onClientServerChanged(changed);
740
+ const deadline = setTimeout(() => {
741
+ cleanup();
742
+ resolve(undefined);
743
+ }, sendTimeoutMs);
744
+ signal?.addEventListener('abort', abort, { once: true });
745
+ // Registration and selection share one event-loop turn; recheck after subscribing.
746
+ changed();
747
+ if (signal?.aborted === true) abort();
748
+ });
685
749
  }
686
750
 
687
751
  startManualClientServerConnections(): void {
@@ -716,26 +780,41 @@ export class ZLinkChannelSocketRegistry {
716
780
  }
717
781
  }
718
782
 
719
- clientServerMonitoringSource(channelName: string): ZLinkBackendSocketMonitor {
720
- if (this.registration.channels.get(channelName)?.client === undefined) {
721
- throw new ZLinkConfigurationException(`Channel client '${channelName}' is not registered.`);
783
+ clientServerMonitoringSource(channelName: string): ZLinkBackendSocketMonitor & {
784
+ onChange(handler: () => void): void;
785
+ } {
786
+ const channel = this.registration.channels.get(channelName);
787
+ if (channel?.client === undefined && channel?.server === undefined) {
788
+ throw new ZLinkConfigurationException(
789
+ `ClientServer channel '${channelName}' is not registered.`
790
+ );
722
791
  }
723
792
  let disposed = false;
724
- let handler: ((event: ZLinkBackendSocketMonitorEvent) => void) | undefined;
793
+ let handler: ((event?: ZLinkBackendSocketMonitorEvent) => void) | undefined;
794
+ const register = (next: (event?: ZLinkBackendSocketMonitorEvent) => void): void => {
795
+ if (disposed) return;
796
+ if (handler !== undefined) {
797
+ this.clientServerMonitorHandlers.get(channelName)?.delete(handler);
798
+ }
799
+ handler = next;
800
+ let handlers = this.clientServerMonitorHandlers.get(channelName);
801
+ if (handlers === undefined) {
802
+ handlers = new Set();
803
+ this.clientServerMonitorHandlers.set(channelName, handlers);
804
+ }
805
+ handlers.add(next);
806
+ };
725
807
  return {
726
808
  nativeInstance: {},
727
809
  onEvent: (next) => {
728
- if (disposed) return;
729
- if (handler !== undefined) {
730
- this.clientServerMonitorHandlers.get(channelName)?.delete(handler);
731
- }
732
- handler = next;
733
- let handlers = this.clientServerMonitorHandlers.get(channelName);
734
- if (handlers === undefined) {
735
- handlers = new Set();
736
- this.clientServerMonitorHandlers.set(channelName, handlers);
737
- }
738
- handlers.add(next);
810
+ register((event) => {
811
+ if (event !== undefined) next(event);
812
+ });
813
+ },
814
+ onChange: (next) => {
815
+ register((event) => {
816
+ if (event === undefined) next();
817
+ });
739
818
  },
740
819
  drain: () => 0,
741
820
  dispose: async () => {
@@ -822,6 +901,11 @@ export class ZLinkChannelSocketRegistry {
822
901
  this.clientServerServerDescriptors.set(channelName, descriptor);
823
902
  this.pushClientServerDescriptorUpdate(channelName, descriptor);
824
903
  }
904
+ this.notifyClientServerTopology(channelName);
905
+ }
906
+
907
+ private notifyClientServerTopology(channelName: string): void {
908
+ for (const handler of this.clientServerMonitorHandlers.get(channelName) ?? []) handler();
825
909
  }
826
910
 
827
911
  tryHandleClientServerControl(
@@ -869,7 +953,7 @@ export class ZLinkChannelSocketRegistry {
869
953
  received.parts.length !== 1 ||
870
954
  received.replyToken === null
871
955
  ) {
872
- reply = encodeClientServerReject(1);
956
+ reply = encodeClientServerReject(ClientServerRejectReason.ProtocolVersionUnsupported);
873
957
  } else {
874
958
  const descriptor = this.clientServerServerDescriptors.get(channelName);
875
959
  if (
@@ -877,10 +961,10 @@ export class ZLinkChannelSocketRegistry {
877
961
  record.hello.channelName !== channelName ||
878
962
  record.hello.securityIdentity !== descriptor.securityIdentity
879
963
  ) {
880
- reply = encodeClientServerReject(3);
964
+ reply = encodeClientServerReject(ClientServerRejectReason.AdmissionMismatch);
881
965
  } else {
882
966
  const normalizedEffectiveMaxMessageBytes = Math.min(
883
- normalizedMessageLimit(router.maxMessageSize),
967
+ normalizeClientServerMessageLimit(router.maxMessageSize),
884
968
  record.hello.normalizedEffectiveMaxMessageBytes
885
969
  );
886
970
  reply = encodeClientServerAdmit(descriptor, normalizedEffectiveMaxMessageBytes);
@@ -966,23 +1050,31 @@ export class ZLinkChannelSocketRegistry {
966
1050
  );
967
1051
  }
968
1052
  const subscriber = this.adapter.createSubscriberSocket(this.context);
969
- subscriber.setChannelName(channelName);
970
- setFanoutSubscriptions(subscriber, channel.subscriptions);
971
- const monitor = this.monitoringAdapter.openSocketMonitor(subscriber);
972
1053
  const connection: FanoutPublisherConnection = {
973
1054
  channelName,
974
1055
  endpoint,
975
1056
  subscriber,
976
- monitor,
977
1057
  callbacks,
978
1058
  physicalConnectionId: Symbol(connectionId),
979
1059
  transportReady: false,
980
1060
  ready: false
981
1061
  };
982
- this.fanoutConnections.set(connectionId, connection);
983
- this.ownedMonitors.add(monitor);
984
- this.ensureClientServerLivenessTimer();
1062
+ this.ownedResources.add(subscriber);
1063
+ const created: (
1064
+ | ZLinkBackendSocketMonitor
1065
+ | ZLinkBackendReadablePoller
1066
+ | ZLinkBackendDealerSocket
1067
+ | ZLinkBackendSubscriberSocket
1068
+ )[] = [subscriber];
985
1069
  try {
1070
+ this.fanoutConnections.set(connectionId, connection);
1071
+ subscriber.setChannelName(channelName);
1072
+ setFanoutSubscriptions(subscriber, channel.subscriptions);
1073
+ const monitor = this.monitoringAdapter.openSocketMonitor(subscriber);
1074
+ connection.monitor = monitor;
1075
+ created.push(monitor);
1076
+ this.ownedResources.add(monitor);
1077
+ this.ensureClientServerLivenessTimer();
986
1078
  monitor.onEvent((event) => {
987
1079
  if (this.fanoutConnections.get(connectionId) !== connection) return;
988
1080
  for (const handler of this.fanoutMonitorHandlers.get(channelName) ?? []) {
@@ -1006,28 +1098,36 @@ export class ZLinkChannelSocketRegistry {
1006
1098
  }
1007
1099
  });
1008
1100
  subscriber.connect(endpoint);
1101
+ return subscriber;
1009
1102
  } catch (error) {
1010
1103
  this.fanoutConnections.delete(connectionId);
1011
- this.ownedMonitors.delete(monitor);
1012
- void Promise.allSettled([monitor.dispose(), subscriber.dispose()]);
1104
+ void Promise.allSettled(
1105
+ created.map(async (resource) => {
1106
+ await resource.dispose();
1107
+ this.ownedResources.delete(resource);
1108
+ })
1109
+ ).then((results) => {
1110
+ for (const result of results)
1111
+ if (result.status === 'rejected') this.oneWayFailureSink?.(result.reason);
1112
+ });
1013
1113
  throw error;
1014
1114
  }
1015
- return subscriber;
1016
1115
  }
1017
1116
 
1018
1117
  async closeFanoutSubscriberConnection(connectionId: string): Promise<void> {
1019
1118
  const connection = this.fanoutConnections.get(connectionId);
1020
1119
  if (connection === undefined) return;
1021
- this.fanoutConnections.delete(connectionId);
1022
1120
  try {
1023
1121
  connection.subscriber.disconnect(connection.endpoint);
1024
1122
  } catch {
1025
- // Disposal remains the terminal cleanup path.
1123
+ // The socket close below releases an endpoint that is already disconnected.
1026
1124
  }
1027
- this.ownedMonitors.delete(connection.monitor);
1028
1125
  const results = await Promise.allSettled([
1029
- connection.monitor.dispose(),
1030
- connection.subscriber.dispose()
1126
+ connection.monitor?.dispose(),
1127
+ (async () => {
1128
+ await connection.subscriber.dispose();
1129
+ this.ownedResources.delete(connection.subscriber);
1130
+ })()
1031
1131
  ]);
1032
1132
  const errors = results
1033
1133
  .filter((result): result is PromiseRejectedResult => result.status === 'rejected')
@@ -1036,6 +1136,8 @@ export class ZLinkChannelSocketRegistry {
1036
1136
  if (errors.length > 1) {
1037
1137
  throw new AggregateError(errors, `Fanout connection '${connectionId}' cleanup failed.`);
1038
1138
  }
1139
+ this.fanoutConnections.delete(connectionId);
1140
+ if (connection.monitor !== undefined) this.ownedResources.delete(connection.monitor);
1039
1141
  }
1040
1142
 
1041
1143
  handleFanoutInbound(
@@ -1156,7 +1258,7 @@ export class ZLinkChannelSocketRegistry {
1156
1258
  };
1157
1259
  }
1158
1260
 
1159
- private notifyFanoutTopology(channelName: string): void {
1261
+ notifyFanoutTopology(channelName: string): void {
1160
1262
  for (const handler of this.fanoutTopologyHandlers.get(channelName) ?? []) {
1161
1263
  try {
1162
1264
  handler();
@@ -1285,7 +1387,7 @@ export class ZLinkChannelSocketRegistry {
1285
1387
  connection: ClientServerPhysicalConnection
1286
1388
  ): void {
1287
1389
  for (;;) {
1288
- if (!connection.readablePoller.wait(0)) return;
1390
+ if (connection.readablePoller === undefined || !connection.readablePoller.wait(0)) return;
1289
1391
  const received = connection.dealer.recv(1);
1290
1392
  if (received === undefined) {
1291
1393
  connection.readablePoller.markDrained();
@@ -1417,12 +1519,15 @@ export class ZLinkChannelSocketRegistry {
1417
1519
 
1418
1520
  private ensureClientServerLivenessTimer(): void {
1419
1521
  if (this.clientServerLivenessTimer !== undefined) return;
1420
- this.clientServerLivenessTimer = setInterval(() => this.tickClientServerLiveness(), 100);
1522
+ this.clientServerLivenessTimer = setInterval(
1523
+ () => this.tickClientServerLiveness(),
1524
+ CLIENT_SERVER_LIVENESS_TICK_MS
1525
+ );
1421
1526
  this.clientServerLivenessTimer.unref();
1422
1527
  }
1423
1528
 
1424
1529
  private drainSocketMonitors(): void {
1425
- for (const monitor of this.ownedMonitors) monitor.drain();
1530
+ for (const monitor of this.ownedResources) if ('drain' in monitor) monitor.drain();
1426
1531
  }
1427
1532
 
1428
1533
  private removeReadyConnection(connectionId: string): void {
@@ -1443,6 +1548,7 @@ export class ZLinkChannelSocketRegistry {
1443
1548
  connection.nextProbeAt = undefined;
1444
1549
  connection.outstandingProbeId = undefined;
1445
1550
  }
1551
+ this.notifyClientServerTopology(identity.channelName);
1446
1552
  }
1447
1553
 
1448
1554
  private requestClientServerLiveness(
@@ -1590,7 +1696,7 @@ export class ZLinkChannelSocketRegistry {
1590
1696
 
1591
1697
  private allocateClientServerProbeId(): bigint {
1592
1698
  const result = this.nextClientServerProbeId;
1593
- this.nextClientServerProbeId = result === 0xffff_ffff_ffff_ffffn ? 1n : result + 1n;
1699
+ this.nextClientServerProbeId = result === UINT64_MAX ? 1n : result + 1n;
1594
1700
  return result;
1595
1701
  }
1596
1702
 
@@ -1613,10 +1719,10 @@ export class ZLinkChannelSocketRegistry {
1613
1719
  }
1614
1720
 
1615
1721
  const publisher = this.adapter.createPublisherSocket(this.context);
1722
+ this.publishers.set(channelName, publisher);
1616
1723
  publisher.setChannelName(channelName);
1617
1724
  applyFanoutPublisherSocketOptions(publisher, channel);
1618
1725
  publisher.bind(channel.publisher.bind);
1619
- this.publishers.set(channelName, publisher);
1620
1726
  const endpoint = buildAdvertisedEndpoint(
1621
1727
  publisher.lastEndpoint ?? channel.publisher.bind,
1622
1728
  channel.publisher.advertiseHost
@@ -1645,6 +1751,7 @@ export class ZLinkChannelSocketRegistry {
1645
1751
  );
1646
1752
  }
1647
1753
  const router = this.adapter.createRouterSocket(this.context);
1754
+ this.routeRouters.set(routerChannelId, router);
1648
1755
  this.registerReceiveFlowSocket(router);
1649
1756
  router.setChannelName(routerChannelId);
1650
1757
  if (
@@ -1656,7 +1763,7 @@ export class ZLinkChannelSocketRegistry {
1656
1763
  router.setRoutingId(
1657
1764
  routeChannel.routingId ?? `${routeChannel.routingIdPrefix ?? routerChannelId}-${randomUUID()}`
1658
1765
  );
1659
- const publicWeight = routeChannel.weight ?? 100;
1766
+ const publicWeight = routeChannel.weight ?? ZLINK_DEFAULT_PUBLIC_WEIGHT;
1660
1767
  this.routeMeshPublicWeights.set(routerChannelId, publicWeight);
1661
1768
  router.peerWeight = rawAvailabilityWeight(publicWeight);
1662
1769
  applySocketConfig(router, routeChannel);
@@ -1670,7 +1777,6 @@ export class ZLinkChannelSocketRegistry {
1670
1777
  if (routeChannel.bind !== undefined && routeChannel.bind.trim().length > 0) {
1671
1778
  router.bind(routeChannel.bind);
1672
1779
  }
1673
- this.routeRouters.set(routerChannelId, router);
1674
1780
  return router;
1675
1781
  }
1676
1782
 
@@ -1680,7 +1786,7 @@ export class ZLinkChannelSocketRegistry {
1680
1786
 
1681
1787
  routeMeshWeight(routerChannelId: string): number {
1682
1788
  this.routeRouter(routerChannelId);
1683
- return this.routeMeshPublicWeights.get(routerChannelId) ?? 100;
1789
+ return this.routeMeshPublicWeights.get(routerChannelId) ?? ZLINK_DEFAULT_PUBLIC_WEIGHT;
1684
1790
  }
1685
1791
 
1686
1792
  setRouteMeshWeight(routerChannelId: string, weight: number): void {
@@ -1717,7 +1823,7 @@ export class ZLinkChannelSocketRegistry {
1717
1823
  return;
1718
1824
  }
1719
1825
  const monitor = this.monitoringAdapter.openSocketMonitor(socket);
1720
- this.ownedMonitors.add(monitor);
1826
+ this.ownedResources.add(monitor);
1721
1827
  monitor.onEvent((event) => {
1722
1828
  if (
1723
1829
  event.nativeEvent === ZLinkSocketNativeEventType.Disconnected &&
@@ -1733,7 +1839,7 @@ export class ZLinkChannelSocketRegistry {
1733
1839
  return;
1734
1840
  }
1735
1841
  const monitor = this.monitoringAdapter.openSocketMonitor(router);
1736
- this.ownedMonitors.add(monitor);
1842
+ this.ownedResources.add(monitor);
1737
1843
  monitor.onEvent((event) => {
1738
1844
  const routingId = event.routingId === undefined ? undefined : String(event.routingId);
1739
1845
  if (
@@ -1775,7 +1881,7 @@ async function requestClientServerAdmission(
1775
1881
  encodeClientServerHello({
1776
1882
  channelName,
1777
1883
  securityIdentity,
1778
- normalizedEffectiveMaxMessageBytes: normalizedMessageLimit(dealer.maxMessageSize)
1884
+ normalizedEffectiveMaxMessageBytes: normalizeClientServerMessageLimit(dealer.maxMessageSize)
1779
1885
  })
1780
1886
  );
1781
1887
  try {
@@ -1853,9 +1959,9 @@ function setFanoutSubscriptions(
1853
1959
 
1854
1960
  function deriveRoutingId(baseRoutingId: string, suffix: string): string {
1855
1961
  const derived = `${baseRoutingId}\0${suffix}`;
1856
- if (Buffer.byteLength(derived, 'utf8') > 255) {
1962
+ if (Buffer.byteLength(derived, 'utf8') > ZLINK_MAX_ROUTING_ID_BYTES) {
1857
1963
  throw new ZLinkConfigurationException(
1858
- `Derived routing id with suffix '${suffix}' exceeds the 255 byte limit.`
1964
+ `Derived routing id with suffix '${suffix}' exceeds the ${ZLINK_MAX_ROUTING_ID_BYTES} byte limit.`
1859
1965
  );
1860
1966
  }
1861
1967
  return derived;
@@ -1866,6 +1972,7 @@ function applyFanoutPublisherSocketOptions(
1866
1972
  channel: ZLinkChannelOptions
1867
1973
  ): void {
1868
1974
  publisher.noDrop = channel.noDrop ?? false;
1975
+ publisher.sendTimeoutMs = configuredSendTimeoutMs(channel.publisher?.sendTimeoutMs);
1869
1976
  }
1870
1977
 
1871
1978
  function fanoutDiscoveryConnectionId(connectionId: string): string {
@@ -1889,13 +1996,11 @@ function advertisedEndpoint(boundEndpoint: string, advertiseHost: string | undef
1889
1996
  return result;
1890
1997
  }
1891
1998
 
1892
- function normalizedMessageLimit(value: number): number {
1893
- return Number.isSafeInteger(value) && value > 0 ? Math.min(value, 0xffff_ffff) : 0x7fff_ffff;
1894
- }
1895
-
1896
1999
  function requirePublicWeight(weight: number): void {
1897
- if (!Number.isInteger(weight) || weight < 0 || weight > 10_000) {
1898
- throw new ZLinkConfigurationException('Weight must be an integer in 0..10000.');
2000
+ if (!isValidPublicWeight(weight)) {
2001
+ throw new ZLinkConfigurationException(
2002
+ `Weight must be an integer in 0..${ZLINK_MAX_PUBLIC_WEIGHT}.`
2003
+ );
1899
2004
  }
1900
2005
  }
1901
2006
 
@@ -1931,3 +2036,7 @@ function applySocketConfig(
1931
2036
  socket.maxMessageSize = config.maxMessageSize;
1932
2037
  }
1933
2038
  }
2039
+
2040
+ function configuredSendTimeoutMs(value: number | undefined): number {
2041
+ return value ?? DEFAULT_SEND_TIMEOUT_MS;
2042
+ }