@zlink-systems/framework 0.30.3 → 0.32.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 (398) hide show
  1. package/dist/.tsbuildinfo +1 -1
  2. package/dist/contracts/Actors/ZLinkActor.d.ts +2 -0
  3. package/dist/contracts/Actors/ZLinkSessionBindingIdentity.d.ts +6 -0
  4. package/dist/contracts/Actors/ZLinkSessionBindingIdentity.js +2 -0
  5. package/dist/contracts/Actors/index.d.ts +1 -0
  6. package/dist/contracts/Actors/index.js +1 -0
  7. package/dist/contracts/Common/CoreTypes.d.ts +1 -0
  8. package/dist/contracts/Common/HandlerMessageType.d.ts +8 -0
  9. package/dist/contracts/Common/HandlerMessageType.js +41 -0
  10. package/dist/contracts/Common/ZLinkEncodedPayload.d.ts +1 -1
  11. package/dist/contracts/Common/ZLinkEncodedPayload.js +12 -20
  12. package/dist/contracts/Common/ZLinkMessage.js +11 -7
  13. package/dist/contracts/Common/encoded-payload-storage.d.ts +0 -2
  14. package/dist/contracts/Common/encoded-payload-storage.js +4 -16
  15. package/dist/contracts/Common/index.d.ts +1 -1
  16. package/dist/contracts/Common/payload-slab.d.ts +4 -0
  17. package/dist/contracts/Common/payload-slab.js +30 -0
  18. package/dist/contracts/Configuration/RegistrationBuilders.js +15 -9
  19. package/dist/contracts/Configuration/RegistrationTypes.d.ts +19 -0
  20. package/dist/contracts/Handlers/Contexts.d.ts +1 -0
  21. package/dist/contracts/Locations/Authority.d.ts +2 -0
  22. package/dist/internal.d.ts +9 -0
  23. package/dist/internal.js +23 -1
  24. package/dist/nest-integration.d.ts +1 -0
  25. package/dist/nest-integration.js +3 -1
  26. package/dist/runtime/actors/actor-client.d.ts +6 -2
  27. package/dist/runtime/actors/actor-client.js +120 -82
  28. package/dist/runtime/actors/actor-context.js +16 -5
  29. package/dist/runtime/actors/actor-execution-context.js +2 -2
  30. package/dist/runtime/actors/actor-handoff.d.ts +12 -1
  31. package/dist/runtime/actors/actor-handoff.js +79 -34
  32. package/dist/runtime/actors/actor-join-deferred-scope.js +6 -6
  33. package/dist/runtime/actors/actor-local-native-join.d.ts +2 -2
  34. package/dist/runtime/actors/actor-local-native-join.js +19 -17
  35. package/dist/runtime/actors/actor-mailbox.d.ts +1 -1
  36. package/dist/runtime/actors/actor-remote-joiner.d.ts +2 -2
  37. package/dist/runtime/actors/actor-remote-joiner.js +4 -4
  38. package/dist/runtime/actors/actor-routed-join-transport.d.ts +9 -3
  39. package/dist/runtime/actors/actor-routed-json-request.d.ts +3 -0
  40. package/dist/runtime/actors/actor-runtime-contracts.d.ts +2 -2
  41. package/dist/runtime/actors/actor-runtime-state.d.ts +1 -1
  42. package/dist/runtime/actors/spot-actor-dispatch.d.ts +9 -5
  43. package/dist/runtime/actors/spot-actor-dispatch.js +60 -38
  44. package/dist/runtime/admission.d.ts +6 -4
  45. package/dist/runtime/admission.js +21 -10
  46. package/dist/runtime/application-jobs/application-ingress-record-owner.d.ts +1 -0
  47. package/dist/runtime/application-jobs/application-ingress-record-owner.js +3 -0
  48. package/dist/runtime/backend/contracts/index.d.ts +26 -10
  49. package/dist/runtime/backend/mesh-completion-table.d.ts +7 -1
  50. package/dist/runtime/backend/mesh-completion-table.js +84 -20
  51. package/dist/runtime/backend/mesh-dispatch-pump.d.ts +19 -6
  52. package/dist/runtime/backend/mesh-dispatch-pump.js +246 -147
  53. package/dist/runtime/backend/node/node-backend-adapter-support.d.ts +3 -2
  54. package/dist/runtime/backend/node/node-backend-adapter-support.js +27 -19
  55. package/dist/runtime/backend/node/node-dealer-channel-client-transport.d.ts +5 -2
  56. package/dist/runtime/backend/node/node-dealer-channel-client-transport.js +70 -13
  57. package/dist/runtime/backend/node/node-event-loop-poller.d.ts +2 -2
  58. package/dist/runtime/backend/node/node-event-loop-poller.js +4 -3
  59. package/dist/runtime/backend/node/node-mesh-backend-adapter.js +5 -1
  60. package/dist/runtime/backend/node/node-raw-binding-port.d.ts +7 -2
  61. package/dist/runtime/backend/node/node-raw-binding-port.js +99 -63
  62. package/dist/runtime/backend/node/node-raw-mesh-backend.d.ts +34 -16
  63. package/dist/runtime/backend/node/node-raw-mesh-backend.js +210 -106
  64. package/dist/runtime/backend/node/node-socket-backend-adapter.js +20 -6
  65. package/dist/runtime/backend/raw-binding-port.d.ts +6 -3
  66. package/dist/runtime/channels/channel-clients.js +3 -3
  67. package/dist/runtime/channels/channel-dispatch-pipeline.d.ts +11 -7
  68. package/dist/runtime/channels/channel-dispatch-pipeline.js +40 -22
  69. package/dist/runtime/channels/channel-dispatch-services.d.ts +3 -1
  70. package/dist/runtime/channels/channel-dispatch-services.js +7 -6
  71. package/dist/runtime/channels/channel-dispatchers.d.ts +13 -6
  72. package/dist/runtime/channels/channel-dispatchers.js +57 -36
  73. package/dist/runtime/channels/channel-envelope.d.ts +2 -2
  74. package/dist/runtime/channels/channel-envelope.js +609 -83
  75. package/dist/runtime/channels/channel-multipart.d.ts +1 -0
  76. package/dist/runtime/channels/channel-multipart.js +10 -6
  77. package/dist/runtime/channels/channel-outbound-operations.d.ts +6 -9
  78. package/dist/runtime/channels/channel-outbound-operations.js +107 -105
  79. package/dist/runtime/channels/channel-receive-loops.d.ts +9 -7
  80. package/dist/runtime/channels/channel-receive-loops.js +126 -90
  81. package/dist/runtime/channels/channel-runtime-lifecycle.d.ts +23 -6
  82. package/dist/runtime/channels/channel-runtime-lifecycle.js +47 -38
  83. package/dist/runtime/channels/channel-runtime-manager.d.ts +13 -6
  84. package/dist/runtime/channels/channel-runtime-manager.js +32 -14
  85. package/dist/runtime/channels/channel-socket-registry.d.ts +28 -4
  86. package/dist/runtime/channels/channel-socket-registry.js +9 -1
  87. package/dist/runtime/channels/channel-transports.d.ts +23 -16
  88. package/dist/runtime/channels/channel-transports.js +139 -119
  89. package/dist/runtime/channels/dispatch-error-reporter.d.ts +4 -4
  90. package/dist/runtime/channels/dispatch-error-reporter.js +5 -5
  91. package/dist/runtime/channels/fanout-location-runtime.d.ts +1 -1
  92. package/dist/runtime/channels/local-spot-route-transport.d.ts +5 -2
  93. package/dist/runtime/channels/local-spot-route-transport.js +15 -18
  94. package/dist/runtime/channels/router-socket-spot-route-transport.d.ts +6 -3
  95. package/dist/runtime/channels/router-socket-spot-route-transport.js +33 -19
  96. package/dist/runtime/channels/source-spot-router.d.ts +6 -3
  97. package/dist/runtime/channels/source-spot-router.js +34 -23
  98. package/dist/runtime/channels/spot-node-route-transport.d.ts +6 -3
  99. package/dist/runtime/channels/spot-node-route-transport.js +23 -17
  100. package/dist/runtime/channels/spot-route-bridge-transport.d.ts +6 -3
  101. package/dist/runtime/channels/spot-route-bridge-transport.js +38 -24
  102. package/dist/runtime/channels/spot-route-dispatch-strategy.d.ts +8 -4
  103. package/dist/runtime/channels/spot-route-dispatch-strategy.js +36 -23
  104. package/dist/runtime/diagnostics/dispatch-error-details.js +9 -3
  105. package/dist/runtime/diagnostics/message-flow-bootstrap.d.ts +1 -0
  106. package/dist/runtime/diagnostics/message-flow-bootstrap.js +8 -0
  107. package/dist/runtime/diagnostics/message-flow-delivery.d.ts +47 -0
  108. package/dist/runtime/diagnostics/message-flow-delivery.js +149 -0
  109. package/dist/runtime/diagnostics/message-flow-record.d.ts +50 -0
  110. package/dist/runtime/diagnostics/message-flow-record.js +228 -0
  111. package/dist/runtime/diagnostics/message-flow-worker.d.ts +1 -0
  112. package/dist/runtime/diagnostics/message-flow-worker.js +118 -0
  113. package/dist/runtime/diagnostics/message-flow.d.ts +7 -19
  114. package/dist/runtime/diagnostics/message-flow.js +42 -290
  115. package/dist/runtime/diagnostics/runtime-metrics.d.ts +4 -3
  116. package/dist/runtime/diagnostics/runtime-metrics.js +8 -4
  117. package/dist/runtime/execution/index.d.ts +1 -0
  118. package/dist/runtime/execution/index.js +6 -3
  119. package/dist/runtime/execution/serial-execution-queue.d.ts +26 -13
  120. package/dist/runtime/execution/serial-execution-queue.js +75 -71
  121. package/dist/runtime/foundation/durable-service-request.d.ts +12 -3
  122. package/dist/runtime/foundation/durable-service-request.js +158 -73
  123. package/dist/runtime/foundation/operation-registry.d.ts +33 -3
  124. package/dist/runtime/foundation/operation-registry.js +272 -33
  125. package/dist/runtime/foundation/raw-service-mesh-runtime.d.ts +62 -23
  126. package/dist/runtime/foundation/raw-service-mesh-runtime.js +373 -194
  127. package/dist/runtime/foundation/request-runtime.d.ts +17 -0
  128. package/dist/runtime/foundation/request-runtime.js +163 -0
  129. package/dist/runtime/foundation/service-discovery-registry.d.ts +4 -0
  130. package/dist/runtime/foundation/service-discovery-registry.js +6 -0
  131. package/dist/runtime/foundation/service-liveness-registry.d.ts +1 -1
  132. package/dist/runtime/foundation/service-mailbox.d.ts +4 -2
  133. package/dist/runtime/foundation/service-mailbox.js +4 -1
  134. package/dist/runtime/foundation/service-relocation-object-owner.d.ts +2 -2
  135. package/dist/runtime/foundation/service-relocation-object-owner.js +12 -5
  136. package/dist/runtime/foundation/service-runtime-contracts.d.ts +7 -2
  137. package/dist/runtime/foundation/service-stateful-registry.d.ts +6 -2
  138. package/dist/runtime/foundation/service-stateful-registry.js +38 -17
  139. package/dist/runtime/foundation/service-stateful-runtime.d.ts +91 -26
  140. package/dist/runtime/foundation/service-stateful-runtime.js +245 -120
  141. package/dist/runtime/foundation/service-stateful-wire-codec.d.ts +3 -0
  142. package/dist/runtime/foundation/service-stateful-wire-codec.js +15 -0
  143. package/dist/runtime/foundation/service-topology-registry.d.ts +2 -0
  144. package/dist/runtime/foundation/service-topology-registry.js +13 -3
  145. package/dist/runtime/foundation/service-wire-constants.generated.d.ts +1 -0
  146. package/dist/runtime/foundation/service-wire-constants.generated.js +12 -0
  147. package/dist/runtime/foundation/service-wire-m6a-codec.d.ts +5 -1
  148. package/dist/runtime/foundation/service-wire-m6a-codec.js +50 -15
  149. package/dist/runtime/host/actor-packet-relay.d.ts +5 -6
  150. package/dist/runtime/host/actor-packet-relay.js +58 -57
  151. package/dist/runtime/host/actor-placement-coordinator.d.ts +1 -1
  152. package/dist/runtime/host/actor-runtime-options-factory.d.ts +2 -0
  153. package/dist/runtime/host/actor-runtime-options-factory.js +3 -2
  154. package/dist/runtime/host/actor-transfer-runtime.d.ts +3 -3
  155. package/dist/runtime/host/application-job-queue.d.ts +7 -5
  156. package/dist/runtime/host/application-job-queue.js +33 -21
  157. package/dist/runtime/host/bound-session-relay.js +0 -1
  158. package/dist/runtime/host/channel-runtime-options-factory.d.ts +2 -0
  159. package/dist/runtime/host/channel-runtime-options-factory.js +1 -0
  160. package/dist/runtime/host/entry-actor-runtime.d.ts +5 -2
  161. package/dist/runtime/host/entry-actor-runtime.js +2 -2
  162. package/dist/runtime/host/index.d.ts +106 -37
  163. package/dist/runtime/host/index.js +303 -151
  164. package/dist/runtime/host/location-runtime-owner.d.ts +2 -2
  165. package/dist/runtime/host/location-runtime-owner.js +1 -1
  166. package/dist/runtime/host/service-relocation-host-runtime.d.ts +195 -45
  167. package/dist/runtime/host/service-relocation-host-runtime.js +257 -144
  168. package/dist/runtime/host/spot-address-transport.d.ts +3 -0
  169. package/dist/runtime/host/spot-address-transport.js +73 -76
  170. package/dist/runtime/host/spot-runtime-options-factory.js +2 -0
  171. package/dist/runtime/host/user-spot-creation-coordinator.d.ts +3 -1
  172. package/dist/runtime/host/user-spot-creation-coordinator.js +49 -21
  173. package/dist/runtime/internal-observation.d.ts +1 -0
  174. package/dist/runtime/internal-observation.js +5 -0
  175. package/dist/runtime/locations/actor-location-claims.d.ts +1 -1
  176. package/dist/runtime/locations/actor-location-claims.js +15 -6
  177. package/dist/runtime/locations/auto-connect-loop.d.ts +0 -1
  178. package/dist/runtime/locations/auto-connect-loop.js +25 -19
  179. package/dist/runtime/locations/auto-connect-planner.js +2 -5
  180. package/dist/runtime/locations/auto-connect-reconciler.d.ts +1 -0
  181. package/dist/runtime/locations/auto-connect-reconciler.js +35 -23
  182. package/dist/runtime/locations/in-memory-authority-store.d.ts +1 -0
  183. package/dist/runtime/locations/in-memory-authority-store.js +15 -5
  184. package/dist/runtime/locations/in-memory-location-store.d.ts +0 -2
  185. package/dist/runtime/locations/in-memory-location-store.js +1 -38
  186. package/dist/runtime/locations/lifecycle.d.ts +1 -1
  187. package/dist/runtime/locations/lifecycle.js +2 -2
  188. package/dist/runtime/locations/location-store-repository.d.ts +0 -1
  189. package/dist/runtime/locations/location-store-repository.js +163 -246
  190. package/dist/runtime/locations/resolvers.d.ts +8 -1
  191. package/dist/runtime/locations/resolvers.js +16 -2
  192. package/dist/runtime/locations/runtime.d.ts +3 -3
  193. package/dist/runtime/locations/runtime.js +12 -16
  194. package/dist/runtime/messaging/creation-payload-codec.js +8 -7
  195. package/dist/runtime/messaging/framework-json-v1.d.ts +1 -1
  196. package/dist/runtime/messaging/framework-json-v1.js +6 -2
  197. package/dist/runtime/messaging/payload-codec.js +21 -35
  198. package/dist/runtime/messaging/request-deadline.d.ts +4 -2
  199. package/dist/runtime/messaging/request-deadline.js +40 -25
  200. package/dist/runtime/messaging/request-result.d.ts +14 -1
  201. package/dist/runtime/messaging/request-result.js +74 -13
  202. package/dist/runtime/protocol/service_wire_codec.generated.d.ts +4 -0
  203. package/dist/runtime/protocol/service_wire_codec.generated.js +17 -7
  204. package/dist/runtime/spots/index.d.ts +28 -7
  205. package/dist/runtime/spots/index.js +31 -6
  206. package/dist/runtime/spots/spot-activation-registry.d.ts +3 -2
  207. package/dist/runtime/spots/spot-activation-registry.js +13 -8
  208. package/dist/runtime/spots/spot-activation-state.d.ts +2 -0
  209. package/dist/runtime/spots/spot-activation-state.js +1 -0
  210. package/dist/runtime/spots/spot-actor-admission-coordinator.d.ts +9 -4
  211. package/dist/runtime/spots/spot-actor-admission-coordinator.js +33 -12
  212. package/dist/runtime/spots/spot-actor-ingress-admission.d.ts +40 -0
  213. package/dist/runtime/spots/spot-actor-ingress-admission.js +78 -0
  214. package/dist/runtime/spots/spot-actor-membership.js +3 -3
  215. package/dist/runtime/spots/spot-actor-packet-dispatch.d.ts +16 -43
  216. package/dist/runtime/spots/spot-actor-packet-dispatch.js +56 -113
  217. package/dist/runtime/spots/spot-actor-packet-drain.d.ts +1 -0
  218. package/dist/runtime/spots/spot-actor-packet-drain.js +12 -5
  219. package/dist/runtime/spots/spot-entry-activation.d.ts +4 -3
  220. package/dist/runtime/spots/spot-entry-activation.js +7 -12
  221. package/dist/runtime/spots/spot-handler-registry.d.ts +5 -1
  222. package/dist/runtime/spots/spot-handler-registry.js +31 -15
  223. package/dist/runtime/spots/spot-manager-public.js +3 -2
  224. package/dist/runtime/spots/spot-node-runtime-manager.d.ts +11 -6
  225. package/dist/runtime/spots/spot-node-runtime-manager.js +6 -1
  226. package/dist/runtime/spots/spot-outbound.d.ts +8 -2
  227. package/dist/runtime/spots/spot-outbound.js +5 -5
  228. package/dist/runtime/spots/spot-route-packet-dispatch.js +13 -8
  229. package/dist/runtime/spots/spot-routed-spot-packet-dispatch.d.ts +3 -3
  230. package/dist/runtime/spots/spot-routed-spot-packet-dispatch.js +9 -5
  231. package/dist/runtime/spots/spot-runtime-ports.d.ts +2 -2
  232. package/dist/runtime/spots/spot-serial-executor.d.ts +2 -1
  233. package/dist/runtime/spots/spot-serial-turn-executor.js +20 -26
  234. package/dist/runtime/spots/spot-subscription-dispatch.js +5 -2
  235. package/dist/runtime/spots/spot-timer.d.ts +1 -1
  236. package/dist/runtime/streams/actor-session-binding-registry.d.ts +11 -3
  237. package/dist/runtime/streams/actor-session-binding-registry.js +28 -0
  238. package/dist/runtime/streams/bound-actor-relay-sender.d.ts +2 -2
  239. package/dist/runtime/streams/bound-actor-relay-sender.js +3 -4
  240. package/dist/runtime/streams/bound-session-service.js +6 -7
  241. package/dist/runtime/streams/index.d.ts +3 -3
  242. package/dist/runtime/streams/index.js +22 -2
  243. package/dist/runtime/streams/managed-stream.js +2 -1
  244. package/dist/runtime/streams/session-calls.d.ts +1 -1
  245. package/dist/runtime/streams/session-calls.js +3 -9
  246. package/dist/runtime/streams/session-context.d.ts +2 -2
  247. package/dist/runtime/streams/session-context.js +2 -2
  248. package/dist/runtime/streams/stream-session-runtime.d.ts +1 -0
  249. package/dist/runtime/streams/stream-session-runtime.js +64 -33
  250. package/package.json +3 -3
  251. package/src/contracts/Actors/ZLinkActor.ts +6 -0
  252. package/src/contracts/Actors/ZLinkSessionBindingIdentity.ts +7 -0
  253. package/src/contracts/Actors/index.ts +1 -0
  254. package/src/contracts/Common/CoreTypes.ts +1 -0
  255. package/src/contracts/Common/HandlerMessageType.ts +50 -0
  256. package/src/contracts/Common/ZLinkEncodedPayload.ts +13 -25
  257. package/src/contracts/Common/ZLinkMessage.ts +11 -7
  258. package/src/contracts/Common/encoded-payload-storage.ts +4 -16
  259. package/src/contracts/Common/index.ts +1 -1
  260. package/src/contracts/Common/payload-slab.ts +29 -0
  261. package/src/contracts/Configuration/RegistrationBuilders.ts +29 -15
  262. package/src/contracts/Configuration/RegistrationTypes.ts +19 -0
  263. package/src/contracts/Handlers/Contexts.ts +1 -0
  264. package/src/contracts/Locations/Authority.ts +7 -1
  265. package/src/internal.ts +17 -0
  266. package/src/nest-integration.ts +1 -0
  267. package/src/runtime/actors/actor-client.ts +257 -163
  268. package/src/runtime/actors/actor-context.ts +26 -14
  269. package/src/runtime/actors/actor-execution-context.ts +2 -2
  270. package/src/runtime/actors/actor-handoff.ts +86 -51
  271. package/src/runtime/actors/actor-join-deferred-scope.ts +6 -6
  272. package/src/runtime/actors/actor-local-native-join.ts +38 -17
  273. package/src/runtime/actors/actor-mailbox.ts +1 -1
  274. package/src/runtime/actors/actor-remote-joiner.ts +8 -4
  275. package/src/runtime/actors/actor-routed-join-transport.ts +13 -5
  276. package/src/runtime/actors/actor-routed-json-request.ts +3 -0
  277. package/src/runtime/actors/actor-runtime-contracts.ts +4 -2
  278. package/src/runtime/actors/actor-runtime-state.ts +1 -1
  279. package/src/runtime/actors/spot-actor-dispatch.ts +70 -68
  280. package/src/runtime/admission.ts +42 -15
  281. package/src/runtime/application-jobs/application-ingress-record-owner.ts +4 -0
  282. package/src/runtime/backend/contracts/index.ts +77 -10
  283. package/src/runtime/backend/mesh-completion-table.ts +106 -15
  284. package/src/runtime/backend/mesh-dispatch-pump.ts +294 -146
  285. package/src/runtime/backend/node/node-backend-adapter-support.ts +42 -32
  286. package/src/runtime/backend/node/node-dealer-channel-client-transport.ts +91 -34
  287. package/src/runtime/backend/node/node-event-loop-poller.ts +14 -5
  288. package/src/runtime/backend/node/node-mesh-backend-adapter.ts +5 -1
  289. package/src/runtime/backend/node/node-raw-binding-port.ts +180 -69
  290. package/src/runtime/backend/node/node-raw-mesh-backend.ts +386 -157
  291. package/src/runtime/backend/node/node-socket-backend-adapter.ts +56 -11
  292. package/src/runtime/backend/raw-binding-port.ts +13 -5
  293. package/src/runtime/channels/channel-clients.ts +26 -11
  294. package/src/runtime/channels/channel-dispatch-pipeline.ts +77 -65
  295. package/src/runtime/channels/channel-dispatch-services.ts +7 -12
  296. package/src/runtime/channels/channel-dispatchers.ts +93 -39
  297. package/src/runtime/channels/channel-envelope.ts +680 -144
  298. package/src/runtime/channels/channel-multipart.ts +17 -13
  299. package/src/runtime/channels/channel-outbound-operations.ts +204 -178
  300. package/src/runtime/channels/channel-receive-loops.ts +160 -107
  301. package/src/runtime/channels/channel-runtime-lifecycle.ts +64 -59
  302. package/src/runtime/channels/channel-runtime-manager.ts +74 -27
  303. package/src/runtime/channels/channel-socket-registry.ts +20 -5
  304. package/src/runtime/channels/channel-transports.ts +414 -287
  305. package/src/runtime/channels/dispatch-error-reporter.ts +4 -9
  306. package/src/runtime/channels/local-spot-route-transport.ts +27 -29
  307. package/src/runtime/channels/router-socket-spot-route-transport.ts +63 -32
  308. package/src/runtime/channels/source-spot-router.ts +75 -38
  309. package/src/runtime/channels/spot-node-route-transport.ts +67 -37
  310. package/src/runtime/channels/spot-route-bridge-transport.ts +62 -30
  311. package/src/runtime/channels/spot-route-dispatch-strategy.ts +105 -34
  312. package/src/runtime/diagnostics/dispatch-error-details.ts +10 -2
  313. package/src/runtime/diagnostics/message-flow-bootstrap.ts +6 -0
  314. package/src/runtime/diagnostics/message-flow-delivery.ts +171 -0
  315. package/src/runtime/diagnostics/message-flow-record.ts +295 -0
  316. package/src/runtime/diagnostics/message-flow-worker.ts +146 -0
  317. package/src/runtime/diagnostics/message-flow.ts +49 -362
  318. package/src/runtime/diagnostics/runtime-metrics.ts +10 -4
  319. package/src/runtime/execution/index.ts +6 -0
  320. package/src/runtime/execution/serial-execution-queue.ts +94 -96
  321. package/src/runtime/foundation/durable-service-request.ts +212 -89
  322. package/src/runtime/foundation/operation-registry.ts +287 -38
  323. package/src/runtime/foundation/raw-service-mesh-runtime.ts +617 -292
  324. package/src/runtime/foundation/request-runtime.ts +227 -0
  325. package/src/runtime/foundation/service-discovery-registry.ts +7 -0
  326. package/src/runtime/foundation/service-liveness-registry.ts +1 -1
  327. package/src/runtime/foundation/service-mailbox.ts +7 -2
  328. package/src/runtime/foundation/service-relocation-object-owner.ts +21 -6
  329. package/src/runtime/foundation/service-runtime-contracts.ts +12 -2
  330. package/src/runtime/foundation/service-stateful-registry.ts +52 -19
  331. package/src/runtime/foundation/service-stateful-runtime.ts +365 -198
  332. package/src/runtime/foundation/service-stateful-wire-codec.ts +18 -0
  333. package/src/runtime/foundation/service-topology-registry.ts +21 -3
  334. package/src/runtime/foundation/service-wire-constants.generated.ts +10 -0
  335. package/src/runtime/foundation/service-wire-m6a-codec.ts +69 -17
  336. package/src/runtime/host/actor-packet-relay.ts +160 -156
  337. package/src/runtime/host/actor-placement-coordinator.ts +1 -1
  338. package/src/runtime/host/actor-runtime-options-factory.ts +7 -2
  339. package/src/runtime/host/actor-transfer-runtime.ts +3 -3
  340. package/src/runtime/host/application-job-queue.ts +56 -27
  341. package/src/runtime/host/bound-session-relay.ts +0 -1
  342. package/src/runtime/host/channel-runtime-options-factory.ts +3 -0
  343. package/src/runtime/host/entry-actor-runtime.ts +14 -6
  344. package/src/runtime/host/index.ts +388 -113
  345. package/src/runtime/host/location-runtime-owner.ts +3 -3
  346. package/src/runtime/host/service-relocation-host-runtime.ts +380 -252
  347. package/src/runtime/host/spot-address-transport.ts +110 -95
  348. package/src/runtime/host/spot-runtime-options-factory.ts +3 -0
  349. package/src/runtime/host/user-spot-creation-coordinator.ts +69 -22
  350. package/src/runtime/internal-observation.ts +2 -0
  351. package/src/runtime/locations/actor-location-claims.ts +42 -16
  352. package/src/runtime/locations/auto-connect-loop.ts +24 -16
  353. package/src/runtime/locations/auto-connect-planner.ts +2 -5
  354. package/src/runtime/locations/auto-connect-reconciler.ts +37 -24
  355. package/src/runtime/locations/in-memory-authority-store.ts +27 -7
  356. package/src/runtime/locations/in-memory-location-store.ts +1 -74
  357. package/src/runtime/locations/lifecycle.ts +4 -2
  358. package/src/runtime/locations/location-store-repository.ts +228 -308
  359. package/src/runtime/locations/resolvers.ts +20 -8
  360. package/src/runtime/locations/runtime.ts +16 -28
  361. package/src/runtime/messaging/creation-payload-codec.ts +12 -10
  362. package/src/runtime/messaging/framework-json-v1.ts +10 -1
  363. package/src/runtime/messaging/payload-codec.ts +50 -75
  364. package/src/runtime/messaging/request-deadline.ts +47 -39
  365. package/src/runtime/messaging/request-result.ts +88 -17
  366. package/src/runtime/protocol/service_wire_codec.generated.ts +18 -8
  367. package/src/runtime/protocol/service_wire_pilot_codec.generated.ts +1 -1
  368. package/src/runtime/spots/index.ts +57 -10
  369. package/src/runtime/spots/spot-activation-registry.ts +12 -8
  370. package/src/runtime/spots/spot-activation-state.ts +2 -0
  371. package/src/runtime/spots/spot-actor-admission-coordinator.ts +62 -37
  372. package/src/runtime/spots/spot-actor-ingress-admission.ts +157 -0
  373. package/src/runtime/spots/spot-actor-membership.ts +8 -5
  374. package/src/runtime/spots/spot-actor-packet-dispatch.ts +122 -206
  375. package/src/runtime/spots/spot-actor-packet-drain.ts +21 -6
  376. package/src/runtime/spots/spot-entry-activation.ts +25 -35
  377. package/src/runtime/spots/spot-handler-registry.ts +72 -15
  378. package/src/runtime/spots/spot-manager-public.ts +4 -2
  379. package/src/runtime/spots/spot-node-runtime-manager.ts +16 -7
  380. package/src/runtime/spots/spot-outbound.ts +26 -10
  381. package/src/runtime/spots/spot-route-packet-dispatch.ts +18 -8
  382. package/src/runtime/spots/spot-routed-spot-packet-dispatch.ts +14 -8
  383. package/src/runtime/spots/spot-runtime-ports.ts +5 -2
  384. package/src/runtime/spots/spot-serial-executor.ts +1 -1
  385. package/src/runtime/spots/spot-serial-turn-executor.ts +25 -40
  386. package/src/runtime/spots/spot-subscription-dispatch.ts +9 -2
  387. package/src/runtime/spots/spot-timer.ts +1 -1
  388. package/src/runtime/streams/actor-session-binding-registry.ts +46 -3
  389. package/src/runtime/streams/bound-actor-relay-sender.ts +16 -5
  390. package/src/runtime/streams/bound-session-service.ts +10 -7
  391. package/src/runtime/streams/index.ts +30 -4
  392. package/src/runtime/streams/managed-stream.ts +2 -1
  393. package/src/runtime/streams/session-calls.ts +9 -14
  394. package/src/runtime/streams/session-context.ts +6 -11
  395. package/src/runtime/streams/stream-session-runtime.ts +79 -40
  396. package/dist/runtime/spots/spot-lifecycle-metrics.d.ts +0 -8
  397. package/dist/runtime/spots/spot-lifecycle-metrics.js +0 -17
  398. package/src/runtime/spots/spot-lifecycle-metrics.ts +0 -16
@@ -1,4 +1,3 @@
1
- import { AsyncLocalStorage } from 'node:async_hooks';
2
1
  import { awaitWithAbort } from '../abort';
3
2
  import { availableParallelism } from 'node:os';
4
3
  import {
@@ -10,9 +9,10 @@ import type {
10
9
  ApplicationJobPermitPort,
11
10
  ApplicationJobQueuePort
12
11
  } from '../application-jobs/contracts';
13
- import { runZLinkExecutionArea } from '../execution';
12
+ import { detachedMeshDispatchScope, runZLinkExecutionArea } from '../execution';
14
13
  import {
15
14
  ReadyDomain,
15
+ ReceiveKind,
16
16
  type Claim,
17
17
  type ReadyBatch,
18
18
  type ReadyRecord,
@@ -39,15 +39,9 @@ const MESH_DISPATCH_YIELD_INTERVAL_MS = 2;
39
39
  const MESH_DISPATCH_LIFECYCLE_CLAIM_BUDGET = 4;
40
40
  const MESH_DISPATCH_RECEIVE_CAPACITY = 64;
41
41
  const MESH_DISPATCH_MAX_APPLICATION_WORKERS = Math.max(2, availableParallelism());
42
- // Captured while the runtime module is loaded, before any application owner
43
- // exists. A ready callback may run inside a Spot turn; the shared Mesh pump
44
- // must enter like an independent receive-loop task, without inheriting that
45
- // owner's AsyncLocalStorage identity.
46
- const detachedMeshDispatchScope = AsyncLocalStorage.snapshot();
47
42
 
48
43
  export interface ZLinkMeshDispatchPumpOptions {
49
44
  readonly readyCapacity?: number;
50
- readonly messageCapacity?: number;
51
45
  readonly partCapacity?: number;
52
46
  readonly dispatch: (owner: ReadyRecord, record: ReceiveRecord) => void | Promise<void>;
53
47
  readonly applicationJobQueue: ApplicationJobQueuePort;
@@ -63,12 +57,26 @@ export interface ZLinkMeshDispatchFailureContext {
63
57
  readonly commandId?: number;
64
58
  }
65
59
 
60
+ interface MeshClaimDrainState {
61
+ readonly suppliedReceiveBatch: ReceiveBatch | undefined;
62
+ receiveBatch: ReceiveBatch | undefined;
63
+ domain: number;
64
+ owner: ReadyRecord | undefined;
65
+ claim: Claim | undefined;
66
+ claimPermit: ApplicationJobPermitPort | undefined;
67
+ records: readonly ReceiveRecord[] | undefined;
68
+ index: number;
69
+ readonly receive: (permit?: ApplicationJobPermitPort) => Promise<void> | undefined;
70
+ readonly dispatchRecords: () => Promise<void> | undefined;
71
+ readonly finish: () => void;
72
+ }
73
+
66
74
  export class ZLinkMeshDispatchPump {
67
75
  private pendingDomains: number = ReadyDomain.None;
68
76
  private infrastructureScheduled = false;
69
77
  private disposed = false;
70
78
  private readonly activeDrains = new Set<Promise<void>>();
71
- private readonly idleApplicationWorkers = new Set<() => void>();
79
+ private readonly idleApplicationWorkers: Array<() => void> = [];
72
80
  private applicationWorkerCount = 0;
73
81
  private readonly capacityStop = new AbortController();
74
82
  private recordsSinceYield = 0;
@@ -102,7 +110,7 @@ export class ZLinkMeshDispatchPump {
102
110
  this.capacityStop.abort();
103
111
  this.pendingDomains = ReadyDomain.None;
104
112
  for (const wake of this.idleApplicationWorkers) wake();
105
- this.idleApplicationWorkers.clear();
113
+ this.idleApplicationWorkers.length = 0;
106
114
  while (this.activeDrains.size > 0) {
107
115
  await awaitWithAbort(Promise.all([...this.activeDrains]), signal);
108
116
  }
@@ -124,18 +132,21 @@ export class ZLinkMeshDispatchPump {
124
132
  if (startInfrastructure) this.scheduleInfrastructure();
125
133
  if (startApplication) {
126
134
  if ((domains & ReadyDomain.Infrastructure) !== 0) {
127
- setImmediate(() => this.wakeApplicationWorker());
135
+ this.scheduleApplicationWorker();
128
136
  } else {
129
137
  this.wakeApplicationWorker();
130
138
  }
131
139
  }
132
140
  }
133
141
 
142
+ private scheduleApplicationWorker(): void {
143
+ setImmediate(() => this.wakeApplicationWorker());
144
+ }
145
+
134
146
  private wakeApplicationWorker(): void {
135
147
  if (this.disposed || (this.pendingDomains & ReadyDomain.Application) === 0) return;
136
- const idle = this.idleApplicationWorkers.values().next().value as (() => void) | undefined;
148
+ const idle = this.idleApplicationWorkers.shift();
137
149
  if (idle !== undefined) {
138
- this.idleApplicationWorkers.delete(idle);
139
150
  this.pendingDomains &= ~ReadyDomain.Application;
140
151
  idle();
141
152
  return;
@@ -157,79 +168,61 @@ export class ZLinkMeshDispatchPump {
157
168
  this.activeDrains.add(worker);
158
169
  }
159
170
 
160
- private async runApplicationWorker(): Promise<void> {
161
- // A worker claims one owner at a time so a suspended handler cannot hold
162
- // unrelated owners. Each owner may supply up to 64 pre-admitted records.
163
- const readyBatch = this.node.createReadyBatch(1);
164
- const receiveBatch = this.node.createReceiveBatch(
165
- MESH_DISPATCH_RECEIVE_CAPACITY,
166
- this.options.partCapacity ?? DEFAULT_MESH_PART_CAPACITY
167
- );
168
- try {
169
- for (;;) {
170
- await this.waitForApplicationReady();
171
- this.beginDrain();
172
- try {
173
- while (!this.disposed) {
174
- readyBatch.reset();
175
- const drained = this.node.drainReady(
176
- ReadyDomain.Application,
177
- readyBatch,
178
- ZLINK_BACKEND_RECV_DONT_WAIT
179
- );
180
- if (!drained.ok || drained.records.length === 0) break;
181
- if (drained.hasResidue) this.markReady(ReadyDomain.Application);
182
- for (let index = 0; index < drained.records.length; index += 1) {
183
- const claim = readyBatch.takeClaim(index);
184
- // Raw ingress already attached one host permit to each record.
185
- // A claim reserving admission may receive only that permit's record.
186
- await this.drainClaim(
187
- ReadyDomain.Application,
188
- drained.records[index]!,
189
- claim,
190
- receiveBatch
191
- );
192
- }
193
- // Empty ready claims count toward the shared pump budget too.
194
- this.recordsSinceYield += 1;
195
- const yieldTurn = this.yieldIfNeeded();
196
- if (yieldTurn !== undefined) await yieldTurn;
197
- }
198
- } catch (error) {
199
- this.reportDispatchError(error);
200
- } finally {
201
- readyBatch.reset();
202
- this.draining -= 1;
203
- }
204
- if (this.disposed) return;
205
- }
206
- } finally {
207
- receiveBatch.close();
208
- readyBatch.close();
209
- }
210
- }
211
-
212
171
  private waitForApplicationReady(): Promise<void> {
213
172
  if (this.disposed) return Promise.resolve();
214
173
  if ((this.pendingDomains & ReadyDomain.Application) !== 0) {
215
174
  this.pendingDomains &= ~ReadyDomain.Application;
216
175
  return Promise.resolve();
217
176
  }
218
- return new Promise((resolve) => this.idleApplicationWorkers.add(resolve));
177
+ return new Promise((resolve) => this.idleApplicationWorkers.push(resolve));
219
178
  }
220
179
 
221
180
  /**
222
181
  * Starts one record in this worker's turn; a permit's scope covers the
223
- * synchronous dispatch. Returns `false` when the dispatch threw (already
224
- * reported), `true` when it returned synchronously, or the handler's pending
225
- * completion, which the draining turn awaits itself before
182
+ * synchronous dispatch. Returns `false` when preparation rejects the record,
183
+ * shutdown starts, or dispatch throws (already reported), `true` when dispatch
184
+ * returns synchronously, or the pending preparation/handler completion,
185
+ * which the draining turn awaits itself before
226
186
  * {@link finishRecord}.
227
187
  */
228
188
  private dispatchRecord(
229
189
  owner: ReadyRecord,
230
190
  record: ReceiveRecord,
231
191
  permit: ApplicationJobPermitPort | undefined
192
+ ): boolean | PromiseLike<void | boolean> {
193
+ if (record.prepareDispatch === undefined) return this.invokeRecord(owner, record, permit);
194
+ try {
195
+ const preparation = record.prepareDispatch(this.capacityStop.signal);
196
+ return preparation instanceof Promise
197
+ ? this.continuePreparingRecord(owner, record, permit, preparation)
198
+ : this.invokeRecord(owner, record, permit, preparation);
199
+ } catch (error) {
200
+ this.failRecord(error, record, permit);
201
+ return false;
202
+ }
203
+ }
204
+
205
+ private continuePreparingRecord(
206
+ owner: ReadyRecord,
207
+ record: ReceiveRecord,
208
+ permit: ApplicationJobPermitPort | undefined,
209
+ preparation: Promise<boolean>
210
+ ): Promise<void | boolean> {
211
+ return preparation.then<void | boolean>((accepted) =>
212
+ this.invokeRecord(owner, record, permit, accepted)
213
+ );
214
+ }
215
+
216
+ private invokeRecord(
217
+ owner: ReadyRecord,
218
+ record: ReceiveRecord,
219
+ permit: ApplicationJobPermitPort | undefined,
220
+ accepted = true
232
221
  ): boolean | PromiseLike<void> {
222
+ if (!accepted || this.capacityStop.signal.aborted) {
223
+ releaseApplicationJobPermitTurn(permit);
224
+ return false;
225
+ }
233
226
  const previous = permit === undefined ? undefined : enterApplicationJobPermitScope(permit);
234
227
  let result: void | PromiseLike<void>;
235
228
  try {
@@ -267,6 +260,14 @@ export class ZLinkMeshDispatchPump {
267
260
  releaseApplicationJobPermitTurn(permit);
268
261
  return;
269
262
  }
263
+ return this.finishPendingRecord(result, record, permit);
264
+ }
265
+
266
+ private finishPendingRecord(
267
+ result: Promise<void>,
268
+ record: ReceiveRecord,
269
+ permit: ApplicationJobPermitPort | undefined
270
+ ): Promise<void> {
270
271
  return Promise.resolve(result).then(
271
272
  () => releaseApplicationJobPermitTurn(permit),
272
273
  (error) => {
@@ -323,7 +324,7 @@ export class ZLinkMeshDispatchPump {
323
324
  }
324
325
  this.pendingDomains &= ~ReadyDomain.Infrastructure;
325
326
  if ((this.pendingDomains & ReadyDomain.Application) !== 0) {
326
- setImmediate(() => this.wakeApplicationWorker());
327
+ this.scheduleApplicationWorker();
327
328
  }
328
329
  const lifecycleBudgetExhausted = await this.drainDomain(readyBatch);
329
330
  if (lifecycleBudgetExhausted) {
@@ -360,9 +361,7 @@ export class ZLinkMeshDispatchPump {
360
361
  claimsDrained += 1;
361
362
  const owner = drained.records[index]!;
362
363
  this.beginDrain();
363
- const drain = this.drainClaim(ReadyDomain.Infrastructure, owner, claim, undefined).catch(
364
- (error) => this.reportDispatchError(error)
365
- );
364
+ const drain = this.drainClaim(ReadyDomain.Infrastructure, owner, claim);
366
365
  this.activeDrains.add(drain);
367
366
  void drain.finally(() => {
368
367
  this.draining -= 1;
@@ -398,98 +397,238 @@ export class ZLinkMeshDispatchPump {
398
397
  this.draining += 1;
399
398
  }
400
399
 
401
- /** Drains one claimed owner in this worker's turn, in claim order. */
400
+ /** Each worker owns claim continuations for its entire lifetime. */
401
+ private async runApplicationWorker(): Promise<void> {
402
+ const readyBatch = this.node.createReadyBatch(1);
403
+ const receiveBatch = this.node.createReceiveBatch(
404
+ MESH_DISPATCH_RECEIVE_CAPACITY,
405
+ this.options.partCapacity ?? DEFAULT_MESH_PART_CAPACITY
406
+ );
407
+ const claimDrain = this.createClaimDrain(receiveBatch);
408
+ try {
409
+ for (;;) {
410
+ // This boundary also keeps the first handler off the receive stack.
411
+ await this.waitForApplicationReady();
412
+ this.beginDrain();
413
+ try {
414
+ while (!this.disposed) {
415
+ readyBatch.reset();
416
+ const drained = this.node.drainReady(
417
+ ReadyDomain.Application,
418
+ readyBatch,
419
+ ZLINK_BACKEND_RECV_DONT_WAIT
420
+ );
421
+ if (!drained.ok || drained.records.length === 0) break;
422
+ if (drained.hasResidue) this.markReady(ReadyDomain.Application);
423
+ const pending = this.dispatchClaim(
424
+ ReadyDomain.Application,
425
+ drained.records[0]!,
426
+ readyBatch.takeClaim(0),
427
+ claimDrain
428
+ );
429
+ if (pending !== undefined) await pending;
430
+ // Returning a claim remains an asynchronous worker boundary without
431
+ // allocating a separate async drain task for a synchronous claim.
432
+ await this.yieldIfNeeded();
433
+ // Empty ready claims count toward the shared pump budget too.
434
+ this.recordsSinceYield += 1;
435
+ const nextTurn = this.yieldIfNeeded();
436
+ if (nextTurn !== undefined) await nextTurn;
437
+ }
438
+ } catch (error) {
439
+ this.reportDispatchError(error);
440
+ } finally {
441
+ readyBatch.reset();
442
+ this.draining -= 1;
443
+ }
444
+ if (this.disposed) return;
445
+ }
446
+ } finally {
447
+ receiveBatch.close();
448
+ readyBatch.close();
449
+ }
450
+ }
451
+
402
452
  private async drainClaim(
403
453
  domain: number,
404
454
  owner: ReadyRecord,
405
455
  claim: Claim,
406
- receiveBatch: ReceiveBatch | undefined
456
+ receiveBatch?: ReceiveBatch
407
457
  ): Promise<void> {
408
- let ownerReceiveBatch = receiveBatch;
409
458
  try {
410
- ownerReceiveBatch ??= this.node.createReceiveBatch(
459
+ const pending = this.dispatchClaim(domain, owner, claim, this.createClaimDrain(receiveBatch));
460
+ if (pending !== undefined) await pending;
461
+ await this.yieldIfNeeded();
462
+ } catch (error) {
463
+ this.reportDispatchError(error);
464
+ }
465
+ }
466
+
467
+ private createClaimDrain(suppliedReceiveBatch?: ReceiveBatch): MeshClaimDrainState {
468
+ const state: MeshClaimDrainState = {
469
+ suppliedReceiveBatch,
470
+ receiveBatch: suppliedReceiveBatch,
471
+ domain: ReadyDomain.None,
472
+ owner: undefined,
473
+ claim: undefined,
474
+ claimPermit: undefined,
475
+ records: undefined,
476
+ index: 0,
477
+ receive: (permit) => this.receiveClaim(state, permit),
478
+ dispatchRecords: () => this.dispatchClaimRecords(state),
479
+ finish: () => this.finishClaim(state)
480
+ };
481
+ return state;
482
+ }
483
+
484
+ /** A synchronous claim finishes without an async wrapper or a Promise. */
485
+ private dispatchClaim(
486
+ domain: number,
487
+ owner: ReadyRecord,
488
+ claim: Claim,
489
+ state: MeshClaimDrainState = this.createClaimDrain()
490
+ ): Promise<void> | undefined {
491
+ state.domain = domain;
492
+ state.owner = owner;
493
+ state.claim = claim;
494
+ state.index = 0;
495
+ let pending: Promise<void> | undefined;
496
+ try {
497
+ state.receiveBatch ??= this.node.createReceiveBatch(
411
498
  MESH_DISPATCH_RECEIVE_CAPACITY,
412
499
  this.options.partCapacity ?? DEFAULT_MESH_PART_CAPACITY
413
500
  );
414
- const capacity =
415
- owner.ordinaryIngressPreAdmitted === true ? MESH_DISPATCH_RECEIVE_CAPACITY : 1;
416
- let claimPermit =
501
+ pending =
417
502
  owner.terminalCompletion === true ||
418
503
  owner.ordinaryIngressPreAdmitted === true ||
419
504
  domain === ReadyDomain.Infrastructure
420
- ? undefined
421
- : await this.acquirePermit();
505
+ ? state.receive()
506
+ : this.acquirePermit().then(state.receive);
507
+ if (pending !== undefined) return pending.finally(state.finish);
508
+ return undefined;
509
+ } finally {
510
+ if (pending === undefined) state.finish();
511
+ }
512
+ }
513
+
514
+ private receiveClaim(
515
+ state: MeshClaimDrainState,
516
+ permit?: ApplicationJobPermitPort
517
+ ): Promise<void> | undefined {
518
+ state.claimPermit = permit;
519
+ if (this.capacityStop.signal.aborted) return undefined;
520
+ const capacity =
521
+ state.owner!.ordinaryIngressPreAdmitted === true ? MESH_DISPATCH_RECEIVE_CAPACITY : 1;
522
+ state.receiveBatch!.reset(capacity);
523
+ const received = state.claim!.recvBatch(state.receiveBatch!, ZLINK_BACKEND_RECV_DONT_WAIT);
524
+ if (!received.ok) return undefined;
525
+ state.records = received.records;
526
+ return this.dispatchClaimRecords(state);
527
+ }
528
+
529
+ private dispatchClaimRecords(state: MeshClaimDrainState): Promise<void> | undefined {
530
+ const records = state.records!;
531
+ const owner = state.owner!;
532
+ while (state.index < records.length && !this.disposed) {
533
+ const record = records[state.index++]!;
534
+ const permit = record.applicationJobPermit ?? state.claimPermit;
535
+ if (owner.ordinaryIngressPreAdmitted === true && permit === undefined) {
536
+ throw new Error('Pre-admitted raw ingress record lost its Application Job Queue permit.');
537
+ }
538
+ this.recordsSinceYield += 1;
539
+ if (permit !== undefined) {
540
+ if (state.domain === ReadyDomain.Application && record.applicationJobPermit === undefined)
541
+ permit.markApplicationQueued();
542
+ // Only reservations not transferred to a record remain claim-owned.
543
+ if (permit === state.claimPermit) state.claimPermit = undefined;
544
+ }
545
+ const dispatched = this.dispatchRecord(owner, record, permit);
546
+ if (dispatched === false) {
547
+ if (isNodeOrChannelRecord(record)) this.releaseRecord(record);
548
+ continue;
549
+ }
550
+ let terminal: Promise<void>;
551
+ if (dispatched === true) {
552
+ const finished = this.finishRecord(record, permit);
553
+ if (finished === undefined) {
554
+ if (isNodeOrChannelRecord(record)) this.releaseRecord(record);
555
+ continue;
556
+ }
557
+ terminal = finished;
558
+ } else {
559
+ terminal = this.continuePendingClaim(dispatched, record, permit);
560
+ }
561
+ if (isNodeOrChannelRecord(record)) {
562
+ // Return the receive claim for the next batch; the existing terminal observer owns record lifetime.
563
+ this.observeRecordTerminal(terminal, record);
564
+ continue;
565
+ }
566
+ return terminal.then(state.dispatchRecords);
567
+ }
568
+ return undefined;
569
+ }
570
+
571
+ private observeRecordTerminal(terminal: Promise<void>, record: ReceiveRecord): void {
572
+ const tracked = terminal.finally(() => this.releaseRecord(record));
573
+ this.activeDrains.add(tracked);
574
+ void tracked.then(
575
+ () => this.activeDrains.delete(tracked),
576
+ (error) => {
577
+ this.activeDrains.delete(tracked);
578
+ this.reportDispatchError(error, meshDispatchFailureContext(record));
579
+ }
580
+ );
581
+ }
582
+
583
+ private continuePendingClaim(
584
+ dispatched: PromiseLike<void | boolean>,
585
+ record: ReceiveRecord,
586
+ permit: ApplicationJobPermitPort | undefined
587
+ ): Promise<void> {
588
+ return Promise.resolve(dispatched).then(
589
+ (accepted) => {
590
+ if (accepted !== false) return this.finishRecord(record, permit);
591
+ },
592
+ (error) => this.failRecord(error, record, permit)
593
+ );
594
+ }
595
+
596
+ private releaseRecord(record: ReceiveRecord): void {
597
+ for (let index = 0; index < record.parts.length; index++) record.parts[index]!.close();
598
+ record.releaseRetainedIngress?.();
599
+ }
600
+
601
+ private finishClaim(state: MeshClaimDrainState): void {
602
+ try {
422
603
  try {
423
- if (this.capacityStop.signal.aborted) return;
424
- ownerReceiveBatch.reset(capacity);
425
- const received = claim.recvBatch(ownerReceiveBatch, ZLINK_BACKEND_RECV_DONT_WAIT);
426
- if (received.ok) {
427
- // The bounded batch stays in claim order until its records finish.
428
- try {
429
- for (const record of received.records) {
430
- if (this.disposed) break;
431
- const permit = record.applicationJobPermit ?? claimPermit;
432
- if (owner.ordinaryIngressPreAdmitted === true && permit === undefined) {
433
- throw new Error(
434
- 'Pre-admitted raw ingress record lost its Application Job Queue permit.'
435
- );
436
- }
437
- this.recordsSinceYield += 1;
438
- if (permit !== undefined) {
439
- if (domain === ReadyDomain.Application && record.applicationJobPermit === undefined)
440
- permit.markApplicationQueued();
441
- // The scope now owns this reservation, including failure
442
- // and detached handler handoff. Only unused permits remain
443
- // owned by the receive attempt's finally block.
444
- if (permit === claimPermit) claimPermit = undefined;
445
- }
446
- // The record's terminal and the permit turn release follow the
447
- // handler in this turn's own continuation.
448
- if (record.prepareDispatch !== undefined) {
449
- try {
450
- const stopSignal = this.capacityStop.signal;
451
- const preparation = record.prepareDispatch(stopSignal);
452
- const accepted = preparation instanceof Promise ? await preparation : preparation;
453
- if (!accepted || stopSignal.aborted) {
454
- releaseApplicationJobPermitTurn(permit);
455
- continue;
456
- }
457
- } catch (error) {
458
- this.failRecord(error, record, permit);
459
- continue;
460
- }
461
- }
462
- const dispatched = this.dispatchRecord(owner, record, permit);
463
- if (dispatched === false) continue;
464
- if (dispatched !== true) {
465
- try {
466
- await dispatched;
467
- } catch (error) {
468
- this.failRecord(error, record, permit);
469
- continue;
470
- }
471
- }
472
- const finished = this.finishRecord(record, permit);
473
- if (finished !== undefined) await finished;
474
- }
475
- } finally {
476
- // Batch ownership includes records whose dispatch never began,
477
- // including on failure or shutdown in the middle of the batch.
478
- for (const record of received.records) {
479
- for (const part of record.parts) part.close();
480
- record.releaseRetainedIngress?.();
481
- }
604
+ // Ownership includes records whose dispatch never began on failure or shutdown.
605
+ const records = state.records;
606
+ if (records !== undefined) {
607
+ for (let recordIndex = 0; recordIndex < records.length; recordIndex += 1) {
608
+ const record = records[recordIndex]!;
609
+ // Started Node and Channel records are cleaned up at their own terminals.
610
+ if (recordIndex < state.index && isNodeOrChannelRecord(record)) continue;
611
+ this.releaseRecord(record);
482
612
  }
483
613
  }
484
614
  } finally {
485
- claimPermit?.releaseAfterInternalProcessing();
615
+ state.claimPermit?.releaseAfterInternalProcessing();
486
616
  }
487
617
  } finally {
488
- claim.release();
489
- if (receiveBatch === undefined) ownerReceiveBatch?.close();
618
+ try {
619
+ state.claim!.release();
620
+ } finally {
621
+ try {
622
+ if (state.suppliedReceiveBatch === undefined) state.receiveBatch?.close();
623
+ } finally {
624
+ // An idle worker must not retain the previous claim's payload or owner.
625
+ state.records = undefined;
626
+ state.owner = undefined;
627
+ state.claim = undefined;
628
+ state.claimPermit = undefined;
629
+ }
630
+ }
490
631
  }
491
- const yieldTurn = this.yieldIfNeeded();
492
- if (yieldTurn !== undefined) await yieldTurn;
493
632
  }
494
633
 
495
634
  /**
@@ -557,3 +696,12 @@ function yieldToEventLoop(): Promise<void> {
557
696
  function yieldToTimers(): Promise<void> {
558
697
  return new Promise((resolve) => setTimeout(resolve, 0));
559
698
  }
699
+
700
+ function isNodeOrChannelRecord(record: ReceiveRecord): boolean {
701
+ return (
702
+ record.kind === ReceiveKind.NodeSend ||
703
+ record.kind === ReceiveKind.NodeRequest ||
704
+ record.kind === ReceiveKind.ChannelSend ||
705
+ record.kind === ReceiveKind.ChannelRequest
706
+ );
707
+ }
@@ -1,5 +1,6 @@
1
1
  import { constants as osConstants } from 'node:os';
2
- import { waitRequestReply } from '../../messaging/request-deadline';
2
+ import type { PendingOperation } from '../../foundation/operation-registry';
3
+ import { remainingRequestTimeout } from '../../messaging/request-deadline';
3
4
  import {
4
5
  requireClassicFanoutCompletion,
5
6
  ZLinkSubmitStatus
@@ -179,14 +180,15 @@ export function submitBindingSyncSend(
179
180
  }
180
181
  }
181
182
 
182
- export async function submitBindingRequest(
183
+ export function submitBindingRequest(
183
184
  operation: ZLinkBindingRequestOperation,
184
185
  payload: unknown,
185
186
  timeoutMs: number | undefined,
186
- recordReceived?: () => void,
187
- onAdmitted?: () => void
188
- ): Promise<readonly unknown[]> {
189
- const deadlineMs = timeoutMs === undefined ? undefined : performance.now() + timeoutMs;
187
+ recordReceived: (() => void) | undefined,
188
+ onAdmitted: (() => void) | undefined,
189
+ pending: PendingOperation<unknown>,
190
+ receiver: import('../../foundation/operation-registry').OperationObserver<unknown, unknown>
191
+ ): void {
190
192
  try {
191
193
  let current: ZLinkBindingRequestSubmitOperation | undefined;
192
194
  if (Array.isArray(payload)) {
@@ -200,45 +202,53 @@ export async function submitBindingRequest(
200
202
  }
201
203
  current ??= operation.message(Buffer.alloc(0));
202
204
  if (timeoutMs !== undefined) {
203
- current = current.timeout(timeoutMs);
205
+ current = current.timeout(
206
+ Math.min(timeoutMs, remainingRequestTimeout('Request', pending.deadlineMs) ?? timeoutMs)
207
+ );
204
208
  }
205
- return await bindingRequestReply(current.submit(), deadlineMs, recordReceived, onAdmitted);
209
+ bindingRequestReply(current.submit(), receiver, pending, recordReceived, onAdmitted);
206
210
  } catch (error) {
207
- throw translateBindingResultError(error);
211
+ receiver.operationFailed(pending.id, translateBindingResultError(error), undefined);
208
212
  }
209
213
  }
210
214
 
211
- export async function bindingRequestReply(
215
+ export function bindingRequestReply(
212
216
  submission: import('@zlink-systems/zlink').RequestSubmission,
213
- deadlineMs: number | undefined,
217
+ receiver: import('../../foundation/operation-registry').OperationObserver<unknown, unknown>,
218
+ pending: PendingOperation<unknown>,
214
219
  recordReceived?: () => void,
215
220
  onAdmitted?: () => void
216
- ): Promise<import('@zlink-systems/zlink').Message[]> {
217
- const reply = submission.reply;
221
+ ): void {
222
+ // The physical receiver remains reachable independently of admission failure.
223
+ void submission.reply.then(
224
+ (replies) => {
225
+ try {
226
+ recordReceived?.();
227
+ } catch (error) {
228
+ receiver.operationFailed(pending.id, error, undefined);
229
+ }
230
+ receiver.operationCompleted(pending.id, replies, undefined);
231
+ },
232
+ (error) => receiver.operationFailed(pending.id, translateBindingResultError(error), undefined)
233
+ );
218
234
  if (submission.result === SubmitResult.Backpressured) {
235
+ void submission.admitted.then(
236
+ () => {
237
+ try {
238
+ onAdmitted?.();
239
+ } catch (error) {
240
+ receiver.operationFailed(pending.id, error, undefined);
241
+ }
242
+ },
243
+ (error) => receiver.operationFailed(pending.id, error, undefined)
244
+ );
245
+ } else {
219
246
  try {
220
- const [, replies] = await waitRequestReply(
221
- Promise.all([submission.admitted.then(() => onAdmitted?.()), reply]),
222
- 'Request',
223
- deadlineMs
224
- );
225
- recordReceived?.();
226
- return replies;
247
+ onAdmitted?.();
227
248
  } catch (error) {
228
- void reply.then(
229
- (parts) => {
230
- recordReceived?.();
231
- closeBindingReply(parts);
232
- },
233
- () => undefined
234
- );
235
- throw error;
249
+ receiver.operationFailed(pending.id, error, undefined);
236
250
  }
237
251
  }
238
- onAdmitted?.();
239
- const replies = await reply;
240
- recordReceived?.();
241
- return replies;
242
252
  }
243
253
 
244
254
  export function closeBindingReply(