@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,3 +1,7 @@
1
+ import { requestTerminalError } from '../messaging/request-deadline';
2
+ import type { PendingOperation } from './operation-registry';
3
+ import type { RequestRuntime } from './request-runtime';
4
+ import { inspectRuntime } from '../internal-observation';
1
5
  import { awaitWithAbort, isAbortError } from '../abort';
2
6
  import { decodeChannelHeader } from '../channels/channel-envelope';
3
7
  import { ZLinkBufferMessage } from '../backend/runtime-message';
@@ -19,7 +23,7 @@ import {
19
23
  ZLinkDispatchMessageKind,
20
24
  ZLinkRuntimeMessageFlowOutcome as ZLinkMessageFlowOutcome
21
25
  } from '../../contracts/Dispatch/ZLinkDispatchOptions';
22
- import { requestDurableService } from './durable-service-request';
26
+ import { admitServiceRequest, requestDurableService } from './durable-service-request';
23
27
  import { shouldCompactBackingArray } from '../admission';
24
28
  import { RequestResult, SubmitResult, isZLinkBackendResultError } from '../backend/runtime-values';
25
29
  import type { ZLinkDispatchErrorReporter } from '../channels/dispatch-error-reporter';
@@ -38,7 +42,7 @@ import {
38
42
  type ActorJoin28
39
43
  } from '../protocol/service_wire_pilot_codec.generated';
40
44
  import { canonicalActorJoinHandoffId, routingIdBytes } from './actor-join-recovery-codec';
41
- import { OperationRegistry } from './operation-registry';
45
+ import { OperationCancelledError, OperationRegistry } from './operation-registry';
42
46
  import {
43
47
  MessageFollowSuppressionRegistry,
44
48
  type MessageFollowSuppressionFence
@@ -119,12 +123,14 @@ import {
119
123
  SERVICE_WIRE_MAJOR,
120
124
  SERVICE_FRAMEWORK_MULTIPART_CONTENT_TYPE
121
125
  } from './service-wire-constants.generated';
126
+ import { copyPayloadBytes } from '../../contracts/Common/payload-slab';
122
127
  import {
123
128
  ServiceWireProtocolError,
124
129
  decodeApplicationPayload,
125
130
  decodeApplicationPayloadView,
126
131
  decodeMultipartApplicationParts,
127
132
  encodeApplicationPayload,
133
+ encodeOwnedApplicationPayload,
128
134
  type ServiceApplicationPayload
129
135
  } from './service-wire-m6a-codec';
130
136
 
@@ -163,6 +169,7 @@ interface ServiceSpotMessageFollowState {
163
169
  export interface ServiceStatefulResult {
164
170
  readonly terminalResult: number;
165
171
  readonly failureCode: number;
172
+ readonly failureMessage?: string;
166
173
  readonly payload?: ServiceApplicationPayload;
167
174
  readonly kindData?: ReceiveKindData;
168
175
  readonly applicationMetadata?: Buffer;
@@ -173,7 +180,7 @@ export interface ServiceStatefulResult {
173
180
  };
174
181
  }
175
182
 
176
- export interface ServiceStatefulPendingOperation {
183
+ export interface ServiceStatefulPendingOperation extends PendingOperation<ServiceStatefulResult> {
177
184
  readonly id: bigint;
178
185
  readonly promise: Promise<ServiceStatefulResult>;
179
186
  }
@@ -442,6 +449,28 @@ export interface ServiceUserSpotOperationHandler {
442
449
  * remain in the common mailbox, where a claimed Spot or Actor owner is serial.
443
450
  */
444
451
  export class ServiceStatefulRuntime {
452
+ [inspectRuntime]() {
453
+ return Object.freeze({
454
+ canonicalActorJoinHandoffs: this.canonicalActorJoinHandoffs.size,
455
+ spotRoutes: this.spotRoutes.size,
456
+ instanceRoute: (spotId: string) => {
457
+ const route = this.instanceIntents.get(spotId)?.route;
458
+ return route === undefined ? undefined : Object.freeze({ ...route });
459
+ },
460
+ directSpotRoute: (spotId: string) => {
461
+ const route = this.directSpotRoutes.get(directSpotKey(spotId));
462
+ return route === undefined
463
+ ? undefined
464
+ : Object.freeze({ ...route, spot: Object.freeze({ ...route.spot }) });
465
+ },
466
+ spotMessageFollow: Object.freeze(
467
+ [...this.spotMessageFollow.values()].map((state) =>
468
+ Object.freeze({ queuedCount: state.queuedCount, queuedBytes: state.queuedBytes })
469
+ )
470
+ )
471
+ });
472
+ }
473
+
445
474
  // Captured at module load, before any application turn exists: running a
446
475
  // callback through this snapshot detaches every AsyncLocalStorage context
447
476
  // (Spot serial turn, execution area, flow) so local loopback ingress
@@ -450,7 +479,7 @@ export class ServiceStatefulRuntime {
450
479
 
451
480
  readonly registry: ServiceStatefulRegistry;
452
481
 
453
- private readonly operations: ServiceTerminalOperationRegistry<ServiceStatefulResult, bigint>;
482
+ readonly operations: ServiceTerminalOperationRegistry<ServiceStatefulResult, bigint>;
454
483
  private readonly sessionDeliveries = new Map<string, ServiceSessionDelivery>();
455
484
  /**
456
485
  * A local Actor owner can replace its own session binding before the
@@ -494,7 +523,7 @@ export class ServiceStatefulRuntime {
494
523
  private dispatchErrors?: ZLinkDispatchErrorReporter;
495
524
  private sessionOwnerDescriptors?: ServiceSessionOwnerDescriptors;
496
525
  private dispatchErrorMeshName?: string;
497
- private readonly admittedUserSpotOperations = new Map<
526
+ readonly admittedUserSpotOperations = new Map<
498
527
  string,
499
528
  {
500
529
  readonly request: string;
@@ -517,10 +546,15 @@ export class ServiceStatefulRuntime {
517
546
  private readonly raw: RawServiceMeshRuntime,
518
547
  readonly nodeRid: string,
519
548
  readonly nodeGeneration: bigint,
520
- onPendingOperationsChanged?: () => void
549
+ onPendingOperationsChanged?: () => void,
550
+ private readonly requests?: RequestRuntime
521
551
  ) {
522
552
  this.operations = new ServiceTerminalOperationRegistry(
523
- new OperationRegistry(undefined, onPendingOperationsChanged)
553
+ requests?.operations<ServiceStatefulResult, bigint>() ??
554
+ new OperationRegistry(undefined, onPendingOperationsChanged, (reason) =>
555
+ requestTerminalError('Request', reason)
556
+ ),
557
+ requests === undefined ? undefined : () => {}
524
558
  );
525
559
  this.registry = new ServiceStatefulRegistry(nodeRid, nodeGeneration);
526
560
  this.registry.createEntrySpot(nodeRid);
@@ -1519,15 +1553,18 @@ export class ServiceStatefulRuntime {
1519
1553
  requested: ServiceDirectSpotRouteFence,
1520
1554
  payload: ServiceApplicationPayload,
1521
1555
  timeoutMs: number,
1522
- onAdmitted?: () => void
1556
+ onAdmitted?: () => void,
1557
+ requestOperation?: PendingOperation<unknown>,
1558
+ receiver?: import('./operation-registry').OperationObserver<unknown, unknown>
1523
1559
  ): ServiceStatefulPendingOperation {
1524
- const pending = this.operations.register(timeoutMs);
1560
+ const pending =
1561
+ (requestOperation as PendingOperation<ServiceStatefulResult> | undefined) ??
1562
+ this.operations.register(timeoutMs);
1525
1563
  const target = this.acceptSpotAuthority(requested);
1526
1564
  if (target === undefined) {
1527
- this.operations.reply(
1528
- pending.id,
1529
- internalFrameworkWireReply(ZLinkFrameworkInternalErrorKind.ActorLocationStale)
1530
- );
1565
+ const result = internalFrameworkWireReply(ZLinkFrameworkInternalErrorKind.ActorLocationStale);
1566
+ if (receiver === undefined) pending.reply(result);
1567
+ else receiver.operationCompleted(pending.id, result, undefined);
1531
1568
  return pending;
1532
1569
  }
1533
1570
  const header = encodeSpotHeader('spotRequest', sourceSpotId, target, pending.id, {
@@ -1541,7 +1578,8 @@ export class ServiceStatefulRuntime {
1541
1578
  timeoutMs,
1542
1579
  'spotRequest',
1543
1580
  undefined,
1544
- onAdmitted
1581
+ onAdmitted,
1582
+ receiver
1545
1583
  );
1546
1584
  return pending;
1547
1585
  }
@@ -1578,16 +1616,20 @@ export class ServiceStatefulRuntime {
1578
1616
  sourceActor?: ServiceActorRef,
1579
1617
  boundSession?: { readonly sessionRid: string; readonly bindingGeneration: bigint },
1580
1618
  onAdmitted?: () => void,
1581
- routeFence?: ServiceActorRouteFence
1619
+ routeFence?: ServiceActorRouteFence,
1620
+ requestOperation?: PendingOperation<unknown>,
1621
+ receiver?: import('./operation-registry').OperationObserver<unknown, unknown>
1582
1622
  ): ServiceStatefulPendingOperation {
1583
1623
  const operationLow = this.nextMessageFollowOperation++;
1584
- const pending = this.operations.register(timeoutMs, 'registry', operationLow);
1624
+ const pending =
1625
+ (requestOperation as PendingOperation<ServiceStatefulResult> | undefined) ??
1626
+ this.operations.register(timeoutMs, 'registry', operationLow);
1627
+ this.operations.setContext(pending.id, operationLow);
1585
1628
  const route = routeFence ?? this.tryActorFence(target);
1586
1629
  if (route === undefined) {
1587
- this.operations.reply(
1588
- pending.id,
1589
- internalFrameworkWireReply(ZLinkFrameworkInternalErrorKind.ActorLocationStale)
1590
- );
1630
+ const result = internalFrameworkWireReply(ZLinkFrameworkInternalErrorKind.ActorLocationStale);
1631
+ if (receiver !== undefined) receiver.operationCompleted(pending.id, result, undefined);
1632
+ else pending.reply(result);
1591
1633
  return pending;
1592
1634
  }
1593
1635
  const header = encodeActorHeader(
@@ -1610,7 +1652,8 @@ export class ServiceStatefulRuntime {
1610
1652
  timeoutMs,
1611
1653
  'actorRequest',
1612
1654
  undefined,
1613
- onAdmitted
1655
+ onAdmitted,
1656
+ receiver
1614
1657
  );
1615
1658
  return pending;
1616
1659
  }
@@ -1712,9 +1755,13 @@ export class ServiceStatefulRuntime {
1712
1755
  sourceSpotId?: string,
1713
1756
  metadataFrame?: Uint8Array,
1714
1757
  instanceIntent = false,
1715
- onAdmitted?: () => void
1758
+ onAdmitted?: () => void,
1759
+ requestOperation?: PendingOperation<unknown>,
1760
+ receiver?: import('./operation-registry').OperationObserver<unknown, unknown>
1716
1761
  ): ServiceStatefulPendingOperation {
1717
- const pending = this.operations.register(timeoutMs);
1762
+ const pending =
1763
+ (requestOperation as PendingOperation<ServiceStatefulResult> | undefined) ??
1764
+ this.operations.register(timeoutMs);
1718
1765
  this.submitRequest(
1719
1766
  pending,
1720
1767
  route.targetNodeRid,
@@ -1738,7 +1785,8 @@ export class ServiceStatefulRuntime {
1738
1785
  timeoutMs,
1739
1786
  'instanceSpotRequest',
1740
1787
  undefined,
1741
- onAdmitted
1788
+ onAdmitted,
1789
+ receiver
1742
1790
  );
1743
1791
  return pending;
1744
1792
  }
@@ -1748,7 +1796,8 @@ export class ServiceStatefulRuntime {
1748
1796
  payload: ServiceApplicationPayload,
1749
1797
  timeoutMs: number,
1750
1798
  sourceSpotId?: string,
1751
- metadataFrame?: Uint8Array
1799
+ metadataFrame?: Uint8Array,
1800
+ requestOperation?: PendingOperation<unknown>
1752
1801
  ): ServiceStatefulPendingOperation {
1753
1802
  const deadlineUnixMs = BigInt(Date.now() + timeoutMs);
1754
1803
  const payloadFrame = encodeApplicationPayload(payload);
@@ -1757,7 +1806,9 @@ export class ServiceStatefulRuntime {
1757
1806
  payloadFrame,
1758
1807
  deadlineUnixMs,
1759
1808
  sourceSpotId,
1760
- metadataFrame
1809
+ metadataFrame,
1810
+ undefined,
1811
+ requestOperation
1761
1812
  );
1762
1813
  }
1763
1814
 
@@ -1767,10 +1818,13 @@ export class ServiceStatefulRuntime {
1767
1818
  deadlineUnixMs: bigint,
1768
1819
  sourceSpotId?: string,
1769
1820
  metadataFrame?: Uint8Array,
1770
- onAdmitted?: () => void
1821
+ onAdmitted?: () => void,
1822
+ requestOperation?: PendingOperation<unknown>
1771
1823
  ): ServiceStatefulPendingOperation {
1772
1824
  const timeoutMs = remainingDeadlineMs(deadlineUnixMs);
1773
- const pending = this.operations.register(timeoutMs);
1825
+ const pending =
1826
+ (requestOperation as PendingOperation<ServiceStatefulResult> | undefined) ??
1827
+ this.operations.register(timeoutMs);
1774
1828
  this.submitRequest(
1775
1829
  pending,
1776
1830
  target.targetNodeRid,
@@ -1822,9 +1876,9 @@ export class ServiceStatefulRuntime {
1822
1876
  queueMicrotask(() => {
1823
1877
  try {
1824
1878
  this.registry.destroyActor(actor);
1825
- this.operations.reply(pending.id, { terminalResult: RequestResult.Ok, failureCode: 0 });
1879
+ pending.reply({ terminalResult: RequestResult.Ok, failureCode: 0 });
1826
1880
  } catch (error) {
1827
- this.operations.reply(pending.id, failure(error));
1881
+ pending.reply(failure(error));
1828
1882
  }
1829
1883
  });
1830
1884
  return pending;
@@ -1843,10 +1897,7 @@ export class ServiceStatefulRuntime {
1843
1897
  timeoutMs: number
1844
1898
  ): ServiceStatefulPendingOperation {
1845
1899
  const deadlineMs = performance.now() + timeoutMs;
1846
- const pending = this.operations.register(
1847
- timeoutMs,
1848
- targetNodeRid === this.nodeRid ? 'registry' : 'sender'
1849
- );
1900
+ const pending = this.operations.register(timeoutMs, 'registry', undefined, deadlineMs);
1850
1901
  const target = this.trySpotFence(targetNodeRid, {
1851
1902
  ...targetSpot,
1852
1903
  generation: targetSpotGeneration
@@ -1866,10 +1917,7 @@ export class ServiceStatefulRuntime {
1866
1917
  timeoutMs: number
1867
1918
  ): ServiceStatefulPendingOperation {
1868
1919
  const deadlineMs = performance.now() + timeoutMs;
1869
- const pending = this.operations.register(
1870
- timeoutMs,
1871
- targetNodeRid === this.nodeRid ? 'registry' : 'sender'
1872
- );
1920
+ const pending = this.operations.register(timeoutMs, 'registry', undefined, deadlineMs);
1873
1921
  const target = this.trySpotFence(targetNodeRid, {
1874
1922
  ...targetSpot,
1875
1923
  generation: targetSpotGeneration
@@ -1889,10 +1937,7 @@ export class ServiceStatefulRuntime {
1889
1937
  timeoutMs: number
1890
1938
  ): ServiceStatefulPendingOperation {
1891
1939
  const deadlineMs = performance.now() + timeoutMs;
1892
- const pending = this.operations.register(
1893
- timeoutMs,
1894
- targetNodeRid === this.nodeRid ? 'registry' : 'sender'
1895
- );
1940
+ const pending = this.operations.register(timeoutMs, 'registry', undefined, deadlineMs);
1896
1941
  this.submitActorJoin(
1897
1942
  pending,
1898
1943
  actor,
@@ -1913,10 +1958,7 @@ export class ServiceStatefulRuntime {
1913
1958
  timeoutMs: number
1914
1959
  ): ServiceStatefulPendingOperation {
1915
1960
  const deadlineMs = performance.now() + timeoutMs;
1916
- const pending = this.operations.register(
1917
- timeoutMs,
1918
- targetNodeRid === this.nodeRid ? 'registry' : 'sender'
1919
- );
1961
+ const pending = this.operations.register(timeoutMs, 'registry', undefined, deadlineMs);
1920
1962
  this.submitActorJoin(
1921
1963
  pending,
1922
1964
  actor,
@@ -1951,9 +1993,9 @@ export class ServiceStatefulRuntime {
1951
1993
  currentMembershipEpoch: transition.currentMembershipEpoch,
1952
1994
  resultCode: 0
1953
1995
  });
1954
- this.operations.reply(pending.id, { terminalResult: RequestResult.Ok, failureCode: 0 });
1996
+ pending.reply({ terminalResult: RequestResult.Ok, failureCode: 0 });
1955
1997
  } catch (error) {
1956
- this.operations.reply(pending.id, failure(error));
1998
+ pending.reply(failure(error));
1957
1999
  }
1958
2000
  });
1959
2001
  return pending;
@@ -1969,11 +2011,10 @@ export class ServiceStatefulRuntime {
1969
2011
  close?: () => Promise<void>
1970
2012
  ): ServiceStatefulPendingOperation {
1971
2013
  const deadlineMs = performance.now() + timeoutMs;
1972
- const pending = this.operations.register(timeoutMs, 'sender');
2014
+ const pending = this.operations.register(timeoutMs, 'registry', undefined, deadlineMs);
1973
2015
  const sessionOwner = this.localSessionOwner();
1974
2016
  if (sessionOwner === undefined) {
1975
- this.operations.reply(
1976
- pending.id,
2017
+ pending.reply(
1977
2018
  failure(
1978
2019
  createInternalFrameworkException(
1979
2020
  ZLinkFrameworkInternalErrorKind.RouteNotConnected,
@@ -2027,7 +2068,7 @@ export class ServiceStatefulRuntime {
2027
2068
  } else {
2028
2069
  this.sessionDeliveries.set(deliveryKey, { ...delivery, binding: previous });
2029
2070
  }
2030
- this.operations.reply(pending.id, {
2071
+ pending.reply({
2031
2072
  terminalResult: RequestResult.Ok,
2032
2073
  failureCode: 0
2033
2074
  });
@@ -2036,7 +2077,7 @@ export class ServiceStatefulRuntime {
2036
2077
  const binding = this.registry.installSessionBinding(localBinding);
2037
2078
  installedDelivery = { ...delivery, binding };
2038
2079
  this.sessionDeliveries.set(deliveryKey, installedDelivery);
2039
- this.operations.reply(pending.id, {
2080
+ pending.reply({
2040
2081
  terminalResult: RequestResult.Ok,
2041
2082
  failureCode: 0,
2042
2083
  kindData: undefined
@@ -2065,7 +2106,7 @@ export class ServiceStatefulRuntime {
2065
2106
  ) {
2066
2107
  this.sessionDeliveries.delete(deliveryKey);
2067
2108
  }
2068
- this.operations.reply(pending.id, failure(error));
2109
+ pending.reply(failure(error));
2069
2110
  }
2070
2111
  return pending;
2071
2112
  }
@@ -2079,7 +2120,7 @@ export class ServiceStatefulRuntime {
2079
2120
  generation
2080
2121
  });
2081
2122
  } catch (error) {
2082
- this.operations.fail(pending.id, error);
2123
+ pending.replyFailure(error);
2083
2124
  return pending;
2084
2125
  }
2085
2126
  void this.requestDurableOperation(
@@ -2087,13 +2128,12 @@ export class ServiceStatefulRuntime {
2087
2128
  [header],
2088
2129
  pending.id,
2089
2130
  'streamBind',
2090
- deadlineMs
2131
+ pending
2091
2132
  ).then(
2092
2133
  (reply) => this.completeRemoteReply(pending, actor.nodeRid, 'streamBind', undefined, reply),
2093
- (error) => this.operations.fail(pending.id, error)
2134
+ (error) => pending.replyFailure(error)
2094
2135
  );
2095
- return {
2096
- id: pending.id,
2136
+ return Object.assign(Object.create(pending) as ServiceStatefulPendingOperation, {
2097
2137
  promise: pending.promise.then((result) => {
2098
2138
  if (result.terminalResult === RequestResult.Ok && result.streamBinding !== undefined) {
2099
2139
  const committed: ServiceSessionDelivery = {
@@ -2125,7 +2165,7 @@ export class ServiceStatefulRuntime {
2125
2165
  }
2126
2166
  return result;
2127
2167
  })
2128
- };
2168
+ });
2129
2169
  }
2130
2170
 
2131
2171
  closeBoundSession(
@@ -2136,8 +2176,7 @@ export class ServiceStatefulRuntime {
2136
2176
  const pending = this.operations.register(timeoutMs);
2137
2177
  const binding = this.registry.binding(actor);
2138
2178
  if (binding === undefined) {
2139
- this.operations.reply(
2140
- pending.id,
2179
+ pending.reply(
2141
2180
  internalFrameworkWireReply(ZLinkFrameworkInternalErrorKind.ActorSessionNotBound)
2142
2181
  );
2143
2182
  return pending;
@@ -2165,8 +2204,14 @@ export class ServiceStatefulRuntime {
2165
2204
  )[0]!
2166
2205
  );
2167
2206
  const reply = routingIdsEqual(binding.sessionOwnerNodeRid, this.nodeRid)
2168
- ? this.requestLocalInfrastructure(header, pending.id, timeoutMs)
2169
- : this.raw.requestService(binding.sessionOwnerNodeRid, [header], timeoutMs);
2207
+ ? this.requestLocalInfrastructure(header, pending.id, pending)
2208
+ : requestDurableService(
2209
+ this.raw,
2210
+ binding.sessionOwnerNodeRid,
2211
+ [header],
2212
+ pending,
2213
+ 'boundSessionClose'
2214
+ );
2170
2215
  void reply.then(
2171
2216
  (parts) =>
2172
2217
  this.completeRemoteReply(
@@ -2176,7 +2221,7 @@ export class ServiceStatefulRuntime {
2176
2221
  undefined,
2177
2222
  parts
2178
2223
  ),
2179
- (error) => this.operations.fail(pending.id, error)
2224
+ (error) => pending.replyFailure(error)
2180
2225
  );
2181
2226
  return pending;
2182
2227
  }
@@ -2194,19 +2239,16 @@ export class ServiceStatefulRuntime {
2194
2239
  !routingIdsEqual(delivery.binding.sessionRid, sessionRid) ||
2195
2240
  delivery.binding.bindingGeneration !== expectedBindingGeneration
2196
2241
  ) {
2197
- this.operations.reply(
2198
- pending.id,
2199
- internalFrameworkWireReply(ZLinkFrameworkInternalErrorKind.ActorLocationStale)
2200
- );
2242
+ pending.reply(internalFrameworkWireReply(ZLinkFrameworkInternalErrorKind.ActorLocationStale));
2201
2243
  return pending;
2202
2244
  }
2203
2245
  this.sessionDeliveries.delete(actorKey(actor));
2204
2246
  if (actor.nodeRid === this.nodeRid) {
2205
2247
  try {
2206
2248
  this.registry.unbindSession(actor, expectedBindingGeneration);
2207
- this.operations.reply(pending.id, { terminalResult: RequestResult.Ok, failureCode: 0 });
2249
+ pending.reply({ terminalResult: RequestResult.Ok, failureCode: 0 });
2208
2250
  } catch (error) {
2209
- this.operations.reply(pending.id, failure(error));
2251
+ pending.reply(failure(error));
2210
2252
  }
2211
2253
  return pending;
2212
2254
  }
@@ -2278,7 +2320,9 @@ export class ServiceStatefulRuntime {
2278
2320
  }
2279
2321
 
2280
2322
  expireOperations(nowMs: number, turnDeadlineMs: number): number {
2281
- return this.operations.expire(nowMs, turnDeadlineMs);
2323
+ return this.requests === undefined && nowMs >= this.operations.nextDeadlineMs()
2324
+ ? this.operations.expire(nowMs, turnDeadlineMs)
2325
+ : 0;
2282
2326
  }
2283
2327
 
2284
2328
  get pendingOperationCount(): number {
@@ -2287,7 +2331,7 @@ export class ServiceStatefulRuntime {
2287
2331
 
2288
2332
  /** The next stateful request expiry, as a lower bound. */
2289
2333
  nextMaintenanceDeadlineMs(): number {
2290
- return this.operations.nextDeadlineMs();
2334
+ return this.requests === undefined ? this.operations.nextDeadlineMs() : Infinity;
2291
2335
  }
2292
2336
 
2293
2337
  close(): void {
@@ -2396,7 +2440,7 @@ export class ServiceStatefulRuntime {
2396
2440
  ? record.parts.length >= 2
2397
2441
  ? record.parts[record.parts.length - 1]
2398
2442
  : undefined
2399
- : encodeApplicationPayload(canonicalPayload);
2443
+ : encodeOwnedApplicationPayload(canonicalPayload);
2400
2444
  try {
2401
2445
  return await this.handleIngress(
2402
2446
  record,
@@ -2462,7 +2506,7 @@ export class ServiceStatefulRuntime {
2462
2506
  }
2463
2507
  }
2464
2508
 
2465
- private async handleIngress(
2509
+ async handleIngress(
2466
2510
  ingress: RawServiceIngressRecord,
2467
2511
  record: ServiceStatefulWireRecord,
2468
2512
  payloadFrame: Buffer | undefined,
@@ -2555,6 +2599,62 @@ export class ServiceStatefulRuntime {
2555
2599
  ) {
2556
2600
  throw new ServiceStaleGenerationError('binding', record.target.actor.actorId);
2557
2601
  }
2602
+ if (
2603
+ !this.registry.acceptBoundSessionSequence(
2604
+ record.target.actor,
2605
+ record.boundSession.bindingGeneration,
2606
+ record.boundSession.sequence
2607
+ )
2608
+ ) {
2609
+ const error = new ZLinkFrameworkException(
2610
+ ZLinkFrameworkErrorKind.InvalidOperation,
2611
+ 'Bound Session relay sequence does not increase.'
2612
+ );
2613
+ const reporter = this.dispatchErrors;
2614
+ if (record.kind === 'actorRequest') {
2615
+ if (reporter?.captureEnabled() === true) {
2616
+ reporter.report({
2617
+ surface: ZLinkDispatchErrorSurface.StreamSession,
2618
+ messageKind: ZLinkDispatchMessageKind.Request,
2619
+ reason: ZLinkDispatchErrorReason.StaleTarget,
2620
+ action: ZLinkDispatchErrorAction.ReplyError,
2621
+ meshName: this.dispatchErrorMeshName,
2622
+ sourceRid: ingress.sourceRoutingId,
2623
+ actorId: record.target.actor.actorId,
2624
+ correlationId: record.correlation?.toString(),
2625
+ error
2626
+ });
2627
+ }
2628
+ const result = failure(error);
2629
+ this.replyWire(
2630
+ ingress,
2631
+ record.correlation!,
2632
+ result.terminalResult,
2633
+ result.failureCode
2634
+ );
2635
+ return 'infrastructure';
2636
+ }
2637
+ const tracePoint = flowIfEnabled(reporter?.flow, ZLinkMessageFlowOutcome.Dropped);
2638
+ if (tracePoint !== undefined) {
2639
+ tracePoint.trace({
2640
+ outcome: ZLinkMessageFlowOutcome.Dropped,
2641
+ surface: ZLinkDispatchErrorSurface.StreamSession,
2642
+ messageKind: ZLinkDispatchMessageKind.Send,
2643
+ packetName: decodeApplicationPayloadView(payloadFrame!).packetName,
2644
+ ...(this.dispatchErrorMeshName === undefined
2645
+ ? {}
2646
+ : { meshName: this.dispatchErrorMeshName }),
2647
+ ...(record.correlation === undefined
2648
+ ? {}
2649
+ : { correlationId: record.correlation.toString() }),
2650
+ sourceRid: ingress.sourceRoutingId,
2651
+ actorId: record.target.actor.actorId,
2652
+ streamSessionId: record.boundSession.sessionRid,
2653
+ errorReason: ZLinkDispatchErrorReason.StaleTarget
2654
+ });
2655
+ }
2656
+ return 'application';
2657
+ }
2558
2658
  }
2559
2659
  return this.enqueueApplicationFrame(
2560
2660
  ingress,
@@ -2714,7 +2814,7 @@ export class ServiceStatefulRuntime {
2714
2814
  return !lifecycle.isMaterialized(applicationTarget);
2715
2815
  }
2716
2816
 
2717
- private enqueueActivatedInstanceSpot(
2817
+ enqueueActivatedInstanceSpot(
2718
2818
  ingress: RawServiceIngressRecord,
2719
2819
  record: Extract<ServiceStatefulWireRecord, { readonly kind: 'instanceSpot' }>,
2720
2820
  payloadFrame: Buffer,
@@ -2795,7 +2895,7 @@ export class ServiceStatefulRuntime {
2795
2895
  return result;
2796
2896
  }
2797
2897
 
2798
- private async continueMissingInstanceActivation(
2898
+ async continueMissingInstanceActivation(
2799
2899
  ingress: RawServiceIngressRecord,
2800
2900
  record: Extract<
2801
2901
  ServiceStatefulWireRecord,
@@ -2894,7 +2994,7 @@ export class ServiceStatefulRuntime {
2894
2994
  * record only of a message whose handler turn started before it; a message queued
2895
2995
  * behind that Close is not counted, so it cannot hold the Close it follows.
2896
2996
  */
2897
- private activationTerminalCompletion(
2997
+ activationTerminalCompletion(
2898
2998
  target: ServiceInstanceActivationTarget,
2899
2999
  route: ServiceInstanceRouteFence
2900
3000
  ): {
@@ -2941,7 +3041,7 @@ export class ServiceStatefulRuntime {
2941
3041
  return { onTerminalCompletion, onHandlerTurnStarted };
2942
3042
  }
2943
3043
 
2944
- private instanceApplicationTerminalCompletion(
3044
+ instanceApplicationTerminalCompletion(
2945
3045
  target: ServiceInstanceApplicationTarget
2946
3046
  ): (() => Promise<void>) | undefined {
2947
3047
  const lifecycle = this.instanceApplicationLifecycle;
@@ -3011,7 +3111,7 @@ export class ServiceStatefulRuntime {
3011
3111
  for (const waiter of waiters) waiter();
3012
3112
  }
3013
3113
 
3014
- private finishMissingInstanceActivationFailure(
3114
+ finishMissingInstanceActivationFailure(
3015
3115
  ingress: RawServiceIngressRecord,
3016
3116
  record: Extract<
3017
3117
  ServiceStatefulWireRecord,
@@ -3179,7 +3279,7 @@ export class ServiceStatefulRuntime {
3179
3279
  return { intent, route: current };
3180
3280
  }
3181
3281
 
3182
- private validateInstanceIngress(
3282
+ validateInstanceIngress(
3183
3283
  ingress: RawServiceIngressRecord,
3184
3284
  record: Extract<ServiceStatefulWireRecord, { readonly kind: 'instanceSpot' }>
3185
3285
  ): void {
@@ -3281,7 +3381,7 @@ export class ServiceStatefulRuntime {
3281
3381
  : undefined;
3282
3382
  }
3283
3383
 
3284
- private activateMissingInstanceAsync(
3384
+ activateMissingInstanceAsync(
3285
3385
  record: Extract<
3286
3386
  ServiceStatefulWireRecord,
3287
3387
  { readonly kind: 'instanceSpot'; readonly activation: 'missing' }
@@ -3352,7 +3452,7 @@ export class ServiceStatefulRuntime {
3352
3452
  return operation;
3353
3453
  }
3354
3454
 
3355
- private async runMissingInstanceActivation(
3455
+ async runMissingInstanceActivation(
3356
3456
  record: Extract<
3357
3457
  ServiceStatefulWireRecord,
3358
3458
  { readonly kind: 'instanceSpot'; readonly activation: 'missing' }
@@ -3716,7 +3816,7 @@ export class ServiceStatefulRuntime {
3716
3816
  }
3717
3817
  })
3718
3818
  };
3719
- const applicationFrame = payloadFrame ?? encodeApplicationPayload(emptyPayload());
3819
+ const applicationFrame = payloadFrame ?? encodeOwnedApplicationPayload(emptyPayload());
3720
3820
  return this.enqueueLifecycleFrame(
3721
3821
  ingress,
3722
3822
  `spot:${record.target.spot.spotId}`,
@@ -4218,7 +4318,7 @@ export class ServiceStatefulRuntime {
4218
4318
  );
4219
4319
  }
4220
4320
 
4221
- private enqueueApplicationFrame(
4321
+ enqueueApplicationFrame(
4222
4322
  ingress: RawServiceIngressRecord,
4223
4323
  owner: string,
4224
4324
  payloadFrame: Buffer,
@@ -4302,7 +4402,7 @@ export class ServiceStatefulRuntime {
4302
4402
  channelName,
4303
4403
  topic,
4304
4404
  sourceSpotId,
4305
- encodeApplicationPayload(payload),
4405
+ encodeOwnedApplicationPayload(payload),
4306
4406
  sourceNodeRid,
4307
4407
  applicationJobOwner
4308
4408
  );
@@ -4644,34 +4744,52 @@ export class ServiceStatefulRuntime {
4644
4744
  operationKind: 'userSpotCreate' | 'userSpotClose' | 'actorCreate',
4645
4745
  timeoutMs: number
4646
4746
  ): Promise<ServiceUserSpotOperationResult> {
4647
- const parts = await this.requestDurableOperation(
4747
+ const deadlineMs = performance.now() + Math.max(1, timeoutMs);
4748
+ const pending = this.operations.register(
4749
+ Math.max(1, timeoutMs),
4750
+ 'registry',
4751
+ undefined,
4752
+ deadlineMs
4753
+ );
4754
+ const completed = (parts: readonly Buffer[]) => {
4755
+ try {
4756
+ if (parts.length < 1 || parts.length > 2) {
4757
+ throw new ServiceWireProtocolError('Invalid creation operation reply parts.');
4758
+ }
4759
+ const decoded = decodeStatefulReply(
4760
+ parts[0]!,
4761
+ correlation,
4762
+ operationKind,
4763
+ parts.length >= 2
4764
+ );
4765
+ if (decoded.terminalResult !== RequestResult.Ok && parts.length !== 1) {
4766
+ throw new ServiceWireProtocolError('Failed creation operation reply carries a payload.');
4767
+ }
4768
+ if (operationKind === 'userSpotClose' && parts.length !== 1) {
4769
+ throw new ServiceWireProtocolError('User Spot close reply carries a payload.');
4770
+ }
4771
+ const value: ServiceUserSpotOperationResult = {
4772
+ terminalResult: decoded.terminalResult,
4773
+ failureCode: decoded.failureCode,
4774
+ ...(decoded.tail === undefined ? {} : { tail: decoded.tail as never }),
4775
+ ...(parts.length === 2 ? { payload: decodeApplicationPayload(parts[1]!) } : {})
4776
+ };
4777
+ pending.complete(value);
4778
+ } catch (error) {
4779
+ pending.fail(translateWireReplyDecodeError(error));
4780
+ }
4781
+ };
4782
+ const failed = (error: unknown) => {
4783
+ pending.fail(error);
4784
+ };
4785
+ void this.requestDurableOperation(
4648
4786
  targetNodeRid,
4649
4787
  [header],
4650
4788
  correlation,
4651
4789
  operationKind,
4652
- performance.now() + Math.max(1, timeoutMs)
4653
- );
4654
- // A received envelope, including a decode failure, ends sender replay.
4655
- try {
4656
- if (parts.length < 1 || parts.length > 2) {
4657
- throw new ServiceWireProtocolError('Invalid creation operation reply parts.');
4658
- }
4659
- const decoded = decodeStatefulReply(parts[0]!, correlation, operationKind, parts.length >= 2);
4660
- if (decoded.terminalResult !== RequestResult.Ok && parts.length !== 1) {
4661
- throw new ServiceWireProtocolError('Failed creation operation reply carries a payload.');
4662
- }
4663
- if (operationKind === 'userSpotClose' && parts.length !== 1) {
4664
- throw new ServiceWireProtocolError('User Spot close reply carries a payload.');
4665
- }
4666
- return {
4667
- terminalResult: decoded.terminalResult,
4668
- failureCode: decoded.failureCode,
4669
- ...(decoded.tail === undefined ? {} : { tail: decoded.tail as never }),
4670
- ...(parts.length === 2 ? { payload: decodeApplicationPayload(parts[1]!) } : {})
4671
- };
4672
- } catch (error) {
4673
- throw translateWireReplyDecodeError(error);
4674
- }
4790
+ pending
4791
+ ).then(completed, failed);
4792
+ return pending.promise;
4675
4793
  }
4676
4794
 
4677
4795
  private async requestDurableOperation(
@@ -4679,44 +4797,31 @@ export class ServiceStatefulRuntime {
4679
4797
  parts: readonly Buffer[],
4680
4798
  correlation: bigint,
4681
4799
  operationKind: 'userSpotCreate' | 'userSpotClose' | 'actorCreate' | 'streamBind' | 'actorJoin',
4682
- deadlineMs: number
4800
+ pending: PendingOperation<unknown>
4683
4801
  ): Promise<readonly Buffer[]> {
4684
4802
  this.requireOpen();
4685
4803
  if (targetNodeRid === this.nodeRid) {
4686
- return this.requestLocalInfrastructure(
4687
- parts[0]!,
4688
- correlation,
4689
- Math.ceil(deadlineMs - performance.now())
4690
- );
4804
+ return this.requestLocalInfrastructure(parts[0]!, correlation, pending);
4691
4805
  }
4692
- return requestDurableService(this.raw, targetNodeRid, parts, deadlineMs, operationKind);
4806
+ return requestDurableService(this.raw, targetNodeRid, parts, pending, operationKind);
4693
4807
  }
4694
4808
 
4695
4809
  private requestLocalInfrastructure(
4696
4810
  header: Buffer,
4697
4811
  requestSequence: bigint,
4698
- timeoutMs: number
4812
+ pending: PendingOperation<unknown>
4699
4813
  ): Promise<readonly Buffer[]> {
4700
4814
  return new Promise((resolve, reject) => {
4701
- let settled = false;
4702
- const fail = (error: unknown) => {
4703
- if (settled) return;
4704
- settled = true;
4705
- clearTimeout(timer);
4706
- reject(error);
4707
- };
4708
- const timer = setTimeout(() => {
4709
- fail(new Error('Local infrastructure request timed out.'));
4710
- }, timeoutMs);
4711
- const finish = (parts: readonly Uint8Array[]) => {
4712
- if (settled) return;
4713
- settled = true;
4714
- clearTimeout(timer);
4815
+ const finish: NonNullable<ServiceMailboxRecord['reply']> = (parts) => {
4715
4816
  resolve(parts.map((part) => Buffer.from(part)));
4716
4817
  };
4717
4818
  void (async () => {
4718
4819
  const applicationJobOwner = await this.raw.reserveLocalIngress();
4719
4820
  try {
4821
+ if (!pending.isPending()) {
4822
+ await pending.promise;
4823
+ throw new OperationCancelledError(pending.id, 'Request is already terminal.');
4824
+ }
4720
4825
  const result = await this.ingress({
4721
4826
  command: header[SERVICE_WIRE_COMMAND_OFFSET]!,
4722
4827
  flags: header[SERVICE_WIRE_FLAGS_OFFSET]!,
@@ -4727,22 +4832,21 @@ export class ServiceStatefulRuntime {
4727
4832
  applicationJobOwner
4728
4833
  });
4729
4834
  if (result !== 'infrastructure') {
4730
- fail(
4731
- new ServiceWireProtocolError(
4732
- `Local infrastructure request was rejected as '${result ?? 'unsupported'}'.`
4733
- )
4835
+ throw new ServiceWireProtocolError(
4836
+ `Local infrastructure request was rejected as '${result ?? 'unsupported'}'.`
4734
4837
  );
4735
4838
  }
4736
4839
  } finally {
4737
4840
  applicationJobOwner.close();
4738
4841
  }
4739
- })().catch(fail);
4842
+ })().catch(reject);
4740
4843
  });
4741
4844
  }
4742
4845
 
4743
4846
  private async submitOneWay(targetNodeRid: string, parts: readonly Buffer[]): Promise<number> {
4744
4847
  this.requireOpen();
4745
4848
  if (targetNodeRid === this.nodeRid) {
4849
+ parts = copyRetainedServiceFrames(parts);
4746
4850
  const applicationJobOwner = await this.raw.reserveLocalIngress();
4747
4851
  if (captureZLinkExecutionTurn() !== undefined) {
4748
4852
  // The sender is inside a Spot serial turn. Running ingress inline
@@ -4814,9 +4918,11 @@ export class ServiceStatefulRuntime {
4814
4918
  | 'streamUnbind'
4815
4919
  | 'instanceSpotRequest',
4816
4920
  actor?: ServiceActorRef,
4817
- onAdmitted?: () => void
4921
+ onAdmitted?: () => void,
4922
+ receiver?: import('./operation-registry').OperationObserver<unknown, unknown>
4818
4923
  ): void {
4819
4924
  if (targetNodeRid === this.nodeRid) {
4925
+ parts = copyRetainedServiceFrames(parts);
4820
4926
  const deadlineUnixMs = BigInt(Date.now() + Math.max(0, timeoutMs));
4821
4927
  const capacityStop = new AbortController();
4822
4928
  void pending.promise.then(
@@ -4826,7 +4932,7 @@ export class ServiceStatefulRuntime {
4826
4932
  void (async () => {
4827
4933
  const applicationJobOwner = await this.raw.reserveLocalIngress(capacityStop.signal);
4828
4934
  try {
4829
- if (!this.operations.isPending(pending.id)) return;
4935
+ if (!pending.isPending()) return;
4830
4936
  const localIngress: RawServiceIngressRecord = {
4831
4937
  command: parts[0]![SERVICE_WIRE_COMMAND_OFFSET]!,
4832
4938
  flags: parts[0]![SERVICE_WIRE_FLAGS_OFFSET]!,
@@ -4841,19 +4947,71 @@ export class ServiceStatefulRuntime {
4841
4947
  pending,
4842
4948
  operationKind,
4843
4949
  actor,
4844
- deadlineUnixMs
4950
+ deadlineUnixMs,
4951
+ receiver
4845
4952
  );
4846
4953
  } catch (error) {
4847
- this.operations.reply(pending.id, failure(error));
4954
+ receiver === undefined
4955
+ ? pending.reply(failure(error))
4956
+ : receiver.operationFailed(pending.id, error, undefined);
4848
4957
  } finally {
4849
4958
  applicationJobOwner.close();
4850
4959
  }
4851
- })().catch((error) => this.operations.reply(pending.id, failure(error)));
4960
+ })().catch((error) =>
4961
+ receiver === undefined
4962
+ ? pending.reply(failure(error))
4963
+ : receiver.operationFailed(pending.id, error, undefined)
4964
+ );
4852
4965
  return;
4853
4966
  }
4854
- void this.raw.requestService(targetNodeRid, parts, timeoutMs, onAdmitted).then(
4967
+ if (receiver !== undefined) {
4968
+ const completion = {
4969
+ operationCompleted: (_id: bigint, reply: readonly Buffer[]) =>
4970
+ this.completeRemoteReply(pending, targetNodeRid, operationKind, actor, reply, receiver),
4971
+ operationFailed: (_id: bigint, error: unknown) =>
4972
+ receiver.operationFailed(pending.id, error, undefined)
4973
+ };
4974
+ if (this.raw.isPeerRouteReady(targetNodeRid) === true) {
4975
+ this.raw.requestService(targetNodeRid, parts, timeoutMs, onAdmitted, pending, completion);
4976
+ return;
4977
+ }
4978
+ admitServiceRequest(
4979
+ this.raw,
4980
+ targetNodeRid,
4981
+ pending,
4982
+ (remaining, finished) => {
4983
+ this.raw.requestService(targetNodeRid, parts, remaining, onAdmitted, pending, {
4984
+ operationCompleted: (id, reply) => {
4985
+ finished();
4986
+ completion.operationCompleted(id, reply);
4987
+ },
4988
+ operationFailed: (id, error) => {
4989
+ finished();
4990
+ completion.operationFailed(id, error);
4991
+ }
4992
+ });
4993
+ },
4994
+ (error) => completion.operationFailed(pending.id, error),
4995
+ operationKind
4996
+ );
4997
+ return;
4998
+ }
4999
+ const reply =
5000
+ this.raw.isPeerRouteReady(targetNodeRid) === true
5001
+ ? this.raw.requestService(targetNodeRid, parts, timeoutMs, onAdmitted, pending)
5002
+ : requestDurableService(
5003
+ this.raw,
5004
+ targetNodeRid,
5005
+ parts,
5006
+ pending,
5007
+ operationKind,
5008
+ undefined,
5009
+ undefined,
5010
+ onAdmitted
5011
+ );
5012
+ void reply.then(
4855
5013
  (reply) => this.completeRemoteReply(pending, targetNodeRid, operationKind, actor, reply),
4856
- (error) => this.operations.fail(pending.id, error)
5014
+ (error) => pending.replyFailure(error)
4857
5015
  );
4858
5016
  }
4859
5017
 
@@ -4871,10 +5029,7 @@ export class ServiceStatefulRuntime {
4871
5029
  ? this.tryActorFence(actor)
4872
5030
  : this.acceptCanonicalActorFence(actor, canonical.actorFence);
4873
5031
  if (target === undefined || actorRoute === undefined) {
4874
- this.operations.reply(
4875
- pending.id,
4876
- internalFrameworkWireReply(ZLinkFrameworkInternalErrorKind.ActorLocationStale)
4877
- );
5032
+ pending.reply(internalFrameworkWireReply(ZLinkFrameworkInternalErrorKind.ActorLocationStale));
4878
5033
  return;
4879
5034
  }
4880
5035
  if (canonical !== undefined) {
@@ -4914,7 +5069,7 @@ export class ServiceStatefulRuntime {
4914
5069
  }).map((frame) => Buffer.from(frame));
4915
5070
  } catch (error) {
4916
5071
  this.canonicalActorJoinHandoffs.delete(pending.id);
4917
- this.operations.fail(pending.id, error);
5072
+ pending.replyFailure(error);
4918
5073
  return;
4919
5074
  }
4920
5075
  if (targetNodeRid === this.nodeRid) {
@@ -4928,22 +5083,16 @@ export class ServiceStatefulRuntime {
4928
5083
  );
4929
5084
  return;
4930
5085
  }
4931
- void this.requestDurableOperation(
4932
- targetNodeRid,
4933
- parts,
4934
- pending.id,
4935
- 'actorJoin',
4936
- deadlineMs
4937
- ).then(
5086
+ void this.requestDurableOperation(targetNodeRid, parts, pending.id, 'actorJoin', pending).then(
4938
5087
  (reply) => this.completeRemoteReply(pending, targetNodeRid, 'actorJoin', actor, reply),
4939
5088
  (error) => {
4940
5089
  this.canonicalActorJoinHandoffs.delete(pending.id);
4941
- this.operations.fail(pending.id, error);
5090
+ pending.replyFailure(error);
4942
5091
  }
4943
5092
  );
4944
5093
  }
4945
5094
 
4946
- private async submitLocalRequest(
5095
+ async submitLocalRequest(
4947
5096
  ingress: RawServiceIngressRecord,
4948
5097
  pending: ServiceStatefulPendingOperation,
4949
5098
  operationKind:
@@ -4956,7 +5105,8 @@ export class ServiceStatefulRuntime {
4956
5105
  | 'streamUnbind'
4957
5106
  | 'instanceSpotRequest',
4958
5107
  actor?: ServiceActorRef,
4959
- deadlineUnixMs?: bigint
5108
+ deadlineUnixMs?: bigint,
5109
+ receiver?: import('./operation-registry').OperationObserver<unknown, unknown>
4960
5110
  ): Promise<void> {
4961
5111
  const canonicalActorJoin =
4962
5112
  operationKind === 'actorJoin' ? decodeActorJoin28(ingress.parts) : undefined;
@@ -4969,15 +5119,14 @@ export class ServiceStatefulRuntime {
4969
5119
  ? ingress.parts.length < 2
4970
5120
  ? undefined
4971
5121
  : ingress.parts[1]
4972
- : encodeApplicationPayload({
5122
+ : encodeOwnedApplicationPayload({
4973
5123
  packetName: canonicalActorJoin.payload.packetName,
4974
5124
  contentType: canonicalActorJoin.payload.contentType,
4975
5125
  payload: Buffer.from(canonicalActorJoin.payload.payload)
4976
5126
  });
4977
5127
  if (decoded.kind === 'actorLookup') {
4978
5128
  const found = this.registry.actor(decoded.actorId);
4979
- this.operations.reply(
4980
- pending.id,
5129
+ pending.reply(
4981
5130
  found === undefined
4982
5131
  ? { terminalResult: RequestResult.NotFound, failureCode: ACTOR_ROUTE_NOT_FOUND }
4983
5132
  : {
@@ -4991,9 +5140,9 @@ export class ServiceStatefulRuntime {
4991
5140
  if (decoded.kind === 'actorDestroy') {
4992
5141
  try {
4993
5142
  this.registry.destroyActor(decoded.actor.actor);
4994
- this.operations.reply(pending.id, { terminalResult: RequestResult.Ok, failureCode: 0 });
5143
+ pending.reply({ terminalResult: RequestResult.Ok, failureCode: 0 });
4995
5144
  } catch (error) {
4996
- this.operations.reply(pending.id, failure(error));
5145
+ pending.reply(failure(error));
4997
5146
  }
4998
5147
  return;
4999
5148
  }
@@ -5002,11 +5151,19 @@ export class ServiceStatefulRuntime {
5002
5151
  failureCode,
5003
5152
  replyPayload,
5004
5153
  tail
5005
- ) =>
5006
- this.operations.reply(
5007
- pending.id,
5008
- this.resultFromReply(terminalResult, failureCode, replyPayload, tail, this.nodeRid, actor)
5154
+ ) => {
5155
+ const result = this.resultFromReply(
5156
+ terminalResult,
5157
+ failureCode,
5158
+ replyPayload,
5159
+ tail,
5160
+ this.nodeRid,
5161
+ actor
5009
5162
  );
5163
+ if (receiver === undefined) return pending.reply(result);
5164
+ receiver.operationCompleted(pending.id, result, undefined);
5165
+ return true;
5166
+ };
5010
5167
  if (decoded.kind === 'spotRequest') {
5011
5168
  this.validateDirectSpotFence(decoded.target);
5012
5169
  this.enqueueApplicationFrame(ingress, `spot:${decoded.target.spot.spotId}`, payloadFrame!, {
@@ -5075,7 +5232,7 @@ export class ServiceStatefulRuntime {
5075
5232
  this.enqueueLifecycleFrame(
5076
5233
  ingress,
5077
5234
  `spot:${decoded.target.spot.spotId}`,
5078
- payloadFrame ?? encodeApplicationPayload(emptyPayload()),
5235
+ payloadFrame ?? encodeOwnedApplicationPayload(emptyPayload()),
5079
5236
  {
5080
5237
  receiveKind: ReceiveKind.SpotControl,
5081
5238
  operationKind: OperationKind.ActorJoin,
@@ -5092,7 +5249,7 @@ export class ServiceStatefulRuntime {
5092
5249
  payload: Buffer.from(canonicalActorJoin.payload.payload)
5093
5250
  }
5094
5251
  }),
5095
- isPending: () => this.operations.isPending(pending.id),
5252
+ isPending: () => pending.isPending(),
5096
5253
  ...(deadlineUnixMs === undefined ? {} : { deadlineUnixMs }),
5097
5254
  onTerminalCompletion: () => completeOnJoinDispatchTerminal?.(),
5098
5255
  reply: (terminalResult, failureCode, replyPayload, tail) => {
@@ -5101,7 +5258,7 @@ export class ServiceStatefulRuntime {
5101
5258
  terminalResult === RequestResult.Ok &&
5102
5259
  tail?.kind === 'actorJoin' &&
5103
5260
  tail.joinResult === 0;
5104
- if (acceptedJoin && this.operations.isPending(pending.id)) {
5261
+ if (acceptedJoin && pending.isPending()) {
5105
5262
  // Commit membership now, but keep the source operation behind
5106
5263
  // target OnJoinedActor. Entry finishes on this record; User
5107
5264
  // Spot lifecycle finishes on the Joined control below.
@@ -5158,9 +5315,9 @@ export class ServiceStatefulRuntime {
5158
5315
  this.nodeRid
5159
5316
  );
5160
5317
  }
5161
- this.operations.reply(pending.id, { terminalResult: RequestResult.Ok, failureCode: 0 });
5318
+ pending.reply({ terminalResult: RequestResult.Ok, failureCode: 0 });
5162
5319
  } catch (error) {
5163
- this.operations.reply(pending.id, failure(error));
5320
+ pending.reply(failure(error));
5164
5321
  }
5165
5322
  return;
5166
5323
  }
@@ -5178,7 +5335,7 @@ export class ServiceStatefulRuntime {
5178
5335
  );
5179
5336
  return;
5180
5337
  }
5181
- this.operations.reply(pending.id, {
5338
+ pending.reply({
5182
5339
  terminalResult: RequestResult.ProtocolError,
5183
5340
  failureCode: 0
5184
5341
  });
@@ -5186,7 +5343,7 @@ export class ServiceStatefulRuntime {
5186
5343
  }
5187
5344
 
5188
5345
  private completeRemoteReply(
5189
- pending: Pick<ServiceStatefulPendingOperation, 'id'>,
5346
+ pending: Pick<ServiceStatefulPendingOperation, 'id' | 'reply' | 'replyFailure'>,
5190
5347
  targetNodeRid: string,
5191
5348
  operationKind:
5192
5349
  | 'spotRequest'
@@ -5199,7 +5356,8 @@ export class ServiceStatefulRuntime {
5199
5356
  | 'boundSessionClose'
5200
5357
  | 'instanceSpotRequest',
5201
5358
  actor: ServiceActorRef | undefined,
5202
- reply: readonly Buffer[]
5359
+ reply: readonly Buffer[],
5360
+ receiver?: import('./operation-registry').OperationObserver<unknown, unknown>
5203
5361
  ): void {
5204
5362
  const canonicalActorJoinHandoffId =
5205
5363
  operationKind === 'actorJoin' ? this.canonicalActorJoinHandoffs.get(pending.id) : undefined;
@@ -5208,23 +5366,23 @@ export class ServiceStatefulRuntime {
5208
5366
  throw new ServiceWireProtocolError('Invalid M6B reply parts.');
5209
5367
  const decoded = decodeStatefulReply(reply[0]!, pending.id, operationKind, reply.length >= 2);
5210
5368
  const payload = reply.length < 2 ? undefined : decodeApplicationPayload(reply[1]);
5211
- this.operations.reply(
5212
- pending.id,
5213
- this.resultFromReply(
5214
- decoded.terminalResult,
5215
- decoded.failureCode,
5216
- payload,
5217
- decoded.tail,
5218
- targetNodeRid,
5219
- actor,
5220
- canonicalActorJoinHandoffId
5221
- )
5369
+ const result = this.resultFromReply(
5370
+ decoded.terminalResult,
5371
+ decoded.failureCode,
5372
+ payload,
5373
+ decoded.tail,
5374
+ targetNodeRid,
5375
+ actor,
5376
+ canonicalActorJoinHandoffId
5222
5377
  );
5378
+ if (receiver === undefined) pending.reply(result);
5379
+ else receiver.operationCompleted(pending.id, result, undefined);
5223
5380
  } catch (error) {
5224
5381
  // Spec 32-framework-error-model:58-60, 91-92 — an unprocessable remote
5225
5382
  // reply (decode/shape failure) fails the awaiting operation with a
5226
5383
  // Framework ProtocolError instead of leaking the codec's plain Error.
5227
- this.operations.fail(pending.id, translateWireReplyDecodeError(error));
5384
+ if (receiver === undefined) pending.replyFailure(translateWireReplyDecodeError(error));
5385
+ else receiver.operationFailed(pending.id, translateWireReplyDecodeError(error), undefined);
5228
5386
  } finally {
5229
5387
  if (operationKind === 'actorJoin') {
5230
5388
  this.canonicalActorJoinHandoffs.delete(pending.id);
@@ -5284,6 +5442,7 @@ export class ServiceStatefulRuntime {
5284
5442
  return {
5285
5443
  terminalResult,
5286
5444
  failureCode,
5445
+ ...(tail?.kind === 'streamBindRejected' ? { failureMessage: tail.rejectionMessage } : {}),
5287
5446
  ...(payload === undefined ? {} : { payload }),
5288
5447
  ...(tail?.kind === 'streamBind'
5289
5448
  ? {
@@ -5297,7 +5456,7 @@ export class ServiceStatefulRuntime {
5297
5456
  };
5298
5457
  }
5299
5458
 
5300
- private validateActorFence(fence: ServiceActorRouteFence): ServiceActorState {
5459
+ validateActorFence(fence: ServiceActorRouteFence): ServiceActorState {
5301
5460
  if (
5302
5461
  fence.actor.nodeRid !== this.nodeRid ||
5303
5462
  fence.targetNodeGeneration !== this.nodeGeneration
@@ -5311,7 +5470,7 @@ export class ServiceStatefulRuntime {
5311
5470
  return actor;
5312
5471
  }
5313
5472
 
5314
- private validateActorMessageFence(fence: ServiceActorRouteFence): ServiceActorState {
5473
+ validateActorMessageFence(fence: ServiceActorRouteFence): ServiceActorState {
5315
5474
  if (
5316
5475
  fence.actor.nodeRid !== this.nodeRid ||
5317
5476
  fence.targetNodeGeneration !== this.nodeGeneration
@@ -5342,7 +5501,7 @@ export class ServiceStatefulRuntime {
5342
5501
  return spot;
5343
5502
  }
5344
5503
 
5345
- private validateDirectSpotFence(fence: ServiceSpotRouteFence): ServiceSpotState {
5504
+ validateDirectSpotFence(fence: ServiceSpotRouteFence): ServiceSpotState {
5346
5505
  if (
5347
5506
  fence.targetNodeRid !== this.nodeRid ||
5348
5507
  fence.targetNodeGeneration !== this.nodeGeneration
@@ -5476,11 +5635,15 @@ export class ServiceStatefulRuntime {
5476
5635
  1,
5477
5636
  Math.min(30_000, Math.ceil(state.expiresAtMs - performance.now()))
5478
5637
  );
5479
- const reply = await this.raw.requestService(
5638
+ const pending = this.raw.beginInfrastructureRequest(remainingMs);
5639
+ const reply = await requestDurableService(
5640
+ this.raw,
5480
5641
  state.target.targetNodeRid,
5481
5642
  parts,
5482
- remainingMs
5643
+ pending,
5644
+ 'spot message follow'
5483
5645
  );
5646
+ pending.complete(reply);
5484
5647
  this.raw.replyService(current.ingress, reply);
5485
5648
  } catch (error) {
5486
5649
  const result = failure(error);
@@ -5670,9 +5833,7 @@ export class ServiceStatefulRuntime {
5670
5833
 
5671
5834
  private tryEntrySpotFence(targetNodeRid: string): ServiceDirectSpotRouteFence | undefined {
5672
5835
  const targetNodeGeneration =
5673
- targetNodeRid === this.nodeRid
5674
- ? this.nodeGeneration
5675
- : this.raw.topology.peer(targetNodeRid)?.descriptor.lifecycleGeneration;
5836
+ this.raw.peerLifecycleGeneration(targetNodeRid) ?? this.tryPeerGeneration(targetNodeRid);
5676
5837
  if (targetNodeGeneration === undefined) return undefined;
5677
5838
  return {
5678
5839
  spot: {
@@ -5715,8 +5876,10 @@ export class ServiceStatefulRuntime {
5715
5876
  ? current
5716
5877
  : undefined;
5717
5878
  }
5718
- const peer = this.raw.topology.peer(targetNodeRid);
5719
- if (peer?.descriptor.lifecycleGeneration !== targetNodeGeneration) {
5879
+ if (
5880
+ (this.raw.peerLifecycleGeneration(targetNodeRid) ?? this.tryPeerGeneration(targetNodeRid)) !==
5881
+ targetNodeGeneration
5882
+ ) {
5720
5883
  return undefined;
5721
5884
  }
5722
5885
  this.rememberSpotRoute(requested);
@@ -6311,6 +6474,10 @@ function emptyPayload(): ServiceApplicationPayload {
6311
6474
  };
6312
6475
  }
6313
6476
 
6477
+ function copyRetainedServiceFrames(parts: readonly Buffer[]): Buffer[] {
6478
+ return parts.map((part) => copyPayloadBytes(part));
6479
+ }
6480
+
6314
6481
  /**
6315
6482
  * The generated command-28 decoder is the canonical wire authority. Keep
6316
6483
  * the stateful mailbox's internal record shape as an adapter only; it must