@zlink-systems/framework 0.29.1 → 0.30.1

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 (322) hide show
  1. package/LICENSE +150 -68
  2. package/dist/.tsbuildinfo +1 -1
  3. package/dist/contracts/Actors/ZLinkActorClient.d.ts +2 -1
  4. package/dist/contracts/Channels/Calls.d.ts +2 -1
  5. package/dist/contracts/Common/ZLinkMessageMetadata.js +11 -5
  6. package/dist/contracts/Configuration/Builders.d.ts +1 -2
  7. package/dist/contracts/Configuration/Configs.d.ts +0 -5
  8. package/dist/contracts/Configuration/RegistrationBuilders.js +6 -4
  9. package/dist/contracts/Configuration/RegistrationTypes.d.ts +1 -6
  10. package/dist/contracts/Configuration/RegistrationValidators.js +4 -4
  11. package/dist/contracts/Configuration/index.d.ts +1 -1
  12. package/dist/contracts/Handlers/Attributes.d.ts +5 -13
  13. package/dist/contracts/Handlers/Attributes.js +7 -11
  14. package/dist/contracts/Handlers/JsonContract.d.ts +2 -46
  15. package/dist/contracts/Handlers/JsonContract.js +4 -153
  16. package/dist/contracts/Spots/Contracts.d.ts +2 -1
  17. package/dist/internal.d.ts +1 -0
  18. package/dist/internal.js +3 -1
  19. package/dist/nest-integration.d.ts +1 -1
  20. package/dist/nest-integration.js +2 -1
  21. package/dist/runtime/actors/actor-client.d.ts +1 -1
  22. package/dist/runtime/actors/actor-client.js +14 -12
  23. package/dist/runtime/actors/actor-handoff.d.ts +3 -2
  24. package/dist/runtime/actors/actor-handoff.js +15 -7
  25. package/dist/runtime/actors/actor-join-relocation.d.ts +1 -0
  26. package/dist/runtime/actors/actor-local-native-join.js +9 -12
  27. package/dist/runtime/actors/actor-remote-wire.js +15 -0
  28. package/dist/runtime/actors/actor-routed-join-transport.d.ts +6 -2
  29. package/dist/runtime/actors/actor-routed-json-request.d.ts +2 -0
  30. package/dist/runtime/actors/index.d.ts +2 -1
  31. package/dist/runtime/actors/index.js +18 -6
  32. package/dist/runtime/actors/spot-actor-dispatch.js +2 -2
  33. package/dist/runtime/admission.d.ts +1 -1
  34. package/dist/runtime/admission.js +15 -5
  35. package/dist/runtime/application-jobs/application-ingress-record-owner.d.ts +9 -9
  36. package/dist/runtime/application-jobs/application-ingress-record-owner.js +45 -23
  37. package/dist/runtime/application-jobs/application-job-queue-scope.d.ts +5 -2
  38. package/dist/runtime/application-jobs/application-job-queue-scope.js +41 -21
  39. package/dist/runtime/application-jobs/contracts.d.ts +15 -2
  40. package/dist/runtime/backend/contracts/index.d.ts +27 -27
  41. package/dist/runtime/backend/mesh-completion-table.d.ts +15 -5
  42. package/dist/runtime/backend/mesh-completion-table.js +160 -50
  43. package/dist/runtime/backend/mesh-dispatch-pump.d.ts +3 -0
  44. package/dist/runtime/backend/mesh-dispatch-pump.js +53 -36
  45. package/dist/runtime/backend/node/node-backend-adapter-factory.js +6 -1
  46. package/dist/runtime/backend/node/node-backend-adapter-support.d.ts +3 -3
  47. package/dist/runtime/backend/node/node-backend-adapter-support.js +33 -31
  48. package/dist/runtime/backend/node/node-dealer-channel-client-transport.d.ts +1 -1
  49. package/dist/runtime/backend/node/node-dealer-channel-client-transport.js +5 -2
  50. package/dist/runtime/backend/node/node-mesh-backend-adapter.d.ts +1 -9
  51. package/dist/runtime/backend/node/node-mesh-backend-adapter.js +1 -1
  52. package/dist/runtime/backend/node/node-raw-binding-port.js +50 -25
  53. package/dist/runtime/backend/node/node-raw-mesh-backend.d.ts +22 -16
  54. package/dist/runtime/backend/node/node-raw-mesh-backend.js +133 -149
  55. package/dist/runtime/backend/node/node-socket-backend-adapter.js +15 -10
  56. package/dist/runtime/backend/raw-binding-port.d.ts +10 -3
  57. package/dist/runtime/backend/runtime-message.d.ts +1 -0
  58. package/dist/runtime/backend/runtime-message.js +5 -0
  59. package/dist/runtime/backend/runtime-values.d.ts +1 -0
  60. package/dist/runtime/backend/runtime-values.js +2 -1
  61. package/dist/runtime/channels/channel-clients.d.ts +1 -0
  62. package/dist/runtime/channels/channel-clients.js +58 -21
  63. package/dist/runtime/channels/channel-dispatch-pipeline.d.ts +3 -2
  64. package/dist/runtime/channels/channel-dispatch-pipeline.js +20 -11
  65. package/dist/runtime/channels/channel-dispatch-services.d.ts +1 -0
  66. package/dist/runtime/channels/channel-dispatch-services.js +45 -0
  67. package/dist/runtime/channels/channel-dispatchers.d.ts +1 -1
  68. package/dist/runtime/channels/channel-dispatchers.js +27 -26
  69. package/dist/runtime/channels/channel-envelope-inspection.d.ts +1 -2
  70. package/dist/runtime/channels/channel-envelope-inspection.js +1 -16
  71. package/dist/runtime/channels/channel-envelope.d.ts +1 -0
  72. package/dist/runtime/channels/channel-envelope.js +83 -8
  73. package/dist/runtime/channels/channel-outbound-operations.d.ts +2 -2
  74. package/dist/runtime/channels/channel-outbound-operations.js +8 -8
  75. package/dist/runtime/channels/channel-receive-loops.js +3 -3
  76. package/dist/runtime/channels/channel-runtime-lifecycle.js +2 -1
  77. package/dist/runtime/channels/channel-runtime-manager.d.ts +6 -6
  78. package/dist/runtime/channels/channel-runtime-manager.js +12 -12
  79. package/dist/runtime/channels/channel-socket-registry.d.ts +10 -3
  80. package/dist/runtime/channels/channel-socket-registry.js +59 -82
  81. package/dist/runtime/channels/channel-transports.d.ts +18 -15
  82. package/dist/runtime/channels/channel-transports.js +48 -31
  83. package/dist/runtime/channels/local-spot-route-transport.d.ts +1 -1
  84. package/dist/runtime/channels/local-spot-route-transport.js +2 -1
  85. package/dist/runtime/channels/router-socket-spot-route-transport.d.ts +2 -2
  86. package/dist/runtime/channels/router-socket-spot-route-transport.js +4 -4
  87. package/dist/runtime/channels/source-spot-router.d.ts +2 -2
  88. package/dist/runtime/channels/source-spot-router.js +4 -4
  89. package/dist/runtime/channels/spot-node-route-transport.d.ts +2 -2
  90. package/dist/runtime/channels/spot-node-route-transport.js +4 -4
  91. package/dist/runtime/channels/spot-route-bridge-transport.d.ts +2 -2
  92. package/dist/runtime/channels/spot-route-bridge-transport.js +4 -4
  93. package/dist/runtime/channels/spot-route-dispatch-strategy.d.ts +5 -4
  94. package/dist/runtime/channels/spot-route-dispatch-strategy.js +18 -18
  95. package/dist/runtime/diagnostics/message-flow.d.ts +1 -0
  96. package/dist/runtime/diagnostics/message-flow.js +3 -3
  97. package/dist/runtime/execution/serial-execution-queue.d.ts +1 -0
  98. package/dist/runtime/execution/serial-execution-queue.js +1 -0
  99. package/dist/runtime/foundation/actor-join-recovery-codec.js +2 -2
  100. package/dist/runtime/foundation/durable-service-request.d.ts +14 -0
  101. package/dist/runtime/foundation/durable-service-request.js +98 -0
  102. package/dist/runtime/foundation/operation-identity.d.ts +1 -0
  103. package/dist/runtime/foundation/operation-identity.js +5 -1
  104. package/dist/runtime/foundation/raw-service-mesh-runtime.d.ts +37 -6
  105. package/dist/runtime/foundation/raw-service-mesh-runtime.js +473 -220
  106. package/dist/runtime/foundation/service-liveness-registry.d.ts +20 -8
  107. package/dist/runtime/foundation/service-liveness-registry.js +57 -44
  108. package/dist/runtime/foundation/service-mailbox.d.ts +3 -0
  109. package/dist/runtime/foundation/service-mailbox.js +2 -1
  110. package/dist/runtime/foundation/service-relocation-object-owner.d.ts +1 -0
  111. package/dist/runtime/foundation/service-relocation-object-owner.js +1 -0
  112. package/dist/runtime/foundation/service-relocation-runtime.d.ts +2 -0
  113. package/dist/runtime/foundation/service-relocation-runtime.js +13 -1
  114. package/dist/runtime/foundation/service-runtime-contracts.d.ts +2 -0
  115. package/dist/runtime/foundation/service-stateful-runtime.d.ts +10 -9
  116. package/dist/runtime/foundation/service-stateful-runtime.js +78 -126
  117. package/dist/runtime/foundation/service-stateful-wire-codec.d.ts +5 -7
  118. package/dist/runtime/foundation/service-stateful-wire-codec.js +43 -61
  119. package/dist/runtime/foundation/service-topology-registry.d.ts +16 -4
  120. package/dist/runtime/foundation/service-topology-registry.js +69 -30
  121. package/dist/runtime/foundation/service-wire-m6a-codec.d.ts +3 -3
  122. package/dist/runtime/foundation/service-wire-m6a-codec.js +36 -38
  123. package/dist/runtime/handlers/handler-instance-scope.d.ts +8 -0
  124. package/dist/runtime/handlers/handler-instance-scope.js +54 -11
  125. package/dist/runtime/host/actor-packet-relay.js +7 -7
  126. package/dist/runtime/host/actor-runtime-options-factory.js +2 -2
  127. package/dist/runtime/host/application-job-queue.d.ts +28 -9
  128. package/dist/runtime/host/application-job-queue.js +214 -50
  129. package/dist/runtime/host/entry-actor-runtime.d.ts +1 -0
  130. package/dist/runtime/host/entry-actor-runtime.js +4 -1
  131. package/dist/runtime/host/index.d.ts +7 -1
  132. package/dist/runtime/host/index.js +154 -126
  133. package/dist/runtime/host/instance-activation-authority.d.ts +2 -1
  134. package/dist/runtime/host/instance-activation-authority.js +89 -25
  135. package/dist/runtime/host/remote-bound-session-relay.js +2 -18
  136. package/dist/runtime/host/route-mesh-runtime.js +1 -1
  137. package/dist/runtime/host/service-relocation-control.d.ts +1 -0
  138. package/dist/runtime/host/service-relocation-control.js +10 -4
  139. package/dist/runtime/host/service-relocation-host-runtime.d.ts +6 -8
  140. package/dist/runtime/host/service-relocation-host-runtime.js +215 -243
  141. package/dist/runtime/host/spot-address-transport.d.ts +1 -0
  142. package/dist/runtime/host/spot-address-transport.js +28 -14
  143. package/dist/runtime/host/spot-runtime-options-factory.js +3 -2
  144. package/dist/runtime/host/user-spot-creation-coordinator.d.ts +1 -0
  145. package/dist/runtime/host/user-spot-creation-coordinator.js +1 -0
  146. package/dist/runtime/locations/actor-location-claims.d.ts +2 -2
  147. package/dist/runtime/locations/actor-location-claims.js +34 -19
  148. package/dist/runtime/locations/domain-store-contract.d.ts +2 -2
  149. package/dist/runtime/locations/in-memory-authority-store.d.ts +4 -2
  150. package/dist/runtime/locations/in-memory-authority-store.js +80 -8
  151. package/dist/runtime/locations/in-memory-location-store.d.ts +2 -2
  152. package/dist/runtime/locations/in-memory-location-store.js +19 -3
  153. package/dist/runtime/locations/internal-location-contracts.d.ts +3 -0
  154. package/dist/runtime/locations/lifecycle.d.ts +1 -2
  155. package/dist/runtime/locations/lifecycle.js +2 -5
  156. package/dist/runtime/locations/location-store-repository.d.ts +3 -2
  157. package/dist/runtime/locations/location-store-repository.js +165 -22
  158. package/dist/runtime/locations/resolvers.d.ts +2 -1
  159. package/dist/runtime/locations/resolvers.js +10 -1
  160. package/dist/runtime/locations/runtime.d.ts +1 -1
  161. package/dist/runtime/locations/runtime.js +24 -23
  162. package/dist/runtime/messaging/framework-json-v1.d.ts +4 -6
  163. package/dist/runtime/messaging/framework-json-v1.js +38 -294
  164. package/dist/runtime/messaging/packet-name.d.ts +1 -1
  165. package/dist/runtime/messaging/packet-name.js +8 -24
  166. package/dist/runtime/messaging/request-result.d.ts +2 -0
  167. package/dist/runtime/messaging/request-result.js +54 -0
  168. package/dist/runtime/messaging/submission-result.d.ts +2 -1
  169. package/dist/runtime/messaging/submission-result.js +7 -4
  170. package/dist/runtime/protocol/service_wire_codec.generated.d.ts +15 -0
  171. package/dist/runtime/protocol/service_wire_codec.generated.js +144 -0
  172. package/dist/runtime/protocol/service_wire_pilot_codec.generated.d.ts +9 -0
  173. package/dist/runtime/protocol/service_wire_pilot_codec.generated.js +14 -1
  174. package/dist/runtime/spots/formal-remote-actor-admission-registry.d.ts +9 -2
  175. package/dist/runtime/spots/formal-remote-actor-admission-registry.js +33 -19
  176. package/dist/runtime/spots/index.d.ts +7 -3
  177. package/dist/runtime/spots/index.js +23 -16
  178. package/dist/runtime/spots/spot-activation.d.ts +3 -1
  179. package/dist/runtime/spots/spot-activation.js +21 -12
  180. package/dist/runtime/spots/spot-actor-admission-coordinator.d.ts +2 -1
  181. package/dist/runtime/spots/spot-actor-admission-coordinator.js +11 -10
  182. package/dist/runtime/spots/spot-actor-packet-dispatch.d.ts +4 -1
  183. package/dist/runtime/spots/spot-actor-packet-dispatch.js +7 -5
  184. package/dist/runtime/spots/spot-actor-packet-drain.js +2 -0
  185. package/dist/runtime/spots/spot-actor-packet-relay-dispatch.js +1 -0
  186. package/dist/runtime/spots/spot-entry-activation.js +9 -3
  187. package/dist/runtime/spots/spot-handler-registry.d.ts +3 -1
  188. package/dist/runtime/spots/spot-handler-registry.js +18 -8
  189. package/dist/runtime/spots/spot-node-autoconnect.js +4 -3
  190. package/dist/runtime/spots/spot-node-runtime-manager.d.ts +2 -1
  191. package/dist/runtime/spots/spot-node-runtime-manager.js +4 -11
  192. package/dist/runtime/spots/spot-outbound.d.ts +3 -0
  193. package/dist/runtime/spots/spot-outbound.js +24 -15
  194. package/dist/runtime/spots/spot-routed-spot-packet-dispatch.d.ts +1 -0
  195. package/dist/runtime/spots/spot-routed-spot-packet-dispatch.js +1 -1
  196. package/dist/runtime/spots/spot-routing-internal.d.ts +6 -0
  197. package/dist/runtime/spots/spot-runtime-ports.d.ts +3 -1
  198. package/dist/runtime/spots/spot-subscription-dispatch.js +0 -3
  199. package/dist/runtime/spots/spot-timer.js +1 -0
  200. package/dist/runtime/streams/stream-session-runtime.d.ts +1 -1
  201. package/dist/runtime/streams/stream-session-runtime.js +14 -28
  202. package/package.json +3 -3
  203. package/src/contracts/Actors/ZLinkActorClient.ts +2 -1
  204. package/src/contracts/Channels/Calls.ts +2 -1
  205. package/src/contracts/Common/ZLinkMessageMetadata.ts +13 -8
  206. package/src/contracts/Configuration/Builders.ts +1 -2
  207. package/src/contracts/Configuration/Configs.ts +0 -6
  208. package/src/contracts/Configuration/RegistrationBuilders.ts +8 -12
  209. package/src/contracts/Configuration/RegistrationTypes.ts +1 -6
  210. package/src/contracts/Configuration/RegistrationValidators.ts +9 -10
  211. package/src/contracts/Configuration/index.ts +1 -6
  212. package/src/contracts/Handlers/Attributes.ts +14 -21
  213. package/src/contracts/Handlers/JsonContract.ts +8 -216
  214. package/src/contracts/Spots/Contracts.ts +2 -1
  215. package/src/internal.ts +1 -0
  216. package/src/nest-integration.ts +1 -0
  217. package/src/runtime/actors/actor-client.ts +40 -16
  218. package/src/runtime/actors/actor-handoff.ts +22 -8
  219. package/src/runtime/actors/actor-join-relocation.ts +1 -0
  220. package/src/runtime/actors/actor-local-native-join.ts +17 -26
  221. package/src/runtime/actors/actor-remote-wire.ts +17 -0
  222. package/src/runtime/actors/actor-routed-join-transport.ts +14 -4
  223. package/src/runtime/actors/actor-routed-json-request.ts +10 -2
  224. package/src/runtime/actors/index.ts +19 -5
  225. package/src/runtime/actors/spot-actor-dispatch.ts +4 -2
  226. package/src/runtime/admission.ts +18 -5
  227. package/src/runtime/application-jobs/application-ingress-record-owner.ts +53 -27
  228. package/src/runtime/application-jobs/application-job-queue-scope.ts +56 -22
  229. package/src/runtime/application-jobs/contracts.ts +28 -2
  230. package/src/runtime/backend/contracts/index.ts +63 -32
  231. package/src/runtime/backend/mesh-completion-table.ts +175 -59
  232. package/src/runtime/backend/mesh-dispatch-pump.ts +59 -32
  233. package/src/runtime/backend/node/node-backend-adapter-factory.ts +12 -5
  234. package/src/runtime/backend/node/node-backend-adapter-support.ts +42 -31
  235. package/src/runtime/backend/node/node-dealer-channel-client-transport.ts +12 -2
  236. package/src/runtime/backend/node/node-mesh-backend-adapter.ts +3 -10
  237. package/src/runtime/backend/node/node-raw-binding-port.ts +73 -37
  238. package/src/runtime/backend/node/node-raw-mesh-backend.ts +209 -176
  239. package/src/runtime/backend/node/node-socket-backend-adapter.ts +32 -13
  240. package/src/runtime/backend/raw-binding-port.ts +18 -3
  241. package/src/runtime/backend/runtime-message.ts +6 -0
  242. package/src/runtime/backend/runtime-values.ts +1 -0
  243. package/src/runtime/channels/channel-clients.ts +90 -41
  244. package/src/runtime/channels/channel-dispatch-pipeline.ts +69 -34
  245. package/src/runtime/channels/channel-dispatch-services.ts +69 -1
  246. package/src/runtime/channels/channel-dispatchers.ts +29 -27
  247. package/src/runtime/channels/channel-envelope-inspection.ts +2 -16
  248. package/src/runtime/channels/channel-envelope.ts +133 -8
  249. package/src/runtime/channels/channel-outbound-operations.ts +22 -8
  250. package/src/runtime/channels/channel-receive-loops.ts +3 -3
  251. package/src/runtime/channels/channel-runtime-lifecycle.ts +7 -1
  252. package/src/runtime/channels/channel-runtime-manager.ts +29 -12
  253. package/src/runtime/channels/channel-socket-registry.ts +84 -130
  254. package/src/runtime/channels/channel-transports.ts +128 -60
  255. package/src/runtime/channels/local-spot-route-transport.ts +3 -1
  256. package/src/runtime/channels/router-socket-spot-route-transport.ts +13 -4
  257. package/src/runtime/channels/source-spot-router.ts +8 -4
  258. package/src/runtime/channels/spot-node-route-transport.ts +8 -4
  259. package/src/runtime/channels/spot-route-bridge-transport.ts +6 -4
  260. package/src/runtime/channels/spot-route-dispatch-strategy.ts +47 -18
  261. package/src/runtime/diagnostics/message-flow.ts +1 -1
  262. package/src/runtime/execution/serial-execution-queue.ts +2 -0
  263. package/src/runtime/foundation/actor-join-recovery-codec.ts +2 -2
  264. package/src/runtime/foundation/durable-service-request.ts +137 -0
  265. package/src/runtime/foundation/operation-identity.ts +5 -1
  266. package/src/runtime/foundation/raw-service-mesh-runtime.ts +642 -253
  267. package/src/runtime/foundation/service-liveness-registry.ts +68 -59
  268. package/src/runtime/foundation/service-mailbox.ts +7 -1
  269. package/src/runtime/foundation/service-relocation-object-owner.ts +2 -0
  270. package/src/runtime/foundation/service-relocation-runtime.ts +18 -1
  271. package/src/runtime/foundation/service-runtime-contracts.ts +7 -1
  272. package/src/runtime/foundation/service-stateful-runtime.ts +128 -160
  273. package/src/runtime/foundation/service-stateful-wire-codec.ts +55 -84
  274. package/src/runtime/foundation/service-topology-registry.ts +103 -42
  275. package/src/runtime/foundation/service-wire-m6a-codec.ts +57 -38
  276. package/src/runtime/handlers/handler-instance-scope.ts +67 -16
  277. package/src/runtime/host/actor-packet-relay.ts +7 -0
  278. package/src/runtime/host/actor-runtime-options-factory.ts +14 -2
  279. package/src/runtime/host/application-job-queue.ts +249 -48
  280. package/src/runtime/host/entry-actor-runtime.ts +5 -0
  281. package/src/runtime/host/index.ts +224 -160
  282. package/src/runtime/host/instance-activation-authority.ts +132 -27
  283. package/src/runtime/host/remote-bound-session-relay.ts +2 -23
  284. package/src/runtime/host/route-mesh-runtime.ts +1 -1
  285. package/src/runtime/host/service-relocation-control.ts +11 -5
  286. package/src/runtime/host/service-relocation-host-runtime.ts +317 -291
  287. package/src/runtime/host/spot-address-transport.ts +49 -24
  288. package/src/runtime/host/spot-runtime-options-factory.ts +4 -0
  289. package/src/runtime/host/user-spot-creation-coordinator.ts +8 -0
  290. package/src/runtime/locations/actor-location-claims.ts +52 -30
  291. package/src/runtime/locations/domain-store-contract.ts +6 -2
  292. package/src/runtime/locations/in-memory-authority-store.ts +113 -9
  293. package/src/runtime/locations/in-memory-location-store.ts +25 -3
  294. package/src/runtime/locations/internal-location-contracts.ts +4 -0
  295. package/src/runtime/locations/lifecycle.ts +8 -26
  296. package/src/runtime/locations/location-store-repository.ts +220 -15
  297. package/src/runtime/locations/resolvers.ts +25 -2
  298. package/src/runtime/locations/runtime.ts +28 -24
  299. package/src/runtime/messaging/framework-json-v1.ts +5 -325
  300. package/src/runtime/messaging/packet-name.ts +5 -25
  301. package/src/runtime/messaging/request-result.ts +58 -0
  302. package/src/runtime/messaging/submission-result.ts +7 -3
  303. package/src/runtime/protocol/service_wire_codec.generated.ts +131 -1
  304. package/src/runtime/protocol/service_wire_pilot_codec.generated.ts +4 -4
  305. package/src/runtime/spots/formal-remote-actor-admission-registry.ts +45 -23
  306. package/src/runtime/spots/index.ts +30 -2
  307. package/src/runtime/spots/spot-activation.ts +33 -10
  308. package/src/runtime/spots/spot-actor-admission-coordinator.ts +13 -0
  309. package/src/runtime/spots/spot-actor-packet-dispatch.ts +10 -0
  310. package/src/runtime/spots/spot-actor-packet-drain.ts +2 -0
  311. package/src/runtime/spots/spot-actor-packet-relay-dispatch.ts +1 -0
  312. package/src/runtime/spots/spot-entry-activation.ts +12 -2
  313. package/src/runtime/spots/spot-handler-registry.ts +41 -8
  314. package/src/runtime/spots/spot-node-autoconnect.ts +6 -2
  315. package/src/runtime/spots/spot-node-runtime-manager.ts +7 -12
  316. package/src/runtime/spots/spot-outbound.ts +36 -16
  317. package/src/runtime/spots/spot-routed-spot-packet-dispatch.ts +2 -1
  318. package/src/runtime/spots/spot-routing-internal.ts +14 -0
  319. package/src/runtime/spots/spot-runtime-ports.ts +3 -0
  320. package/src/runtime/spots/spot-subscription-dispatch.ts +0 -3
  321. package/src/runtime/spots/spot-timer.ts +5 -1
  322. package/src/runtime/streams/stream-session-runtime.ts +13 -30
@@ -14,6 +14,7 @@ import {
14
14
  encodeInstanceRouteV1,
15
15
  encodeSpotRequestCommand,
16
16
  encodeSpotSendCommand,
17
+ type InstanceRouteV1,
17
18
  type ServiceWireDecoderContext
18
19
  } from '../protocol/service_wire_codec.generated';
19
20
  import {
@@ -82,8 +83,6 @@ import {
82
83
  import { APPLICATION_PAYLOAD_VERSION, ServiceWireProtocolError } from './service-wire-m6a-codec';
83
84
  const MESSAGE_FOLLOW_MAX_BODY_BYTES = 16 * 1024 * 1024;
84
85
  const MESSAGE_FOLLOW_VERSION = 1;
85
- const INSTANCE_ROUTE_VERSION = 1;
86
- const INSTANCE_ACTIVATION_VERSION = 2;
87
86
 
88
87
  const PREFIX_SIZE = SERVICE_WIRE_PREFIX_SIZE;
89
88
  const MAGIC_0 = SERVICE_WIRE_MAGIC[0];
@@ -190,11 +189,6 @@ export interface ServiceMaintenanceRelocationPrepare extends ServiceWireRelocati
190
189
  /** CRC-32C (Castagnoli) over the fully assembled payload bytes. */
191
190
  readonly payloadChecksumCrc32c: number;
192
191
  readonly applicationVersion: bigint;
193
- /** NODE-INTERNAL; serialized as extra frames after canonical command 40. */
194
- readonly nodeInternalBoundSessions?: readonly {
195
- readonly participantKey: string;
196
- readonly payload: Uint8Array;
197
- }[];
198
192
  }
199
193
 
200
194
  export interface ServiceMaintenanceRelocationReady extends ServiceWireRelocationBase {
@@ -946,6 +940,10 @@ export interface ServiceInstanceActivationTarget {
946
940
  readonly descriptorVersion: string;
947
941
  }
948
942
 
943
+ export interface ServiceInstanceColdActivationTarget extends ServiceInstanceActivationTarget {
944
+ readonly targetMeshName: string;
945
+ }
946
+
949
947
  export interface ServiceUserSpotReservationFence {
950
948
  readonly reservationId: string;
951
949
  readonly expectedStoreVersion: string;
@@ -1105,7 +1103,7 @@ export type ServiceStatefulWireRecord =
1105
1103
  | {
1106
1104
  readonly kind: 'instanceSpot';
1107
1105
  readonly activation: 'missing';
1108
- readonly target: ServiceInstanceActivationTarget;
1106
+ readonly target: ServiceInstanceColdActivationTarget;
1109
1107
  readonly sourceNodeGeneration: bigint;
1110
1108
  readonly sourceNodeRid: string;
1111
1109
  readonly sourceSpotId?: string;
@@ -1435,7 +1433,7 @@ export function encodeInstanceSpotHeader(
1435
1433
  }
1436
1434
 
1437
1435
  export function encodeInstanceSpotActivationHeader(
1438
- target: ServiceInstanceActivationTarget,
1436
+ target: ServiceInstanceColdActivationTarget,
1439
1437
  sourceNodeGeneration: bigint,
1440
1438
  sourceNodeRid: string,
1441
1439
  sourceSpotId: string | undefined,
@@ -1454,25 +1452,28 @@ export function encodeInstanceSpotActivationHeader(
1454
1452
  if (operationKind === 'send' && replyRouteId !== undefined) {
1455
1453
  throw new RangeError('Instance Spot send must not carry a reply route.');
1456
1454
  }
1457
- const targetBody = concat(
1458
- rid(target.targetNodeRid, 'targetNodeRid'),
1459
- u64(target.targetNodeGeneration),
1460
- rid(target.targetSpotId, 'targetSpotId'),
1461
- text16(target.stableType, 'stableType'),
1462
- text16(target.descriptorVersion, 'descriptorVersion')
1455
+ const encodedRoute = encodeInstanceRouteV1(
1456
+ {
1457
+ routeKind: 'coldActivation',
1458
+ targetNodeRid: toGeneratedRoutingId(target.targetNodeRid, 'targetNodeRid'),
1459
+ targetNodeGeneration: target.targetNodeGeneration,
1460
+ targetSpotId: target.targetSpotId,
1461
+ targetMeshName: target.targetMeshName,
1462
+ stableType: target.stableType,
1463
+ targetDescriptorVersion: target.descriptorVersion,
1464
+ deadlineUnixMs
1465
+ },
1466
+ STATEFUL_MESSAGE_CONTEXT
1463
1467
  );
1464
1468
  return concat(
1465
1469
  prefix(M6bServiceWireCommand.instanceSpot, hasMetadata ? M6bServiceWireFlag.metadata : 0),
1466
- Buffer.of(INSTANCE_ACTIVATION_VERSION),
1467
- u16(targetBody.byteLength),
1468
- targetBody,
1470
+ encodedRoute,
1469
1471
  u64Any(sourceNodeGeneration),
1470
1472
  rid(sourceNodeRid, 'sourceNodeRid'),
1471
1473
  optionalRid(sourceSpotId),
1472
1474
  Buffer.of(operationKind === 'send' ? 1 : 2),
1473
1475
  u64Any(operation.high),
1474
1476
  u64Any(operation.low),
1475
- u64(deadlineUnixMs),
1476
1477
  ...(operationKind === 'request' ? [u64(requirePositive(replyRouteId, 'replyRouteId'))] : [])
1477
1478
  );
1478
1479
  }
@@ -1741,53 +1742,31 @@ export function decodeStatefulHeader(
1741
1742
  fail(`Invalid command flags '${command.flags}'.`);
1742
1743
  }
1743
1744
  const routeStart = reader.offset;
1744
- const version = reader.u8('instanceRoute.version');
1745
- if (version !== INSTANCE_ROUTE_VERSION && version !== INSTANCE_ACTIVATION_VERSION)
1746
- fail('Unsupported Instance route version.');
1745
+ reader.u8('instanceRoute.kind');
1747
1746
  const routeLength = reader.u16('instanceRoute.length');
1748
1747
  const routeEnd = reader.offset + routeLength;
1749
- const generatedReadyRoute =
1750
- version === INSTANCE_ROUTE_VERSION
1751
- ? decodeInstanceRouteV1(
1752
- reader.bytes.subarray(routeStart, routeEnd),
1753
- STATEFUL_MESSAGE_CONTEXT
1754
- )
1755
- : undefined;
1756
- if (generatedReadyRoute !== undefined && generatedReadyRoute.routeKind !== 'ready') {
1757
- fail('Invalid Ready Instance route kind.');
1758
- }
1759
- const commonTarget =
1760
- generatedReadyRoute?.routeKind === 'ready'
1761
- ? {
1762
- targetNodeRid: fromGeneratedRoutingId(
1763
- generatedReadyRoute.targetNodeRid,
1764
- 'targetNodeRid'
1765
- ),
1766
- targetNodeGeneration: generatedReadyRoute.targetNodeGeneration,
1767
- targetSpotId: generatedReadyRoute.targetSpotId
1768
- }
1769
- : {
1770
- targetNodeRid: reader.rid('targetNodeRid'),
1771
- targetNodeGeneration: reader.nonZeroU64('targetNodeGeneration'),
1772
- targetSpotId: reader.rid('targetSpotId')
1773
- };
1774
- const route: ServiceInstanceRouteFence | undefined =
1775
- generatedReadyRoute?.routeKind === 'ready'
1776
- ? {
1777
- ...commonTarget,
1778
- ...generatedReadyRoute.authority
1779
- }
1748
+ const generatedRoute = decodeCanonicalInstanceRoute(
1749
+ reader.bytes.subarray(routeStart, routeEnd)
1750
+ );
1751
+ const commonTarget = {
1752
+ targetNodeRid: fromGeneratedRoutingId(generatedRoute.targetNodeRid, 'targetNodeRid'),
1753
+ targetNodeGeneration: generatedRoute.targetNodeGeneration,
1754
+ targetSpotId: generatedRoute.targetSpotId
1755
+ };
1756
+ const route =
1757
+ generatedRoute.routeKind === 'ready'
1758
+ ? { ...commonTarget, ...generatedRoute.authority }
1780
1759
  : undefined;
1781
- const target: ServiceInstanceActivationTarget | undefined =
1782
- version === INSTANCE_ACTIVATION_VERSION
1760
+ const target =
1761
+ generatedRoute.routeKind === 'coldActivation'
1783
1762
  ? {
1784
1763
  ...commonTarget,
1785
- stableType: reader.text16('stableType'),
1786
- descriptorVersion: reader.text16('descriptorVersion')
1764
+ targetMeshName: generatedRoute.targetMeshName,
1765
+ stableType: generatedRoute.stableType,
1766
+ descriptorVersion: generatedRoute.targetDescriptorVersion
1787
1767
  }
1788
1768
  : undefined;
1789
- if (generatedReadyRoute !== undefined) reader.offset = routeEnd;
1790
- if (reader.offset !== routeEnd) fail('Invalid Instance route body length.');
1769
+ reader.offset = routeEnd;
1791
1770
  const sourceNodeGeneration = reader.nonZeroU64('sourceNodeGeneration');
1792
1771
  const sourceNodeRid = reader.rid('sourceNodeRid');
1793
1772
  const sourceSpotId = reader.optionalRid('sourceSpotId');
@@ -1799,21 +1778,21 @@ export function decodeStatefulHeader(
1799
1778
  };
1800
1779
  const operationKind = operationValue === 1 ? ('send' as const) : ('request' as const);
1801
1780
  if (
1802
- version === INSTANCE_ROUTE_VERSION &&
1781
+ generatedRoute.routeKind === 'ready' &&
1803
1782
  ((operationKind === 'send' && (operation.high !== 0n || operation.low !== 0n)) ||
1804
1783
  (operationKind === 'request' && operation.high === 0n && operation.low === 0n))
1805
1784
  ) {
1806
1785
  fail('Invalid Instance operation identity.');
1807
1786
  }
1808
1787
  if (
1809
- version === INSTANCE_ACTIVATION_VERSION &&
1788
+ generatedRoute.routeKind === 'coldActivation' &&
1810
1789
  operation.high === 0n &&
1811
1790
  operation.low === 0n
1812
1791
  ) {
1813
1792
  fail('Instance activation requires a non-zero operation identity.');
1814
1793
  }
1815
1794
  const deadlineUnixMs =
1816
- version === INSTANCE_ACTIVATION_VERSION ? reader.nonZeroU64('deadlineUnixMs') : undefined;
1795
+ generatedRoute.routeKind === 'coldActivation' ? generatedRoute.deadlineUnixMs : undefined;
1817
1796
  const replyRouteId =
1818
1797
  operationKind === 'request' ? reader.nonZeroU64('replyRouteId') : undefined;
1819
1798
  reader.end();
@@ -1826,12 +1805,12 @@ export function decodeStatefulHeader(
1826
1805
  operation,
1827
1806
  ...(replyRouteId === undefined ? {} : { replyRouteId })
1828
1807
  };
1829
- return version === INSTANCE_ROUTE_VERSION
1808
+ return generatedRoute.routeKind === 'ready'
1830
1809
  ? {
1831
1810
  ...common,
1832
1811
  activation: 'ready',
1833
1812
  route: route!,
1834
- instanceIntent: generatedReadyRoute!.instanceIntent === 'true'
1813
+ instanceIntent: generatedRoute.instanceIntent === 'true'
1835
1814
  }
1836
1815
  : {
1837
1816
  ...common,
@@ -2387,11 +2366,6 @@ function text8(value: string, name: string): Buffer {
2387
2366
  return sized8(value, name);
2388
2367
  }
2389
2368
 
2390
- function text16(value: string, name: string): Buffer {
2391
- const bytes = encodeCanonicalServiceWireText(value, name, 0xffff, outOfRange);
2392
- return concat(u16(bytes.byteLength), bytes);
2393
- }
2394
-
2395
2369
  function optionalRid(value: string | undefined): Buffer {
2396
2370
  return value === undefined ? Buffer.of(0) : rid(value, 'sourceSpotId');
2397
2371
  }
@@ -2448,6 +2422,15 @@ function concat(...parts: readonly Uint8Array[]): Buffer {
2448
2422
  return Buffer.concat(parts.map((part) => Buffer.from(part)));
2449
2423
  }
2450
2424
 
2425
+ function decodeCanonicalInstanceRoute(bytes: Uint8Array): InstanceRouteV1 {
2426
+ try {
2427
+ return decodeInstanceRouteV1(bytes, STATEFUL_MESSAGE_CONTEXT);
2428
+ } catch (error) {
2429
+ if (error instanceof RangeError) throw new ServiceWireProtocolError(error.message);
2430
+ throw error;
2431
+ }
2432
+ }
2433
+
2451
2434
  function fail(message: string): never {
2452
2435
  throw new ServiceWireProtocolError(message);
2453
2436
  }
@@ -3093,21 +3076,9 @@ class FrozenReader {
3093
3076
 
3094
3077
  private instanceRoute(): void {
3095
3078
  const start = this.offset;
3096
- const kind = this.u8('instanceRouteKind');
3097
- if (kind < 1 || kind > 2) fail('Invalid Instance route kind.');
3098
- const body = this.body16('Instance route');
3099
- if (kind === INSTANCE_ROUTE_VERSION) {
3100
- decodeInstanceRouteV1(this.bytes.subarray(start, this.offset), STATEFUL_MESSAGE_CONTEXT);
3101
- return;
3102
- }
3103
- body.rid8('targetNodeRid');
3104
- body.nonZeroU64('targetNodeGeneration');
3105
- body.text8('targetSpotId');
3106
- body.text8('targetMeshName');
3107
- body.text8('stableType');
3108
- body.text8('targetDescriptorVersion');
3109
- body.nonZeroU64('deadlineUnixMs');
3110
- body.end('Instance route');
3079
+ this.u8('instanceRouteKind');
3080
+ this.body16('Instance route');
3081
+ decodeCanonicalInstanceRoute(this.bytes.subarray(start, this.offset));
3111
3082
  }
3112
3083
 
3113
3084
  private relocationObject(): void {
@@ -1,4 +1,5 @@
1
1
  import { ZLINK_MAX_IDENTITY_TEXT_BYTES } from '../../contracts/Common/CoreTypes';
2
+ import type { ServiceLivenessConnection } from './service-liveness-registry';
2
3
  import {
3
4
  ZLINK_MAX_PUBLIC_WEIGHT,
4
5
  isValidCapacity,
@@ -7,7 +8,10 @@ import {
7
8
  } from '../../contracts/Configuration/RegistrationBuilderPolicy';
8
9
  import { descriptorConnectionNotRequired } from './route-mesh-connection-policy';
9
10
  import { SmoothWeightedSelection } from './service-weighted-selection';
10
- import { SERVICE_WIRE_REQUIRED_CAPABILITY } from './service-wire-constants.generated';
11
+ import {
12
+ SERVICE_WIRE_REQUIRED_CAPABILITY,
13
+ ServiceWireCommand
14
+ } from './service-wire-constants.generated';
11
15
 
12
16
  export type ServiceNodeState =
13
17
  'preparing' | 'serving' | 'retiring' | 'draining' | 'stopped' | 'error';
@@ -39,11 +43,18 @@ export interface ServiceNodeDescriptor {
39
43
  readonly pendingCapacityUsed: number;
40
44
  }
41
45
 
42
- export interface AdmittedServicePeer {
46
+ interface ServiceRouteAdmission {
43
47
  readonly descriptor: ServiceNodeDescriptor;
48
+ readonly descriptorBytes?: Uint8Array;
49
+ readonly connectionId?: string | bigint;
50
+ readonly remoteAdmitReceived?: boolean;
51
+ }
52
+
53
+ export interface AdmittedServicePeer extends ServiceRouteAdmission {
44
54
  // The Core selected-route generation this admission belongs to (Core ROUTER
45
55
  // §10.1), as an opaque token compared only for equality.
46
- readonly connectionId: string;
56
+ readonly connectionId: string | bigint;
57
+ readonly liveness?: ServiceLivenessConnection;
47
58
  }
48
59
 
49
60
  export interface ServicePeerAdmissionExpectation {
@@ -67,7 +78,7 @@ interface ServiceSelectionCacheEntry {
67
78
  export class ServiceTopologyRegistry {
68
79
  private local: ServiceNodeDescriptor;
69
80
  private readonly peersByRid = new Map<string, AdmittedServicePeer>();
70
- private readonly notRequiredByRid = new Map<string, ServiceNodeDescriptor>();
81
+ private readonly notRequiredByRid = new Map<string, ServiceRouteAdmission>();
71
82
  private readonly knownByRid = new Map<string, ServiceNodeDescriptor>();
72
83
  private readonly selections = new Map<string, ServiceSelectionCacheEntry>();
73
84
 
@@ -94,7 +105,7 @@ export class ServiceTopologyRegistry {
94
105
  }
95
106
  this.local = cloneDescriptor(descriptor);
96
107
  for (const [nodeRoutingId, remote] of this.notRequiredByRid) {
97
- if (!descriptorConnectionNotRequired(this.local, remote)) {
108
+ if (!descriptorConnectionNotRequired(this.local, remote.descriptor)) {
98
109
  this.notRequiredByRid.delete(nodeRoutingId);
99
110
  }
100
111
  }
@@ -103,12 +114,16 @@ export class ServiceTopologyRegistry {
103
114
 
104
115
  admit(
105
116
  descriptor: ServiceNodeDescriptor,
106
- connectionId: string,
107
- expected?: ServicePeerAdmissionExpectation
117
+ connectionId: string | bigint,
118
+ expected?: ServicePeerAdmissionExpectation,
119
+ admitLiveness?: () => ServiceLivenessConnection,
120
+ command: number = ServiceWireCommand.hello,
121
+ descriptorBytes?: Uint8Array
108
122
  ): PeerAdmissionResult {
109
123
  try {
110
124
  validateDescriptor(descriptor);
111
- requireText(connectionId, 'connectionId');
125
+ if (typeof connectionId === 'string') requireText(connectionId, 'connectionId');
126
+ else if (connectionId === 0n) throw new TypeError('connectionId must be nonzero.');
112
127
  } catch (error) {
113
128
  return 'invalidDescriptor';
114
129
  }
@@ -123,45 +138,62 @@ export class ServiceTopologyRegistry {
123
138
  ) {
124
139
  return 'invalidDescriptor';
125
140
  }
141
+ const current = this.peersByRid.get(descriptor.nodeRoutingId);
142
+ const previous = current ?? this.notRequiredByRid.get(descriptor.nodeRoutingId);
143
+ const receivedAdmit =
144
+ command === ServiceWireCommand.admit ||
145
+ (previous?.connectionId === connectionId && previous.remoteAdmitReceived === true);
146
+ if (
147
+ previous !== undefined &&
148
+ previous.descriptor.lifecycleGeneration === descriptor.lifecycleGeneration
149
+ ) {
150
+ const existing = previous.descriptor;
151
+ if (
152
+ descriptor.descriptorRevision < existing.descriptorRevision ||
153
+ (descriptor.descriptorRevision === existing.descriptorRevision &&
154
+ !(previous.descriptorBytes !== undefined && descriptorBytes !== undefined
155
+ ? Buffer.compare(previous.descriptorBytes, descriptorBytes) === 0
156
+ : sameServiceNodeDescriptor(existing, descriptor))) ||
157
+ (descriptor.descriptorRevision > existing.descriptorRevision &&
158
+ command !== ServiceWireCommand.update)
159
+ )
160
+ return 'staleDescriptor';
161
+ if (
162
+ descriptor.descriptorRevision > existing.descriptorRevision &&
163
+ !sameImmutableDescriptor(existing, descriptor)
164
+ )
165
+ return 'invalidDescriptor';
166
+ } else if (command === ServiceWireCommand.update) {
167
+ return 'staleDescriptor';
168
+ }
169
+ const admission: ServiceRouteAdmission = {
170
+ descriptor: cloneDescriptor(descriptor),
171
+ ...(descriptorBytes === undefined ? {} : { descriptorBytes: Buffer.from(descriptorBytes) }),
172
+ connectionId,
173
+ remoteAdmitReceived: receivedAdmit
174
+ };
126
175
  if (descriptorConnectionNotRequired(this.local, descriptor)) {
127
176
  this.peersByRid.delete(descriptor.nodeRoutingId);
128
177
  this.remember(descriptor);
129
- this.notRequiredByRid.set(descriptor.nodeRoutingId, cloneDescriptor(descriptor));
178
+ this.notRequiredByRid.set(descriptor.nodeRoutingId, admission);
130
179
  this.rebuildSelections();
131
180
  return 'notRequired';
132
181
  }
133
182
  this.notRequiredByRid.delete(descriptor.nodeRoutingId);
134
183
 
135
- const current = this.peersByRid.get(descriptor.nodeRoutingId);
136
- if (
137
- current !== undefined &&
138
- current.descriptor.lifecycleGeneration === descriptor.lifecycleGeneration &&
139
- descriptor.descriptorRevision > current.descriptor.descriptorRevision &&
140
- !sameImmutableDescriptor(current.descriptor, descriptor)
141
- ) {
142
- return 'invalidDescriptor';
143
- }
144
- if (
145
- current !== undefined &&
146
- current.descriptor.lifecycleGeneration === descriptor.lifecycleGeneration &&
147
- (current.descriptor.descriptorRevision > descriptor.descriptorRevision ||
148
- (current.descriptor.descriptorRevision === descriptor.descriptorRevision &&
149
- !sameServiceNodeDescriptor(current.descriptor, descriptor)))
150
- ) {
151
- return 'staleDescriptor';
152
- }
153
184
  // Core selects the one route per RID (Core ROUTER §10.1); an admission on
154
185
  // that route replaces the admission of a route it replaced.
155
186
  this.peersByRid.set(descriptor.nodeRoutingId, {
156
- descriptor: cloneDescriptor(descriptor),
157
- connectionId
187
+ ...admission,
188
+ connectionId,
189
+ liveness: admitLiveness?.() ?? current?.liveness
158
190
  });
159
191
  this.remember(descriptor);
160
192
  this.rebuildSelections();
161
193
  return 'admitted';
162
194
  }
163
195
 
164
- disconnect(nodeRoutingId: string, connectionId: string): boolean {
196
+ disconnect(nodeRoutingId: string, connectionId: string | bigint): boolean {
165
197
  const current = this.peersByRid.get(nodeRoutingId);
166
198
  if (current === undefined || current.connectionId !== connectionId) return false;
167
199
  this.peersByRid.delete(nodeRoutingId);
@@ -170,10 +202,18 @@ export class ServiceTopologyRegistry {
170
202
  }
171
203
 
172
204
  peer(nodeRoutingId: string): AdmittedServicePeer | undefined {
173
- const peer = this.peersByRid.get(nodeRoutingId);
205
+ const peer = this.admittedPeer(nodeRoutingId);
174
206
  return peer === undefined ? undefined : clonePeer(peer);
175
207
  }
176
208
 
209
+ routeAdmission(nodeRoutingId: string): ServiceRouteAdmission | undefined {
210
+ return this.peersByRid.get(nodeRoutingId) ?? this.notRequiredByRid.get(nodeRoutingId);
211
+ }
212
+
213
+ admittedPeer(nodeRoutingId: string): AdmittedServicePeer | undefined {
214
+ return this.peersByRid.get(nodeRoutingId);
215
+ }
216
+
177
217
  peers(): readonly AdmittedServicePeer[] {
178
218
  return this.peersCore();
179
219
  }
@@ -188,12 +228,14 @@ export class ServiceTopologyRegistry {
188
228
 
189
229
  notRequiredPeers(): readonly ServiceNodeDescriptor[] {
190
230
  return [...this.notRequiredByRid.values()]
191
- .sort((left, right) => compareOrdinal(left.nodeRoutingId, right.nodeRoutingId))
192
- .map(cloneDescriptor);
231
+ .sort((left, right) =>
232
+ compareOrdinal(left.descriptor.nodeRoutingId, right.descriptor.nodeRoutingId)
233
+ )
234
+ .map((peer) => cloneDescriptor(peer.descriptor));
193
235
  }
194
236
 
195
237
  replaceDiscoveredNotRequired(descriptors: readonly ServiceNodeDescriptor[]): void {
196
- const next = new Map<string, ServiceNodeDescriptor>();
238
+ const next = new Map<string, ServiceRouteAdmission>();
197
239
  for (const descriptor of descriptors) {
198
240
  validateDescriptor(descriptor);
199
241
  if (
@@ -201,13 +243,16 @@ export class ServiceTopologyRegistry {
201
243
  descriptor.nodeRoutingId !== this.local.nodeRoutingId &&
202
244
  descriptorConnectionNotRequired(this.local, descriptor)
203
245
  ) {
204
- next.set(descriptor.nodeRoutingId, cloneDescriptor(descriptor));
246
+ next.set(descriptor.nodeRoutingId, {
247
+ ...this.notRequiredByRid.get(descriptor.nodeRoutingId),
248
+ descriptor: cloneDescriptor(descriptor)
249
+ });
205
250
  }
206
251
  }
207
252
  this.notRequiredByRid.clear();
208
- for (const [nodeRoutingId, descriptor] of next) {
209
- this.notRequiredByRid.set(nodeRoutingId, descriptor);
210
- this.remember(descriptor);
253
+ for (const [nodeRoutingId, admission] of next) {
254
+ this.notRequiredByRid.set(nodeRoutingId, admission);
255
+ this.remember(admission.descriptor);
211
256
  }
212
257
  this.rebuildSelections();
213
258
  }
@@ -217,12 +262,27 @@ export class ServiceTopologyRegistry {
217
262
  }
218
263
 
219
264
  knownDescriptor(nodeRoutingId: string): ServiceNodeDescriptor | undefined {
220
- const admitted = this.peersByRid.get(nodeRoutingId)?.descriptor;
221
- const descriptor =
222
- admitted ?? this.notRequiredByRid.get(nodeRoutingId) ?? this.knownByRid.get(nodeRoutingId);
265
+ const descriptor = this.knownPeerDescriptor(nodeRoutingId);
223
266
  return descriptor === undefined ? undefined : cloneDescriptor(descriptor);
224
267
  }
225
268
 
269
+ isObjectClientNodeDirectTarget(nodeRoutingId: string): boolean {
270
+ const descriptor =
271
+ nodeRoutingId === this.local.nodeRoutingId
272
+ ? this.local
273
+ : this.knownPeerDescriptor(nodeRoutingId);
274
+ return descriptor?.objectRole === 'client';
275
+ }
276
+
277
+ private knownPeerDescriptor(nodeRoutingId: string): ServiceNodeDescriptor | undefined {
278
+ const admitted = this.peersByRid.get(nodeRoutingId)?.descriptor;
279
+ return (
280
+ admitted ??
281
+ this.notRequiredByRid.get(nodeRoutingId)?.descriptor ??
282
+ this.knownByRid.get(nodeRoutingId)
283
+ );
284
+ }
285
+
226
286
  hasKnownChannelTarget(channelName: string): boolean {
227
287
  requireText(channelName, 'channelName');
228
288
  return [...this.knownByRid.values()].some(
@@ -525,7 +585,8 @@ function cloneDescriptor(descriptor: ServiceNodeDescriptor): ServiceNodeDescript
525
585
  function clonePeer(peer: AdmittedServicePeer): AdmittedServicePeer {
526
586
  return {
527
587
  descriptor: cloneDescriptor(peer.descriptor),
528
- connectionId: peer.connectionId
588
+ connectionId: peer.connectionId,
589
+ liveness: peer.liveness
529
590
  };
530
591
  }
531
592