@zlink-systems/framework 0.30.1 → 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 (340) hide show
  1. package/dist/.tsbuildinfo +1 -1
  2. package/dist/contracts/Common/ZLinkEncodedPayload.d.ts +6 -0
  3. package/dist/contracts/Common/ZLinkEncodedPayload.js +18 -3
  4. package/dist/contracts/Common/encoded-payload-storage.d.ts +1 -1
  5. package/dist/contracts/Common/encoded-payload-storage.js +5 -2
  6. package/dist/contracts/Configuration/Builders.d.ts +1 -1
  7. package/dist/contracts/Configuration/RegistrationBuilderPolicy.d.ts +2 -1
  8. package/dist/contracts/Configuration/RegistrationBuilderPolicy.js +5 -1
  9. package/dist/contracts/Configuration/RegistrationBuilders.js +2 -2
  10. package/dist/contracts/Configuration/RegistrationTypes.d.ts +1 -0
  11. package/dist/contracts/Dispatch/ZLinkDispatchOptions.d.ts +2 -2
  12. package/dist/contracts/Locations/Rows.d.ts +2 -0
  13. package/dist/contracts/Spots/Contracts.d.ts +4 -0
  14. package/dist/contracts/Spots/ZLinkSpot.d.ts +3 -3
  15. package/dist/runtime/abort.d.ts +5 -0
  16. package/dist/runtime/abort.js +10 -0
  17. package/dist/runtime/actors/actor-authority-publication.js +3 -2
  18. package/dist/runtime/actors/actor-client.d.ts +0 -1
  19. package/dist/runtime/actors/actor-client.js +38 -45
  20. package/dist/runtime/actors/actor-context.d.ts +2 -0
  21. package/dist/runtime/actors/actor-context.js +46 -9
  22. package/dist/runtime/actors/actor-handoff.d.ts +7 -3
  23. package/dist/runtime/actors/actor-handoff.js +212 -88
  24. package/dist/runtime/actors/actor-join-relocation.d.ts +2 -0
  25. package/dist/runtime/actors/actor-local-native-join.js +4 -0
  26. package/dist/runtime/actors/actor-mailbox.js +27 -1
  27. package/dist/runtime/actors/actor-remote-joiner.js +3 -1
  28. package/dist/runtime/actors/actor-reply.d.ts +4 -0
  29. package/dist/runtime/actors/actor-reply.js +29 -0
  30. package/dist/runtime/actors/actor-runtime-contracts.d.ts +2 -0
  31. package/dist/runtime/actors/actor-runtime-state.js +2 -20
  32. package/dist/runtime/actors/actor-source-transfer.d.ts +1 -17
  33. package/dist/runtime/actors/index.d.ts +6 -2
  34. package/dist/runtime/actors/index.js +37 -21
  35. package/dist/runtime/actors/session-disconnected-wire.d.ts +8 -0
  36. package/dist/runtime/actors/session-disconnected-wire.js +48 -0
  37. package/dist/runtime/admission.d.ts +9 -1
  38. package/dist/runtime/admission.js +55 -32
  39. package/dist/runtime/application-jobs/application-job-queue-scope.d.ts +13 -0
  40. package/dist/runtime/application-jobs/application-job-queue-scope.js +27 -1
  41. package/dist/runtime/application-jobs/contracts.d.ts +2 -0
  42. package/dist/runtime/backend/contracts/index.d.ts +19 -3
  43. package/dist/runtime/backend/mesh-actor-session-node-adapter.js +2 -2
  44. package/dist/runtime/backend/mesh-completion-table.js +5 -0
  45. package/dist/runtime/backend/mesh-dispatch-pump.d.ts +26 -2
  46. package/dist/runtime/backend/mesh-dispatch-pump.js +193 -107
  47. package/dist/runtime/backend/node/node-raw-binding-port.js +90 -58
  48. package/dist/runtime/backend/node/node-raw-mesh-backend.d.ts +33 -8
  49. package/dist/runtime/backend/node/node-raw-mesh-backend.js +142 -143
  50. package/dist/runtime/backend/node/node-socket-backend-adapter.d.ts +1 -1
  51. package/dist/runtime/backend/node/node-socket-backend-adapter.js +5 -5
  52. package/dist/runtime/channels/channel-clients.d.ts +1 -0
  53. package/dist/runtime/channels/channel-clients.js +20 -5
  54. package/dist/runtime/channels/channel-dispatch-pipeline.d.ts +22 -3
  55. package/dist/runtime/channels/channel-dispatch-pipeline.js +103 -57
  56. package/dist/runtime/channels/channel-dispatchers.d.ts +3 -2
  57. package/dist/runtime/channels/channel-dispatchers.js +44 -37
  58. package/dist/runtime/channels/channel-envelope.d.ts +1 -0
  59. package/dist/runtime/channels/channel-envelope.js +74 -31
  60. package/dist/runtime/channels/channel-runtime-lifecycle.d.ts +4 -3
  61. package/dist/runtime/channels/channel-runtime-lifecycle.js +19 -24
  62. package/dist/runtime/channels/channel-runtime-manager.d.ts +3 -2
  63. package/dist/runtime/channels/channel-runtime-manager.js +4 -4
  64. package/dist/runtime/channels/channel-transports.d.ts +0 -1
  65. package/dist/runtime/channels/channel-transports.js +35 -33
  66. package/dist/runtime/channels/client-server-location-runtime.js +5 -4
  67. package/dist/runtime/channels/dispatch-error-reporter.d.ts +2 -1
  68. package/dist/runtime/channels/dispatch-error-reporter.js +2 -1
  69. package/dist/runtime/channels/fanout-location-runtime.d.ts +1 -1
  70. package/dist/runtime/channels/fanout-location-runtime.js +3 -3
  71. package/dist/runtime/diagnostics/flow-context.js +19 -7
  72. package/dist/runtime/diagnostics/index.js +4 -9
  73. package/dist/runtime/diagnostics/message-flow.d.ts +8 -0
  74. package/dist/runtime/diagnostics/message-flow.js +35 -5
  75. package/dist/runtime/diagnostics/runtime-metrics.d.ts +2 -2
  76. package/dist/runtime/diagnostics/runtime-metrics.js +10 -8
  77. package/dist/runtime/execution/index.d.ts +4 -2
  78. package/dist/runtime/execution/index.js +33 -10
  79. package/dist/runtime/execution/serial-execution-queue.d.ts +4 -0
  80. package/dist/runtime/execution/serial-execution-queue.js +21 -2
  81. package/dist/runtime/execution/state-lane.d.ts +2 -0
  82. package/dist/runtime/execution/state-lane.js +5 -0
  83. package/dist/runtime/foundation/operation-registry.d.ts +25 -1
  84. package/dist/runtime/foundation/operation-registry.js +86 -18
  85. package/dist/runtime/foundation/raw-service-mesh-runtime.d.ts +39 -3
  86. package/dist/runtime/foundation/raw-service-mesh-runtime.js +151 -55
  87. package/dist/runtime/foundation/service-liveness-registry.d.ts +12 -1
  88. package/dist/runtime/foundation/service-liveness-registry.js +38 -0
  89. package/dist/runtime/foundation/service-mailbox.d.ts +7 -0
  90. package/dist/runtime/foundation/service-maintenance-runtime.js +1 -6
  91. package/dist/runtime/foundation/service-relocation-object-owner.d.ts +2 -3
  92. package/dist/runtime/foundation/service-relocation-object-owner.js +48 -35
  93. package/dist/runtime/foundation/service-relocation-runtime.js +7 -3
  94. package/dist/runtime/foundation/service-runtime-contracts.d.ts +8 -1
  95. package/dist/runtime/foundation/service-session-binding-ingress-port.d.ts +2 -1
  96. package/dist/runtime/foundation/service-stateful-registry.d.ts +5 -4
  97. package/dist/runtime/foundation/service-stateful-registry.js +24 -26
  98. package/dist/runtime/foundation/service-stateful-runtime.d.ts +72 -6
  99. package/dist/runtime/foundation/service-stateful-runtime.js +444 -117
  100. package/dist/runtime/foundation/service-stateful-wire-codec.d.ts +14 -1
  101. package/dist/runtime/foundation/service-stateful-wire-codec.js +48 -27
  102. package/dist/runtime/foundation/service-wire-binary-primitives.d.ts +6 -1
  103. package/dist/runtime/foundation/service-wire-binary-primitives.js +27 -11
  104. package/dist/runtime/foundation/service-wire-constants.generated.d.ts +1 -0
  105. package/dist/runtime/foundation/service-wire-constants.generated.js +1 -0
  106. package/dist/runtime/foundation/service-wire-m6a-codec.d.ts +10 -0
  107. package/dist/runtime/foundation/service-wire-m6a-codec.js +166 -53
  108. package/dist/runtime/host/actor-packet-relay.d.ts +6 -4
  109. package/dist/runtime/host/actor-packet-relay.js +59 -72
  110. package/dist/runtime/host/actor-placement-coordinator.js +25 -8
  111. package/dist/runtime/host/actor-transfer-runtime.d.ts +7 -31
  112. package/dist/runtime/host/actor-transfer-runtime.js +85 -331
  113. package/dist/runtime/host/application-job-queue.d.ts +24 -3
  114. package/dist/runtime/host/application-job-queue.js +28 -41
  115. package/dist/runtime/host/index.d.ts +5 -1
  116. package/dist/runtime/host/index.js +171 -97
  117. package/dist/runtime/host/location-runtime-owner.js +2 -6
  118. package/dist/runtime/host/mesh-router-resolver.d.ts +4 -0
  119. package/dist/runtime/host/mesh-router-resolver.js +14 -6
  120. package/dist/runtime/host/remote-bound-session-relay.d.ts +2 -4
  121. package/dist/runtime/host/remote-bound-session-relay.js +71 -190
  122. package/dist/runtime/host/route-mesh-runtime.d.ts +2 -2
  123. package/dist/runtime/host/route-mesh-runtime.js +5 -3
  124. package/dist/runtime/host/runtime-shutdown.d.ts +1 -0
  125. package/dist/runtime/host/runtime-shutdown.js +3 -2
  126. package/dist/runtime/host/service-relocation-host-runtime.d.ts +17 -7
  127. package/dist/runtime/host/service-relocation-host-runtime.js +550 -367
  128. package/dist/runtime/host/spot-runtime-options-factory.js +15 -7
  129. package/dist/runtime/host/user-spot-creation-coordinator.js +33 -84
  130. package/dist/runtime/locations/auto-connect-loop.d.ts +2 -0
  131. package/dist/runtime/locations/auto-connect-loop.js +22 -14
  132. package/dist/runtime/locations/auto-connect-reconciler.js +0 -6
  133. package/dist/runtime/locations/auto-connect-types.d.ts +0 -1
  134. package/dist/runtime/locations/descriptor-publication.d.ts +4 -0
  135. package/dist/runtime/locations/descriptor-publication.js +11 -0
  136. package/dist/runtime/locations/domain-store-contract.d.ts +1 -0
  137. package/dist/runtime/locations/in-memory-authority-store.d.ts +7 -1
  138. package/dist/runtime/locations/in-memory-authority-store.js +56 -19
  139. package/dist/runtime/locations/in-memory-location-store.js +1 -10
  140. package/dist/runtime/locations/index.d.ts +1 -0
  141. package/dist/runtime/locations/index.js +1 -0
  142. package/dist/runtime/locations/lease-tracker.js +1 -6
  143. package/dist/runtime/locations/location-store-repository.d.ts +51 -1
  144. package/dist/runtime/locations/location-store-repository.js +363 -139
  145. package/dist/runtime/locations/relocation-blob.d.ts +18 -1
  146. package/dist/runtime/locations/relocation-blob.js +52 -1
  147. package/dist/runtime/locations/request-source-resolver.d.ts +37 -0
  148. package/dist/runtime/locations/request-source-resolver.js +80 -0
  149. package/dist/runtime/locations/resolvers.js +1 -1
  150. package/dist/runtime/locations/runtime.d.ts +6 -2
  151. package/dist/runtime/locations/runtime.js +37 -30
  152. package/dist/runtime/messaging/payload-codec.d.ts +7 -1
  153. package/dist/runtime/messaging/payload-codec.js +7 -6
  154. package/dist/runtime/messaging/request-result.js +29 -26
  155. package/dist/runtime/protocol/service_wire_codec.generated.d.ts +19 -1
  156. package/dist/runtime/protocol/service_wire_codec.generated.js +85 -0
  157. package/dist/runtime/protocol/service_wire_pilot_codec.generated.d.ts +7 -1
  158. package/dist/runtime/protocol/service_wire_pilot_codec.generated.js +23 -7
  159. package/dist/runtime/spots/formal-remote-actor-admission-registry.js +3 -2
  160. package/dist/runtime/spots/index.d.ts +18 -11
  161. package/dist/runtime/spots/index.js +234 -176
  162. package/dist/runtime/spots/spot-activation-registry.d.ts +4 -2
  163. package/dist/runtime/spots/spot-activation-registry.js +21 -11
  164. package/dist/runtime/spots/spot-activation-state.d.ts +1 -1
  165. package/dist/runtime/spots/spot-activation-state.js +7 -7
  166. package/dist/runtime/spots/spot-activation.d.ts +6 -3
  167. package/dist/runtime/spots/spot-activation.js +123 -44
  168. package/dist/runtime/spots/spot-actor-admission-coordinator.d.ts +1 -0
  169. package/dist/runtime/spots/spot-actor-admission-coordinator.js +13 -22
  170. package/dist/runtime/spots/spot-actor-membership.d.ts +0 -1
  171. package/dist/runtime/spots/spot-actor-membership.js +0 -8
  172. package/dist/runtime/spots/spot-actor-packet-dispatch.js +33 -8
  173. package/dist/runtime/spots/spot-actor-packet-drain.js +5 -33
  174. package/dist/runtime/spots/spot-entry-activation.d.ts +2 -0
  175. package/dist/runtime/spots/spot-entry-activation.js +14 -9
  176. package/dist/runtime/spots/spot-handler-registry.d.ts +4 -3
  177. package/dist/runtime/spots/spot-handler-registry.js +6 -2
  178. package/dist/runtime/spots/spot-manager-internal-contracts.d.ts +2 -2
  179. package/dist/runtime/spots/spot-manager-public.js +2 -2
  180. package/dist/runtime/spots/spot-node-autoconnect.d.ts +2 -1
  181. package/dist/runtime/spots/spot-node-autoconnect.js +18 -39
  182. package/dist/runtime/spots/spot-node-runtime-manager.d.ts +19 -2
  183. package/dist/runtime/spots/spot-node-runtime-manager.js +115 -50
  184. package/dist/runtime/spots/spot-outbound.js +3 -3
  185. package/dist/runtime/spots/spot-remote-codec.js +5 -1
  186. package/dist/runtime/spots/spot-runtime-ports.d.ts +0 -1
  187. package/dist/runtime/spots/spot-serial-executor.d.ts +10 -0
  188. package/dist/runtime/spots/spot-serial-executor.js +61 -8
  189. package/dist/runtime/spots/spot-serial-turn-executor.js +19 -2
  190. package/dist/runtime/spots/spot-subscription-dispatch.js +1 -1
  191. package/dist/runtime/spots/spot-timer.d.ts +57 -5
  192. package/dist/runtime/spots/spot-timer.js +287 -103
  193. package/dist/runtime/streams/actor-session-binding-registry.d.ts +42 -11
  194. package/dist/runtime/streams/actor-session-binding-registry.js +165 -48
  195. package/dist/runtime/streams/actor-session-binding-runtime-owner.d.ts +8 -4
  196. package/dist/runtime/streams/bound-actor-relay-sender.d.ts +2 -1
  197. package/dist/runtime/streams/bound-actor-relay-sender.js +15 -8
  198. package/dist/runtime/streams/bound-session-service.d.ts +1 -1
  199. package/dist/runtime/streams/bound-session-service.js +6 -11
  200. package/dist/runtime/streams/index.d.ts +3 -2
  201. package/dist/runtime/streams/index.js +6 -4
  202. package/dist/runtime/streams/managed-stream.js +3 -2
  203. package/dist/runtime/streams/native-fallback-bound-session.js +8 -73
  204. package/dist/runtime/streams/session-actor-coordinator.d.ts +2 -8
  205. package/dist/runtime/streams/session-actor-coordinator.js +15 -32
  206. package/dist/runtime/streams/stream-binding-runtime-ports.d.ts +3 -10
  207. package/dist/runtime/streams/stream-session-runtime.js +1 -4
  208. package/dist/runtime/workers/index.js +1 -1
  209. package/package.json +3 -3
  210. package/src/contracts/Common/ZLinkEncodedPayload.ts +24 -4
  211. package/src/contracts/Common/encoded-payload-storage.ts +6 -3
  212. package/src/contracts/Configuration/Builders.ts +4 -1
  213. package/src/contracts/Configuration/RegistrationBuilderPolicy.ts +7 -2
  214. package/src/contracts/Configuration/RegistrationBuilders.ts +6 -2
  215. package/src/contracts/Configuration/RegistrationTypes.ts +1 -0
  216. package/src/contracts/Dispatch/ZLinkDispatchOptions.ts +2 -1
  217. package/src/contracts/Locations/Rows.ts +2 -0
  218. package/src/contracts/Spots/Contracts.ts +8 -0
  219. package/src/contracts/Spots/ZLinkSpot.ts +3 -3
  220. package/src/runtime/abort.ts +12 -0
  221. package/src/runtime/actors/actor-authority-publication.ts +3 -2
  222. package/src/runtime/actors/actor-client.ts +61 -70
  223. package/src/runtime/actors/actor-context.ts +49 -9
  224. package/src/runtime/actors/actor-handoff.ts +282 -106
  225. package/src/runtime/actors/actor-join-relocation.ts +2 -0
  226. package/src/runtime/actors/actor-local-native-join.ts +4 -0
  227. package/src/runtime/actors/actor-mailbox.ts +40 -2
  228. package/src/runtime/actors/actor-remote-joiner.ts +6 -1
  229. package/src/runtime/actors/actor-reply.ts +42 -0
  230. package/src/runtime/actors/actor-runtime-contracts.ts +2 -0
  231. package/src/runtime/actors/actor-runtime-state.ts +2 -20
  232. package/src/runtime/actors/actor-source-transfer.ts +1 -34
  233. package/src/runtime/actors/index.ts +41 -27
  234. package/src/runtime/actors/session-disconnected-wire.ts +66 -0
  235. package/src/runtime/admission.ts +69 -34
  236. package/src/runtime/application-jobs/application-job-queue-scope.ts +33 -1
  237. package/src/runtime/application-jobs/contracts.ts +2 -0
  238. package/src/runtime/backend/contracts/index.ts +39 -4
  239. package/src/runtime/backend/mesh-actor-session-node-adapter.ts +5 -3
  240. package/src/runtime/backend/mesh-completion-table.ts +4 -0
  241. package/src/runtime/backend/mesh-dispatch-pump.ts +223 -124
  242. package/src/runtime/backend/node/node-raw-binding-port.ts +106 -70
  243. package/src/runtime/backend/node/node-raw-mesh-backend.ts +221 -170
  244. package/src/runtime/backend/node/node-socket-backend-adapter.ts +5 -5
  245. package/src/runtime/channels/channel-clients.ts +49 -24
  246. package/src/runtime/channels/channel-dispatch-pipeline.ts +173 -124
  247. package/src/runtime/channels/channel-dispatchers.ts +116 -72
  248. package/src/runtime/channels/channel-envelope.ts +105 -36
  249. package/src/runtime/channels/channel-runtime-lifecycle.ts +13 -13
  250. package/src/runtime/channels/channel-runtime-manager.ts +12 -5
  251. package/src/runtime/channels/channel-transports.ts +49 -58
  252. package/src/runtime/channels/client-server-location-runtime.ts +11 -10
  253. package/src/runtime/channels/dispatch-error-reporter.ts +4 -2
  254. package/src/runtime/channels/fanout-location-runtime.ts +17 -9
  255. package/src/runtime/diagnostics/flow-context.ts +20 -7
  256. package/src/runtime/diagnostics/index.ts +1 -7
  257. package/src/runtime/diagnostics/message-flow.ts +47 -9
  258. package/src/runtime/diagnostics/runtime-metrics.ts +12 -10
  259. package/src/runtime/execution/index.ts +40 -14
  260. package/src/runtime/execution/serial-execution-queue.ts +31 -4
  261. package/src/runtime/execution/state-lane.ts +7 -0
  262. package/src/runtime/foundation/operation-registry.ts +98 -20
  263. package/src/runtime/foundation/raw-service-mesh-runtime.ts +244 -67
  264. package/src/runtime/foundation/service-liveness-registry.ts +39 -0
  265. package/src/runtime/foundation/service-mailbox.ts +8 -0
  266. package/src/runtime/foundation/service-maintenance-runtime.ts +1 -8
  267. package/src/runtime/foundation/service-relocation-object-owner.ts +54 -37
  268. package/src/runtime/foundation/service-relocation-runtime.ts +7 -3
  269. package/src/runtime/foundation/service-runtime-contracts.ts +12 -1
  270. package/src/runtime/foundation/service-session-binding-ingress-port.ts +2 -1
  271. package/src/runtime/foundation/service-stateful-registry.ts +38 -35
  272. package/src/runtime/foundation/service-stateful-runtime.ts +667 -152
  273. package/src/runtime/foundation/service-stateful-wire-codec.ts +49 -11
  274. package/src/runtime/foundation/service-wire-binary-primitives.ts +35 -12
  275. package/src/runtime/foundation/service-wire-constants.generated.ts +1 -0
  276. package/src/runtime/foundation/service-wire-m6a-codec.ts +187 -51
  277. package/src/runtime/host/actor-packet-relay.ts +113 -94
  278. package/src/runtime/host/actor-placement-coordinator.ts +31 -8
  279. package/src/runtime/host/actor-transfer-runtime.ts +104 -430
  280. package/src/runtime/host/application-job-queue.ts +29 -44
  281. package/src/runtime/host/index.ts +286 -129
  282. package/src/runtime/host/location-runtime-owner.ts +2 -6
  283. package/src/runtime/host/mesh-router-resolver.ts +13 -5
  284. package/src/runtime/host/remote-bound-session-relay.ts +86 -248
  285. package/src/runtime/host/route-mesh-runtime.ts +11 -5
  286. package/src/runtime/host/runtime-shutdown.ts +15 -4
  287. package/src/runtime/host/service-relocation-host-runtime.ts +784 -475
  288. package/src/runtime/host/spot-runtime-options-factory.ts +18 -7
  289. package/src/runtime/host/user-spot-creation-coordinator.ts +41 -100
  290. package/src/runtime/locations/auto-connect-loop.ts +22 -14
  291. package/src/runtime/locations/auto-connect-reconciler.ts +0 -6
  292. package/src/runtime/locations/auto-connect-types.ts +0 -1
  293. package/src/runtime/locations/descriptor-publication.ts +7 -0
  294. package/src/runtime/locations/domain-store-contract.ts +5 -0
  295. package/src/runtime/locations/in-memory-authority-store.ts +85 -23
  296. package/src/runtime/locations/in-memory-location-store.ts +1 -12
  297. package/src/runtime/locations/index.ts +1 -0
  298. package/src/runtime/locations/lease-tracker.ts +2 -9
  299. package/src/runtime/locations/location-store-repository.ts +628 -152
  300. package/src/runtime/locations/relocation-blob.ts +75 -1
  301. package/src/runtime/locations/request-source-resolver.ts +138 -0
  302. package/src/runtime/locations/resolvers.ts +2 -2
  303. package/src/runtime/locations/runtime.ts +70 -40
  304. package/src/runtime/messaging/payload-codec.ts +8 -11
  305. package/src/runtime/messaging/request-result.ts +33 -29
  306. package/src/runtime/protocol/service_wire_codec.generated.ts +87 -4
  307. package/src/runtime/protocol/service_wire_pilot_codec.generated.ts +13 -10
  308. package/src/runtime/spots/formal-remote-actor-admission-registry.ts +3 -2
  309. package/src/runtime/spots/index.ts +375 -281
  310. package/src/runtime/spots/spot-activation-registry.ts +25 -13
  311. package/src/runtime/spots/spot-activation-state.ts +12 -19
  312. package/src/runtime/spots/spot-activation.ts +170 -86
  313. package/src/runtime/spots/spot-actor-admission-coordinator.ts +25 -55
  314. package/src/runtime/spots/spot-actor-membership.ts +0 -15
  315. package/src/runtime/spots/spot-actor-packet-dispatch.ts +56 -11
  316. package/src/runtime/spots/spot-actor-packet-drain.ts +9 -52
  317. package/src/runtime/spots/spot-entry-activation.ts +24 -19
  318. package/src/runtime/spots/spot-handler-registry.ts +15 -4
  319. package/src/runtime/spots/spot-manager-internal-contracts.ts +2 -2
  320. package/src/runtime/spots/spot-manager-public.ts +2 -2
  321. package/src/runtime/spots/spot-node-autoconnect.ts +22 -45
  322. package/src/runtime/spots/spot-node-runtime-manager.ts +197 -67
  323. package/src/runtime/spots/spot-outbound.ts +3 -3
  324. package/src/runtime/spots/spot-remote-codec.ts +9 -2
  325. package/src/runtime/spots/spot-runtime-ports.ts +0 -1
  326. package/src/runtime/spots/spot-serial-executor.ts +97 -25
  327. package/src/runtime/spots/spot-serial-turn-executor.ts +22 -3
  328. package/src/runtime/spots/spot-subscription-dispatch.ts +1 -1
  329. package/src/runtime/spots/spot-timer.ts +413 -157
  330. package/src/runtime/streams/actor-session-binding-registry.ts +236 -64
  331. package/src/runtime/streams/actor-session-binding-runtime-owner.ts +16 -8
  332. package/src/runtime/streams/bound-actor-relay-sender.ts +23 -9
  333. package/src/runtime/streams/bound-session-service.ts +7 -10
  334. package/src/runtime/streams/index.ts +12 -6
  335. package/src/runtime/streams/managed-stream.ts +4 -2
  336. package/src/runtime/streams/native-fallback-bound-session.ts +14 -103
  337. package/src/runtime/streams/session-actor-coordinator.ts +39 -88
  338. package/src/runtime/streams/stream-binding-runtime-ports.ts +3 -9
  339. package/src/runtime/streams/stream-session-runtime.ts +1 -5
  340. package/src/runtime/workers/index.ts +1 -1
@@ -228,10 +228,6 @@ export class ZLinkLocationRuntimeOwner {
228
228
  this.options.registration.locations.options,
229
229
  this.currentEvents
230
230
  );
231
- if (runtime.ownerLeaseUsable) {
232
- await spotNodeRuntime.startLocationAutoConnect();
233
- await channelRuntime.startLocationAutoConnect();
234
- }
235
231
  return runtime;
236
232
  }
237
233
 
@@ -252,7 +248,7 @@ export class ZLinkLocationRuntimeOwner {
252
248
  const locations = this.options.registration.locations;
253
249
  if (locations.useInMemoryStores) {
254
250
  const provider = new ZLinkInMemoryProviderLocationStore();
255
- const store = new ZLinkLocationStoreRepository(provider);
251
+ const store = new ZLinkLocationStoreRepository(provider, undefined, this.options.metrics);
256
252
  return {
257
253
  locationStore: store,
258
254
  authorityStore: store,
@@ -267,7 +263,7 @@ export class ZLinkLocationRuntimeOwner {
267
263
  }
268
264
  const provider = locations.storeInstance;
269
265
  if (provider !== undefined) {
270
- const store = new ZLinkLocationStoreRepository(provider);
266
+ const store = new ZLinkLocationStoreRepository(provider, undefined, this.options.metrics);
271
267
  return {
272
268
  locationStore: store,
273
269
  authorityStore: store,
@@ -13,14 +13,22 @@ export class MeshRouterResolver {
13
13
  );
14
14
  }
15
15
 
16
+ /**
17
+ * Runs on every node-direct send: a direct scan of the registered manual
18
+ * peers, without temporary arrays or a predicate closure per call.
19
+ */
16
20
  classifyManualNodeTarget(meshName: string, targetNodeRid: RoutingId): boolean | undefined {
17
21
  const router = this.registration.spotNodes.get(meshName)?.router;
18
22
  if (router === undefined) return undefined;
19
- const manualConnections = router.manualConnections ?? [];
20
- const manualPeers = router.manualPeerConnections ?? [];
21
- if (manualConnections.length === 0 && manualPeers.length === 0) return undefined;
22
- if (manualPeers.some((peer) => routingIdsEqual(peer.peerRid, targetNodeRid))) return true;
23
- return manualConnections.length === 0 ? false : undefined;
23
+ const manualPeers = router.manualPeerConnections;
24
+ if (manualPeers !== undefined) {
25
+ for (const peer of manualPeers) {
26
+ if (routingIdsEqual(peer.peerRid, targetNodeRid)) return true;
27
+ }
28
+ }
29
+ const manualConnectionCount = router.manualConnections?.length ?? 0;
30
+ if (manualConnectionCount === 0 && (manualPeers?.length ?? 0) === 0) return undefined;
31
+ return manualConnectionCount === 0 ? false : undefined;
24
32
  }
25
33
 
26
34
  defaultRouterChannelId(): string | undefined {
@@ -26,18 +26,15 @@ import {
26
26
  ZLinkRemoteBoundSessionFenceError
27
27
  } from '../actors/bound-session-wire';
28
28
  import { encodeRemoteActorPacketTarget } from '../actors/actor-packet-relay-wire';
29
- import { decodeRoutingId as decodeWireRoutingId, routingIdsEqual } from '../routing-id';
29
+ import { routingIdsEqual } from '../routing-id';
30
30
  import type { MeshRouterResolver } from './mesh-router-resolver';
31
31
  import {
32
- encodeSessionRelocationRoute,
33
- encodeSessionRelocationSeal,
34
32
  serviceSessionRelocationIdentityKey,
35
33
  type ServiceSessionRelocationRoute,
36
34
  type ServiceSessionRelocationSeal,
37
35
  type ServiceSessionRelocationSealed
38
36
  } from '../foundation/service-stateful-wire-codec';
39
37
  import { ServiceWireProtocolError } from '../foundation/service-wire-m6a-codec';
40
- import { BoundedReplayMap } from './bounded-replay-map';
41
38
  import {
42
39
  ZLinkFrameworkInternalErrorKind,
43
40
  createInternalFrameworkException
@@ -58,29 +55,12 @@ export interface ZLinkRemoteBoundSessionRelayOptions {
58
55
  readonly reportOwnershipRefreshError?: (actorId: string, error: unknown) => void;
59
56
  }
60
57
 
61
- const SERVICE_CONTROL_TERMINAL_CAPACITY = 4096;
62
-
63
58
  interface ActiveServiceWireSessionRelocation {
64
59
  readonly actorId: string;
65
- readonly sealFingerprint: string;
66
60
  readonly sealPromise: Promise<ServiceSessionRelocationSealed>;
67
- sealed?: ServiceSessionRelocationSealed;
68
61
  sealTimer?: ReturnType<typeof setTimeout>;
69
- sealController?: AbortController;
70
62
  sealAbortCleanup?: () => void;
71
63
  terminal?: boolean;
72
- routeRequestFingerprint?: string;
73
- routeFingerprint?: string;
74
- routePromise?: Promise<void>;
75
- }
76
-
77
- interface TerminalServiceWireSessionRelocation {
78
- readonly actorId: string;
79
- readonly sealFingerprint: string;
80
- readonly sealed: ServiceSessionRelocationSealed;
81
- /** Absent only when the Session seal timed out before command 44 arrived. */
82
- readonly routeRequestFingerprint?: string;
83
- readonly routeFingerprint?: string;
84
64
  }
85
65
 
86
66
  type RemoteBoundSessionSend = ReturnType<typeof decodeRemoteBoundSessionSendPayload>;
@@ -91,10 +71,6 @@ export class ZLinkRemoteBoundSessionRelay {
91
71
  string,
92
72
  ActiveServiceWireSessionRelocation
93
73
  >();
94
- private readonly terminalServiceWireRelocations = new BoundedReplayMap<
95
- string,
96
- TerminalServiceWireSessionRelocation
97
- >(SERVICE_CONTROL_TERMINAL_CAPACITY);
98
74
 
99
75
  constructor(private readonly options: ZLinkRemoteBoundSessionRelayOptions) {}
100
76
 
@@ -255,86 +231,42 @@ export class ZLinkRemoteBoundSessionRelay {
255
231
 
256
232
  async receiveServiceWireSessionRelocationSeal(
257
233
  value: ServiceSessionRelocationSeal,
258
- signal?: AbortSignal
259
- ): Promise<ServiceSessionRelocationSealed> {
234
+ signal?: AbortSignal,
235
+ onInstalled?: () => void
236
+ ): Promise<ServiceSessionRelocationSealed | undefined> {
237
+ const runtime = this.options.streamBindingRuntime();
238
+ const owner = actorSessionBindingRuntimeOwner(runtime);
239
+ const sealController = new AbortController();
240
+ const sealSignal =
241
+ signal === undefined
242
+ ? sealController.signal
243
+ : AbortSignal.any([signal, sealController.signal]);
244
+ const prepared = await owner.prepareSessionRelocationSeal(value, sealSignal);
245
+ if (prepared === undefined) return undefined;
246
+ if (prepared.response.sealResult === 'bindingAbsent') return prepared.response;
260
247
  const key = serviceWireBarrierKey(value);
261
- const fingerprint = encodeSessionRelocationSeal(value).toString('base64');
262
- const terminal = this.terminalServiceWireRelocations.get(key);
263
- if (terminal !== undefined) {
264
- if (terminal.sealFingerprint !== fingerprint) {
265
- throw new ServiceWireProtocolError(
266
- `Session relocation '${key}' repeated command 42 with different bytes.`
267
- );
268
- }
269
- this.terminalServiceWireRelocations.touch(key);
270
- return terminal.sealed;
271
- }
272
- const active = this.activeServiceWireRelocations.get(key);
273
- if (active !== undefined) {
274
- if (active.sealFingerprint !== fingerprint) {
275
- throw new ServiceWireProtocolError(
276
- `Session relocation '${key}' repeated command 42 with different bytes.`
277
- );
278
- }
279
- return await active.sealPromise;
280
- }
248
+ const existing = this.activeServiceWireRelocations.get(key);
249
+ if (existing !== undefined) return await existing.sealPromise;
281
250
  const actorId = value.actor.actor.actorId;
282
-
283
- // Register the identity before the first asynchronous owner operation.
284
- // Concurrent identical commands join this promise; different bytes for
285
- // the same identity fail before they can install another seal.
286
- let state!: ActiveServiceWireSessionRelocation;
287
- const sealController = new AbortController();
288
- const sealPromise = Promise.resolve().then(async () => {
289
- await this.validateServiceWireSessionRoute(value);
290
- await actorSessionBindingRuntimeOwner(this.options.streamBindingRuntime()).sealRelocation(
291
- {
292
- actorId,
293
- actorGeneration: value.actor.actor.generation,
294
- bindingGeneration: value.session.bindingGeneration,
295
- sessionIdentity: value.session.sessionRid,
296
- actorNodeRid: value.actor.actor.nodeRid,
297
- actorNodeGeneration: value.actor.targetNodeGeneration,
298
- sealId: key
299
- },
300
- {
301
- objectGeneration: value.actor.actor.generation,
302
- bindingGeneration: value.session.bindingGeneration
303
- },
304
- sealController.signal
305
- );
306
- return {
307
- relocation: value.relocation,
308
- coordinator: value.coordinator,
309
- actor: value.actor,
310
- session: value.session
311
- } satisfies ServiceSessionRelocationSealed;
312
- });
313
- state = {
251
+ const state: ActiveServiceWireSessionRelocation = {
314
252
  actorId,
315
- sealFingerprint: fingerprint,
316
- sealPromise,
317
- sealController
253
+ sealPromise: prepared.ready.then(() => prepared.response)
318
254
  };
319
255
  this.activeServiceWireRelocations.set(key, state);
256
+ onInstalled?.();
320
257
  const expire = async (error: unknown): Promise<void> => {
321
- if (state.terminal === true || state.routePromise !== undefined) return;
258
+ if (
259
+ state.terminal === true ||
260
+ (await owner.relocationSnapshot(actorId, key))?.phase !== 'sealed'
261
+ )
262
+ return;
322
263
  state.terminal = true;
323
264
  sealController.abort(error);
324
265
  if (this.activeServiceWireRelocations.get(key) === state) {
325
266
  this.activeServiceWireRelocations.delete(key);
326
267
  }
327
- if (state.sealed !== undefined) {
328
- this.terminalServiceWireRelocations.remember(key, {
329
- actorId,
330
- sealFingerprint: state.sealFingerprint,
331
- sealed: state.sealed
332
- });
333
- }
334
- const owner = actorSessionBindingRuntimeOwner(this.options.streamBindingRuntime());
335
- await owner.clearRelocation(actorId, error);
336
- void this.options
337
- .streamBindingRuntime()
268
+ await owner.clearRelocation(actorId, error, key);
269
+ void runtime
338
270
  .closeSessionBinding(actorId, value.session)
339
271
  .catch((disconnectError) =>
340
272
  this.options.reportOwnershipRefreshError?.(actorId, disconnectError)
@@ -360,26 +292,20 @@ export class ZLinkRemoteBoundSessionRelay {
360
292
  else signal.addEventListener('abort', onAbort, { once: true });
361
293
  }
362
294
  try {
363
- const sealed = await sealPromise;
364
- state.sealed = sealed;
365
- return sealed;
295
+ return await state.sealPromise;
366
296
  } catch (error) {
367
297
  clearTimeout(state.sealTimer);
368
298
  state.sealAbortCleanup?.();
369
299
  if (this.activeServiceWireRelocations.get(key) === state) {
370
300
  this.activeServiceWireRelocations.delete(key);
371
301
  }
372
- if (state.terminal !== true) {
373
- const owner = actorSessionBindingRuntimeOwner(this.options.streamBindingRuntime());
374
- if ((await owner.relocationSnapshot(actorId, key)) !== undefined) {
375
- await owner.clearRelocation(actorId, error);
376
- void this.options
377
- .streamBindingRuntime()
378
- .closeSessionBinding(actorId, value.session)
379
- .catch((disconnectError) =>
380
- this.options.reportOwnershipRefreshError?.(actorId, disconnectError)
381
- );
382
- }
302
+ if (state.terminal !== true && (await owner.relocationSnapshot(actorId, key)) !== undefined) {
303
+ await owner.clearRelocation(actorId, error, key);
304
+ void runtime
305
+ .closeSessionBinding(actorId, value.session)
306
+ .catch((disconnectError) =>
307
+ this.options.reportOwnershipRefreshError?.(actorId, disconnectError)
308
+ );
383
309
  }
384
310
  throw sealController.signal.aborted ? sealController.signal.reason : error;
385
311
  }
@@ -389,108 +315,50 @@ export class ZLinkRemoteBoundSessionRelay {
389
315
  value: ServiceSessionRelocationRoute
390
316
  ): Promise<void> {
391
317
  const key = serviceWireBarrierKey(value);
392
- const routeRequestFingerprint = encodeSessionRelocationRoute(value).toString('base64');
393
- const fingerprint = routeRequestFingerprint;
394
- const terminal = this.terminalServiceWireRelocations.get(key);
395
- if (terminal !== undefined) {
396
- if (terminal.routeFingerprint === undefined) {
397
- // The Session owner already closed this binding at the seal deadline.
398
- // A late command 44 is terminal and cannot reactivate the route.
399
- this.terminalServiceWireRelocations.touch(key);
400
- this.warnLateSessionRouteUpdate(value);
401
- return;
402
- }
403
- if (terminal.routeFingerprint !== fingerprint) {
404
- throw new ServiceWireProtocolError(
405
- `Session relocation '${key}' repeated command 44 with different bytes.`
406
- );
407
- }
408
- this.terminalServiceWireRelocations.touch(key);
409
- this.warnLateSessionRouteUpdate(value);
410
- return;
411
- }
318
+ const runtime = this.options.streamBindingRuntime();
319
+ const owner = actorSessionBindingRuntimeOwner(runtime);
412
320
  const state = this.activeServiceWireRelocations.get(key);
413
- if (state === undefined) {
414
- this.warnLateSessionRouteUpdate(value);
415
- return;
416
- }
417
- if (
418
- state.routeRequestFingerprint !== undefined &&
419
- state.routeRequestFingerprint !== routeRequestFingerprint
420
- ) {
421
- throw new ServiceWireProtocolError(
422
- `Session relocation '${key}' repeated command 44 with different bytes.`
423
- );
424
- }
425
- if (state.routeFingerprint !== undefined) {
426
- if (state.routeFingerprint !== fingerprint || state.routePromise === undefined) {
427
- throw new ServiceWireProtocolError(
428
- `Session relocation '${key}' repeated command 44 with different bytes.`
321
+ const accepted = await owner.acceptSessionRelocationRoute(value, async () => {
322
+ if (state === undefined) {
323
+ throw new ZLinkRemoteBoundSessionFenceError(
324
+ `Session relocation '${key}' has no active seal.`
429
325
  );
430
326
  }
431
- this.warnLateSessionRouteUpdate(value);
432
- await state.routePromise;
433
- return;
434
- }
435
- state.routeRequestFingerprint = routeRequestFingerprint;
436
- state.routeFingerprint = fingerprint;
437
- if (state.sealTimer !== undefined) clearTimeout(state.sealTimer);
438
- state.sealAbortCleanup?.();
439
- const routePromise = state.sealPromise.then(async (sealed) => {
440
- validateSessionRelocationRouteAgainstSeal(value, sealed);
441
- await this.applyServiceWireSessionRelocationRoute(key, value);
442
- });
443
- state.routePromise = routePromise;
444
- try {
445
- await routePromise;
446
- this.terminalServiceWireRelocations.remember(key, {
447
- actorId: state.actorId,
448
- sealFingerprint: state.sealFingerprint,
449
- sealed: state.sealed ?? (await state.sealPromise),
450
- routeRequestFingerprint,
451
- routeFingerprint: fingerprint
452
- });
453
- if (this.activeServiceWireRelocations.get(key) === state) {
454
- this.activeServiceWireRelocations.delete(key);
455
- }
456
- state.terminal = true;
457
- } catch (error) {
458
- // Command 44 is one-way. Once an exact update wins the timeout race,
459
- // an apply failure cannot be repaired by waiting for an ACK-driven
460
- // retry. Close the physical Session and terminalize this identity so a
461
- // late duplicate cannot reactivate the binding or its held messages.
462
- state.terminal = true;
463
- if (this.activeServiceWireRelocations.get(key) === state) {
464
- this.activeServiceWireRelocations.delete(key);
327
+ if (state.sealTimer !== undefined) clearTimeout(state.sealTimer);
328
+ state.sealAbortCleanup?.();
329
+ try {
330
+ const sealed = await state.sealPromise;
331
+ validateSessionRelocationRouteAgainstSeal(value, sealed);
332
+ await this.applyServiceWireSessionRelocationRoute(key, value);
333
+ } catch (error) {
334
+ // The binding owner chose this command. A failed one-way apply closes
335
+ // its physical Session; conflicting duplicates never enter this callback.
336
+ await owner.clearRelocation(state.actorId, error, key);
337
+ await runtime
338
+ .closeSessionBinding(state.actorId, value.session)
339
+ .catch((disconnectError) =>
340
+ this.options.reportOwnershipRefreshError?.(state.actorId, disconnectError)
341
+ );
342
+ throw error;
343
+ } finally {
344
+ state.terminal = true;
345
+ if (this.activeServiceWireRelocations.get(key) === state) {
346
+ this.activeServiceWireRelocations.delete(key);
347
+ }
465
348
  }
466
- const sealed = state.sealed ?? (await state.sealPromise);
467
- this.terminalServiceWireRelocations.remember(key, {
468
- actorId: state.actorId,
469
- sealFingerprint: state.sealFingerprint,
470
- sealed,
471
- routeRequestFingerprint,
472
- routeFingerprint: fingerprint
473
- });
474
- actorSessionBindingRuntimeOwner(this.options.streamBindingRuntime()).clearRelocation(
475
- state.actorId,
476
- error
477
- );
478
- await this.options
479
- .streamBindingRuntime()
480
- .closeSessionBinding(state.actorId, value.session)
481
- .catch((disconnectError) =>
482
- this.options.reportOwnershipRefreshError?.(state.actorId, disconnectError)
483
- );
484
- throw error;
485
- }
349
+ });
350
+ if (!accepted) this.warnLateSessionRouteUpdate(value);
486
351
  }
487
352
 
488
- clearServiceWireSessionRelocations(): void {
353
+ async clearServiceWireSessionRelocations(): Promise<void> {
489
354
  for (const state of this.activeServiceWireRelocations.values()) {
490
355
  if (state.sealTimer !== undefined) clearTimeout(state.sealTimer);
356
+ state.sealAbortCleanup?.();
491
357
  }
492
358
  this.activeServiceWireRelocations.clear();
493
- this.terminalServiceWireRelocations.clear();
359
+ await actorSessionBindingRuntimeOwnerIfRegistered(
360
+ this.options.streamBindingRuntime()
361
+ )?.clearSessionRelocationResults();
494
362
  }
495
363
 
496
364
  private warnLateSessionRouteUpdate(value: ServiceSessionRelocationRoute): void {
@@ -502,16 +370,12 @@ export class ZLinkRemoteBoundSessionRelay {
502
370
  value: ServiceSessionRelocationRoute
503
371
  ): Promise<void> {
504
372
  const runtime = this.options.streamBindingRuntime();
505
- const owner = actorSessionBindingRuntimeOwner(runtime);
506
- const fingerprint = encodeSessionRelocationRoute(value).toString('base64');
507
373
  if (value.route.action === 'abort') {
508
- await owner.applyRelocation(value.actor.actorId, key, fingerprint, async () => {
509
- if (!(await runtime.abortActorRouteSeal(value.actor.actorId, key))) {
510
- throw new ZLinkRemoteBoundSessionFenceError(
511
- `Actor '${value.actor.actorId}' command 44 abort lost its Session seal.`
512
- );
513
- }
514
- });
374
+ if (!(await runtime.abortActorRouteSeal(value.actor.actorId, key))) {
375
+ throw new ZLinkRemoteBoundSessionFenceError(
376
+ `Actor '${value.actor.actorId}' command 44 abort lost its Session seal.`
377
+ );
378
+ }
515
379
  } else {
516
380
  const committedRoute = value.route;
517
381
  const current = (await runtime.find(value.actor.actorId))?.ref;
@@ -524,48 +388,25 @@ export class ZLinkRemoteBoundSessionRelay {
524
388
  actorId: value.actor.actorId,
525
389
  objectGeneration: value.actor.generation,
526
390
  meshName: current.meshName,
527
- nodeRid: decodeWireRoutingId(committedRoute.targetNodeRid, undefined),
391
+ nodeRid: committedRoute.targetNodeRid,
528
392
  bindingGeneration: value.session.bindingGeneration,
529
393
  ownershipGeneration: committedRoute.targetAuthorityOwnerGeneration,
530
394
  ownerNodeGeneration: committedRoute.targetNodeGeneration,
531
395
  ownerLeaseGeneration: committedRoute.targetOwnerLeaseGeneration
532
396
  } as ActorRef;
533
- await owner.applyRelocation(value.actor.actorId, key, fingerprint, async () => {
534
- await runtime.commitActorRoute(targetActorRef, undefined, {
535
- confirmRemoteSessionBinding: 'send',
536
- releaseSeal: { sealId: key }
537
- });
538
- const currentGeneration = this.actorOwnershipGenerations.get(value.actor.actorId);
539
- if (
540
- currentGeneration === undefined ||
541
- currentGeneration < committedRoute.targetAuthorityOwnerGeneration
542
- ) {
543
- this.actorOwnershipGenerations.set(
544
- value.actor.actorId,
545
- committedRoute.targetAuthorityOwnerGeneration
546
- );
547
- }
397
+ await runtime.commitActorRoute(targetActorRef, undefined, {
398
+ releaseSeal: { sealId: key }
548
399
  });
549
- }
550
- await owner.observeRelocationTerminal(value.actor.actorId, key, fingerprint);
551
- }
552
-
553
- private async validateServiceWireSessionRoute(
554
- value: ServiceSessionRelocationSeal
555
- ): Promise<void> {
556
- const current = await this.options
557
- .streamBindingRuntime()
558
- .sessionRouteFence(value.actor.actor.actorId);
559
- if (
560
- current === undefined ||
561
- current.actor.objectGeneration !== value.actor.actor.generation ||
562
- !routingIdsEqual(current.actor.nodeRid, value.actor.actor.nodeRid) ||
563
- current.sessionRid.toString() !== value.session.sessionRid ||
564
- current.bindingGeneration !== value.session.bindingGeneration
565
- ) {
566
- throw new ZLinkRemoteBoundSessionFenceError(
567
- `Actor '${value.actor.actor.actorId}' command 42 was fenced by its exact Session route.`
568
- );
400
+ const currentGeneration = this.actorOwnershipGenerations.get(value.actor.actorId);
401
+ if (
402
+ currentGeneration === undefined ||
403
+ currentGeneration < committedRoute.targetAuthorityOwnerGeneration
404
+ ) {
405
+ this.actorOwnershipGenerations.set(
406
+ value.actor.actorId,
407
+ committedRoute.targetAuthorityOwnerGeneration
408
+ );
409
+ }
569
410
  }
570
411
  }
571
412
 
@@ -603,9 +444,6 @@ export class ZLinkRemoteBoundSessionRelay {
603
444
  this.activeServiceWireRelocations.delete(key);
604
445
  }
605
446
  }
606
- for (const [key, value] of this.terminalServiceWireRelocations) {
607
- if (value.actorId === actorId) this.terminalServiceWireRelocations.delete(key);
608
- }
609
447
  }
610
448
 
611
449
  async sendActorResponse(
@@ -42,7 +42,7 @@ const DEFAULT_ROUTE_MESH_DRAIN_TIMEOUT_MS = 30_000;
42
42
  const MAX_ROUTE_MESH_OBSERVATION_WAIT_MS = 1000;
43
43
  const PLACEMENT_OBSERVATION_INTERVAL_MS = 100;
44
44
 
45
- type ZLinkDrainForceReason =
45
+ export type ZLinkDrainForceReason =
46
46
  'deadline_exceeded' | 'drain_state_publish_failed' | 'owner_cleanup_failed' | 'teardown_failed';
47
47
 
48
48
  type ZLinkMeshDrainResult =
@@ -74,7 +74,11 @@ export interface ZLinkRouteMeshRuntimeCoordinatorOptions {
74
74
  ) => Promise<void>;
75
75
  readonly shutdownResources?: (meshName: string, signal: AbortSignal) => Promise<void>;
76
76
  readonly cleanupHostResources: (signal: AbortSignal) => Promise<void>;
77
- readonly forceStopResources: (meshName: string) => Promise<void>;
77
+ readonly forceStopResources: (
78
+ meshName: string,
79
+ reason: ZLinkDrainForceReason,
80
+ signal: AbortSignal
81
+ ) => Promise<void>;
78
82
  }
79
83
 
80
84
  export interface ZLinkLocalPlacementCounts {
@@ -465,7 +469,9 @@ export class ZLinkRouteMeshRuntimeCoordinator implements ZLinkRouteMeshRuntime {
465
469
  : deadline.signal.aborted
466
470
  ? 'deadline_exceeded'
467
471
  : classified;
468
- await this.options.forceStopResources(meshName).catch(() => undefined);
472
+ await this.options
473
+ .forceStopResources(meshName, reason, deadline.signal)
474
+ .catch(() => undefined);
469
475
  result = { kind: 'forceStopped', reason };
470
476
  this.transition(meshName, state, ZLinkTopologyState.Failed);
471
477
  } finally {
@@ -526,7 +532,7 @@ export class ZLinkRouteMeshRuntimeCoordinator implements ZLinkRouteMeshRuntime {
526
532
  : classified;
527
533
  await Promise.all(
528
534
  entries.map(([meshName]) =>
529
- this.options.forceStopResources(meshName).catch(() => undefined)
535
+ this.options.forceStopResources(meshName, reason, deadline.signal).catch(() => undefined)
530
536
  )
531
537
  );
532
538
  result = { kind: 'forceStopped', reason };
@@ -585,7 +591,7 @@ export class ZLinkRouteMeshRuntimeCoordinator implements ZLinkRouteMeshRuntime {
585
591
  : classified;
586
592
  await Promise.all(
587
593
  entries.map(([meshName]) =>
588
- this.options.forceStopResources(meshName).catch(() => undefined)
594
+ this.options.forceStopResources(meshName, reason, signal).catch(() => undefined)
589
595
  )
590
596
  );
591
597
  result = { kind: 'forceStopped', reason, error };
@@ -5,7 +5,7 @@ import type { ZLinkLocationRuntime } from '../locations';
5
5
  import type { ZLinkSpotNodeRuntimeManager } from '../spots';
6
6
  import type { ZLinkStreamRuntimeManager } from '../streams';
7
7
  import type { ZLinkLocationRuntimeStopSnapshot } from './location-runtime-owner';
8
- import { isAbortError } from '../abort';
8
+ import { awaitWithAbort, isAbortError } from '../abort';
9
9
 
10
10
  interface ZLinkRuntimeOwnedStore {
11
11
  dispose?(): void | Promise<void>;
@@ -29,7 +29,10 @@ export interface ZLinkRuntimeStopParts {
29
29
  readonly streamRuntime?: ZLinkStreamRuntimeManager;
30
30
  readonly spotNodeRuntime?: ZLinkSpotNodeRuntimeManager;
31
31
  readonly channelRuntime?: ZLinkChannelRuntimeManager;
32
- readonly serviceRelocation?: { dispose(): Promise<void> };
32
+ readonly serviceRelocation?: {
33
+ drainActorJoinSources?(): Promise<void>;
34
+ dispose(): Promise<void>;
35
+ };
33
36
  readonly ownedStores?: readonly ZLinkRuntimeOwnedStore[];
34
37
  }
35
38
 
@@ -48,12 +51,20 @@ export async function rollbackRuntimeStart(parts: ZLinkRuntimeStartRollbackParts
48
51
  export async function stopRuntimeParts(parts: ZLinkRuntimeStopParts): Promise<void> {
49
52
  const state = parts.state;
50
53
  const errors: unknown[] = [];
54
+ await runShutdownStep(errors, () =>
55
+ awaitWithAbort(
56
+ Promise.resolve(parts.serviceRelocation?.drainActorJoinSources?.()),
57
+ parts.shutdownSignal
58
+ )
59
+ );
51
60
  await runShutdownStep(errors, () => parts.streamRuntime?.dispose());
52
61
  await runShutdownStep(errors, () =>
53
- parts.spotNodeRuntime?.dispose(undefined, parts.cleanupDeadline)
62
+ parts.spotNodeRuntime?.dispose(parts.shutdownSignal, parts.cleanupDeadline)
54
63
  );
55
64
  await runShutdownStep(errors, () => parts.channelRuntime?.dispose());
56
- await runShutdownStep(errors, () => parts.serviceRelocation?.dispose());
65
+ await runShutdownStep(errors, () =>
66
+ awaitWithAbort(Promise.resolve(parts.serviceRelocation?.dispose()), parts.shutdownSignal)
67
+ );
57
68
  await runShutdownStep(errors, () => parts.locationSnapshot.lifecycle?.dispose());
58
69
  await runShutdownStep(errors, () => parts.locationSnapshot.runtime?.stop(parts.shutdownSignal));
59
70
  await Promise.allSettled(state.listenerTasks);