@zlink-systems/framework 0.29.1 → 0.30.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (322) hide show
  1. package/LICENSE +150 -68
  2. package/dist/.tsbuildinfo +1 -1
  3. package/dist/contracts/Actors/ZLinkActorClient.d.ts +2 -1
  4. package/dist/contracts/Channels/Calls.d.ts +2 -1
  5. package/dist/contracts/Common/ZLinkMessageMetadata.js +11 -5
  6. package/dist/contracts/Configuration/Builders.d.ts +1 -2
  7. package/dist/contracts/Configuration/Configs.d.ts +0 -5
  8. package/dist/contracts/Configuration/RegistrationBuilders.js +6 -4
  9. package/dist/contracts/Configuration/RegistrationTypes.d.ts +1 -6
  10. package/dist/contracts/Configuration/RegistrationValidators.js +4 -4
  11. package/dist/contracts/Configuration/index.d.ts +1 -1
  12. package/dist/contracts/Handlers/Attributes.d.ts +5 -13
  13. package/dist/contracts/Handlers/Attributes.js +7 -11
  14. package/dist/contracts/Handlers/JsonContract.d.ts +2 -46
  15. package/dist/contracts/Handlers/JsonContract.js +4 -153
  16. package/dist/contracts/Spots/Contracts.d.ts +2 -1
  17. package/dist/internal.d.ts +1 -0
  18. package/dist/internal.js +3 -1
  19. package/dist/nest-integration.d.ts +1 -1
  20. package/dist/nest-integration.js +2 -1
  21. package/dist/runtime/actors/actor-client.d.ts +1 -1
  22. package/dist/runtime/actors/actor-client.js +14 -12
  23. package/dist/runtime/actors/actor-handoff.d.ts +3 -2
  24. package/dist/runtime/actors/actor-handoff.js +15 -7
  25. package/dist/runtime/actors/actor-join-relocation.d.ts +1 -0
  26. package/dist/runtime/actors/actor-local-native-join.js +9 -12
  27. package/dist/runtime/actors/actor-remote-wire.js +15 -0
  28. package/dist/runtime/actors/actor-routed-join-transport.d.ts +6 -2
  29. package/dist/runtime/actors/actor-routed-json-request.d.ts +2 -0
  30. package/dist/runtime/actors/index.d.ts +2 -1
  31. package/dist/runtime/actors/index.js +18 -6
  32. package/dist/runtime/actors/spot-actor-dispatch.js +2 -2
  33. package/dist/runtime/admission.d.ts +1 -1
  34. package/dist/runtime/admission.js +15 -5
  35. package/dist/runtime/application-jobs/application-ingress-record-owner.d.ts +9 -9
  36. package/dist/runtime/application-jobs/application-ingress-record-owner.js +45 -23
  37. package/dist/runtime/application-jobs/application-job-queue-scope.d.ts +5 -2
  38. package/dist/runtime/application-jobs/application-job-queue-scope.js +41 -21
  39. package/dist/runtime/application-jobs/contracts.d.ts +15 -2
  40. package/dist/runtime/backend/contracts/index.d.ts +27 -27
  41. package/dist/runtime/backend/mesh-completion-table.d.ts +15 -5
  42. package/dist/runtime/backend/mesh-completion-table.js +160 -50
  43. package/dist/runtime/backend/mesh-dispatch-pump.d.ts +3 -0
  44. package/dist/runtime/backend/mesh-dispatch-pump.js +53 -36
  45. package/dist/runtime/backend/node/node-backend-adapter-factory.js +6 -1
  46. package/dist/runtime/backend/node/node-backend-adapter-support.d.ts +3 -3
  47. package/dist/runtime/backend/node/node-backend-adapter-support.js +33 -31
  48. package/dist/runtime/backend/node/node-dealer-channel-client-transport.d.ts +1 -1
  49. package/dist/runtime/backend/node/node-dealer-channel-client-transport.js +5 -2
  50. package/dist/runtime/backend/node/node-mesh-backend-adapter.d.ts +1 -9
  51. package/dist/runtime/backend/node/node-mesh-backend-adapter.js +1 -1
  52. package/dist/runtime/backend/node/node-raw-binding-port.js +50 -25
  53. package/dist/runtime/backend/node/node-raw-mesh-backend.d.ts +22 -16
  54. package/dist/runtime/backend/node/node-raw-mesh-backend.js +133 -149
  55. package/dist/runtime/backend/node/node-socket-backend-adapter.js +15 -10
  56. package/dist/runtime/backend/raw-binding-port.d.ts +10 -3
  57. package/dist/runtime/backend/runtime-message.d.ts +1 -0
  58. package/dist/runtime/backend/runtime-message.js +5 -0
  59. package/dist/runtime/backend/runtime-values.d.ts +1 -0
  60. package/dist/runtime/backend/runtime-values.js +2 -1
  61. package/dist/runtime/channels/channel-clients.d.ts +1 -0
  62. package/dist/runtime/channels/channel-clients.js +58 -21
  63. package/dist/runtime/channels/channel-dispatch-pipeline.d.ts +3 -2
  64. package/dist/runtime/channels/channel-dispatch-pipeline.js +20 -11
  65. package/dist/runtime/channels/channel-dispatch-services.d.ts +1 -0
  66. package/dist/runtime/channels/channel-dispatch-services.js +45 -0
  67. package/dist/runtime/channels/channel-dispatchers.d.ts +1 -1
  68. package/dist/runtime/channels/channel-dispatchers.js +27 -26
  69. package/dist/runtime/channels/channel-envelope-inspection.d.ts +1 -2
  70. package/dist/runtime/channels/channel-envelope-inspection.js +1 -16
  71. package/dist/runtime/channels/channel-envelope.d.ts +1 -0
  72. package/dist/runtime/channels/channel-envelope.js +83 -8
  73. package/dist/runtime/channels/channel-outbound-operations.d.ts +2 -2
  74. package/dist/runtime/channels/channel-outbound-operations.js +8 -8
  75. package/dist/runtime/channels/channel-receive-loops.js +3 -3
  76. package/dist/runtime/channels/channel-runtime-lifecycle.js +2 -1
  77. package/dist/runtime/channels/channel-runtime-manager.d.ts +6 -6
  78. package/dist/runtime/channels/channel-runtime-manager.js +12 -12
  79. package/dist/runtime/channels/channel-socket-registry.d.ts +10 -3
  80. package/dist/runtime/channels/channel-socket-registry.js +59 -82
  81. package/dist/runtime/channels/channel-transports.d.ts +18 -15
  82. package/dist/runtime/channels/channel-transports.js +48 -31
  83. package/dist/runtime/channels/local-spot-route-transport.d.ts +1 -1
  84. package/dist/runtime/channels/local-spot-route-transport.js +2 -1
  85. package/dist/runtime/channels/router-socket-spot-route-transport.d.ts +2 -2
  86. package/dist/runtime/channels/router-socket-spot-route-transport.js +4 -4
  87. package/dist/runtime/channels/source-spot-router.d.ts +2 -2
  88. package/dist/runtime/channels/source-spot-router.js +4 -4
  89. package/dist/runtime/channels/spot-node-route-transport.d.ts +2 -2
  90. package/dist/runtime/channels/spot-node-route-transport.js +4 -4
  91. package/dist/runtime/channels/spot-route-bridge-transport.d.ts +2 -2
  92. package/dist/runtime/channels/spot-route-bridge-transport.js +4 -4
  93. package/dist/runtime/channels/spot-route-dispatch-strategy.d.ts +5 -4
  94. package/dist/runtime/channels/spot-route-dispatch-strategy.js +18 -18
  95. package/dist/runtime/diagnostics/message-flow.d.ts +1 -0
  96. package/dist/runtime/diagnostics/message-flow.js +3 -3
  97. package/dist/runtime/execution/serial-execution-queue.d.ts +1 -0
  98. package/dist/runtime/execution/serial-execution-queue.js +1 -0
  99. package/dist/runtime/foundation/actor-join-recovery-codec.js +2 -2
  100. package/dist/runtime/foundation/durable-service-request.d.ts +14 -0
  101. package/dist/runtime/foundation/durable-service-request.js +98 -0
  102. package/dist/runtime/foundation/operation-identity.d.ts +1 -0
  103. package/dist/runtime/foundation/operation-identity.js +5 -1
  104. package/dist/runtime/foundation/raw-service-mesh-runtime.d.ts +37 -6
  105. package/dist/runtime/foundation/raw-service-mesh-runtime.js +473 -220
  106. package/dist/runtime/foundation/service-liveness-registry.d.ts +20 -8
  107. package/dist/runtime/foundation/service-liveness-registry.js +57 -44
  108. package/dist/runtime/foundation/service-mailbox.d.ts +3 -0
  109. package/dist/runtime/foundation/service-mailbox.js +2 -1
  110. package/dist/runtime/foundation/service-relocation-object-owner.d.ts +1 -0
  111. package/dist/runtime/foundation/service-relocation-object-owner.js +1 -0
  112. package/dist/runtime/foundation/service-relocation-runtime.d.ts +2 -0
  113. package/dist/runtime/foundation/service-relocation-runtime.js +13 -1
  114. package/dist/runtime/foundation/service-runtime-contracts.d.ts +2 -0
  115. package/dist/runtime/foundation/service-stateful-runtime.d.ts +10 -9
  116. package/dist/runtime/foundation/service-stateful-runtime.js +78 -126
  117. package/dist/runtime/foundation/service-stateful-wire-codec.d.ts +5 -7
  118. package/dist/runtime/foundation/service-stateful-wire-codec.js +43 -61
  119. package/dist/runtime/foundation/service-topology-registry.d.ts +16 -4
  120. package/dist/runtime/foundation/service-topology-registry.js +69 -30
  121. package/dist/runtime/foundation/service-wire-m6a-codec.d.ts +3 -3
  122. package/dist/runtime/foundation/service-wire-m6a-codec.js +36 -38
  123. package/dist/runtime/handlers/handler-instance-scope.d.ts +8 -0
  124. package/dist/runtime/handlers/handler-instance-scope.js +54 -11
  125. package/dist/runtime/host/actor-packet-relay.js +7 -7
  126. package/dist/runtime/host/actor-runtime-options-factory.js +2 -2
  127. package/dist/runtime/host/application-job-queue.d.ts +28 -9
  128. package/dist/runtime/host/application-job-queue.js +214 -50
  129. package/dist/runtime/host/entry-actor-runtime.d.ts +1 -0
  130. package/dist/runtime/host/entry-actor-runtime.js +4 -1
  131. package/dist/runtime/host/index.d.ts +7 -1
  132. package/dist/runtime/host/index.js +154 -126
  133. package/dist/runtime/host/instance-activation-authority.d.ts +2 -1
  134. package/dist/runtime/host/instance-activation-authority.js +89 -25
  135. package/dist/runtime/host/remote-bound-session-relay.js +2 -18
  136. package/dist/runtime/host/route-mesh-runtime.js +1 -1
  137. package/dist/runtime/host/service-relocation-control.d.ts +1 -0
  138. package/dist/runtime/host/service-relocation-control.js +10 -4
  139. package/dist/runtime/host/service-relocation-host-runtime.d.ts +6 -8
  140. package/dist/runtime/host/service-relocation-host-runtime.js +215 -243
  141. package/dist/runtime/host/spot-address-transport.d.ts +1 -0
  142. package/dist/runtime/host/spot-address-transport.js +28 -14
  143. package/dist/runtime/host/spot-runtime-options-factory.js +3 -2
  144. package/dist/runtime/host/user-spot-creation-coordinator.d.ts +1 -0
  145. package/dist/runtime/host/user-spot-creation-coordinator.js +1 -0
  146. package/dist/runtime/locations/actor-location-claims.d.ts +2 -2
  147. package/dist/runtime/locations/actor-location-claims.js +34 -19
  148. package/dist/runtime/locations/domain-store-contract.d.ts +2 -2
  149. package/dist/runtime/locations/in-memory-authority-store.d.ts +4 -2
  150. package/dist/runtime/locations/in-memory-authority-store.js +80 -8
  151. package/dist/runtime/locations/in-memory-location-store.d.ts +2 -2
  152. package/dist/runtime/locations/in-memory-location-store.js +19 -3
  153. package/dist/runtime/locations/internal-location-contracts.d.ts +3 -0
  154. package/dist/runtime/locations/lifecycle.d.ts +1 -2
  155. package/dist/runtime/locations/lifecycle.js +2 -5
  156. package/dist/runtime/locations/location-store-repository.d.ts +3 -2
  157. package/dist/runtime/locations/location-store-repository.js +165 -22
  158. package/dist/runtime/locations/resolvers.d.ts +2 -1
  159. package/dist/runtime/locations/resolvers.js +10 -1
  160. package/dist/runtime/locations/runtime.d.ts +1 -1
  161. package/dist/runtime/locations/runtime.js +24 -23
  162. package/dist/runtime/messaging/framework-json-v1.d.ts +4 -6
  163. package/dist/runtime/messaging/framework-json-v1.js +38 -294
  164. package/dist/runtime/messaging/packet-name.d.ts +1 -1
  165. package/dist/runtime/messaging/packet-name.js +8 -24
  166. package/dist/runtime/messaging/request-result.d.ts +2 -0
  167. package/dist/runtime/messaging/request-result.js +54 -0
  168. package/dist/runtime/messaging/submission-result.d.ts +2 -1
  169. package/dist/runtime/messaging/submission-result.js +7 -4
  170. package/dist/runtime/protocol/service_wire_codec.generated.d.ts +15 -0
  171. package/dist/runtime/protocol/service_wire_codec.generated.js +144 -0
  172. package/dist/runtime/protocol/service_wire_pilot_codec.generated.d.ts +9 -0
  173. package/dist/runtime/protocol/service_wire_pilot_codec.generated.js +14 -1
  174. package/dist/runtime/spots/formal-remote-actor-admission-registry.d.ts +9 -2
  175. package/dist/runtime/spots/formal-remote-actor-admission-registry.js +33 -19
  176. package/dist/runtime/spots/index.d.ts +7 -3
  177. package/dist/runtime/spots/index.js +23 -16
  178. package/dist/runtime/spots/spot-activation.d.ts +3 -1
  179. package/dist/runtime/spots/spot-activation.js +21 -12
  180. package/dist/runtime/spots/spot-actor-admission-coordinator.d.ts +2 -1
  181. package/dist/runtime/spots/spot-actor-admission-coordinator.js +11 -10
  182. package/dist/runtime/spots/spot-actor-packet-dispatch.d.ts +4 -1
  183. package/dist/runtime/spots/spot-actor-packet-dispatch.js +7 -5
  184. package/dist/runtime/spots/spot-actor-packet-drain.js +2 -0
  185. package/dist/runtime/spots/spot-actor-packet-relay-dispatch.js +1 -0
  186. package/dist/runtime/spots/spot-entry-activation.js +9 -3
  187. package/dist/runtime/spots/spot-handler-registry.d.ts +3 -1
  188. package/dist/runtime/spots/spot-handler-registry.js +18 -8
  189. package/dist/runtime/spots/spot-node-autoconnect.js +4 -3
  190. package/dist/runtime/spots/spot-node-runtime-manager.d.ts +2 -1
  191. package/dist/runtime/spots/spot-node-runtime-manager.js +4 -11
  192. package/dist/runtime/spots/spot-outbound.d.ts +3 -0
  193. package/dist/runtime/spots/spot-outbound.js +24 -15
  194. package/dist/runtime/spots/spot-routed-spot-packet-dispatch.d.ts +1 -0
  195. package/dist/runtime/spots/spot-routed-spot-packet-dispatch.js +1 -1
  196. package/dist/runtime/spots/spot-routing-internal.d.ts +6 -0
  197. package/dist/runtime/spots/spot-runtime-ports.d.ts +3 -1
  198. package/dist/runtime/spots/spot-subscription-dispatch.js +0 -3
  199. package/dist/runtime/spots/spot-timer.js +1 -0
  200. package/dist/runtime/streams/stream-session-runtime.d.ts +1 -1
  201. package/dist/runtime/streams/stream-session-runtime.js +14 -28
  202. package/package.json +3 -3
  203. package/src/contracts/Actors/ZLinkActorClient.ts +2 -1
  204. package/src/contracts/Channels/Calls.ts +2 -1
  205. package/src/contracts/Common/ZLinkMessageMetadata.ts +13 -8
  206. package/src/contracts/Configuration/Builders.ts +1 -2
  207. package/src/contracts/Configuration/Configs.ts +0 -6
  208. package/src/contracts/Configuration/RegistrationBuilders.ts +8 -12
  209. package/src/contracts/Configuration/RegistrationTypes.ts +1 -6
  210. package/src/contracts/Configuration/RegistrationValidators.ts +9 -10
  211. package/src/contracts/Configuration/index.ts +1 -6
  212. package/src/contracts/Handlers/Attributes.ts +14 -21
  213. package/src/contracts/Handlers/JsonContract.ts +8 -216
  214. package/src/contracts/Spots/Contracts.ts +2 -1
  215. package/src/internal.ts +1 -0
  216. package/src/nest-integration.ts +1 -0
  217. package/src/runtime/actors/actor-client.ts +40 -16
  218. package/src/runtime/actors/actor-handoff.ts +22 -8
  219. package/src/runtime/actors/actor-join-relocation.ts +1 -0
  220. package/src/runtime/actors/actor-local-native-join.ts +17 -26
  221. package/src/runtime/actors/actor-remote-wire.ts +17 -0
  222. package/src/runtime/actors/actor-routed-join-transport.ts +14 -4
  223. package/src/runtime/actors/actor-routed-json-request.ts +10 -2
  224. package/src/runtime/actors/index.ts +19 -5
  225. package/src/runtime/actors/spot-actor-dispatch.ts +4 -2
  226. package/src/runtime/admission.ts +18 -5
  227. package/src/runtime/application-jobs/application-ingress-record-owner.ts +53 -27
  228. package/src/runtime/application-jobs/application-job-queue-scope.ts +56 -22
  229. package/src/runtime/application-jobs/contracts.ts +28 -2
  230. package/src/runtime/backend/contracts/index.ts +63 -32
  231. package/src/runtime/backend/mesh-completion-table.ts +175 -59
  232. package/src/runtime/backend/mesh-dispatch-pump.ts +59 -32
  233. package/src/runtime/backend/node/node-backend-adapter-factory.ts +12 -5
  234. package/src/runtime/backend/node/node-backend-adapter-support.ts +42 -31
  235. package/src/runtime/backend/node/node-dealer-channel-client-transport.ts +12 -2
  236. package/src/runtime/backend/node/node-mesh-backend-adapter.ts +3 -10
  237. package/src/runtime/backend/node/node-raw-binding-port.ts +73 -37
  238. package/src/runtime/backend/node/node-raw-mesh-backend.ts +209 -176
  239. package/src/runtime/backend/node/node-socket-backend-adapter.ts +32 -13
  240. package/src/runtime/backend/raw-binding-port.ts +18 -3
  241. package/src/runtime/backend/runtime-message.ts +6 -0
  242. package/src/runtime/backend/runtime-values.ts +1 -0
  243. package/src/runtime/channels/channel-clients.ts +90 -41
  244. package/src/runtime/channels/channel-dispatch-pipeline.ts +69 -34
  245. package/src/runtime/channels/channel-dispatch-services.ts +69 -1
  246. package/src/runtime/channels/channel-dispatchers.ts +29 -27
  247. package/src/runtime/channels/channel-envelope-inspection.ts +2 -16
  248. package/src/runtime/channels/channel-envelope.ts +133 -8
  249. package/src/runtime/channels/channel-outbound-operations.ts +22 -8
  250. package/src/runtime/channels/channel-receive-loops.ts +3 -3
  251. package/src/runtime/channels/channel-runtime-lifecycle.ts +7 -1
  252. package/src/runtime/channels/channel-runtime-manager.ts +29 -12
  253. package/src/runtime/channels/channel-socket-registry.ts +84 -130
  254. package/src/runtime/channels/channel-transports.ts +128 -60
  255. package/src/runtime/channels/local-spot-route-transport.ts +3 -1
  256. package/src/runtime/channels/router-socket-spot-route-transport.ts +13 -4
  257. package/src/runtime/channels/source-spot-router.ts +8 -4
  258. package/src/runtime/channels/spot-node-route-transport.ts +8 -4
  259. package/src/runtime/channels/spot-route-bridge-transport.ts +6 -4
  260. package/src/runtime/channels/spot-route-dispatch-strategy.ts +47 -18
  261. package/src/runtime/diagnostics/message-flow.ts +1 -1
  262. package/src/runtime/execution/serial-execution-queue.ts +2 -0
  263. package/src/runtime/foundation/actor-join-recovery-codec.ts +2 -2
  264. package/src/runtime/foundation/durable-service-request.ts +137 -0
  265. package/src/runtime/foundation/operation-identity.ts +5 -1
  266. package/src/runtime/foundation/raw-service-mesh-runtime.ts +642 -253
  267. package/src/runtime/foundation/service-liveness-registry.ts +68 -59
  268. package/src/runtime/foundation/service-mailbox.ts +7 -1
  269. package/src/runtime/foundation/service-relocation-object-owner.ts +2 -0
  270. package/src/runtime/foundation/service-relocation-runtime.ts +18 -1
  271. package/src/runtime/foundation/service-runtime-contracts.ts +7 -1
  272. package/src/runtime/foundation/service-stateful-runtime.ts +128 -160
  273. package/src/runtime/foundation/service-stateful-wire-codec.ts +55 -84
  274. package/src/runtime/foundation/service-topology-registry.ts +103 -42
  275. package/src/runtime/foundation/service-wire-m6a-codec.ts +57 -38
  276. package/src/runtime/handlers/handler-instance-scope.ts +67 -16
  277. package/src/runtime/host/actor-packet-relay.ts +7 -0
  278. package/src/runtime/host/actor-runtime-options-factory.ts +14 -2
  279. package/src/runtime/host/application-job-queue.ts +249 -48
  280. package/src/runtime/host/entry-actor-runtime.ts +5 -0
  281. package/src/runtime/host/index.ts +224 -160
  282. package/src/runtime/host/instance-activation-authority.ts +132 -27
  283. package/src/runtime/host/remote-bound-session-relay.ts +2 -23
  284. package/src/runtime/host/route-mesh-runtime.ts +1 -1
  285. package/src/runtime/host/service-relocation-control.ts +11 -5
  286. package/src/runtime/host/service-relocation-host-runtime.ts +317 -291
  287. package/src/runtime/host/spot-address-transport.ts +49 -24
  288. package/src/runtime/host/spot-runtime-options-factory.ts +4 -0
  289. package/src/runtime/host/user-spot-creation-coordinator.ts +8 -0
  290. package/src/runtime/locations/actor-location-claims.ts +52 -30
  291. package/src/runtime/locations/domain-store-contract.ts +6 -2
  292. package/src/runtime/locations/in-memory-authority-store.ts +113 -9
  293. package/src/runtime/locations/in-memory-location-store.ts +25 -3
  294. package/src/runtime/locations/internal-location-contracts.ts +4 -0
  295. package/src/runtime/locations/lifecycle.ts +8 -26
  296. package/src/runtime/locations/location-store-repository.ts +220 -15
  297. package/src/runtime/locations/resolvers.ts +25 -2
  298. package/src/runtime/locations/runtime.ts +28 -24
  299. package/src/runtime/messaging/framework-json-v1.ts +5 -325
  300. package/src/runtime/messaging/packet-name.ts +5 -25
  301. package/src/runtime/messaging/request-result.ts +58 -0
  302. package/src/runtime/messaging/submission-result.ts +7 -3
  303. package/src/runtime/protocol/service_wire_codec.generated.ts +131 -1
  304. package/src/runtime/protocol/service_wire_pilot_codec.generated.ts +4 -4
  305. package/src/runtime/spots/formal-remote-actor-admission-registry.ts +45 -23
  306. package/src/runtime/spots/index.ts +30 -2
  307. package/src/runtime/spots/spot-activation.ts +33 -10
  308. package/src/runtime/spots/spot-actor-admission-coordinator.ts +13 -0
  309. package/src/runtime/spots/spot-actor-packet-dispatch.ts +10 -0
  310. package/src/runtime/spots/spot-actor-packet-drain.ts +2 -0
  311. package/src/runtime/spots/spot-actor-packet-relay-dispatch.ts +1 -0
  312. package/src/runtime/spots/spot-entry-activation.ts +12 -2
  313. package/src/runtime/spots/spot-handler-registry.ts +41 -8
  314. package/src/runtime/spots/spot-node-autoconnect.ts +6 -2
  315. package/src/runtime/spots/spot-node-runtime-manager.ts +7 -12
  316. package/src/runtime/spots/spot-outbound.ts +36 -16
  317. package/src/runtime/spots/spot-routed-spot-packet-dispatch.ts +2 -1
  318. package/src/runtime/spots/spot-routing-internal.ts +14 -0
  319. package/src/runtime/spots/spot-runtime-ports.ts +3 -0
  320. package/src/runtime/spots/spot-subscription-dispatch.ts +0 -3
  321. package/src/runtime/spots/spot-timer.ts +5 -1
  322. package/src/runtime/streams/stream-session-runtime.ts +13 -30
@@ -1,3 +1,4 @@
1
+ import { requestDurableService } from '../../foundation/durable-service-request';
1
2
  import {
2
3
  decodeStreamWireFrame,
3
4
  decodeStreamWireHeader,
@@ -17,8 +18,13 @@ import {
17
18
  type SubmitResult as SubmitResultValue
18
19
  } from '@zlink-systems/zlink';
19
20
  import { randomBytes } from 'node:crypto';
21
+ import type { ZLinkMeshCompletionHandler } from '../mesh-completion-table';
20
22
  import { setImmediate as yieldToIO } from 'node:timers/promises';
21
- import { type RoutingId, ZLinkFrameworkException } from '../../../contracts';
23
+ import {
24
+ type RoutingId,
25
+ ZLinkFrameworkException,
26
+ ZLinkFrameworkErrorKind
27
+ } from '../../../contracts';
22
28
 
23
29
  import type { Message as FrameworkMessage } from '../../../contracts/Common/Message';
24
30
  import { ZLinkConfigurationException } from '../../../contracts/Configuration/ConfigurationException';
@@ -32,7 +38,6 @@ import {
32
38
  ZLINK_MAX_CAPACITY,
33
39
  ZLINK_MAX_PUBLIC_WEIGHT
34
40
  } from '../../../contracts/Configuration/RegistrationBuilderPolicy';
35
- import { shouldCompactBackingArray } from '../../admission';
36
41
  import type { ApplicationJobQueuePort } from '../../application-jobs/contracts';
37
42
  import type { ZLinkDispatchErrorReporter } from '../../channels/dispatch-error-reporter';
38
43
  import { ZLINK_NATIVE_CORRELATION_OPERATION_NAMESPACE } from '../../foundation/operation-identity';
@@ -91,6 +96,7 @@ import type {
91
96
  ServiceActorCreateRecord,
92
97
  ServiceDirectSpotRouteFence,
93
98
  ServiceInstanceActivationTarget,
99
+ ServiceInstanceColdActivationTarget,
94
100
  ServiceInstanceRouteFence,
95
101
  ServiceRetiredBoundSessionRouteFence,
96
102
  ServiceSpotRouteFence,
@@ -170,10 +176,8 @@ export class ZLinkNodeRawMeshBackend implements ZLinkBackendMeshNode {
170
176
  readonly lifecycleGeneration?: bigint;
171
177
  }
172
178
  >();
173
- private readonly completions: Array<PendingCompletion | undefined> = [];
174
- private completionHead = 0;
175
- private completionCount = 0;
176
- private readonly routingId: string;
179
+ private completionHandler?: ZLinkMeshCompletionHandler;
180
+ readonly routingId: string;
177
181
  private readonly lifecycleGeneration: bigint;
178
182
  private bindEndpoint?: string;
179
183
  private advertiseHost?: string;
@@ -231,7 +235,8 @@ export class ZLinkNodeRawMeshBackend implements ZLinkBackendMeshNode {
231
235
  private readonly bindingPort: ZLinkRawBindingPort,
232
236
  private readonly applicationJobQueue?: ApplicationJobQueuePort,
233
237
  private readonly applicationJobReceiveFlowFailureSink?: (error: unknown) => void,
234
- private readonly peerAdmissionSealed?: () => boolean
238
+ private readonly peerAdmissionSealed?: () => boolean,
239
+ private readonly infrastructureTaskRunner?: import('../../spots/spot-actor-join-dispatch').ZLinkDetachedTaskRunner
235
240
  ) {
236
241
  if (meshName.length === 0) throw new TypeError('MeshName must be non-empty.');
237
242
  if (routingId === undefined || routingId.length === 0) {
@@ -321,7 +326,7 @@ export class ZLinkNodeRawMeshBackend implements ZLinkBackendMeshNode {
321
326
  }
322
327
 
323
328
  async sendToMissingInstanceSpot(
324
- target: ServiceInstanceActivationTarget,
329
+ target: ServiceInstanceColdActivationTarget,
325
330
  parts: MessageLike | readonly MessageLike[],
326
331
  deadlineUnixMs: bigint,
327
332
  sourceSpotId?: string,
@@ -338,11 +343,12 @@ export class ZLinkNodeRawMeshBackend implements ZLinkBackendMeshNode {
338
343
  }
339
344
 
340
345
  requestToMissingInstanceSpot(
341
- target: ServiceInstanceActivationTarget,
346
+ target: ServiceInstanceColdActivationTarget,
342
347
  parts: MessageLike | readonly MessageLike[],
343
348
  deadlineUnixMs: bigint,
344
349
  sourceSpotId?: string,
345
- metadata?: ReadonlyMap<string, string>
350
+ metadata?: ReadonlyMap<string, string>,
351
+ onAdmitted?: () => void
346
352
  ): MeshOperationId {
347
353
  return this.observeStateful(
348
354
  OperationKind.InstanceSpotRequest,
@@ -351,7 +357,8 @@ export class ZLinkNodeRawMeshBackend implements ZLinkBackendMeshNode {
351
357
  encodeMultipartApplicationFrame(parts),
352
358
  deadlineUnixMs,
353
359
  sourceSpotId,
354
- metadata === undefined ? undefined : encodeServiceMetadataFrame(metadata)
360
+ metadata === undefined ? undefined : encodeServiceMetadataFrame(metadata),
361
+ onAdmitted
355
362
  )
356
363
  );
357
364
  }
@@ -386,6 +393,8 @@ export class ZLinkNodeRawMeshBackend implements ZLinkBackendMeshNode {
386
393
  resolveAdvertisedEndpoint: (boundEndpoint) => this.resolveAdvertisedEndpoint(boundEndpoint),
387
394
  bindingPort: this.bindingPort,
388
395
  applicationJobQueue: this.requireApplicationJobQueue(),
396
+ onReceiveReady: () => this.onReadable(true, false),
397
+ infrastructureTaskRunner: this.infrastructureTaskRunner,
389
398
  peerAdmissionSealed: this.peerAdmissionSealed,
390
399
  onReceiveFlowConfigFailure: this.applicationJobReceiveFlowFailureSink,
391
400
  onMailboxReady: (domain) =>
@@ -409,15 +418,7 @@ export class ZLinkNodeRawMeshBackend implements ZLinkBackendMeshNode {
409
418
  }
410
419
  }
411
420
  },
412
- onPeerDisconnected: (nodeRoutingId, endpoint) => {
413
- for (const [intentId, peer] of this.peerIntents) {
414
- if (
415
- peer.endpoint === endpoint &&
416
- (peer.nodeRoutingId === undefined || peer.nodeRoutingId === nodeRoutingId)
417
- ) {
418
- this.peerIntents.delete(intentId);
419
- }
420
- }
421
+ onPeerDisconnected: (_nodeRoutingId, endpoint) => {
421
422
  for (const handler of this.peerDisconnectedHandlers) handler(endpoint);
422
423
  }
423
424
  });
@@ -481,7 +482,6 @@ export class ZLinkNodeRawMeshBackend implements ZLinkBackendMeshNode {
481
482
  this.stateful = undefined;
482
483
  this.runtime?.close();
483
484
  this.runtime = undefined;
484
- this.clearCompletions();
485
485
  this.closed = true;
486
486
  }
487
487
 
@@ -629,20 +629,38 @@ export class ZLinkNodeRawMeshBackend implements ZLinkBackendMeshNode {
629
629
  return this.requireRuntime().isObjectClientNodeDirectTarget(String(targetRid));
630
630
  }
631
631
 
632
+ observePeerRoute(targetRid: unknown) {
633
+ return this.requireRuntime().observePeerRoute(String(targetRid));
634
+ }
635
+
636
+ hasPeerRouteOrConnectionIntent(targetRid: unknown, endpoint: string): boolean {
637
+ const rid = String(targetRid);
638
+ if (this.requireRuntime().hasSelectedPeerRoute(rid)) return true;
639
+ for (const intent of this.peerIntents.values()) {
640
+ if (
641
+ intent.nodeRoutingId === rid ||
642
+ (intent.nodeRoutingId === undefined && intent.endpoint === endpoint)
643
+ )
644
+ return true;
645
+ }
646
+ return false;
647
+ }
648
+
632
649
  isPeerRouteReady(targetRid: unknown, lifecycleGeneration?: bigint): boolean {
633
650
  return this.requireRuntime().isPeerRouteReady(String(targetRid), lifecycleGeneration);
634
651
  }
635
652
 
636
- async sendToNode(
653
+ sendToNode(
637
654
  targetRid: unknown,
638
655
  parts: MessageLike | readonly MessageLike[]
639
- ): Promise<SubmitResultValue> {
640
- return (await this.requireRuntime().sendToNode(
656
+ ): SubmitResultValue | Promise<SubmitResultValue> {
657
+ const submitted = this.requireRuntime().sendToNode(
641
658
  String(targetRid),
642
659
  encodeMultipartApplicationFrame(parts)
643
- ))
644
- ? SubmitResult.Ok
645
- : SubmitResult.NotConnected;
660
+ );
661
+ return submitted instanceof Promise
662
+ ? submitted.then(nodeSendResult)
663
+ : nodeSendResult(submitted);
646
664
  }
647
665
 
648
666
  async sendInfrastructureControl(
@@ -672,24 +690,33 @@ export class ZLinkNodeRawMeshBackend implements ZLinkBackendMeshNode {
672
690
  async requestInfrastructureControlFrames(
673
691
  targetRid: unknown,
674
692
  frames: readonly Uint8Array[],
675
- options?: { readonly timeoutMs?: number }
693
+ options?: {
694
+ readonly timeoutMs?: number;
695
+ readonly signal?: AbortSignal;
696
+ readonly onSubmitted?: (signal: AbortSignal) => Promise<void>;
697
+ }
676
698
  ): Promise<readonly Uint8Array[]> {
677
- return await this.requireRuntime().requestService(
699
+ return requestDurableService(
700
+ this.requireRuntime(),
678
701
  String(targetRid),
679
- frames.map((frame) => Buffer.from(frame)),
680
- options?.timeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS
702
+ frames,
703
+ performance.now() + (options?.timeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS),
704
+ 'relocation control',
705
+ options?.signal,
706
+ options?.onSubmitted
681
707
  );
682
708
  }
683
709
 
684
710
  requestToNode(
685
711
  targetRid: unknown,
686
712
  parts: MessageLike | readonly MessageLike[],
687
- options?: { readonly timeoutMs?: number }
713
+ options?: { readonly timeoutMs?: number; readonly onAdmitted?: () => void }
688
714
  ): MeshOperationId {
689
715
  const pending = this.requireRuntime().requestToNode(
690
716
  String(targetRid),
691
717
  encodeMultipartApplicationFrame(parts),
692
- options?.timeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS
718
+ options?.timeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS,
719
+ options?.onAdmitted
693
720
  );
694
721
  return this.observeCompletion(pending.id, OperationKind.NodeRequest, pending.promise);
695
722
  }
@@ -704,12 +731,13 @@ export class ZLinkNodeRawMeshBackend implements ZLinkBackendMeshNode {
704
731
  requestToChannel(
705
732
  channelName: string,
706
733
  parts: MessageLike | readonly MessageLike[],
707
- options?: { readonly timeoutMs?: number }
734
+ options?: { readonly timeoutMs?: number; readonly onAdmitted?: () => void }
708
735
  ): MeshOperationId {
709
736
  const pending = this.requireRuntime().requestToChannel(
710
737
  channelName,
711
738
  encodeMultipartApplicationFrame(parts),
712
- options?.timeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS
739
+ options?.timeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS,
740
+ options?.onAdmitted
713
741
  );
714
742
  return this.observeCompletion(pending.id, OperationKind.ChannelRequest, pending.promise);
715
743
  }
@@ -730,7 +758,7 @@ export class ZLinkNodeRawMeshBackend implements ZLinkBackendMeshNode {
730
758
  drainingPeerCount: peers.filter((peer) => peer.descriptor.state === 'draining').length,
731
759
  pendingApplicationMessages: BigInt(this.runtime?.mailbox.pendingMessages('application') ?? 0),
732
760
  pendingInfrastructureMessages: BigInt(
733
- (this.runtime?.mailbox.pendingMessages('infrastructure') ?? 0) + this.completionCount
761
+ this.runtime?.mailbox.pendingMessages('infrastructure') ?? 0
734
762
  ),
735
763
  pendingBytes: BigInt(
736
764
  (this.runtime?.mailbox.pendingBytes('application') ?? 0) +
@@ -846,6 +874,10 @@ export class ZLinkNodeRawMeshBackend implements ZLinkBackendMeshNode {
846
874
  };
847
875
  }
848
876
 
877
+ setCompletionHandler(handler: ZLinkMeshCompletionHandler): void {
878
+ this.completionHandler = handler;
879
+ }
880
+
849
881
  setReadyHandler(handler: (readyDomains: number) => number): void {
850
882
  this.readyHandler = handler;
851
883
  this.notifyReady();
@@ -869,7 +901,6 @@ export class ZLinkNodeRawMeshBackend implements ZLinkBackendMeshNode {
869
901
  } {
870
902
  const target = requireRawReadyBatch(batch);
871
903
  if ((domains & ReadyDomain.Infrastructure) !== 0) {
872
- this.drainCompletions(target);
873
904
  this.drainMailbox('infrastructure', target);
874
905
  }
875
906
  if ((domains & ReadyDomain.Application) !== 0) {
@@ -878,7 +909,7 @@ export class ZLinkNodeRawMeshBackend implements ZLinkBackendMeshNode {
878
909
  const runtime = this.runtime;
879
910
  const infrastructureResidue =
880
911
  (domains & ReadyDomain.Infrastructure) !== 0 &&
881
- (this.completionCount > 0 || (runtime?.mailbox.pendingMessages('infrastructure') ?? 0) > 0);
912
+ (runtime?.mailbox.pendingMessages('infrastructure') ?? 0) > 0;
882
913
  const applicationResidue =
883
914
  (domains & ReadyDomain.Application) !== 0 &&
884
915
  (runtime?.mailbox.pendingMessages('application') ?? 0) > 0;
@@ -1169,7 +1200,8 @@ export class ZLinkNodeRawMeshBackend implements ZLinkBackendMeshNode {
1169
1200
  timeoutMs: number = DEFAULT_REQUEST_TIMEOUT_MS,
1170
1201
  sourceSpotId?: string,
1171
1202
  metadata?: ReadonlyMap<string, string>,
1172
- instanceIntent = false
1203
+ instanceIntent = false,
1204
+ onAdmitted?: () => void
1173
1205
  ): MeshOperationId {
1174
1206
  return this.observeStateful(
1175
1207
  OperationKind.InstanceSpotRequest,
@@ -1179,7 +1211,8 @@ export class ZLinkNodeRawMeshBackend implements ZLinkBackendMeshNode {
1179
1211
  timeoutMs,
1180
1212
  sourceSpotId,
1181
1213
  metadata === undefined ? undefined : encodeServiceMetadataFrame(metadata),
1182
- instanceIntent
1214
+ instanceIntent,
1215
+ onAdmitted
1183
1216
  )
1184
1217
  );
1185
1218
  }
@@ -1324,7 +1357,7 @@ export class ZLinkNodeRawMeshBackend implements ZLinkBackendMeshNode {
1324
1357
  requestToActor(
1325
1358
  actor: ZLinkBackendActorRef,
1326
1359
  parts: MessageLike | readonly MessageLike[],
1327
- options?: { readonly timeoutMs?: number }
1360
+ options?: { readonly timeoutMs?: number; readonly onAdmitted?: () => void }
1328
1361
  ): MeshOperationId {
1329
1362
  return this.observeStateful(
1330
1363
  OperationKind.ActorRequest,
@@ -1333,7 +1366,10 @@ export class ZLinkNodeRawMeshBackend implements ZLinkBackendMeshNode {
1333
1366
  this.peerGeneration(String(actor.nodeRid)),
1334
1367
  actor.generation,
1335
1368
  encodeMultipart(parts),
1336
- options?.timeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS
1369
+ options?.timeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS,
1370
+ undefined,
1371
+ undefined,
1372
+ options?.onAdmitted
1337
1373
  )
1338
1374
  );
1339
1375
  }
@@ -1356,7 +1392,7 @@ export class ZLinkNodeRawMeshBackend implements ZLinkBackendMeshNode {
1356
1392
  source: ZLinkBackendActorRef,
1357
1393
  target: ZLinkBackendActorRef,
1358
1394
  parts: MessageLike | readonly MessageLike[],
1359
- options?: { readonly timeoutMs?: number }
1395
+ options?: { readonly timeoutMs?: number; readonly onAdmitted?: () => void }
1360
1396
  ): MeshOperationId {
1361
1397
  return this.observeStateful(
1362
1398
  OperationKind.ActorRequest,
@@ -1366,7 +1402,9 @@ export class ZLinkNodeRawMeshBackend implements ZLinkBackendMeshNode {
1366
1402
  target.generation,
1367
1403
  encodeMultipart(parts),
1368
1404
  options?.timeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS,
1369
- source
1405
+ source,
1406
+ undefined,
1407
+ options?.onAdmitted
1370
1408
  )
1371
1409
  );
1372
1410
  }
@@ -1391,7 +1429,7 @@ export class ZLinkNodeRawMeshBackend implements ZLinkBackendMeshNode {
1391
1429
  ): MeshOperationId {
1392
1430
  const binding = this.requireStateful().registry.binding(actor);
1393
1431
  if (binding === undefined) {
1394
- return this.enqueueImmediateFailure(OperationKind.StreamUnbind, RequestResult.NotFound);
1432
+ return this.observeImmediateFailure(OperationKind.StreamUnbind, RequestResult.NotFound);
1395
1433
  }
1396
1434
  return this.observeStateful(
1397
1435
  OperationKind.StreamUnbind,
@@ -1439,7 +1477,8 @@ export class ZLinkNodeRawMeshBackend implements ZLinkBackendMeshNode {
1439
1477
  source: ServiceSpotState,
1440
1478
  target: ServiceDirectSpotRouteFence,
1441
1479
  parts: MessageLike | readonly MessageLike[],
1442
- timeoutMs: number
1480
+ timeoutMs: number,
1481
+ onAdmitted?: () => void
1443
1482
  ): MeshOperationId {
1444
1483
  return this.observeStateful(
1445
1484
  OperationKind.SpotRequest,
@@ -1447,7 +1486,8 @@ export class ZLinkNodeRawMeshBackend implements ZLinkBackendMeshNode {
1447
1486
  source.ref.spotId,
1448
1487
  target,
1449
1488
  encodeMultipart(parts),
1450
- timeoutMs
1489
+ timeoutMs,
1490
+ onAdmitted
1451
1491
  )
1452
1492
  );
1453
1493
  }
@@ -1471,6 +1511,11 @@ export class ZLinkNodeRawMeshBackend implements ZLinkBackendMeshNode {
1471
1511
  }
1472
1512
 
1473
1513
  setSpotSubscription(state: ServiceSpotState, channelName: string, topicFilter: string): void {
1514
+ if (!this.channels.has(channelName))
1515
+ throw new ZLinkFrameworkException(
1516
+ ZLinkFrameworkErrorKind.InvalidOperation,
1517
+ `Spot does not participate in subscription channel '${channelName}'.`
1518
+ );
1474
1519
  this.requireStateful().setSubscription(state, channelName, topicFilter);
1475
1520
  }
1476
1521
 
@@ -1559,7 +1604,7 @@ export class ZLinkNodeRawMeshBackend implements ZLinkBackendMeshNode {
1559
1604
  private notifyReady(): void {
1560
1605
  const runtime = this.runtime;
1561
1606
  let domains = ReadyDomain.None;
1562
- if (this.completionCount > 0 || (runtime?.mailbox.pendingMessages('infrastructure') ?? 0) > 0) {
1607
+ if ((runtime?.mailbox.pendingMessages('infrastructure') ?? 0) > 0) {
1563
1608
  domains |= ReadyDomain.Infrastructure;
1564
1609
  }
1565
1610
  if ((runtime?.mailbox.pendingMessages('application') ?? 0) > 0) {
@@ -1575,8 +1620,8 @@ export class ZLinkNodeRawMeshBackend implements ZLinkBackendMeshNode {
1575
1620
  ): MeshOperationId {
1576
1621
  const id = { high: 1n, low };
1577
1622
  void promise.then(
1578
- (result) => this.enqueueCompletion(id, operationKind, result),
1579
- (error) => this.enqueueCompletion(id, operationKind, requestFailureResult(error))
1623
+ (result) => this.deliverCompletion(id, operationKind, result),
1624
+ (error) => this.deliverCompletion(id, operationKind, requestFailureResult(error))
1580
1625
  );
1581
1626
  return id;
1582
1627
  }
@@ -1587,66 +1632,40 @@ export class ZLinkNodeRawMeshBackend implements ZLinkBackendMeshNode {
1587
1632
  ): MeshOperationId {
1588
1633
  const id = { high: ZLINK_NATIVE_CORRELATION_OPERATION_NAMESPACE, low: pending.id };
1589
1634
  void pending.promise.then(
1590
- (result) => this.enqueueCompletion(id, operationKind, result),
1591
- (error) => this.enqueueCompletion(id, operationKind, requestFailureResult(error))
1635
+ (result) => this.deliverCompletion(id, operationKind, result),
1636
+ (error) => this.deliverCompletion(id, operationKind, requestFailureResult(error))
1592
1637
  );
1593
1638
  return id;
1594
1639
  }
1595
1640
 
1596
- private enqueueImmediateFailure(operationKind: number, terminalResult: number): MeshOperationId {
1641
+ private observeImmediateFailure(operationKind: number, terminalResult: number): MeshOperationId {
1597
1642
  const low = this.nextPeerIntent++;
1598
- const id = { high: 1n, low };
1599
- this.enqueueCompletion(id, operationKind, { terminalResult, failureCode: 0 });
1600
- return id;
1643
+ return this.observeCompletion(
1644
+ low,
1645
+ operationKind,
1646
+ Promise.resolve({ terminalResult, failureCode: 0 })
1647
+ );
1601
1648
  }
1602
1649
 
1603
- private enqueueCompletion(
1650
+ private deliverCompletion(
1604
1651
  operationId: MeshOperationId,
1605
1652
  operationKind: number,
1606
1653
  result: RawServiceRequestResult | ServiceStatefulResult
1607
1654
  ): void {
1608
- if (this.closed) return;
1609
- this.completions.push({ operationId, operationKind, result });
1610
- this.completionCount += 1;
1611
- this.readyHandler?.(ReadyDomain.Infrastructure);
1612
- }
1613
-
1614
- private drainCompletions(batch: RawReadyBatch): void {
1615
- while (!batch.full && this.completionCount > 0) {
1616
- const completion = this.takeCompletion();
1617
- if (completion === undefined) continue;
1618
- batch.push(
1619
- {
1620
- ownerKind: ReadyOwnerKind.Node,
1621
- domain: ReadyDomain.Infrastructure,
1622
- spotId: null,
1623
- actor: null,
1624
- terminalCompletion: true
1625
- },
1626
- new CompletionClaim(completion)
1655
+ if (this.completionHandler !== undefined) {
1656
+ this.completionHandler({ operationId, terminalResult: result.terminalResult }, () =>
1657
+ completionRecord(operationId, operationKind, result)
1627
1658
  );
1659
+ return;
1628
1660
  }
1629
- }
1630
-
1631
- private takeCompletion(): PendingCompletion | undefined {
1632
- const completion = this.completions[this.completionHead];
1633
- if (completion === undefined) return undefined;
1634
- this.completions[this.completionHead] = undefined;
1635
- this.completionHead += 1;
1636
- this.completionCount -= 1;
1637
- if (this.completionCount === 0) {
1638
- this.clearCompletions();
1639
- } else if (shouldCompactBackingArray(this.completionHead, this.completions.length)) {
1640
- this.completions.splice(0, this.completionHead);
1641
- this.completionHead = 0;
1642
- }
1643
- return completion;
1644
- }
1645
-
1646
- private clearCompletions(): void {
1647
- this.completions.length = 0;
1648
- this.completionHead = 0;
1649
- this.completionCount = 0;
1661
+ // The raw pull contract uses the existing infrastructure mailbox. A
1662
+ // registered Framework owner receives the terminal directly above.
1663
+ this.runtime?.mailbox.tryEnqueue({
1664
+ owner: this.routingId,
1665
+ domain: 'infrastructure',
1666
+ parts: [],
1667
+ completion: completionRecord(operationId, operationKind, result)
1668
+ });
1650
1669
  }
1651
1670
 
1652
1671
  private drainMailbox(domain: ServiceMailboxDomain, batch: RawReadyBatch): void {
@@ -1655,7 +1674,16 @@ export class ZLinkNodeRawMeshBackend implements ZLinkBackendMeshNode {
1655
1674
  while (!batch.full) {
1656
1675
  const claim = runtime.mailbox.tryClaim(domain, MAX_DRAIN_RECORDS, Number.MAX_SAFE_INTEGER);
1657
1676
  if (claim === undefined) break;
1658
- const owner = readyOwner(claim.owner, this.routingId, this.stateful, domain);
1677
+ const owner =
1678
+ claim.records[0]?.completion === undefined
1679
+ ? readyOwner(claim.owner, this.routingId, this.stateful, domain)
1680
+ : {
1681
+ ownerKind: ReadyOwnerKind.Node,
1682
+ domain: ReadyDomain.Infrastructure,
1683
+ spotId: null,
1684
+ actor: null,
1685
+ terminalCompletion: true
1686
+ };
1659
1687
  batch.push(owner, new MailboxClaim(runtime, claim));
1660
1688
  }
1661
1689
  }
@@ -1690,12 +1718,6 @@ export class ZLinkNodeRawMeshBackend implements ZLinkBackendMeshNode {
1690
1718
  }
1691
1719
  }
1692
1720
 
1693
- interface PendingCompletion {
1694
- readonly operationId: MeshOperationId;
1695
- readonly operationKind: number;
1696
- readonly result: RawServiceRequestResult | ServiceStatefulResult;
1697
- }
1698
-
1699
1721
  interface RawClaim {
1700
1722
  recvBatch(batch: ReceiveBatch): {
1701
1723
  readonly ok: boolean;
@@ -1738,7 +1760,11 @@ class RawServiceSpot implements ServiceSpot {
1738
1760
  requestToChannel(
1739
1761
  channelName: string,
1740
1762
  parts: MessageLike | readonly MessageLike[],
1741
- options?: { readonly flags?: number; readonly timeoutMs?: number }
1763
+ options?: {
1764
+ readonly flags?: number;
1765
+ readonly timeoutMs?: number;
1766
+ readonly onAdmitted?: () => void;
1767
+ }
1742
1768
  ): MeshOperationId {
1743
1769
  this.requireOpen();
1744
1770
  return this.backend.requestToChannel(channelName, parts, options);
@@ -1774,6 +1800,7 @@ class RawServiceSpot implements ServiceSpot {
1774
1800
  parts: MessageLike | readonly MessageLike[],
1775
1801
  options?: {
1776
1802
  readonly timeoutMs?: number;
1803
+ readonly onAdmitted?: () => void;
1777
1804
  readonly routeFence?: ServiceDirectSpotRouteFence;
1778
1805
  readonly entrySpot?: boolean;
1779
1806
  }
@@ -1792,7 +1819,8 @@ class RawServiceSpot implements ServiceSpot {
1792
1819
  this.state,
1793
1820
  routeFence,
1794
1821
  parts,
1795
- options?.timeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS
1822
+ options?.timeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS,
1823
+ options?.onAdmitted
1796
1824
  );
1797
1825
  }
1798
1826
 
@@ -1842,6 +1870,10 @@ class RawServiceSpot implements ServiceSpot {
1842
1870
  }
1843
1871
  }
1844
1872
 
1873
+ function nodeSendResult(submitted: boolean): SubmitResultValue {
1874
+ return submitted ? SubmitResult.Ok : SubmitResult.NotConnected;
1875
+ }
1876
+
1845
1877
  function requireDirectSpotRouteFence(
1846
1878
  route: ServiceDirectSpotRouteFence | undefined,
1847
1879
  targetNodeRid: string,
@@ -1989,7 +2021,10 @@ class RawStreamSessionService implements StreamSessionService {
1989
2021
  const target = this.sessionTargets.get(sessionRid);
1990
2022
  if (target === undefined) return false;
1991
2023
  const operation = this.stream.send(target as unknown as BindingRoutingId);
1992
- const parts = decodeMultipartBuffers(decodeApplicationPayloadView(payload).payload);
2024
+ const parts = decodeMultipartParts(
2025
+ decodeApplicationPayloadView(payload).payload,
2026
+ borrowMultipartPart
2027
+ );
1993
2028
  if (parts.length === 0) return false;
1994
2029
  const actorSlot = await serviceSessionBindingIngressPortIfRegistered(this)?.actorSlot(
1995
2030
  actorId,
@@ -2166,54 +2201,43 @@ class MailboxClaim implements RawClaim {
2166
2201
  }
2167
2202
  }
2168
2203
 
2169
- class CompletionClaim implements RawClaim {
2170
- private consumed = false;
2171
-
2172
- constructor(private readonly completion: PendingCompletion) {}
2173
-
2174
- recvBatch(): { readonly ok: boolean; readonly records: ReceiveRecord[] } {
2175
- if (this.consumed) return { ok: false, records: [] };
2176
- this.consumed = true;
2177
- const payload = this.completion.result.payload;
2178
- return {
2179
- ok: true,
2180
- records: [
2181
- {
2182
- kind: ReceiveKind.Completion,
2183
- domain: ReadyDomain.Infrastructure,
2184
- sourceNodeRid: null,
2185
- sourceSpotId: null,
2186
- sourceBindingGeneration: 0n,
2187
- sourceActor: null,
2188
- operationId: this.completion.operationId,
2189
- operationKind: this.completion.operationKind,
2190
- channelName: null,
2191
- topic: null,
2192
- applicationMetadata: null,
2193
- kindData:
2194
- 'kindData' in this.completion.result ? (this.completion.result.kindData ?? null) : null,
2195
- terminalResult: this.completion.result.terminalResult,
2196
- failureErrno: this.completion.result.failureCode,
2197
- parts:
2198
- payload === undefined
2199
- ? []
2200
- : payload.contentType === MULTIPART_CONTENT_TYPE
2201
- ? decodeMultipart(payload.payload)
2202
- : [Message.from(payload.payload)],
2203
- reply: () => SubmitResult.InvalidState,
2204
- replyActorJoin: () => SubmitResult.NotSupported
2205
- }
2206
- ]
2207
- };
2208
- }
2209
-
2210
- release(): void {}
2204
+ function completionRecord(
2205
+ operationId: MeshOperationId,
2206
+ operationKind: number,
2207
+ result: RawServiceRequestResult | ServiceStatefulResult
2208
+ ): ReceiveRecord {
2209
+ const payload = result.payload;
2210
+ return {
2211
+ kind: ReceiveKind.Completion,
2212
+ domain: ReadyDomain.Infrastructure,
2213
+ sourceNodeRid: null,
2214
+ sourceSpotId: null,
2215
+ sourceBindingGeneration: 0n,
2216
+ sourceActor: null,
2217
+ operationId,
2218
+ operationKind,
2219
+ channelName: null,
2220
+ topic: null,
2221
+ applicationMetadata: null,
2222
+ kindData: 'kindData' in result ? (result.kindData ?? null) : null,
2223
+ terminalResult: result.terminalResult,
2224
+ failureErrno: result.failureCode,
2225
+ parts:
2226
+ payload === undefined
2227
+ ? []
2228
+ : payload.contentType === MULTIPART_CONTENT_TYPE
2229
+ ? decodeMultipart(payload.payload)
2230
+ : [ZLinkBufferMessage.from(payload.payload)],
2231
+ reply: () => SubmitResult.InvalidState,
2232
+ replyActorJoin: () => SubmitResult.NotSupported
2233
+ };
2211
2234
  }
2212
2235
 
2213
2236
  function decodeMultipartRecord(
2214
2237
  runtime: RawServiceMeshRuntime,
2215
2238
  record: ServiceMailboxRecord
2216
2239
  ): ReceiveRecord {
2240
+ if (record.completion !== undefined) return record.completion;
2217
2241
  const stateful = statefulMailboxData(record);
2218
2242
  if (stateful !== undefined) {
2219
2243
  return decodeStatefulRecord(record, stateful);
@@ -2614,45 +2638,54 @@ function decodeApplicationEnvelope(frame: Uint8Array) {
2614
2638
  }
2615
2639
 
2616
2640
  function decodeMultipart(payload: Uint8Array): FrameworkMessage[] {
2617
- const buffers = decodeMultipartBuffers(payload);
2618
- const parts = new Array<FrameworkMessage>(buffers.length);
2619
- let materialized = 0;
2620
- try {
2621
- for (; materialized < buffers.length; materialized += 1) {
2622
- parts[materialized] = ZLinkBufferMessage.fromOwned(buffers[materialized]!);
2623
- }
2624
- return parts;
2625
- } catch (error) {
2626
- for (let index = 0; index < materialized; index += 1) parts[index]!.close();
2627
- throw error;
2628
- }
2641
+ return decodeMultipartParts(payload, ZLinkBufferMessage.fromOwned, closeMultipartMessage);
2642
+ }
2643
+
2644
+ function closeMultipartMessage(part: FrameworkMessage): void {
2645
+ part.close();
2629
2646
  }
2630
2647
 
2631
- function decodeMultipartBuffers(payload: Uint8Array): Buffer[] {
2648
+ function borrowMultipartPart(part: Buffer): Buffer {
2649
+ return part;
2650
+ }
2651
+
2652
+ function decodeMultipartParts<T>(
2653
+ payload: Uint8Array,
2654
+ materialize: (part: Buffer) => T,
2655
+ release?: (part: T) => void
2656
+ ): T[] {
2632
2657
  const bytes = Buffer.from(payload.buffer, payload.byteOffset, payload.byteLength);
2633
2658
  if (bytes.length < 4) throw new ServiceWireProtocolError('Truncated multipart payload.');
2634
2659
  const count = bytes.readUInt32BE(0);
2635
2660
  if (count === 0 || count > Math.floor((bytes.length - 4) / 4)) {
2636
2661
  throw new ServiceWireProtocolError('Invalid multipart part count.');
2637
2662
  }
2638
- const result = new Array<Buffer>(count);
2663
+ const result = new Array<T>(count);
2639
2664
  let offset = 4;
2640
- for (let index = 0; index < count; index++) {
2641
- if (bytes.length - offset < 4) {
2642
- throw new ServiceWireProtocolError('Truncated multipart part length.');
2665
+ let index = 0;
2666
+ try {
2667
+ for (; index < count; index++) {
2668
+ if (bytes.length - offset < 4) {
2669
+ throw new ServiceWireProtocolError('Truncated multipart part length.');
2670
+ }
2671
+ const length = bytes.readUInt32BE(offset);
2672
+ offset += 4;
2673
+ if (bytes.length - offset < length) {
2674
+ throw new ServiceWireProtocolError('Truncated multipart part.');
2675
+ }
2676
+ result[index] = materialize(bytes.subarray(offset, offset + length));
2677
+ offset += length;
2643
2678
  }
2644
- const length = bytes.readUInt32BE(offset);
2645
- offset += 4;
2646
- if (bytes.length - offset < length) {
2647
- throw new ServiceWireProtocolError('Truncated multipart part.');
2679
+ if (offset !== bytes.length) {
2680
+ throw new ServiceWireProtocolError('Multipart payload has trailing bytes.');
2648
2681
  }
2649
- result[index] = bytes.subarray(offset, offset + length);
2650
- offset += length;
2651
- }
2652
- if (offset !== bytes.length) {
2653
- throw new ServiceWireProtocolError('Multipart payload has trailing bytes.');
2682
+ return result;
2683
+ } catch (error) {
2684
+ if (release !== undefined) {
2685
+ for (let retained = 0; retained < index; retained++) release(result[retained]!);
2686
+ }
2687
+ throw error;
2654
2688
  }
2655
- return result;
2656
2689
  }
2657
2690
 
2658
2691
  function messageBytesView(value: MessageLike): Uint8Array {