@zlink-systems/framework 0.21.0 → 0.23.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (516) hide show
  1. package/dist/.tsbuildinfo +1 -1
  2. package/dist/contracts/Common/ZLinkMessage.js +5 -5
  3. package/dist/contracts/Configuration/CodecContentType.js +5 -7
  4. package/dist/contracts/Configuration/DiagnosticsValidation.js +1 -6
  5. package/dist/contracts/Configuration/EndpointNotation.js +4 -8
  6. package/dist/contracts/Configuration/Registration.js +14 -11
  7. package/dist/contracts/Configuration/RegistrationBuilders.js +32 -25
  8. package/dist/contracts/Configuration/RegistrationNormalizers.js +25 -26
  9. package/dist/contracts/Configuration/RegistrationValidators.js +36 -38
  10. package/dist/contracts/Configuration/SendTimeoutValidation.js +4 -4
  11. package/dist/contracts/Configuration/TimerRegistrationValidator.js +7 -7
  12. package/dist/contracts/Dispatch/ZLinkDispatchOptions.d.ts +1 -0
  13. package/dist/contracts/Handlers/JsonContract.js +23 -11
  14. package/dist/contracts/Spots/SpotKind.js +16 -8
  15. package/dist/contracts/Streams/IZLinkSession.d.ts +2 -1
  16. package/dist/location-store-integration.js +16 -16
  17. package/dist/nest-integration.js +17 -11
  18. package/dist/runtime/abort.js +9 -5
  19. package/dist/runtime/actors/actor-authority-payload-codec.js +12 -16
  20. package/dist/runtime/actors/actor-authority-publication.js +18 -17
  21. package/dist/runtime/actors/actor-client.js +83 -63
  22. package/dist/runtime/actors/actor-context.js +28 -22
  23. package/dist/runtime/actors/actor-creation.js +4 -3
  24. package/dist/runtime/actors/actor-handoff.js +89 -92
  25. package/dist/runtime/actors/actor-join-deferred-scope.d.ts +0 -1
  26. package/dist/runtime/actors/actor-join-deferred-scope.js +0 -18
  27. package/dist/runtime/actors/actor-local-native-join.js +18 -19
  28. package/dist/runtime/actors/actor-mailbox.js +1 -1
  29. package/dist/runtime/actors/actor-message-follow-context.js +24 -21
  30. package/dist/runtime/actors/actor-packet-relay-wire.js +1 -3
  31. package/dist/runtime/actors/actor-remote-joiner.js +20 -17
  32. package/dist/runtime/actors/actor-remote-wire.js +6 -7
  33. package/dist/runtime/actors/actor-runtime-state.js +87 -81
  34. package/dist/runtime/actors/actor-transfer-registry.js +3 -5
  35. package/dist/runtime/actors/bound-session-wire.js +14 -9
  36. package/dist/runtime/actors/deferred-join-accepted-journal.js +160 -130
  37. package/dist/runtime/actors/index.js +2 -5
  38. package/dist/runtime/actors/post-commit-actor-binder.js +3 -6
  39. package/dist/runtime/actors/post-commit-actor-location.js +1 -1
  40. package/dist/runtime/actors/spot-actor-dispatch.js +5 -5
  41. package/dist/runtime/actors/transferred-actor-rollback.js +4 -4
  42. package/dist/runtime/admission.js +2 -6
  43. package/dist/runtime/application-jobs/application-ingress-record-owner.js +2 -6
  44. package/dist/runtime/application-jobs/receive-flow-controller.js +11 -12
  45. package/dist/runtime/backend/contracts/index.d.ts +1 -0
  46. package/dist/runtime/backend/mesh-completion-table.js +1 -3
  47. package/dist/runtime/backend/mesh-dispatch-pump.js +12 -16
  48. package/dist/runtime/backend/node/node-backend-adapter-factory.js +1 -3
  49. package/dist/runtime/backend/node/node-backend-adapter-support.js +26 -17
  50. package/dist/runtime/backend/node/node-mesh-backend-adapter.js +4 -3
  51. package/dist/runtime/backend/node/node-raw-binding-port.js +7 -6
  52. package/dist/runtime/backend/node/node-raw-mesh-backend.d.ts +3 -0
  53. package/dist/runtime/backend/node/node-raw-mesh-backend.js +134 -118
  54. package/dist/runtime/backend/node/node-socket-backend-adapter.js +12 -13
  55. package/dist/runtime/backend/runtime-message.js +3 -3
  56. package/dist/runtime/backend/runtime-values.d.ts +2 -2
  57. package/dist/runtime/backend/runtime-values.js +4 -5
  58. package/dist/runtime/channels/channel-clients.js +27 -24
  59. package/dist/runtime/channels/channel-dispatch-pipeline.js +12 -20
  60. package/dist/runtime/channels/channel-dispatch-services.js +7 -4
  61. package/dist/runtime/channels/channel-dispatchers.js +9 -9
  62. package/dist/runtime/channels/channel-envelope-inspection.js +16 -13
  63. package/dist/runtime/channels/channel-envelope.js +83 -47
  64. package/dist/runtime/channels/channel-outbound-operations.js +8 -8
  65. package/dist/runtime/channels/channel-receive-loops.js +20 -22
  66. package/dist/runtime/channels/channel-receive-task-tracker.js +1 -1
  67. package/dist/runtime/channels/channel-runtime-lifecycle.js +61 -56
  68. package/dist/runtime/channels/channel-runtime-manager.js +18 -9
  69. package/dist/runtime/channels/channel-socket-registry.js +126 -123
  70. package/dist/runtime/channels/channel-transports.js +46 -42
  71. package/dist/runtime/channels/client-server-location-runtime.js +32 -40
  72. package/dist/runtime/channels/client-server-service-wire.js +29 -22
  73. package/dist/runtime/channels/dispatch-error-reporter.d.ts +1 -0
  74. package/dist/runtime/channels/dispatch-error-reporter.js +9 -39
  75. package/dist/runtime/channels/fanout-location-runtime.js +34 -47
  76. package/dist/runtime/channels/fanout-service-wire.js +3 -5
  77. package/dist/runtime/channels/local-spot-route-transport.js +7 -1
  78. package/dist/runtime/channels/route-member-snapshot.js +3 -3
  79. package/dist/runtime/channels/source-spot-router.js +6 -2
  80. package/dist/runtime/channels/spot-route-bridge-transport.js +5 -2
  81. package/dist/runtime/channels/spot-route-dispatch-strategy.js +2 -2
  82. package/dist/runtime/channels/spot-route-target-resolver.js +6 -6
  83. package/dist/runtime/diagnostics/dispatch-error-details.d.ts +6 -0
  84. package/dist/runtime/diagnostics/dispatch-error-details.js +55 -0
  85. package/dist/runtime/diagnostics/flow-context.d.ts +2 -1
  86. package/dist/runtime/diagnostics/flow-context.js +2 -2
  87. package/dist/runtime/diagnostics/index.js +38 -10
  88. package/dist/runtime/diagnostics/message-flow.js +58 -42
  89. package/dist/runtime/diagnostics/runtime-metrics.js +18 -9
  90. package/dist/runtime/diagnostics/runtime-observation-queue.js +8 -10
  91. package/dist/runtime/diagnostics/topology-runtime-projections.js +17 -10
  92. package/dist/runtime/execution/index.js +7 -6
  93. package/dist/runtime/execution/serial-execution-queue.js +12 -18
  94. package/dist/runtime/execution/state-lane.js +2 -2
  95. package/dist/runtime/foundation/actor-join-recovery-codec.js +31 -27
  96. package/dist/runtime/foundation/event-loop-resources.js +4 -4
  97. package/dist/runtime/foundation/message-follow-suppression-registry.js +4 -4
  98. package/dist/runtime/foundation/raw-service-mesh-runtime.d.ts +4 -2
  99. package/dist/runtime/foundation/raw-service-mesh-runtime.js +169 -144
  100. package/dist/runtime/foundation/route-mesh-connection-policy.js +4 -4
  101. package/dist/runtime/foundation/runtime-state-projections.js +22 -11
  102. package/dist/runtime/foundation/service-authority-payload-codec.js +13 -15
  103. package/dist/runtime/foundation/service-discovery-registry.js +35 -33
  104. package/dist/runtime/foundation/service-instance-activation-recovery-codec.js +20 -22
  105. package/dist/runtime/foundation/service-liveness-registry.js +16 -12
  106. package/dist/runtime/foundation/service-maintenance-runtime.js +2 -4
  107. package/dist/runtime/foundation/service-relocation-aggregate-committer.js +24 -24
  108. package/dist/runtime/foundation/service-relocation-object-owner.js +6 -6
  109. package/dist/runtime/foundation/service-relocation-runtime.js +137 -94
  110. package/dist/runtime/foundation/service-runtime-contracts.js +5 -5
  111. package/dist/runtime/foundation/service-session-binding-ingress-port.d.ts +1 -0
  112. package/dist/runtime/foundation/service-stateful-registry.js +24 -23
  113. package/dist/runtime/foundation/service-stateful-runtime.d.ts +4 -0
  114. package/dist/runtime/foundation/service-stateful-runtime.js +461 -439
  115. package/dist/runtime/foundation/service-stateful-wire-codec.js +95 -98
  116. package/dist/runtime/foundation/service-topology-registry.d.ts +1 -0
  117. package/dist/runtime/foundation/service-topology-registry.js +105 -96
  118. package/dist/runtime/foundation/service-weighted-selection.js +6 -11
  119. package/dist/runtime/foundation/service-wire-binary-primitives.js +5 -6
  120. package/dist/runtime/foundation/service-wire-m6a-codec.js +46 -35
  121. package/dist/runtime/framework-errors-internal.js +7 -10
  122. package/dist/runtime/handlers/handler-instance-scope.js +4 -5
  123. package/dist/runtime/handlers/index.js +3 -1
  124. package/dist/runtime/host/actor-packet-relay.js +74 -70
  125. package/dist/runtime/host/actor-placement-coordinator.js +29 -31
  126. package/dist/runtime/host/actor-runtime-options-factory.js +12 -14
  127. package/dist/runtime/host/actor-transfer-authority-runtime.js +7 -9
  128. package/dist/runtime/host/actor-transfer-runtime.js +176 -153
  129. package/dist/runtime/host/application-job-queue.js +18 -22
  130. package/dist/runtime/host/bound-session-relay.js +3 -1
  131. package/dist/runtime/host/channel-runtime-options-factory.js +31 -14
  132. package/dist/runtime/host/host-capacity-status.js +8 -4
  133. package/dist/runtime/host/index.js +245 -228
  134. package/dist/runtime/host/instance-activation-authority.js +93 -96
  135. package/dist/runtime/host/location-runtime-owner.js +16 -14
  136. package/dist/runtime/host/mesh-router-resolver.js +11 -13
  137. package/dist/runtime/host/relocation-direct-transfer.js +10 -9
  138. package/dist/runtime/host/remote-actor-join-receiver.js +20 -15
  139. package/dist/runtime/host/remote-actor-packet-target-store.js +18 -22
  140. package/dist/runtime/host/remote-bound-session-relay.js +97 -73
  141. package/dist/runtime/host/route-mesh-runtime.js +64 -69
  142. package/dist/runtime/host/runtime-shutdown.js +1 -2
  143. package/dist/runtime/host/service-relocation-host-runtime.js +586 -511
  144. package/dist/runtime/host/spot-address-transport.js +69 -71
  145. package/dist/runtime/host/spot-runtime-options-factory.js +30 -29
  146. package/dist/runtime/host/stateful-authority-route-runtime.js +65 -68
  147. package/dist/runtime/host/user-spot-creation-coordinator.js +61 -67
  148. package/dist/runtime/locations/actor-location-claims.js +26 -20
  149. package/dist/runtime/locations/aggregate-inventory-store.js +72 -75
  150. package/dist/runtime/locations/authority-key-codec.js +7 -7
  151. package/dist/runtime/locations/auto-connect-loop.js +3 -3
  152. package/dist/runtime/locations/auto-connect-planner.js +25 -19
  153. package/dist/runtime/locations/auto-connect-reconciler.js +51 -31
  154. package/dist/runtime/locations/in-memory-authority-store.js +128 -118
  155. package/dist/runtime/locations/in-memory-location-store.js +195 -168
  156. package/dist/runtime/locations/in-memory-provider-location-store.js +8 -10
  157. package/dist/runtime/locations/key-codec.js +1 -1
  158. package/dist/runtime/locations/lease-tracker.js +23 -21
  159. package/dist/runtime/locations/lifecycle.js +4 -5
  160. package/dist/runtime/locations/location-store-repository.js +368 -324
  161. package/dist/runtime/locations/opaque-record-key.js +2 -2
  162. package/dist/runtime/locations/resolvers.js +73 -82
  163. package/dist/runtime/locations/runtime.js +68 -63
  164. package/dist/runtime/locations/spot-location-claims.js +39 -35
  165. package/dist/runtime/messaging/framework-json-v1.js +7 -7
  166. package/dist/runtime/messaging/packet-name.js +7 -6
  167. package/dist/runtime/messaging/payload-codec.js +21 -18
  168. package/dist/runtime/protocol/service_wire_codec.generated.d.ts +30 -2
  169. package/dist/runtime/protocol/service_wire_codec.generated.js +1671 -234
  170. package/dist/runtime/protocol/service_wire_pilot_codec.generated.js +20 -18
  171. package/dist/runtime/routing-id.js +3 -5
  172. package/dist/runtime/spots/formal-remote-actor-admission-registry.js +35 -31
  173. package/dist/runtime/spots/formal-remote-actor-transfer-registry.js +1 -2
  174. package/dist/runtime/spots/index.js +209 -220
  175. package/dist/runtime/spots/spot-activation-registry.js +15 -14
  176. package/dist/runtime/spots/spot-activation-state.js +17 -15
  177. package/dist/runtime/spots/spot-activation.js +33 -16
  178. package/dist/runtime/spots/spot-actor-admission-coordinator.js +18 -15
  179. package/dist/runtime/spots/spot-actor-membership.js +1 -3
  180. package/dist/runtime/spots/spot-actor-packet-dispatch.d.ts +2 -1
  181. package/dist/runtime/spots/spot-actor-packet-dispatch.js +29 -21
  182. package/dist/runtime/spots/spot-actor-packet-drain.js +14 -10
  183. package/dist/runtime/spots/spot-actor-packet-relay-dispatch.js +10 -6
  184. package/dist/runtime/spots/spot-closing.js +3 -7
  185. package/dist/runtime/spots/spot-context.js +2 -2
  186. package/dist/runtime/spots/spot-entry-activation.js +13 -14
  187. package/dist/runtime/spots/spot-handle.js +6 -3
  188. package/dist/runtime/spots/spot-handler-registry.js +12 -12
  189. package/dist/runtime/spots/spot-manager-public.js +5 -6
  190. package/dist/runtime/spots/spot-native-actor-join-admission.js +4 -3
  191. package/dist/runtime/spots/spot-node-autoconnect.js +15 -18
  192. package/dist/runtime/spots/spot-node-runtime-manager.js +79 -86
  193. package/dist/runtime/spots/spot-outbound.js +10 -14
  194. package/dist/runtime/spots/spot-remote-codec.js +22 -26
  195. package/dist/runtime/spots/spot-remote-route-codec.js +5 -7
  196. package/dist/runtime/spots/spot-route-packet-dispatch.js +17 -15
  197. package/dist/runtime/spots/spot-route-replies.js +4 -6
  198. package/dist/runtime/spots/spot-routed-actor-admission.js +9 -7
  199. package/dist/runtime/spots/spot-routed-bound-session-dispatch.js +2 -3
  200. package/dist/runtime/spots/spot-routed-frame-dispatch.js +5 -5
  201. package/dist/runtime/spots/spot-routed-spot-packet-dispatch.js +14 -10
  202. package/dist/runtime/spots/spot-serial-executor.js +5 -8
  203. package/dist/runtime/spots/spot-serial-turn-executor.js +4 -6
  204. package/dist/runtime/spots/spot-subscription-dispatch.js +6 -6
  205. package/dist/runtime/spots/spot-timer.js +26 -30
  206. package/dist/runtime/streams/actor-session-binding-registry.d.ts +21 -8
  207. package/dist/runtime/streams/actor-session-binding-registry.js +168 -148
  208. package/dist/runtime/streams/actor-session-binding-runtime-owner.d.ts +1 -0
  209. package/dist/runtime/streams/actor-session-lifecycle-coordinator.js +3 -1
  210. package/dist/runtime/streams/bound-actor-relay-sender.js +20 -17
  211. package/dist/runtime/streams/bound-session-response-target.js +8 -1
  212. package/dist/runtime/streams/bound-session-service.d.ts +1 -0
  213. package/dist/runtime/streams/bound-session-service.js +14 -12
  214. package/dist/runtime/streams/index.js +28 -20
  215. package/dist/runtime/streams/managed-stream.d.ts +3 -0
  216. package/dist/runtime/streams/managed-stream.js +52 -31
  217. package/dist/runtime/streams/native-fallback-bound-session.js +21 -17
  218. package/dist/runtime/streams/protocol.d.ts +5 -1
  219. package/dist/runtime/streams/protocol.js +68 -20
  220. package/dist/runtime/streams/session-actor-coordinator.js +37 -41
  221. package/dist/runtime/streams/session-context.d.ts +9 -2
  222. package/dist/runtime/streams/session-context.js +50 -32
  223. package/dist/runtime/streams/session-local-actors.d.ts +3 -1
  224. package/dist/runtime/streams/session-local-actors.js +17 -2
  225. package/dist/runtime/streams/session-provider.js +2 -2
  226. package/dist/runtime/streams/session-serial-executor.js +1 -2
  227. package/dist/runtime/streams/stream-frame-factory.d.ts +1 -1
  228. package/dist/runtime/streams/stream-frame-factory.js +14 -7
  229. package/dist/runtime/streams/stream-session-runtime.js +112 -78
  230. package/dist/runtime/workers/index.js +15 -4
  231. package/package.json +3 -3
  232. package/src/contracts/Channels/RouteCalls.ts +6 -1
  233. package/src/contracts/Common/ZLinkMessage.ts +5 -5
  234. package/src/contracts/Common/ZLinkMessageMetadata.ts +4 -3
  235. package/src/contracts/Configuration/Builders.ts +14 -14
  236. package/src/contracts/Configuration/CodecContentType.ts +8 -10
  237. package/src/contracts/Configuration/DiagnosticsValidation.ts +1 -6
  238. package/src/contracts/Configuration/EndpointNotation.ts +11 -11
  239. package/src/contracts/Configuration/ObjectRoles.ts +1 -3
  240. package/src/contracts/Configuration/Registration.ts +46 -17
  241. package/src/contracts/Configuration/RegistrationBuilderPolicy.ts +10 -8
  242. package/src/contracts/Configuration/RegistrationBuilders.ts +107 -96
  243. package/src/contracts/Configuration/RegistrationCodecRegistry.ts +9 -3
  244. package/src/contracts/Configuration/RegistrationNormalizers.ts +116 -84
  245. package/src/contracts/Configuration/RegistrationTypes.ts +21 -25
  246. package/src/contracts/Configuration/RegistrationValidators.ts +122 -73
  247. package/src/contracts/Configuration/RouteChannelInternalState.ts +1 -4
  248. package/src/contracts/Configuration/RuntimeEndpointConnections.ts +4 -1
  249. package/src/contracts/Configuration/SendTimeoutValidation.ts +6 -4
  250. package/src/contracts/Configuration/TimerRegistrationValidator.ts +8 -13
  251. package/src/contracts/Dispatch/ZLinkDispatchOptions.ts +2 -6
  252. package/src/contracts/Errors/index.ts +1 -4
  253. package/src/contracts/Handlers/Attributes.ts +15 -9
  254. package/src/contracts/Handlers/IZLinkChannelHandlers.ts +24 -4
  255. package/src/contracts/Handlers/JsonContract.ts +53 -19
  256. package/src/contracts/Locations/ActorTransfer.ts +1 -5
  257. package/src/contracts/Locations/Authority.ts +4 -11
  258. package/src/contracts/Locations/Keys.ts +6 -1
  259. package/src/contracts/Locations/Options.ts +3 -2
  260. package/src/contracts/Locations/RelocationStore.ts +1 -4
  261. package/src/contracts/Locations/Resolvers.ts +5 -5
  262. package/src/contracts/Locations/RuntimeQuery.ts +6 -2
  263. package/src/contracts/Locations/Stores.ts +1 -2
  264. package/src/contracts/Locations/index.ts +2 -8
  265. package/src/contracts/RouteMesh/Contracts.ts +1 -7
  266. package/src/contracts/RouteMesh/RuntimeTopology.ts +1 -4
  267. package/src/contracts/Spots/Contracts.ts +2 -8
  268. package/src/contracts/Spots/SpotKind.ts +16 -8
  269. package/src/contracts/Spots/ZLinkSpot.ts +8 -11
  270. package/src/contracts/Streams/IZLinkSession.ts +2 -2
  271. package/src/contracts/Streams/IZLinkSessionActor.ts +5 -1
  272. package/src/contracts/Streams/IZLinkSessionPacketHandler.ts +5 -1
  273. package/src/internal.ts +5 -4
  274. package/src/location-store-integration.ts +24 -16
  275. package/src/nest-integration.ts +40 -25
  276. package/src/runtime/abort.ts +10 -4
  277. package/src/runtime/actors/actor-authority-payload-codec.ts +20 -29
  278. package/src/runtime/actors/actor-authority-publication.ts +92 -77
  279. package/src/runtime/actors/actor-client.ts +162 -133
  280. package/src/runtime/actors/actor-context.ts +142 -134
  281. package/src/runtime/actors/actor-creation.ts +47 -44
  282. package/src/runtime/actors/actor-execution-context.ts +6 -4
  283. package/src/runtime/actors/actor-handoff.ts +269 -293
  284. package/src/runtime/actors/actor-join-deferred-scope.ts +1 -32
  285. package/src/runtime/actors/actor-lifecycle-snapshot.ts +5 -8
  286. package/src/runtime/actors/actor-local-native-join.ts +131 -159
  287. package/src/runtime/actors/actor-mailbox.ts +16 -19
  288. package/src/runtime/actors/actor-message-follow-context.ts +46 -36
  289. package/src/runtime/actors/actor-packet-relay-wire.ts +32 -21
  290. package/src/runtime/actors/actor-remote-joiner.ts +50 -54
  291. package/src/runtime/actors/actor-remote-wire.ts +9 -13
  292. package/src/runtime/actors/actor-routed-join-transport.ts +10 -2
  293. package/src/runtime/actors/actor-runtime-contracts.ts +2 -5
  294. package/src/runtime/actors/actor-runtime-state.ts +127 -124
  295. package/src/runtime/actors/actor-transfer-registry.ts +9 -14
  296. package/src/runtime/actors/actor-transport-delivery-gate.ts +4 -6
  297. package/src/runtime/actors/bound-session-wire.ts +37 -17
  298. package/src/runtime/actors/deferred-join-accepted-journal.ts +353 -326
  299. package/src/runtime/actors/index.ts +43 -86
  300. package/src/runtime/actors/post-commit-actor-binder.ts +10 -10
  301. package/src/runtime/actors/post-commit-actor-location.ts +30 -23
  302. package/src/runtime/actors/spot-actor-dispatch.ts +78 -53
  303. package/src/runtime/actors/transferred-actor-rollback.ts +18 -13
  304. package/src/runtime/admission.ts +9 -9
  305. package/src/runtime/application-jobs/application-ingress-record-owner.ts +5 -15
  306. package/src/runtime/application-jobs/application-job-queue-handler-start-gate.ts +3 -2
  307. package/src/runtime/application-jobs/receive-flow-controller.ts +17 -14
  308. package/src/runtime/backend/contracts/index.ts +77 -52
  309. package/src/runtime/backend/mesh-actor-session-node-adapter.ts +4 -14
  310. package/src/runtime/backend/mesh-completion-table.ts +6 -9
  311. package/src/runtime/backend/mesh-dispatch-pump.ts +38 -30
  312. package/src/runtime/backend/node/node-backend-adapter-factory.ts +23 -21
  313. package/src/runtime/backend/node/node-backend-adapter-support.ts +36 -22
  314. package/src/runtime/backend/node/node-dealer-channel-client-transport.ts +59 -58
  315. package/src/runtime/backend/node/node-event-loop-poller.ts +2 -10
  316. package/src/runtime/backend/node/node-mesh-backend-adapter.ts +12 -5
  317. package/src/runtime/backend/node/node-monitor-backend-adapter.ts +4 -3
  318. package/src/runtime/backend/node/node-raw-binding-port.ts +29 -29
  319. package/src/runtime/backend/node/node-raw-mesh-backend.ts +370 -390
  320. package/src/runtime/backend/node/node-socket-backend-adapter.ts +101 -54
  321. package/src/runtime/backend/runtime-message.ts +5 -3
  322. package/src/runtime/backend/runtime-values.ts +10 -7
  323. package/src/runtime/channels/channel-autoconnect.ts +1 -4
  324. package/src/runtime/channels/channel-clients.ts +93 -73
  325. package/src/runtime/channels/channel-dispatch-pipeline.ts +44 -44
  326. package/src/runtime/channels/channel-dispatch-services.ts +51 -49
  327. package/src/runtime/channels/channel-dispatchers.ts +152 -96
  328. package/src/runtime/channels/channel-envelope-inspection.ts +20 -16
  329. package/src/runtime/channels/channel-envelope.ts +256 -150
  330. package/src/runtime/channels/channel-multipart.ts +13 -5
  331. package/src/runtime/channels/channel-outbound-operations.ts +37 -41
  332. package/src/runtime/channels/channel-receive-loops.ts +102 -98
  333. package/src/runtime/channels/channel-receive-task-tracker.ts +1 -1
  334. package/src/runtime/channels/channel-runtime-lifecycle.ts +248 -190
  335. package/src/runtime/channels/channel-runtime-manager.ts +63 -37
  336. package/src/runtime/channels/channel-socket-options.ts +3 -10
  337. package/src/runtime/channels/channel-socket-registry.ts +331 -273
  338. package/src/runtime/channels/channel-transports.ts +218 -206
  339. package/src/runtime/channels/client-server-location-runtime.ts +116 -100
  340. package/src/runtime/channels/client-server-service-wire.ts +37 -36
  341. package/src/runtime/channels/dispatch-error-reporter.ts +12 -47
  342. package/src/runtime/channels/fanout-location-runtime.ts +91 -94
  343. package/src/runtime/channels/fanout-service-wire.ts +5 -12
  344. package/src/runtime/channels/handler-filter-scope.ts +1 -4
  345. package/src/runtime/channels/index.ts +1 -4
  346. package/src/runtime/channels/local-spot-route-transport.ts +20 -5
  347. package/src/runtime/channels/route-member-snapshot.ts +11 -5
  348. package/src/runtime/channels/router-socket-spot-route-transport.ts +1 -7
  349. package/src/runtime/channels/source-spot-router.ts +26 -22
  350. package/src/runtime/channels/spot-direct-envelope.ts +10 -8
  351. package/src/runtime/channels/spot-node-route-transport.ts +13 -16
  352. package/src/runtime/channels/spot-route-bridge-transport.ts +26 -9
  353. package/src/runtime/channels/spot-route-dispatch-strategy.ts +40 -13
  354. package/src/runtime/channels/spot-route-target-resolver.ts +18 -9
  355. package/src/runtime/codecs/index.ts +3 -2
  356. package/src/runtime/diagnostics/dispatch-error-details.ts +62 -0
  357. package/src/runtime/diagnostics/flow-context.ts +18 -7
  358. package/src/runtime/diagnostics/index.ts +96 -61
  359. package/src/runtime/diagnostics/internal-event-contracts.ts +87 -33
  360. package/src/runtime/diagnostics/message-flow.ts +107 -79
  361. package/src/runtime/diagnostics/runtime-metrics.ts +46 -24
  362. package/src/runtime/diagnostics/runtime-observation-queue.ts +17 -28
  363. package/src/runtime/diagnostics/topology-runtime-projections.ts +62 -43
  364. package/src/runtime/execution/index.ts +18 -26
  365. package/src/runtime/execution/serial-execution-queue.ts +31 -40
  366. package/src/runtime/execution/state-lane.ts +2 -2
  367. package/src/runtime/foundation/actor-join-recovery-codec.ts +69 -55
  368. package/src/runtime/foundation/event-loop-resources.ts +8 -4
  369. package/src/runtime/foundation/message-follow-suppression-registry.ts +7 -14
  370. package/src/runtime/foundation/operation-identity.ts +1 -2
  371. package/src/runtime/foundation/operation-registry.ts +8 -2
  372. package/src/runtime/foundation/raw-service-mesh-runtime.ts +364 -396
  373. package/src/runtime/foundation/route-mesh-connection-policy.ts +7 -8
  374. package/src/runtime/foundation/runtime-state-projections.ts +24 -23
  375. package/src/runtime/foundation/service-authority-payload-codec.ts +54 -57
  376. package/src/runtime/foundation/service-discovery-registry.ts +67 -59
  377. package/src/runtime/foundation/service-instance-activation-recovery-codec.ts +28 -29
  378. package/src/runtime/foundation/service-liveness-registry.ts +18 -13
  379. package/src/runtime/foundation/service-mailbox.ts +14 -14
  380. package/src/runtime/foundation/service-maintenance-runtime.ts +22 -21
  381. package/src/runtime/foundation/service-metadata-codec.ts +2 -9
  382. package/src/runtime/foundation/service-relocation-aggregate-committer.ts +39 -36
  383. package/src/runtime/foundation/service-relocation-coordinator.ts +1 -4
  384. package/src/runtime/foundation/service-relocation-object-owner.ts +40 -58
  385. package/src/runtime/foundation/service-relocation-runtime.ts +292 -216
  386. package/src/runtime/foundation/service-runtime-contracts.ts +8 -8
  387. package/src/runtime/foundation/service-session-binding-ingress-port.ts +2 -4
  388. package/src/runtime/foundation/service-stateful-registry.ts +69 -59
  389. package/src/runtime/foundation/service-stateful-runtime.ts +1233 -1112
  390. package/src/runtime/foundation/service-stateful-wire-codec.ts +318 -270
  391. package/src/runtime/foundation/service-topology-registry.ts +170 -159
  392. package/src/runtime/foundation/service-weighted-selection.ts +9 -15
  393. package/src/runtime/foundation/service-wire-binary-primitives.ts +6 -12
  394. package/src/runtime/foundation/service-wire-m6a-codec.ts +69 -47
  395. package/src/runtime/framework-errors-internal.ts +31 -30
  396. package/src/runtime/handlers/handler-instance-scope.ts +18 -29
  397. package/src/runtime/handlers/index.ts +18 -8
  398. package/src/runtime/host/actor-packet-relay.ts +290 -261
  399. package/src/runtime/host/actor-placement-coordinator.ts +165 -150
  400. package/src/runtime/host/actor-runtime-options-factory.ts +89 -87
  401. package/src/runtime/host/actor-transfer-authority-runtime.ts +46 -38
  402. package/src/runtime/host/actor-transfer-runtime.ts +391 -395
  403. package/src/runtime/host/application-job-queue.ts +32 -48
  404. package/src/runtime/host/bound-session-relay.ts +7 -9
  405. package/src/runtime/host/channel-runtime-options-factory.ts +75 -35
  406. package/src/runtime/host/host-capacity-status.ts +10 -9
  407. package/src/runtime/host/index.ts +861 -789
  408. package/src/runtime/host/instance-activation-authority.ts +125 -143
  409. package/src/runtime/host/location-runtime-owner.ts +38 -26
  410. package/src/runtime/host/mesh-router-resolver.ts +30 -23
  411. package/src/runtime/host/relocation-direct-transfer.ts +15 -15
  412. package/src/runtime/host/relocation-integrity-fault-gate.ts +3 -2
  413. package/src/runtime/host/remote-actor-join-receiver.ts +43 -34
  414. package/src/runtime/host/remote-actor-packet-target-store.ts +54 -52
  415. package/src/runtime/host/remote-bound-session-relay.ts +274 -247
  416. package/src/runtime/host/route-mesh-runtime-options.ts +1 -3
  417. package/src/runtime/host/route-mesh-runtime.ts +227 -181
  418. package/src/runtime/host/runtime-shutdown.ts +4 -3
  419. package/src/runtime/host/service-relocation-control.ts +14 -5
  420. package/src/runtime/host/service-relocation-host-runtime.ts +1388 -1165
  421. package/src/runtime/host/spot-address-transport.ts +284 -237
  422. package/src/runtime/host/spot-node-runtime-options-factory.ts +14 -8
  423. package/src/runtime/host/spot-runtime-options-factory.ts +71 -62
  424. package/src/runtime/host/stateful-authority-route-runtime.ts +117 -116
  425. package/src/runtime/host/user-spot-creation-coordinator.ts +225 -220
  426. package/src/runtime/locations/actor-location-claims.ts +61 -49
  427. package/src/runtime/locations/actor-session-route-claims.ts +1 -4
  428. package/src/runtime/locations/aggregate-inventory-store.ts +105 -134
  429. package/src/runtime/locations/authority-key-codec.ts +13 -10
  430. package/src/runtime/locations/auto-connect-loop.ts +14 -11
  431. package/src/runtime/locations/auto-connect-planner.ts +42 -31
  432. package/src/runtime/locations/auto-connect-reconciler.ts +106 -63
  433. package/src/runtime/locations/canonical-codec.ts +3 -1
  434. package/src/runtime/locations/creation-operation-id.ts +4 -3
  435. package/src/runtime/locations/domain-store-contract.ts +13 -7
  436. package/src/runtime/locations/in-memory-authority-store.ts +232 -199
  437. package/src/runtime/locations/in-memory-location-store.ts +432 -250
  438. package/src/runtime/locations/in-memory-provider-location-store.ts +16 -17
  439. package/src/runtime/locations/internal-store-contracts.ts +95 -38
  440. package/src/runtime/locations/key-codec.ts +3 -4
  441. package/src/runtime/locations/lease-tracker.ts +36 -27
  442. package/src/runtime/locations/lifecycle-runtime.ts +15 -3
  443. package/src/runtime/locations/lifecycle.ts +33 -28
  444. package/src/runtime/locations/location-store-repository.ts +1329 -1185
  445. package/src/runtime/locations/opaque-record-key.ts +4 -9
  446. package/src/runtime/locations/resolvers.ts +201 -178
  447. package/src/runtime/locations/runtime.ts +251 -159
  448. package/src/runtime/locations/spot-location-claims.ts +110 -112
  449. package/src/runtime/messaging/creation-payload-codec.ts +4 -1
  450. package/src/runtime/messaging/framework-json-v1.ts +34 -15
  451. package/src/runtime/messaging/packet-name.ts +8 -6
  452. package/src/runtime/messaging/payload-codec.ts +70 -50
  453. package/src/runtime/messaging/submission-result.ts +6 -9
  454. package/src/runtime/protocol/service_wire_codec.generated.ts +1376 -159
  455. package/src/runtime/protocol/service_wire_pilot_codec.generated.ts +19 -18
  456. package/src/runtime/routing-id.ts +10 -7
  457. package/src/runtime/spots/formal-remote-actor-admission-registry.ts +56 -62
  458. package/src/runtime/spots/formal-remote-actor-transfer-registry.ts +23 -20
  459. package/src/runtime/spots/index.ts +595 -564
  460. package/src/runtime/spots/spot-activation-registry.ts +38 -34
  461. package/src/runtime/spots/spot-activation-state.ts +43 -51
  462. package/src/runtime/spots/spot-activation.ts +179 -116
  463. package/src/runtime/spots/spot-actor-admission-coordinator.ts +110 -78
  464. package/src/runtime/spots/spot-actor-join-dispatch.ts +57 -41
  465. package/src/runtime/spots/spot-actor-lifecycle-drain.ts +5 -7
  466. package/src/runtime/spots/spot-actor-membership.ts +25 -27
  467. package/src/runtime/spots/spot-actor-packet-dispatch.ts +196 -148
  468. package/src/runtime/spots/spot-actor-packet-drain.ts +56 -42
  469. package/src/runtime/spots/spot-actor-packet-relay-dispatch.ts +37 -39
  470. package/src/runtime/spots/spot-closing.ts +11 -12
  471. package/src/runtime/spots/spot-context.ts +46 -26
  472. package/src/runtime/spots/spot-entry-activation.ts +84 -65
  473. package/src/runtime/spots/spot-handle.ts +17 -15
  474. package/src/runtime/spots/spot-handler-registry.ts +44 -31
  475. package/src/runtime/spots/spot-location-claim.ts +5 -4
  476. package/src/runtime/spots/spot-manager-public.ts +62 -82
  477. package/src/runtime/spots/spot-native-actor-join-admission.ts +20 -16
  478. package/src/runtime/spots/spot-node-autoconnect.ts +54 -61
  479. package/src/runtime/spots/spot-node-runtime-manager.ts +235 -222
  480. package/src/runtime/spots/spot-outbound.ts +47 -59
  481. package/src/runtime/spots/spot-publisher-transport.ts +5 -4
  482. package/src/runtime/spots/spot-remote-codec.ts +66 -65
  483. package/src/runtime/spots/spot-remote-route-codec.ts +61 -41
  484. package/src/runtime/spots/spot-route-packet-dispatch.ts +129 -95
  485. package/src/runtime/spots/spot-route-replies.ts +23 -24
  486. package/src/runtime/spots/spot-route-reply-wire.ts +3 -2
  487. package/src/runtime/spots/spot-routed-actor-admission.ts +37 -27
  488. package/src/runtime/spots/spot-routed-bound-session-dispatch.ts +13 -18
  489. package/src/runtime/spots/spot-routed-frame-dispatch.ts +18 -15
  490. package/src/runtime/spots/spot-routed-spot-packet-dispatch.ts +35 -26
  491. package/src/runtime/spots/spot-routing-internal.ts +1 -4
  492. package/src/runtime/spots/spot-runtime-ports.ts +5 -5
  493. package/src/runtime/spots/spot-serial-executor.ts +5 -9
  494. package/src/runtime/spots/spot-serial-turn-executor.ts +19 -26
  495. package/src/runtime/spots/spot-subscription-dispatch.ts +58 -47
  496. package/src/runtime/spots/spot-timer.ts +103 -91
  497. package/src/runtime/streams/actor-session-binding-registry.ts +421 -292
  498. package/src/runtime/streams/actor-session-binding-runtime-owner.ts +8 -4
  499. package/src/runtime/streams/actor-session-lifecycle-coordinator.ts +3 -1
  500. package/src/runtime/streams/bound-actor-relay-sender.ts +60 -50
  501. package/src/runtime/streams/bound-session-response-target.ts +39 -9
  502. package/src/runtime/streams/bound-session-service.ts +52 -42
  503. package/src/runtime/streams/index.ts +183 -100
  504. package/src/runtime/streams/managed-stream.ts +123 -90
  505. package/src/runtime/streams/native-fallback-bound-session.ts +57 -52
  506. package/src/runtime/streams/protocol.ts +115 -46
  507. package/src/runtime/streams/session-actor-coordinator.ts +109 -93
  508. package/src/runtime/streams/session-calls.ts +2 -8
  509. package/src/runtime/streams/session-context.ts +96 -51
  510. package/src/runtime/streams/session-local-actors.ts +19 -3
  511. package/src/runtime/streams/session-provider.ts +5 -7
  512. package/src/runtime/streams/session-serial-executor.ts +7 -6
  513. package/src/runtime/streams/stream-binding-runtime-ports.ts +79 -29
  514. package/src/runtime/streams/stream-frame-factory.ts +59 -40
  515. package/src/runtime/streams/stream-session-runtime.ts +317 -214
  516. package/src/runtime/workers/index.ts +68 -29
@@ -8,11 +8,13 @@ import {
8
8
  internalFrameworkWireReply,
9
9
  translateWireReplyDecodeError
10
10
  } from '../framework-errors-internal';
11
+ import { RequestResult, SubmitResult, isZLinkBackendResultError } from '../backend/runtime-values';
12
+ import type { ZLinkDispatchErrorReporter } from '../channels/dispatch-error-reporter';
11
13
  import {
12
- RequestResult,
13
- SubmitResult,
14
- isZLinkBackendResultError
15
- } from '../backend/runtime-values';
14
+ ZLinkRuntimeDispatchErrorAction as ZLinkDispatchErrorAction,
15
+ ZLinkDispatchErrorSurface,
16
+ ZLinkDispatchMessageKind
17
+ } from '../../contracts/Dispatch/ZLinkDispatchOptions';
16
18
  import type {
17
19
  RawServiceIngressRecord,
18
20
  RawServiceMeshRuntime,
@@ -84,10 +86,7 @@ import {
84
86
  encodeActorJoin28,
85
87
  type ActorJoin28
86
88
  } from '../protocol/service_wire_pilot_codec.generated';
87
- import {
88
- canonicalActorJoinHandoffId,
89
- routingIdBytes
90
- } from './actor-join-recovery-codec';
89
+ import { canonicalActorJoinHandoffId, routingIdBytes } from './actor-join-recovery-codec';
91
90
 
92
91
  import {
93
92
  decodeApplicationPayload,
@@ -95,14 +94,10 @@ import {
95
94
  type ServiceApplicationPayload,
96
95
  ServiceWireProtocolError
97
96
  } from './service-wire-m6a-codec';
98
- import type {
99
- ServiceInstanceActivationRecoveryEnvelope
100
- } from './service-instance-activation-recovery-codec';
97
+ import type { ServiceInstanceActivationRecoveryEnvelope } from './service-instance-activation-recovery-codec';
101
98
  import { validateServiceMetadataFrame } from './service-metadata-codec';
102
99
  import type { ServiceSessionBindingIngressPort } from './service-session-binding-ingress-port';
103
- import {
104
- ZLinkFrameworkException
105
- } from '../../contracts';
100
+ import { ZLinkFrameworkException } from '../../contracts';
106
101
 
107
102
  const ACTOR_ROUTE_STALE = 21;
108
103
  const SPOT_MOVING = 34;
@@ -123,10 +118,7 @@ export interface ServiceBoundSessionSendFence {
123
118
 
124
119
  interface ServiceSpotMessageFollowRecord {
125
120
  readonly ingress: RawServiceIngressRecord;
126
- readonly wire: Extract<
127
- ServiceStatefulWireRecord,
128
- { readonly kind: 'spotSend' | 'spotRequest' }
129
- >;
121
+ readonly wire: Extract<ServiceStatefulWireRecord, { readonly kind: 'spotSend' | 'spotRequest' }>;
130
122
  readonly bytes: number;
131
123
  }
132
124
 
@@ -294,7 +286,10 @@ export interface ServiceInstanceActivationAuthority {
294
286
  reservation: ServiceInstanceActivationReservation,
295
287
  spot: ServiceSpotState
296
288
  ): { readonly kind: 'committed' | 'lost'; readonly route: ServiceInstanceRouteFence };
297
- abort(target: ServiceInstanceActivationTarget, reservation: ServiceInstanceActivationReservation): void;
289
+ abort(
290
+ target: ServiceInstanceActivationTarget,
291
+ reservation: ServiceInstanceActivationReservation
292
+ ): void;
298
293
  }
299
294
 
300
295
  /**
@@ -344,9 +339,18 @@ export interface ServiceUserSpotOperationResult {
344
339
  }
345
340
 
346
341
  export interface ServiceUserSpotOperationHandler {
347
- create(record: ServiceUserSpotCreateRecord, signal: AbortSignal): Promise<ServiceUserSpotOperationResult>;
348
- close(record: ServiceUserSpotCloseRecord, signal: AbortSignal): Promise<ServiceUserSpotOperationResult>;
349
- createActor?(record: ServiceActorCreateRecord, signal: AbortSignal): Promise<ServiceUserSpotOperationResult>;
342
+ create(
343
+ record: ServiceUserSpotCreateRecord,
344
+ signal: AbortSignal
345
+ ): Promise<ServiceUserSpotOperationResult>;
346
+ close(
347
+ record: ServiceUserSpotCloseRecord,
348
+ signal: AbortSignal
349
+ ): Promise<ServiceUserSpotOperationResult>;
350
+ createActor?(
351
+ record: ServiceActorCreateRecord,
352
+ signal: AbortSignal
353
+ ): Promise<ServiceUserSpotOperationResult>;
350
354
  }
351
355
 
352
356
  /**
@@ -403,16 +407,24 @@ export class ServiceStatefulRuntime {
403
407
  readonly kind: 'spot_multicast' | 'actor_control' | 'actor_binding';
404
408
  readonly owner: string;
405
409
  }) => void;
406
- private readonly admittedUserSpotOperations = new Map<string, {
407
- readonly request: string;
408
- readonly replayExpiresAtMs: number;
409
- readonly result: Promise<ServiceUserSpotOperationResult>;
410
- settled: boolean;
411
- }>();
412
- private readonly pendingInstanceActivations = new Map<string, Promise<{
413
- readonly spot: ServiceSpotState;
414
- readonly route: ServiceInstanceRouteFence;
415
- }>>();
410
+ private dispatchErrors?: ZLinkDispatchErrorReporter;
411
+ private dispatchErrorMeshName?: string;
412
+ private readonly admittedUserSpotOperations = new Map<
413
+ string,
414
+ {
415
+ readonly request: string;
416
+ readonly replayExpiresAtMs: number;
417
+ readonly result: Promise<ServiceUserSpotOperationResult>;
418
+ settled: boolean;
419
+ }
420
+ >();
421
+ private readonly pendingInstanceActivations = new Map<
422
+ string,
423
+ Promise<{
424
+ readonly spot: ServiceSpotState;
425
+ readonly route: ServiceInstanceRouteFence;
426
+ }>
427
+ >();
416
428
  private closed = false;
417
429
 
418
430
  constructor(
@@ -422,17 +434,28 @@ export class ServiceStatefulRuntime {
422
434
  ) {
423
435
  this.registry = new ServiceStatefulRegistry(nodeRid, nodeGeneration);
424
436
  this.registry.createEntrySpot(nodeRid);
425
- raw.setServiceIngress(record => this.ingress(record));
437
+ raw.setServiceIngress((record) => this.ingress(record));
426
438
  }
427
439
 
428
- setMailboxDropHandler(handler: (record: {
429
- readonly kind: 'spot_multicast' | 'actor_control' | 'actor_binding';
430
- readonly owner: string;
431
- }) => void): void {
440
+ setMailboxDropHandler(
441
+ handler: (record: {
442
+ readonly kind: 'spot_multicast' | 'actor_control' | 'actor_binding';
443
+ readonly owner: string;
444
+ }) => void
445
+ ): void {
432
446
  this.mailboxDropHandler = handler;
433
447
  }
434
448
 
435
- createSpot(routingId?: string, kind: 'user' | 'instance' = 'user', stableType = kind): ServiceSpotState {
449
+ setDispatchErrorReporter(reporter: ZLinkDispatchErrorReporter, meshName: string): void {
450
+ this.dispatchErrors = reporter;
451
+ this.dispatchErrorMeshName = meshName;
452
+ }
453
+
454
+ createSpot(
455
+ routingId?: string,
456
+ kind: 'user' | 'instance' = 'user',
457
+ stableType = kind
458
+ ): ServiceSpotState {
436
459
  this.requireOpen();
437
460
  return this.registry.createSpot(
438
461
  routingId ?? `spot-${this.nodeRid}-${this.nextSpotId++}`,
@@ -514,17 +537,17 @@ export class ServiceStatefulRuntime {
514
537
  this.requireOpen();
515
538
  const actor = this.registry.actor(actorRef.actorId);
516
539
  if (
517
- actor === undefined
518
- || actor.ref.generation !== actorRef.generation
519
- || actor.ref.nodeRid !== actorRef.nodeRid
540
+ actor === undefined ||
541
+ actor.ref.generation !== actorRef.generation ||
542
+ actor.ref.nodeRid !== actorRef.nodeRid
520
543
  ) {
521
544
  throw new ServiceStaleGenerationError('actor', actorRef.actorId);
522
545
  }
523
546
  const current = this.registry.binding(actor.ref);
524
547
  if (
525
- current?.bindingGeneration === bindingGeneration
526
- && current.sessionOwnerNodeRid === sessionNodeRid
527
- && current.sessionRid === sessionRid
548
+ current?.bindingGeneration === bindingGeneration &&
549
+ current.sessionOwnerNodeRid === sessionNodeRid &&
550
+ current.sessionRid === sessionRid
528
551
  ) {
529
552
  return;
530
553
  }
@@ -554,14 +577,15 @@ export class ServiceStatefulRuntime {
554
577
  }
555
578
  if (current.ref.generation === attempt) {
556
579
  return {
557
- spot: current.authorityOwnerGeneration === authorityOwnerGeneration
558
- ? current
559
- : this.registry.restoreSpot(
560
- current.ref,
561
- 'instance',
562
- instanceType,
563
- authorityOwnerGeneration
564
- ),
580
+ spot:
581
+ current.authorityOwnerGeneration === authorityOwnerGeneration
582
+ ? current
583
+ : this.registry.restoreSpot(
584
+ current.ref,
585
+ 'instance',
586
+ instanceType,
587
+ authorityOwnerGeneration
588
+ ),
565
589
  created: false
566
590
  };
567
591
  }
@@ -585,7 +609,10 @@ export class ServiceStatefulRuntime {
585
609
  route: ServiceInstanceRouteFence,
586
610
  expectedCurrentRoute?: ServiceInstanceRouteFence | null
587
611
  ): void {
588
- if (route.targetNodeRid !== this.nodeRid || route.targetNodeGeneration !== this.nodeGeneration) {
612
+ if (
613
+ route.targetNodeRid !== this.nodeRid ||
614
+ route.targetNodeGeneration !== this.nodeGeneration
615
+ ) {
589
616
  throw new ServiceStaleGenerationError('spot', route.targetSpotId);
590
617
  }
591
618
  const current = this.instanceIntents.get(route.targetSpotId);
@@ -595,7 +622,10 @@ export class ServiceStatefulRuntime {
595
622
  }
596
623
  if (!matchesExpectedInstanceRoute(current.route, expectedCurrentRoute)) return;
597
624
  if (current.route.objectGeneration < route.objectGeneration) {
598
- this.instanceIntents.set(route.targetSpotId, Object.freeze({ instanceType, route: { ...route } }));
625
+ this.instanceIntents.set(
626
+ route.targetSpotId,
627
+ Object.freeze({ instanceType, route: { ...route } })
628
+ );
599
629
  return;
600
630
  }
601
631
  if (current.route.objectGeneration > route.objectGeneration) {
@@ -615,7 +645,10 @@ export class ServiceStatefulRuntime {
615
645
  } else if (!matchesExpectedInstanceRoute(undefined, expectedCurrentRoute)) {
616
646
  return;
617
647
  }
618
- this.instanceIntents.set(route.targetSpotId, Object.freeze({ instanceType, route: { ...route } }));
648
+ this.instanceIntents.set(
649
+ route.targetSpotId,
650
+ Object.freeze({ instanceType, route: { ...route } })
651
+ );
619
652
  }
620
653
 
621
654
  instanceSpotApplicationTarget(
@@ -624,10 +657,10 @@ export class ServiceStatefulRuntime {
624
657
  const intent = this.instanceIntents.get(spotId);
625
658
  const spot = this.registry.spot(spotId);
626
659
  if (
627
- intent === undefined
628
- || spot?.kind !== 'instance'
629
- || spot.state !== 'ready'
630
- || spot.ref.generation !== intent.route.objectGeneration
660
+ intent === undefined ||
661
+ spot?.kind !== 'instance' ||
662
+ spot.state !== 'ready' ||
663
+ spot.ref.generation !== intent.route.objectGeneration
631
664
  ) {
632
665
  return undefined;
633
666
  }
@@ -645,9 +678,9 @@ export class ServiceStatefulRuntime {
645
678
  ): void {
646
679
  const current = this.instanceIntents.get(spotId);
647
680
  if (
648
- current?.route.objectGeneration === objectGeneration
649
- && current.route.authorityOwnerGeneration === authorityOwnerGeneration
650
- && (storeVersion === undefined || current.route.storeVersion === storeVersion)
681
+ current?.route.objectGeneration === objectGeneration &&
682
+ current.route.authorityOwnerGeneration === authorityOwnerGeneration &&
683
+ (storeVersion === undefined || current.route.storeVersion === storeVersion)
651
684
  ) {
652
685
  this.instanceIntents.delete(spotId);
653
686
  }
@@ -656,8 +689,8 @@ export class ServiceStatefulRuntime {
656
689
  registerInstanceActivationAuthority(authority: ServiceInstanceActivationAuthority): void {
657
690
  this.requireOpen();
658
691
  if (
659
- this.asyncInstanceAuthority !== undefined
660
- || this.instanceAuthority !== undefined && this.instanceAuthority !== authority
692
+ this.asyncInstanceAuthority !== undefined ||
693
+ (this.instanceAuthority !== undefined && this.instanceAuthority !== authority)
661
694
  ) {
662
695
  throw new Error('Instance activation authority is already registered.');
663
696
  }
@@ -669,18 +702,15 @@ export class ServiceStatefulRuntime {
669
702
  ): void {
670
703
  this.requireOpen();
671
704
  if (
672
- this.instanceAuthority !== undefined
673
- || this.asyncInstanceAuthority !== undefined
674
- && this.asyncInstanceAuthority !== authority
705
+ this.instanceAuthority !== undefined ||
706
+ (this.asyncInstanceAuthority !== undefined && this.asyncInstanceAuthority !== authority)
675
707
  ) {
676
708
  throw new Error('Instance activation authority is already registered.');
677
709
  }
678
710
  this.asyncInstanceAuthority = authority;
679
711
  }
680
712
 
681
- registerInstanceApplicationLifecycle(
682
- lifecycle: ServiceInstanceApplicationLifecycle
683
- ): void {
713
+ registerInstanceApplicationLifecycle(lifecycle: ServiceInstanceApplicationLifecycle): void {
684
714
  if (this.instanceApplicationLifecycle !== undefined) {
685
715
  throw new Error('Instance application lifecycle is already registered.');
686
716
  }
@@ -689,10 +719,7 @@ export class ServiceStatefulRuntime {
689
719
 
690
720
  registerUserSpotOperationHandler(handler: ServiceUserSpotOperationHandler): void {
691
721
  this.requireOpen();
692
- if (
693
- this.userSpotOperationHandler !== undefined
694
- && this.userSpotOperationHandler !== handler
695
- ) {
722
+ if (this.userSpotOperationHandler !== undefined && this.userSpotOperationHandler !== handler) {
696
723
  throw new Error('User Spot operation handler is already registered.');
697
724
  }
698
725
  this.userSpotOperationHandler = handler;
@@ -775,16 +802,19 @@ export class ServiceStatefulRuntime {
775
802
  expectedCurrentRoute?: ServiceInstanceRouteFence | null
776
803
  ): Promise<boolean> {
777
804
  const target = envelope.target;
778
- if (!matchesExpectedInstanceRoute(
779
- this.instanceIntents.get(target.targetSpotId)?.route,
780
- expectedCurrentRoute
781
- )) return false;
782
805
  if (
783
- target.targetNodeRid !== this.nodeRid
784
- || target.targetNodeGeneration !== this.nodeGeneration
785
- || target.targetSpotId !== route.targetSpotId
786
- || route.targetNodeRid !== this.nodeRid
787
- || route.targetNodeGeneration !== this.nodeGeneration
806
+ !matchesExpectedInstanceRoute(
807
+ this.instanceIntents.get(target.targetSpotId)?.route,
808
+ expectedCurrentRoute
809
+ )
810
+ )
811
+ return false;
812
+ if (
813
+ target.targetNodeRid !== this.nodeRid ||
814
+ target.targetNodeGeneration !== this.nodeGeneration ||
815
+ target.targetSpotId !== route.targetSpotId ||
816
+ route.targetNodeRid !== this.nodeRid ||
817
+ route.targetNodeGeneration !== this.nodeGeneration
788
818
  ) {
789
819
  throw new ServiceStaleGenerationError('spot', target.targetSpotId);
790
820
  }
@@ -802,8 +832,9 @@ export class ServiceStatefulRuntime {
802
832
  expectedCurrentRoute?: ServiceInstanceRouteFence | null
803
833
  ): Promise<boolean> {
804
834
  const target = envelope.target;
805
- const spot = this.registry.spot(target.targetSpotId)
806
- ?? this.registry.restoreSpot(
835
+ const spot =
836
+ this.registry.spot(target.targetSpotId) ??
837
+ this.registry.restoreSpot(
807
838
  {
808
839
  spotId: target.targetSpotId,
809
840
  generation: route.objectGeneration
@@ -813,17 +844,20 @@ export class ServiceStatefulRuntime {
813
844
  route.authorityOwnerGeneration
814
845
  );
815
846
  if (
816
- spot.kind !== 'instance'
817
- || spot.stableType !== target.stableType
818
- || spot.ref.generation !== route.objectGeneration
819
- || spot.authorityOwnerGeneration !== route.authorityOwnerGeneration
847
+ spot.kind !== 'instance' ||
848
+ spot.stableType !== target.stableType ||
849
+ spot.ref.generation !== route.objectGeneration ||
850
+ spot.authorityOwnerGeneration !== route.authorityOwnerGeneration
820
851
  ) {
821
852
  throw new ServiceStaleGenerationError('spot', target.targetSpotId);
822
853
  }
823
- if (!matchesExpectedInstanceRoute(
824
- this.instanceIntents.get(target.targetSpotId)?.route,
825
- expectedCurrentRoute
826
- )) return false;
854
+ if (
855
+ !matchesExpectedInstanceRoute(
856
+ this.instanceIntents.get(target.targetSpotId)?.route,
857
+ expectedCurrentRoute
858
+ )
859
+ )
860
+ return false;
827
861
  this.publishCommittedInstanceRoute(target.stableType, route, expectedCurrentRoute);
828
862
  const record = {
829
863
  kind: 'instanceSpot' as const,
@@ -831,9 +865,7 @@ export class ServiceStatefulRuntime {
831
865
  target,
832
866
  sourceNodeGeneration: envelope.sourceNodeGeneration,
833
867
  sourceNodeRid: envelope.sourceNodeRid,
834
- ...(envelope.sourceSpotId === undefined
835
- ? {}
836
- : { sourceSpotId: envelope.sourceSpotId }),
868
+ ...(envelope.sourceSpotId === undefined ? {} : { sourceSpotId: envelope.sourceSpotId }),
837
869
  operationKind: envelope.operationKind,
838
870
  operation: envelope.operation,
839
871
  deadlineUnixMs: envelope.deadlineUnixMs,
@@ -843,23 +875,23 @@ export class ServiceStatefulRuntime {
843
875
  try {
844
876
  const admitted = this.enqueueActivatedInstanceSpot(
845
877
  {
846
- command: M6bServiceWireCommand.instanceSpot,
847
- flags: envelope.metadataFrame === undefined ? 0 : M6bServiceWireFlag.metadata,
848
- sourceRoutingId: envelope.sourceNodeRid,
849
- parts: [
850
- encodeInstanceSpotActivationHeader(
851
- target,
852
- envelope.sourceNodeGeneration,
853
- envelope.sourceNodeRid,
854
- envelope.sourceSpotId,
855
- envelope.operationKind,
856
- envelope.operation,
857
- envelope.deadlineUnixMs,
858
- envelope.replyRouteId,
859
- envelope.metadataFrame !== undefined
860
- )
861
- ],
862
- applicationJobOwner
878
+ command: M6bServiceWireCommand.instanceSpot,
879
+ flags: envelope.metadataFrame === undefined ? 0 : M6bServiceWireFlag.metadata,
880
+ sourceRoutingId: envelope.sourceNodeRid,
881
+ parts: [
882
+ encodeInstanceSpotActivationHeader(
883
+ target,
884
+ envelope.sourceNodeGeneration,
885
+ envelope.sourceNodeRid,
886
+ envelope.sourceSpotId,
887
+ envelope.operationKind,
888
+ envelope.operation,
889
+ envelope.deadlineUnixMs,
890
+ envelope.replyRouteId,
891
+ envelope.metadataFrame !== undefined
892
+ )
893
+ ],
894
+ applicationJobOwner
863
895
  },
864
896
  record,
865
897
  Buffer.from(envelope.applicationPayloadFrame),
@@ -887,16 +919,19 @@ export class ServiceStatefulRuntime {
887
919
  expectedCurrentRoute?: ServiceInstanceRouteFence | null
888
920
  ): Promise<boolean> {
889
921
  const target = envelope.target;
890
- if (!matchesExpectedInstanceRoute(
891
- this.instanceIntents.get(target.targetSpotId)?.route,
892
- expectedCurrentRoute
893
- )) return false;
894
922
  if (
895
- target.targetNodeRid !== this.nodeRid
896
- || target.targetNodeGeneration !== this.nodeGeneration
897
- || pending.nodeRid !== this.nodeRid
898
- || pending.nodeGeneration !== this.nodeGeneration
899
- || pending.meshName !== envelope.targetMeshName
923
+ !matchesExpectedInstanceRoute(
924
+ this.instanceIntents.get(target.targetSpotId)?.route,
925
+ expectedCurrentRoute
926
+ )
927
+ )
928
+ return false;
929
+ if (
930
+ target.targetNodeRid !== this.nodeRid ||
931
+ target.targetNodeGeneration !== this.nodeGeneration ||
932
+ pending.nodeRid !== this.nodeRid ||
933
+ pending.nodeGeneration !== this.nodeGeneration ||
934
+ pending.meshName !== envelope.targetMeshName
900
935
  ) {
901
936
  throw new ServiceStaleGenerationError('spot', target.targetSpotId);
902
937
  }
@@ -928,10 +963,13 @@ export class ServiceStatefulRuntime {
928
963
  route: ServiceInstanceRouteFence,
929
964
  expectedCurrentRoute?: ServiceInstanceRouteFence | null
930
965
  ): Promise<ServiceInstanceRouteFence | undefined> {
931
- if (!matchesExpectedInstanceRoute(
932
- this.instanceIntents.get(target.targetSpotId)?.route,
933
- expectedCurrentRoute
934
- )) return undefined;
966
+ if (
967
+ !matchesExpectedInstanceRoute(
968
+ this.instanceIntents.get(target.targetSpotId)?.route,
969
+ expectedCurrentRoute
970
+ )
971
+ )
972
+ return undefined;
935
973
  const authority = this.asyncInstanceAuthority;
936
974
  if (authority === undefined) {
937
975
  throw new Error('Async Instance activation authority is not registered.');
@@ -940,17 +978,17 @@ export class ServiceStatefulRuntime {
940
978
  const currentRoute = this.instanceIntents.get(target.targetSpotId)?.route;
941
979
  if (!matchesExpectedInstanceRoute(currentRoute, expectedCurrentRoute)) return undefined;
942
980
  if (currentRoute !== undefined && !sameInstanceRoute(currentRoute, route)) return undefined;
943
- const authorityReleased = await this.instanceApplicationLifecycle?.completeTerminal({
944
- targetSpotId: target.targetSpotId,
945
- stableType: target.stableType,
946
- objectGeneration: route.objectGeneration
947
- })
948
- ?? false;
981
+ const authorityReleased =
982
+ (await this.instanceApplicationLifecycle?.completeTerminal({
983
+ targetSpotId: target.targetSpotId,
984
+ stableType: target.stableType,
985
+ objectGeneration: route.objectGeneration
986
+ })) ?? false;
949
987
  if (!authorityReleased) {
950
988
  if (currentRoute === undefined) {
951
989
  this.publishCommittedInstanceRoute(target.stableType, released, null);
952
990
  } else if (!this.replaceCommittedInstanceRoute(target.stableType, route, released)) {
953
- return undefined;
991
+ return undefined;
954
992
  }
955
993
  } else {
956
994
  this.forgetClosedInstanceRoute(released);
@@ -958,14 +996,11 @@ export class ServiceStatefulRuntime {
958
996
  return released;
959
997
  }
960
998
 
961
- waitForInstanceApplicationQuiescence(
962
- spotId: string,
963
- signal?: AbortSignal
964
- ): Promise<void> {
999
+ waitForInstanceApplicationQuiescence(spotId: string, signal?: AbortSignal): Promise<void> {
965
1000
  const key = String(spotId);
966
1001
  if (
967
- (this.pendingInstanceTerminals.get(key) ?? 0) === 0
968
- && (this.pendingInstanceAuthorityTerminals.get(key) ?? 0) === 0
1002
+ (this.pendingInstanceTerminals.get(key) ?? 0) === 0 &&
1003
+ (this.pendingInstanceAuthorityTerminals.get(key) ?? 0) === 0
969
1004
  ) {
970
1005
  return Promise.resolve();
971
1006
  }
@@ -989,17 +1024,19 @@ export class ServiceStatefulRuntime {
989
1024
  });
990
1025
  }
991
1026
 
992
-
993
1027
  rememberActorRoute(route: ServiceActorRouteFence): void {
994
1028
  if (route.actor.nodeRid.length === 0) {
995
1029
  throw new TypeError('Actor route requires a target node.');
996
1030
  }
997
- this.actorRoutes.set(actorKey(route.actor), Object.freeze({
998
- actor: Object.freeze({ ...route.actor }),
999
- targetNodeGeneration: route.targetNodeGeneration,
1000
- authorityOwnerGeneration: route.authorityOwnerGeneration,
1001
- ownerLeaseGeneration: route.ownerLeaseGeneration
1002
- }));
1031
+ this.actorRoutes.set(
1032
+ actorKey(route.actor),
1033
+ Object.freeze({
1034
+ actor: Object.freeze({ ...route.actor }),
1035
+ targetNodeGeneration: route.targetNodeGeneration,
1036
+ authorityOwnerGeneration: route.authorityOwnerGeneration,
1037
+ ownerLeaseGeneration: route.ownerLeaseGeneration
1038
+ })
1039
+ );
1003
1040
  }
1004
1041
 
1005
1042
  rememberSpotRoute(
@@ -1017,9 +1054,10 @@ export class ServiceStatefulRuntime {
1017
1054
  return;
1018
1055
  }
1019
1056
  if (
1020
- expectedCurrentRoute !== undefined
1021
- && !matchesExpectedDirectSpotRoute(current, expectedCurrentRoute)
1022
- ) return;
1057
+ expectedCurrentRoute !== undefined &&
1058
+ !matchesExpectedDirectSpotRoute(current, expectedCurrentRoute)
1059
+ )
1060
+ return;
1023
1061
  if (current !== undefined) {
1024
1062
  if (current.spot.generation < route.spot.generation) {
1025
1063
  const next = freezeDirectSpotRoute(route);
@@ -1061,9 +1099,9 @@ export class ServiceStatefulRuntime {
1061
1099
  return await this.raw.sendService(targetNodeRid, [encodeMessageFollowHeader(record)]);
1062
1100
  }
1063
1101
 
1064
- setMessageFollowHandler(handler: (
1065
- record: import('./service-stateful-wire-codec').ServiceMessageFollowRecord
1066
- ) => void): void {
1102
+ setMessageFollowHandler(
1103
+ handler: (record: import('./service-stateful-wire-codec').ServiceMessageFollowRecord) => void
1104
+ ): void {
1067
1105
  this.messageFollowHandler = handler;
1068
1106
  }
1069
1107
 
@@ -1072,8 +1110,8 @@ export class ServiceStatefulRuntime {
1072
1110
  ): ServiceSpotMessageFollowSeal | undefined {
1073
1111
  this.requireOpen();
1074
1112
  if (
1075
- source.targetNodeRid !== this.nodeRid
1076
- || source.targetNodeGeneration !== this.nodeGeneration
1113
+ source.targetNodeRid !== this.nodeRid ||
1114
+ source.targetNodeGeneration !== this.nodeGeneration
1077
1115
  ) {
1078
1116
  return undefined;
1079
1117
  }
@@ -1125,10 +1163,10 @@ export class ServiceStatefulRuntime {
1125
1163
  throw new RangeError('Message Follow duration must be a non-negative safe integer.');
1126
1164
  }
1127
1165
  if (
1128
- target.spot.spotId !== state.source.spot.spotId
1129
- || target.spot.generation !== state.source.spot.generation
1130
- || target.authorityOwnerGeneration <= state.source.authorityOwnerGeneration
1131
- || target.targetNodeRid === this.nodeRid
1166
+ target.spot.spotId !== state.source.spot.spotId ||
1167
+ target.spot.generation !== state.source.spot.generation ||
1168
+ target.authorityOwnerGeneration <= state.source.authorityOwnerGeneration ||
1169
+ target.targetNodeRid === this.nodeRid
1132
1170
  ) {
1133
1171
  throw new ServiceStaleGenerationError('spot', state.source.spot.spotId);
1134
1172
  }
@@ -1139,9 +1177,7 @@ export class ServiceStatefulRuntime {
1139
1177
  state.target
1140
1178
  );
1141
1179
  this.spotMessageFollowSuppression.retainRoute(state.suppressionFence);
1142
- state.expiresAtMs = durationMs === 0
1143
- ? Number.MAX_SAFE_INTEGER
1144
- : performance.now() + durationMs;
1180
+ state.expiresAtMs = durationMs === 0 ? Number.MAX_SAFE_INTEGER : performance.now() + durationMs;
1145
1181
  await this.drainSpotMessageFollow(state);
1146
1182
  if (durationMs === 0) this.removeSpotMessageFollow(state);
1147
1183
  return true;
@@ -1156,16 +1192,16 @@ export class ServiceStatefulRuntime {
1156
1192
  const exact = this.spotRoutes.get(exactKey);
1157
1193
  const current = this.directSpotRoutes.get(directSpotKey(spot.spotId));
1158
1194
  if (
1159
- exact?.authorityOwnerGeneration === authorityOwnerGeneration
1160
- && (storeVersion === undefined || exact.storeVersion === storeVersion)
1195
+ exact?.authorityOwnerGeneration === authorityOwnerGeneration &&
1196
+ (storeVersion === undefined || exact.storeVersion === storeVersion)
1161
1197
  ) {
1162
1198
  this.spotRoutes.delete(exactKey);
1163
1199
  }
1164
1200
  const key = directSpotKey(spot.spotId);
1165
1201
  if (
1166
- current?.authorityOwnerGeneration === authorityOwnerGeneration
1167
- && current.spot.generation === spot.generation
1168
- && (storeVersion === undefined || current.storeVersion === storeVersion)
1202
+ current?.authorityOwnerGeneration === authorityOwnerGeneration &&
1203
+ current.spot.generation === spot.generation &&
1204
+ (storeVersion === undefined || current.storeVersion === storeVersion)
1169
1205
  ) {
1170
1206
  this.directSpotRoutes.delete(key);
1171
1207
  }
@@ -1204,16 +1240,43 @@ export class ServiceStatefulRuntime {
1204
1240
  sourceSpotId = this.nodeRid
1205
1241
  ): Promise<void> {
1206
1242
  await this.enqueueLogicalMulticast(channelName, topic, sourceSpotId, payload);
1207
- const targets = this.raw.topology.peers()
1208
- .filter(peer => peer.descriptor.channels.some(
1209
- channel => channel.name === channelName && channel.weight > 0
1210
- ));
1243
+ const targets = this.raw.topology
1244
+ .peers()
1245
+ .filter(
1246
+ (peer) =>
1247
+ peer.descriptor.channels.some(
1248
+ (channel) => channel.name === channelName && channel.weight > 0
1249
+ ) && this.raw.isPeerRouteReady(peer.descriptor.nodeRoutingId)
1250
+ );
1211
1251
  const header = encodeLogicalMulticastHeader(channelName, topic, sourceSpotId);
1212
1252
  const payloadFrame = encodeApplicationPayload(payload);
1253
+ const reporter = this.dispatchErrors;
1254
+ const captureFailures = reporter?.captureEnabled() === true;
1213
1255
  for (const target of targets) {
1214
1256
  // Remote admission ends at the source outbound transport queue. The
1215
1257
  // receiver's Spot queue and handler completion are not publish results.
1216
- await this.raw.sendService(target.descriptor.nodeRoutingId, [header, payloadFrame]);
1258
+ const accepted = await this.raw.sendService(target.descriptor.nodeRoutingId, [
1259
+ header,
1260
+ payloadFrame
1261
+ ]);
1262
+ if (!accepted) {
1263
+ if (captureFailures) {
1264
+ reporter.report({
1265
+ surface: ZLinkDispatchErrorSurface.SpotRoute,
1266
+ messageKind: ZLinkDispatchMessageKind.Send,
1267
+ reason: serviceSpotPublishFailureReason(
1268
+ undefined,
1269
+ this.raw.isPeerRouteReady(target.descriptor.nodeRoutingId),
1270
+ this.closed
1271
+ ),
1272
+ action: ZLinkDispatchErrorAction.Drop,
1273
+ meshName: this.dispatchErrorMeshName,
1274
+ channelName,
1275
+ topic,
1276
+ targetRid: target.descriptor.nodeRoutingId
1277
+ });
1278
+ }
1279
+ }
1217
1280
  }
1218
1281
  }
1219
1282
 
@@ -1327,19 +1390,25 @@ export class ServiceStatefulRuntime {
1327
1390
  sourceSpotId?: string,
1328
1391
  metadataFrame?: Uint8Array
1329
1392
  ): Promise<number> {
1330
- return this.submitOneWay(route.targetNodeRid, instanceOperationParts([
1331
- encodeInstanceSpotHeader(
1332
- route,
1333
- this.nodeGeneration,
1334
- this.nodeRid,
1335
- sourceSpotId,
1336
- 'send',
1337
- { high: 0n, low: 0n },
1338
- undefined,
1339
- metadataFrame !== undefined
1340
- ),
1341
- encodeApplicationPayload(payload)
1342
- ], metadataFrame));
1393
+ return this.submitOneWay(
1394
+ route.targetNodeRid,
1395
+ instanceOperationParts(
1396
+ [
1397
+ encodeInstanceSpotHeader(
1398
+ route,
1399
+ this.nodeGeneration,
1400
+ this.nodeRid,
1401
+ sourceSpotId,
1402
+ 'send',
1403
+ { high: 0n, low: 0n },
1404
+ undefined,
1405
+ metadataFrame !== undefined
1406
+ ),
1407
+ encodeApplicationPayload(payload)
1408
+ ],
1409
+ metadataFrame
1410
+ )
1411
+ );
1343
1412
  }
1344
1413
 
1345
1414
  async sendToMissingInstanceSpot(
@@ -1366,20 +1435,26 @@ export class ServiceStatefulRuntime {
1366
1435
  metadataFrame?: Uint8Array
1367
1436
  ): Promise<number> {
1368
1437
  const operation = { high: this.nodeGeneration, low: this.nextInstanceOperation++ };
1369
- return await this.submitOneWay(target.targetNodeRid, instanceOperationParts([
1370
- encodeInstanceSpotActivationHeader(
1371
- target,
1372
- this.nodeGeneration,
1373
- this.nodeRid,
1374
- sourceSpotId,
1375
- 'send',
1376
- operation,
1377
- deadlineUnixMs,
1378
- undefined,
1379
- metadataFrame !== undefined
1380
- ),
1381
- payloadFrame
1382
- ], metadataFrame));
1438
+ return await this.submitOneWay(
1439
+ target.targetNodeRid,
1440
+ instanceOperationParts(
1441
+ [
1442
+ encodeInstanceSpotActivationHeader(
1443
+ target,
1444
+ this.nodeGeneration,
1445
+ this.nodeRid,
1446
+ sourceSpotId,
1447
+ 'send',
1448
+ operation,
1449
+ deadlineUnixMs,
1450
+ undefined,
1451
+ metadataFrame !== undefined
1452
+ ),
1453
+ payloadFrame
1454
+ ],
1455
+ metadataFrame
1456
+ )
1457
+ );
1383
1458
  }
1384
1459
 
1385
1460
  requestToInstanceSpot(
@@ -1393,19 +1468,22 @@ export class ServiceStatefulRuntime {
1393
1468
  this.submitRequest(
1394
1469
  pending,
1395
1470
  route.targetNodeRid,
1396
- instanceOperationParts([
1397
- encodeInstanceSpotHeader(
1398
- route,
1399
- this.nodeGeneration,
1400
- this.nodeRid,
1401
- sourceSpotId,
1402
- 'request',
1403
- { high: 2n, low: pending.id },
1404
- pending.id,
1405
- metadataFrame !== undefined
1406
- ),
1407
- encodeApplicationPayload(payload)
1408
- ], metadataFrame),
1471
+ instanceOperationParts(
1472
+ [
1473
+ encodeInstanceSpotHeader(
1474
+ route,
1475
+ this.nodeGeneration,
1476
+ this.nodeRid,
1477
+ sourceSpotId,
1478
+ 'request',
1479
+ { high: 2n, low: pending.id },
1480
+ pending.id,
1481
+ metadataFrame !== undefined
1482
+ ),
1483
+ encodeApplicationPayload(payload)
1484
+ ],
1485
+ metadataFrame
1486
+ ),
1409
1487
  timeoutMs,
1410
1488
  'instanceSpotRequest'
1411
1489
  );
@@ -1442,20 +1520,23 @@ export class ServiceStatefulRuntime {
1442
1520
  this.submitRequest(
1443
1521
  pending,
1444
1522
  target.targetNodeRid,
1445
- instanceOperationParts([
1446
- encodeInstanceSpotActivationHeader(
1447
- target,
1448
- this.nodeGeneration,
1449
- this.nodeRid,
1450
- sourceSpotId,
1451
- 'request',
1452
- { high: this.nodeGeneration, low: pending.id },
1453
- deadlineUnixMs,
1454
- pending.id,
1455
- metadataFrame !== undefined
1456
- ),
1457
- payloadFrame
1458
- ], metadataFrame),
1523
+ instanceOperationParts(
1524
+ [
1525
+ encodeInstanceSpotActivationHeader(
1526
+ target,
1527
+ this.nodeGeneration,
1528
+ this.nodeRid,
1529
+ sourceSpotId,
1530
+ 'request',
1531
+ { high: this.nodeGeneration, low: pending.id },
1532
+ deadlineUnixMs,
1533
+ pending.id,
1534
+ metadataFrame !== undefined
1535
+ ),
1536
+ payloadFrame
1537
+ ],
1538
+ metadataFrame
1539
+ ),
1459
1540
  timeoutMs,
1460
1541
  'instanceSpotRequest'
1461
1542
  );
@@ -1506,19 +1587,15 @@ export class ServiceStatefulRuntime {
1506
1587
  timeoutMs: number
1507
1588
  ): ServiceStatefulPendingOperation {
1508
1589
  const deadlineMs = performance.now() + timeoutMs;
1509
- const pending = this.operations.register(timeoutMs, targetNodeRid === this.nodeRid ? 'registry' : 'sender');
1590
+ const pending = this.operations.register(
1591
+ timeoutMs,
1592
+ targetNodeRid === this.nodeRid ? 'registry' : 'sender'
1593
+ );
1510
1594
  const target = this.trySpotFence(targetNodeRid, {
1511
1595
  ...targetSpot,
1512
1596
  generation: targetSpotGeneration
1513
1597
  });
1514
- this.submitActorJoin(
1515
- pending,
1516
- actor,
1517
- targetNodeRid,
1518
- target,
1519
- payload,
1520
- deadlineMs
1521
- );
1598
+ this.submitActorJoin(pending, actor, targetNodeRid, target, payload, deadlineMs);
1522
1599
  return pending;
1523
1600
  }
1524
1601
 
@@ -1533,20 +1610,19 @@ export class ServiceStatefulRuntime {
1533
1610
  timeoutMs: number
1534
1611
  ): ServiceStatefulPendingOperation {
1535
1612
  const deadlineMs = performance.now() + timeoutMs;
1536
- const pending = this.operations.register(timeoutMs, targetNodeRid === this.nodeRid ? 'registry' : 'sender');
1613
+ const pending = this.operations.register(
1614
+ timeoutMs,
1615
+ targetNodeRid === this.nodeRid ? 'registry' : 'sender'
1616
+ );
1537
1617
  const target = this.trySpotFence(targetNodeRid, {
1538
1618
  ...targetSpot,
1539
1619
  generation: targetSpotGeneration
1540
1620
  });
1541
- this.submitActorJoin(
1542
- pending,
1543
- actor,
1544
- targetNodeRid,
1545
- target,
1621
+ this.submitActorJoin(pending, actor, targetNodeRid, target, request, deadlineMs, {
1546
1622
  request,
1547
- deadlineMs,
1548
- { request, actorFence, local }
1549
- );
1623
+ actorFence,
1624
+ local
1625
+ });
1550
1626
  return pending;
1551
1627
  }
1552
1628
 
@@ -1557,7 +1633,10 @@ export class ServiceStatefulRuntime {
1557
1633
  timeoutMs: number
1558
1634
  ): ServiceStatefulPendingOperation {
1559
1635
  const deadlineMs = performance.now() + timeoutMs;
1560
- const pending = this.operations.register(timeoutMs, targetNodeRid === this.nodeRid ? 'registry' : 'sender');
1636
+ const pending = this.operations.register(
1637
+ timeoutMs,
1638
+ targetNodeRid === this.nodeRid ? 'registry' : 'sender'
1639
+ );
1561
1640
  this.submitActorJoin(
1562
1641
  pending,
1563
1642
  actor,
@@ -1578,7 +1657,10 @@ export class ServiceStatefulRuntime {
1578
1657
  timeoutMs: number
1579
1658
  ): ServiceStatefulPendingOperation {
1580
1659
  const deadlineMs = performance.now() + timeoutMs;
1581
- const pending = this.operations.register(timeoutMs, targetNodeRid === this.nodeRid ? 'registry' : 'sender');
1660
+ const pending = this.operations.register(
1661
+ timeoutMs,
1662
+ targetNodeRid === this.nodeRid ? 'registry' : 'sender'
1663
+ );
1582
1664
  this.submitActorJoin(
1583
1665
  pending,
1584
1666
  actor,
@@ -1656,7 +1738,10 @@ export class ServiceStatefulRuntime {
1656
1738
  const previous = this.registry.binding(actor);
1657
1739
  if (previous !== undefined && sameSessionIdentity(previous, localBinding)) {
1658
1740
  const currentDelivery = this.sessionDeliveries.get(deliveryKey);
1659
- if (currentDelivery !== undefined && sameSessionBinding(currentDelivery.binding, previous)) {
1741
+ if (
1742
+ currentDelivery !== undefined &&
1743
+ sameSessionBinding(currentDelivery.binding, previous)
1744
+ ) {
1660
1745
  this.sessionDeliveries.set(deliveryKey, {
1661
1746
  ...delivery,
1662
1747
  binding: previous
@@ -1680,10 +1765,7 @@ export class ServiceStatefulRuntime {
1680
1765
  this.nodeGeneration
1681
1766
  );
1682
1767
  if (previousDelivery !== undefined && previous !== undefined) {
1683
- this.retiredSessionDeliveries.set(
1684
- sessionDeliveryKey(previous),
1685
- previousDelivery
1686
- );
1768
+ this.retiredSessionDeliveries.set(sessionDeliveryKey(previous), previousDelivery);
1687
1769
  }
1688
1770
  installedDelivery = { ...delivery, binding };
1689
1771
  this.sessionDeliveries.set(deliveryKey, installedDelivery);
@@ -1693,18 +1775,24 @@ export class ServiceStatefulRuntime {
1693
1775
  kindData: undefined
1694
1776
  });
1695
1777
  if (previous !== undefined) {
1696
- this.sendBoundSessionReplacement(previous, actorAuthorityFromRoute(
1697
- this.tryActorFence(actor) ?? {
1698
- actor,
1699
- targetNodeGeneration: this.nodeGeneration,
1700
- authorityOwnerGeneration: this.registry.actor(actor.actorId)?.authorityOwnerGeneration
1701
- ?? actor.generation,
1702
- ownerLeaseGeneration: this.nodeGeneration
1703
- }
1704
- ));
1778
+ this.sendBoundSessionReplacement(
1779
+ previous,
1780
+ actorAuthorityFromRoute(
1781
+ this.tryActorFence(actor) ?? {
1782
+ actor,
1783
+ targetNodeGeneration: this.nodeGeneration,
1784
+ authorityOwnerGeneration:
1785
+ this.registry.actor(actor.actorId)?.authorityOwnerGeneration ?? actor.generation,
1786
+ ownerLeaseGeneration: this.nodeGeneration
1787
+ }
1788
+ )
1789
+ );
1705
1790
  }
1706
1791
  } catch (error) {
1707
- if (installedDelivery !== undefined && this.sessionDeliveries.get(deliveryKey) === installedDelivery) {
1792
+ if (
1793
+ installedDelivery !== undefined &&
1794
+ this.sessionDeliveries.get(deliveryKey) === installedDelivery
1795
+ ) {
1708
1796
  this.sessionDeliveries.delete(deliveryKey);
1709
1797
  }
1710
1798
  this.operations.reply(pending.id, failure(error));
@@ -1715,28 +1803,29 @@ export class ServiceStatefulRuntime {
1715
1803
  let bindingActorFence: ServiceActorRouteFence;
1716
1804
  let header: Buffer;
1717
1805
  try {
1718
- bindingActorFence = actorAuthority === undefined
1719
- ? this.actorFence(actor)
1720
- : { actor, ...actorAuthority };
1721
- header = encodeBoundSessionBindHeader(
1722
- pending.id,
1723
- bindingActorFence,
1724
- sessionRid,
1725
- { state: 'active', generation }
1726
- );
1806
+ bindingActorFence =
1807
+ actorAuthority === undefined ? this.actorFence(actor) : { actor, ...actorAuthority };
1808
+ header = encodeBoundSessionBindHeader(pending.id, bindingActorFence, sessionRid, {
1809
+ state: 'active',
1810
+ generation
1811
+ });
1727
1812
  } catch (error) {
1728
1813
  this.operations.fail(pending.id, error);
1729
1814
  return pending;
1730
1815
  }
1731
1816
  void this.requestDurableOperation(
1732
- actor.nodeRid, [header], pending.id, 'streamBind', deadlineMs
1817
+ actor.nodeRid,
1818
+ [header],
1819
+ pending.id,
1820
+ 'streamBind',
1821
+ deadlineMs
1733
1822
  ).then(
1734
- reply => this.completeRemoteReply(pending, actor.nodeRid, 'streamBind', undefined, reply),
1735
- error => this.operations.fail(pending.id, error)
1823
+ (reply) => this.completeRemoteReply(pending, actor.nodeRid, 'streamBind', undefined, reply),
1824
+ (error) => this.operations.fail(pending.id, error)
1736
1825
  );
1737
1826
  return {
1738
1827
  id: pending.id,
1739
- promise: pending.promise.then(result => {
1828
+ promise: pending.promise.then((result) => {
1740
1829
  if (result.terminalResult === RequestResult.Ok && result.streamBinding !== undefined) {
1741
1830
  const committed: ServiceSessionDelivery = {
1742
1831
  ...delivery,
@@ -1747,10 +1836,10 @@ export class ServiceStatefulRuntime {
1747
1836
  };
1748
1837
  const current = this.sessionDeliveries.get(deliveryKey);
1749
1838
  if (
1750
- current === previousDelivery
1751
- || current === undefined
1752
- || sameSessionOwnerIdentity(current.binding, committed.binding)
1753
- && current.binding.bindingGeneration < committed.binding.bindingGeneration
1839
+ current === previousDelivery ||
1840
+ current === undefined ||
1841
+ (sameSessionOwnerIdentity(current.binding, committed.binding) &&
1842
+ current.binding.bindingGeneration < committed.binding.bindingGeneration)
1754
1843
  ) {
1755
1844
  if (current !== undefined && !sameSessionBinding(current.binding, committed.binding)) {
1756
1845
  this.retiredSessionDeliveries.set(sessionDeliveryKey(current.binding), current);
@@ -1776,9 +1865,9 @@ export class ServiceStatefulRuntime {
1776
1865
  const pending = this.operations.register(timeoutMs);
1777
1866
  const delivery = this.sessionDeliveries.get(actorKey(actor));
1778
1867
  if (
1779
- delivery === undefined
1780
- || delivery.binding.sessionRid !== sessionRid
1781
- || delivery.binding.bindingGeneration !== expectedBindingGeneration
1868
+ delivery === undefined ||
1869
+ delivery.binding.sessionRid !== sessionRid ||
1870
+ delivery.binding.bindingGeneration !== expectedBindingGeneration
1782
1871
  ) {
1783
1872
  this.operations.reply(pending.id, {
1784
1873
  terminalResult: RequestResult.NotFound,
@@ -1796,24 +1885,22 @@ export class ServiceStatefulRuntime {
1796
1885
  }
1797
1886
  return pending;
1798
1887
  }
1799
- const header = encodeBoundSessionBindHeader(
1800
- pending.id,
1801
- this.actorFence(actor),
1802
- sessionRid,
1803
- { state: 'tombstone', retiredGeneration: expectedBindingGeneration }
1804
- );
1888
+ const header = encodeBoundSessionBindHeader(pending.id, this.actorFence(actor), sessionRid, {
1889
+ state: 'tombstone',
1890
+ retiredGeneration: expectedBindingGeneration
1891
+ });
1805
1892
  this.submitRequest(pending, actor.nodeRid, [header], timeoutMs, 'streamUnbind');
1806
1893
  return pending;
1807
1894
  }
1808
1895
 
1809
1896
  sessionBindings(sessionRid: string): readonly ServiceSessionBinding[] {
1810
1897
  return [...this.sessionDeliveries.values()]
1811
- .map(value => value.binding)
1812
- .filter(binding => binding.sessionRid === sessionRid);
1898
+ .map((value) => value.binding)
1899
+ .filter((binding) => binding.sessionRid === sessionRid);
1813
1900
  }
1814
1901
 
1815
1902
  allSessionBindings(): readonly ServiceSessionBinding[] {
1816
- return [...this.sessionDeliveries.values()].map(value => value.binding);
1903
+ return [...this.sessionDeliveries.values()].map((value) => value.binding);
1817
1904
  }
1818
1905
 
1819
1906
  async sendSessionToActor(
@@ -1852,14 +1939,11 @@ export class ServiceStatefulRuntime {
1852
1939
  }
1853
1940
  const actorFence = this.tryBoundSessionSendFence(actor, senderFence);
1854
1941
  if (actorFence === undefined) return SubmitResult.InvalidState;
1855
- const header = encodeBoundSessionSendHeader(
1856
- actorFence,
1857
- expectedBindingGeneration
1858
- );
1859
- return this.submitOneWay(
1860
- binding.sessionOwnerNodeRid,
1861
- [header, encodeApplicationPayload(payload)]
1862
- );
1942
+ const header = encodeBoundSessionSendHeader(actorFence, expectedBindingGeneration);
1943
+ return this.submitOneWay(binding.sessionOwnerNodeRid, [
1944
+ header,
1945
+ encodeApplicationPayload(payload)
1946
+ ]);
1863
1947
  }
1864
1948
 
1865
1949
  close(): void {
@@ -1906,23 +1990,21 @@ export class ServiceStatefulRuntime {
1906
1990
  // fall through to RawServiceMeshRuntime's relocation ingress instead of
1907
1991
  // being decoded as stateful actor/spot work.
1908
1992
  if (
1909
- record.command === M6bServiceWireCommand.relocationReady
1910
- || record.command === M6bServiceWireCommand.relocationData
1911
- || record.command === M6bServiceWireCommand.replyRelay
1912
- || record.command === M6bServiceWireCommand.relocationCutover
1993
+ record.command === M6bServiceWireCommand.relocationReady ||
1994
+ record.command === M6bServiceWireCommand.relocationData ||
1995
+ record.command === M6bServiceWireCommand.replyRelay ||
1996
+ record.command === M6bServiceWireCommand.relocationCutover
1913
1997
  ) {
1914
1998
  return undefined;
1915
1999
  }
1916
2000
  if (
1917
- record.command < M6bServiceWireCommand.spotSend
1918
- || (
1919
- record.command > M6bServiceWireCommand.instanceSpot
1920
- && record.command !== M6bServiceWireCommand.userSpotCreate
1921
- && record.command !== M6bServiceWireCommand.userSpotClose
1922
- && record.command !== M6bServiceWireCommand.actorCreate
1923
- && record.command !== M6bServiceWireCommand.messageFollow
1924
- && record.command !== M6bServiceWireCommand.boundSessionReplaced
1925
- )
2001
+ record.command < M6bServiceWireCommand.spotSend ||
2002
+ (record.command > M6bServiceWireCommand.instanceSpot &&
2003
+ record.command !== M6bServiceWireCommand.userSpotCreate &&
2004
+ record.command !== M6bServiceWireCommand.userSpotClose &&
2005
+ record.command !== M6bServiceWireCommand.actorCreate &&
2006
+ record.command !== M6bServiceWireCommand.messageFollow &&
2007
+ record.command !== M6bServiceWireCommand.boundSessionReplaced)
1926
2008
  ) {
1927
2009
  return undefined;
1928
2010
  }
@@ -1948,38 +2030,40 @@ export class ServiceStatefulRuntime {
1948
2030
  'actorJoin',
1949
2031
  'boundSessionSend'
1950
2032
  ].includes(decoded.kind);
1951
- const instanceMetadata = decoded.kind === 'instanceSpot'
1952
- && (record.flags & M6bServiceWireFlag.metadata) !== 0;
1953
- const userSpotInfrastructure = decoded.kind === 'userSpotCreate'
1954
- || decoded.kind === 'userSpotClose'
1955
- || decoded.kind === 'actorCreate'
1956
- || decoded.kind === 'messageFollow'
1957
- || decoded.kind === 'boundSessionReplaced';
2033
+ const instanceMetadata =
2034
+ decoded.kind === 'instanceSpot' && (record.flags & M6bServiceWireFlag.metadata) !== 0;
2035
+ const userSpotInfrastructure =
2036
+ decoded.kind === 'userSpotCreate' ||
2037
+ decoded.kind === 'userSpotClose' ||
2038
+ decoded.kind === 'actorCreate' ||
2039
+ decoded.kind === 'messageFollow' ||
2040
+ decoded.kind === 'boundSessionReplaced';
1958
2041
  if (
1959
- record.parts.length < 1
1960
- || record.parts.length > (instanceMetadata ? 3 : 2)
1961
- || (hasPayload && decoded.kind !== 'actorJoin' && record.parts.length !== 2)
1962
- || (
1963
- decoded.kind === 'instanceSpot'
1964
- && record.parts.length !== (instanceMetadata ? 3 : 2)
1965
- )
1966
- || (userSpotInfrastructure && record.parts.length !== 1)
2042
+ record.parts.length < 1 ||
2043
+ record.parts.length > (instanceMetadata ? 3 : 2) ||
2044
+ (hasPayload && decoded.kind !== 'actorJoin' && record.parts.length !== 2) ||
2045
+ (decoded.kind === 'instanceSpot' && record.parts.length !== (instanceMetadata ? 3 : 2)) ||
2046
+ (userSpotInfrastructure && record.parts.length !== 1)
1967
2047
  ) {
1968
2048
  return 'protocolError';
1969
2049
  }
1970
2050
  const metadataFrame = instanceMetadata
1971
2051
  ? validateServiceMetadataFrame(record.parts[1]!)
1972
2052
  : undefined;
1973
- const canonicalPayload = canonicalActorJoin?.payload === undefined
1974
- ? undefined
1975
- : {
1976
- packetName: canonicalActorJoin.payload.packetName,
1977
- contentType: canonicalActorJoin.payload.contentType,
1978
- payload: Buffer.from(canonicalActorJoin.payload.payload)
1979
- };
1980
- const payloadFrame = canonicalPayload === undefined
1981
- ? (record.parts.length >= 2 ? record.parts[record.parts.length - 1] : undefined)
1982
- : encodeApplicationPayload(canonicalPayload);
2053
+ const canonicalPayload =
2054
+ canonicalActorJoin?.payload === undefined
2055
+ ? undefined
2056
+ : {
2057
+ packetName: canonicalActorJoin.payload.packetName,
2058
+ contentType: canonicalActorJoin.payload.contentType,
2059
+ payload: Buffer.from(canonicalActorJoin.payload.payload)
2060
+ };
2061
+ const payloadFrame =
2062
+ canonicalPayload === undefined
2063
+ ? record.parts.length >= 2
2064
+ ? record.parts[record.parts.length - 1]
2065
+ : undefined
2066
+ : encodeApplicationPayload(canonicalPayload);
1983
2067
  try {
1984
2068
  return await this.handleIngress(
1985
2069
  record,
@@ -2000,9 +2084,9 @@ export class ServiceStatefulRuntime {
2000
2084
  if (error instanceof ZLinkFrameworkException) {
2001
2085
  const kind = internalFrameworkErrorKind(error);
2002
2086
  if (
2003
- kind === ZLinkFrameworkInternalErrorKind.RequestTargetNotFound
2004
- || kind === ZLinkFrameworkInternalErrorKind.SpotMoving
2005
- || kind === ZLinkFrameworkInternalErrorKind.SpotGenerationStale
2087
+ kind === ZLinkFrameworkInternalErrorKind.RequestTargetNotFound ||
2088
+ kind === ZLinkFrameworkInternalErrorKind.SpotMoving ||
2089
+ kind === ZLinkFrameworkInternalErrorKind.SpotGenerationStale
2006
2090
  ) {
2007
2091
  return 'protocolError';
2008
2092
  }
@@ -2025,9 +2109,10 @@ export class ServiceStatefulRuntime {
2025
2109
  ): Promise<RawServicePumpResult> {
2026
2110
  switch (record.kind) {
2027
2111
  case 'messageFollow': {
2028
- if (record.source.kind !== record.target.kind
2029
- || record.target.authorityOwnerGeneration
2030
- <= record.source.authorityOwnerGeneration) {
2112
+ if (
2113
+ record.source.kind !== record.target.kind ||
2114
+ record.target.authorityOwnerGeneration <= record.source.authorityOwnerGeneration
2115
+ ) {
2031
2116
  throw new ServiceWireProtocolError(
2032
2117
  'Message Follow target owner generation must increase at every hop.'
2033
2118
  );
@@ -2043,10 +2128,10 @@ export class ServiceStatefulRuntime {
2043
2128
  'Message Follow source route is not the current admitted peer.'
2044
2129
  );
2045
2130
  }
2046
- const targetGeneration = record.target.targetNodeRid === this.nodeRid
2047
- ? this.nodeGeneration
2048
- : this.raw.topology.peer(record.target.targetNodeRid)?.descriptor
2049
- .lifecycleGeneration;
2131
+ const targetGeneration =
2132
+ record.target.targetNodeRid === this.nodeRid
2133
+ ? this.nodeGeneration
2134
+ : this.raw.topology.peer(record.target.targetNodeRid)?.descriptor.lifecycleGeneration;
2050
2135
  if (targetGeneration !== record.target.targetNodeGeneration) {
2051
2136
  throw new ServiceWireProtocolError(
2052
2137
  'Message Follow target route is not the current topology target.'
@@ -2057,8 +2142,7 @@ export class ServiceStatefulRuntime {
2057
2142
  } else {
2058
2143
  const directKey = directSpotKey(record.source.spot.spotId);
2059
2144
  const current = this.directSpotRoutes.get(directKey);
2060
- if (current !== undefined
2061
- && sameMessageFollowSpotSource(current, record.source)) {
2145
+ if (current !== undefined && sameMessageFollowSpotSource(current, record.source)) {
2062
2146
  this.directSpotRoutes.delete(directKey);
2063
2147
  const exactKey = spotKey(record.source.spot);
2064
2148
  const exact = this.spotRoutes.get(exactKey);
@@ -2079,7 +2163,8 @@ export class ServiceStatefulRuntime {
2079
2163
  `spot:${record.target.spot.spotId}`,
2080
2164
  payloadFrame!,
2081
2165
  {
2082
- receiveKind: record.kind === 'spotSend' ? ReceiveKind.SpotSend : ReceiveKind.SpotRequest,
2166
+ receiveKind:
2167
+ record.kind === 'spotSend' ? ReceiveKind.SpotSend : ReceiveKind.SpotRequest,
2083
2168
  operationKind: record.kind === 'spotRequest' ? OperationKind.SpotRequest : 0,
2084
2169
  ...(record.correlation === undefined ? {} : { correlation: record.correlation }),
2085
2170
  sourceSpotId: record.sourceSpotId,
@@ -2092,17 +2177,18 @@ export class ServiceStatefulRuntime {
2092
2177
  }
2093
2178
  case 'actorSend':
2094
2179
  case 'actorRequest': {
2095
- const actor = record.boundSession === undefined
2096
- ? this.validateActorMessageFence(record.target)
2097
- : this.validateActorFence(record.target);
2180
+ const actor =
2181
+ record.boundSession === undefined
2182
+ ? this.validateActorMessageFence(record.target)
2183
+ : this.validateActorFence(record.target);
2098
2184
  if (record.boundSession !== undefined) {
2099
2185
  const binding = this.registry.validateBoundSession(
2100
2186
  record.target.actor,
2101
2187
  record.boundSession.bindingGeneration
2102
2188
  );
2103
2189
  if (
2104
- binding.sessionRid !== record.boundSession.sessionRid
2105
- || binding.sessionOwnerNodeRid !== ingress.sourceRoutingId
2190
+ binding.sessionRid !== record.boundSession.sessionRid ||
2191
+ binding.sessionOwnerNodeRid !== ingress.sourceRoutingId
2106
2192
  ) {
2107
2193
  throw new ServiceStaleGenerationError('binding', record.target.actor.actorId);
2108
2194
  }
@@ -2112,7 +2198,8 @@ export class ServiceStatefulRuntime {
2112
2198
  `actor:${actor.ref.actorId}\0${actor.ref.generation}`,
2113
2199
  payloadFrame!,
2114
2200
  {
2115
- receiveKind: record.kind === 'actorSend' ? ReceiveKind.ActorSend : ReceiveKind.ActorRequest,
2201
+ receiveKind:
2202
+ record.kind === 'actorSend' ? ReceiveKind.ActorSend : ReceiveKind.ActorRequest,
2116
2203
  operationKind: record.kind === 'actorRequest' ? OperationKind.ActorRequest : 0,
2117
2204
  ...(record.correlation === undefined ? {} : { correlation: record.correlation }),
2118
2205
  ...(record.sourceActor === undefined
@@ -2170,18 +2257,9 @@ export class ServiceStatefulRuntime {
2170
2257
  case 'boundSessionReplaced':
2171
2258
  return this.handleBoundSessionReplaced(ingress, record);
2172
2259
  case 'boundSessionSend':
2173
- return await this.deliverBoundSession(
2174
- ingress,
2175
- record,
2176
- payloadFrame
2177
- );
2260
+ return await this.deliverBoundSession(ingress, record, payloadFrame);
2178
2261
  case 'instanceSpot':
2179
- return this.enqueueInstanceSpot(
2180
- ingress,
2181
- record,
2182
- payloadFrame!,
2183
- metadataFrame
2184
- );
2262
+ return this.enqueueInstanceSpot(ingress, record, payloadFrame!, metadataFrame);
2185
2263
  case 'userSpotCreate':
2186
2264
  case 'userSpotClose':
2187
2265
  case 'actorCreate':
@@ -2207,8 +2285,8 @@ export class ServiceStatefulRuntime {
2207
2285
  return 'infrastructure';
2208
2286
  }
2209
2287
  if (
2210
- record.activation === 'ready'
2211
- && this.needsInstanceApplicationMaterialization(ingress, record)
2288
+ record.activation === 'ready' &&
2289
+ this.needsInstanceApplicationMaterialization(ingress, record)
2212
2290
  ) {
2213
2291
  const ownedIngress = shareIngressOwnership(ingress);
2214
2292
  void this.continueReadyInstanceMaterialization(
@@ -2220,13 +2298,14 @@ export class ServiceStatefulRuntime {
2220
2298
  return 'infrastructure';
2221
2299
  }
2222
2300
  const spot = this.requireInstanceActivation(ingress, record);
2223
- const applicationTarget = record.activation === 'missing'
2224
- ? {
2225
- targetSpotId: record.target.targetSpotId,
2226
- stableType: record.target.stableType,
2227
- objectGeneration: spot.ref.generation
2228
- }
2229
- : this.instanceApplicationTarget(record);
2301
+ const applicationTarget =
2302
+ record.activation === 'missing'
2303
+ ? {
2304
+ targetSpotId: record.target.targetSpotId,
2305
+ stableType: record.target.stableType,
2306
+ objectGeneration: spot.ref.generation
2307
+ }
2308
+ : this.instanceApplicationTarget(record);
2230
2309
  return this.enqueueActivatedInstanceSpot(
2231
2310
  ingress,
2232
2311
  record,
@@ -2248,10 +2327,12 @@ export class ServiceStatefulRuntime {
2248
2327
  const lifecycle = this.instanceApplicationLifecycle;
2249
2328
  if (lifecycle === undefined) return false;
2250
2329
  const { intent } = this.requireReadyInstanceApplicationRoute(ingress, record);
2251
- if (this.instanceApplicationLifecycle?.isIdleEvicting?.({
2252
- targetSpotId: record.route.targetSpotId,
2253
- stableType: intent.instanceType
2254
- }) === true) {
2330
+ if (
2331
+ this.instanceApplicationLifecycle?.isIdleEvicting?.({
2332
+ targetSpotId: record.route.targetSpotId,
2333
+ stableType: intent.instanceType
2334
+ }) === true
2335
+ ) {
2255
2336
  throw createInternalFrameworkException(
2256
2337
  ZLinkFrameworkInternalErrorKind.SpotMoving,
2257
2338
  `Instance Spot '${record.route.targetSpotId}' is entering idle eviction.`
@@ -2289,15 +2370,13 @@ export class ServiceStatefulRuntime {
2289
2370
  operationKey = instanceOperationKey(record);
2290
2371
  if (this.admittedInstanceOperations.has(operationKey)) return 'application';
2291
2372
  }
2292
- const directReply = record.operationKind === 'request'
2293
- ? localReply ?? this.replyPort(
2294
- ingress,
2295
- record.replyRouteId,
2296
- 'instanceSpotRequest'
2297
- )
2298
- : undefined;
2299
- const applicationTarget = applicationTargetOverride
2300
- ?? (record.activation === 'missing'
2373
+ const directReply =
2374
+ record.operationKind === 'request'
2375
+ ? (localReply ?? this.replyPort(ingress, record.replyRouteId, 'instanceSpotRequest'))
2376
+ : undefined;
2377
+ const applicationTarget =
2378
+ applicationTargetOverride ??
2379
+ (record.activation === 'missing'
2301
2380
  ? {
2302
2381
  targetSpotId: record.target.targetSpotId,
2303
2382
  stableType: record.target.stableType,
@@ -2305,45 +2384,42 @@ export class ServiceStatefulRuntime {
2305
2384
  }
2306
2385
  : this.instanceApplicationTarget(record));
2307
2386
  let deferredReply: Parameters<NonNullable<ServiceStatefulMailboxData['reply']>> | undefined;
2308
- const terminalCompletion = onTerminalCompletion === undefined
2309
- ? undefined
2310
- : async () => {
2311
- // The application turn has returned before authority cleanup starts.
2312
- // Mark it quiescent first so a close requested by that turn can finish
2313
- // its local cleanup and release the exact authority fence below.
2314
- this.completeInstanceApplicationOperation(applicationTarget.targetSpotId);
2315
- try {
2316
- await onTerminalCompletion();
2317
- } finally {
2318
- if (deferredReply !== undefined && directReply !== undefined) {
2319
- directReply(...deferredReply);
2387
+ const terminalCompletion =
2388
+ onTerminalCompletion === undefined
2389
+ ? undefined
2390
+ : async () => {
2391
+ // The application turn has returned before authority cleanup starts.
2392
+ // Mark it quiescent first so a close requested by that turn can finish
2393
+ // its local cleanup and release the exact authority fence below.
2394
+ this.completeInstanceApplicationOperation(applicationTarget.targetSpotId);
2395
+ try {
2396
+ await onTerminalCompletion();
2397
+ } finally {
2398
+ if (deferredReply !== undefined && directReply !== undefined) {
2399
+ directReply(...deferredReply);
2400
+ }
2320
2401
  }
2321
- }
2322
- };
2323
- const result = this.enqueueApplicationFrame(
2324
- ingress,
2325
- `spot:${spot.ref.spotId}`,
2326
- payloadFrame,
2327
- {
2328
- receiveKind: ReceiveKind.InstanceSpotActivation,
2329
- operationKind: record.operationKind === 'request' ? OperationKind.InstanceSpotRequest : 0,
2330
- ...(record.operationKind === 'request' ? { correlation: record.replyRouteId } : {}),
2331
- ...(record.sourceSpotId === undefined ? {} : { sourceSpotId: record.sourceSpotId }),
2332
- targetSpot: spot.ref,
2333
- ...(metadataFrame === undefined ? {} : { applicationMetadata: metadataFrame }),
2334
- ...(terminalCompletion === undefined ? {} : { onTerminalCompletion: terminalCompletion }),
2335
- ...(record.operationKind === 'request'
2336
- ? {
2337
- reply: onTerminalCompletion === undefined
2402
+ };
2403
+ const result = this.enqueueApplicationFrame(ingress, `spot:${spot.ref.spotId}`, payloadFrame, {
2404
+ receiveKind: ReceiveKind.InstanceSpotActivation,
2405
+ operationKind: record.operationKind === 'request' ? OperationKind.InstanceSpotRequest : 0,
2406
+ ...(record.operationKind === 'request' ? { correlation: record.replyRouteId } : {}),
2407
+ ...(record.sourceSpotId === undefined ? {} : { sourceSpotId: record.sourceSpotId }),
2408
+ targetSpot: spot.ref,
2409
+ ...(metadataFrame === undefined ? {} : { applicationMetadata: metadataFrame }),
2410
+ ...(terminalCompletion === undefined ? {} : { onTerminalCompletion: terminalCompletion }),
2411
+ ...(record.operationKind === 'request'
2412
+ ? {
2413
+ reply:
2414
+ onTerminalCompletion === undefined
2338
2415
  ? directReply
2339
- : ((...reply: Parameters<NonNullable<ServiceStatefulMailboxData['reply']>>) => {
2416
+ : (...reply: Parameters<NonNullable<ServiceStatefulMailboxData['reply']>>) => {
2340
2417
  deferredReply = reply;
2341
2418
  return true;
2342
- })
2343
- }
2344
- : {})
2345
- }
2346
- );
2419
+ }
2420
+ }
2421
+ : {})
2422
+ });
2347
2423
  if (operationKey !== undefined && result === 'application' && record.activation === 'missing') {
2348
2424
  this.admittedInstanceOperations.set(operationKey, record.deadlineUnixMs);
2349
2425
  }
@@ -2369,7 +2445,11 @@ export class ServiceStatefulRuntime {
2369
2445
  ): Promise<void> {
2370
2446
  try {
2371
2447
  this.validateInstanceIngress(ingress, record);
2372
- const activation = await this.activateMissingInstanceAsync(record, payloadFrame, metadataFrame);
2448
+ const activation = await this.activateMissingInstanceAsync(
2449
+ record,
2450
+ payloadFrame,
2451
+ metadataFrame
2452
+ );
2373
2453
  if (this.closed) return;
2374
2454
  const admitted = this.enqueueActivatedInstanceSpot(
2375
2455
  ingress,
@@ -2408,12 +2488,7 @@ export class ServiceStatefulRuntime {
2408
2488
  localReply(result.terminalResult, result.failureCode);
2409
2489
  } else {
2410
2490
  if (record.replyRouteId === undefined) return;
2411
- this.replyWire(
2412
- ingress,
2413
- record.replyRouteId,
2414
- result.terminalResult,
2415
- result.failureCode
2416
- );
2491
+ this.replyWire(ingress, record.replyRouteId, result.terminalResult, result.failureCode);
2417
2492
  }
2418
2493
  }
2419
2494
  }
@@ -2445,10 +2520,10 @@ export class ServiceStatefulRuntime {
2445
2520
  );
2446
2521
  if (this.closed) return;
2447
2522
  const latestRoute = this.instanceIntents.get(record.route.targetSpotId)?.route;
2448
- const refreshedRecord = latestRoute !== undefined
2449
- && sameInstanceApplicationOwner(latestRoute, record.route)
2450
- ? { ...record, route: latestRoute }
2451
- : record;
2523
+ const refreshedRecord =
2524
+ latestRoute !== undefined && sameInstanceApplicationOwner(latestRoute, record.route)
2525
+ ? { ...record, route: latestRoute }
2526
+ : record;
2452
2527
  const spot = this.requireInstanceActivation(ingress, refreshedRecord);
2453
2528
  const admitted = this.enqueueActivatedInstanceSpot(
2454
2529
  ingress,
@@ -2465,12 +2540,7 @@ export class ServiceStatefulRuntime {
2465
2540
  } catch (error) {
2466
2541
  if (record.operationKind !== 'request' || record.replyRouteId === undefined) return;
2467
2542
  const result = failure(error);
2468
- this.replyWire(
2469
- ingress,
2470
- record.replyRouteId,
2471
- result.terminalResult,
2472
- result.failureCode
2473
- );
2543
+ this.replyWire(ingress, record.replyRouteId, result.terminalResult, result.failureCode);
2474
2544
  }
2475
2545
  }
2476
2546
 
@@ -2484,40 +2554,42 @@ export class ServiceStatefulRuntime {
2484
2554
  stableType: target.stableType,
2485
2555
  objectGeneration: route.objectGeneration
2486
2556
  };
2487
- return () => completion ??= (async () => {
2488
- let authorityCompletionSignaled = false;
2489
- try {
2490
- const released = await this.asyncInstanceAuthority?.complete(target, route);
2491
- this.completeInstanceAuthorityOperation(target.targetSpotId);
2492
- authorityCompletionSignaled = true;
2493
- if (released !== undefined) {
2494
- const authorityReleased = await this.instanceApplicationLifecycle?.completeTerminal(applicationTarget)
2495
- ?? false;
2496
- if (!authorityReleased) {
2497
- this.replaceCommittedInstanceRoute(target.stableType, route, released);
2498
- } else {
2499
- this.forgetClosedInstanceRoute(released);
2500
- }
2501
- }
2502
- } finally {
2503
- if (!authorityCompletionSignaled) {
2557
+ return () =>
2558
+ (completion ??= (async () => {
2559
+ let authorityCompletionSignaled = false;
2560
+ try {
2561
+ const released = await this.asyncInstanceAuthority?.complete(target, route);
2504
2562
  this.completeInstanceAuthorityOperation(target.targetSpotId);
2563
+ authorityCompletionSignaled = true;
2564
+ if (released !== undefined) {
2565
+ const authorityReleased =
2566
+ (await this.instanceApplicationLifecycle?.completeTerminal(applicationTarget)) ??
2567
+ false;
2568
+ if (!authorityReleased) {
2569
+ this.replaceCommittedInstanceRoute(target.stableType, route, released);
2570
+ } else {
2571
+ this.forgetClosedInstanceRoute(released);
2572
+ }
2573
+ }
2574
+ } finally {
2575
+ if (!authorityCompletionSignaled) {
2576
+ this.completeInstanceAuthorityOperation(target.targetSpotId);
2577
+ }
2505
2578
  }
2506
- }
2507
- })();
2579
+ })());
2508
2580
  }
2509
2581
 
2510
2582
  private instanceApplicationTerminalCompletion(
2511
2583
  target: ServiceInstanceApplicationTarget
2512
2584
  ): () => Promise<void> {
2513
2585
  return async () => {
2514
- const authorityReleased = await this.instanceApplicationLifecycle?.completeTerminal(target)
2515
- ?? false;
2586
+ const authorityReleased =
2587
+ (await this.instanceApplicationLifecycle?.completeTerminal(target)) ?? false;
2516
2588
  if (!authorityReleased) return;
2517
2589
  const current = this.instanceIntents.get(target.targetSpotId);
2518
2590
  if (
2519
- current?.instanceType === target.stableType
2520
- && current.route.objectGeneration === target.objectGeneration
2591
+ current?.instanceType === target.stableType &&
2592
+ current.route.objectGeneration === target.objectGeneration
2521
2593
  ) {
2522
2594
  this.forgetClosedInstanceRoute(current.route);
2523
2595
  }
@@ -2551,10 +2623,7 @@ export class ServiceStatefulRuntime {
2551
2623
 
2552
2624
  private beginInstanceApplicationOperation(spotId: string): void {
2553
2625
  const key = String(spotId);
2554
- this.pendingInstanceTerminals.set(
2555
- key,
2556
- (this.pendingInstanceTerminals.get(key) ?? 0) + 1
2557
- );
2626
+ this.pendingInstanceTerminals.set(key, (this.pendingInstanceTerminals.get(key) ?? 0) + 1);
2558
2627
  }
2559
2628
 
2560
2629
  private beginInstanceAuthorityOperation(spotId: string): void {
@@ -2589,9 +2658,10 @@ export class ServiceStatefulRuntime {
2589
2658
 
2590
2659
  private completeInstanceApplicationWaitersIfQuiescent(key: string): void {
2591
2660
  if (
2592
- (this.pendingInstanceTerminals.get(key) ?? 0) !== 0
2593
- || (this.pendingInstanceAuthorityTerminals.get(key) ?? 0) !== 0
2594
- ) return;
2661
+ (this.pendingInstanceTerminals.get(key) ?? 0) !== 0 ||
2662
+ (this.pendingInstanceAuthorityTerminals.get(key) ?? 0) !== 0
2663
+ )
2664
+ return;
2595
2665
  const waiters = this.instanceApplicationWaiters.get(key);
2596
2666
  if (waiters === undefined) return;
2597
2667
  this.instanceApplicationWaiters.delete(key);
@@ -2620,20 +2690,26 @@ export class ServiceStatefulRuntime {
2620
2690
  targetSpotId: route.targetSpotId
2621
2691
  };
2622
2692
  if (record.operationKind === 'send') {
2623
- const submitted = await this.submitOneWay(route.targetNodeRid, instanceOperationParts([
2624
- encodeInstanceSpotActivationHeader(
2625
- redirectedTarget,
2626
- this.nodeGeneration,
2627
- this.nodeRid,
2628
- record.sourceSpotId,
2629
- 'send',
2630
- record.operation,
2631
- record.deadlineUnixMs,
2632
- undefined,
2633
- metadataFrame !== undefined
2634
- ),
2635
- payloadFrame
2636
- ], metadataFrame));
2693
+ const submitted = await this.submitOneWay(
2694
+ route.targetNodeRid,
2695
+ instanceOperationParts(
2696
+ [
2697
+ encodeInstanceSpotActivationHeader(
2698
+ redirectedTarget,
2699
+ this.nodeGeneration,
2700
+ this.nodeRid,
2701
+ record.sourceSpotId,
2702
+ 'send',
2703
+ record.operation,
2704
+ record.deadlineUnixMs,
2705
+ undefined,
2706
+ metadataFrame !== undefined
2707
+ ),
2708
+ payloadFrame
2709
+ ],
2710
+ metadataFrame
2711
+ )
2712
+ );
2637
2713
  if (submitted !== SubmitResult.Ok) {
2638
2714
  throw new Error(`Instance activation redirect was not admitted: ${submitted}.`);
2639
2715
  }
@@ -2644,20 +2720,23 @@ export class ServiceStatefulRuntime {
2644
2720
  this.submitRequest(
2645
2721
  pending,
2646
2722
  route.targetNodeRid,
2647
- instanceOperationParts([
2648
- encodeInstanceSpotActivationHeader(
2649
- redirectedTarget,
2650
- this.nodeGeneration,
2651
- this.nodeRid,
2652
- record.sourceSpotId,
2653
- 'request',
2654
- record.operation,
2655
- record.deadlineUnixMs,
2656
- pending.id,
2657
- metadataFrame !== undefined
2658
- ),
2659
- payloadFrame
2660
- ], metadataFrame),
2723
+ instanceOperationParts(
2724
+ [
2725
+ encodeInstanceSpotActivationHeader(
2726
+ redirectedTarget,
2727
+ this.nodeGeneration,
2728
+ this.nodeRid,
2729
+ record.sourceSpotId,
2730
+ 'request',
2731
+ record.operation,
2732
+ record.deadlineUnixMs,
2733
+ pending.id,
2734
+ metadataFrame !== undefined
2735
+ ),
2736
+ payloadFrame
2737
+ ],
2738
+ metadataFrame
2739
+ ),
2661
2740
  remainingMs,
2662
2741
  'instanceSpotRequest'
2663
2742
  );
@@ -2682,16 +2761,18 @@ export class ServiceStatefulRuntime {
2682
2761
  record: Extract<ServiceStatefulWireRecord, { readonly kind: 'instanceSpot' }>
2683
2762
  ): ServiceSpotState {
2684
2763
  const readyRoute = record.activation === 'ready' ? record.route : undefined;
2685
- const spotId = readyRoute?.targetSpotId
2686
- ?? (record.activation === 'missing' ? record.target.targetSpotId : undefined);
2764
+ const spotId =
2765
+ readyRoute?.targetSpotId ??
2766
+ (record.activation === 'missing' ? record.target.targetSpotId : undefined);
2687
2767
  if (spotId === undefined) throw new ServiceStaleGenerationError('spot', 'unknown');
2688
2768
  this.validateInstanceIngress(ingress, record);
2689
2769
  if (record.activation === 'missing') {
2690
2770
  return this.activateMissingInstance(record);
2691
2771
  }
2692
2772
  const { intent, route } = this.requireReadyInstanceApplicationRoute(ingress, record);
2693
- const spot = this.registry.spot(route.targetSpotId)
2694
- ?? this.registry.restoreSpot(
2773
+ const spot =
2774
+ this.registry.spot(route.targetSpotId) ??
2775
+ this.registry.restoreSpot(
2695
2776
  {
2696
2777
  spotId: route.targetSpotId,
2697
2778
  generation: route.objectGeneration
@@ -2701,11 +2782,11 @@ export class ServiceStatefulRuntime {
2701
2782
  route.authorityOwnerGeneration
2702
2783
  );
2703
2784
  if (
2704
- spot.state !== 'ready'
2705
- || spot.kind !== 'instance'
2706
- || spot.stableType !== intent.instanceType
2707
- || spot.ref.generation !== route.objectGeneration
2708
- || spot.authorityOwnerGeneration !== route.authorityOwnerGeneration
2785
+ spot.state !== 'ready' ||
2786
+ spot.kind !== 'instance' ||
2787
+ spot.stableType !== intent.instanceType ||
2788
+ spot.ref.generation !== route.objectGeneration ||
2789
+ spot.authorityOwnerGeneration !== route.authorityOwnerGeneration
2709
2790
  ) {
2710
2791
  throw createInternalFrameworkException(
2711
2792
  ZLinkFrameworkInternalErrorKind.SpotMoving,
@@ -2733,9 +2814,9 @@ export class ServiceStatefulRuntime {
2733
2814
  // request. A mismatched or absent local projection remains NotFound.
2734
2815
  const local = this.registry.spot(record.route.targetSpotId);
2735
2816
  if (
2736
- local?.kind === 'instance'
2737
- && local.state === 'ready'
2738
- && routeMatchesLocal(record.route, local, this.nodeRid, this.nodeGeneration)
2817
+ local?.kind === 'instance' &&
2818
+ local.state === 'ready' &&
2819
+ routeMatchesLocal(record.route, local, this.nodeRid, this.nodeGeneration)
2739
2820
  ) {
2740
2821
  this.publishCommittedInstanceRoute(local.stableType, record.route);
2741
2822
  intent = this.instanceIntents.get(record.route.targetSpotId);
@@ -2761,8 +2842,8 @@ export class ServiceStatefulRuntime {
2761
2842
  );
2762
2843
  }
2763
2844
  if (
2764
- current.objectGeneration === record.route.objectGeneration
2765
- && current.authorityOwnerGeneration !== record.route.authorityOwnerGeneration
2845
+ current.objectGeneration === record.route.objectGeneration &&
2846
+ current.authorityOwnerGeneration !== record.route.authorityOwnerGeneration
2766
2847
  ) {
2767
2848
  throw createInternalFrameworkException(
2768
2849
  ZLinkFrameworkInternalErrorKind.SpotMoving,
@@ -2778,8 +2859,8 @@ export class ServiceStatefulRuntime {
2778
2859
  ): void {
2779
2860
  const expectedSourceGeneration = this.peerGeneration(record.sourceNodeRid);
2780
2861
  if (
2781
- record.sourceNodeRid !== ingress.sourceRoutingId
2782
- || record.sourceNodeGeneration !== expectedSourceGeneration
2862
+ record.sourceNodeRid !== ingress.sourceRoutingId ||
2863
+ record.sourceNodeGeneration !== expectedSourceGeneration
2783
2864
  ) {
2784
2865
  if (record.activation === 'ready') {
2785
2866
  throw createInternalFrameworkException(
@@ -2799,9 +2880,9 @@ export class ServiceStatefulRuntime {
2799
2880
  ): ServiceSpotState {
2800
2881
  const target = record.target;
2801
2882
  if (
2802
- target.targetNodeRid !== this.nodeRid
2803
- || target.targetNodeGeneration !== this.nodeGeneration
2804
- || record.deadlineUnixMs < BigInt(Date.now())
2883
+ target.targetNodeRid !== this.nodeRid ||
2884
+ target.targetNodeGeneration !== this.nodeGeneration ||
2885
+ record.deadlineUnixMs < BigInt(Date.now())
2805
2886
  ) {
2806
2887
  throw new ServiceStaleGenerationError('spot', target.targetSpotId);
2807
2888
  }
@@ -2817,10 +2898,10 @@ export class ServiceStatefulRuntime {
2817
2898
  const current = authority.read(target);
2818
2899
  if (local !== undefined) {
2819
2900
  if (
2820
- local.kind !== 'instance'
2821
- || local.stableType !== target.stableType
2822
- || current.kind !== 'ready'
2823
- || !routeMatchesLocal(current.route, local, this.nodeRid, this.nodeGeneration)
2901
+ local.kind !== 'instance' ||
2902
+ local.stableType !== target.stableType ||
2903
+ current.kind !== 'ready' ||
2904
+ !routeMatchesLocal(current.route, local, this.nodeRid, this.nodeGeneration)
2824
2905
  ) {
2825
2906
  throw new ServiceStaleGenerationError('spot', target.targetSpotId);
2826
2907
  }
@@ -2852,12 +2933,7 @@ export class ServiceStatefulRuntime {
2852
2933
  if (activation.created) this.registry.closeSpot(activation.spot.ref);
2853
2934
  throw new ServiceInstanceActivationRedirectError(committed.route);
2854
2935
  }
2855
- if (!routeMatchesLocal(
2856
- committed.route,
2857
- activation.spot,
2858
- this.nodeRid,
2859
- this.nodeGeneration
2860
- )) {
2936
+ if (!routeMatchesLocal(committed.route, activation.spot, this.nodeRid, this.nodeGeneration)) {
2861
2937
  if (activation.created) this.registry.closeSpot(activation.spot.ref);
2862
2938
  throw new ServiceStaleGenerationError('spot', target.targetSpotId);
2863
2939
  }
@@ -2896,9 +2972,9 @@ export class ServiceStatefulRuntime {
2896
2972
  ): Promise<{ readonly spot: ServiceSpotState; readonly route: ServiceInstanceRouteFence }> {
2897
2973
  const target = record.target;
2898
2974
  if (
2899
- target.targetNodeRid !== this.nodeRid
2900
- || target.targetNodeGeneration !== this.nodeGeneration
2901
- || record.deadlineUnixMs < BigInt(Date.now())
2975
+ target.targetNodeRid !== this.nodeRid ||
2976
+ target.targetNodeGeneration !== this.nodeGeneration ||
2977
+ record.deadlineUnixMs < BigInt(Date.now())
2902
2978
  ) {
2903
2979
  throw new ServiceStaleGenerationError('spot', target.targetSpotId);
2904
2980
  }
@@ -2925,17 +3001,14 @@ export class ServiceStatefulRuntime {
2925
3001
  throw new ServiceStaleGenerationError('spot', target.targetSpotId);
2926
3002
  }
2927
3003
  if (
2928
- local !== undefined
2929
- && (
2930
- local.kind !== 'instance'
2931
- || local.stableType !== target.stableType
2932
- )
3004
+ local !== undefined &&
3005
+ (local.kind !== 'instance' || local.stableType !== target.stableType)
2933
3006
  ) {
2934
3007
  throw new ServiceStaleGenerationError('spot', target.targetSpotId);
2935
3008
  }
2936
3009
  if (
2937
- local !== undefined
2938
- && routeMatchesLocal(current.route, local, this.nodeRid, this.nodeGeneration)
3010
+ local !== undefined &&
3011
+ routeMatchesLocal(current.route, local, this.nodeRid, this.nodeGeneration)
2939
3012
  ) {
2940
3013
  return { spot: local, route: current.route };
2941
3014
  }
@@ -2944,26 +3017,22 @@ export class ServiceStatefulRuntime {
2944
3017
  if (local !== undefined) {
2945
3018
  const lifecycle = this.instanceApplicationLifecycle;
2946
3019
  const closing = lifecycle?.isClosing?.(target) === true;
2947
- let materialized = lifecycle === undefined
2948
- ? undefined
2949
- : lifecycle.isMaterialized(target);
3020
+ let materialized = lifecycle === undefined ? undefined : lifecycle.isMaterialized(target);
2950
3021
  const materializing = lifecycle?.isMaterializing?.(target) === true;
2951
- if (
2952
- local.kind !== 'instance'
2953
- || local.stableType !== target.stableType
2954
- ) {
3022
+ if (local.kind !== 'instance' || local.stableType !== target.stableType) {
2955
3023
  throw new ServiceStaleGenerationError('spot', target.targetSpotId);
2956
3024
  }
2957
- const joinsCreating = current.kind === 'creating'
2958
- && local.ref.generation === current.objectGeneration
2959
- && local.authorityOwnerGeneration === current.authorityOwnerGeneration;
3025
+ const joinsCreating =
3026
+ current.kind === 'creating' &&
3027
+ local.ref.generation === current.objectGeneration &&
3028
+ local.authorityOwnerGeneration === current.authorityOwnerGeneration;
2960
3029
  const replacesClosingProjection = current.kind === 'creating' && closing;
2961
3030
  if (
2962
- current.kind === 'missing'
2963
- && !closing
2964
- && !materializing
2965
- && materialized === true
2966
- && lifecycle !== undefined
3031
+ current.kind === 'missing' &&
3032
+ !closing &&
3033
+ !materializing &&
3034
+ materialized === true &&
3035
+ lifecycle !== undefined
2967
3036
  ) {
2968
3037
  // The durable authority is the ownership source of truth. Its removal
2969
3038
  // can become visible before the route reconciler has discarded the
@@ -2984,8 +3053,8 @@ export class ServiceStatefulRuntime {
2984
3053
  // If disposal did not remove an orphaned materialization, keep fencing
2985
3054
  // it instead of admitting work into two application generations.
2986
3055
  if (
2987
- (!joinsCreating && !replacesClosingProjection && current.kind !== 'missing')
2988
- || (!joinsCreating && !closing && materialized !== false && !materializing)
3056
+ (!joinsCreating && !replacesClosingProjection && current.kind !== 'missing') ||
3057
+ (!joinsCreating && !closing && materialized !== false && !materializing)
2989
3058
  ) {
2990
3059
  throw new ServiceStaleGenerationError('spot', target.targetSpotId);
2991
3060
  }
@@ -3037,12 +3106,7 @@ export class ServiceStatefulRuntime {
3037
3106
  await this.instanceApplicationLifecycle?.discard(target);
3038
3107
  throw new ServiceInstanceActivationRedirectError(committed.route);
3039
3108
  }
3040
- if (!routeMatchesLocal(
3041
- committed.route,
3042
- activation.spot,
3043
- this.nodeRid,
3044
- this.nodeGeneration
3045
- )) {
3109
+ if (!routeMatchesLocal(committed.route, activation.spot, this.nodeRid, this.nodeGeneration)) {
3046
3110
  if (activation.created) this.registry.closeSpot(activation.spot.ref);
3047
3111
  await this.instanceApplicationLifecycle?.discard(target);
3048
3112
  throw new ServiceStaleGenerationError('spot', target.targetSpotId);
@@ -3059,8 +3123,9 @@ export class ServiceStatefulRuntime {
3059
3123
  };
3060
3124
  };
3061
3125
  const descriptor = topology.localDescriptor?.();
3062
- return descriptor === undefined
3063
- || (descriptor.state === 'serving' && descriptor.placementWeight > 0);
3126
+ return (
3127
+ descriptor === undefined || (descriptor.state === 'serving' && descriptor.placementWeight > 0)
3128
+ );
3064
3129
  }
3065
3130
 
3066
3131
  private async reconcileReadyInstanceProjection(
@@ -3075,12 +3140,7 @@ export class ServiceStatefulRuntime {
3075
3140
  route.objectGeneration,
3076
3141
  route.authorityOwnerGeneration
3077
3142
  );
3078
- if (!routeMatchesLocal(
3079
- route,
3080
- activation.spot,
3081
- this.nodeRid,
3082
- this.nodeGeneration
3083
- )) {
3143
+ if (!routeMatchesLocal(route, activation.spot, this.nodeRid, this.nodeGeneration)) {
3084
3144
  if (activation.created) this.registry.closeSpot(activation.spot.ref);
3085
3145
  throw new ServiceStaleGenerationError('spot', target.targetSpotId);
3086
3146
  }
@@ -3088,18 +3148,15 @@ export class ServiceStatefulRuntime {
3088
3148
 
3089
3149
  const confirmed = await authority.read(target);
3090
3150
  if (confirmed.kind !== 'ready' || !sameInstanceRoute(confirmed.route, route)) {
3091
- if (
3092
- confirmed.kind === 'ready'
3093
- && confirmed.route.targetNodeRid !== this.nodeRid
3094
- ) {
3151
+ if (confirmed.kind === 'ready' && confirmed.route.targetNodeRid !== this.nodeRid) {
3095
3152
  throw new ServiceInstanceActivationRedirectError(confirmed.route);
3096
3153
  }
3097
3154
  throw new ServiceStaleGenerationError('spot', target.targetSpotId);
3098
3155
  }
3099
3156
  const current = this.registry.spot(target.targetSpotId);
3100
3157
  if (
3101
- current === undefined
3102
- || !routeMatchesLocal(confirmed.route, current, this.nodeRid, this.nodeGeneration)
3158
+ current === undefined ||
3159
+ !routeMatchesLocal(confirmed.route, current, this.nodeRid, this.nodeGeneration)
3103
3160
  ) {
3104
3161
  throw new ServiceStaleGenerationError('spot', target.targetSpotId);
3105
3162
  }
@@ -3112,11 +3169,12 @@ export class ServiceStatefulRuntime {
3112
3169
  expectedCurrentRoute?: ServiceInstanceRouteFence | null
3113
3170
  ): void {
3114
3171
  const directRoute = instanceRouteAsDirectRoute(route);
3115
- const expectedDirectRoute = expectedCurrentRoute === undefined
3116
- ? undefined
3117
- : expectedCurrentRoute === null
3118
- ? null
3119
- : instanceRouteAsDirectRoute(expectedCurrentRoute);
3172
+ const expectedDirectRoute =
3173
+ expectedCurrentRoute === undefined
3174
+ ? undefined
3175
+ : expectedCurrentRoute === null
3176
+ ? null
3177
+ : instanceRouteAsDirectRoute(expectedCurrentRoute);
3120
3178
  this.rememberSpotRoute(directRoute, expectedDirectRoute);
3121
3179
  this.registerInstanceIntent(stableType, route, expectedCurrentRoute);
3122
3180
  }
@@ -3150,9 +3208,9 @@ export class ServiceStatefulRuntime {
3150
3208
  private forgetClosedInstanceRoute(route: ServiceInstanceRouteFence): void {
3151
3209
  const local = this.registry.spot(route.targetSpotId);
3152
3210
  if (
3153
- local?.kind === 'instance'
3154
- && local.ref.generation === route.objectGeneration
3155
- && local.authorityOwnerGeneration === route.authorityOwnerGeneration
3211
+ local?.kind === 'instance' &&
3212
+ local.ref.generation === route.objectGeneration &&
3213
+ local.authorityOwnerGeneration === route.authorityOwnerGeneration
3156
3214
  ) {
3157
3215
  this.registry.closeSpot(local.ref);
3158
3216
  }
@@ -3279,8 +3337,8 @@ export class ServiceStatefulRuntime {
3279
3337
  if (record.binding.state === 'active') {
3280
3338
  const actor = this.validateActorFence(record.actor);
3281
3339
  const previous = this.registry.binding(actor.ref);
3282
- const sourceGeneration = ingress.sourceNodeGeneration
3283
- ?? this.peerGeneration(ingress.sourceRoutingId);
3340
+ const sourceGeneration =
3341
+ ingress.sourceNodeGeneration ?? this.peerGeneration(ingress.sourceRoutingId);
3284
3342
  const binding = sessionBindingFromWire(
3285
3343
  actor.ref,
3286
3344
  record.sessionRid,
@@ -3337,9 +3395,9 @@ export class ServiceStatefulRuntime {
3337
3395
  : undefined
3338
3396
  );
3339
3397
  if (
3340
- terminalResult === RequestResult.Ok
3341
- && replacedBinding !== undefined
3342
- && !sameSessionBinding(replacedBinding, completedBinding)
3398
+ terminalResult === RequestResult.Ok &&
3399
+ replacedBinding !== undefined &&
3400
+ !sameSessionBinding(replacedBinding, completedBinding)
3343
3401
  ) {
3344
3402
  this.sendBoundSessionReplacement(
3345
3403
  replacedBinding,
@@ -3353,16 +3411,13 @@ export class ServiceStatefulRuntime {
3353
3411
  }
3354
3412
  );
3355
3413
  if (!accepted) {
3356
- const result = failure(createInternalFrameworkException(
3357
- ZLinkFrameworkInternalErrorKind.SpotMoving,
3358
- `Actor '${actor.ref.actorId}' no longer accepts session bindings.`
3359
- ));
3360
- this.replyWire(
3361
- ingress,
3362
- record.correlation,
3363
- result.terminalResult,
3364
- result.failureCode
3414
+ const result = failure(
3415
+ createInternalFrameworkException(
3416
+ ZLinkFrameworkInternalErrorKind.SpotMoving,
3417
+ `Actor '${actor.ref.actorId}' no longer accepts session bindings.`
3418
+ )
3365
3419
  );
3420
+ this.replyWire(ingress, record.correlation, result.terminalResult, result.failureCode);
3366
3421
  }
3367
3422
  } else {
3368
3423
  this.enqueueSessionBindingTombstone(ingress, record);
@@ -3388,8 +3443,8 @@ export class ServiceStatefulRuntime {
3388
3443
  if (authority.actor.nodeRid !== ingress.sourceRoutingId) {
3389
3444
  return 'protocolError';
3390
3445
  }
3391
- const sourceGeneration = ingress.sourceNodeGeneration
3392
- ?? this.tryPeerGeneration(ingress.sourceRoutingId);
3446
+ const sourceGeneration =
3447
+ ingress.sourceNodeGeneration ?? this.tryPeerGeneration(ingress.sourceRoutingId);
3393
3448
  if (sourceGeneration === undefined) return 'infrastructure';
3394
3449
  if (sourceGeneration !== authority.targetNodeGeneration) {
3395
3450
  // A notice from a restarted authority is stale. It must not tear down a
@@ -3397,10 +3452,10 @@ export class ServiceStatefulRuntime {
3397
3452
  return 'infrastructure';
3398
3453
  }
3399
3454
  if (
3400
- record.retiredSession.sessionOwnerNodeRid !== this.nodeRid
3401
- || record.retiredSession.sessionOwnerNodeGeneration !== this.nodeGeneration
3402
- || record.retiredSession.sessionOwnerId !== this.nodeRid
3403
- || record.retiredSession.sessionOwnerLeaseGeneration !== this.nodeGeneration
3455
+ record.retiredSession.sessionOwnerNodeRid !== this.nodeRid ||
3456
+ record.retiredSession.sessionOwnerNodeGeneration !== this.nodeGeneration ||
3457
+ record.retiredSession.sessionOwnerId !== this.nodeRid ||
3458
+ record.retiredSession.sessionOwnerLeaseGeneration !== this.nodeGeneration
3404
3459
  ) {
3405
3460
  return 'infrastructure';
3406
3461
  }
@@ -3417,16 +3472,15 @@ export class ServiceStatefulRuntime {
3417
3472
  sessionOwnerNodeGeneration: record.retiredSession.sessionOwnerNodeGeneration,
3418
3473
  sessionOwnerId: record.retiredSession.sessionOwnerId,
3419
3474
  sessionOwnerLeaseGeneration: record.retiredSession.sessionOwnerLeaseGeneration,
3420
- bindingGeneration: record.retiredSession.retiredBindingGeneration,
3475
+ bindingGeneration: record.retiredSession.retiredBindingGeneration
3421
3476
  })
3422
3477
  );
3423
- const delivery = current !== undefined
3424
- && exactRetiredDelivery(current.binding, record.retiredSession)
3425
- ? current
3426
- : retired !== undefined
3427
- && exactRetiredDelivery(retired.binding, record.retiredSession)
3428
- ? retired
3429
- : undefined;
3478
+ const delivery =
3479
+ current !== undefined && exactRetiredDelivery(current.binding, record.retiredSession)
3480
+ ? current
3481
+ : retired !== undefined && exactRetiredDelivery(retired.binding, record.retiredSession)
3482
+ ? retired
3483
+ : undefined;
3430
3484
  if (delivery === undefined) return 'infrastructure';
3431
3485
  this.appliedReplacementNotices.add(key);
3432
3486
  delivery.onBindingReplaced?.(actor.actorId, record.retiredSession, actor);
@@ -3440,20 +3494,17 @@ export class ServiceStatefulRuntime {
3440
3494
  previous: ServiceSessionBinding,
3441
3495
  actorAuthority: ServiceBoundSessionActorAuthority
3442
3496
  ): void {
3443
- const ownerGeneration = previous.sessionOwnerNodeGeneration
3444
- ?? this.tryPeerGeneration(previous.sessionOwnerNodeRid);
3497
+ const ownerGeneration =
3498
+ previous.sessionOwnerNodeGeneration ?? this.tryPeerGeneration(previous.sessionOwnerNodeRid);
3445
3499
  if (ownerGeneration === undefined) return;
3446
- const header = encodeBoundSessionReplacedHeader(
3447
- actorAuthority,
3448
- {
3449
- sessionOwnerNodeRid: previous.sessionOwnerNodeRid,
3450
- sessionOwnerNodeGeneration: ownerGeneration,
3451
- sessionOwnerId: previous.sessionOwnerId ?? previous.sessionOwnerNodeRid,
3452
- sessionOwnerLeaseGeneration: previous.sessionOwnerLeaseGeneration ?? ownerGeneration,
3453
- sessionRid: previous.sessionRid,
3454
- retiredBindingGeneration: previous.bindingGeneration
3455
- }
3456
- );
3500
+ const header = encodeBoundSessionReplacedHeader(actorAuthority, {
3501
+ sessionOwnerNodeRid: previous.sessionOwnerNodeRid,
3502
+ sessionOwnerNodeGeneration: ownerGeneration,
3503
+ sessionOwnerId: previous.sessionOwnerId ?? previous.sessionOwnerNodeRid,
3504
+ sessionOwnerLeaseGeneration: previous.sessionOwnerLeaseGeneration ?? ownerGeneration,
3505
+ sessionRid: previous.sessionRid,
3506
+ retiredBindingGeneration: previous.bindingGeneration
3507
+ });
3457
3508
  // submitOneWay owns the normal transport admission timeout. A replacement
3458
3509
  // notice is one-way, so an unsuccessful admission has no caller terminal
3459
3510
  // to complete and must not delay the already-completed bind.
@@ -3467,26 +3518,26 @@ export class ServiceStatefulRuntime {
3467
3518
  if (record.binding.state !== 'tombstone') return;
3468
3519
  const actor = record.actor.actor;
3469
3520
  const current = this.registry.binding(actor);
3470
- const sourceGeneration = ingress.sourceNodeGeneration
3471
- ?? this.tryPeerGeneration(ingress.sourceRoutingId);
3521
+ const sourceGeneration =
3522
+ ingress.sourceNodeGeneration ?? this.tryPeerGeneration(ingress.sourceRoutingId);
3472
3523
  if (
3473
- current === undefined
3474
- || sourceGeneration === undefined
3475
- || current.bindingGeneration !== record.binding.retiredGeneration
3476
- || current.sessionRid !== record.sessionRid
3477
- || current.sessionOwnerNodeRid !== ingress.sourceRoutingId
3478
- || current.sessionOwnerNodeGeneration !== sourceGeneration
3479
- || current.sessionOwnerId !== ingress.sourceRoutingId
3480
- || current.sessionOwnerLeaseGeneration !== sourceGeneration
3524
+ current === undefined ||
3525
+ sourceGeneration === undefined ||
3526
+ current.bindingGeneration !== record.binding.retiredGeneration ||
3527
+ current.sessionRid !== record.sessionRid ||
3528
+ current.sessionOwnerNodeRid !== ingress.sourceRoutingId ||
3529
+ current.sessionOwnerNodeGeneration !== sourceGeneration ||
3530
+ current.sessionOwnerId !== ingress.sourceRoutingId ||
3531
+ current.sessionOwnerLeaseGeneration !== sourceGeneration
3481
3532
  ) {
3482
3533
  this.replyWire(ingress, record.correlation, RequestResult.Ok, 0);
3483
3534
  return;
3484
3535
  }
3485
3536
  const delivery = this.sessionDeliveries.get(actorKey(actor));
3486
- const currentDelivery = delivery !== undefined
3487
- && sameSessionBinding(delivery.binding, current)
3488
- ? delivery
3489
- : undefined;
3537
+ const currentDelivery =
3538
+ delivery !== undefined && sameSessionBinding(delivery.binding, current)
3539
+ ? delivery
3540
+ : undefined;
3490
3541
  const accepted = this.enqueueSessionBindingRetirement(
3491
3542
  ingress,
3492
3543
  current,
@@ -3503,8 +3554,8 @@ export class ServiceStatefulRuntime {
3503
3554
  );
3504
3555
  }
3505
3556
  if (
3506
- currentDelivery !== undefined
3507
- && this.sessionDeliveries.get(actorKey(actor)) === currentDelivery
3557
+ currentDelivery !== undefined &&
3558
+ this.sessionDeliveries.get(actorKey(actor)) === currentDelivery
3508
3559
  ) {
3509
3560
  this.sessionDeliveries.delete(actorKey(actor));
3510
3561
  }
@@ -3514,10 +3565,12 @@ export class ServiceStatefulRuntime {
3514
3565
  }
3515
3566
  );
3516
3567
  if (!accepted) {
3517
- const result = failure(createInternalFrameworkException(
3518
- ZLinkFrameworkInternalErrorKind.SpotMoving,
3519
- `Actor '${actor.actorId}' no longer accepts session binding tombstones.`
3520
- ));
3568
+ const result = failure(
3569
+ createInternalFrameworkException(
3570
+ ZLinkFrameworkInternalErrorKind.SpotMoving,
3571
+ `Actor '${actor.actorId}' no longer accepts session binding tombstones.`
3572
+ )
3573
+ );
3521
3574
  this.replyWire(ingress, record.correlation, result.terminalResult, result.failureCode);
3522
3575
  }
3523
3576
  }
@@ -3569,12 +3622,12 @@ export class ServiceStatefulRuntime {
3569
3622
  ): Promise<RawServicePumpResult> {
3570
3623
  const delivery = this.sessionDeliveries.get(actorKey(record.actor.actor));
3571
3624
  if (
3572
- delivery === undefined
3573
- || delivery.binding.bindingGeneration !== record.expectedBindingGeneration
3574
- || payloadFrame === undefined
3575
- || ingress.sourceNodeGeneration === undefined
3576
- || !routingIdsEqual(ingress.sourceRoutingId, record.actor.actor.nodeRid)
3577
- || ingress.sourceNodeGeneration !== record.actor.targetNodeGeneration
3625
+ delivery === undefined ||
3626
+ delivery.binding.bindingGeneration !== record.expectedBindingGeneration ||
3627
+ payloadFrame === undefined ||
3628
+ ingress.sourceNodeGeneration === undefined ||
3629
+ !routingIdsEqual(ingress.sourceRoutingId, record.actor.actor.nodeRid) ||
3630
+ ingress.sourceNodeGeneration !== record.actor.targetNodeGeneration
3578
3631
  ) {
3579
3632
  return 'protocolError';
3580
3633
  }
@@ -3598,18 +3651,21 @@ export class ServiceStatefulRuntime {
3598
3651
  settle();
3599
3652
  }
3600
3653
  };
3601
- const decision = await delivery.bindingIngress?.retainOutbound({
3602
- actorId: record.actor.actor.actorId,
3603
- objectGeneration: record.actor.actor.generation,
3604
- actorNodeRid: record.actor.actor.nodeRid,
3605
- actorNodeGeneration: record.actor.targetNodeGeneration,
3606
- authorityOwnerGeneration: record.actor.authorityOwnerGeneration,
3607
- ownerLeaseGeneration: record.actor.ownerLeaseGeneration,
3608
- producerNodeRid: ingress.sourceRoutingId,
3609
- producerNodeGeneration: ingress.sourceNodeGeneration,
3610
- sessionIdentity: sessionRid,
3611
- bindingGeneration: record.expectedBindingGeneration
3612
- }, operation);
3654
+ const decision = await delivery.bindingIngress?.retainOutbound(
3655
+ {
3656
+ actorId: record.actor.actor.actorId,
3657
+ objectGeneration: record.actor.actor.generation,
3658
+ actorNodeRid: record.actor.actor.nodeRid,
3659
+ actorNodeGeneration: record.actor.targetNodeGeneration,
3660
+ authorityOwnerGeneration: record.actor.authorityOwnerGeneration,
3661
+ ownerLeaseGeneration: record.actor.ownerLeaseGeneration,
3662
+ producerNodeRid: ingress.sourceRoutingId,
3663
+ producerNodeGeneration: ingress.sourceNodeGeneration,
3664
+ sessionIdentity: sessionRid,
3665
+ bindingGeneration: record.expectedBindingGeneration
3666
+ },
3667
+ operation
3668
+ );
3613
3669
  if (decision === 'retained') return 'application';
3614
3670
  if (decision === 'rejected') {
3615
3671
  return 'protocolError';
@@ -3624,9 +3680,9 @@ export class ServiceStatefulRuntime {
3624
3680
  // already completed, so a later client delivery terminal is local to
3625
3681
  // this session owner. Local fast paths still preserve the typed result.
3626
3682
  if (
3627
- ingress.sourceRoutingId !== this.nodeRid
3628
- && isZLinkBackendResultError(error)
3629
- && error.operation === 'submit'
3683
+ ingress.sourceRoutingId !== this.nodeRid &&
3684
+ isZLinkBackendResultError(error) &&
3685
+ error.operation === 'submit'
3630
3686
  ) {
3631
3687
  return 'application';
3632
3688
  }
@@ -3668,7 +3724,9 @@ export class ServiceStatefulRuntime {
3668
3724
  sourceRoutingId: ingress.sourceRoutingId,
3669
3725
  sourceRoute: ingress.sourceRoute,
3670
3726
  ...(ingress.reply === undefined ? {} : { reply: ingress.reply }),
3671
- ...(ingress.requestSequence === undefined ? {} : { requestSequence: ingress.requestSequence }),
3727
+ ...(ingress.requestSequence === undefined
3728
+ ? {}
3729
+ : { requestSequence: ingress.requestSequence }),
3672
3730
  ...(stateful.correlation === undefined ? {} : { correlation: stateful.correlation }),
3673
3731
  stateful,
3674
3732
  applicationJob
@@ -3676,10 +3734,12 @@ export class ServiceStatefulRuntime {
3676
3734
  if (accepted) return domain;
3677
3735
  applicationJob.close();
3678
3736
  if (stateful.reply !== undefined) {
3679
- const result = failure(createInternalFrameworkException(
3680
- ZLinkFrameworkInternalErrorKind.SpotMoving,
3681
- `Mailbox owner '${owner}' no longer accepts work on this runtime.`
3682
- ));
3737
+ const result = failure(
3738
+ createInternalFrameworkException(
3739
+ ZLinkFrameworkInternalErrorKind.SpotMoving,
3740
+ `Mailbox owner '${owner}' no longer accepts work on this runtime.`
3741
+ )
3742
+ );
3683
3743
  stateful.reply(result.terminalResult, result.failureCode);
3684
3744
  return 'infrastructure';
3685
3745
  }
@@ -3717,11 +3777,15 @@ export class ServiceStatefulRuntime {
3717
3777
  applicationJobOwner: NonNullable<RawServiceIngressRecord['applicationJobOwner']>
3718
3778
  ): Promise<void> {
3719
3779
  const targets = [...this.subscriptions.entries()]
3720
- .filter(([, values]) => [...values].some(value => {
3721
- const separator = value.indexOf('\0');
3722
- return value.slice(0, separator) === channelName
3723
- && topicMatches(value.slice(separator + 1), topic);
3724
- }))
3780
+ .filter(([, values]) =>
3781
+ [...values].some((value) => {
3782
+ const separator = value.indexOf('\0');
3783
+ return (
3784
+ value.slice(0, separator) === channelName &&
3785
+ topicMatches(value.slice(separator + 1), topic)
3786
+ );
3787
+ })
3788
+ )
3725
3789
  .map(([spotId]) => spotId)
3726
3790
  .sort();
3727
3791
  for (const spotId of targets) {
@@ -3731,10 +3795,7 @@ export class ServiceStatefulRuntime {
3731
3795
  const accepted = this.raw.mailbox.tryEnqueue({
3732
3796
  owner: `spot:${spotId}`,
3733
3797
  domain: 'application',
3734
- parts: [
3735
- encodeLogicalMulticastHeader(channelName, topic, sourceSpotId),
3736
- payloadFrame
3737
- ],
3798
+ parts: [encodeLogicalMulticastHeader(channelName, topic, sourceSpotId), payloadFrame],
3738
3799
  sourceRoutingId: sourceNodeRid,
3739
3800
  stateful: {
3740
3801
  receiveKind: ReceiveKind.SpotMulticast,
@@ -3843,10 +3904,10 @@ export class ServiceStatefulRuntime {
3843
3904
  private replyPort(
3844
3905
  ingress: RawServiceIngressRecord,
3845
3906
  correlation: bigint | undefined,
3846
- operationKind: 'spotRequest' | 'actorRequest' | 'actorJoin'
3847
- | 'instanceSpotRequest'
3907
+ operationKind: 'spotRequest' | 'actorRequest' | 'actorJoin' | 'instanceSpotRequest'
3848
3908
  ): NonNullable<ServiceStatefulMailboxData['reply']> {
3849
- if (correlation === undefined) throw new ServiceWireProtocolError('Request correlation is missing.');
3909
+ if (correlation === undefined)
3910
+ throw new ServiceWireProtocolError('Request correlation is missing.');
3850
3911
  return (terminalResult, failureCode, payload, tail) => {
3851
3912
  this.replyWire(ingress, correlation, terminalResult, failureCode, payload, tail);
3852
3913
  void operationKind;
@@ -3873,26 +3934,22 @@ export class ServiceStatefulRuntime {
3873
3934
  record: ServiceUserSpotCreateRecord | ServiceUserSpotCloseRecord | ServiceActorCreateRecord
3874
3935
  ): RawServicePumpResult {
3875
3936
  if (
3876
- ingress.requestSequence === undefined
3877
- || record.sourceNodeRid !== ingress.sourceRoutingId
3878
- || record.sourceNodeGeneration !== this.peerGeneration(ingress.sourceRoutingId)
3879
- || (record.kind === 'actorCreate' && record.reservation.pendingCapacityDelta !== 1)
3937
+ ingress.requestSequence === undefined ||
3938
+ record.sourceNodeRid !== ingress.sourceRoutingId ||
3939
+ record.sourceNodeGeneration !== this.peerGeneration(ingress.sourceRoutingId) ||
3940
+ (record.kind === 'actorCreate' && record.reservation.pendingCapacityDelta !== 1)
3880
3941
  ) {
3881
3942
  return 'protocolError';
3882
3943
  }
3883
- const target = record.kind === 'userSpotCreate' || record.kind === 'actorCreate'
3884
- ? record.reservation
3885
- : record.target;
3944
+ const target =
3945
+ record.kind === 'userSpotCreate' || record.kind === 'actorCreate'
3946
+ ? record.reservation
3947
+ : record.target;
3886
3948
  if (
3887
- target.targetNodeRid !== this.nodeRid
3888
- || target.targetNodeGeneration !== this.nodeGeneration
3949
+ target.targetNodeRid !== this.nodeRid ||
3950
+ target.targetNodeGeneration !== this.nodeGeneration
3889
3951
  ) {
3890
- this.replyWire(
3891
- ingress,
3892
- record.correlation,
3893
- RequestResult.Conflict,
3894
- SPOT_MOVING
3895
- );
3952
+ this.replyWire(ingress, record.correlation, RequestResult.Conflict, SPOT_MOVING);
3896
3953
  return 'infrastructure';
3897
3954
  }
3898
3955
  const operationKey = [
@@ -3903,10 +3960,7 @@ export class ServiceStatefulRuntime {
3903
3960
  ].join('\0');
3904
3961
  const encodedRequest = userSpotOperationFingerprint(record);
3905
3962
  let admitted = this.admittedUserSpotOperations.get(operationKey);
3906
- if (
3907
- admitted?.settled === true
3908
- && operationReplayExpired(admitted.replayExpiresAtMs)
3909
- ) {
3963
+ if (admitted?.settled === true && operationReplayExpired(admitted.replayExpiresAtMs)) {
3910
3964
  this.admittedUserSpotOperations.delete(operationKey);
3911
3965
  admitted = undefined;
3912
3966
  }
@@ -3915,36 +3969,28 @@ export class ServiceStatefulRuntime {
3915
3969
  }
3916
3970
  if (admitted === undefined) {
3917
3971
  if (record.deadlineUnixMs < BigInt(Date.now())) {
3918
- this.replyWire(
3919
- ingress,
3920
- record.correlation,
3921
- RequestResult.TimedOut,
3922
- 0
3923
- );
3972
+ this.replyWire(ingress, record.correlation, RequestResult.TimedOut, 0);
3924
3973
  return 'infrastructure';
3925
3974
  }
3926
3975
  if (this.admittedUserSpotOperations.size >= USER_SPOT_OPERATION_CAPACITY) {
3927
3976
  this.releaseExpiredUserSpotOperations();
3928
3977
  }
3929
3978
  if (this.admittedUserSpotOperations.size >= USER_SPOT_OPERATION_CAPACITY) {
3930
- this.replyWire(
3931
- ingress,
3932
- record.correlation,
3933
- RequestResult.Busy,
3934
- 0
3935
- );
3979
+ this.replyWire(ingress, record.correlation, RequestResult.Busy, 0);
3936
3980
  return 'infrastructure';
3937
3981
  }
3938
- const replayExpiresAtMs = performance.now()
3939
- + Number(record.deadlineUnixMs - BigInt(Date.now()))
3940
- + USER_SPOT_OPERATION_REPLAY_RETENTION_MS;
3982
+ const replayExpiresAtMs =
3983
+ performance.now() +
3984
+ Number(record.deadlineUnixMs - BigInt(Date.now())) +
3985
+ USER_SPOT_OPERATION_REPLAY_RETENTION_MS;
3941
3986
  const handler = this.userSpotOperationHandler;
3942
- const result = handler === undefined
3943
- ? Promise.resolve<ServiceUserSpotOperationResult>({
3944
- terminalResult: RequestResult.InvalidState,
3945
- failureCode: 0
3946
- })
3947
- : this.executeUserSpotOperation(handler, record);
3987
+ const result =
3988
+ handler === undefined
3989
+ ? Promise.resolve<ServiceUserSpotOperationResult>({
3990
+ terminalResult: RequestResult.InvalidState,
3991
+ failureCode: 0
3992
+ })
3993
+ : this.executeUserSpotOperation(handler, record);
3948
3994
  admitted = {
3949
3995
  request: encodedRequest,
3950
3996
  replayExpiresAtMs,
@@ -3952,13 +3998,15 @@ export class ServiceStatefulRuntime {
3952
3998
  settled: false
3953
3999
  };
3954
4000
  this.admittedUserSpotOperations.set(operationKey, admitted);
3955
- void result.finally(() => {
3956
- const current = this.admittedUserSpotOperations.get(operationKey);
3957
- if (current?.result === result) current.settled = true;
3958
- }).catch(() => undefined);
4001
+ void result
4002
+ .finally(() => {
4003
+ const current = this.admittedUserSpotOperations.get(operationKey);
4004
+ if (current?.result === result) current.settled = true;
4005
+ })
4006
+ .catch(() => undefined);
3959
4007
  }
3960
4008
  void admitted.result.then(
3961
- result => {
4009
+ (result) => {
3962
4010
  if (this.closed) return;
3963
4011
  this.raw.replyService(ingress, [
3964
4012
  encodeStatefulReply(
@@ -3967,20 +4015,13 @@ export class ServiceStatefulRuntime {
3967
4015
  result.failureCode,
3968
4016
  result.tail
3969
4017
  ),
3970
- ...(result.payload === undefined
3971
- ? []
3972
- : [encodeApplicationPayload(result.payload)])
4018
+ ...(result.payload === undefined ? [] : [encodeApplicationPayload(result.payload)])
3973
4019
  ]);
3974
4020
  },
3975
- error => {
4021
+ (error) => {
3976
4022
  if (this.closed) return;
3977
4023
  const failed = failure(error);
3978
- this.replyWire(
3979
- ingress,
3980
- record.correlation,
3981
- failed.terminalResult,
3982
- failed.failureCode
3983
- );
4024
+ this.replyWire(ingress, record.correlation, failed.terminalResult, failed.failureCode);
3984
4025
  }
3985
4026
  );
3986
4027
  return 'infrastructure';
@@ -4000,22 +4041,20 @@ export class ServiceStatefulRuntime {
4000
4041
  ): Promise<ServiceUserSpotOperationResult> {
4001
4042
  const deadline = userSpotDeadline(record.deadlineUnixMs);
4002
4043
  try {
4003
- const result = record.kind === 'userSpotCreate'
4004
- ? await handler.create(record, deadline.signal)
4005
- : record.kind === 'userSpotClose'
4006
- ? await handler.close(record, deadline.signal)
4007
- : handler.createActor === undefined
4008
- ? {
4009
- terminalResult: RequestResult.InvalidState,
4010
- failureCode: 0
4011
- }
4012
- : await handler.createActor(record, deadline.signal);
4044
+ const result =
4045
+ record.kind === 'userSpotCreate'
4046
+ ? await handler.create(record, deadline.signal)
4047
+ : record.kind === 'userSpotClose'
4048
+ ? await handler.close(record, deadline.signal)
4049
+ : handler.createActor === undefined
4050
+ ? {
4051
+ terminalResult: RequestResult.InvalidState,
4052
+ failureCode: 0
4053
+ }
4054
+ : await handler.createActor(record, deadline.signal);
4013
4055
  if (
4014
- result.terminalResult === RequestResult.Ok
4015
- && (
4016
- result.tail === undefined
4017
- || result.tail.kind !== record.kind
4018
- )
4056
+ result.terminalResult === RequestResult.Ok &&
4057
+ (result.tail === undefined || result.tail.kind !== record.kind)
4019
4058
  ) {
4020
4059
  throw new ServiceWireProtocolError('User Spot success result omits its operation tail.');
4021
4060
  }
@@ -4036,7 +4075,11 @@ export class ServiceStatefulRuntime {
4036
4075
  timeoutMs: number
4037
4076
  ): Promise<ServiceUserSpotOperationResult> {
4038
4077
  const parts = await this.requestDurableOperation(
4039
- targetNodeRid, [header], correlation, operationKind, performance.now() + Math.max(1, timeoutMs)
4078
+ targetNodeRid,
4079
+ [header],
4080
+ correlation,
4081
+ operationKind,
4082
+ performance.now() + Math.max(1, timeoutMs)
4040
4083
  );
4041
4084
  // A received envelope, including a decode failure, ends sender replay.
4042
4085
  try {
@@ -4044,25 +4087,17 @@ export class ServiceStatefulRuntime {
4044
4087
  throw new ServiceWireProtocolError('Invalid creation operation reply parts.');
4045
4088
  }
4046
4089
  const decoded = decodeStatefulReply(parts[0]!, correlation, operationKind, parts.length >= 2);
4047
- if (
4048
- decoded.terminalResult !== RequestResult.Ok
4049
- && parts.length !== 1
4050
- ) {
4090
+ if (decoded.terminalResult !== RequestResult.Ok && parts.length !== 1) {
4051
4091
  throw new ServiceWireProtocolError('Failed creation operation reply carries a payload.');
4052
4092
  }
4053
- if (
4054
- operationKind === 'userSpotClose'
4055
- && parts.length !== 1
4056
- ) {
4093
+ if (operationKind === 'userSpotClose' && parts.length !== 1) {
4057
4094
  throw new ServiceWireProtocolError('User Spot close reply carries a payload.');
4058
4095
  }
4059
4096
  return {
4060
4097
  terminalResult: decoded.terminalResult,
4061
4098
  failureCode: decoded.failureCode,
4062
4099
  ...(decoded.tail === undefined ? {} : { tail: decoded.tail as never }),
4063
- ...(parts.length === 2
4064
- ? { payload: decodeApplicationPayload(parts[1]!) }
4065
- : {})
4100
+ ...(parts.length === 2 ? { payload: decodeApplicationPayload(parts[1]!) } : {})
4066
4101
  };
4067
4102
  } catch (error) {
4068
4103
  throw translateWireReplyDecodeError(error);
@@ -4077,13 +4112,15 @@ export class ServiceStatefulRuntime {
4077
4112
  deadlineMs: number
4078
4113
  ): Promise<readonly Buffer[]> {
4079
4114
  const stop = new AbortController();
4080
- const unobserve = this.raw.observePeerConnectionIntentRemoved(nodeRoutingId => {
4115
+ const unobserve = this.raw.observePeerConnectionIntentRemoved((nodeRoutingId) => {
4081
4116
  if (nodeRoutingId === targetNodeRid) {
4082
- stop.abort(createInternalFrameworkException(
4083
- ZLinkFrameworkInternalErrorKind.RouteNotConnected,
4084
- `${operationKind} target node lifecycle ended.`,
4085
- true
4086
- ));
4117
+ stop.abort(
4118
+ createInternalFrameworkException(
4119
+ ZLinkFrameworkInternalErrorKind.RouteNotConnected,
4120
+ `${operationKind} target node lifecycle ended.`,
4121
+ true
4122
+ )
4123
+ );
4087
4124
  }
4088
4125
  });
4089
4126
  let wasAdmitted = false;
@@ -4112,9 +4149,12 @@ export class ServiceStatefulRuntime {
4112
4149
  }
4113
4150
  let timer: ReturnType<typeof setTimeout> | undefined;
4114
4151
  try {
4115
- await awaitWithAbort(new Promise<void>(resolve => {
4116
- timer = setTimeout(resolve, retryDelayMs);
4117
- }), stop.signal);
4152
+ await awaitWithAbort(
4153
+ new Promise<void>((resolve) => {
4154
+ timer = setTimeout(resolve, retryDelayMs);
4155
+ }),
4156
+ stop.signal
4157
+ );
4118
4158
  } finally {
4119
4159
  if (timer !== undefined) clearTimeout(timer);
4120
4160
  }
@@ -4148,7 +4188,7 @@ export class ServiceStatefulRuntime {
4148
4188
  if (settled) return;
4149
4189
  settled = true;
4150
4190
  clearTimeout(timer);
4151
- resolve(parts.map(part => Buffer.from(part)));
4191
+ resolve(parts.map((part) => Buffer.from(part)));
4152
4192
  };
4153
4193
  void (async () => {
4154
4194
  const applicationJobOwner = await this.raw.reserveLocalIngress();
@@ -4163,9 +4203,11 @@ export class ServiceStatefulRuntime {
4163
4203
  applicationJobOwner
4164
4204
  });
4165
4205
  if (result !== 'infrastructure') {
4166
- fail(new ServiceWireProtocolError(
4167
- `Local infrastructure request was rejected as '${result ?? 'unsupported'}'.`
4168
- ));
4206
+ fail(
4207
+ new ServiceWireProtocolError(
4208
+ `Local infrastructure request was rejected as '${result ?? 'unsupported'}'.`
4209
+ )
4210
+ );
4169
4211
  }
4170
4212
  } finally {
4171
4213
  applicationJobOwner.close();
@@ -4174,10 +4216,7 @@ export class ServiceStatefulRuntime {
4174
4216
  });
4175
4217
  }
4176
4218
 
4177
- private async submitOneWay(
4178
- targetNodeRid: string,
4179
- parts: readonly Buffer[]
4180
- ): Promise<number> {
4219
+ private async submitOneWay(targetNodeRid: string, parts: readonly Buffer[]): Promise<number> {
4181
4220
  this.requireOpen();
4182
4221
  if (targetNodeRid === this.nodeRid) {
4183
4222
  const applicationJobOwner = await this.raw.reserveLocalIngress();
@@ -4231,7 +4270,7 @@ export class ServiceStatefulRuntime {
4231
4270
  applicationJobOwner.close();
4232
4271
  }
4233
4272
  }
4234
- return await this.raw.sendService(targetNodeRid, parts)
4273
+ return (await this.raw.sendService(targetNodeRid, parts))
4235
4274
  ? SubmitResult.Ok
4236
4275
  : SubmitResult.NotConnected;
4237
4276
  }
@@ -4241,7 +4280,13 @@ export class ServiceStatefulRuntime {
4241
4280
  targetNodeRid: string,
4242
4281
  parts: readonly Buffer[],
4243
4282
  timeoutMs: number,
4244
- operationKind: 'spotRequest' | 'actorRequest' | 'actorLookup' | 'actorDestroy' | 'actorJoin' | 'streamBind'
4283
+ operationKind:
4284
+ | 'spotRequest'
4285
+ | 'actorRequest'
4286
+ | 'actorLookup'
4287
+ | 'actorDestroy'
4288
+ | 'actorJoin'
4289
+ | 'streamBind'
4245
4290
  | 'streamUnbind'
4246
4291
  | 'instanceSpotRequest',
4247
4292
  actor?: ServiceActorRef
@@ -4259,24 +4304,18 @@ export class ServiceStatefulRuntime {
4259
4304
  applicationJobOwner
4260
4305
  };
4261
4306
  try {
4262
- this.submitLocalRequest(
4263
- localIngress,
4264
- pending,
4265
- operationKind,
4266
- actor,
4267
- deadlineUnixMs
4268
- );
4307
+ this.submitLocalRequest(localIngress, pending, operationKind, actor, deadlineUnixMs);
4269
4308
  } catch (error) {
4270
4309
  this.operations.reply(pending.id, failure(error));
4271
4310
  } finally {
4272
4311
  applicationJobOwner.close();
4273
4312
  }
4274
- })().catch(error => this.operations.reply(pending.id, failure(error)));
4313
+ })().catch((error) => this.operations.reply(pending.id, failure(error)));
4275
4314
  return;
4276
4315
  }
4277
4316
  void this.raw.requestService(targetNodeRid, parts, timeoutMs).then(
4278
- reply => this.completeRemoteReply(pending, targetNodeRid, operationKind, actor, reply),
4279
- error => this.operations.fail(pending.id, error)
4317
+ (reply) => this.completeRemoteReply(pending, targetNodeRid, operationKind, actor, reply),
4318
+ (error) => this.operations.fail(pending.id, error)
4280
4319
  );
4281
4320
  }
4282
4321
 
@@ -4289,9 +4328,10 @@ export class ServiceStatefulRuntime {
4289
4328
  deadlineMs: number,
4290
4329
  canonical?: ServiceCanonicalActorJoinCandidate
4291
4330
  ): void {
4292
- const actorRoute = canonical === undefined
4293
- ? this.tryActorFence(actor)
4294
- : this.acceptCanonicalActorFence(actor, canonical.actorFence);
4331
+ const actorRoute =
4332
+ canonical === undefined
4333
+ ? this.tryActorFence(actor)
4334
+ : this.acceptCanonicalActorFence(actor, canonical.actorFence);
4295
4335
  if (target === undefined || actorRoute === undefined) {
4296
4336
  this.operations.reply(pending.id, {
4297
4337
  terminalResult: RequestResult.NotFound,
@@ -4300,13 +4340,16 @@ export class ServiceStatefulRuntime {
4300
4340
  return;
4301
4341
  }
4302
4342
  if (canonical !== undefined) {
4303
- this.canonicalActorJoinHandoffs.set(pending.id, canonicalActorJoinHandoffId({
4304
- sourceActorNodeRid: routingIdBytes(actor.nodeRid as never),
4305
- actorId: actor.actorId,
4306
- actorGeneration: actor.generation,
4307
- sourceActorNodeGeneration: actorRoute.targetNodeGeneration,
4308
- correlation: pending.id
4309
- }));
4343
+ this.canonicalActorJoinHandoffs.set(
4344
+ pending.id,
4345
+ canonicalActorJoinHandoffId({
4346
+ sourceActorNodeRid: routingIdBytes(actor.nodeRid as never),
4347
+ actorId: actor.actorId,
4348
+ actorGeneration: actor.generation,
4349
+ sourceActorNodeGeneration: actorRoute.targetNodeGeneration,
4350
+ correlation: pending.id
4351
+ })
4352
+ );
4310
4353
  }
4311
4354
  let parts: readonly Buffer[];
4312
4355
  try {
@@ -4330,7 +4373,7 @@ export class ServiceStatefulRuntime {
4330
4373
  expectedOwnerLeaseGeneration: target.ownerLeaseGeneration
4331
4374
  },
4332
4375
  ...(payload === undefined ? {} : { payload })
4333
- }).map(frame => Buffer.from(frame));
4376
+ }).map((frame) => Buffer.from(frame));
4334
4377
  } catch (error) {
4335
4378
  this.canonicalActorJoinHandoffs.delete(pending.id);
4336
4379
  this.operations.fail(pending.id, error);
@@ -4338,14 +4381,24 @@ export class ServiceStatefulRuntime {
4338
4381
  }
4339
4382
  if (targetNodeRid === this.nodeRid) {
4340
4383
  this.submitRequest(
4341
- pending, targetNodeRid, parts, Math.max(0, Math.ceil(deadlineMs - performance.now())),
4342
- 'actorJoin', actor
4384
+ pending,
4385
+ targetNodeRid,
4386
+ parts,
4387
+ Math.max(0, Math.ceil(deadlineMs - performance.now())),
4388
+ 'actorJoin',
4389
+ actor
4343
4390
  );
4344
4391
  return;
4345
4392
  }
4346
- void this.requestDurableOperation(targetNodeRid, parts, pending.id, 'actorJoin', deadlineMs).then(
4347
- reply => this.completeRemoteReply(pending, targetNodeRid, 'actorJoin', actor, reply),
4348
- error => {
4393
+ void this.requestDurableOperation(
4394
+ targetNodeRid,
4395
+ parts,
4396
+ pending.id,
4397
+ 'actorJoin',
4398
+ deadlineMs
4399
+ ).then(
4400
+ (reply) => this.completeRemoteReply(pending, targetNodeRid, 'actorJoin', actor, reply),
4401
+ (error) => {
4349
4402
  this.canonicalActorJoinHandoffs.delete(pending.id);
4350
4403
  this.operations.fail(pending.id, error);
4351
4404
  }
@@ -4355,34 +4408,46 @@ export class ServiceStatefulRuntime {
4355
4408
  private submitLocalRequest(
4356
4409
  ingress: RawServiceIngressRecord,
4357
4410
  pending: ServiceStatefulPendingOperation,
4358
- operationKind: 'spotRequest' | 'actorRequest' | 'actorLookup' | 'actorDestroy' | 'actorJoin' | 'streamBind'
4411
+ operationKind:
4412
+ | 'spotRequest'
4413
+ | 'actorRequest'
4414
+ | 'actorLookup'
4415
+ | 'actorDestroy'
4416
+ | 'actorJoin'
4417
+ | 'streamBind'
4359
4418
  | 'streamUnbind'
4360
4419
  | 'instanceSpotRequest',
4361
4420
  actor?: ServiceActorRef,
4362
4421
  deadlineUnixMs?: bigint
4363
4422
  ): void {
4364
- const canonicalActorJoin = operationKind === 'actorJoin'
4365
- ? decodeActorJoin28(ingress.parts)
4366
- : undefined;
4367
- const decoded = canonicalActorJoin === undefined
4368
- ? decodeStatefulHeader(ingress.parts[0]!)
4369
- : statefulActorJoinFromCanonical(canonicalActorJoin);
4370
- const payloadFrame = canonicalActorJoin?.payload === undefined
4371
- ? (ingress.parts.length < 2 ? undefined : ingress.parts[1])
4372
- : encodeApplicationPayload({
4373
- packetName: canonicalActorJoin.payload.packetName,
4374
- contentType: canonicalActorJoin.payload.contentType,
4375
- payload: Buffer.from(canonicalActorJoin.payload.payload)
4376
- });
4423
+ const canonicalActorJoin =
4424
+ operationKind === 'actorJoin' ? decodeActorJoin28(ingress.parts) : undefined;
4425
+ const decoded =
4426
+ canonicalActorJoin === undefined
4427
+ ? decodeStatefulHeader(ingress.parts[0]!)
4428
+ : statefulActorJoinFromCanonical(canonicalActorJoin);
4429
+ const payloadFrame =
4430
+ canonicalActorJoin?.payload === undefined
4431
+ ? ingress.parts.length < 2
4432
+ ? undefined
4433
+ : ingress.parts[1]
4434
+ : encodeApplicationPayload({
4435
+ packetName: canonicalActorJoin.payload.packetName,
4436
+ contentType: canonicalActorJoin.payload.contentType,
4437
+ payload: Buffer.from(canonicalActorJoin.payload.payload)
4438
+ });
4377
4439
  if (decoded.kind === 'actorLookup') {
4378
4440
  const found = this.registry.actor(decoded.actorId);
4379
- this.operations.reply(pending.id, found === undefined
4380
- ? { terminalResult: RequestResult.NotFound, failureCode: ACTOR_ROUTE_NOT_FOUND }
4381
- : {
4382
- terminalResult: RequestResult.Ok,
4383
- failureCode: 0,
4384
- kindData: lookupKindData(found)
4385
- });
4441
+ this.operations.reply(
4442
+ pending.id,
4443
+ found === undefined
4444
+ ? { terminalResult: RequestResult.NotFound, failureCode: ACTOR_ROUTE_NOT_FOUND }
4445
+ : {
4446
+ terminalResult: RequestResult.Ok,
4447
+ failureCode: 0,
4448
+ kindData: lookupKindData(found)
4449
+ }
4450
+ );
4386
4451
  return;
4387
4452
  }
4388
4453
  if (decoded.kind === 'actorDestroy') {
@@ -4399,35 +4464,28 @@ export class ServiceStatefulRuntime {
4399
4464
  failureCode,
4400
4465
  replyPayload,
4401
4466
  tail
4402
- ) => this.operations.reply(pending.id, this.resultFromReply(
4403
- terminalResult,
4404
- failureCode,
4405
- replyPayload,
4406
- tail,
4407
- this.nodeRid,
4408
- actor
4409
- ));
4467
+ ) =>
4468
+ this.operations.reply(
4469
+ pending.id,
4470
+ this.resultFromReply(terminalResult, failureCode, replyPayload, tail, this.nodeRid, actor)
4471
+ );
4410
4472
  if (decoded.kind === 'spotRequest') {
4411
4473
  this.validateDirectSpotFence(decoded.target);
4412
- this.enqueueApplicationFrame(
4413
- ingress,
4414
- `spot:${decoded.target.spot.spotId}`,
4415
- payloadFrame!,
4416
- {
4417
- receiveKind: ReceiveKind.SpotRequest,
4418
- operationKind: OperationKind.SpotRequest,
4419
- correlation: decoded.correlation,
4420
- sourceSpotId: decoded.sourceSpotId,
4421
- targetSpot: decoded.target.spot,
4422
- reply: localReply
4423
- }
4424
- );
4474
+ this.enqueueApplicationFrame(ingress, `spot:${decoded.target.spot.spotId}`, payloadFrame!, {
4475
+ receiveKind: ReceiveKind.SpotRequest,
4476
+ operationKind: OperationKind.SpotRequest,
4477
+ correlation: decoded.correlation,
4478
+ sourceSpotId: decoded.sourceSpotId,
4479
+ targetSpot: decoded.target.spot,
4480
+ reply: localReply
4481
+ });
4425
4482
  return;
4426
4483
  }
4427
4484
  if (decoded.kind === 'actorRequest') {
4428
- const current = decoded.boundSession === undefined
4429
- ? this.validateActorMessageFence(decoded.target)
4430
- : this.validateActorFence(decoded.target);
4485
+ const current =
4486
+ decoded.boundSession === undefined
4487
+ ? this.validateActorMessageFence(decoded.target)
4488
+ : this.validateActorFence(decoded.target);
4431
4489
  this.enqueueApplicationFrame(
4432
4490
  ingress,
4433
4491
  `actor:${current.ref.actorId}\0${current.ref.generation}`,
@@ -4490,9 +4548,10 @@ export class ServiceStatefulRuntime {
4490
4548
  onTerminalCompletion: () => completeOnJoinDispatchTerminal?.(),
4491
4549
  reply: (terminalResult, failureCode, replyPayload, tail) => {
4492
4550
  if (actorJoinReplyAccepted) return false;
4493
- const acceptedJoin = terminalResult === RequestResult.Ok
4494
- && tail?.kind === 'actorJoin'
4495
- && tail.joinResult === 0;
4551
+ const acceptedJoin =
4552
+ terminalResult === RequestResult.Ok &&
4553
+ tail?.kind === 'actorJoin' &&
4554
+ tail.joinResult === 0;
4496
4555
  if (acceptedJoin && this.operations.isPending(pending.id)) {
4497
4556
  // Commit membership now, but keep the source operation behind
4498
4557
  // target OnJoinedActor. Entry finishes on this record; User
@@ -4517,12 +4576,7 @@ export class ServiceStatefulRuntime {
4517
4576
  }
4518
4577
  return true;
4519
4578
  }
4520
- const acceptedReply = localReply(
4521
- terminalResult,
4522
- failureCode,
4523
- replyPayload,
4524
- tail
4525
- );
4579
+ const acceptedReply = localReply(terminalResult, failureCode, replyPayload, tail);
4526
4580
  if (acceptedReply) actorJoinReplyAccepted = true;
4527
4581
  return acceptedReply;
4528
4582
  }
@@ -4534,13 +4588,15 @@ export class ServiceStatefulRuntime {
4534
4588
  try {
4535
4589
  const current = this.validateActorFence(decoded.actor);
4536
4590
  if (decoded.binding.state === 'active') {
4537
- this.registry.installSessionBinding(sessionBindingFromWire(
4538
- current.ref,
4539
- decoded.sessionRid,
4540
- this.nodeRid,
4541
- decoded.binding.generation,
4542
- current.membershipEpoch
4543
- ));
4591
+ this.registry.installSessionBinding(
4592
+ sessionBindingFromWire(
4593
+ current.ref,
4594
+ decoded.sessionRid,
4595
+ this.nodeRid,
4596
+ decoded.binding.generation,
4597
+ current.membershipEpoch
4598
+ )
4599
+ );
4544
4600
  } else {
4545
4601
  this.registry.unbindSession(
4546
4602
  current.ref,
@@ -4557,29 +4613,19 @@ export class ServiceStatefulRuntime {
4557
4613
  }
4558
4614
  if (decoded.kind === 'instanceSpot') {
4559
4615
  if (decoded.activation === 'missing' && this.asyncInstanceAuthority !== undefined) {
4560
- void this.continueMissingInstanceActivation(
4561
- ingress,
4562
- decoded,
4563
- payloadFrame!,
4564
- localReply
4565
- );
4616
+ void this.continueMissingInstanceActivation(ingress, decoded, payloadFrame!, localReply);
4566
4617
  return;
4567
4618
  }
4568
4619
  try {
4569
4620
  const activation = this.requireInstanceActivation(ingress, decoded);
4570
- this.enqueueApplicationFrame(
4571
- ingress,
4572
- `spot:${activation.ref.spotId}`,
4573
- payloadFrame!,
4574
- {
4575
- receiveKind: ReceiveKind.InstanceSpotActivation,
4576
- operationKind: OperationKind.InstanceSpotRequest,
4577
- correlation: pending.id,
4578
- ...(decoded.sourceSpotId === undefined ? {} : { sourceSpotId: decoded.sourceSpotId }),
4579
- targetSpot: activation.ref,
4580
- reply: localReply
4581
- }
4582
- );
4621
+ this.enqueueApplicationFrame(ingress, `spot:${activation.ref.spotId}`, payloadFrame!, {
4622
+ receiveKind: ReceiveKind.InstanceSpotActivation,
4623
+ operationKind: OperationKind.InstanceSpotRequest,
4624
+ correlation: pending.id,
4625
+ ...(decoded.sourceSpotId === undefined ? {} : { sourceSpotId: decoded.sourceSpotId }),
4626
+ targetSpot: activation.ref,
4627
+ reply: localReply
4628
+ });
4583
4629
  } catch (error) {
4584
4630
  this.operations.reply(pending.id, failure(error));
4585
4631
  }
@@ -4595,28 +4641,37 @@ export class ServiceStatefulRuntime {
4595
4641
  private completeRemoteReply(
4596
4642
  pending: ServiceStatefulPendingOperation,
4597
4643
  targetNodeRid: string,
4598
- operationKind: 'spotRequest' | 'actorRequest' | 'actorLookup' | 'actorDestroy' | 'actorJoin' | 'streamBind'
4644
+ operationKind:
4645
+ | 'spotRequest'
4646
+ | 'actorRequest'
4647
+ | 'actorLookup'
4648
+ | 'actorDestroy'
4649
+ | 'actorJoin'
4650
+ | 'streamBind'
4599
4651
  | 'streamUnbind'
4600
4652
  | 'instanceSpotRequest',
4601
4653
  actor: ServiceActorRef | undefined,
4602
4654
  reply: readonly Buffer[]
4603
4655
  ): void {
4604
- const canonicalActorJoinHandoffId = operationKind === 'actorJoin'
4605
- ? this.canonicalActorJoinHandoffs.get(pending.id)
4606
- : undefined;
4656
+ const canonicalActorJoinHandoffId =
4657
+ operationKind === 'actorJoin' ? this.canonicalActorJoinHandoffs.get(pending.id) : undefined;
4607
4658
  try {
4608
- if (reply.length < 1 || reply.length > 2) throw new ServiceWireProtocolError('Invalid M6B reply parts.');
4659
+ if (reply.length < 1 || reply.length > 2)
4660
+ throw new ServiceWireProtocolError('Invalid M6B reply parts.');
4609
4661
  const decoded = decodeStatefulReply(reply[0]!, pending.id, operationKind, reply.length >= 2);
4610
4662
  const payload = reply.length < 2 ? undefined : decodeApplicationPayload(reply[1]);
4611
- this.operations.reply(pending.id, this.resultFromReply(
4612
- decoded.terminalResult,
4613
- decoded.failureCode,
4614
- payload,
4615
- decoded.tail,
4616
- targetNodeRid,
4617
- actor,
4618
- canonicalActorJoinHandoffId
4619
- ));
4663
+ this.operations.reply(
4664
+ pending.id,
4665
+ this.resultFromReply(
4666
+ decoded.terminalResult,
4667
+ decoded.failureCode,
4668
+ payload,
4669
+ decoded.tail,
4670
+ targetNodeRid,
4671
+ actor,
4672
+ canonicalActorJoinHandoffId
4673
+ )
4674
+ );
4620
4675
  } catch (error) {
4621
4676
  // Spec 32-framework-error-model:58-60, 91-92 — an unprocessable remote
4622
4677
  // reply (decode/shape failure) fails the awaiting operation with a
@@ -4695,7 +4750,10 @@ export class ServiceStatefulRuntime {
4695
4750
  }
4696
4751
 
4697
4752
  private validateActorFence(fence: ServiceActorRouteFence): ServiceActorState {
4698
- if (fence.actor.nodeRid !== this.nodeRid || fence.targetNodeGeneration !== this.nodeGeneration) {
4753
+ if (
4754
+ fence.actor.nodeRid !== this.nodeRid ||
4755
+ fence.targetNodeGeneration !== this.nodeGeneration
4756
+ ) {
4699
4757
  throw new ServiceStaleGenerationError('actor', fence.actor.actorId);
4700
4758
  }
4701
4759
  const actor = this.registry.requireActor(fence.actor);
@@ -4706,7 +4764,10 @@ export class ServiceStatefulRuntime {
4706
4764
  }
4707
4765
 
4708
4766
  private validateActorMessageFence(fence: ServiceActorRouteFence): ServiceActorState {
4709
- if (fence.actor.nodeRid !== this.nodeRid || fence.targetNodeGeneration !== this.nodeGeneration) {
4767
+ if (
4768
+ fence.actor.nodeRid !== this.nodeRid ||
4769
+ fence.targetNodeGeneration !== this.nodeGeneration
4770
+ ) {
4710
4771
  throw new ServiceStaleGenerationError('actor', fence.actor.actorId);
4711
4772
  }
4712
4773
  const actor = this.registry.actor(fence.actor.actorId);
@@ -4720,7 +4781,10 @@ export class ServiceStatefulRuntime {
4720
4781
  }
4721
4782
 
4722
4783
  private validateSpotFence(fence: ServiceSpotRouteFence): ServiceSpotState {
4723
- if (fence.targetNodeRid !== this.nodeRid || fence.targetNodeGeneration !== this.nodeGeneration) {
4784
+ if (
4785
+ fence.targetNodeRid !== this.nodeRid ||
4786
+ fence.targetNodeGeneration !== this.nodeGeneration
4787
+ ) {
4724
4788
  throw new ServiceStaleGenerationError('spot', fence.spot.spotId);
4725
4789
  }
4726
4790
  const spot = this.registry.requireSpot(fence.spot);
@@ -4744,7 +4808,10 @@ export class ServiceStatefulRuntime {
4744
4808
  `Spot '${fence.spot.spotId}' is not Ready.`
4745
4809
  );
4746
4810
  }
4747
- if (fence.targetNodeRid !== this.nodeRid || fence.targetNodeGeneration !== this.nodeGeneration) {
4811
+ if (
4812
+ fence.targetNodeRid !== this.nodeRid ||
4813
+ fence.targetNodeGeneration !== this.nodeGeneration
4814
+ ) {
4748
4815
  throw createInternalFrameworkException(
4749
4816
  ZLinkFrameworkInternalErrorKind.SpotMoving,
4750
4817
  `Spot '${fence.spot.spotId}' targets an unavailable owner route.`
@@ -4767,15 +4834,11 @@ export class ServiceStatefulRuntime {
4767
4834
  );
4768
4835
  }
4769
4836
  if (
4770
- current.targetNodeRid !== this.nodeRid
4771
- || current.targetNodeGeneration !== this.nodeGeneration
4772
- || current.ownerLeaseGeneration !== fence.ownerLeaseGeneration
4773
- || (
4774
- current.spot.generation === fence.spot.generation
4775
- && (
4776
- current.authorityOwnerGeneration !== fence.authorityOwnerGeneration
4777
- )
4778
- )
4837
+ current.targetNodeRid !== this.nodeRid ||
4838
+ current.targetNodeGeneration !== this.nodeGeneration ||
4839
+ current.ownerLeaseGeneration !== fence.ownerLeaseGeneration ||
4840
+ (current.spot.generation === fence.spot.generation &&
4841
+ current.authorityOwnerGeneration !== fence.authorityOwnerGeneration)
4779
4842
  ) {
4780
4843
  throw createInternalFrameworkException(
4781
4844
  ZLinkFrameworkInternalErrorKind.SpotMoving,
@@ -4787,10 +4850,7 @@ export class ServiceStatefulRuntime {
4787
4850
 
4788
4851
  private holdOrRelaySpotMessage(
4789
4852
  ingress: RawServiceIngressRecord,
4790
- wire: Extract<
4791
- ServiceStatefulWireRecord,
4792
- { readonly kind: 'spotSend' | 'spotRequest' }
4793
- >
4853
+ wire: Extract<ServiceStatefulWireRecord, { readonly kind: 'spotSend' | 'spotRequest' }>
4794
4854
  ): RawServicePumpResult | undefined {
4795
4855
  const state = this.spotMessageFollow.get(spotKey(wire.target.spot));
4796
4856
  if (state === undefined || !sameDirectSpotRoute(state.source, wire.target)) {
@@ -4855,7 +4915,7 @@ export class ServiceStatefulRuntime {
4855
4915
  current.ingress.parts[1]!
4856
4916
  ];
4857
4917
  if (current.wire.kind === 'spotSend') {
4858
- if (!await this.raw.sendService(state.target.targetNodeRid, parts)) continue;
4918
+ if (!(await this.raw.sendService(state.target.targetNodeRid, parts))) continue;
4859
4919
  } else {
4860
4920
  try {
4861
4921
  const remainingMs = Math.max(
@@ -4900,22 +4960,24 @@ export class ServiceStatefulRuntime {
4900
4960
  if (target === undefined || suppressionFence === undefined) return;
4901
4961
  const claim = this.spotMessageFollowSuppression.begin(suppressionFence);
4902
4962
  if (claim === undefined) return;
4903
- const operationLow = current.ingress.requestSequence !== undefined
4904
- && current.ingress.requestSequence !== 0n
4905
- ? current.ingress.requestSequence
4906
- : this.nextMessageFollowOperation++;
4907
- const accepted = await this.raw.sendService(current.ingress.sourceRoutingId, [encodeMessageFollowHeader({
4908
- source: messageFollowSpotRoute(state.source),
4909
- target: messageFollowSpotRoute(target),
4910
- hopCount: 1,
4911
- queuedMessages: Math.min(state.queuedCount, 0xffff_ffff),
4912
- queuedBytes: Math.min(state.queuedBytes, 0xffff_ffff),
4913
- originalOperation: {
4914
- high: this.nodeGeneration,
4915
- low: operationLow
4916
- },
4917
- originalReplyRouteId: current.ingress.requestSequence ?? 0n
4918
- })]);
4963
+ const operationLow =
4964
+ current.ingress.requestSequence !== undefined && current.ingress.requestSequence !== 0n
4965
+ ? current.ingress.requestSequence
4966
+ : this.nextMessageFollowOperation++;
4967
+ const accepted = await this.raw.sendService(current.ingress.sourceRoutingId, [
4968
+ encodeMessageFollowHeader({
4969
+ source: messageFollowSpotRoute(state.source),
4970
+ target: messageFollowSpotRoute(target),
4971
+ hopCount: 1,
4972
+ queuedMessages: Math.min(state.queuedCount, 0xffff_ffff),
4973
+ queuedBytes: Math.min(state.queuedBytes, 0xffff_ffff),
4974
+ originalOperation: {
4975
+ high: this.nodeGeneration,
4976
+ low: operationLow
4977
+ },
4978
+ originalReplyRouteId: current.ingress.requestSequence ?? 0n
4979
+ })
4980
+ ]);
4919
4981
  if (accepted) {
4920
4982
  this.spotMessageFollowSuppression.markSent(claim);
4921
4983
  } else {
@@ -4994,18 +5056,18 @@ export class ServiceStatefulRuntime {
4994
5056
  senderFence: ServiceBoundSessionSendFence | undefined
4995
5057
  ): ServiceActorRouteFence | undefined {
4996
5058
  if (
4997
- senderFence === undefined
4998
- || senderFence.targetNodeGeneration !== this.nodeGeneration
4999
- || senderFence.authorityOwnerGeneration <= 0n
5000
- || senderFence.ownerLeaseGeneration <= 0n
5059
+ senderFence === undefined ||
5060
+ senderFence.targetNodeGeneration !== this.nodeGeneration ||
5061
+ senderFence.authorityOwnerGeneration <= 0n ||
5062
+ senderFence.ownerLeaseGeneration <= 0n
5001
5063
  ) {
5002
5064
  return undefined;
5003
5065
  }
5004
5066
  const local = actor.nodeRid === this.nodeRid ? this.registry.actor(actor.actorId) : undefined;
5005
5067
  if (
5006
- local === undefined
5007
- || !sameActorRef(local.ref, actor)
5008
- || local.authorityOwnerGeneration !== senderFence.authorityOwnerGeneration
5068
+ local === undefined ||
5069
+ !sameActorRef(local.ref, actor) ||
5070
+ local.authorityOwnerGeneration !== senderFence.authorityOwnerGeneration
5009
5071
  ) {
5010
5072
  return undefined;
5011
5073
  }
@@ -5043,10 +5105,10 @@ export class ServiceStatefulRuntime {
5043
5105
  // Object/authority/lease are bounded counters. Node lifecycle is a
5044
5106
  // full-range opaque token, where only zero represents absence.
5045
5107
  if (
5046
- actor.generation <= 0n
5047
- || fence.targetNodeGeneration === 0n
5048
- || fence.authorityOwnerGeneration <= 0n
5049
- || fence.ownerLeaseGeneration <= 0n
5108
+ actor.generation <= 0n ||
5109
+ fence.targetNodeGeneration === 0n ||
5110
+ fence.authorityOwnerGeneration <= 0n ||
5111
+ fence.ownerLeaseGeneration <= 0n
5050
5112
  ) {
5051
5113
  return undefined;
5052
5114
  }
@@ -5073,17 +5135,18 @@ export class ServiceStatefulRuntime {
5073
5135
  };
5074
5136
  }
5075
5137
  const route = this.spotRoutes.get(spotKey(spot));
5076
- return route !== undefined
5077
- && route.targetNodeRid === targetNodeRid
5078
- && sameSpotRef(route.spot, spot)
5138
+ return route !== undefined &&
5139
+ route.targetNodeRid === targetNodeRid &&
5140
+ sameSpotRef(route.spot, spot)
5079
5141
  ? route
5080
5142
  : undefined;
5081
5143
  }
5082
5144
 
5083
5145
  private tryEntrySpotFence(targetNodeRid: string): ServiceDirectSpotRouteFence | undefined {
5084
- const targetNodeGeneration = targetNodeRid === this.nodeRid
5085
- ? this.nodeGeneration
5086
- : this.raw.topology.peer(targetNodeRid)?.descriptor.lifecycleGeneration;
5146
+ const targetNodeGeneration =
5147
+ targetNodeRid === this.nodeRid
5148
+ ? this.nodeGeneration
5149
+ : this.raw.topology.peer(targetNodeRid)?.descriptor.lifecycleGeneration;
5087
5150
  if (targetNodeGeneration === undefined) return undefined;
5088
5151
  return {
5089
5152
  spot: {
@@ -5105,28 +5168,24 @@ export class ServiceStatefulRuntime {
5105
5168
  if (targetNodeRid === this.nodeRid) {
5106
5169
  const local = this.registry.spot(spot.spotId);
5107
5170
  if (
5108
- local?.kind === 'entry'
5109
- && sameSpotRef(local.ref, spot)
5110
- && targetNodeGeneration === this.nodeGeneration
5111
- && requested.authorityOwnerGeneration === local.authorityOwnerGeneration
5112
- && isEntrySpotFence(requested)
5171
+ local?.kind === 'entry' &&
5172
+ sameSpotRef(local.ref, spot) &&
5173
+ targetNodeGeneration === this.nodeGeneration &&
5174
+ requested.authorityOwnerGeneration === local.authorityOwnerGeneration &&
5175
+ isEntrySpotFence(requested)
5113
5176
  ) {
5114
5177
  return requested;
5115
5178
  }
5116
5179
  const current = this.directSpotRoutes.get(directSpotKey(spot.spotId));
5117
- return local !== undefined
5118
- && local.state === 'ready'
5119
- && targetNodeGeneration === this.nodeGeneration
5120
- && current !== undefined
5121
- && current.targetNodeRid === this.nodeRid
5122
- && current.targetNodeGeneration === this.nodeGeneration
5123
- && current.ownerLeaseGeneration === requested.ownerLeaseGeneration
5124
- && (
5125
- current.spot.generation !== requested.spot.generation
5126
- || (
5127
- current.authorityOwnerGeneration === requested.authorityOwnerGeneration
5128
- )
5129
- )
5180
+ return local !== undefined &&
5181
+ local.state === 'ready' &&
5182
+ targetNodeGeneration === this.nodeGeneration &&
5183
+ current !== undefined &&
5184
+ current.targetNodeRid === this.nodeRid &&
5185
+ current.targetNodeGeneration === this.nodeGeneration &&
5186
+ current.ownerLeaseGeneration === requested.ownerLeaseGeneration &&
5187
+ (current.spot.generation !== requested.spot.generation ||
5188
+ current.authorityOwnerGeneration === requested.authorityOwnerGeneration)
5130
5189
  ? current
5131
5190
  : undefined;
5132
5191
  }
@@ -5160,9 +5219,8 @@ export class ServiceStatefulRuntime {
5160
5219
  const current = this.registry.actor(actor.actorId);
5161
5220
  const previousActor = current?.ref ?? actor;
5162
5221
  const previousSpot = current?.spot;
5163
- const previousSpotState = previousSpot === undefined
5164
- ? undefined
5165
- : this.registry.spot(previousSpot.spotId);
5222
+ const previousSpotState =
5223
+ previousSpot === undefined ? undefined : this.registry.spot(previousSpot.spotId);
5166
5224
  const previousMembershipEpoch = current?.membershipEpoch ?? membershipEpoch - 1n;
5167
5225
  if (current === undefined) {
5168
5226
  this.registry.restoreActor(
@@ -5180,26 +5238,30 @@ export class ServiceStatefulRuntime {
5180
5238
  });
5181
5239
  const targetSpot = this.registry.spot(spot.spotId);
5182
5240
  if (targetSpot?.kind !== 'entry') {
5183
- this.enqueueActorControl(spot.spotId, {
5184
- kind: 'actorControl',
5185
- lifecycleKind: ActorLifecycleKind.Joined,
5186
- previousActor,
5187
- currentActor: committed.ref,
5188
- previousSpotId: previousSpot?.spotId ?? null,
5189
- currentSpotId: spot.spotId,
5190
- previousSpotGeneration: previousSpot?.generation ?? 0n,
5191
- currentSpotGeneration: spot.generation,
5192
- previousMembershipEpoch,
5193
- currentMembershipEpoch: committed.membershipEpoch,
5194
- resultCode: 0
5195
- }, onTargetLifecycleCompleted);
5241
+ this.enqueueActorControl(
5242
+ spot.spotId,
5243
+ {
5244
+ kind: 'actorControl',
5245
+ lifecycleKind: ActorLifecycleKind.Joined,
5246
+ previousActor,
5247
+ currentActor: committed.ref,
5248
+ previousSpotId: previousSpot?.spotId ?? null,
5249
+ currentSpotId: spot.spotId,
5250
+ previousSpotGeneration: previousSpot?.generation ?? 0n,
5251
+ currentSpotGeneration: spot.generation,
5252
+ previousMembershipEpoch,
5253
+ currentMembershipEpoch: committed.membershipEpoch,
5254
+ resultCode: 0
5255
+ },
5256
+ onTargetLifecycleCompleted
5257
+ );
5196
5258
  }
5197
5259
  if (
5198
- actor.nodeRid === this.nodeRid
5199
- && previousSpot !== undefined
5200
- && previousSpot.spotId !== spot.spotId
5201
- && previousSpotState?.ref.generation === previousSpot.generation
5202
- && (previousSpotState.kind === 'entry' || previousSpotState.kind === 'user')
5260
+ actor.nodeRid === this.nodeRid &&
5261
+ previousSpot !== undefined &&
5262
+ previousSpot.spotId !== spot.spotId &&
5263
+ previousSpotState?.ref.generation === previousSpot.generation &&
5264
+ (previousSpotState.kind === 'entry' || previousSpotState.kind === 'user')
5203
5265
  ) {
5204
5266
  // A same-node Core join commits the target membership and publishes
5205
5267
  // the source LEFT control separately. Remote joins use the formal
@@ -5221,18 +5283,41 @@ export class ServiceStatefulRuntime {
5221
5283
  }
5222
5284
  }
5223
5285
 
5224
-
5225
5286
  private requireOpen(): void {
5226
5287
  if (this.closed) throw new Error('Stateful runtime is closed.');
5227
5288
  }
5228
5289
  }
5229
5290
 
5291
+ function serviceSpotPublishFailureReason(
5292
+ result: number | undefined,
5293
+ routeReady: boolean,
5294
+ closed: boolean
5295
+ ): 'stale_target' | 'backpressure' | 'shutdown' {
5296
+ if (closed || result === SubmitResult.Terminated) return 'shutdown';
5297
+ switch (result) {
5298
+ case SubmitResult.Backpressured:
5299
+ return 'backpressure';
5300
+ case SubmitResult.NotAdmitted:
5301
+ case SubmitResult.NotConnected:
5302
+ case SubmitResult.NotFound:
5303
+ case SubmitResult.InvalidHandle:
5304
+ return 'stale_target';
5305
+ default:
5306
+ // RawServiceMeshRuntime exposes failed Core submissions as false. A
5307
+ // ready route therefore identifies queue admission failure; a route
5308
+ // that became unready after selection is a stale target.
5309
+ return routeReady ? 'backpressure' : 'stale_target';
5310
+ }
5311
+ }
5312
+
5230
5313
  function isEntrySpotFence(fence: ServiceDirectSpotRouteFence): boolean {
5231
- return fence.spot.spotId === fence.targetNodeRid
5232
- && fence.spot.generation === fence.targetNodeGeneration
5233
- && fence.authorityOwnerGeneration === fence.targetNodeGeneration
5234
- && fence.ownerLeaseGeneration === fence.targetNodeGeneration
5235
- && fence.storeVersion === `entry:${fence.targetNodeGeneration}`;
5314
+ return (
5315
+ fence.spot.spotId === fence.targetNodeRid &&
5316
+ fence.spot.generation === fence.targetNodeGeneration &&
5317
+ fence.authorityOwnerGeneration === fence.targetNodeGeneration &&
5318
+ fence.ownerLeaseGeneration === fence.targetNodeGeneration &&
5319
+ fence.storeVersion === `entry:${fence.targetNodeGeneration}`
5320
+ );
5236
5321
  }
5237
5322
 
5238
5323
  function userSpotDeadline(deadlineUnixMs: bigint): {
@@ -5280,10 +5365,10 @@ function durableRequestCanReplay(error: unknown): boolean {
5280
5365
  if (!isZLinkBackendResultError(error)) return false;
5281
5366
  return error.operation === 'request'
5282
5367
  ? error.result === RequestResult.NotConnected || error.result === RequestResult.TimedOut
5283
- : error.result === SubmitResult.NotConnected
5284
- || error.result === SubmitResult.NotFound
5285
- || error.result === SubmitResult.NotAdmitted
5286
- || error.result === SubmitResult.Backpressured;
5368
+ : error.result === SubmitResult.NotConnected ||
5369
+ error.result === SubmitResult.NotFound ||
5370
+ error.result === SubmitResult.NotAdmitted ||
5371
+ error.result === SubmitResult.Backpressured;
5287
5372
  }
5288
5373
 
5289
5374
  function remainingDeadlineMs(deadlineUnixMs: bigint): number {
@@ -5302,9 +5387,8 @@ function userSpotOperationFingerprint(
5302
5387
  record: ServiceUserSpotCreateRecord | ServiceUserSpotCloseRecord | ServiceActorCreateRecord
5303
5388
  ): string {
5304
5389
  const { correlation: _correlation, ...semantic } = record;
5305
- return JSON.stringify(
5306
- semantic,
5307
- (_key, value: unknown) => typeof value === 'bigint' ? `${value}n` : value
5390
+ return JSON.stringify(semantic, (_key, value: unknown) =>
5391
+ typeof value === 'bigint' ? `${value}n` : value
5308
5392
  );
5309
5393
  }
5310
5394
 
@@ -5339,32 +5423,44 @@ function actorKey(actor: ServiceActorRef): string {
5339
5423
  }
5340
5424
 
5341
5425
  function sameSessionBinding(left: ServiceSessionBinding, right: ServiceSessionBinding): boolean {
5342
- return sameActorRef(left.actor, right.actor)
5343
- && left.sessionRid === right.sessionRid
5344
- && sameSessionOwnerIdentity(left, right)
5345
- && left.bindingGeneration === right.bindingGeneration;
5426
+ return (
5427
+ sameActorRef(left.actor, right.actor) &&
5428
+ left.sessionRid === right.sessionRid &&
5429
+ sameSessionOwnerIdentity(left, right) &&
5430
+ left.bindingGeneration === right.bindingGeneration
5431
+ );
5346
5432
  }
5347
5433
 
5348
5434
  function sameSessionIdentity(left: ServiceSessionBinding, right: ServiceSessionBinding): boolean {
5349
- return sameActorRef(left.actor, right.actor)
5350
- && left.sessionRid === right.sessionRid
5351
- && sameSessionOwnerIdentity(left, right);
5435
+ return (
5436
+ sameActorRef(left.actor, right.actor) &&
5437
+ left.sessionRid === right.sessionRid &&
5438
+ sameSessionOwnerIdentity(left, right)
5439
+ );
5352
5440
  }
5353
5441
 
5354
5442
  function sameSessionOwnerIdentity(
5355
5443
  left: Pick<
5356
5444
  ServiceSessionBinding,
5357
- 'sessionOwnerNodeRid' | 'sessionOwnerNodeGeneration' | 'sessionOwnerId' | 'sessionOwnerLeaseGeneration'
5445
+ | 'sessionOwnerNodeRid'
5446
+ | 'sessionOwnerNodeGeneration'
5447
+ | 'sessionOwnerId'
5448
+ | 'sessionOwnerLeaseGeneration'
5358
5449
  >,
5359
5450
  right: Pick<
5360
5451
  ServiceSessionBinding,
5361
- 'sessionOwnerNodeRid' | 'sessionOwnerNodeGeneration' | 'sessionOwnerId' | 'sessionOwnerLeaseGeneration'
5452
+ | 'sessionOwnerNodeRid'
5453
+ | 'sessionOwnerNodeGeneration'
5454
+ | 'sessionOwnerId'
5455
+ | 'sessionOwnerLeaseGeneration'
5362
5456
  >
5363
5457
  ): boolean {
5364
- return left.sessionOwnerNodeRid === right.sessionOwnerNodeRid
5365
- && left.sessionOwnerNodeGeneration === right.sessionOwnerNodeGeneration
5366
- && left.sessionOwnerId === right.sessionOwnerId
5367
- && left.sessionOwnerLeaseGeneration === right.sessionOwnerLeaseGeneration;
5458
+ return (
5459
+ left.sessionOwnerNodeRid === right.sessionOwnerNodeRid &&
5460
+ left.sessionOwnerNodeGeneration === right.sessionOwnerNodeGeneration &&
5461
+ left.sessionOwnerId === right.sessionOwnerId &&
5462
+ left.sessionOwnerLeaseGeneration === right.sessionOwnerLeaseGeneration
5463
+ );
5368
5464
  }
5369
5465
 
5370
5466
  function requireSessionOwnerIdentity(binding: ServiceSessionBinding): {
@@ -5373,9 +5469,9 @@ function requireSessionOwnerIdentity(binding: ServiceSessionBinding): {
5373
5469
  readonly leaseGeneration: bigint;
5374
5470
  } {
5375
5471
  if (
5376
- binding.sessionOwnerNodeGeneration === undefined
5377
- || binding.sessionOwnerId === undefined
5378
- || binding.sessionOwnerLeaseGeneration === undefined
5472
+ binding.sessionOwnerNodeGeneration === undefined ||
5473
+ binding.sessionOwnerId === undefined ||
5474
+ binding.sessionOwnerLeaseGeneration === undefined
5379
5475
  ) {
5380
5476
  throw new ServiceWireProtocolError(
5381
5477
  `Session binding '${binding.sessionRid}' omits its owner lifecycle identity.`
@@ -5388,47 +5484,55 @@ function requireSessionOwnerIdentity(binding: ServiceSessionBinding): {
5388
5484
  };
5389
5485
  }
5390
5486
 
5391
- function sessionDeliveryKey(binding: Pick<
5392
- ServiceSessionBinding,
5393
- | 'actor'
5394
- | 'sessionRid'
5395
- | 'sessionOwnerNodeRid'
5396
- | 'sessionOwnerNodeGeneration'
5397
- | 'sessionOwnerId'
5398
- | 'sessionOwnerLeaseGeneration'
5399
- | 'bindingGeneration'
5400
- >): string {
5401
- return `${actorKey(binding.actor)}\0${binding.sessionOwnerNodeRid}\0${binding.sessionRid}`
5402
- + `\0${binding.sessionOwnerNodeGeneration ?? ''}`
5403
- + `\0${binding.sessionOwnerId ?? ''}`
5404
- + `\0${binding.sessionOwnerLeaseGeneration ?? ''}`
5405
- + `\0${binding.bindingGeneration}`;
5487
+ function sessionDeliveryKey(
5488
+ binding: Pick<
5489
+ ServiceSessionBinding,
5490
+ | 'actor'
5491
+ | 'sessionRid'
5492
+ | 'sessionOwnerNodeRid'
5493
+ | 'sessionOwnerNodeGeneration'
5494
+ | 'sessionOwnerId'
5495
+ | 'sessionOwnerLeaseGeneration'
5496
+ | 'bindingGeneration'
5497
+ >
5498
+ ): string {
5499
+ return (
5500
+ `${actorKey(binding.actor)}\0${binding.sessionOwnerNodeRid}\0${binding.sessionRid}` +
5501
+ `\0${binding.sessionOwnerNodeGeneration ?? ''}` +
5502
+ `\0${binding.sessionOwnerId ?? ''}` +
5503
+ `\0${binding.sessionOwnerLeaseGeneration ?? ''}` +
5504
+ `\0${binding.bindingGeneration}`
5505
+ );
5406
5506
  }
5407
5507
 
5408
5508
  function exactRetiredDelivery(
5409
5509
  binding: ServiceSessionBinding,
5410
5510
  retired: ServiceRetiredBoundSessionRouteFence
5411
5511
  ): boolean {
5412
- return binding.sessionRid === retired.sessionRid
5413
- && binding.sessionOwnerNodeRid === retired.sessionOwnerNodeRid
5414
- && binding.sessionOwnerNodeGeneration === retired.sessionOwnerNodeGeneration
5415
- && binding.sessionOwnerId === retired.sessionOwnerId
5416
- && binding.sessionOwnerLeaseGeneration === retired.sessionOwnerLeaseGeneration
5417
- && binding.bindingGeneration === retired.retiredBindingGeneration;
5512
+ return (
5513
+ binding.sessionRid === retired.sessionRid &&
5514
+ binding.sessionOwnerNodeRid === retired.sessionOwnerNodeRid &&
5515
+ binding.sessionOwnerNodeGeneration === retired.sessionOwnerNodeGeneration &&
5516
+ binding.sessionOwnerId === retired.sessionOwnerId &&
5517
+ binding.sessionOwnerLeaseGeneration === retired.sessionOwnerLeaseGeneration &&
5518
+ binding.bindingGeneration === retired.retiredBindingGeneration
5519
+ );
5418
5520
  }
5419
5521
 
5420
5522
  function replacementNoticeKey(
5421
5523
  record: Extract<ServiceStatefulWireRecord, { readonly kind: 'boundSessionReplaced' }>
5422
5524
  ): string {
5423
- return `${actorKey(record.actorAuthority.actor)}\0${record.retiredSession.sessionOwnerNodeRid}`
5424
- + `\0${record.actorAuthority.targetNodeGeneration}`
5425
- + `\0${record.actorAuthority.authorityOwnerGeneration}`
5426
- + `\0${record.actorAuthority.ownerLeaseGeneration}`
5427
- + `\0${record.retiredSession.sessionOwnerNodeGeneration}`
5428
- + `\0${record.retiredSession.sessionOwnerId}`
5429
- + `\0${record.retiredSession.sessionOwnerLeaseGeneration}`
5430
- + `\0${record.retiredSession.sessionRid}`
5431
- + `\0${record.retiredSession.retiredBindingGeneration}`;
5525
+ return (
5526
+ `${actorKey(record.actorAuthority.actor)}\0${record.retiredSession.sessionOwnerNodeRid}` +
5527
+ `\0${record.actorAuthority.targetNodeGeneration}` +
5528
+ `\0${record.actorAuthority.authorityOwnerGeneration}` +
5529
+ `\0${record.actorAuthority.ownerLeaseGeneration}` +
5530
+ `\0${record.retiredSession.sessionOwnerNodeGeneration}` +
5531
+ `\0${record.retiredSession.sessionOwnerId}` +
5532
+ `\0${record.retiredSession.sessionOwnerLeaseGeneration}` +
5533
+ `\0${record.retiredSession.sessionRid}` +
5534
+ `\0${record.retiredSession.retiredBindingGeneration}`
5535
+ );
5432
5536
  }
5433
5537
 
5434
5538
  function actorAuthorityFromRoute(route: ServiceActorRouteFence): ServiceBoundSessionActorAuthority {
@@ -5449,9 +5553,11 @@ function directSpotKey(spotId: string): string {
5449
5553
  }
5450
5554
 
5451
5555
  function sameActorRef(left: ServiceActorRef, right: ServiceActorRef): boolean {
5452
- return left.nodeRid === right.nodeRid
5453
- && left.actorId === right.actorId
5454
- && left.generation === right.generation;
5556
+ return (
5557
+ left.nodeRid === right.nodeRid &&
5558
+ left.actorId === right.actorId &&
5559
+ left.generation === right.generation
5560
+ );
5455
5561
  }
5456
5562
 
5457
5563
  function sameSpotRef(left: ServiceSpotRef, right: ServiceSpotRef): boolean {
@@ -5468,9 +5574,7 @@ function freezeSpotRoute(route: ServiceSpotRouteFence): ServiceSpotRouteFence {
5468
5574
  });
5469
5575
  }
5470
5576
 
5471
- function freezeDirectSpotRoute(
5472
- route: ServiceDirectSpotRouteFence
5473
- ): ServiceDirectSpotRouteFence {
5577
+ function freezeDirectSpotRoute(route: ServiceDirectSpotRouteFence): ServiceDirectSpotRouteFence {
5474
5578
  return Object.freeze({
5475
5579
  ...freezeSpotRoute(route),
5476
5580
  ownerLeaseGeneration: route.ownerLeaseGeneration,
@@ -5511,39 +5615,48 @@ function matchesExpectedInstanceRoute(
5511
5615
  : current !== undefined && sameInstanceRoute(current, expected);
5512
5616
  }
5513
5617
 
5514
- function sameInstanceRoute(left: ServiceInstanceRouteFence, right: ServiceInstanceRouteFence): boolean {
5515
- return left.targetNodeRid === right.targetNodeRid
5516
- && left.targetNodeGeneration === right.targetNodeGeneration
5517
- && left.targetSpotId === right.targetSpotId
5518
- && left.objectGeneration === right.objectGeneration
5519
- && left.ownerId === right.ownerId
5520
- && left.authorityOwnerGeneration === right.authorityOwnerGeneration
5521
- && left.leaseGeneration === right.leaseGeneration
5522
- && left.storeVersion === right.storeVersion;
5618
+ function sameInstanceRoute(
5619
+ left: ServiceInstanceRouteFence,
5620
+ right: ServiceInstanceRouteFence
5621
+ ): boolean {
5622
+ return (
5623
+ left.targetNodeRid === right.targetNodeRid &&
5624
+ left.targetNodeGeneration === right.targetNodeGeneration &&
5625
+ left.targetSpotId === right.targetSpotId &&
5626
+ left.objectGeneration === right.objectGeneration &&
5627
+ left.ownerId === right.ownerId &&
5628
+ left.authorityOwnerGeneration === right.authorityOwnerGeneration &&
5629
+ left.leaseGeneration === right.leaseGeneration &&
5630
+ left.storeVersion === right.storeVersion
5631
+ );
5523
5632
  }
5524
5633
 
5525
5634
  function sameInstanceOwnerIdentity(
5526
5635
  left: ServiceInstanceRouteFence,
5527
5636
  right: ServiceInstanceRouteFence
5528
5637
  ): boolean {
5529
- return left.targetNodeRid === right.targetNodeRid
5530
- && left.targetNodeGeneration === right.targetNodeGeneration
5531
- && left.targetSpotId === right.targetSpotId
5532
- && left.objectGeneration === right.objectGeneration
5533
- && left.ownerId === right.ownerId
5534
- && left.authorityOwnerGeneration === right.authorityOwnerGeneration
5535
- && left.leaseGeneration === right.leaseGeneration;
5638
+ return (
5639
+ left.targetNodeRid === right.targetNodeRid &&
5640
+ left.targetNodeGeneration === right.targetNodeGeneration &&
5641
+ left.targetSpotId === right.targetSpotId &&
5642
+ left.objectGeneration === right.objectGeneration &&
5643
+ left.ownerId === right.ownerId &&
5644
+ left.authorityOwnerGeneration === right.authorityOwnerGeneration &&
5645
+ left.leaseGeneration === right.leaseGeneration
5646
+ );
5536
5647
  }
5537
5648
 
5538
5649
  function sameInstanceApplicationOwner(
5539
5650
  left: ServiceInstanceRouteFence,
5540
5651
  right: ServiceInstanceRouteFence
5541
5652
  ): boolean {
5542
- return left.targetNodeRid === right.targetNodeRid
5543
- && left.targetNodeGeneration === right.targetNodeGeneration
5544
- && left.targetSpotId === right.targetSpotId
5545
- && left.ownerId === right.ownerId
5546
- && left.leaseGeneration === right.leaseGeneration;
5653
+ return (
5654
+ left.targetNodeRid === right.targetNodeRid &&
5655
+ left.targetNodeGeneration === right.targetNodeGeneration &&
5656
+ left.targetSpotId === right.targetSpotId &&
5657
+ left.ownerId === right.ownerId &&
5658
+ left.leaseGeneration === right.leaseGeneration
5659
+ );
5547
5660
  }
5548
5661
 
5549
5662
  function matchesExpectedDirectSpotRoute(
@@ -5573,8 +5686,7 @@ function sameDirectSpotRoute(
5573
5686
  left: ServiceDirectSpotRouteFence,
5574
5687
  right: ServiceDirectSpotRouteFence
5575
5688
  ): boolean {
5576
- return sameDirectSpotRouteIdentity(left, right)
5577
- && left.storeVersion === right.storeVersion;
5689
+ return sameDirectSpotRouteIdentity(left, right) && left.storeVersion === right.storeVersion;
5578
5690
  }
5579
5691
 
5580
5692
  function messageFollowSpotRoute(
@@ -5614,31 +5726,34 @@ function sameMessageFollowSpotSource(
5614
5726
  current: ServiceDirectSpotRouteFence,
5615
5727
  source: Extract<ServiceMessageFollowRoute, { readonly kind: 'spot' }>
5616
5728
  ): boolean {
5617
- return current.spot.spotId === source.spot.spotId
5618
- && current.spot.generation === source.spot.generation
5619
- && current.targetNodeRid === source.targetNodeRid
5620
- && current.targetNodeGeneration === source.targetNodeGeneration
5621
- && current.authorityOwnerGeneration === source.authorityOwnerGeneration
5622
- && current.ownerLeaseGeneration === source.ownerLeaseGeneration;
5729
+ return (
5730
+ current.spot.spotId === source.spot.spotId &&
5731
+ current.spot.generation === source.spot.generation &&
5732
+ current.targetNodeRid === source.targetNodeRid &&
5733
+ current.targetNodeGeneration === source.targetNodeGeneration &&
5734
+ current.authorityOwnerGeneration === source.authorityOwnerGeneration &&
5735
+ current.ownerLeaseGeneration === source.ownerLeaseGeneration
5736
+ );
5623
5737
  }
5624
5738
 
5625
5739
  function sameDirectSpotRouteIdentity(
5626
5740
  left: ServiceDirectSpotRouteFence,
5627
5741
  right: ServiceDirectSpotRouteFence
5628
5742
  ): boolean {
5629
- return sameDirectSpotOwnerIdentity(left, right)
5630
- && left.spot.generation === right.spot.generation;
5743
+ return sameDirectSpotOwnerIdentity(left, right) && left.spot.generation === right.spot.generation;
5631
5744
  }
5632
5745
 
5633
5746
  function sameDirectSpotOwnerIdentity(
5634
5747
  left: ServiceDirectSpotRouteFence,
5635
5748
  right: ServiceDirectSpotRouteFence
5636
5749
  ): boolean {
5637
- return left.spot.spotId === right.spot.spotId
5638
- && left.targetNodeRid === right.targetNodeRid
5639
- && left.targetNodeGeneration === right.targetNodeGeneration
5640
- && left.authorityOwnerGeneration === right.authorityOwnerGeneration
5641
- && left.ownerLeaseGeneration === right.ownerLeaseGeneration;
5750
+ return (
5751
+ left.spot.spotId === right.spot.spotId &&
5752
+ left.targetNodeRid === right.targetNodeRid &&
5753
+ left.targetNodeGeneration === right.targetNodeGeneration &&
5754
+ left.authorityOwnerGeneration === right.authorityOwnerGeneration &&
5755
+ left.ownerLeaseGeneration === right.ownerLeaseGeneration
5756
+ );
5642
5757
  }
5643
5758
 
5644
5759
  function routeMatchesLocal(
@@ -5647,25 +5762,34 @@ function routeMatchesLocal(
5647
5762
  nodeRid: string,
5648
5763
  nodeGeneration: bigint
5649
5764
  ): boolean {
5650
- return route.targetNodeRid === nodeRid
5651
- && route.targetNodeGeneration === nodeGeneration
5652
- && route.targetSpotId === spot.ref.spotId
5653
- && route.objectGeneration === spot.ref.generation
5654
- && route.authorityOwnerGeneration === spot.authorityOwnerGeneration;
5765
+ return (
5766
+ route.targetNodeRid === nodeRid &&
5767
+ route.targetNodeGeneration === nodeGeneration &&
5768
+ route.targetSpotId === spot.ref.spotId &&
5769
+ route.objectGeneration === spot.ref.generation &&
5770
+ route.authorityOwnerGeneration === spot.authorityOwnerGeneration
5771
+ );
5655
5772
  }
5656
5773
 
5657
5774
  function instanceOperationKey(
5658
5775
  record: Extract<ServiceStatefulWireRecord, { readonly kind: 'instanceSpot' }>
5659
5776
  ): string {
5660
- return `${record.sourceNodeRid}\0${record.sourceNodeGeneration}\0`
5661
- + `${record.operation.high}\0${record.operation.low}`;
5777
+ return (
5778
+ `${record.sourceNodeRid}\0${record.sourceNodeGeneration}\0` +
5779
+ `${record.operation.high}\0${record.operation.low}`
5780
+ );
5662
5781
  }
5663
5782
 
5664
5783
  function instanceActivationKey(
5665
- record: Extract<ServiceStatefulWireRecord, { readonly kind: 'instanceSpot'; readonly activation: 'missing' }>
5784
+ record: Extract<
5785
+ ServiceStatefulWireRecord,
5786
+ { readonly kind: 'instanceSpot'; readonly activation: 'missing' }
5787
+ >
5666
5788
  ): string {
5667
- return `${record.target.targetNodeRid}\0${record.target.targetNodeGeneration}\0`
5668
- + `${record.target.targetSpotId}\0${record.target.stableType}`;
5789
+ return (
5790
+ `${record.target.targetNodeRid}\0${record.target.targetNodeGeneration}\0` +
5791
+ `${record.target.targetSpotId}\0${record.target.stableType}`
5792
+ );
5669
5793
  }
5670
5794
 
5671
5795
  function subscriptionKey(channelName: string, topicFilter: string): string {
@@ -5694,10 +5818,9 @@ function emptyPayload(): ServiceApplicationPayload {
5694
5818
  * the stateful mailbox's internal record shape as an adapter only; it must
5695
5819
  * not re-parse the canonical bytes with the legacy hand-written decoder.
5696
5820
  */
5697
- function statefulActorJoinFromCanonical(value: ActorJoin28): Extract<
5698
- ServiceStatefulWireRecord,
5699
- { readonly kind: 'actorJoin' }
5700
- > {
5821
+ function statefulActorJoinFromCanonical(
5822
+ value: ActorJoin28
5823
+ ): Extract<ServiceStatefulWireRecord, { readonly kind: 'actorJoin' }> {
5701
5824
  return {
5702
5825
  kind: 'actorJoin',
5703
5826
  correlation: value.correlation,
@@ -5737,13 +5860,11 @@ function instanceOperationParts(
5737
5860
  throw new TypeError('Instance operation requires one header and one payload frame.');
5738
5861
  }
5739
5862
  if (metadataFrame === undefined) return headerAndPayload;
5740
- return [
5741
- headerAndPayload[0]!,
5742
- validateServiceMetadataFrame(metadataFrame),
5743
- headerAndPayload[1]!
5744
- ];
5863
+ return [headerAndPayload[0]!, validateServiceMetadataFrame(metadataFrame), headerAndPayload[1]!];
5745
5864
  }
5746
5865
 
5747
- export function statefulMailboxData(record: ServiceMailboxRecord): ServiceStatefulMailboxData | undefined {
5866
+ export function statefulMailboxData(
5867
+ record: ServiceMailboxRecord
5868
+ ): ServiceStatefulMailboxData | undefined {
5748
5869
  return record.stateful as ServiceStatefulMailboxData | undefined;
5749
5870
  }