@zlink-systems/framework 0.30.0 → 0.30.2

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 (456) hide show
  1. package/LICENSE +150 -68
  2. package/dist/.tsbuildinfo +1 -1
  3. package/dist/contracts/Actors/ZLinkActorClient.d.ts +2 -1
  4. package/dist/contracts/Channels/Calls.d.ts +2 -1
  5. package/dist/contracts/Common/ZLinkEncodedPayload.d.ts +6 -0
  6. package/dist/contracts/Common/ZLinkEncodedPayload.js +18 -3
  7. package/dist/contracts/Common/ZLinkMessageMetadata.js +11 -5
  8. package/dist/contracts/Common/encoded-payload-storage.d.ts +1 -1
  9. package/dist/contracts/Common/encoded-payload-storage.js +5 -2
  10. package/dist/contracts/Configuration/Builders.d.ts +1 -1
  11. package/dist/contracts/Configuration/RegistrationBuilderPolicy.d.ts +2 -1
  12. package/dist/contracts/Configuration/RegistrationBuilderPolicy.js +5 -1
  13. package/dist/contracts/Configuration/RegistrationBuilders.js +2 -2
  14. package/dist/contracts/Configuration/RegistrationTypes.d.ts +1 -0
  15. package/dist/contracts/Dispatch/ZLinkDispatchOptions.d.ts +2 -2
  16. package/dist/contracts/Handlers/Attributes.d.ts +5 -13
  17. package/dist/contracts/Handlers/Attributes.js +7 -11
  18. package/dist/contracts/Handlers/JsonContract.d.ts +2 -46
  19. package/dist/contracts/Handlers/JsonContract.js +4 -153
  20. package/dist/contracts/Locations/Rows.d.ts +2 -0
  21. package/dist/contracts/Spots/Contracts.d.ts +6 -1
  22. package/dist/contracts/Spots/ZLinkSpot.d.ts +3 -3
  23. package/dist/nest-integration.d.ts +1 -1
  24. package/dist/nest-integration.js +2 -1
  25. package/dist/runtime/abort.d.ts +5 -0
  26. package/dist/runtime/abort.js +10 -0
  27. package/dist/runtime/actors/actor-authority-publication.js +3 -2
  28. package/dist/runtime/actors/actor-client.d.ts +1 -2
  29. package/dist/runtime/actors/actor-client.js +52 -57
  30. package/dist/runtime/actors/actor-context.d.ts +2 -0
  31. package/dist/runtime/actors/actor-context.js +46 -9
  32. package/dist/runtime/actors/actor-handoff.d.ts +8 -4
  33. package/dist/runtime/actors/actor-handoff.js +219 -92
  34. package/dist/runtime/actors/actor-join-relocation.d.ts +3 -0
  35. package/dist/runtime/actors/actor-local-native-join.js +13 -12
  36. package/dist/runtime/actors/actor-mailbox.js +27 -1
  37. package/dist/runtime/actors/actor-remote-joiner.js +3 -1
  38. package/dist/runtime/actors/actor-remote-wire.js +15 -0
  39. package/dist/runtime/actors/actor-reply.d.ts +4 -0
  40. package/dist/runtime/actors/actor-reply.js +29 -0
  41. package/dist/runtime/actors/actor-routed-join-transport.d.ts +6 -2
  42. package/dist/runtime/actors/actor-routed-json-request.d.ts +2 -0
  43. package/dist/runtime/actors/actor-runtime-contracts.d.ts +2 -0
  44. package/dist/runtime/actors/actor-runtime-state.js +2 -20
  45. package/dist/runtime/actors/actor-source-transfer.d.ts +1 -17
  46. package/dist/runtime/actors/index.d.ts +8 -3
  47. package/dist/runtime/actors/index.js +55 -27
  48. package/dist/runtime/actors/session-disconnected-wire.d.ts +8 -0
  49. package/dist/runtime/actors/session-disconnected-wire.js +48 -0
  50. package/dist/runtime/actors/spot-actor-dispatch.js +2 -2
  51. package/dist/runtime/admission.d.ts +9 -1
  52. package/dist/runtime/admission.js +56 -23
  53. package/dist/runtime/application-jobs/application-ingress-record-owner.d.ts +6 -8
  54. package/dist/runtime/application-jobs/application-ingress-record-owner.js +39 -22
  55. package/dist/runtime/application-jobs/application-job-queue-scope.d.ts +15 -1
  56. package/dist/runtime/application-jobs/application-job-queue-scope.js +61 -20
  57. package/dist/runtime/application-jobs/contracts.d.ts +12 -1
  58. package/dist/runtime/backend/contracts/index.d.ts +37 -12
  59. package/dist/runtime/backend/mesh-actor-session-node-adapter.js +2 -2
  60. package/dist/runtime/backend/mesh-completion-table.d.ts +9 -1
  61. package/dist/runtime/backend/mesh-completion-table.js +154 -49
  62. package/dist/runtime/backend/mesh-dispatch-pump.d.ts +28 -1
  63. package/dist/runtime/backend/mesh-dispatch-pump.js +208 -101
  64. package/dist/runtime/backend/node/node-backend-adapter-support.d.ts +2 -2
  65. package/dist/runtime/backend/node/node-backend-adapter-support.js +16 -9
  66. package/dist/runtime/backend/node/node-dealer-channel-client-transport.d.ts +1 -1
  67. package/dist/runtime/backend/node/node-dealer-channel-client-transport.js +5 -2
  68. package/dist/runtime/backend/node/node-raw-binding-port.js +124 -72
  69. package/dist/runtime/backend/node/node-raw-mesh-backend.d.ts +46 -13
  70. package/dist/runtime/backend/node/node-raw-mesh-backend.js +181 -164
  71. package/dist/runtime/backend/node/node-socket-backend-adapter.d.ts +1 -1
  72. package/dist/runtime/backend/node/node-socket-backend-adapter.js +11 -11
  73. package/dist/runtime/backend/raw-binding-port.d.ts +2 -2
  74. package/dist/runtime/backend/runtime-message.d.ts +1 -0
  75. package/dist/runtime/backend/runtime-message.js +5 -0
  76. package/dist/runtime/backend/runtime-values.d.ts +1 -0
  77. package/dist/runtime/backend/runtime-values.js +2 -1
  78. package/dist/runtime/channels/channel-clients.d.ts +2 -0
  79. package/dist/runtime/channels/channel-clients.js +75 -23
  80. package/dist/runtime/channels/channel-dispatch-pipeline.d.ts +25 -5
  81. package/dist/runtime/channels/channel-dispatch-pipeline.js +111 -56
  82. package/dist/runtime/channels/channel-dispatch-services.d.ts +1 -0
  83. package/dist/runtime/channels/channel-dispatch-services.js +45 -0
  84. package/dist/runtime/channels/channel-dispatchers.d.ts +4 -3
  85. package/dist/runtime/channels/channel-dispatchers.js +62 -54
  86. package/dist/runtime/channels/channel-envelope-inspection.d.ts +1 -2
  87. package/dist/runtime/channels/channel-envelope-inspection.js +1 -16
  88. package/dist/runtime/channels/channel-envelope.d.ts +2 -0
  89. package/dist/runtime/channels/channel-envelope.js +146 -28
  90. package/dist/runtime/channels/channel-outbound-operations.d.ts +2 -2
  91. package/dist/runtime/channels/channel-outbound-operations.js +8 -8
  92. package/dist/runtime/channels/channel-runtime-lifecycle.d.ts +4 -3
  93. package/dist/runtime/channels/channel-runtime-lifecycle.js +19 -24
  94. package/dist/runtime/channels/channel-runtime-manager.d.ts +9 -8
  95. package/dist/runtime/channels/channel-runtime-manager.js +16 -16
  96. package/dist/runtime/channels/channel-transports.d.ts +18 -16
  97. package/dist/runtime/channels/channel-transports.js +77 -58
  98. package/dist/runtime/channels/client-server-location-runtime.js +5 -4
  99. package/dist/runtime/channels/dispatch-error-reporter.d.ts +2 -1
  100. package/dist/runtime/channels/dispatch-error-reporter.js +2 -1
  101. package/dist/runtime/channels/fanout-location-runtime.d.ts +1 -1
  102. package/dist/runtime/channels/fanout-location-runtime.js +3 -3
  103. package/dist/runtime/channels/local-spot-route-transport.d.ts +1 -1
  104. package/dist/runtime/channels/local-spot-route-transport.js +2 -1
  105. package/dist/runtime/channels/router-socket-spot-route-transport.d.ts +2 -2
  106. package/dist/runtime/channels/router-socket-spot-route-transport.js +4 -4
  107. package/dist/runtime/channels/source-spot-router.d.ts +2 -2
  108. package/dist/runtime/channels/source-spot-router.js +4 -4
  109. package/dist/runtime/channels/spot-node-route-transport.d.ts +2 -2
  110. package/dist/runtime/channels/spot-node-route-transport.js +4 -4
  111. package/dist/runtime/channels/spot-route-bridge-transport.d.ts +2 -2
  112. package/dist/runtime/channels/spot-route-bridge-transport.js +4 -4
  113. package/dist/runtime/channels/spot-route-dispatch-strategy.d.ts +5 -4
  114. package/dist/runtime/channels/spot-route-dispatch-strategy.js +18 -18
  115. package/dist/runtime/diagnostics/flow-context.js +19 -7
  116. package/dist/runtime/diagnostics/index.js +4 -9
  117. package/dist/runtime/diagnostics/message-flow.d.ts +8 -0
  118. package/dist/runtime/diagnostics/message-flow.js +35 -5
  119. package/dist/runtime/diagnostics/runtime-metrics.d.ts +2 -2
  120. package/dist/runtime/diagnostics/runtime-metrics.js +10 -8
  121. package/dist/runtime/execution/index.d.ts +4 -2
  122. package/dist/runtime/execution/index.js +33 -10
  123. package/dist/runtime/execution/serial-execution-queue.d.ts +5 -0
  124. package/dist/runtime/execution/serial-execution-queue.js +22 -2
  125. package/dist/runtime/execution/state-lane.d.ts +2 -0
  126. package/dist/runtime/execution/state-lane.js +5 -0
  127. package/dist/runtime/foundation/actor-join-recovery-codec.js +2 -2
  128. package/dist/runtime/foundation/durable-service-request.d.ts +14 -0
  129. package/dist/runtime/foundation/durable-service-request.js +98 -0
  130. package/dist/runtime/foundation/operation-identity.d.ts +1 -0
  131. package/dist/runtime/foundation/operation-identity.js +5 -1
  132. package/dist/runtime/foundation/operation-registry.d.ts +25 -1
  133. package/dist/runtime/foundation/operation-registry.js +86 -18
  134. package/dist/runtime/foundation/raw-service-mesh-runtime.d.ts +61 -8
  135. package/dist/runtime/foundation/raw-service-mesh-runtime.js +486 -266
  136. package/dist/runtime/foundation/service-liveness-registry.d.ts +12 -1
  137. package/dist/runtime/foundation/service-liveness-registry.js +38 -0
  138. package/dist/runtime/foundation/service-mailbox.d.ts +7 -0
  139. package/dist/runtime/foundation/service-maintenance-runtime.js +1 -6
  140. package/dist/runtime/foundation/service-relocation-object-owner.d.ts +3 -3
  141. package/dist/runtime/foundation/service-relocation-object-owner.js +48 -34
  142. package/dist/runtime/foundation/service-relocation-runtime.d.ts +2 -0
  143. package/dist/runtime/foundation/service-relocation-runtime.js +20 -4
  144. package/dist/runtime/foundation/service-runtime-contracts.d.ts +10 -1
  145. package/dist/runtime/foundation/service-session-binding-ingress-port.d.ts +2 -1
  146. package/dist/runtime/foundation/service-stateful-registry.d.ts +5 -4
  147. package/dist/runtime/foundation/service-stateful-registry.js +24 -26
  148. package/dist/runtime/foundation/service-stateful-runtime.d.ts +75 -9
  149. package/dist/runtime/foundation/service-stateful-runtime.js +486 -218
  150. package/dist/runtime/foundation/service-stateful-wire-codec.d.ts +14 -6
  151. package/dist/runtime/foundation/service-stateful-wire-codec.js +48 -27
  152. package/dist/runtime/foundation/service-topology-registry.d.ts +12 -2
  153. package/dist/runtime/foundation/service-topology-registry.js +61 -27
  154. package/dist/runtime/foundation/service-wire-binary-primitives.d.ts +6 -1
  155. package/dist/runtime/foundation/service-wire-binary-primitives.js +27 -11
  156. package/dist/runtime/foundation/service-wire-constants.generated.d.ts +1 -0
  157. package/dist/runtime/foundation/service-wire-constants.generated.js +1 -0
  158. package/dist/runtime/foundation/service-wire-m6a-codec.d.ts +13 -3
  159. package/dist/runtime/foundation/service-wire-m6a-codec.js +189 -78
  160. package/dist/runtime/handlers/handler-instance-scope.d.ts +8 -0
  161. package/dist/runtime/handlers/handler-instance-scope.js +54 -11
  162. package/dist/runtime/host/actor-packet-relay.d.ts +6 -4
  163. package/dist/runtime/host/actor-packet-relay.js +59 -72
  164. package/dist/runtime/host/actor-placement-coordinator.js +25 -8
  165. package/dist/runtime/host/actor-runtime-options-factory.js +2 -2
  166. package/dist/runtime/host/actor-transfer-runtime.d.ts +7 -31
  167. package/dist/runtime/host/actor-transfer-runtime.js +85 -331
  168. package/dist/runtime/host/application-job-queue.d.ts +40 -7
  169. package/dist/runtime/host/application-job-queue.js +137 -42
  170. package/dist/runtime/host/entry-actor-runtime.d.ts +1 -0
  171. package/dist/runtime/host/entry-actor-runtime.js +3 -0
  172. package/dist/runtime/host/index.d.ts +12 -2
  173. package/dist/runtime/host/index.js +300 -202
  174. package/dist/runtime/host/location-runtime-owner.js +2 -6
  175. package/dist/runtime/host/mesh-router-resolver.d.ts +4 -0
  176. package/dist/runtime/host/mesh-router-resolver.js +14 -6
  177. package/dist/runtime/host/remote-bound-session-relay.d.ts +2 -4
  178. package/dist/runtime/host/remote-bound-session-relay.js +73 -208
  179. package/dist/runtime/host/route-mesh-runtime.d.ts +2 -2
  180. package/dist/runtime/host/route-mesh-runtime.js +6 -4
  181. package/dist/runtime/host/runtime-shutdown.d.ts +1 -0
  182. package/dist/runtime/host/runtime-shutdown.js +3 -2
  183. package/dist/runtime/host/service-relocation-control.d.ts +1 -0
  184. package/dist/runtime/host/service-relocation-control.js +10 -4
  185. package/dist/runtime/host/service-relocation-host-runtime.d.ts +22 -14
  186. package/dist/runtime/host/service-relocation-host-runtime.js +754 -599
  187. package/dist/runtime/host/spot-address-transport.js +3 -2
  188. package/dist/runtime/host/spot-runtime-options-factory.js +16 -7
  189. package/dist/runtime/host/user-spot-creation-coordinator.js +33 -84
  190. package/dist/runtime/locations/actor-location-claims.d.ts +2 -2
  191. package/dist/runtime/locations/actor-location-claims.js +34 -19
  192. package/dist/runtime/locations/auto-connect-loop.d.ts +2 -0
  193. package/dist/runtime/locations/auto-connect-loop.js +22 -14
  194. package/dist/runtime/locations/auto-connect-reconciler.js +0 -6
  195. package/dist/runtime/locations/auto-connect-types.d.ts +0 -1
  196. package/dist/runtime/locations/descriptor-publication.d.ts +4 -0
  197. package/dist/runtime/locations/descriptor-publication.js +11 -0
  198. package/dist/runtime/locations/domain-store-contract.d.ts +1 -0
  199. package/dist/runtime/locations/in-memory-authority-store.d.ts +7 -1
  200. package/dist/runtime/locations/in-memory-authority-store.js +56 -19
  201. package/dist/runtime/locations/in-memory-location-store.js +1 -10
  202. package/dist/runtime/locations/index.d.ts +1 -0
  203. package/dist/runtime/locations/index.js +1 -0
  204. package/dist/runtime/locations/lease-tracker.js +1 -6
  205. package/dist/runtime/locations/lifecycle.d.ts +1 -2
  206. package/dist/runtime/locations/lifecycle.js +2 -5
  207. package/dist/runtime/locations/location-store-repository.d.ts +51 -1
  208. package/dist/runtime/locations/location-store-repository.js +363 -139
  209. package/dist/runtime/locations/relocation-blob.d.ts +18 -1
  210. package/dist/runtime/locations/relocation-blob.js +52 -1
  211. package/dist/runtime/locations/request-source-resolver.d.ts +37 -0
  212. package/dist/runtime/locations/request-source-resolver.js +80 -0
  213. package/dist/runtime/locations/resolvers.js +1 -1
  214. package/dist/runtime/locations/runtime.d.ts +7 -3
  215. package/dist/runtime/locations/runtime.js +61 -53
  216. package/dist/runtime/messaging/framework-json-v1.d.ts +4 -6
  217. package/dist/runtime/messaging/framework-json-v1.js +38 -294
  218. package/dist/runtime/messaging/packet-name.d.ts +1 -1
  219. package/dist/runtime/messaging/packet-name.js +8 -24
  220. package/dist/runtime/messaging/payload-codec.d.ts +7 -1
  221. package/dist/runtime/messaging/payload-codec.js +7 -6
  222. package/dist/runtime/messaging/request-result.d.ts +2 -0
  223. package/dist/runtime/messaging/request-result.js +57 -0
  224. package/dist/runtime/messaging/submission-result.d.ts +1 -0
  225. package/dist/runtime/messaging/submission-result.js +5 -2
  226. package/dist/runtime/protocol/service_wire_codec.generated.d.ts +34 -1
  227. package/dist/runtime/protocol/service_wire_codec.generated.js +229 -0
  228. package/dist/runtime/protocol/service_wire_pilot_codec.generated.d.ts +16 -1
  229. package/dist/runtime/protocol/service_wire_pilot_codec.generated.js +37 -8
  230. package/dist/runtime/spots/formal-remote-actor-admission-registry.d.ts +7 -2
  231. package/dist/runtime/spots/formal-remote-actor-admission-registry.js +36 -21
  232. package/dist/runtime/spots/index.d.ts +21 -11
  233. package/dist/runtime/spots/index.js +243 -178
  234. package/dist/runtime/spots/spot-activation-registry.d.ts +4 -2
  235. package/dist/runtime/spots/spot-activation-registry.js +21 -11
  236. package/dist/runtime/spots/spot-activation-state.d.ts +1 -1
  237. package/dist/runtime/spots/spot-activation-state.js +7 -7
  238. package/dist/runtime/spots/spot-activation.d.ts +7 -3
  239. package/dist/runtime/spots/spot-activation.js +140 -52
  240. package/dist/runtime/spots/spot-actor-admission-coordinator.d.ts +1 -0
  241. package/dist/runtime/spots/spot-actor-admission-coordinator.js +13 -22
  242. package/dist/runtime/spots/spot-actor-membership.d.ts +0 -1
  243. package/dist/runtime/spots/spot-actor-membership.js +0 -8
  244. package/dist/runtime/spots/spot-actor-packet-dispatch.js +33 -8
  245. package/dist/runtime/spots/spot-actor-packet-drain.js +5 -33
  246. package/dist/runtime/spots/spot-entry-activation.d.ts +2 -0
  247. package/dist/runtime/spots/spot-entry-activation.js +20 -11
  248. package/dist/runtime/spots/spot-handler-registry.d.ts +7 -4
  249. package/dist/runtime/spots/spot-handler-registry.js +24 -10
  250. package/dist/runtime/spots/spot-manager-internal-contracts.d.ts +2 -2
  251. package/dist/runtime/spots/spot-manager-public.js +2 -2
  252. package/dist/runtime/spots/spot-node-autoconnect.d.ts +2 -1
  253. package/dist/runtime/spots/spot-node-autoconnect.js +22 -42
  254. package/dist/runtime/spots/spot-node-runtime-manager.d.ts +19 -2
  255. package/dist/runtime/spots/spot-node-runtime-manager.js +115 -50
  256. package/dist/runtime/spots/spot-outbound.d.ts +3 -0
  257. package/dist/runtime/spots/spot-outbound.js +27 -18
  258. package/dist/runtime/spots/spot-remote-codec.js +5 -1
  259. package/dist/runtime/spots/spot-routed-spot-packet-dispatch.d.ts +1 -0
  260. package/dist/runtime/spots/spot-routed-spot-packet-dispatch.js +1 -1
  261. package/dist/runtime/spots/spot-runtime-ports.d.ts +1 -1
  262. package/dist/runtime/spots/spot-serial-executor.d.ts +10 -0
  263. package/dist/runtime/spots/spot-serial-executor.js +61 -8
  264. package/dist/runtime/spots/spot-serial-turn-executor.js +19 -2
  265. package/dist/runtime/spots/spot-subscription-dispatch.js +1 -4
  266. package/dist/runtime/spots/spot-timer.d.ts +57 -5
  267. package/dist/runtime/spots/spot-timer.js +288 -103
  268. package/dist/runtime/streams/actor-session-binding-registry.d.ts +42 -11
  269. package/dist/runtime/streams/actor-session-binding-registry.js +165 -48
  270. package/dist/runtime/streams/actor-session-binding-runtime-owner.d.ts +8 -4
  271. package/dist/runtime/streams/bound-actor-relay-sender.d.ts +2 -1
  272. package/dist/runtime/streams/bound-actor-relay-sender.js +15 -8
  273. package/dist/runtime/streams/bound-session-service.d.ts +1 -1
  274. package/dist/runtime/streams/bound-session-service.js +6 -11
  275. package/dist/runtime/streams/index.d.ts +3 -2
  276. package/dist/runtime/streams/index.js +6 -4
  277. package/dist/runtime/streams/managed-stream.js +3 -2
  278. package/dist/runtime/streams/native-fallback-bound-session.js +8 -73
  279. package/dist/runtime/streams/session-actor-coordinator.d.ts +2 -8
  280. package/dist/runtime/streams/session-actor-coordinator.js +15 -32
  281. package/dist/runtime/streams/stream-binding-runtime-ports.d.ts +3 -10
  282. package/dist/runtime/streams/stream-session-runtime.d.ts +1 -1
  283. package/dist/runtime/streams/stream-session-runtime.js +14 -31
  284. package/dist/runtime/workers/index.js +1 -1
  285. package/package.json +3 -3
  286. package/src/contracts/Actors/ZLinkActorClient.ts +2 -1
  287. package/src/contracts/Channels/Calls.ts +2 -1
  288. package/src/contracts/Common/ZLinkEncodedPayload.ts +24 -4
  289. package/src/contracts/Common/ZLinkMessageMetadata.ts +13 -8
  290. package/src/contracts/Common/encoded-payload-storage.ts +6 -3
  291. package/src/contracts/Configuration/Builders.ts +4 -1
  292. package/src/contracts/Configuration/RegistrationBuilderPolicy.ts +7 -2
  293. package/src/contracts/Configuration/RegistrationBuilders.ts +6 -2
  294. package/src/contracts/Configuration/RegistrationTypes.ts +1 -0
  295. package/src/contracts/Dispatch/ZLinkDispatchOptions.ts +2 -1
  296. package/src/contracts/Handlers/Attributes.ts +14 -21
  297. package/src/contracts/Handlers/JsonContract.ts +8 -216
  298. package/src/contracts/Locations/Rows.ts +2 -0
  299. package/src/contracts/Spots/Contracts.ts +10 -1
  300. package/src/contracts/Spots/ZLinkSpot.ts +3 -3
  301. package/src/nest-integration.ts +1 -0
  302. package/src/runtime/abort.ts +12 -0
  303. package/src/runtime/actors/actor-authority-publication.ts +3 -2
  304. package/src/runtime/actors/actor-client.ts +100 -85
  305. package/src/runtime/actors/actor-context.ts +49 -9
  306. package/src/runtime/actors/actor-handoff.ts +291 -110
  307. package/src/runtime/actors/actor-join-relocation.ts +3 -0
  308. package/src/runtime/actors/actor-local-native-join.ts +21 -26
  309. package/src/runtime/actors/actor-mailbox.ts +40 -2
  310. package/src/runtime/actors/actor-remote-joiner.ts +6 -1
  311. package/src/runtime/actors/actor-remote-wire.ts +17 -0
  312. package/src/runtime/actors/actor-reply.ts +42 -0
  313. package/src/runtime/actors/actor-routed-join-transport.ts +14 -4
  314. package/src/runtime/actors/actor-routed-json-request.ts +10 -2
  315. package/src/runtime/actors/actor-runtime-contracts.ts +2 -0
  316. package/src/runtime/actors/actor-runtime-state.ts +2 -20
  317. package/src/runtime/actors/actor-source-transfer.ts +1 -34
  318. package/src/runtime/actors/index.ts +60 -32
  319. package/src/runtime/actors/session-disconnected-wire.ts +66 -0
  320. package/src/runtime/actors/spot-actor-dispatch.ts +4 -2
  321. package/src/runtime/admission.ts +69 -21
  322. package/src/runtime/application-jobs/application-ingress-record-owner.ts +41 -25
  323. package/src/runtime/application-jobs/application-job-queue-scope.ts +83 -22
  324. package/src/runtime/application-jobs/contracts.ts +16 -1
  325. package/src/runtime/backend/contracts/index.ts +92 -18
  326. package/src/runtime/backend/mesh-actor-session-node-adapter.ts +5 -3
  327. package/src/runtime/backend/mesh-completion-table.ts +160 -57
  328. package/src/runtime/backend/mesh-dispatch-pump.ts +237 -108
  329. package/src/runtime/backend/node/node-backend-adapter-support.ts +17 -8
  330. package/src/runtime/backend/node/node-dealer-channel-client-transport.ts +12 -2
  331. package/src/runtime/backend/node/node-raw-binding-port.ts +148 -85
  332. package/src/runtime/backend/node/node-raw-mesh-backend.ts +315 -201
  333. package/src/runtime/backend/node/node-socket-backend-adapter.ts +26 -11
  334. package/src/runtime/backend/raw-binding-port.ts +7 -2
  335. package/src/runtime/backend/runtime-message.ts +6 -0
  336. package/src/runtime/backend/runtime-values.ts +1 -0
  337. package/src/runtime/channels/channel-clients.ts +132 -58
  338. package/src/runtime/channels/channel-dispatch-pipeline.ts +198 -114
  339. package/src/runtime/channels/channel-dispatch-services.ts +69 -1
  340. package/src/runtime/channels/channel-dispatchers.ts +136 -90
  341. package/src/runtime/channels/channel-envelope-inspection.ts +2 -16
  342. package/src/runtime/channels/channel-envelope.ts +225 -31
  343. package/src/runtime/channels/channel-outbound-operations.ts +22 -8
  344. package/src/runtime/channels/channel-runtime-lifecycle.ts +13 -13
  345. package/src/runtime/channels/channel-runtime-manager.ts +41 -17
  346. package/src/runtime/channels/channel-transports.ts +171 -112
  347. package/src/runtime/channels/client-server-location-runtime.ts +11 -10
  348. package/src/runtime/channels/dispatch-error-reporter.ts +4 -2
  349. package/src/runtime/channels/fanout-location-runtime.ts +17 -9
  350. package/src/runtime/channels/local-spot-route-transport.ts +3 -1
  351. package/src/runtime/channels/router-socket-spot-route-transport.ts +13 -4
  352. package/src/runtime/channels/source-spot-router.ts +8 -4
  353. package/src/runtime/channels/spot-node-route-transport.ts +8 -4
  354. package/src/runtime/channels/spot-route-bridge-transport.ts +6 -4
  355. package/src/runtime/channels/spot-route-dispatch-strategy.ts +47 -18
  356. package/src/runtime/diagnostics/flow-context.ts +20 -7
  357. package/src/runtime/diagnostics/index.ts +1 -7
  358. package/src/runtime/diagnostics/message-flow.ts +47 -9
  359. package/src/runtime/diagnostics/runtime-metrics.ts +12 -10
  360. package/src/runtime/execution/index.ts +40 -14
  361. package/src/runtime/execution/serial-execution-queue.ts +33 -4
  362. package/src/runtime/execution/state-lane.ts +7 -0
  363. package/src/runtime/foundation/actor-join-recovery-codec.ts +2 -2
  364. package/src/runtime/foundation/durable-service-request.ts +137 -0
  365. package/src/runtime/foundation/operation-identity.ts +5 -1
  366. package/src/runtime/foundation/operation-registry.ts +98 -20
  367. package/src/runtime/foundation/raw-service-mesh-runtime.ts +704 -336
  368. package/src/runtime/foundation/service-liveness-registry.ts +39 -0
  369. package/src/runtime/foundation/service-mailbox.ts +8 -0
  370. package/src/runtime/foundation/service-maintenance-runtime.ts +1 -8
  371. package/src/runtime/foundation/service-relocation-object-owner.ts +55 -36
  372. package/src/runtime/foundation/service-relocation-runtime.ts +25 -4
  373. package/src/runtime/foundation/service-runtime-contracts.ts +19 -2
  374. package/src/runtime/foundation/service-session-binding-ingress-port.ts +2 -1
  375. package/src/runtime/foundation/service-stateful-registry.ts +38 -35
  376. package/src/runtime/foundation/service-stateful-runtime.ts +732 -275
  377. package/src/runtime/foundation/service-stateful-wire-codec.ts +49 -16
  378. package/src/runtime/foundation/service-topology-registry.ts +91 -36
  379. package/src/runtime/foundation/service-wire-binary-primitives.ts +35 -12
  380. package/src/runtime/foundation/service-wire-constants.generated.ts +1 -0
  381. package/src/runtime/foundation/service-wire-m6a-codec.ts +231 -76
  382. package/src/runtime/handlers/handler-instance-scope.ts +67 -16
  383. package/src/runtime/host/actor-packet-relay.ts +113 -94
  384. package/src/runtime/host/actor-placement-coordinator.ts +31 -8
  385. package/src/runtime/host/actor-runtime-options-factory.ts +13 -2
  386. package/src/runtime/host/actor-transfer-runtime.ts +104 -430
  387. package/src/runtime/host/application-job-queue.ts +160 -41
  388. package/src/runtime/host/entry-actor-runtime.ts +4 -0
  389. package/src/runtime/host/index.ts +473 -271
  390. package/src/runtime/host/location-runtime-owner.ts +2 -6
  391. package/src/runtime/host/mesh-router-resolver.ts +13 -5
  392. package/src/runtime/host/remote-bound-session-relay.ts +88 -271
  393. package/src/runtime/host/route-mesh-runtime.ts +12 -6
  394. package/src/runtime/host/runtime-shutdown.ts +15 -4
  395. package/src/runtime/host/service-relocation-control.ts +11 -5
  396. package/src/runtime/host/service-relocation-host-runtime.ts +1092 -759
  397. package/src/runtime/host/spot-address-transport.ts +4 -2
  398. package/src/runtime/host/spot-runtime-options-factory.ts +20 -7
  399. package/src/runtime/host/user-spot-creation-coordinator.ts +41 -100
  400. package/src/runtime/locations/actor-location-claims.ts +52 -30
  401. package/src/runtime/locations/auto-connect-loop.ts +22 -14
  402. package/src/runtime/locations/auto-connect-reconciler.ts +0 -6
  403. package/src/runtime/locations/auto-connect-types.ts +0 -1
  404. package/src/runtime/locations/descriptor-publication.ts +7 -0
  405. package/src/runtime/locations/domain-store-contract.ts +5 -0
  406. package/src/runtime/locations/in-memory-authority-store.ts +85 -23
  407. package/src/runtime/locations/in-memory-location-store.ts +1 -12
  408. package/src/runtime/locations/index.ts +1 -0
  409. package/src/runtime/locations/lease-tracker.ts +2 -9
  410. package/src/runtime/locations/lifecycle.ts +8 -26
  411. package/src/runtime/locations/location-store-repository.ts +628 -152
  412. package/src/runtime/locations/relocation-blob.ts +75 -1
  413. package/src/runtime/locations/request-source-resolver.ts +138 -0
  414. package/src/runtime/locations/resolvers.ts +2 -2
  415. package/src/runtime/locations/runtime.ts +98 -64
  416. package/src/runtime/messaging/framework-json-v1.ts +5 -325
  417. package/src/runtime/messaging/packet-name.ts +5 -25
  418. package/src/runtime/messaging/payload-codec.ts +8 -11
  419. package/src/runtime/messaging/request-result.ts +62 -0
  420. package/src/runtime/messaging/submission-result.ts +5 -1
  421. package/src/runtime/protocol/service_wire_codec.generated.ts +218 -5
  422. package/src/runtime/protocol/service_wire_pilot_codec.generated.ts +16 -13
  423. package/src/runtime/spots/formal-remote-actor-admission-registry.ts +46 -25
  424. package/src/runtime/spots/index.ts +389 -283
  425. package/src/runtime/spots/spot-activation-registry.ts +25 -13
  426. package/src/runtime/spots/spot-activation-state.ts +12 -19
  427. package/src/runtime/spots/spot-activation.ts +198 -96
  428. package/src/runtime/spots/spot-actor-admission-coordinator.ts +25 -55
  429. package/src/runtime/spots/spot-actor-membership.ts +0 -15
  430. package/src/runtime/spots/spot-actor-packet-dispatch.ts +56 -11
  431. package/src/runtime/spots/spot-actor-packet-drain.ts +9 -52
  432. package/src/runtime/spots/spot-entry-activation.ts +33 -21
  433. package/src/runtime/spots/spot-handler-registry.ts +56 -12
  434. package/src/runtime/spots/spot-manager-internal-contracts.ts +2 -2
  435. package/src/runtime/spots/spot-manager-public.ts +2 -2
  436. package/src/runtime/spots/spot-node-autoconnect.ts +28 -47
  437. package/src/runtime/spots/spot-node-runtime-manager.ts +197 -67
  438. package/src/runtime/spots/spot-outbound.ts +39 -19
  439. package/src/runtime/spots/spot-remote-codec.ts +9 -2
  440. package/src/runtime/spots/spot-routed-spot-packet-dispatch.ts +2 -1
  441. package/src/runtime/spots/spot-runtime-ports.ts +1 -1
  442. package/src/runtime/spots/spot-serial-executor.ts +97 -25
  443. package/src/runtime/spots/spot-serial-turn-executor.ts +22 -3
  444. package/src/runtime/spots/spot-subscription-dispatch.ts +1 -4
  445. package/src/runtime/spots/spot-timer.ts +418 -158
  446. package/src/runtime/streams/actor-session-binding-registry.ts +236 -64
  447. package/src/runtime/streams/actor-session-binding-runtime-owner.ts +16 -8
  448. package/src/runtime/streams/bound-actor-relay-sender.ts +23 -9
  449. package/src/runtime/streams/bound-session-service.ts +7 -10
  450. package/src/runtime/streams/index.ts +12 -6
  451. package/src/runtime/streams/managed-stream.ts +4 -2
  452. package/src/runtime/streams/native-fallback-bound-session.ts +14 -103
  453. package/src/runtime/streams/session-actor-coordinator.ts +39 -88
  454. package/src/runtime/streams/stream-binding-runtime-ports.ts +3 -9
  455. package/src/runtime/streams/stream-session-runtime.ts +13 -34
  456. package/src/runtime/workers/index.ts +1 -1
@@ -1,6 +1,7 @@
1
1
  import { type ActorRef, type RoutingId, ZLinkFrameworkException } from '../../contracts';
2
2
 
3
3
  import type { Message } from '../../contracts/Common/Message';
4
+ import { DEFAULT_REQUEST_TIMEOUT_MS } from '../../contracts/Configuration/Registration';
4
5
  import { zlinkDefaultLocationOptions } from '../../contracts/Locations/Options';
5
6
  import { releaseApplicationJobPermitForDurableHandoff } from '../application-jobs/application-job-queue-scope';
6
7
  import type { ApplicationJobOrigin } from '../application-jobs/contracts';
@@ -10,12 +11,22 @@ import {
10
11
  type MessageFollowSuppressionFence
11
12
  } from '../foundation/message-follow-suppression-registry';
12
13
  import type { ZLinkMessageFollowOrigin } from '../foundation/service-runtime-contracts';
14
+ import { RELOCATION_REPLY_RETENTION_MS } from '../foundation/service-stateful-registry';
15
+ import type { ServiceActorRouteFence } from '../foundation/service-stateful-wire-codec';
16
+ import { OPERATION_IDENTITY_BYTES } from '../foundation/operation-identity';
17
+ import { UINT64_BYTES } from '@zlink-systems/stream-wire';
13
18
  import {
14
19
  createInternalFrameworkException,
15
20
  internalFrameworkErrorKind,
16
21
  ZLinkFrameworkInternalErrorKind
17
22
  } from '../framework-errors-internal';
18
- import { encodeRoutingIdStorageHex, routingIdsEqual } from '../routing-id';
23
+ import { waitRequestReply } from '../messaging/request-deadline';
24
+ import {
25
+ decodeRoutingId,
26
+ encodeRoutingIdStorageHex,
27
+ routingIdsEqual,
28
+ routingIdWireHex
29
+ } from '../routing-id';
19
30
  import type { ZLinkSpotRouteTarget } from '../spots/spot-routing-internal';
20
31
  import { decodeActorRequestDeadlineUnixMs, decodeStreamHeader } from '../streams/protocol';
21
32
  import {
@@ -43,7 +54,7 @@ import type { ZLinkRemoteBoundSessionTarget } from './actor-runtime-state';
43
54
 
44
55
  export const DEFAULT_MESSAGE_FOLLOW_DURATION_MS =
45
56
  zlinkDefaultLocationOptions.messageFollowDurationMs;
46
- const RELOCATION_REPLY_RETENTION_MS = 24 * 60 * 60 * 1_000;
57
+ export const RELOCATED_REQUEST_OWNED_BY_REQUESTER = Symbol('relocated request owned by requester');
47
58
 
48
59
  export interface ZLinkActorHandoffPacket {
49
60
  readonly index: number;
@@ -74,6 +85,7 @@ export interface ZLinkActorHandoffRequestSource {
74
85
  readonly ownerId: string;
75
86
  readonly ownerLeaseGeneration: string;
76
87
  readonly nodeRid: string;
88
+ readonly nodeRidHex?: string;
77
89
  readonly nodeGeneration: string;
78
90
  readonly replyRouteId: string;
79
91
  }
@@ -119,6 +131,7 @@ export interface ZLinkActorHandoffPrefixAdmission {
119
131
  }
120
132
 
121
133
  export interface ZLinkActorHandoffPrefixRecord {
134
+ readonly onWithdrawable?: (withdraw: () => boolean) => void;
122
135
  readonly drain: (dispatch: ZLinkActorHandoffDispatch) => Promise<void>;
123
136
  readonly preparation?: {
124
137
  prepare(signal: AbortSignal): Promise<void>;
@@ -139,6 +152,7 @@ export type ZLinkActorHandoffPrefixQueue = (
139
152
  ) => ZLinkActorHandoffPrefixAdmission;
140
153
 
141
154
  interface PendingPacket {
155
+ withdraw?: () => boolean;
142
156
  readonly origin: ApplicationJobOrigin;
143
157
  readonly packet: ZLinkActorHandoffPacket;
144
158
  readonly resolve?: (value: unknown) => void;
@@ -290,7 +304,12 @@ function requireExactTargetOwnerFence(
290
304
  /** Owns packet ordering from relocation start through Message Follow removal. */
291
305
  export class ZLinkActorHandoffCoordinator {
292
306
  private readonly active = new Map<string, ActiveHandoff>();
293
- private readonly messageFollowRoutes = new Map<string, MessageFollowRoute>();
307
+ // Each route is stored once: Actor -> native fence -> location owner id.
308
+ // Native ingress has the complete fence except the location owner's text id.
309
+ private readonly messageFollowRoutes = new Map<
310
+ string,
311
+ Map<string, Map<string, MessageFollowRoute>>
312
+ >();
294
313
  private readonly messageFollowSuppression = new MessageFollowSuppressionRegistry();
295
314
  // Relocation preserves ObjectGeneration, so (nodeRid, objectGeneration) alone
296
315
  // also matches a tenure that later RETURNS to a previously-visited node. The
@@ -322,7 +341,10 @@ export class ZLinkActorHandoffCoordinator {
322
341
  oldGeneration: bigint,
323
342
  phase: 'relocating' | 'provisional'
324
343
  ): void {
325
- if (this.active.has(actorId)) {
344
+ // A releasing handoff has returned its hold to the Actor FIFO; only its
345
+ // durable prefix drain remains, and the next hold takes over its ingress.
346
+ const previous = this.active.get(actorId);
347
+ if (this.isActive(actorId)) {
326
348
  throw new Error(`Actor '${actorId}' already has an active packet handoff.`);
327
349
  }
328
350
  if (oldGeneration <= 0n) {
@@ -362,6 +384,24 @@ export class ZLinkActorHandoffCoordinator {
362
384
  nodeGeneration: source.nodeGeneration,
363
385
  authorityOwnerGeneration: source.authorityOwnerGeneration
364
386
  });
387
+ const pending: PendingPacket[] = [];
388
+ if (previous?.prefixRelease !== undefined) {
389
+ // Only records still in the FIFO belong to the new barrier. Running
390
+ // records keep their existing terminal; withdrawn records surrender
391
+ // readiness and move their payload before later ingress can arrive.
392
+ for (let index = 0; index < previous.pending.length;) {
393
+ const record = previous.pending[index]!;
394
+ if (record.withdraw?.() === true) {
395
+ record.withdraw = undefined;
396
+ pending.push(record);
397
+ previous.pending.splice(index, 1);
398
+ previous.prefixRelease.cursor -= 1;
399
+ previous.pendingBytes -= packetBytes(record.packet);
400
+ } else {
401
+ index += 1;
402
+ }
403
+ }
404
+ }
365
405
  this.active.set(actorId, {
366
406
  oldGeneration,
367
407
  oldNodeRid: sourceOwner.nodeRid,
@@ -371,29 +411,23 @@ export class ZLinkActorHandoffCoordinator {
371
411
  phase,
372
412
  deferredJoin: phase === 'provisional',
373
413
  connectionBoundSealed: false,
374
- pending: [],
375
- nextIndex: 0,
414
+ pending,
415
+ nextIndex: pending.reduce((next, record) => Math.max(next, record.packet.index + 1), 0),
376
416
  snapshotIndex: -1,
377
- pendingBytes: 0
417
+ pendingBytes: pending.reduce((bytes, record) => bytes + packetBytes(record.packet), 0)
378
418
  });
379
419
  }
380
420
 
421
+ /** True while a hold owns this Actor's ingress, before its release to the Actor FIFO. */
381
422
  isActive(actorId: string): boolean {
382
- return this.active.has(actorId);
423
+ const handoff = this.active.get(actorId);
424
+ return handoff !== undefined && handoff.phase !== 'releasing';
383
425
  }
384
426
 
385
427
  isProvisional(actorId: string): boolean {
386
428
  return this.active.get(actorId)?.phase === 'provisional';
387
429
  }
388
430
 
389
- promoteProvisional(actorId: string): void {
390
- const handoff = this.active.get(actorId);
391
- if (handoff?.phase !== 'provisional') {
392
- throw new Error(`Actor '${actorId}' does not have a provisional packet handoff.`);
393
- }
394
- handoff.phase = 'relocating';
395
- }
396
-
397
431
  sealConnectionBoundIngress(actorId: string): void {
398
432
  const handoff = this.active.get(actorId);
399
433
  if (handoff !== undefined) handoff.connectionBoundSealed = true;
@@ -459,6 +493,44 @@ export class ZLinkActorHandoffCoordinator {
459
493
  return this.admitHandoffPrefix(actorId, handoff, queue, preparation, start);
460
494
  }
461
495
 
496
+ /** Installs a restored target's payload in the same owner used by local handoffs. */
497
+ admitTransferredPrefix(
498
+ actorId: string,
499
+ objectGeneration: bigint,
500
+ packets: readonly ZLinkActorHandoffPacket[],
501
+ queue: ZLinkActorHandoffPrefixQueue,
502
+ preparation: ZLinkActorHandoffReplayPreparation | undefined,
503
+ start: Promise<void>,
504
+ onResult: (packet: ZLinkActorHandoffPacket, result: ZLinkActorHandoffResult) => void
505
+ ): ZLinkActorHandoffPrefixAdmission {
506
+ this.beginProvisional(actorId, objectGeneration);
507
+ const handoff = this.requireActive(actorId);
508
+ for (const packet of packets) {
509
+ handoff.pending.push({
510
+ packet,
511
+ origin: 'remote',
512
+ resolve: (response) => {
513
+ if (response !== RELOCATED_REQUEST_OWNED_BY_REQUESTER) {
514
+ onResult(packet, { index: packet.index, ok: true, response });
515
+ }
516
+ },
517
+ reject: (error) =>
518
+ onResult(packet, {
519
+ index: packet.index,
520
+ ok: false,
521
+ error: error instanceof Error ? error.message : String(error),
522
+ errorKind:
523
+ error instanceof ZLinkFrameworkException
524
+ ? internalFrameworkErrorKind(error)
525
+ : undefined
526
+ })
527
+ });
528
+ handoff.nextIndex = Math.max(handoff.nextIndex, packet.index + 1);
529
+ handoff.pendingBytes += packetBytes(packet);
530
+ }
531
+ return this.admitHandoffPrefix(actorId, handoff, queue, preparation, start);
532
+ }
533
+
462
534
  private admitHandoffPrefix(
463
535
  actorId: string,
464
536
  handoff: ActiveHandoff,
@@ -551,6 +623,9 @@ export class ZLinkActorHandoffCoordinator {
551
623
  prepared = undefined;
552
624
  };
553
625
  return {
626
+ onWithdrawable: (withdraw) => {
627
+ pending.withdraw = withdraw;
628
+ },
554
629
  payloadBytes: packetBytes(pending.packet),
555
630
  preparation: {
556
631
  prepare: async (signal) => {
@@ -572,6 +647,9 @@ export class ZLinkActorHandoffCoordinator {
572
647
  cancel
573
648
  },
574
649
  drain: async (replay) => {
650
+ // The FIFO claim, rather than this prefix's eventual terminal,
651
+ // ends the record's durable ownership and transfer capability.
652
+ pending.withdraw = undefined;
575
653
  const admission =
576
654
  prepared === undefined
577
655
  ? undefined
@@ -776,13 +854,41 @@ export class ZLinkActorHandoffCoordinator {
776
854
  fallbackActorRef?: ActorRef,
777
855
  deadlineUnixMs?: number,
778
856
  messageFollowOrigin?: ZLinkMessageFollowOrigin,
779
- provisionalReplay?: ZLinkActorHandoffDispatch
857
+ provisionalReplay?: ZLinkActorHandoffDispatch,
858
+ onAdmitted?: () => void
780
859
  ): Promise<unknown> | undefined {
781
- const incomingContext = actorMessageFollowContext(fallbackActorRef);
860
+ let incomingContext = actorMessageFollowContext(fallbackActorRef);
782
861
  const originalDeadlineUnixMs =
783
862
  deadlineUnixMs ?? incomingContext?.deadlineUnixMs ?? packetDeadlineUnixMs(parts);
784
- const handoff = this.active.get(actorId);
863
+ const followRoute = this.findMessageFollowRoute(
864
+ actorId,
865
+ incomingContext,
866
+ messageFollowOrigin?.target
867
+ );
868
+ // An exact departed tenure belongs to its committed route, even while the
869
+ // same Actor incarnation is performing a later Join on this node.
870
+ const handoff = followRoute === undefined ? this.active.get(actorId) : undefined;
871
+ if (
872
+ incomingContext === undefined &&
873
+ followRoute !== undefined &&
874
+ messageFollowOrigin?.target !== undefined
875
+ ) {
876
+ incomingContext = this.createInitialIngressContext(
877
+ followRoute.sourceOwner,
878
+ messageFollowOrigin.target.actor.generation,
879
+ parts,
880
+ returnResponse,
881
+ originalDeadlineUnixMs,
882
+ messageFollowOrigin
883
+ );
884
+ }
785
885
  if (handoff !== undefined) {
886
+ if (
887
+ handoff.phase === 'releasing' &&
888
+ handoff.prefixRelease !== undefined &&
889
+ handoff.pending.at(-1)?.withdraw === undefined
890
+ )
891
+ return undefined;
786
892
  if (parts.length < 2) return Promise.resolve(undefined);
787
893
  if (
788
894
  handoff.connectionBoundSealed &&
@@ -805,10 +911,15 @@ export class ZLinkActorHandoffCoordinator {
805
911
  handoff.oldGeneration,
806
912
  parts,
807
913
  returnResponse,
808
- originalDeadlineUnixMs
914
+ originalDeadlineUnixMs,
915
+ messageFollowOrigin
809
916
  );
810
917
  try {
811
918
  this.validateContext(actorId, context, parts, returnResponse, fallbackActorRef);
919
+ // Accepted handoff retains its original deadline; Message Follow uses a local relay window.
920
+ if (context.deadlineUnixMs !== undefined && Date.now() >= context.deadlineUnixMs) {
921
+ throw actorDeadlineExceeded(actorId);
922
+ }
812
923
  } catch (error) {
813
924
  return Promise.reject(error);
814
925
  }
@@ -843,8 +954,25 @@ export class ZLinkActorHandoffCoordinator {
843
954
  return Promise.resolve(undefined);
844
955
  }
845
956
  const result = new Promise((resolve, reject) => {
846
- const source = this.captureRequestSource(handoff.sourceEvidence, context.replyRouteId);
957
+ const original = messageFollowOrigin?.requestSource;
958
+ const originalRidHex =
959
+ original === undefined ? undefined : routingIdWireHex(original.nodeRid);
960
+ const source =
961
+ original === undefined
962
+ ? this.captureRequestSource(handoff.sourceEvidence, context.replyRouteId)
963
+ : {
964
+ ownerId: original.ownerId,
965
+ ownerLeaseGeneration: original.leaseGeneration.toString(),
966
+ nodeRid: String(original.nodeRid),
967
+ ...(originalRidHex === undefined ? {} : { nodeRidHex: originalRidHex }),
968
+ nodeGeneration: original.nodeGeneration.toString(),
969
+ replyRouteId: messageFollowOrigin!.originalReplyRouteId.toString()
970
+ };
847
971
  const requestPacket = { ...packet, source };
972
+ if (original !== undefined) {
973
+ handoff.pending.push({ packet: requestPacket, origin, resolve, reject });
974
+ return;
975
+ }
848
976
  const route: ReplyRoute = {
849
977
  actorId,
850
978
  operationId: requestPacket.messageFollowContext.operationId,
@@ -871,6 +999,7 @@ export class ZLinkActorHandoffCoordinator {
871
999
  });
872
1000
  });
873
1001
  releaseApplicationJobPermitForDurableHandoff();
1002
+ onAdmitted?.();
874
1003
  if (handoff.prefixRelease !== undefined) {
875
1004
  try {
876
1005
  this.admitPendingPrefix(actorId, handoff, handoff.prefixRelease);
@@ -883,7 +1012,6 @@ export class ZLinkActorHandoffCoordinator {
883
1012
  return result;
884
1013
  }
885
1014
 
886
- const followRoute = this.findMessageFollowRoute(actorId, incomingContext);
887
1015
  const staleGeneration = fallbackActorRef?.objectGeneration;
888
1016
  if (
889
1017
  fallbackActorRef !== undefined &&
@@ -916,7 +1044,7 @@ export class ZLinkActorHandoffCoordinator {
916
1044
  incomingContext,
917
1045
  messageFollowOrigin
918
1046
  );
919
- return this.enqueueMessageFollow(followRoute, actorId, packet);
1047
+ return this.enqueueMessageFollow(followRoute, actorId, packet, onAdmitted);
920
1048
  }
921
1049
  this.options.onMarker?.('message_follow_rejected', actorId);
922
1050
  return Promise.reject(actorLocationStale(actorId));
@@ -973,7 +1101,7 @@ export class ZLinkActorHandoffCoordinator {
973
1101
  context,
974
1102
  messageFollowOrigin
975
1103
  );
976
- return this.enqueueMessageFollow(followRoute, actorId, packet);
1104
+ return this.enqueueMessageFollow(followRoute, actorId, packet, onAdmitted);
977
1105
  }
978
1106
 
979
1107
  snapshot(actorId: string): readonly ZLinkActorHandoffPacket[] {
@@ -982,19 +1110,6 @@ export class ZLinkActorHandoffCoordinator {
982
1110
  return handoff.pending.map((entry) => entry.packet);
983
1111
  }
984
1112
 
985
- snapshotCoreBacklog(actorId: string): readonly ZLinkActorHandoffPacket[] {
986
- const handoff = this.requireActive(actorId);
987
- let snapshotIndex = -1;
988
- while (
989
- snapshotIndex + 1 < handoff.pending.length &&
990
- handoff.pending[snapshotIndex + 1].packet.returnResponse === false
991
- ) {
992
- snapshotIndex++;
993
- }
994
- handoff.snapshotIndex = snapshotIndex;
995
- return handoff.pending.slice(0, snapshotIndex + 1).map((entry) => entry.packet);
996
- }
997
-
998
1113
  /**
999
1114
  * Freezes the post-capture ingress segment immediately before the caller
1000
1115
  * appends the one-way cutover on the same relocation lane. Records returned
@@ -1013,14 +1128,25 @@ export class ZLinkActorHandoffCoordinator {
1013
1128
  target: ZLinkSpotRouteTarget,
1014
1129
  targetActorRef: ActorRef,
1015
1130
  results: readonly ZLinkActorHandoffResult[],
1016
- targetOwnerFence: ZLinkActorMessageFollowOwnerFence
1131
+ targetOwnerFence: ZLinkActorMessageFollowOwnerFence | null
1017
1132
  ): void {
1018
1133
  const handoff = this.requireActive(actorId);
1019
- const committedTargetOwner = requireExactTargetOwnerFence(actorId, targetOwnerFence);
1134
+ const committedTargetOwner =
1135
+ targetOwnerFence === null ? null : requireExactTargetOwnerFence(actorId, targetOwnerFence);
1020
1136
  this.active.delete(actorId);
1137
+ // Location runtime §10: a later owner has no source-local Follow route.
1138
+ if (committedTargetOwner === null) {
1139
+ const unavailable = actorLocationStale(actorId);
1140
+ for (const pending of handoff.pending) this.failReleasedPending(pending, unavailable);
1141
+ return;
1142
+ }
1021
1143
  const byIndex = new Map(results.map((result) => [result.index, result]));
1022
1144
  for (let i = 0; i <= handoff.snapshotIndex; i++) {
1023
1145
  const pending = handoff.pending[i];
1146
+ if (pending.packet.messageFollowOrigin?.requestSource !== undefined) {
1147
+ pending.resolve?.(RELOCATED_REQUEST_OWNED_BY_REQUESTER);
1148
+ continue;
1149
+ }
1024
1150
  if (pending.packet.source !== undefined) continue;
1025
1151
  const result = byIndex.get(pending.packet.index);
1026
1152
  if (result?.ok === false) {
@@ -1072,11 +1198,16 @@ export class ZLinkActorHandoffCoordinator {
1072
1198
  }
1073
1199
 
1074
1200
  messageFollowCount(actorId?: string): number {
1075
- return actorId === undefined
1076
- ? this.messageFollowRoutes.size
1077
- : [...this.messageFollowRoutes.values()].filter(
1078
- (route) => route.targetActorRef.actorId === actorId
1079
- ).length;
1201
+ let count = 0;
1202
+ if (actorId === undefined) {
1203
+ for (const id of this.messageFollowRoutes.keys()) count += this.messageFollowCount(id);
1204
+ } else {
1205
+ const routes = this.messageFollowRoutes.get(actorId);
1206
+ if (routes !== undefined) {
1207
+ for (const owners of routes.values()) count += owners.size;
1208
+ }
1209
+ }
1210
+ return count;
1080
1211
  }
1081
1212
 
1082
1213
  pendingCount(actorId: string): number {
@@ -1085,7 +1216,7 @@ export class ZLinkActorHandoffCoordinator {
1085
1216
 
1086
1217
  isKnownStale(actor: ActorRef): boolean {
1087
1218
  return (
1088
- this.messageFollowCount(actor.actorId) === 0 &&
1219
+ !this.messageFollowRoutes.has(actor.actorId) &&
1089
1220
  this.options.isCurrentActorRef?.(actor.actorId, actor) !== true &&
1090
1221
  this.isKnownStaleRef(actor.actorId, actor)
1091
1222
  );
@@ -1242,8 +1373,24 @@ export class ZLinkActorHandoffCoordinator {
1242
1373
  refs.set(exactRefKey, departedAuthorityOwnerGeneration);
1243
1374
  }
1244
1375
  }
1245
- const key = messageFollowRouteKey(actorId, oldGeneration, sourceOwner);
1246
- const previous = this.messageFollowRoutes.get(key);
1376
+ const key = messageFollowRouteKey(
1377
+ oldGeneration,
1378
+ sourceOwner.nodeRidHex ?? encodeRoutingIdStorageHex(sourceOwner.nodeRid),
1379
+ sourceOwner.nodeGeneration,
1380
+ sourceOwner.authorityOwnerGeneration,
1381
+ sourceOwner.ownerLeaseGeneration
1382
+ );
1383
+ let routes = this.messageFollowRoutes.get(actorId);
1384
+ if (routes === undefined) {
1385
+ routes = new Map();
1386
+ this.messageFollowRoutes.set(actorId, routes);
1387
+ }
1388
+ let owners = routes.get(key);
1389
+ if (owners === undefined) {
1390
+ owners = new Map();
1391
+ routes.set(key, owners);
1392
+ }
1393
+ const previous = owners.get(sourceOwner.ownerId);
1247
1394
  if (previous !== undefined) clearTimeout(previous.deadline);
1248
1395
  const suppressionFence = actorMessageFollowSuppressionFence(
1249
1396
  actorId,
@@ -1279,15 +1426,21 @@ export class ZLinkActorHandoffCoordinator {
1279
1426
  } else {
1280
1427
  this.messageFollowSuppression.replaceRoute(previous.suppressionFence, suppressionFence);
1281
1428
  }
1282
- this.messageFollowRoutes.set(key, entry);
1429
+ owners.set(sourceOwner.ownerId, entry);
1283
1430
  this.options.onMarker?.('message_follow_registered', actorId, this.messageFollowDurationMs);
1284
1431
  return entry;
1285
1432
  }
1286
1433
 
1287
1434
  private removeMessageFollowRoute(entry: MessageFollowRoute): void {
1288
- if (this.messageFollowRoutes.get(entry.key) !== entry) return;
1435
+ const actorId = entry.targetActorRef.actorId;
1436
+ const routes = this.messageFollowRoutes.get(actorId);
1437
+ if (routes === undefined) return;
1438
+ const owners = routes.get(entry.key);
1439
+ if (owners?.get(entry.sourceOwner.ownerId) !== entry) return;
1289
1440
  clearTimeout(entry.deadline);
1290
- this.messageFollowRoutes.delete(entry.key);
1441
+ owners.delete(entry.sourceOwner.ownerId);
1442
+ if (owners.size === 0) routes.delete(entry.key);
1443
+ if (routes.size === 0) this.messageFollowRoutes.delete(actorId);
1291
1444
  this.messageFollowSuppression.expireRoute(entry.suppressionFence);
1292
1445
  this.pruneStaleTenureRecords(entry);
1293
1446
  this.options.onMarker?.('message_follow_route_removed', entry.targetActorRef.actorId);
@@ -1326,22 +1479,54 @@ export class ZLinkActorHandoffCoordinator {
1326
1479
 
1327
1480
  private findMessageFollowRoute(
1328
1481
  actorId: string,
1329
- context: ZLinkActorMessageFollowContext | undefined
1482
+ context: ZLinkActorMessageFollowContext | undefined,
1483
+ nativeTarget?: ServiceActorRouteFence
1330
1484
  ): MessageFollowRoute | undefined {
1331
- if (context === undefined) return undefined;
1332
- return this.messageFollowRoutes.get(
1333
- messageFollowRouteKey(actorId, BigInt(context.objectGeneration), context.targetOwner)
1334
- );
1485
+ const routes = this.messageFollowRoutes.get(actorId);
1486
+ if (routes === undefined) return undefined;
1487
+ if (context === undefined) {
1488
+ if (nativeTarget === undefined || nativeTarget.actor.actorId !== actorId) return undefined;
1489
+ return routes
1490
+ .get(
1491
+ messageFollowRouteKey(
1492
+ nativeTarget.actor.generation,
1493
+ encodeRoutingIdStorageHex(nativeTarget.actor.nodeRid),
1494
+ nativeTarget.targetNodeGeneration,
1495
+ nativeTarget.authorityOwnerGeneration,
1496
+ nativeTarget.ownerLeaseGeneration
1497
+ )
1498
+ )
1499
+ ?.values()
1500
+ .next().value;
1501
+ }
1502
+ const owner = context.targetOwner;
1503
+ return routes
1504
+ .get(
1505
+ messageFollowRouteKey(
1506
+ BigInt(context.objectGeneration),
1507
+ owner.nodeRidHex ?? encodeRoutingIdStorageHex(owner.nodeRid),
1508
+ owner.nodeGeneration,
1509
+ owner.authorityOwnerGeneration,
1510
+ owner.ownerLeaseGeneration
1511
+ )
1512
+ )
1513
+ ?.get(owner.ownerId);
1335
1514
  }
1336
1515
 
1337
1516
  private hasMessageFollowRouteForStaleRef(actorId: string, actorRef: ActorRef): boolean {
1338
- return [...this.messageFollowRoutes.values()].some(
1339
- (route) =>
1340
- route.targetActorRef.actorId === actorId &&
1341
- actorRef.objectGeneration === route.oldGeneration &&
1342
- (route.oldNodeRid === undefined ||
1343
- routingIdsEqual(actorRef.nodeRid, messageFollowOwnerNodeRid(route.sourceOwner)))
1344
- );
1517
+ const routes = this.messageFollowRoutes.get(actorId);
1518
+ if (routes === undefined) return false;
1519
+ for (const owners of routes.values()) {
1520
+ for (const route of owners.values()) {
1521
+ if (
1522
+ actorRef.objectGeneration === route.oldGeneration &&
1523
+ (route.oldNodeRid === undefined ||
1524
+ routingIdsEqual(actorRef.nodeRid, messageFollowOwnerNodeRid(route.sourceOwner)))
1525
+ )
1526
+ return true;
1527
+ }
1528
+ }
1529
+ return false;
1345
1530
  }
1346
1531
 
1347
1532
  private createInitialIngressContext(
@@ -1349,9 +1534,21 @@ export class ZLinkActorHandoffCoordinator {
1349
1534
  generation: bigint,
1350
1535
  parts: readonly Message[],
1351
1536
  request: boolean,
1352
- deadlineUnixMs?: number
1537
+ deadlineUnixMs?: number,
1538
+ origin?: ZLinkMessageFollowOrigin
1353
1539
  ): ZLinkActorMessageFollowContext {
1354
- const operationId = createMessageFollowId();
1540
+ let operationId: string;
1541
+ if (origin === undefined) {
1542
+ operationId = createMessageFollowId();
1543
+ } else {
1544
+ const bytes = Buffer.allocUnsafe(OPERATION_IDENTITY_BYTES);
1545
+ bytes.writeBigUInt64BE(BigInt.asUintN(UINT64_BYTES * 8, origin.originalOperation.high));
1546
+ bytes.writeBigUInt64BE(
1547
+ BigInt.asUintN(UINT64_BYTES * 8, origin.originalOperation.low),
1548
+ UINT64_BYTES
1549
+ );
1550
+ operationId = bytes.toString('hex');
1551
+ }
1355
1552
  return Object.freeze({
1356
1553
  operationId,
1357
1554
  objectGeneration: generation.toString(),
@@ -1359,7 +1556,11 @@ export class ZLinkActorHandoffCoordinator {
1359
1556
  targetOwner: sourceOwner,
1360
1557
  deadlineUnixMs,
1361
1558
  correlationId: request ? createMessageFollowId() : undefined,
1362
- replyRouteId: request ? createMessageFollowId() : undefined,
1559
+ replyRouteId: request
1560
+ ? origin === undefined
1561
+ ? createMessageFollowId()
1562
+ : operationId
1563
+ : undefined,
1363
1564
  request,
1364
1565
  hopCount: 0,
1365
1566
  visitedOwners: Object.freeze([messageFollowOwnerFenceKey(sourceOwner)]),
@@ -1383,9 +1584,6 @@ export class ZLinkActorHandoffCoordinator {
1383
1584
  if (context.objectGeneration === '0' || context.request !== request) {
1384
1585
  throw actorLocationStale(actorId);
1385
1586
  }
1386
- if (context.deadlineUnixMs !== undefined && Date.now() >= context.deadlineUnixMs) {
1387
- throw actorDeadlineExceeded(actorId);
1388
- }
1389
1587
  verifyActorMessageFollowPayload(context, parts);
1390
1588
  }
1391
1589
 
@@ -1431,7 +1629,10 @@ export class ZLinkActorHandoffCoordinator {
1431
1629
  return BigInt(context.targetOwner.authorityOwnerGeneration);
1432
1630
  }
1433
1631
  const current = this.options.currentOwnerFence?.(actorId);
1434
- if (current !== undefined && current.nodeRid === String(actor.nodeRid)) {
1632
+ if (
1633
+ current !== undefined &&
1634
+ routingIdsEqual(messageFollowOwnerNodeRid(current), actor.nodeRid)
1635
+ ) {
1435
1636
  return BigInt(current.authorityOwnerGeneration);
1436
1637
  }
1437
1638
  return undefined;
@@ -1440,7 +1641,8 @@ export class ZLinkActorHandoffCoordinator {
1440
1641
  private enqueueMessageFollow(
1441
1642
  entry: MessageFollowRoute,
1442
1643
  actorId: string,
1443
- packet: ZLinkActorHandoffPacket
1644
+ packet: ZLinkActorHandoffPacket,
1645
+ onAdmitted?: () => void
1444
1646
  ): Promise<unknown> {
1445
1647
  const context = packet.messageFollowContext;
1446
1648
  const duplicate = entry.operations.get(context.operationId);
@@ -1453,6 +1655,7 @@ export class ZLinkActorHandoffCoordinator {
1453
1655
  this.options.onMarker?.('message_follow_rejected', actorId);
1454
1656
  return Promise.reject(actorLocationStale(actorId));
1455
1657
  }
1658
+ onAdmitted?.();
1456
1659
  return duplicate.result;
1457
1660
  }
1458
1661
  const bytes = packetBytes(packet);
@@ -1474,6 +1677,7 @@ export class ZLinkActorHandoffCoordinator {
1474
1677
  replyRouteId: context.replyRouteId,
1475
1678
  result
1476
1679
  });
1680
+ onAdmitted?.();
1477
1681
  entry.tail = entry.tail.then(async () => {
1478
1682
  try {
1479
1683
  resolve(await this.relayMessageFollow(actorId, entry, packet));
@@ -1521,15 +1725,16 @@ export class ZLinkActorHandoffCoordinator {
1521
1725
  await this.messageFollowRelayed(actorId, entry, packet, advanced);
1522
1726
  return undefined;
1523
1727
  }
1524
- const remainingMs = remainingRequestTime(actorId, packet.messageFollowContext.deadlineUnixMs);
1728
+ const timeoutMs = this.options.requestTimeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS;
1729
+ const relayDeadlineMs = performance.now() + timeoutMs;
1525
1730
  if (this.options.routedTransport.requestRawToSpot === undefined) {
1526
- const reply = await awaitBeforeDeadline(
1731
+ const reply = await waitRequestReply(
1527
1732
  this.options.routedTransport.requestToSpot<Record<string, unknown>>(target, payload, {
1528
1733
  packetName: ZLINK_REMOTE_ACTOR_PACKET_RELAY_PACKET,
1529
- timeoutMs: remainingMs ?? this.options.requestTimeoutMs
1734
+ timeoutMs
1530
1735
  }),
1531
1736
  actorId,
1532
- remainingMs
1737
+ relayDeadlineMs
1533
1738
  );
1534
1739
  if (reply.ok === false) {
1535
1740
  throw actorRelayError(actorId, reply.errorKind, reply.error);
@@ -1537,12 +1742,12 @@ export class ZLinkActorHandoffCoordinator {
1537
1742
  await this.messageFollowRelayed(actorId, entry, packet, advanced);
1538
1743
  return reply.response;
1539
1744
  }
1540
- const response = await awaitBeforeDeadline(
1745
+ const response = await waitRequestReply(
1541
1746
  requestRoutedJsonReply(
1542
1747
  this.options.routedTransport,
1543
1748
  target,
1544
1749
  payload,
1545
- { timeoutMs: remainingMs ?? this.options.requestTimeoutMs },
1750
+ { timeoutMs },
1546
1751
  `Actor Message Follow raw request is not available for '${actorId}'.`,
1547
1752
  (parts) => {
1548
1753
  if (parts.length === 0) {
@@ -1561,7 +1766,7 @@ export class ZLinkActorHandoffCoordinator {
1561
1766
  }
1562
1767
  ),
1563
1768
  actorId,
1564
- remainingMs
1769
+ relayDeadlineMs
1565
1770
  );
1566
1771
  await this.messageFollowRelayed(actorId, entry, packet, advanced);
1567
1772
  return response;
@@ -1770,35 +1975,6 @@ function packetDeadlineUnixMs(parts: readonly Message[]): number | undefined {
1770
1975
  }
1771
1976
  }
1772
1977
 
1773
- function remainingRequestTime(
1774
- actorId: string,
1775
- deadlineUnixMs: number | undefined
1776
- ): number | undefined {
1777
- if (deadlineUnixMs === undefined) return undefined;
1778
- const remaining = deadlineUnixMs - Date.now();
1779
- if (remaining <= 0) throw actorDeadlineExceeded(actorId);
1780
- return Math.max(1, Math.ceil(remaining));
1781
- }
1782
-
1783
- async function awaitBeforeDeadline<T>(
1784
- operation: Promise<T>,
1785
- actorId: string,
1786
- remainingMs: number | undefined
1787
- ): Promise<T> {
1788
- if (remainingMs === undefined) return await operation;
1789
- let timer: ReturnType<typeof setTimeout> | undefined;
1790
- try {
1791
- return await Promise.race([
1792
- operation,
1793
- new Promise<never>((_resolve, reject) => {
1794
- timer = setTimeout(() => reject(actorDeadlineExceeded(actorId)), remainingMs);
1795
- })
1796
- ]);
1797
- } finally {
1798
- if (timer !== undefined) clearTimeout(timer);
1799
- }
1800
- }
1801
-
1802
1978
  async function waitForHandoffReplayStart(start: Promise<void>, signal: AbortSignal): Promise<void> {
1803
1979
  if (signal.aborted) throw signal.reason;
1804
1980
  let abort!: () => void;
@@ -1814,11 +1990,13 @@ async function waitForHandoffReplayStart(start: Promise<void>, signal: AbortSign
1814
1990
  }
1815
1991
 
1816
1992
  function messageFollowRouteKey(
1817
- actorId: string,
1818
1993
  objectGeneration: bigint,
1819
- sourceOwner: ZLinkActorMessageFollowOwnerFence
1994
+ nodeRidHex: string,
1995
+ nodeGeneration: bigint | string,
1996
+ authorityOwnerGeneration: bigint | string,
1997
+ ownerLeaseGeneration: bigint | string
1820
1998
  ): string {
1821
- return `${actorId}\u0000${objectGeneration}\u0000${messageFollowOwnerFenceKey(sourceOwner)}`;
1999
+ return `${objectGeneration}\u0000${nodeRidHex}\u0000${nodeGeneration}\u0000${authorityOwnerGeneration}\u0000${ownerLeaseGeneration}`;
1822
2000
  }
1823
2001
 
1824
2002
  function actorRefKey(nodeRid: ActorRef['nodeRid'], generation: bigint): string {
@@ -1841,7 +2019,10 @@ function requestSourcesEqual(
1841
2019
  expected.replyRouteId === actual.replyRouteId &&
1842
2020
  expected.ownerId === actual.ownerId &&
1843
2021
  expected.ownerLeaseGeneration === actual.ownerLeaseGeneration &&
1844
- expected.nodeRid === actual.nodeRid &&
2022
+ routingIdsEqual(
2023
+ decodeRoutingId(expected.nodeRid, expected.nodeRidHex),
2024
+ decodeRoutingId(actual.nodeRid, actual.nodeRidHex)
2025
+ ) &&
1845
2026
  expected.nodeGeneration === actual.nodeGeneration &&
1846
2027
  /^[1-9][0-9]*$/.test(actual.ownerLeaseGeneration) &&
1847
2028
  /^[1-9][0-9]*$/.test(actual.nodeGeneration)