@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
@@ -26,7 +26,11 @@ import {
26
26
  import type { ZLinkRuntimeTaskErrorSink } from '../execution';
27
27
  import { ZLinkDispatchErrorReporter } from './dispatch-error-reporter';
28
28
  import { invokeZLinkHandlerFilters } from '../handlers';
29
- import { runInHandlerInstanceScope } from '../handlers/handler-instance-scope';
29
+ import {
30
+ runInHandlerInstanceScope,
31
+ prepareHandlerInstance,
32
+ handlerInstanceCleanup
33
+ } from '../handlers/handler-instance-scope';
30
34
  import { handlerFilterScope } from './handler-filter-scope';
31
35
  import type {
32
36
  ZLinkChannelRequestHandler,
@@ -109,6 +113,17 @@ export class ZLinkChannelDispatchServices {
109
113
  }
110
114
 
111
115
  channelRequestHandler(handlerType: Type): ZLinkChannelRequestHandler {
116
+ const activate =
117
+ this.registration.filterTypes.length === 0
118
+ ? prepareHandlerInstance(
119
+ this.providerResolver,
120
+ handlerType as Type<ZLinkChannelRequestHandler>
121
+ )
122
+ : undefined;
123
+ if (activate !== undefined)
124
+ return {
125
+ handle: (payload, context) => this.invokeScopeFreeHandler(activate, payload, context)
126
+ };
112
127
  return {
113
128
  handle: (payload, context) =>
114
129
  this.withHandlerScope(context, async (scope) => {
@@ -119,6 +134,17 @@ export class ZLinkChannelDispatchServices {
119
134
  }
120
135
 
121
136
  channelSendHandler(handlerType: Type): ZLinkChannelSendHandler {
137
+ const activate =
138
+ this.registration.filterTypes.length === 0
139
+ ? prepareHandlerInstance(
140
+ this.providerResolver,
141
+ handlerType as Type<ZLinkChannelSendHandler>
142
+ )
143
+ : undefined;
144
+ if (activate !== undefined)
145
+ return {
146
+ handle: (payload, context) => this.invokeScopeFreeHandler(activate, payload, context)
147
+ };
122
148
  return {
123
149
  handle: (payload, context) =>
124
150
  this.withHandlerScope(context, async (scope) => {
@@ -129,6 +155,17 @@ export class ZLinkChannelDispatchServices {
129
155
  }
130
156
 
131
157
  routeRequestHandler(handlerType: Type): ZLinkRouteRuntimeRequestHandler {
158
+ const activate =
159
+ this.registration.filterTypes.length === 0
160
+ ? prepareHandlerInstance(
161
+ this.providerResolver,
162
+ handlerType as Type<ZLinkRouteRuntimeRequestHandler>
163
+ )
164
+ : undefined;
165
+ if (activate !== undefined)
166
+ return {
167
+ handle: (payload, context) => this.invokeScopeFreeHandler(activate, payload, context)
168
+ };
132
169
  return {
133
170
  handle: (payload, context) =>
134
171
  this.withHandlerScope(context, async (scope) => {
@@ -139,6 +176,17 @@ export class ZLinkChannelDispatchServices {
139
176
  }
140
177
 
141
178
  routeSendHandler(handlerType: Type): ZLinkRouteRuntimeSendHandler {
179
+ const activate =
180
+ this.registration.filterTypes.length === 0
181
+ ? prepareHandlerInstance(
182
+ this.providerResolver,
183
+ handlerType as Type<ZLinkRouteRuntimeSendHandler>
184
+ )
185
+ : undefined;
186
+ if (activate !== undefined)
187
+ return {
188
+ handle: (payload, context) => this.invokeScopeFreeHandler(activate, payload, context)
189
+ };
142
190
  return {
143
191
  handle: (payload, context) =>
144
192
  this.withHandlerScope(context, async (scope) => {
@@ -148,6 +196,26 @@ export class ZLinkChannelDispatchServices {
148
196
  };
149
197
  }
150
198
 
199
+ private invokeScopeFreeHandler<TContext extends ZLinkMessageContext, TResult>(
200
+ activate: () => { handle(payload: unknown, context: TContext): TResult | Promise<TResult> },
201
+ payload: unknown,
202
+ context: TContext
203
+ ): TResult | Promise<TResult> {
204
+ const handler = activate();
205
+ const cleanup = handlerInstanceCleanup(handler);
206
+ if (cleanup === undefined) return handler.handle(payload, context);
207
+ let result: TResult | Promise<TResult>;
208
+ try {
209
+ result = handler.handle(payload, context);
210
+ } catch (error) {
211
+ const disposed = cleanup.call(handler);
212
+ return Promise.resolve(disposed).then(() => {
213
+ throw error;
214
+ });
215
+ }
216
+ return Promise.resolve(result).finally(() => cleanup.call(handler));
217
+ }
218
+
151
219
  private async invokeHandlerFilters(
152
220
  context: ZLinkHandlerFilterContext,
153
221
  next: () => Promise<void>,
@@ -13,7 +13,7 @@ import {
13
13
  } from '../../contracts/Dispatch/ZLinkDispatchOptions';
14
14
  import type { Message } from '../../contracts/Common/Message';
15
15
  import { SubmitResult } from '../backend/runtime-values';
16
- import type { ReceiveRecord } from '../foundation/service-runtime-contracts';
16
+ import { ReceiveKind, type ReceiveRecord } from '../foundation/service-runtime-contracts';
17
17
  import { ZLinkConfigurationException, type ZLinkRouteChannelOptions } from '../configuration';
18
18
  import type { ZLinkBackendSpotRouteBridge } from '../backend/contracts';
19
19
  import type { ZLinkRuntimeMetrics } from '../diagnostics';
@@ -59,6 +59,8 @@ export interface ZLinkChannelRequestDispatcherOptions {
59
59
  readonly unhandled?: ZLinkUnhandledDispatchOptions;
60
60
  }
61
61
 
62
+ const completedChannelReply = Promise.resolve();
63
+
62
64
  export interface ZLinkChannelRequestHandler {
63
65
  handle(payload: unknown, context: ZLinkMessageContext): Promise<unknown> | unknown;
64
66
  }
@@ -134,7 +136,7 @@ export class ZLinkChannelRequestDispatcher {
134
136
  await this.pipeline.dispatchMalformed({
135
137
  info,
136
138
  error,
137
- transportRequest: replyToken !== null,
139
+ transportRequest: replyToken != null,
138
140
  writeProtocolError:
139
141
  replyToken === null
140
142
  ? undefined
@@ -236,19 +238,19 @@ export class ZLinkChannelRequestDispatcher {
236
238
  });
237
239
  }
238
240
 
239
- async dispatchMesh(record: ReceiveRecord, signal?: AbortSignal): Promise<void> {
241
+ dispatchMesh(record: ReceiveRecord, signal?: AbortSignal): Promise<void> {
240
242
  if (record.parts.length === 0 || record.parts[0].data().length === 0) {
241
- return;
243
+ return completedChannelReply;
242
244
  }
243
245
  let envelope: ReturnType<typeof decodeChannelEnvelope>;
244
246
  try {
245
247
  envelope = decodeChannelEnvelope(record.parts, undefined, this.flowEnabled());
246
248
  } catch (error) {
247
249
  const info = inspectMalformedChannelHeader(record.parts, this.flowEnabled());
248
- await this.pipeline.dispatchMalformed({
250
+ return this.pipeline.dispatchMalformed({
249
251
  info,
250
252
  error,
251
- transportRequest: false,
253
+ transportRequest: isMeshRequest(record),
252
254
  sourceRid: record.sourceNodeRid == null ? undefined : String(record.sourceNodeRid),
253
255
  writeProtocolError: async (protocolError) => {
254
256
  requireMeshReplyAccepted(
@@ -261,7 +263,6 @@ export class ZLinkChannelRequestDispatcher {
261
263
  );
262
264
  }
263
265
  });
264
- return;
265
266
  }
266
267
  const packetName = envelope.packetName;
267
268
  if (packetName === undefined) {
@@ -269,7 +270,7 @@ export class ZLinkChannelRequestDispatcher {
269
270
  }
270
271
  const correlationId = envelope.header.correlationId ?? undefined;
271
272
  if (envelope.header.kind === ZLinkChannelMessageKind.Command) {
272
- await this.pipeline.dispatchOneWay({
273
+ return this.pipeline.dispatchOneWay({
273
274
  fields: {
274
275
  messageKind: ZLinkDispatchMessageKind.Send,
275
276
  packetName,
@@ -283,10 +284,9 @@ export class ZLinkChannelRequestDispatcher {
283
284
  context: this.createMeshContext(envelope, record.sourceNodeRid),
284
285
  signal
285
286
  });
286
- return;
287
287
  }
288
288
  if (envelope.header.kind !== ZLinkChannelMessageKind.Request) {
289
- return;
289
+ return completedChannelReply;
290
290
  }
291
291
  const fields: ZLinkChannelDispatchFields = {
292
292
  messageKind: ZLinkDispatchMessageKind.Request,
@@ -295,7 +295,7 @@ export class ZLinkChannelRequestDispatcher {
295
295
  flowId: envelope.header.flowId,
296
296
  flowOrigin: envelope.header.flowOrigin
297
297
  };
298
- await this.pipeline.dispatchRequest({
298
+ return this.pipeline.dispatchRequest({
299
299
  fields,
300
300
  envelope,
301
301
  codecs: this.options.codecs,
@@ -303,12 +303,12 @@ export class ZLinkChannelRequestDispatcher {
303
303
  context: this.createMeshContext(envelope, record.sourceNodeRid),
304
304
  signal,
305
305
  missingHandlerMessage: `No channel request handler is registered for '${this.options.channelName}:${packetName}'.`,
306
- writeReply: async (reply) => {
306
+ writeReply: (reply) => {
307
307
  requireMeshReplyAccepted(
308
308
  record.reply(encodeChannelReplyParts(envelope.header, reply, this.options.codecs))
309
309
  );
310
310
  },
311
- writeError: async (error) => {
311
+ writeError: (error) => {
312
312
  requireMeshReplyAccepted(
313
313
  record.reply(encodeChannelErrorReplyParts(envelope.header, error))
314
314
  );
@@ -324,7 +324,7 @@ export class ZLinkChannelRequestDispatcher {
324
324
  if (operation.submit() === false) {
325
325
  throw new ZLinkConfigurationException('Channel reply was not accepted by Core.');
326
326
  }
327
- return Promise.resolve();
327
+ return completedChannelReply;
328
328
  }
329
329
 
330
330
  private createMeshContext(
@@ -587,7 +587,7 @@ export class ZLinkRoutePacketDispatcher {
587
587
  await this.pipeline.dispatchMalformed({
588
588
  info,
589
589
  error,
590
- transportRequest: replyToken !== null,
590
+ transportRequest: replyToken != null,
591
591
  sourceRid: String(received.routingId),
592
592
  writeProtocolError:
593
593
  replyToken === null
@@ -685,19 +685,19 @@ export class ZLinkRoutePacketDispatcher {
685
685
  });
686
686
  }
687
687
 
688
- async dispatchMesh(record: ReceiveRecord, signal?: AbortSignal): Promise<void> {
688
+ dispatchMesh(record: ReceiveRecord, signal?: AbortSignal): Promise<void> {
689
689
  if (record.parts.length === 0 || record.parts[0].data().length === 0) {
690
- return;
690
+ return completedChannelReply;
691
691
  }
692
692
  let envelope: ReturnType<typeof decodeChannelEnvelope>;
693
693
  try {
694
694
  envelope = decodeChannelEnvelope(record.parts, undefined, this.flowEnabled());
695
695
  } catch (error) {
696
696
  const info = inspectMalformedChannelHeader(record.parts, this.flowEnabled());
697
- await this.pipeline.dispatchMalformed({
697
+ return this.pipeline.dispatchMalformed({
698
698
  info,
699
699
  error,
700
- transportRequest: false,
700
+ transportRequest: isMeshRequest(record),
701
701
  sourceRid: record.sourceNodeRid == null ? undefined : String(record.sourceNodeRid),
702
702
  writeProtocolError: async (protocolError) => {
703
703
  requireMeshReplyAccepted(
@@ -710,7 +710,6 @@ export class ZLinkRoutePacketDispatcher {
710
710
  );
711
711
  }
712
712
  });
713
- return;
714
713
  }
715
714
  const packetName = envelope.packetName;
716
715
  if (packetName === undefined) {
@@ -719,17 +718,16 @@ export class ZLinkRoutePacketDispatcher {
719
718
  const sourceNodeRid = String(record.sourceNodeRid ?? '');
720
719
  const correlationId = envelope.header.correlationId ?? undefined;
721
720
  if (envelope.header.kind === ZLinkChannelMessageKind.Command) {
722
- await this.dispatchMeshCommand(
721
+ return this.dispatchMeshCommand(
723
722
  envelope,
724
723
  packetName,
725
724
  sourceNodeRid,
726
725
  record.sourceNodeRid,
727
726
  signal
728
727
  );
729
- return;
730
728
  }
731
729
  if (envelope.header.kind !== ZLinkChannelMessageKind.Request) {
732
- return;
730
+ return completedChannelReply;
733
731
  }
734
732
  const fields: ZLinkChannelDispatchFields = {
735
733
  messageKind: ZLinkDispatchMessageKind.Request,
@@ -740,7 +738,7 @@ export class ZLinkRoutePacketDispatcher {
740
738
  flowOrigin: envelope.header.flowOrigin
741
739
  };
742
740
  const codecs = codecsForFrameworkPacket(packetName, this.codecs);
743
- await this.pipeline.dispatchRequest({
741
+ return this.pipeline.dispatchRequest({
744
742
  fields,
745
743
  envelope,
746
744
  codecs,
@@ -748,12 +746,12 @@ export class ZLinkRoutePacketDispatcher {
748
746
  context: this.createRouteContext(envelope, record.sourceNodeRid),
749
747
  signal,
750
748
  missingHandlerMessage: `No routed request handler is registered for '${this.routerChannelId}:${packetName}'.`,
751
- writeReply: async (reply) => {
749
+ writeReply: (reply) => {
752
750
  requireMeshReplyAccepted(
753
751
  record.reply(encodeChannelReplyParts(envelope.header, reply, codecs))
754
752
  );
755
753
  },
756
- writeError: async (error) => {
754
+ writeError: (error) => {
757
755
  requireMeshReplyAccepted(
758
756
  record.reply(encodeChannelErrorReplyParts(envelope.header, error))
759
757
  );
@@ -826,7 +824,7 @@ export class ZLinkRoutePacketDispatcher {
826
824
  if (operation.submit() === false) {
827
825
  throw new ZLinkConfigurationException('Route reply was not accepted by Core.');
828
826
  }
829
- return Promise.resolve();
827
+ return completedChannelReply;
830
828
  }
831
829
 
832
830
  private createRouteContext(
@@ -844,3 +842,7 @@ export class ZLinkRoutePacketDispatcher {
844
842
  };
845
843
  }
846
844
  }
845
+
846
+ function isMeshRequest(record: ReceiveRecord): boolean {
847
+ return record.kind === ReceiveKind.NodeRequest || record.kind === ReceiveKind.ChannelRequest;
848
+ }
@@ -3,6 +3,7 @@ import type { Message } from '../../contracts/Common/Message';
3
3
  import type { ZLinkFlowOrigin } from '../../contracts';
4
4
  import {
5
5
  decodeChannelHeader,
6
+ isValidChannelCorrelationId,
6
7
  ZLINK_CHANNEL_FORMAT_MARKER,
7
8
  ZLinkChannelMessageKind,
8
9
  type ZLinkChannelEnvelopeHeader
@@ -29,7 +30,6 @@ export function tryDecodeChannelHeader(
29
30
  * present only when it is individually well-formed.
30
31
  */
31
32
  export interface ZLinkMalformedChannelHeaderInfo {
32
- readonly kind?: ZLinkChannelMessageKind;
33
33
  readonly channelName?: string;
34
34
  readonly messageName?: string;
35
35
  readonly correlationId?: string;
@@ -50,7 +50,6 @@ export function inspectMalformedChannelHeader(
50
50
  } catch {
51
51
  return {};
52
52
  }
53
- if (header.formatMarker !== ZLINK_CHANNEL_FORMAT_MARKER) return {};
54
53
  const flowId =
55
54
  typeof header.flowId === 'string' && CHANNEL_FLOW_ID_PATTERN.test(header.flowId)
56
55
  ? header.flowId
@@ -58,7 +57,6 @@ export function inspectMalformedChannelHeader(
58
57
  const flowOrigin = salvageFlowOrigin(header.flowOrigin);
59
58
  const flowPairValid = flowEnabled && flowId !== undefined && flowOrigin !== undefined;
60
59
  return {
61
- kind: salvageChannelKind(header.kind),
62
60
  channelName: salvageString(header.channelName),
63
61
  messageName: salvageString(header.messageName),
64
62
  correlationId: salvageCorrelationId(header.correlationId),
@@ -94,24 +92,12 @@ export function malformedProtocolErrorRequestHeader(
94
92
  const CHANNEL_FLOW_ID_PATTERN =
95
93
  /^[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/;
96
94
 
97
- function salvageChannelKind(value: unknown): ZLinkChannelMessageKind | undefined {
98
- return value === ZLinkChannelMessageKind.Request ||
99
- value === ZLinkChannelMessageKind.Response ||
100
- value === ZLinkChannelMessageKind.Command ||
101
- value === ZLinkChannelMessageKind.Publish ||
102
- value === ZLinkChannelMessageKind.Error
103
- ? value
104
- : undefined;
105
- }
106
-
107
95
  function salvageString(value: unknown): string | undefined {
108
96
  return typeof value === 'string' && value.length > 0 ? value : undefined;
109
97
  }
110
98
 
111
99
  function salvageCorrelationId(value: unknown): string | undefined {
112
- if (typeof value !== 'string') return undefined;
113
- const byteLength = Buffer.byteLength(value, 'utf8');
114
- return byteLength >= 1 && byteLength <= 64 && /^[\x00-\x7f]*$/.test(value) ? value : undefined;
100
+ return typeof value === 'string' && isValidChannelCorrelationId(value) ? value : undefined;
115
101
  }
116
102
 
117
103
  function salvageFlowOrigin(value: unknown): ZLinkFlowOrigin | undefined {
@@ -1,4 +1,5 @@
1
1
  import type { Message } from '../../contracts/Common/Message';
2
+ import { ZLinkBufferMessage } from '../backend/runtime-message';
2
3
  import type { ZLinkBackendMessageLike as MessageLike } from '../backend/runtime-values';
3
4
  import { randomUUID } from 'node:crypto';
4
5
  import { isUtf8 } from 'node:buffer';
@@ -70,6 +71,24 @@ export interface ZLinkChannelEnvelopeCodecRegistry {
70
71
  readonly serializers: ReadonlyMap<string, ZLinkMessageSerializer>;
71
72
  }
72
73
 
74
+ interface PreparedChannelHeader {
75
+ readonly bytes: Buffer;
76
+ readonly correlationOffset: number;
77
+ readonly deadlineOffset: number;
78
+ }
79
+
80
+ type PreparedHeaderVariants = Map<ZLinkChannelMessageKind, Map<boolean, PreparedChannelHeader>>;
81
+ const preparedChannelHeaders = new WeakMap<
82
+ ReadonlyMap<string, ZLinkMessageSerializer>,
83
+ Map<string, Map<string, Map<string, PreparedHeaderVariants>>>
84
+ >();
85
+ const CHANNEL_CORRELATION_FIELD = ',"correlationId":';
86
+ const CHANNEL_DEADLINE_FIELD = ',"deadline":';
87
+ const CHANNEL_CORRELATION_TEXT_LENGTH = 32;
88
+ const PREPARED_CHANNEL_CORRELATION = '0'.repeat(CHANNEL_CORRELATION_TEXT_LENGTH);
89
+ const PREPARED_CHANNEL_DEADLINE = '2000-01-01T00:00:00.000Z';
90
+ const CHANNEL_CORRELATION_TEXT = /^[0-9a-f]{32}$/;
91
+
73
92
  export function newChannelCorrelationId(): string {
74
93
  return randomUUID().replaceAll('-', '');
75
94
  }
@@ -147,7 +166,8 @@ export function encodeChannelEnvelopePartsAtDeadline(
147
166
  undefined,
148
167
  applicationMetadataRecord(metadata),
149
168
  flow?.flowId,
150
- flow?.flowOrigin
169
+ flow?.flowOrigin,
170
+ codecs
151
171
  ),
152
172
  encoded.message
153
173
  ];
@@ -215,7 +235,8 @@ export function encodeChannelReplyParts(
215
235
  undefined,
216
236
  EMPTY_APPLICATION_METADATA,
217
237
  request.flowId,
218
- request.flowOrigin
238
+ request.flowOrigin,
239
+ codecs
219
240
  ),
220
241
  encoded.message
221
242
  ];
@@ -325,7 +346,7 @@ export function decodeChannelReply<TReply>(
325
346
  return undefined as TReply;
326
347
  }
327
348
  if (header.contentType === BINARY_CONTENT_TYPE) {
328
- return Buffer.from(parts[1].data()) as TReply;
349
+ return ZLinkBufferMessage.retainPayload(parts[1]) as TReply;
329
350
  }
330
351
  if (serializer !== undefined) {
331
352
  return serializer.deserialize<TReply>(
@@ -517,8 +538,47 @@ function encodeChannelHeader(
517
538
  source: string | null | undefined,
518
539
  metadata: Readonly<Record<string, string>>,
519
540
  flowId: string | undefined,
520
- flowOrigin: ZLinkFlowOrigin | undefined
541
+ flowOrigin: ZLinkFlowOrigin | undefined,
542
+ codecs?: ZLinkChannelEnvelopeCodecRegistry
521
543
  ): Buffer {
544
+ if (
545
+ codecs !== undefined &&
546
+ metadata === EMPTY_APPLICATION_METADATA &&
547
+ flowId === undefined &&
548
+ flowOrigin === undefined &&
549
+ topic === null &&
550
+ source === undefined &&
551
+ ((kind === ZLinkChannelMessageKind.Command &&
552
+ correlationId === null &&
553
+ deadline === null &&
554
+ errorCode === null &&
555
+ errorMessage === null) ||
556
+ (kind === ZLinkChannelMessageKind.Request &&
557
+ correlationId !== null &&
558
+ CHANNEL_CORRELATION_TEXT.test(correlationId) &&
559
+ deadline !== null &&
560
+ deadline.length === PREPARED_CHANNEL_DEADLINE.length &&
561
+ errorCode === null &&
562
+ errorMessage === null) ||
563
+ (kind === ZLinkChannelMessageKind.Response &&
564
+ correlationId !== null &&
565
+ CHANNEL_CORRELATION_TEXT.test(correlationId) &&
566
+ deadline === null &&
567
+ errorCode === undefined &&
568
+ errorMessage === undefined))
569
+ ) {
570
+ return preparedChannelHeader(
571
+ codecs,
572
+ kind,
573
+ channelName,
574
+ messageName,
575
+ contentType,
576
+ correlationId,
577
+ deadline,
578
+ errorCode,
579
+ errorMessage
580
+ );
581
+ }
522
582
  // The wire has a fixed field order. Measure escaped UTF-8 first, then write
523
583
  // each field once into the only header Buffer: no header object, whole JSON
524
584
  // string, or post-encode byte copy exists on the outbound path.
@@ -560,6 +620,63 @@ function encodeChannelHeader(
560
620
  return result;
561
621
  }
562
622
 
623
+ function preparedChannelHeader(
624
+ codecs: ZLinkChannelEnvelopeCodecRegistry,
625
+ kind: ZLinkChannelMessageKind,
626
+ channelName: string,
627
+ messageName: string,
628
+ contentType: string,
629
+ correlationId: string | null,
630
+ deadline: string | null,
631
+ errorCode: string | null | undefined,
632
+ errorMessage: string | null | undefined
633
+ ): Buffer {
634
+ let channels = preparedChannelHeaders.get(codecs.serializers);
635
+ if (channels === undefined)
636
+ preparedChannelHeaders.set(codecs.serializers, (channels = new Map()));
637
+ let packets = channels.get(channelName);
638
+ if (packets === undefined) channels.set(channelName, (packets = new Map()));
639
+ let contentTypes = packets.get(messageName);
640
+ if (contentTypes === undefined) packets.set(messageName, (contentTypes = new Map()));
641
+ let kinds = contentTypes.get(contentType);
642
+ if (kinds === undefined) contentTypes.set(contentType, (kinds = new Map()));
643
+ let deadlines = kinds.get(kind);
644
+ if (deadlines === undefined) kinds.set(kind, (deadlines = new Map()));
645
+ const hasDeadline = deadline !== null;
646
+ let prepared = deadlines.get(hasDeadline);
647
+ if (prepared === undefined) {
648
+ const bytes = encodeChannelHeader(
649
+ kind,
650
+ channelName,
651
+ messageName,
652
+ contentType,
653
+ correlationId === null ? null : PREPARED_CHANNEL_CORRELATION,
654
+ hasDeadline ? PREPARED_CHANNEL_DEADLINE : null,
655
+ null,
656
+ errorCode,
657
+ errorMessage,
658
+ undefined,
659
+ EMPTY_APPLICATION_METADATA,
660
+ undefined,
661
+ undefined
662
+ );
663
+ prepared = {
664
+ bytes,
665
+ correlationOffset:
666
+ bytes.indexOf(CHANNEL_CORRELATION_FIELD) + CHANNEL_CORRELATION_FIELD.length + 1,
667
+ deadlineOffset: bytes.indexOf(CHANNEL_DEADLINE_FIELD) + CHANNEL_DEADLINE_FIELD.length + 1
668
+ };
669
+ deadlines.set(hasDeadline, prepared);
670
+ }
671
+ if (correlationId === null) return prepared.bytes;
672
+ const bytes = Buffer.alloc(prepared.bytes.byteLength);
673
+ prepared.bytes.copy(bytes);
674
+ bytes.write(correlationId, prepared.correlationOffset, CHANNEL_CORRELATION_TEXT_LENGTH, 'ascii');
675
+ if (deadline !== null)
676
+ bytes.write(deadline, prepared.deadlineOffset, PREPARED_CHANNEL_DEADLINE.length, 'ascii');
677
+ return bytes;
678
+ }
679
+
563
680
  function writeChannelHeader(
564
681
  writer: ChannelHeaderWriter,
565
682
  kind: ZLinkChannelMessageKind,
@@ -586,9 +703,9 @@ function writeChannelHeader(
586
703
  writer.string(messageName);
587
704
  writer.append(',"contentType":');
588
705
  writer.string(contentType);
589
- writer.append(',"correlationId":');
706
+ writer.append(CHANNEL_CORRELATION_FIELD);
590
707
  writer.nullableString(correlationId);
591
- writer.append(',"deadline":');
708
+ writer.append(CHANNEL_DEADLINE_FIELD);
592
709
  writer.nullableString(deadline);
593
710
  writer.append(',"topic":');
594
711
  writer.nullableString(topic);
@@ -994,9 +1111,17 @@ function validateCorrelationForKind(
994
1111
  }
995
1112
  }
996
1113
 
1114
+ const MAXIMUM_CORRELATION_ID_BYTES = 64;
1115
+
1116
+ export function isValidChannelCorrelationId(value: string): boolean {
1117
+ const byteLength = Buffer.byteLength(value, 'utf8');
1118
+ return (
1119
+ byteLength >= 1 && byteLength <= MAXIMUM_CORRELATION_ID_BYTES && /^[\x00-\x7f]*$/.test(value)
1120
+ );
1121
+ }
1122
+
997
1123
  function validateCorrelationValue(correlationId: string): void {
998
- const byteLength = Buffer.byteLength(correlationId, 'utf8');
999
- if (byteLength < 1 || byteLength > 64 || !/^[\x00-\x7f]*$/.test(correlationId)) {
1124
+ if (!isValidChannelCorrelationId(correlationId)) {
1000
1125
  throw new ZLinkConfigurationException(
1001
1126
  'Channel envelope correlationId must be a non-empty ASCII value of at most 64 bytes.'
1002
1127
  );
@@ -128,11 +128,20 @@ export class ZLinkChannelOutboundOperations {
128
128
  request: unknown,
129
129
  timeoutMs: number | undefined,
130
130
  signal?: AbortSignal,
131
- metadata?: ReadonlyMap<string, string>
131
+ metadata?: ReadonlyMap<string, string>,
132
+ onAdmitted?: () => void
132
133
  ): Promise<TReply> {
133
134
  return keepChannelRequestAlive(
134
135
  runWithOutboundFlow(this.dispatchServices.flowCreationEnabled(), () =>
135
- this.requestScoped<TReply>(channelName, packetName, request, timeoutMs, signal, metadata)
136
+ this.requestScoped<TReply>(
137
+ channelName,
138
+ packetName,
139
+ request,
140
+ timeoutMs,
141
+ signal,
142
+ metadata,
143
+ onAdmitted
144
+ )
136
145
  )
137
146
  );
138
147
  }
@@ -143,7 +152,8 @@ export class ZLinkChannelOutboundOperations {
143
152
  request: unknown,
144
153
  timeoutMs: number | undefined,
145
154
  signal?: AbortSignal,
146
- metadata?: ReadonlyMap<string, string>
155
+ metadata?: ReadonlyMap<string, string>,
156
+ onAdmitted?: () => void
147
157
  ): Promise<TReply> {
148
158
  const deadlineMs = timeoutMs === undefined ? undefined : performance.now() + timeoutMs;
149
159
  const deadlineUnixMs = timeoutMs === undefined ? undefined : Date.now() + timeoutMs;
@@ -213,7 +223,8 @@ export class ZLinkChannelOutboundOperations {
213
223
  replyParts = await awaitWithAbort(
214
224
  dealer.request(
215
225
  parts,
216
- remainingRequestTimeout(`Channel request '${channelName}'`, deadlineMs)
226
+ remainingRequestTimeout(`Channel request '${channelName}'`, deadlineMs),
227
+ onAdmitted
217
228
  ),
218
229
  signal
219
230
  );
@@ -397,7 +408,8 @@ export class ZLinkChannelOutboundOperations {
397
408
  request: unknown,
398
409
  timeoutMs: number | undefined,
399
410
  signal?: AbortSignal,
400
- metadata?: ReadonlyMap<string, string>
411
+ metadata?: ReadonlyMap<string, string>,
412
+ onAdmitted?: () => void
401
413
  ): Promise<TReply> {
402
414
  return runWithOutboundFlow(this.dispatchServices.flowCreationEnabled(), () =>
403
415
  this.routeRequestScoped<TReply>(
@@ -407,7 +419,8 @@ export class ZLinkChannelOutboundOperations {
407
419
  request,
408
420
  timeoutMs,
409
421
  signal,
410
- metadata
422
+ metadata,
423
+ onAdmitted
411
424
  )
412
425
  );
413
426
  }
@@ -419,7 +432,8 @@ export class ZLinkChannelOutboundOperations {
419
432
  request: unknown,
420
433
  timeoutMs: number | undefined,
421
434
  signal?: AbortSignal,
422
- metadata?: ReadonlyMap<string, string>
435
+ metadata?: ReadonlyMap<string, string>,
436
+ onAdmitted?: () => void
423
437
  ): Promise<TReply> {
424
438
  let correlationId: string | undefined;
425
439
  let router: ReturnType<ZLinkChannelSocketRegistry['routeRouter']> | undefined;
@@ -471,7 +485,7 @@ export class ZLinkChannelOutboundOperations {
471
485
  });
472
486
  const reply = await this.measureRequest(routerChannelId, async () => {
473
487
  const replyParts = await awaitWithAbort(
474
- router!.request(targetNodeRid, parts, timeoutMs),
488
+ router!.request(targetNodeRid, parts, timeoutMs, onAdmitted),
475
489
  signal
476
490
  );
477
491
  try {
@@ -359,7 +359,7 @@ export class ZLinkChannelReceiveLoop {
359
359
 
360
360
  private async acquirePermit(signal: AbortSignal): Promise<ApplicationJobQueuePermit | undefined> {
361
361
  try {
362
- return await this.applicationJobQueue.acquire(signal);
362
+ return await this.applicationJobQueue.acquire(signal, 'remote');
363
363
  } catch (error) {
364
364
  if (this.isStopped() || signal.aborted) return undefined;
365
365
  throw error;
@@ -585,7 +585,7 @@ export class ZLinkSubscriberReceiveLoop {
585
585
 
586
586
  private async acquirePermit(signal: AbortSignal): Promise<ApplicationJobQueuePermit | undefined> {
587
587
  try {
588
- return await this.applicationJobQueue.acquire(signal);
588
+ return await this.applicationJobQueue.acquire(signal, 'remote');
589
589
  } catch (error) {
590
590
  if (this.isStopped() || signal.aborted) return undefined;
591
591
  throw error;
@@ -795,7 +795,7 @@ export class ZLinkRouteReceiveLoop {
795
795
 
796
796
  private async acquirePermit(signal: AbortSignal): Promise<ApplicationJobQueuePermit | undefined> {
797
797
  try {
798
- return await this.applicationJobQueue.acquire(signal);
798
+ return await this.applicationJobQueue.acquire(signal, 'remote');
799
799
  } catch (error) {
800
800
  if (this.isStopped() || signal.aborted) return undefined;
801
801
  throw error;