@zlink-systems/framework 0.25.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 (557) hide show
  1. package/dist/.tsbuildinfo +1 -1
  2. package/dist/contracts/Channels/IZLinkFanoutClient.d.ts +0 -6
  3. package/dist/contracts/Common/CoreTypes.d.ts +6 -0
  4. package/dist/contracts/Common/CoreTypes.js +7 -0
  5. package/dist/contracts/Common/index.d.ts +1 -1
  6. package/dist/contracts/Common/index.js +0 -1
  7. package/dist/contracts/Configuration/InternalDefaults.d.ts +8 -0
  8. package/dist/contracts/Configuration/InternalDefaults.js +9 -1
  9. package/dist/contracts/Configuration/Registration.d.ts +13 -2
  10. package/dist/contracts/Configuration/Registration.js +58 -36
  11. package/dist/contracts/Configuration/RegistrationBuilderPolicy.d.ts +13 -1
  12. package/dist/contracts/Configuration/RegistrationBuilderPolicy.js +38 -1
  13. package/dist/contracts/Configuration/RegistrationBuilders.d.ts +2 -3
  14. package/dist/contracts/Configuration/RegistrationBuilders.js +27 -32
  15. package/dist/contracts/Configuration/RegistrationTypes.d.ts +1 -0
  16. package/dist/contracts/Configuration/RegistrationValidators.js +15 -12
  17. package/dist/contracts/Configuration/TimerRegistrationValidator.js +3 -2
  18. package/dist/contracts/Dispatch/ZLinkDispatchOptions.d.ts +1 -1
  19. package/dist/contracts/Handlers/JsonContract.js +10 -4
  20. package/dist/contracts/Locations/Authority.d.ts +1 -1
  21. package/dist/contracts/Locations/Authority.js +3 -2
  22. package/dist/contracts/Locations/Options.js +1 -1
  23. package/dist/contracts/Locations/Stores.d.ts +12 -0
  24. package/dist/contracts/Locations/Stores.js +9 -0
  25. package/dist/contracts/RouteMesh/RuntimeTopology.d.ts +8 -0
  26. package/dist/contracts/Spots/Contracts.d.ts +1 -1
  27. package/dist/internal.d.ts +5 -0
  28. package/dist/internal.js +16 -1
  29. package/dist/nest-integration.d.ts +4 -2
  30. package/dist/nest-integration.js +14 -4
  31. package/dist/runtime/abort.d.ts +1 -0
  32. package/dist/runtime/abort.js +8 -5
  33. package/dist/runtime/activation-admission.d.ts +28 -0
  34. package/dist/runtime/activation-admission.js +57 -0
  35. package/dist/runtime/actors/actor-authority-payload-codec.d.ts +1 -2
  36. package/dist/runtime/actors/actor-authority-payload-codec.js +34 -18
  37. package/dist/runtime/actors/actor-client.d.ts +2 -2
  38. package/dist/runtime/actors/actor-client.js +42 -143
  39. package/dist/runtime/actors/actor-context.d.ts +3 -5
  40. package/dist/runtime/actors/actor-context.js +19 -17
  41. package/dist/runtime/actors/actor-handoff.d.ts +13 -7
  42. package/dist/runtime/actors/actor-handoff.js +36 -25
  43. package/dist/runtime/actors/actor-lifecycle-snapshot.js +2 -1
  44. package/dist/runtime/actors/actor-local-native-join.d.ts +11 -6
  45. package/dist/runtime/actors/actor-local-native-join.js +85 -123
  46. package/dist/runtime/actors/actor-native-lookup.js +2 -8
  47. package/dist/runtime/actors/actor-packet-relay-wire.d.ts +3 -3
  48. package/dist/runtime/actors/actor-packet-relay-wire.js +5 -3
  49. package/dist/runtime/actors/actor-remote-joiner.d.ts +3 -3
  50. package/dist/runtime/actors/actor-remote-joiner.js +11 -17
  51. package/dist/runtime/actors/actor-remote-wire.js +5 -3
  52. package/dist/runtime/actors/actor-request-deadline.d.ts +3 -0
  53. package/dist/runtime/actors/actor-request-deadline.js +31 -0
  54. package/dist/runtime/actors/actor-retry-delay.js +2 -1
  55. package/dist/runtime/actors/actor-runtime-contracts.d.ts +4 -2
  56. package/dist/runtime/actors/actor-runtime-state.d.ts +9 -21
  57. package/dist/runtime/actors/actor-runtime-state.js +70 -187
  58. package/dist/runtime/actors/actor-source-transfer.d.ts +5 -5
  59. package/dist/runtime/actors/bound-session-wire.js +2 -7
  60. package/dist/runtime/actors/deferred-join-completion.d.ts +19 -0
  61. package/dist/runtime/actors/deferred-join-completion.js +21 -0
  62. package/dist/runtime/actors/index.d.ts +10 -8
  63. package/dist/runtime/actors/index.js +101 -73
  64. package/dist/runtime/actors/spot-actor-dispatch.d.ts +3 -3
  65. package/dist/runtime/actors/spot-actor-dispatch.js +25 -10
  66. package/dist/runtime/actors/transferred-actor-rollback.d.ts +3 -5
  67. package/dist/runtime/actors/transferred-actor-rollback.js +9 -42
  68. package/dist/runtime/admission.d.ts +7 -1
  69. package/dist/runtime/admission.js +11 -1
  70. package/dist/runtime/application-jobs/application-job-queue-scope.d.ts +1 -1
  71. package/dist/runtime/application-jobs/application-job-queue-scope.js +1 -1
  72. package/dist/runtime/backend/contracts/index.d.ts +8 -33
  73. package/dist/runtime/backend/mesh-actor-session-node-adapter.js +3 -26
  74. package/dist/runtime/backend/mesh-dispatch-pump.d.ts +1 -2
  75. package/dist/runtime/backend/mesh-dispatch-pump.js +95 -107
  76. package/dist/runtime/backend/node/node-backend-adapter-factory.d.ts +1 -2
  77. package/dist/runtime/backend/node/node-backend-adapter-factory.js +4 -18
  78. package/dist/runtime/backend/node/node-backend-adapter-support.d.ts +7 -4
  79. package/dist/runtime/backend/node/node-backend-adapter-support.js +28 -34
  80. package/dist/runtime/backend/node/node-event-loop-poller.d.ts +2 -2
  81. package/dist/runtime/backend/node/node-event-loop-poller.js +11 -6
  82. package/dist/runtime/backend/node/node-monitor-backend-adapter.js +1 -0
  83. package/dist/runtime/backend/node/node-raw-binding-port.d.ts +1 -1
  84. package/dist/runtime/backend/node/node-raw-binding-port.js +51 -19
  85. package/dist/runtime/backend/node/node-raw-mesh-backend.d.ts +21 -19
  86. package/dist/runtime/backend/node/node-raw-mesh-backend.js +171 -111
  87. package/dist/runtime/backend/node/node-socket-backend-adapter.js +4 -3
  88. package/dist/runtime/backend/raw-binding-port.d.ts +13 -1
  89. package/dist/runtime/backend/runtime-values.d.ts +4 -1
  90. package/dist/runtime/backend/runtime-values.js +2 -0
  91. package/dist/runtime/channels/channel-clients.d.ts +20 -9
  92. package/dist/runtime/channels/channel-clients.js +68 -60
  93. package/dist/runtime/channels/channel-envelope-inspection.js +2 -1
  94. package/dist/runtime/channels/channel-envelope.js +47 -29
  95. package/dist/runtime/channels/channel-outbound-operations.d.ts +3 -0
  96. package/dist/runtime/channels/channel-outbound-operations.js +9 -18
  97. package/dist/runtime/channels/channel-receive-loops.d.ts +8 -3
  98. package/dist/runtime/channels/channel-receive-loops.js +27 -6
  99. package/dist/runtime/channels/channel-runtime-lifecycle.d.ts +12 -1
  100. package/dist/runtime/channels/channel-runtime-lifecycle.js +48 -28
  101. package/dist/runtime/channels/channel-runtime-manager.d.ts +2 -5
  102. package/dist/runtime/channels/channel-runtime-manager.js +4 -12
  103. package/dist/runtime/channels/channel-socket-options.js +3 -2
  104. package/dist/runtime/channels/channel-socket-registry.d.ts +30 -32
  105. package/dist/runtime/channels/channel-socket-registry.js +296 -235
  106. package/dist/runtime/channels/channel-transports.d.ts +11 -20
  107. package/dist/runtime/channels/channel-transports.js +68 -47
  108. package/dist/runtime/channels/client-server-location-runtime.d.ts +1 -1
  109. package/dist/runtime/channels/client-server-location-runtime.js +10 -11
  110. package/dist/runtime/channels/client-server-service-wire.d.ts +7 -2
  111. package/dist/runtime/channels/client-server-service-wire.js +32 -11
  112. package/dist/runtime/channels/dispatch-error-reporter.d.ts +1 -2
  113. package/dist/runtime/channels/dispatch-error-reporter.js +2 -1
  114. package/dist/runtime/channels/fanout-location-runtime.d.ts +16 -3
  115. package/dist/runtime/channels/fanout-location-runtime.js +133 -81
  116. package/dist/runtime/channels/spot-direct-envelope.d.ts +1 -0
  117. package/dist/runtime/channels/spot-direct-envelope.js +4 -3
  118. package/dist/runtime/channels/spot-node-route-transport.js +3 -2
  119. package/dist/runtime/diagnostics/diagnostic-text.d.ts +2 -0
  120. package/dist/runtime/diagnostics/diagnostic-text.js +7 -0
  121. package/dist/runtime/diagnostics/dispatch-error-details.d.ts +3 -0
  122. package/dist/runtime/diagnostics/dispatch-error-details.js +30 -2
  123. package/dist/runtime/diagnostics/flow-context.d.ts +6 -0
  124. package/dist/runtime/diagnostics/flow-context.js +16 -2
  125. package/dist/runtime/diagnostics/index.d.ts +4 -2
  126. package/dist/runtime/diagnostics/index.js +14 -4
  127. package/dist/runtime/diagnostics/message-flow.d.ts +1 -1
  128. package/dist/runtime/diagnostics/message-flow.js +10 -19
  129. package/dist/runtime/diagnostics/runtime-metrics.d.ts +94 -31
  130. package/dist/runtime/diagnostics/runtime-metrics.js +168 -105
  131. package/dist/runtime/diagnostics/runtime-observation-queue.js +3 -2
  132. package/dist/runtime/diagnostics/topology-runtime-projections.d.ts +2 -4
  133. package/dist/runtime/diagnostics/topology-runtime-projections.js +135 -154
  134. package/dist/runtime/disposal.d.ts +5 -0
  135. package/dist/runtime/disposal.js +22 -0
  136. package/dist/runtime/execution/index.d.ts +22 -9
  137. package/dist/runtime/execution/index.js +107 -37
  138. package/dist/runtime/execution/serial-execution-queue.d.ts +12 -7
  139. package/dist/runtime/execution/serial-execution-queue.js +99 -26
  140. package/dist/runtime/execution/state-lane.d.ts +8 -1
  141. package/dist/runtime/execution/state-lane.js +118 -3
  142. package/dist/runtime/foundation/actor-join-recovery-codec.d.ts +3 -0
  143. package/dist/runtime/foundation/actor-join-recovery-codec.js +15 -11
  144. package/dist/runtime/foundation/event-loop-resources.d.ts +2 -24
  145. package/dist/runtime/foundation/event-loop-resources.js +6 -119
  146. package/dist/runtime/foundation/listener-records.d.ts +11 -0
  147. package/dist/runtime/foundation/listener-records.js +20 -0
  148. package/dist/runtime/foundation/operation-identity.d.ts +2 -0
  149. package/dist/runtime/foundation/operation-identity.js +9 -5
  150. package/dist/runtime/foundation/operation-registry.d.ts +5 -7
  151. package/dist/runtime/foundation/operation-registry.js +34 -44
  152. package/dist/runtime/foundation/raw-service-mesh-runtime.d.ts +18 -26
  153. package/dist/runtime/foundation/raw-service-mesh-runtime.js +122 -469
  154. package/dist/runtime/foundation/runtime-state-projections.d.ts +3 -1
  155. package/dist/runtime/foundation/runtime-state-projections.js +8 -0
  156. package/dist/runtime/foundation/service-authority-payload-codec.d.ts +1 -0
  157. package/dist/runtime/foundation/service-authority-payload-codec.js +30 -12
  158. package/dist/runtime/foundation/service-discovery-registry.d.ts +4 -0
  159. package/dist/runtime/foundation/service-discovery-registry.js +22 -3
  160. package/dist/runtime/foundation/service-instance-activation-recovery-codec.js +8 -4
  161. package/dist/runtime/foundation/service-liveness-registry.js +2 -1
  162. package/dist/runtime/foundation/service-maintenance-runtime.d.ts +0 -1
  163. package/dist/runtime/foundation/service-maintenance-runtime.js +23 -8
  164. package/dist/runtime/foundation/service-metadata-codec.js +3 -3
  165. package/dist/runtime/foundation/service-relocation-aggregate-committer.d.ts +2 -5
  166. package/dist/runtime/foundation/service-relocation-aggregate-committer.js +1 -48
  167. package/dist/runtime/foundation/service-relocation-coordinator.d.ts +9 -0
  168. package/dist/runtime/foundation/service-relocation-coordinator.js +14 -1
  169. package/dist/runtime/foundation/service-relocation-object-owner.d.ts +8 -0
  170. package/dist/runtime/foundation/service-relocation-object-owner.js +19 -6
  171. package/dist/runtime/foundation/service-relocation-runtime.js +43 -32
  172. package/dist/runtime/foundation/service-runtime-contracts.d.ts +40 -8
  173. package/dist/runtime/foundation/service-runtime-contracts.js +25 -1
  174. package/dist/runtime/foundation/service-session-binding-ingress-port.d.ts +0 -19
  175. package/dist/runtime/foundation/service-stateful-registry.d.ts +2 -0
  176. package/dist/runtime/foundation/service-stateful-registry.js +10 -2
  177. package/dist/runtime/foundation/service-stateful-runtime.d.ts +28 -24
  178. package/dist/runtime/foundation/service-stateful-runtime.js +297 -244
  179. package/dist/runtime/foundation/service-stateful-wire-codec.d.ts +12 -7
  180. package/dist/runtime/foundation/service-stateful-wire-codec.js +240 -143
  181. package/dist/runtime/foundation/service-topology-registry.d.ts +1 -3
  182. package/dist/runtime/foundation/service-topology-registry.js +22 -61
  183. package/dist/runtime/foundation/service-wire-binary-primitives.d.ts +5 -0
  184. package/dist/runtime/foundation/service-wire-binary-primitives.js +6 -0
  185. package/dist/runtime/foundation/service-wire-codec.js +10 -8
  186. package/dist/runtime/foundation/service-wire-constants.generated.d.ts +1 -0
  187. package/dist/runtime/foundation/service-wire-constants.generated.js +2 -1
  188. package/dist/runtime/foundation/service-wire-m6a-codec.d.ts +2 -0
  189. package/dist/runtime/foundation/service-wire-m6a-codec.js +23 -13
  190. package/dist/runtime/framework-errors-internal.d.ts +2 -1
  191. package/dist/runtime/framework-errors-internal.js +343 -122
  192. package/dist/runtime/handlers/handler-instance-scope.d.ts +3 -1
  193. package/dist/runtime/handlers/handler-instance-scope.js +61 -74
  194. package/dist/runtime/host/actor-packet-relay.d.ts +9 -6
  195. package/dist/runtime/host/actor-packet-relay.js +48 -91
  196. package/dist/runtime/host/actor-placement-coordinator.js +7 -5
  197. package/dist/runtime/host/actor-runtime-options-factory.d.ts +2 -0
  198. package/dist/runtime/host/actor-runtime-options-factory.js +17 -4
  199. package/dist/runtime/host/actor-transfer-runtime.d.ts +28 -28
  200. package/dist/runtime/host/actor-transfer-runtime.js +210 -256
  201. package/dist/runtime/host/application-job-queue.js +16 -33
  202. package/dist/runtime/host/bound-session-relay.js +1 -1
  203. package/dist/runtime/host/channel-runtime-options-factory.js +1 -1
  204. package/dist/runtime/host/index.d.ts +19 -14
  205. package/dist/runtime/host/index.js +234 -175
  206. package/dist/runtime/host/instance-activation-authority.d.ts +2 -3
  207. package/dist/runtime/host/instance-activation-authority.js +17 -45
  208. package/dist/runtime/host/location-runtime-owner.d.ts +1 -1
  209. package/dist/runtime/host/location-runtime-owner.js +2 -2
  210. package/dist/runtime/host/remote-actor-join-receiver.d.ts +2 -2
  211. package/dist/runtime/host/remote-actor-join-receiver.js +1 -14
  212. package/dist/runtime/host/remote-actor-packet-target-store.d.ts +3 -2
  213. package/dist/runtime/host/remote-actor-packet-target-store.js +8 -47
  214. package/dist/runtime/host/remote-bound-session-relay.d.ts +2 -3
  215. package/dist/runtime/host/remote-bound-session-relay.js +11 -23
  216. package/dist/runtime/host/route-mesh-runtime.d.ts +14 -10
  217. package/dist/runtime/host/route-mesh-runtime.js +178 -257
  218. package/dist/runtime/host/runtime-shutdown.d.ts +2 -0
  219. package/dist/runtime/host/runtime-shutdown.js +18 -21
  220. package/dist/runtime/host/service-relocation-control.js +6 -1
  221. package/dist/runtime/host/service-relocation-host-runtime.d.ts +71 -38
  222. package/dist/runtime/host/service-relocation-host-runtime.js +816 -651
  223. package/dist/runtime/host/spot-address-transport.d.ts +2 -3
  224. package/dist/runtime/host/spot-address-transport.js +34 -136
  225. package/dist/runtime/host/spot-node-runtime-options-factory.d.ts +1 -1
  226. package/dist/runtime/host/spot-node-runtime-options-factory.js +3 -2
  227. package/dist/runtime/host/spot-runtime-options-factory.d.ts +4 -7
  228. package/dist/runtime/host/spot-runtime-options-factory.js +53 -21
  229. package/dist/runtime/host/stateful-authority-route-runtime.js +6 -2
  230. package/dist/runtime/host/user-spot-creation-coordinator.d.ts +14 -6
  231. package/dist/runtime/host/user-spot-creation-coordinator.js +96 -95
  232. package/dist/runtime/locations/aggregate-inventory-store.js +13 -10
  233. package/dist/runtime/locations/authority-key-codec.js +4 -3
  234. package/dist/runtime/locations/auto-connect-reconciler.d.ts +4 -0
  235. package/dist/runtime/locations/auto-connect-reconciler.js +37 -25
  236. package/dist/runtime/locations/creation-operation-id.js +6 -4
  237. package/dist/runtime/locations/domain-store-contract.d.ts +3 -3
  238. package/dist/runtime/locations/in-memory-authority-store.js +31 -15
  239. package/dist/runtime/locations/in-memory-location-store.d.ts +2 -2
  240. package/dist/runtime/locations/in-memory-location-store.js +17 -14
  241. package/dist/runtime/locations/in-memory-provider-location-store.d.ts +1 -0
  242. package/dist/runtime/locations/in-memory-provider-location-store.js +79 -27
  243. package/dist/runtime/locations/key-codec.js +3 -2
  244. package/dist/runtime/locations/lease-tracker.d.ts +3 -5
  245. package/dist/runtime/locations/lease-tracker.js +7 -11
  246. package/dist/runtime/locations/lifecycle.d.ts +5 -10
  247. package/dist/runtime/locations/lifecycle.js +4 -33
  248. package/dist/runtime/locations/location-store-failure.d.ts +2 -0
  249. package/dist/runtime/locations/location-store-failure.js +7 -0
  250. package/dist/runtime/locations/location-store-pages.d.ts +3 -0
  251. package/dist/runtime/locations/location-store-pages.js +13 -0
  252. package/dist/runtime/locations/location-store-repository.d.ts +5 -7
  253. package/dist/runtime/locations/location-store-repository.js +303 -332
  254. package/dist/runtime/locations/relocation-blob.js +18 -5
  255. package/dist/runtime/locations/resolvers.d.ts +5 -5
  256. package/dist/runtime/locations/resolvers.js +44 -30
  257. package/dist/runtime/locations/runtime.d.ts +5 -4
  258. package/dist/runtime/locations/runtime.js +123 -92
  259. package/dist/runtime/locations/spot-location-claims.d.ts +8 -2
  260. package/dist/runtime/locations/spot-location-claims.js +40 -23
  261. package/dist/runtime/messaging/payload-codec.js +26 -20
  262. package/dist/runtime/messaging/submission-result.d.ts +3 -0
  263. package/dist/runtime/messaging/submission-result.js +48 -0
  264. package/dist/runtime/protocol/service_wire_codec.generated.d.ts +2 -0
  265. package/dist/runtime/protocol/service_wire_codec.generated.js +17 -8
  266. package/dist/runtime/protocol/service_wire_pilot_codec.generated.d.ts +1 -0
  267. package/dist/runtime/protocol/service_wire_pilot_codec.generated.js +3 -2
  268. package/dist/runtime/spots/formal-remote-actor-admission-registry.d.ts +3 -3
  269. package/dist/runtime/spots/formal-remote-actor-admission-registry.js +4 -4
  270. package/dist/runtime/spots/formal-remote-actor-transfer-registry.d.ts +6 -3
  271. package/dist/runtime/spots/index.d.ts +29 -29
  272. package/dist/runtime/spots/index.js +441 -313
  273. package/dist/runtime/spots/spot-activation-registry.d.ts +4 -4
  274. package/dist/runtime/spots/spot-activation-registry.js +27 -60
  275. package/dist/runtime/spots/spot-activation-state.d.ts +2 -11
  276. package/dist/runtime/spots/spot-activation-state.js +4 -17
  277. package/dist/runtime/spots/spot-activation.d.ts +10 -9
  278. package/dist/runtime/spots/spot-activation.js +103 -81
  279. package/dist/runtime/spots/spot-actor-admission-coordinator.d.ts +1 -2
  280. package/dist/runtime/spots/spot-actor-admission-coordinator.js +3 -40
  281. package/dist/runtime/spots/spot-actor-join-dispatch.d.ts +10 -18
  282. package/dist/runtime/spots/spot-actor-join-dispatch.js +5 -55
  283. package/dist/runtime/spots/spot-actor-lifecycle-drain.js +2 -2
  284. package/dist/runtime/spots/spot-actor-membership.d.ts +7 -5
  285. package/dist/runtime/spots/spot-actor-membership.js +44 -53
  286. package/dist/runtime/spots/spot-actor-packet-dispatch.d.ts +0 -1
  287. package/dist/runtime/spots/spot-actor-packet-dispatch.js +0 -9
  288. package/dist/runtime/spots/spot-actor-packet-relay-dispatch.d.ts +2 -2
  289. package/dist/runtime/spots/spot-actor-packet-relay-dispatch.js +1 -7
  290. package/dist/runtime/spots/spot-context.d.ts +2 -2
  291. package/dist/runtime/spots/spot-entry-activation.d.ts +3 -4
  292. package/dist/runtime/spots/spot-entry-activation.js +9 -21
  293. package/dist/runtime/spots/spot-lifecycle-metrics.js +3 -2
  294. package/dist/runtime/spots/spot-manager-public.d.ts +5 -6
  295. package/dist/runtime/spots/spot-manager-public.js +6 -5
  296. package/dist/runtime/spots/spot-node-autoconnect.js +22 -31
  297. package/dist/runtime/spots/spot-node-runtime-manager.d.ts +22 -21
  298. package/dist/runtime/spots/spot-node-runtime-manager.js +73 -82
  299. package/dist/runtime/spots/spot-outbound.d.ts +4 -3
  300. package/dist/runtime/spots/spot-outbound.js +10 -37
  301. package/dist/runtime/spots/spot-remote-codec.js +5 -3
  302. package/dist/runtime/spots/spot-route-packet-dispatch.d.ts +2 -2
  303. package/dist/runtime/spots/spot-route-packet-dispatch.js +8 -8
  304. package/dist/runtime/spots/spot-route-replies.d.ts +2 -2
  305. package/dist/runtime/spots/spot-route-replies.js +3 -1
  306. package/dist/runtime/spots/spot-routed-actor-admission.d.ts +3 -2
  307. package/dist/runtime/spots/spot-routed-actor-admission.js +3 -2
  308. package/dist/runtime/spots/spot-routed-frame-dispatch.d.ts +2 -7
  309. package/dist/runtime/spots/spot-routed-frame-dispatch.js +1 -70
  310. package/dist/runtime/spots/spot-routed-spot-packet-dispatch.d.ts +4 -0
  311. package/dist/runtime/spots/spot-routed-spot-packet-dispatch.js +65 -15
  312. package/dist/runtime/spots/spot-runtime-ports.d.ts +4 -20
  313. package/dist/runtime/spots/spot-serial-executor.d.ts +5 -0
  314. package/dist/runtime/spots/spot-serial-executor.js +9 -2
  315. package/dist/runtime/spots/spot-serial-turn-executor.d.ts +29 -6
  316. package/dist/runtime/spots/spot-serial-turn-executor.js +89 -13
  317. package/dist/runtime/spots/spot-timer.d.ts +3 -2
  318. package/dist/runtime/streams/actor-session-binding-registry.d.ts +17 -32
  319. package/dist/runtime/streams/actor-session-binding-registry.js +145 -367
  320. package/dist/runtime/streams/actor-session-binding-runtime-owner.d.ts +2 -6
  321. package/dist/runtime/streams/bound-actor-relay-sender.d.ts +6 -2
  322. package/dist/runtime/streams/bound-actor-relay-sender.js +57 -33
  323. package/dist/runtime/streams/bound-session-service.d.ts +7 -0
  324. package/dist/runtime/streams/bound-session-service.js +12 -19
  325. package/dist/runtime/streams/index.d.ts +15 -14
  326. package/dist/runtime/streams/index.js +38 -39
  327. package/dist/runtime/streams/managed-stream.d.ts +3 -0
  328. package/dist/runtime/streams/managed-stream.js +17 -8
  329. package/dist/runtime/streams/native-fallback-bound-session.js +1 -3
  330. package/dist/runtime/streams/protocol.d.ts +6 -33
  331. package/dist/runtime/streams/protocol.js +38 -110
  332. package/dist/runtime/streams/session-actor-coordinator.d.ts +2 -3
  333. package/dist/runtime/streams/session-actor-coordinator.js +12 -4
  334. package/dist/runtime/streams/session-calls.d.ts +1 -1
  335. package/dist/runtime/streams/session-calls.js +5 -4
  336. package/dist/runtime/streams/session-context.d.ts +6 -6
  337. package/dist/runtime/streams/session-context.js +22 -4
  338. package/dist/runtime/streams/session-requests.js +2 -1
  339. package/dist/runtime/streams/session-serial-executor.js +2 -2
  340. package/dist/runtime/streams/stream-binding-runtime-ports.d.ts +16 -1
  341. package/dist/runtime/streams/stream-frame-factory.js +2 -2
  342. package/dist/runtime/streams/stream-session-runtime.d.ts +10 -11
  343. package/dist/runtime/streams/stream-session-runtime.js +25 -33
  344. package/dist/runtime/workers/index.d.ts +2 -2
  345. package/dist/runtime/workers/index.js +5 -4
  346. package/package.json +3 -3
  347. package/src/contracts/Channels/IZLinkFanoutClient.ts +0 -7
  348. package/src/contracts/Common/CoreTypes.ts +7 -0
  349. package/src/contracts/Common/index.ts +1 -1
  350. package/src/contracts/Configuration/InternalDefaults.ts +12 -0
  351. package/src/contracts/Configuration/Registration.ts +92 -48
  352. package/src/contracts/Configuration/RegistrationBuilderPolicy.ts +44 -2
  353. package/src/contracts/Configuration/RegistrationBuilders.ts +77 -68
  354. package/src/contracts/Configuration/RegistrationTypes.ts +1 -0
  355. package/src/contracts/Configuration/RegistrationValidators.ts +19 -13
  356. package/src/contracts/Configuration/TimerRegistrationValidator.ts +4 -2
  357. package/src/contracts/Dispatch/ZLinkDispatchOptions.ts +1 -0
  358. package/src/contracts/Handlers/JsonContract.ts +14 -4
  359. package/src/contracts/Locations/Authority.ts +7 -3
  360. package/src/contracts/Locations/Options.ts +1 -1
  361. package/src/contracts/Locations/Stores.ts +14 -0
  362. package/src/contracts/RouteMesh/RuntimeTopology.ts +10 -0
  363. package/src/contracts/Spots/Contracts.ts +1 -1
  364. package/src/internal.ts +15 -0
  365. package/src/nest-integration.ts +28 -10
  366. package/src/runtime/abort.ts +6 -5
  367. package/src/runtime/activation-admission.ts +72 -0
  368. package/src/runtime/actors/actor-authority-payload-codec.ts +58 -20
  369. package/src/runtime/actors/actor-client.ts +77 -204
  370. package/src/runtime/actors/actor-context.ts +45 -39
  371. package/src/runtime/actors/actor-handoff.ts +55 -45
  372. package/src/runtime/actors/actor-lifecycle-snapshot.ts +2 -1
  373. package/src/runtime/actors/actor-local-native-join.ts +174 -215
  374. package/src/runtime/actors/actor-native-lookup.ts +2 -9
  375. package/src/runtime/actors/actor-packet-relay-wire.ts +18 -12
  376. package/src/runtime/actors/actor-remote-joiner.ts +15 -36
  377. package/src/runtime/actors/actor-remote-wire.ts +5 -3
  378. package/src/runtime/actors/actor-request-deadline.ts +49 -0
  379. package/src/runtime/actors/actor-retry-delay.ts +2 -1
  380. package/src/runtime/actors/actor-runtime-contracts.ts +4 -10
  381. package/src/runtime/actors/actor-runtime-state.ts +85 -247
  382. package/src/runtime/actors/actor-source-transfer.ts +5 -18
  383. package/src/runtime/actors/bound-session-wire.ts +2 -8
  384. package/src/runtime/actors/deferred-join-completion.ts +44 -0
  385. package/src/runtime/actors/index.ts +122 -88
  386. package/src/runtime/actors/spot-actor-dispatch.ts +60 -29
  387. package/src/runtime/actors/transferred-actor-rollback.ts +11 -62
  388. package/src/runtime/admission.ts +13 -2
  389. package/src/runtime/application-jobs/application-job-queue-scope.ts +4 -4
  390. package/src/runtime/backend/contracts/index.ts +15 -42
  391. package/src/runtime/backend/mesh-actor-session-node-adapter.ts +4 -28
  392. package/src/runtime/backend/mesh-dispatch-pump.ts +111 -117
  393. package/src/runtime/backend/node/node-backend-adapter-factory.ts +5 -25
  394. package/src/runtime/backend/node/node-backend-adapter-support.ts +32 -35
  395. package/src/runtime/backend/node/node-event-loop-poller.ts +16 -8
  396. package/src/runtime/backend/node/node-monitor-backend-adapter.ts +1 -0
  397. package/src/runtime/backend/node/node-raw-binding-port.ts +58 -23
  398. package/src/runtime/backend/node/node-raw-mesh-backend.ts +252 -162
  399. package/src/runtime/backend/node/node-socket-backend-adapter.ts +5 -4
  400. package/src/runtime/backend/raw-binding-port.ts +14 -1
  401. package/src/runtime/backend/runtime-values.ts +4 -1
  402. package/src/runtime/channels/channel-clients.ts +132 -96
  403. package/src/runtime/channels/channel-envelope-inspection.ts +2 -1
  404. package/src/runtime/channels/channel-envelope.ts +58 -29
  405. package/src/runtime/channels/channel-outbound-operations.ts +10 -31
  406. package/src/runtime/channels/channel-receive-loops.ts +39 -7
  407. package/src/runtime/channels/channel-runtime-lifecycle.ts +60 -27
  408. package/src/runtime/channels/channel-runtime-manager.ts +8 -15
  409. package/src/runtime/channels/channel-socket-options.ts +8 -2
  410. package/src/runtime/channels/channel-socket-registry.ts +369 -262
  411. package/src/runtime/channels/channel-transports.ts +161 -115
  412. package/src/runtime/channels/client-server-location-runtime.ts +17 -17
  413. package/src/runtime/channels/client-server-service-wire.ts +40 -12
  414. package/src/runtime/channels/dispatch-error-reporter.ts +7 -5
  415. package/src/runtime/channels/fanout-location-runtime.ts +175 -106
  416. package/src/runtime/channels/spot-direct-envelope.ts +1 -1
  417. package/src/runtime/channels/spot-node-route-transport.ts +5 -2
  418. package/src/runtime/diagnostics/diagnostic-text.ts +4 -0
  419. package/src/runtime/diagnostics/dispatch-error-details.ts +36 -1
  420. package/src/runtime/diagnostics/flow-context.ts +16 -2
  421. package/src/runtime/diagnostics/index.ts +27 -17
  422. package/src/runtime/diagnostics/message-flow.ts +15 -25
  423. package/src/runtime/diagnostics/runtime-metrics.ts +181 -113
  424. package/src/runtime/diagnostics/runtime-observation-queue.ts +3 -2
  425. package/src/runtime/diagnostics/topology-runtime-projections.ts +194 -162
  426. package/src/runtime/disposal.ts +19 -0
  427. package/src/runtime/execution/index.ts +116 -38
  428. package/src/runtime/execution/serial-execution-queue.ts +179 -34
  429. package/src/runtime/execution/state-lane.ts +142 -4
  430. package/src/runtime/foundation/actor-join-recovery-codec.ts +13 -8
  431. package/src/runtime/foundation/event-loop-resources.ts +5 -122
  432. package/src/runtime/foundation/listener-records.ts +21 -0
  433. package/src/runtime/foundation/operation-identity.ts +11 -5
  434. package/src/runtime/foundation/operation-registry.ts +33 -50
  435. package/src/runtime/foundation/raw-service-mesh-runtime.ts +170 -571
  436. package/src/runtime/foundation/runtime-state-projections.ts +9 -1
  437. package/src/runtime/foundation/service-authority-payload-codec.ts +41 -13
  438. package/src/runtime/foundation/service-discovery-registry.ts +32 -3
  439. package/src/runtime/foundation/service-instance-activation-recovery-codec.ts +12 -4
  440. package/src/runtime/foundation/service-liveness-registry.ts +2 -1
  441. package/src/runtime/foundation/service-maintenance-runtime.ts +30 -19
  442. package/src/runtime/foundation/service-metadata-codec.ts +2 -2
  443. package/src/runtime/foundation/service-relocation-aggregate-committer.ts +3 -66
  444. package/src/runtime/foundation/service-relocation-coordinator.ts +13 -0
  445. package/src/runtime/foundation/service-relocation-object-owner.ts +23 -7
  446. package/src/runtime/foundation/service-relocation-runtime.ts +57 -35
  447. package/src/runtime/foundation/service-runtime-contracts.ts +46 -10
  448. package/src/runtime/foundation/service-session-binding-ingress-port.ts +0 -25
  449. package/src/runtime/foundation/service-stateful-registry.ts +14 -2
  450. package/src/runtime/foundation/service-stateful-runtime.ts +435 -327
  451. package/src/runtime/foundation/service-stateful-wire-codec.ts +329 -199
  452. package/src/runtime/foundation/service-topology-registry.ts +30 -79
  453. package/src/runtime/foundation/service-wire-binary-primitives.ts +6 -0
  454. package/src/runtime/foundation/service-wire-codec.ts +15 -8
  455. package/src/runtime/foundation/service-wire-constants.generated.ts +1 -0
  456. package/src/runtime/foundation/service-wire-m6a-codec.ts +29 -15
  457. package/src/runtime/framework-errors-internal.ts +380 -134
  458. package/src/runtime/handlers/handler-instance-scope.ts +68 -95
  459. package/src/runtime/host/actor-packet-relay.ts +57 -147
  460. package/src/runtime/host/actor-placement-coordinator.ts +8 -5
  461. package/src/runtime/host/actor-runtime-options-factory.ts +27 -8
  462. package/src/runtime/host/actor-transfer-runtime.ts +266 -418
  463. package/src/runtime/host/application-job-queue.ts +28 -34
  464. package/src/runtime/host/bound-session-relay.ts +1 -2
  465. package/src/runtime/host/channel-runtime-options-factory.ts +1 -2
  466. package/src/runtime/host/index.ts +408 -312
  467. package/src/runtime/host/instance-activation-authority.ts +89 -109
  468. package/src/runtime/host/location-runtime-owner.ts +4 -2
  469. package/src/runtime/host/remote-actor-join-receiver.ts +3 -31
  470. package/src/runtime/host/remote-actor-packet-target-store.ts +17 -58
  471. package/src/runtime/host/remote-bound-session-relay.ts +12 -44
  472. package/src/runtime/host/route-mesh-runtime.ts +236 -275
  473. package/src/runtime/host/runtime-shutdown.ts +17 -21
  474. package/src/runtime/host/service-relocation-control.ts +14 -1
  475. package/src/runtime/host/service-relocation-host-runtime.ts +1161 -904
  476. package/src/runtime/host/spot-address-transport.ts +73 -195
  477. package/src/runtime/host/spot-node-runtime-options-factory.ts +6 -3
  478. package/src/runtime/host/spot-runtime-options-factory.ts +92 -30
  479. package/src/runtime/host/stateful-authority-route-runtime.ts +8 -4
  480. package/src/runtime/host/user-spot-creation-coordinator.ts +182 -163
  481. package/src/runtime/locations/aggregate-inventory-store.ts +16 -13
  482. package/src/runtime/locations/authority-key-codec.ts +7 -3
  483. package/src/runtime/locations/auto-connect-reconciler.ts +39 -26
  484. package/src/runtime/locations/creation-operation-id.ts +6 -3
  485. package/src/runtime/locations/domain-store-contract.ts +12 -3
  486. package/src/runtime/locations/in-memory-authority-store.ts +44 -15
  487. package/src/runtime/locations/in-memory-location-store.ts +50 -39
  488. package/src/runtime/locations/in-memory-provider-location-store.ts +110 -31
  489. package/src/runtime/locations/key-codec.ts +3 -2
  490. package/src/runtime/locations/lease-tracker.ts +8 -14
  491. package/src/runtime/locations/lifecycle.ts +16 -45
  492. package/src/runtime/locations/location-store-failure.ts +4 -0
  493. package/src/runtime/locations/location-store-pages.ts +18 -0
  494. package/src/runtime/locations/location-store-repository.ts +450 -478
  495. package/src/runtime/locations/relocation-blob.ts +17 -6
  496. package/src/runtime/locations/resolvers.ts +90 -58
  497. package/src/runtime/locations/runtime.ts +220 -110
  498. package/src/runtime/locations/spot-location-claims.ts +54 -26
  499. package/src/runtime/messaging/payload-codec.ts +35 -24
  500. package/src/runtime/messaging/submission-result.ts +57 -1
  501. package/src/runtime/protocol/service_wire_codec.generated.ts +27 -10
  502. package/src/runtime/protocol/service_wire_pilot_codec.generated.ts +4 -4
  503. package/src/runtime/spots/formal-remote-actor-admission-registry.ts +6 -6
  504. package/src/runtime/spots/formal-remote-actor-transfer-registry.ts +6 -3
  505. package/src/runtime/spots/index.ts +687 -437
  506. package/src/runtime/spots/spot-activation-registry.ts +42 -71
  507. package/src/runtime/spots/spot-activation-state.ts +4 -16
  508. package/src/runtime/spots/spot-activation.ts +167 -115
  509. package/src/runtime/spots/spot-actor-admission-coordinator.ts +5 -57
  510. package/src/runtime/spots/spot-actor-join-dispatch.ts +25 -79
  511. package/src/runtime/spots/spot-actor-lifecycle-drain.ts +20 -18
  512. package/src/runtime/spots/spot-actor-membership.ts +107 -75
  513. package/src/runtime/spots/spot-actor-packet-dispatch.ts +0 -16
  514. package/src/runtime/spots/spot-actor-packet-relay-dispatch.ts +3 -15
  515. package/src/runtime/spots/spot-context.ts +3 -3
  516. package/src/runtime/spots/spot-entry-activation.ts +13 -33
  517. package/src/runtime/spots/spot-lifecycle-metrics.ts +3 -2
  518. package/src/runtime/spots/spot-manager-public.ts +29 -21
  519. package/src/runtime/spots/spot-node-autoconnect.ts +20 -26
  520. package/src/runtime/spots/spot-node-runtime-manager.ts +145 -140
  521. package/src/runtime/spots/spot-outbound.ts +47 -68
  522. package/src/runtime/spots/spot-remote-codec.ts +7 -3
  523. package/src/runtime/spots/spot-route-packet-dispatch.ts +25 -24
  524. package/src/runtime/spots/spot-route-replies.ts +6 -4
  525. package/src/runtime/spots/spot-routed-actor-admission.ts +13 -6
  526. package/src/runtime/spots/spot-routed-frame-dispatch.ts +6 -77
  527. package/src/runtime/spots/spot-routed-spot-packet-dispatch.ts +95 -22
  528. package/src/runtime/spots/spot-runtime-ports.ts +10 -43
  529. package/src/runtime/spots/spot-serial-executor.ts +10 -2
  530. package/src/runtime/spots/spot-serial-turn-executor.ts +120 -13
  531. package/src/runtime/spots/spot-timer.ts +3 -2
  532. package/src/runtime/streams/actor-session-binding-registry.ts +182 -560
  533. package/src/runtime/streams/actor-session-binding-runtime-owner.ts +1 -19
  534. package/src/runtime/streams/bound-actor-relay-sender.ts +89 -43
  535. package/src/runtime/streams/bound-session-service.ts +23 -37
  536. package/src/runtime/streams/index.ts +102 -88
  537. package/src/runtime/streams/managed-stream.ts +29 -10
  538. package/src/runtime/streams/native-fallback-bound-session.ts +1 -3
  539. package/src/runtime/streams/protocol.ts +34 -88
  540. package/src/runtime/streams/session-actor-coordinator.ts +17 -5
  541. package/src/runtime/streams/session-calls.ts +6 -5
  542. package/src/runtime/streams/session-context.ts +54 -10
  543. package/src/runtime/streams/session-requests.ts +2 -1
  544. package/src/runtime/streams/session-serial-executor.ts +2 -2
  545. package/src/runtime/streams/stream-binding-runtime-ports.ts +22 -1
  546. package/src/runtime/streams/stream-frame-factory.ts +2 -3
  547. package/src/runtime/streams/stream-session-runtime.ts +57 -59
  548. package/src/runtime/workers/index.ts +13 -12
  549. package/dist/runtime/actors/deferred-join-accepted-journal.d.ts +0 -47
  550. package/dist/runtime/actors/deferred-join-accepted-journal.js +0 -992
  551. package/dist/runtime/actors/post-commit-actor-location.d.ts +0 -19
  552. package/dist/runtime/actors/post-commit-actor-location.js +0 -72
  553. package/dist/runtime/spots/spot-native-actor-join-admission.d.ts +0 -26
  554. package/dist/runtime/spots/spot-native-actor-join-admission.js +0 -106
  555. package/src/runtime/actors/deferred-join-accepted-journal.ts +0 -1346
  556. package/src/runtime/actors/post-commit-actor-location.ts +0 -121
  557. package/src/runtime/spots/spot-native-actor-join-admission.ts +0 -155
@@ -1,30 +1,36 @@
1
- import { randomUUID } from 'node:crypto';
1
+ import { constants as osConstants } from 'node:os';
2
+ import { ApplicationIngressRecordOwner } from '../application-jobs/application-ingress-record-owner';
3
+ import type {
4
+ ApplicationJobPermitPort,
5
+ ApplicationJobQueuePort
6
+ } from '../application-jobs/contracts';
2
7
  import type {
3
8
  ZLinkRawBindingPort,
4
9
  ZLinkRawHostPort,
5
- ZLinkRawMonitorRecord,
6
- ZLinkRawMonitorPort,
7
10
  ZLinkRawReceivedRecord,
8
11
  ZLinkRawRouterPort
9
12
  } from '../backend/raw-binding-port';
10
13
  import { RequestResult, SubmitResult } from '../backend/runtime-values';
11
- import type {
12
- ApplicationJobPermitPort,
13
- ApplicationJobQueuePort
14
- } from '../application-jobs/contracts';
15
- import { ApplicationIngressRecordOwner } from '../application-jobs/application-ingress-record-owner';
14
+ import { enumWireRejectReason } from '../protocol/service_wire_codec.generated';
16
15
  import { OperationRegistry, type PendingOperation } from './operation-registry';
17
16
  import { ServiceLivenessRegistry, type ServiceLivenessTick } from './service-liveness-registry';
18
17
  import { ServiceMailbox, type ServiceMailboxRecord } from './service-mailbox';
19
18
  import {
20
- ServiceTopologyRegistry,
21
19
  sameServiceNodeDescriptor,
20
+ ServiceTopologyRegistry,
22
21
  validateDescriptor,
23
22
  type AdmittedServicePeer,
24
23
  type PeerAdmissionResult,
25
- type ServicePeerAdmissionExpectation,
26
- type ServiceNodeDescriptor
24
+ type ServiceNodeDescriptor,
25
+ type ServicePeerAdmissionExpectation
27
26
  } from './service-topology-registry';
27
+ import { createServiceWireCodec } from './service-wire-codec';
28
+ import {
29
+ SERVICE_WIRE_MAGIC,
30
+ SERVICE_WIRE_MAJOR,
31
+ ServiceWireCommand,
32
+ ServiceWireFrameworkErrorCode
33
+ } from './service-wire-constants.generated';
28
34
  import {
29
35
  decodeApplicationPayloadView,
30
36
  decodeChannelRequestHeader,
@@ -43,14 +49,11 @@ import {
43
49
  encodeReplyHeader,
44
50
  encodeRouteMeshAdmission,
45
51
  M6aServiceWireCommand,
46
- type ServiceApplicationPayload,
47
- ServiceWireProtocolError
52
+ ServiceWireProtocolError,
53
+ type ServiceApplicationPayload
48
54
  } from './service-wire-m6a-codec';
49
- import { createServiceWireCodec } from './service-wire-codec';
50
- import {
51
- ServiceWireCommand,
52
- ServiceWireFrameworkErrorCode
53
- } from './service-wire-constants.generated';
55
+
56
+ const nativeErrnoValues = osConstants.errno;
54
57
 
55
58
  export type RawServicePumpResult =
56
59
  'noData' | 'infrastructure' | 'application' | 'dropped' | 'protocolError';
@@ -96,6 +99,7 @@ export type RawServiceIngressHandler = (
96
99
  ) => RawServicePumpResult | undefined | Promise<RawServicePumpResult | undefined>;
97
100
 
98
101
  export interface RawServiceMeshRuntimeOptions {
102
+ readonly onPendingOperationsChanged?: () => void;
99
103
  readonly descriptor: ServiceNodeDescriptor;
100
104
  readonly resolveAdvertisedEndpoint?: (boundEndpoint: string) => string;
101
105
  readonly probeIntervalMs?: number;
@@ -119,31 +123,20 @@ export interface RawServiceMeshRuntimeOptions {
119
123
  }) => void;
120
124
  }
121
125
 
122
- const MONITOR_DISCONNECTED = 0x0200;
123
- const MONITOR_CONNECTION_READY = 0x1000;
124
- const MONITOR_CONNECTION_READY_EDGE = 1;
125
126
  // Framework error code 13 (RequestTargetNotFound) is encoded as 14 on a
126
127
  // RequestResult.NotFound reply. Boundary transport results keep failureCode 0.
127
- const REQUEST_TARGET_NOT_FOUND_FAILURE_CODE = 14;
128
- type PhysicalConnectionDirection = 'inbound' | 'outbound' | 'unknown';
129
-
130
- interface PhysicalConnectionCandidate {
131
- readonly connectionId: string;
132
- readonly direction: PhysicalConnectionDirection;
133
- readonly discriminator: string;
134
- readonly localAddress: string;
135
- readonly remoteAddress: string;
136
- }
128
+ const RAW_MESH_RECEIVE_RECORD_BUDGET = 64;
129
+ const RAW_MESH_RECEIVE_BYTE_BUDGET = 4 * 1024 * 1024;
130
+ export const RAW_MESH_RECEIVE_TIME_BUDGET_MS = 2;
131
+
132
+ const REQUEST_TARGET_NOT_FOUND_FAILURE_CODE = ServiceWireFrameworkErrorCode.requestTargetNotFound;
137
133
 
138
134
  const livenessCodec = createServiceWireCodec({
139
- magic: [0x5a, 0x4d],
140
- major: 1,
135
+ magic: SERVICE_WIRE_MAGIC,
136
+ major: SERVICE_WIRE_MAJOR,
141
137
  commands: M6aServiceWireCommand
142
138
  });
143
139
 
144
- const MAX_PENDING_MONITOR_EVENTS = 8192;
145
- const MAX_UNRESOLVED_CONNECTION_CANDIDATES = 4096;
146
-
147
140
  /**
148
141
  * RouteMesh M6A runtime built only on the public raw binding package.
149
142
  * It owns protocol, admission, mailbox, request and liveness state.
@@ -153,7 +146,7 @@ export class RawServiceMeshRuntime {
153
146
  readonly mailbox: ServiceMailbox;
154
147
  readonly liveness: ServiceLivenessRegistry;
155
148
 
156
- private readonly operations = new OperationRegistry<RawServiceRequestResult>();
149
+ private readonly operations: OperationRegistry<RawServiceRequestResult>;
157
150
  private readonly expectedPeers = new Map<
158
151
  string,
159
152
  {
@@ -162,24 +155,16 @@ export class RawServiceMeshRuntime {
162
155
  readonly endpoint?: string;
163
156
  readonly securityIdentity?: string;
164
157
  readonly lifecycleGeneration?: bigint;
158
+ helloSubmittedGeneration?: bigint;
165
159
  }
166
160
  >();
167
161
  private readonly endpointOnlyPeers = new Set<string>();
168
162
  private readonly peerConnectionIntentRemoved = new Set<(nodeRoutingId: string) => void>();
169
- private readonly connectionCandidates = new Map<
170
- string,
171
- Map<string, PhysicalConnectionCandidate>
172
- >();
173
- private readonly unresolvedConnectionCandidates: PhysicalConnectionCandidate[] = [];
174
- private readonly connectionIds = new Map<string, string>();
175
163
  /**
176
- * The monitor drain updates this fence before the event reaches the
177
- * normal runtime handler. `null` means that the last observed pair is no
178
- * longer usable by the application route.
164
+ * The last observed Core selected route of each RID (Core ROUTER §10.1):
165
+ * RID -> route generation. Only `observeSelectedRoutes` replaces it.
179
166
  */
180
- private readonly monitorConnectionStates = new Map<string, string | null>();
181
- private monitorEvents: ZLinkRawMonitorRecord[] = [];
182
- private monitorDrainBuffer: ZLinkRawMonitorRecord[] = [];
167
+ private selectedRoutes = new Map<string, bigint>();
183
168
  private readonly bindingPort: ZLinkRawBindingPort;
184
169
  private readonly applicationJobQueue: ApplicationJobQueuePort;
185
170
  private readonly peerAdmissionSealed?: () => boolean;
@@ -192,12 +177,12 @@ export class RawServiceMeshRuntime {
192
177
  private descriptor: ServiceNodeDescriptor;
193
178
  private host?: ZLinkRawHostPort;
194
179
  private router?: ZLinkRawRouterPort;
195
- private monitor?: ZLinkRawMonitorPort;
196
180
  private nextCorrelation = 1n;
197
181
  private serviceIngress?: RawServiceIngressHandler;
198
182
  private closed = false;
199
183
 
200
184
  constructor(options: RawServiceMeshRuntimeOptions) {
185
+ this.operations = new OperationRegistry(undefined, options.onPendingOperationsChanged);
201
186
  this.descriptor = options.descriptor;
202
187
  this.topology = new ServiceTopologyRegistry(options.descriptor);
203
188
  this.mailbox = new ServiceMailbox(options.onMailboxReady);
@@ -239,8 +224,6 @@ export class RawServiceMeshRuntime {
239
224
  };
240
225
  this.topology.publishLocal(next);
241
226
  this.descriptor = next;
242
- this.monitor = router.monitor();
243
- this.pullMonitorEvents();
244
227
  this.host = host;
245
228
  this.router = router;
246
229
  } catch (error) {
@@ -254,13 +237,16 @@ export class RawServiceMeshRuntime {
254
237
 
255
238
  connectPeer(endpoint: string, expected: ServiceNodeDescriptor): void {
256
239
  this.requireStarted().connectToRoutingId(expected.nodeRoutingId, endpoint);
257
- this.expectedPeers.set(expected.nodeRoutingId, {
258
- meshName: expected.meshName,
259
- nodeRoutingId: expected.nodeRoutingId,
260
- endpoint,
261
- securityIdentity: expected.securityIdentity,
262
- lifecycleGeneration: expected.lifecycleGeneration
263
- });
240
+ this.expectedPeers.set(
241
+ expected.nodeRoutingId,
242
+ Object.assign(this.expectedPeers.get(expected.nodeRoutingId) ?? {}, {
243
+ meshName: expected.meshName,
244
+ nodeRoutingId: expected.nodeRoutingId,
245
+ endpoint,
246
+ securityIdentity: expected.securityIdentity,
247
+ lifecycleGeneration: expected.lifecycleGeneration
248
+ })
249
+ );
264
250
  }
265
251
 
266
252
  connectPeerByRoutingId(
@@ -270,13 +256,16 @@ export class RawServiceMeshRuntime {
270
256
  lifecycleGeneration?: bigint
271
257
  ): void {
272
258
  this.requireStarted().connectToRoutingId(nodeRoutingId, endpoint);
273
- this.expectedPeers.set(nodeRoutingId, {
274
- meshName: this.topology.localDescriptor().meshName,
259
+ this.expectedPeers.set(
275
260
  nodeRoutingId,
276
- endpoint,
277
- securityIdentity,
278
- lifecycleGeneration
279
- });
261
+ Object.assign(this.expectedPeers.get(nodeRoutingId) ?? {}, {
262
+ meshName: this.topology.localDescriptor().meshName,
263
+ nodeRoutingId,
264
+ endpoint,
265
+ securityIdentity,
266
+ lifecycleGeneration
267
+ })
268
+ );
280
269
  }
281
270
 
282
271
  expectPeerByRoutingId(
@@ -285,13 +274,16 @@ export class RawServiceMeshRuntime {
285
274
  securityIdentity?: string,
286
275
  lifecycleGeneration?: bigint
287
276
  ): void {
288
- this.expectedPeers.set(nodeRoutingId, {
289
- meshName: this.topology.localDescriptor().meshName,
277
+ this.expectedPeers.set(
290
278
  nodeRoutingId,
291
- endpoint,
292
- securityIdentity,
293
- lifecycleGeneration
294
- });
279
+ Object.assign(this.expectedPeers.get(nodeRoutingId) ?? {}, {
280
+ meshName: this.topology.localDescriptor().meshName,
281
+ nodeRoutingId,
282
+ endpoint,
283
+ securityIdentity,
284
+ lifecycleGeneration
285
+ })
286
+ );
295
287
  }
296
288
 
297
289
  connectPeerEndpoint(endpoint: string): void {
@@ -379,35 +371,42 @@ export class RawServiceMeshRuntime {
379
371
  }
380
372
 
381
373
  async announcePeer(nodeRoutingId: string): Promise<boolean> {
382
- if (!this.expectedPeers.has(nodeRoutingId) || this.peerAdmissionSealed?.() === true)
374
+ const expected = this.expectedPeers.get(nodeRoutingId);
375
+ const generation = this.selectedRoutes.get(nodeRoutingId);
376
+ if (
377
+ expected === undefined ||
378
+ generation === undefined ||
379
+ expected.helloSubmittedGeneration === generation ||
380
+ this.peerAdmissionSealed?.() === true
381
+ )
383
382
  return false;
384
- return this.send(nodeRoutingId, [
383
+ const accepted = await this.send(nodeRoutingId, [
385
384
  encodeRouteMeshAdmission(M6aServiceWireCommand.hello, this.topology.localDescriptor())
386
385
  ]);
386
+ if (
387
+ accepted &&
388
+ this.expectedPeers.get(nodeRoutingId) === expected &&
389
+ this.selectedRoutes.get(nodeRoutingId) === generation
390
+ )
391
+ expected.helloSubmittedGeneration = generation;
392
+ return accepted;
387
393
  }
388
394
 
389
395
  isPeerRouteReady(nodeRoutingId: string, lifecycleGeneration?: bigint): boolean {
396
+ // Admission is bound to the observed selected route: the route observer
397
+ // removes the peer when that route ends or is replaced.
390
398
  const peer = this.topology.peer(nodeRoutingId);
391
- const monitorConnection = this.monitorConnectionStates.get(nodeRoutingId);
392
- const applicationRouteReady =
393
- monitorConnection === undefined || monitorConnection === peer?.connectionId;
394
- const ready =
399
+ return (
395
400
  peer !== undefined &&
396
401
  (lifecycleGeneration === undefined ||
397
402
  peer.descriptor.lifecycleGeneration === lifecycleGeneration) &&
398
- applicationRouteReady &&
399
- this.liveness.isReady(nodeRoutingId, peer.connectionId);
400
- return ready;
403
+ this.liveness.isReady(nodeRoutingId, peer.connectionId)
404
+ );
401
405
  }
402
406
 
403
407
  async announceExpectedPeers(): Promise<number> {
404
408
  let accepted = 0;
405
409
  for (const nodeRoutingId of this.expectedPeers.keys()) {
406
- // Admission is a one-time fence for the current physical connection.
407
- // Re-sending Hello after the peer is admitted would re-run admission on
408
- // every poll and reset the liveness record before application traffic
409
- // can use the route. A disconnected peer is removed by monitor handling
410
- // and remains eligible for the next admission attempt.
411
410
  if (this.topology.peer(nodeRoutingId) !== undefined) continue;
412
411
  if (await this.announcePeer(nodeRoutingId)) accepted++;
413
412
  }
@@ -451,7 +450,6 @@ export class RawServiceMeshRuntime {
451
450
  for (const peer of this.topology.peers()) {
452
451
  await this.send(peer.descriptor.nodeRoutingId, [update]);
453
452
  }
454
- await this.announceExpectedPeers();
455
453
  }
456
454
 
457
455
  replaceDiscoveredNotRequired(descriptors: readonly ServiceNodeDescriptor[]): void {
@@ -481,23 +479,6 @@ export class RawServiceMeshRuntime {
481
479
  if (selection.kind !== 'selected') return selection.submitResult;
482
480
  const selected = selection.peer;
483
481
  const applicationFrame = this.applicationFrame(payload);
484
- if (selected.descriptor.nodeRoutingId === this.descriptor.nodeRoutingId) {
485
- const applicationJobOwner = await this.reserveLocalIngress();
486
- try {
487
- const applicationJob = await applicationJobOwner.acquire('application');
488
- const accepted = this.mailbox.tryEnqueue({
489
- owner: `channel:${channelName}`,
490
- domain: 'application',
491
- parts: [encodeChannelSendHeader(channelName), applicationFrame],
492
- sourceRoutingId: this.descriptor.nodeRoutingId,
493
- applicationJob
494
- });
495
- if (!accepted) applicationJob.close();
496
- return accepted ? SubmitResult.Ok : SubmitResult.NotAdmitted;
497
- } finally {
498
- applicationJobOwner.close();
499
- }
500
- }
501
482
  return (await this.send(selected.descriptor.nodeRoutingId, [
502
483
  encodeChannelSendHeader(channelName),
503
484
  applicationFrame
@@ -535,7 +516,7 @@ export class RawServiceMeshRuntime {
535
516
 
536
517
  private selectChannelTarget(channelName: string): RawServiceChannelTargetSelection {
537
518
  const selected = this.topology.selectChannel(channelName, (peer) =>
538
- this.isLocalOrReadyPeer(peer.descriptor.nodeRoutingId)
519
+ this.isPeerRouteReady(peer.descriptor.nodeRoutingId)
539
520
  );
540
521
  if (selected !== undefined) return { kind: 'selected', peer: selected };
541
522
  return this.topology.hasKnownChannelTarget(channelName)
@@ -554,10 +535,6 @@ export class RawServiceMeshRuntime {
554
535
  };
555
536
  }
556
537
 
557
- private isLocalOrReadyPeer(nodeRoutingId: string): boolean {
558
- return nodeRoutingId === this.descriptor.nodeRoutingId || this.isPeerRouteReady(nodeRoutingId);
559
- }
560
-
561
538
  setServiceIngress(handler: RawServiceIngressHandler): void {
562
539
  if (this.serviceIngress !== undefined && this.serviceIngress !== handler) {
563
540
  throw new Error('Raw service ingress is already registered.');
@@ -629,24 +606,23 @@ export class RawServiceMeshRuntime {
629
606
  nowMs = performance.now(),
630
607
  observe?: RawServicePumpObserver
631
608
  ): Promise<RawServicePumpResult> {
632
- this.pullMonitorEvents();
633
609
  return this.receiveOne(nowMs, observe);
634
610
  }
635
611
 
636
- setReadableHandler(handler: () => void): void {
612
+ setReadableHandler(handler: (receiveReady: boolean, routeReady: boolean) => void): void {
637
613
  this.requireStarted().setReadableHandler(handler);
638
614
  }
639
615
 
640
616
  /** Returns whether a receive budget ended before no-data; idle ticks only maintain peers. */
641
- async pumpBatch(receiveReady = true): Promise<boolean> {
642
- await this.drainMonitorEvents();
617
+ async pumpBatch(receiveReady = true, routeReady = false): Promise<boolean> {
618
+ if (routeReady) await this.observeSelectedRoutes();
643
619
  const startedAtMs = performance.now();
644
620
  let messages = 0;
645
621
  let bytes = 0;
646
622
  const observe: RawServicePumpObserver = (_source, byteCount) => {
647
623
  bytes += byteCount;
648
624
  };
649
- while (receiveReady && messages < 64 && !this.closed) {
625
+ while (receiveReady && messages < RAW_MESH_RECEIVE_RECORD_BUDGET && !this.closed) {
650
626
  const result = await this.receiveOne(performance.now(), observe);
651
627
  if (result === 'noData') {
652
628
  receiveReady = false;
@@ -655,7 +631,11 @@ export class RawServiceMeshRuntime {
655
631
  messages += 1;
656
632
  // Core owns the per-peer fair-queue cursor. The Framework limit bounds
657
633
  // the entire round, so changing peers does not renew its byte/count budget.
658
- if (bytes >= 4 * 1024 * 1024 || performance.now() - startedAtMs >= 2) break;
634
+ if (
635
+ bytes >= RAW_MESH_RECEIVE_BYTE_BUDGET ||
636
+ performance.now() - startedAtMs >= RAW_MESH_RECEIVE_TIME_BUDGET_MS
637
+ )
638
+ break;
659
639
  }
660
640
  if (!this.closed) {
661
641
  await this.announceExpectedPeers();
@@ -711,24 +691,6 @@ export class RawServiceMeshRuntime {
711
691
  }
712
692
  }
713
693
 
714
- private pullMonitorEvents(): void {
715
- this.monitor?.drain((event) => {
716
- this.observeMonitorEvent(event);
717
- if (this.monitorEvents.length < MAX_PENDING_MONITOR_EVENTS) {
718
- this.monitorEvents.push(event);
719
- return;
720
- }
721
- const existingIndex = this.monitorEvents.findIndex((candidate) =>
722
- sameMonitorConnection(candidate, event)
723
- );
724
- if (existingIndex >= 0) this.monitorEvents[existingIndex] = event;
725
- else {
726
- this.monitorEvents.shift();
727
- this.monitorEvents.push(event);
728
- }
729
- });
730
- }
731
-
732
694
  private reportProtocolError(
733
695
  received: import('../backend/node/node-raw-binding-port').ZLinkRawReceivedRecord
734
696
  ): void {
@@ -809,14 +771,17 @@ export class RawServiceMeshRuntime {
809
771
  (expected.meshName !== descriptor.meshName ||
810
772
  expected.nodeRoutingId !== descriptor.nodeRoutingId)
811
773
  ) {
812
- await this.send(received.sourceRid, [encodeReject(3)]);
774
+ await this.send(received.sourceRid, [
775
+ encodeReject(enumWireRejectReason('identityMismatch'))
776
+ ]);
813
777
  return 'infrastructure';
814
778
  }
815
- const connection = this.currentConnectionCandidate(
816
- received.sourceRid,
817
- descriptor.advertisedEndpoint
779
+ const result = this.admitPeer(
780
+ descriptor,
781
+ routeConnectionId(received.routeGeneration),
782
+ nowMs,
783
+ expected
818
784
  );
819
- const result = this.admitPeer(descriptor, connection, nowMs, expected);
820
785
  if (result !== 'admitted' && result !== 'notRequired') {
821
786
  const detail =
822
787
  result === 'invalidDescriptor'
@@ -848,25 +813,7 @@ export class RawServiceMeshRuntime {
848
813
  }
849
814
  if (header.command === M6aServiceWireCommand.reject) {
850
815
  if (received.parts.length !== 1) return 'protocolError';
851
- const reason = decodeReject(received.parts[0]!);
852
- // A reject belongs to one physical candidate, but the wire record does
853
- // not carry that candidate's connection id. Keep an already admitted
854
- // peer: bilateral manual connect can reject the duplicate after the
855
- // other candidate has become Ready.
856
- if (reason === 4 && this.topology.peer(received.sourceRid) === undefined) {
857
- const expected = this.expectedPeers.get(received.sourceRid);
858
- const local = this.topology.localDescriptor();
859
- this.topology.markNotRequired({
860
- ...local,
861
- nodeRoutingId: received.sourceRid,
862
- lifecycleGeneration: 1n,
863
- descriptorRevision: 1n,
864
- advertisedEndpoint: expected?.endpoint ?? local.advertisedEndpoint,
865
- channels: [],
866
- objectRole: 'client'
867
- });
868
- this.retireNotRequiredExpectedPeer(received.sourceRid);
869
- }
816
+ decodeReject(received.parts[0]!);
870
817
  return 'infrastructure';
871
818
  }
872
819
  const peer = this.topology.peer(received.sourceRid);
@@ -997,6 +944,14 @@ export class RawServiceMeshRuntime {
997
944
  }
998
945
  }
999
946
 
947
+ expireOperations(nowMs: number, turnDeadlineMs: number): number {
948
+ return this.operations.expire(nowMs, turnDeadlineMs);
949
+ }
950
+
951
+ get pendingOperationCount(): number {
952
+ return this.operations.size;
953
+ }
954
+
1000
955
  async tickLiveness(nowMs = performance.now()): Promise<ServiceLivenessTick> {
1001
956
  const result = this.liveness.tick(nowMs);
1002
957
  this.requireStarted();
@@ -1011,130 +966,50 @@ export class RawServiceMeshRuntime {
1011
966
  for (const nodeRoutingId of result.timedOutNodes) {
1012
967
  const peer = this.topology.peer(nodeRoutingId);
1013
968
  if (peer === undefined) continue;
1014
- // Liveness timeout is a semantic peer removal. Route topology,
1015
- // physical candidate state, and auto-connect intent must be retired by
1016
- // the same owner so a failed endpoint cannot be selected again.
1017
- this.removeConnectionCandidate(nodeRoutingId, peer.connectionId);
969
+ // Liveness timeout is a semantic peer removal of the admitted route.
1018
970
  this.removePeer(peer);
1019
971
  }
1020
972
  return result;
1021
973
  }
1022
974
 
1023
- async drainMonitorEvents(nowMs = performance.now()): Promise<number> {
1024
- this.pullMonitorEvents();
1025
- let handled = 0;
1026
- // Detach the current batch so monitor pulls that run while an event is
1027
- // being handled append to the next batch without copying or reindexing it.
1028
- const events = this.monitorEvents;
1029
- this.monitorEvents = this.monitorDrainBuffer;
1030
- this.monitorDrainBuffer = events;
1031
- this.monitorEvents.length = 0;
1032
- for (const event of events) {
1033
- handled++;
1034
- const nodeRoutingId = event.routingId ?? this.expectedPeerRoutingId(event.remoteAddress);
1035
- if (event.event === MONITOR_CONNECTION_READY && isConnectionReadyEdge(event)) {
1036
- if (nodeRoutingId === undefined) {
1037
- const candidate = this.createUnresolvedConnectionCandidate(event);
1038
- const alreadyQueued = this.unresolvedConnectionCandidates.some(
1039
- (value) => value.connectionId === candidate.connectionId
1040
- );
1041
- if (
1042
- !alreadyQueued &&
1043
- this.unresolvedConnectionCandidates.length < MAX_UNRESOLVED_CONNECTION_CANDIDATES
1044
- ) {
1045
- this.unresolvedConnectionCandidates.push(candidate);
1046
- }
1047
- continue;
1048
- }
1049
- if (!this.acceptsExpectedMonitorEndpoint(nodeRoutingId, event)) {
1050
- continue;
1051
- }
1052
- const candidate = this.createConnectionCandidate(nodeRoutingId, event);
1053
- const existingPeer = this.topology.peer(nodeRoutingId);
1054
- if (existingPeer !== undefined && existingPeer.connectionId === candidate.connectionId) {
1055
- this.monitorConnectionStates.set(nodeRoutingId, candidate.connectionId);
1056
- continue;
1057
- }
1058
- if (existingPeer !== undefined) {
1059
- if (this.liveness.isReady(nodeRoutingId, existingPeer.connectionId)) {
1060
- const existingCandidate = this.connectionCandidates
1061
- .get(nodeRoutingId)
1062
- ?.get(existingPeer.connectionId);
1063
- if (this.isDiscoveredLifecycleReplacement(existingPeer, nodeRoutingId)) {
1064
- // A current discovery descriptor with the same RID but a
1065
- // different lifecycle token denotes a replacement process.
1066
- // Keep its physical pair provisional until its Hello passes
1067
- // the descriptor fence; the old ready peer remains semantic
1068
- // current until then.
1069
- let provisionalCandidates = this.connectionCandidates.get(nodeRoutingId);
1070
- if (provisionalCandidates === undefined) {
1071
- provisionalCandidates = new Map();
1072
- this.connectionCandidates.set(nodeRoutingId, provisionalCandidates);
1073
- }
1074
- provisionalCandidates.set(candidate.connectionId, candidate);
1075
- await this.announcePeer(nodeRoutingId);
1076
- continue;
1077
- }
1078
- if (existingCandidate?.connectionId === candidate.connectionId) {
1079
- this.removeConnectionCandidate(nodeRoutingId, candidate.connectionId);
1080
- this.monitorConnectionStates.set(nodeRoutingId, existingPeer.connectionId);
1081
- continue;
1082
- }
1083
- // A non-replacement ready route is the current semantic owner.
1084
- // A second physical candidate may be admitted only after the
1085
- // current lease expires; this also prevents a late old-process
1086
- // reconnect from replacing the ready replacement by arrival order.
1087
- this.removeConnectionCandidate(nodeRoutingId, candidate.connectionId);
1088
- continue;
1089
- }
1090
- // Keep the physical candidate until the wire descriptor decides
1091
- // whether it is the current logical peer. READY events can race
1092
- // with DISCONNECTED events during reconnect; rejecting the READY
1093
- // here can terminate the replacement before admission evaluates its
1094
- // lifecycle generation.
1095
- let provisionalCandidates = this.connectionCandidates.get(nodeRoutingId);
1096
- if (provisionalCandidates === undefined) {
1097
- provisionalCandidates = new Map();
1098
- this.connectionCandidates.set(nodeRoutingId, provisionalCandidates);
1099
- }
1100
- provisionalCandidates.set(candidate.connectionId, candidate);
1101
- this.connectionIds.set(nodeRoutingId, candidate.connectionId);
1102
- await this.announcePeer(nodeRoutingId);
1103
- continue;
1104
- }
1105
- let candidates = this.connectionCandidates.get(nodeRoutingId);
1106
- if (candidates === undefined) {
1107
- candidates = new Map();
1108
- this.connectionCandidates.set(nodeRoutingId, candidates);
1109
- }
1110
- candidates.set(candidate.connectionId, candidate);
1111
- // Before wire admission the monitor candidate is the only physical
1112
- // route evidence available to the admission message.
1113
- this.connectionIds.set(nodeRoutingId, candidate.connectionId);
1114
- await this.announcePeer(nodeRoutingId);
1115
- } else if (event.event === MONITOR_DISCONNECTED && nodeRoutingId !== undefined) {
1116
- const peer = this.topology.peer(nodeRoutingId);
1117
- const disconnectedId = monitorConnectionId(event, nodeRoutingId);
1118
- this.removeConnectionCandidate(nodeRoutingId, disconnectedId);
1119
- if (peer !== undefined && peer.connectionId === disconnectedId) {
1120
- this.removePeer(peer);
1121
- }
1122
- } else if (event.event === MONITOR_DISCONNECTED) {
1123
- const disconnectedId = monitorConnectionId(event);
1124
- const index = this.unresolvedConnectionCandidates.findIndex(
1125
- (candidate) => candidate.connectionId === disconnectedId
1126
- );
1127
- if (index >= 0) this.unresolvedConnectionCandidates.splice(index, 1);
975
+ /**
976
+ * The socket's one route observer (Core ROUTER §10.1). It replaces the
977
+ * observation with Core's selected-route snapshot, ends the admission of
978
+ * every RID whose observed route disappeared or was replaced, and starts the
979
+ * handshake of every newly selected route. Returns the number of changes.
980
+ */
981
+ async observeSelectedRoutes(): Promise<number> {
982
+ const router = this.router;
983
+ if (router === undefined || this.closed) return 0;
984
+ const observed = new Map<string, bigint>();
985
+ for (const route of router.routesSnapshot()) {
986
+ observed.set(route.routingId, route.routeGeneration);
987
+ }
988
+ let changes = 0;
989
+ for (const [nodeRoutingId, generation] of this.selectedRoutes) {
990
+ if (observed.get(nodeRoutingId) === generation) continue;
991
+ changes++;
992
+ const expected = this.expectedPeers.get(nodeRoutingId);
993
+ if (expected !== undefined) delete expected.helloSubmittedGeneration;
994
+ const peer = this.topology.peer(nodeRoutingId);
995
+ if (peer !== undefined && peer.connectionId === routeConnectionId(generation)) {
996
+ this.removePeer(peer);
1128
997
  }
1129
998
  }
1130
- this.monitorDrainBuffer.length = 0;
1131
- void nowMs;
1132
- return handled;
999
+ const selected: string[] = [];
1000
+ for (const [nodeRoutingId, generation] of observed) {
1001
+ if (this.selectedRoutes.get(nodeRoutingId) === generation) continue;
1002
+ if (!this.selectedRoutes.has(nodeRoutingId)) changes++;
1003
+ selected.push(nodeRoutingId);
1004
+ }
1005
+ this.selectedRoutes = observed;
1006
+ // A new selected route admits only through a new handshake.
1007
+ for (const nodeRoutingId of selected) await this.announcePeer(nodeRoutingId);
1008
+ return changes;
1133
1009
  }
1134
1010
 
1135
1011
  close(): void {
1136
1012
  if (this.closed) return;
1137
- this.closed = true;
1138
1013
  this.applicationJobStop.abort(
1139
1014
  new Error('Raw service runtime application job admission stopped.')
1140
1015
  );
@@ -1145,12 +1020,11 @@ export class RawServiceMeshRuntime {
1145
1020
  if (router !== undefined) {
1146
1021
  this.applicationJobQueue.unregisterReceiveFlowTarget?.(router);
1147
1022
  }
1148
- this.monitor?.close();
1149
- this.monitor = undefined;
1150
1023
  const host = this.host;
1024
+ if (host !== undefined) host.close();
1151
1025
  this.router = undefined;
1152
1026
  this.host = undefined;
1153
- if (host !== undefined) host.close();
1027
+ this.closed = true;
1154
1028
  }
1155
1029
 
1156
1030
  private requestToTarget(
@@ -1181,14 +1055,11 @@ export class RawServiceMeshRuntime {
1181
1055
  for (;;) {
1182
1056
  const alternate = this.topology.selectChannel(channelName, (peer) => {
1183
1057
  const candidate = peer.descriptor.nodeRoutingId;
1184
- return !excludedTargets.has(candidate) && this.isLocalOrReadyPeer(candidate);
1058
+ return !excludedTargets.has(candidate) && this.isPeerRouteReady(candidate);
1185
1059
  });
1186
1060
  if (alternate === undefined) break;
1187
1061
  selectedTargetNodeRoutingId = alternate.descriptor.nodeRoutingId;
1188
- if (
1189
- selectedTargetNodeRoutingId === this.descriptor.nodeRoutingId ||
1190
- this.isPeerRouteReady(selectedTargetNodeRoutingId)
1191
- ) {
1062
+ if (this.isPeerRouteReady(selectedTargetNodeRoutingId)) {
1192
1063
  break;
1193
1064
  }
1194
1065
  excludedTargets.add(selectedTargetNodeRoutingId);
@@ -1212,10 +1083,7 @@ export class RawServiceMeshRuntime {
1212
1083
  return;
1213
1084
  }
1214
1085
  const accepted = this.mailbox.tryEnqueue({
1215
- owner:
1216
- channelName === undefined
1217
- ? `node:${this.descriptor.nodeRoutingId}`
1218
- : `channel:${channelName}`,
1086
+ owner: `node:${this.descriptor.nodeRoutingId}`,
1219
1087
  domain: 'application',
1220
1088
  parts,
1221
1089
  sourceRoutingId: this.descriptor.nodeRoutingId,
@@ -1241,17 +1109,13 @@ export class RawServiceMeshRuntime {
1241
1109
  })().catch((error) => this.operations.fail(pending.id, error));
1242
1110
  return pending;
1243
1111
  }
1244
- if (!this.isPeerRouteReady(selectedTargetNodeRoutingId)) {
1245
- // Preserve Core's distinct target-not-found result for an RID the
1246
- // topology has never observed. A known peer without a usable route is
1247
- // a Framework NotConnected result; an unknown RID is completed locally
1248
- // as RequestTargetNotFound without submitting an application frame.
1249
- const knownTarget =
1250
- this.topology.peer(selectedTargetNodeRoutingId) !== undefined ||
1251
- this.topology.knownDescriptor(selectedTargetNodeRoutingId) !== undefined;
1112
+ if (this.topology.peer(selectedTargetNodeRoutingId) === undefined) {
1113
+ // Logical target selection is the requester's decision: an RID that is
1114
+ // not an admitted peer is not a target. Whether an admitted target's
1115
+ // route can carry the request is Core's REQUEST result.
1252
1116
  this.operations.complete(pending.id, {
1253
- terminalResult: knownTarget ? RequestResult.NotConnected : RequestResult.NotFound,
1254
- failureCode: knownTarget ? 0 : REQUEST_TARGET_NOT_FOUND_FAILURE_CODE
1117
+ terminalResult: RequestResult.NotFound,
1118
+ failureCode: REQUEST_TARGET_NOT_FOUND_FAILURE_CODE
1255
1119
  });
1256
1120
  return pending;
1257
1121
  }
@@ -1320,7 +1184,7 @@ export class RawServiceMeshRuntime {
1320
1184
 
1321
1185
  private admitPeer(
1322
1186
  descriptor: ServiceNodeDescriptor,
1323
- connection: PhysicalConnectionCandidate,
1187
+ connectionId: string,
1324
1188
  nowMs: number,
1325
1189
  expected?: {
1326
1190
  readonly endpoint?: string;
@@ -1340,232 +1204,16 @@ export class RawServiceMeshRuntime {
1340
1204
  `RouteMesh peer '${descriptor.nodeRoutingId}' descriptor revision is stale or conflicting.`
1341
1205
  );
1342
1206
  }
1343
- const result = this.topology.admit(
1344
- descriptor,
1345
- connection.connectionId,
1346
- expected,
1347
- connection.discriminator
1348
- );
1207
+ const result = this.topology.admit(descriptor, connectionId, expected);
1349
1208
  if (result === 'admitted') {
1350
- this.connectionIds.set(descriptor.nodeRoutingId, connection.connectionId);
1351
- this.liveness.admit(descriptor.nodeRoutingId, connection.connectionId, nowMs);
1352
- this.liveness.requestProbe(descriptor.nodeRoutingId, connection.connectionId, nowMs);
1353
- this.monitorConnectionStates.set(descriptor.nodeRoutingId, connection.connectionId);
1354
- if (previous !== undefined && previous.connectionId !== connection.connectionId) {
1355
- const previousCandidate = this.connectionCandidates
1356
- .get(descriptor.nodeRoutingId)
1357
- ?.get(previous.connectionId);
1358
- if (previousCandidate !== undefined) {
1359
- this.removeConnectionCandidate(descriptor.nodeRoutingId, previousCandidate.connectionId);
1360
- }
1361
- }
1209
+ this.liveness.admit(descriptor.nodeRoutingId, connectionId, nowMs);
1210
+ this.liveness.requestProbe(descriptor.nodeRoutingId, connectionId, nowMs);
1362
1211
  } else if (result === 'notRequired' && previous !== undefined) {
1363
1212
  this.liveness.disconnect(descriptor.nodeRoutingId, previous.connectionId);
1364
- } else if (previous !== undefined) {
1365
- this.connectionIds.set(descriptor.nodeRoutingId, previous.connectionId);
1366
- if (connection.connectionId !== previous.connectionId) {
1367
- this.removeConnectionCandidate(descriptor.nodeRoutingId, connection.connectionId);
1368
- }
1369
1213
  }
1370
1214
  return result;
1371
1215
  }
1372
1216
 
1373
- private currentConnectionCandidate(
1374
- nodeRoutingId: string,
1375
- advertisedEndpoint: string
1376
- ): PhysicalConnectionCandidate {
1377
- let connectionId = this.connectionIds.get(nodeRoutingId);
1378
- let candidate =
1379
- connectionId === undefined
1380
- ? undefined
1381
- : this.connectionCandidates.get(nodeRoutingId)?.get(connectionId);
1382
- if (candidate === undefined) {
1383
- candidate = this.promoteUnresolvedConnectionCandidate(nodeRoutingId, advertisedEndpoint);
1384
- connectionId = candidate?.connectionId;
1385
- }
1386
- if (candidate === undefined) {
1387
- const localRid = this.topology.localDescriptor().nodeRoutingId;
1388
- const endpointOnly = this.endpointOnlyPeers.has(advertisedEndpoint);
1389
- const direction: PhysicalConnectionDirection = this.expectedPeers.has(nodeRoutingId)
1390
- ? 'outbound'
1391
- : endpointOnly
1392
- ? localRid.localeCompare(nodeRoutingId) <= 0
1393
- ? 'outbound'
1394
- : 'inbound'
1395
- : 'inbound';
1396
- const initiator =
1397
- endpointOnly && localRid.localeCompare(nodeRoutingId) > 0
1398
- ? nodeRoutingId
1399
- : direction === 'outbound'
1400
- ? localRid
1401
- : nodeRoutingId;
1402
- connectionId = `unmonitored:${direction}:${randomUUID()}`;
1403
- candidate = {
1404
- connectionId,
1405
- direction,
1406
- discriminator: `initiator:${initiator}`,
1407
- localAddress: '',
1408
- remoteAddress: advertisedEndpoint
1409
- };
1410
- let candidates = this.connectionCandidates.get(nodeRoutingId);
1411
- if (candidates === undefined) {
1412
- candidates = new Map();
1413
- this.connectionCandidates.set(nodeRoutingId, candidates);
1414
- }
1415
- candidates.set(connectionId, candidate);
1416
- this.connectionIds.set(nodeRoutingId, connectionId);
1417
- }
1418
- return candidate;
1419
- }
1420
-
1421
- private createConnectionCandidate(
1422
- nodeRoutingId: string,
1423
- event: ZLinkRawMonitorRecord
1424
- ): PhysicalConnectionCandidate {
1425
- const local = this.topology.localDescriptor();
1426
- const expected = this.expectedPeers.get(nodeRoutingId);
1427
- const direction: PhysicalConnectionDirection =
1428
- event.localAddress === local.advertisedEndpoint
1429
- ? 'inbound'
1430
- : expected?.endpoint === event.remoteAddress
1431
- ? 'outbound'
1432
- : this.endpointOnlyPeers.has(event.remoteAddress)
1433
- ? 'outbound'
1434
- : 'unknown';
1435
- const initiator =
1436
- direction === 'outbound'
1437
- ? local.nodeRoutingId
1438
- : direction === 'inbound'
1439
- ? nodeRoutingId
1440
- : undefined;
1441
- return {
1442
- connectionId: monitorConnectionId(event, nodeRoutingId),
1443
- direction,
1444
- discriminator:
1445
- initiator === undefined
1446
- ? `unknown:${monitorConnectionId(event, nodeRoutingId)}`
1447
- : `initiator:${initiator}`,
1448
- localAddress: event.localAddress,
1449
- remoteAddress: event.remoteAddress
1450
- };
1451
- }
1452
-
1453
- private createUnresolvedConnectionCandidate(
1454
- event: ZLinkRawMonitorRecord
1455
- ): PhysicalConnectionCandidate {
1456
- const connectionId = monitorConnectionId(event);
1457
- const local = this.topology.localDescriptor();
1458
- const direction: PhysicalConnectionDirection =
1459
- this.endpointOnlyPeers.has(event.remoteAddress) ||
1460
- this.expectedPeerRoutingId(event.remoteAddress) !== undefined
1461
- ? 'outbound'
1462
- : event.localAddress === local.advertisedEndpoint
1463
- ? 'inbound'
1464
- : 'unknown';
1465
- return {
1466
- connectionId,
1467
- direction,
1468
- discriminator: `unresolved:${connectionId}`,
1469
- localAddress: event.localAddress,
1470
- remoteAddress: event.remoteAddress
1471
- };
1472
- }
1473
-
1474
- private promoteUnresolvedConnectionCandidate(
1475
- nodeRoutingId: string,
1476
- advertisedEndpoint: string
1477
- ): PhysicalConnectionCandidate | undefined {
1478
- const relevant = this.unresolvedConnectionCandidates
1479
- .map((candidate, index) => ({ candidate, index }))
1480
- .filter(
1481
- ({ candidate }) =>
1482
- candidate.remoteAddress === advertisedEndpoint || candidate.direction === 'inbound'
1483
- );
1484
- if (relevant.length === 0) return undefined;
1485
- const directions = new Set(relevant.map((value) => value.candidate.direction));
1486
- const localRid = this.topology.localDescriptor().nodeRoutingId;
1487
- const preferredDirection: PhysicalConnectionDirection =
1488
- directions.has('inbound') && directions.has('outbound')
1489
- ? localRid.localeCompare(nodeRoutingId) <= 0
1490
- ? 'outbound'
1491
- : 'inbound'
1492
- : relevant.at(-1)!.candidate.direction;
1493
- const selected =
1494
- [...relevant].reverse().find((value) => value.candidate.direction === preferredDirection) ??
1495
- relevant.at(-1)!;
1496
- this.unresolvedConnectionCandidates.splice(selected.index, 1);
1497
- const initiator =
1498
- selected.candidate.direction === 'outbound'
1499
- ? localRid
1500
- : selected.candidate.direction === 'inbound'
1501
- ? nodeRoutingId
1502
- : undefined;
1503
- const candidate: PhysicalConnectionCandidate = {
1504
- ...selected.candidate,
1505
- discriminator:
1506
- initiator === undefined
1507
- ? `unknown:${selected.candidate.connectionId}`
1508
- : `initiator:${initiator}`
1509
- };
1510
- let candidates = this.connectionCandidates.get(nodeRoutingId);
1511
- if (candidates === undefined) {
1512
- candidates = new Map();
1513
- this.connectionCandidates.set(nodeRoutingId, candidates);
1514
- }
1515
- candidates.set(candidate.connectionId, candidate);
1516
- this.connectionIds.set(nodeRoutingId, candidate.connectionId);
1517
- return candidate;
1518
- }
1519
-
1520
- private removeConnectionCandidate(nodeRoutingId: string, connectionId: string): void {
1521
- const candidates = this.connectionCandidates.get(nodeRoutingId);
1522
- candidates?.delete(connectionId);
1523
- if (candidates?.size === 0) this.connectionCandidates.delete(nodeRoutingId);
1524
- if (this.connectionIds.get(nodeRoutingId) === connectionId) {
1525
- this.connectionIds.delete(nodeRoutingId);
1526
- }
1527
- }
1528
-
1529
- private isDiscoveredLifecycleReplacement(
1530
- admitted: AdmittedServicePeer,
1531
- nodeRoutingId: string
1532
- ): boolean {
1533
- const expected = this.expectedPeers.get(nodeRoutingId);
1534
- // A same-RID replacement is permitted only from a complete discovery
1535
- // fence. Manual/endpoint-only intent has no authority to replace a ready
1536
- // peer, and lifecycle generations are opaque equality tokens.
1537
- return (
1538
- expected?.endpoint !== undefined &&
1539
- expected.securityIdentity !== undefined &&
1540
- expected.lifecycleGeneration !== undefined &&
1541
- admitted.descriptor.lifecycleGeneration !== expected.lifecycleGeneration
1542
- );
1543
- }
1544
-
1545
- private expectedPeerRoutingId(endpoint: string): string | undefined {
1546
- for (const [nodeRoutingId, expected] of this.expectedPeers) {
1547
- if (expected.endpoint === endpoint) return nodeRoutingId;
1548
- }
1549
- return undefined;
1550
- }
1551
-
1552
- private acceptsExpectedMonitorEndpoint(
1553
- nodeRoutingId: string,
1554
- event: Pick<ZLinkRawMonitorRecord, 'remoteAddress' | 'routingId'>
1555
- ): boolean {
1556
- // A monitor address is the physical socket address, which may be an
1557
- // ephemeral port. Once Core has resolved the peer routing ID, that ID is
1558
- // the semantic identity; comparing the physical address with the
1559
- // discovery advertised endpoint would reject valid READY events.
1560
- if (event.routingId === nodeRoutingId) return true;
1561
- const expected = this.expectedPeers.get(nodeRoutingId);
1562
- return (
1563
- expected === undefined ||
1564
- expected.endpoint === undefined ||
1565
- expected.endpoint === event.remoteAddress
1566
- );
1567
- }
1568
-
1569
1217
  private retireNotRequiredExpectedPeer(nodeRoutingId: string, advertisedEndpoint?: string): void {
1570
1218
  const expected = this.expectedPeers.get(nodeRoutingId);
1571
1219
  const endpoint =
@@ -1597,9 +1245,6 @@ export class RawServiceMeshRuntime {
1597
1245
  }
1598
1246
 
1599
1247
  private removePeer(peer: AdmittedServicePeer): void {
1600
- if (this.monitorConnectionStates.get(peer.descriptor.nodeRoutingId) === peer.connectionId) {
1601
- this.monitorConnectionStates.set(peer.descriptor.nodeRoutingId, null);
1602
- }
1603
1248
  this.topology.disconnect(peer.descriptor.nodeRoutingId, peer.connectionId);
1604
1249
  this.liveness.disconnect(peer.descriptor.nodeRoutingId, peer.connectionId);
1605
1250
  this.onPeerDisconnected?.(
@@ -1609,25 +1254,6 @@ export class RawServiceMeshRuntime {
1609
1254
  );
1610
1255
  }
1611
1256
 
1612
- private observeMonitorEvent(event: ZLinkRawMonitorRecord): void {
1613
- const nodeRoutingId = event.routingId ?? this.expectedPeerRoutingId(event.remoteAddress);
1614
- if (nodeRoutingId === undefined) return;
1615
- const connectionId = monitorConnectionId(event, nodeRoutingId);
1616
- if (event.event === MONITOR_CONNECTION_READY && isConnectionReadyEdge(event)) {
1617
- if (!this.acceptsExpectedMonitorEndpoint(nodeRoutingId, event)) return;
1618
- // The event is queued for admission. Updating monitor state here would
1619
- // allow a late stale READY to overwrite the admitted replacement.
1620
- return;
1621
- }
1622
- if (
1623
- event.event === MONITOR_DISCONNECTED &&
1624
- this.monitorConnectionStates.get(nodeRoutingId) === connectionId &&
1625
- this.topology.peer(nodeRoutingId)?.connectionId === connectionId
1626
- ) {
1627
- this.monitorConnectionStates.set(nodeRoutingId, null);
1628
- }
1629
- }
1630
-
1631
1257
  private requireStarted(): ZLinkRawRouterPort {
1632
1258
  if (this.router === undefined) throw new Error('Raw service runtime is not started.');
1633
1259
  return this.router;
@@ -1677,38 +1303,15 @@ function isAlreadyDisconnectedError(error: unknown): boolean {
1677
1303
  if (typeof error !== 'object' || error === null || !('nativeErrno' in error)) {
1678
1304
  return false;
1679
1305
  }
1680
- return (error as { readonly nativeErrno?: unknown }).nativeErrno === 2;
1681
- }
1682
-
1683
- function monitorConnectionId(
1684
- event: ZLinkRawMonitorRecord,
1685
- resolvedNodeRoutingId = event.routingId ?? ''
1686
- ): string {
1687
- if (event.connectionId !== undefined && event.connectionId !== 0n) {
1688
- return JSON.stringify([resolvedNodeRoutingId, 'connection', event.connectionId.toString()]);
1689
- }
1690
- return JSON.stringify([
1691
- // Monitor `value` is event-specific: CONNECTION_READY reports the
1692
- // socket's ready count and DISCONNECTED reports its reason. It is not a
1693
- // connection identity. The public monitor record has no native
1694
- // connection id, so use the stable routing and endpoint tuple instead.
1695
- resolvedNodeRoutingId,
1696
- event.localAddress,
1697
- event.remoteAddress
1698
- ]);
1306
+ return (error as { readonly nativeErrno?: unknown }).nativeErrno === nativeErrnoValues.ENOENT;
1699
1307
  }
1700
1308
 
1701
- function sameMonitorConnection(left: ZLinkRawMonitorRecord, right: ZLinkRawMonitorRecord): boolean {
1702
- return (
1703
- monitorConnectionId(left) === monitorConnectionId(right) &&
1704
- left.remoteAddress === right.remoteAddress
1705
- );
1706
- }
1707
-
1708
- function isConnectionReadyEdge(event: ZLinkRawMonitorRecord): boolean {
1709
- return event.flags === undefined
1710
- ? event.value > 0n
1711
- : (event.flags & MONITOR_CONNECTION_READY_EDGE) !== 0;
1309
+ /**
1310
+ * An admission belongs to one Core selected route. Its connection identity is
1311
+ * that route's generation, an opaque token compared only for equality.
1312
+ */
1313
+ function routeConnectionId(routeGeneration: bigint): string {
1314
+ return `route:${routeGeneration.toString()}`;
1712
1315
  }
1713
1316
 
1714
1317
  function describeInvalidAdmissionDescriptor(
@@ -1778,17 +1381,13 @@ function immutableDescriptorMismatch(
1778
1381
  return undefined;
1779
1382
  }
1780
1383
 
1781
- function admissionReason(result: PeerAdmissionResult): number {
1384
+ function admissionReason(result: Exclude<PeerAdmissionResult, 'admitted' | 'notRequired'>): number {
1782
1385
  switch (result) {
1783
1386
  case 'meshMismatch':
1784
- return 2;
1387
+ return enumWireRejectReason('topologyMismatch');
1785
1388
  case 'staleDescriptor':
1786
- return 7;
1389
+ return enumWireRejectReason('descriptorRevisionStale');
1787
1390
  case 'invalidDescriptor':
1788
- return 11;
1789
- case 'notRequired':
1790
- return 4;
1791
- case 'admitted':
1792
- return 1;
1391
+ return enumWireRejectReason('invalidDescriptor');
1793
1392
  }
1794
1393
  }