@zlink-systems/framework 0.30.0 → 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 (245) 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/Handlers/Attributes.d.ts +5 -13
  7. package/dist/contracts/Handlers/Attributes.js +7 -11
  8. package/dist/contracts/Handlers/JsonContract.d.ts +2 -46
  9. package/dist/contracts/Handlers/JsonContract.js +4 -153
  10. package/dist/contracts/Spots/Contracts.d.ts +2 -1
  11. package/dist/nest-integration.d.ts +1 -1
  12. package/dist/nest-integration.js +2 -1
  13. package/dist/runtime/actors/actor-client.d.ts +1 -1
  14. package/dist/runtime/actors/actor-client.js +14 -12
  15. package/dist/runtime/actors/actor-handoff.d.ts +1 -1
  16. package/dist/runtime/actors/actor-handoff.js +7 -4
  17. package/dist/runtime/actors/actor-join-relocation.d.ts +1 -0
  18. package/dist/runtime/actors/actor-local-native-join.js +9 -12
  19. package/dist/runtime/actors/actor-remote-wire.js +15 -0
  20. package/dist/runtime/actors/actor-routed-join-transport.d.ts +6 -2
  21. package/dist/runtime/actors/actor-routed-json-request.d.ts +2 -0
  22. package/dist/runtime/actors/index.d.ts +2 -1
  23. package/dist/runtime/actors/index.js +18 -6
  24. package/dist/runtime/actors/spot-actor-dispatch.js +2 -2
  25. package/dist/runtime/admission.d.ts +1 -1
  26. package/dist/runtime/admission.js +15 -5
  27. package/dist/runtime/application-jobs/application-ingress-record-owner.d.ts +6 -8
  28. package/dist/runtime/application-jobs/application-ingress-record-owner.js +39 -22
  29. package/dist/runtime/application-jobs/application-job-queue-scope.d.ts +2 -1
  30. package/dist/runtime/application-jobs/application-job-queue-scope.js +37 -22
  31. package/dist/runtime/application-jobs/contracts.d.ts +10 -1
  32. package/dist/runtime/backend/contracts/index.d.ts +18 -9
  33. package/dist/runtime/backend/mesh-completion-table.d.ts +9 -1
  34. package/dist/runtime/backend/mesh-completion-table.js +149 -49
  35. package/dist/runtime/backend/mesh-dispatch-pump.d.ts +3 -0
  36. package/dist/runtime/backend/mesh-dispatch-pump.js +32 -11
  37. package/dist/runtime/backend/node/node-backend-adapter-support.d.ts +2 -2
  38. package/dist/runtime/backend/node/node-backend-adapter-support.js +16 -9
  39. package/dist/runtime/backend/node/node-dealer-channel-client-transport.d.ts +1 -1
  40. package/dist/runtime/backend/node/node-dealer-channel-client-transport.js +5 -2
  41. package/dist/runtime/backend/node/node-raw-binding-port.js +42 -22
  42. package/dist/runtime/backend/node/node-raw-mesh-backend.d.ts +13 -5
  43. package/dist/runtime/backend/node/node-raw-mesh-backend.js +69 -51
  44. package/dist/runtime/backend/node/node-socket-backend-adapter.js +6 -6
  45. package/dist/runtime/backend/raw-binding-port.d.ts +2 -2
  46. package/dist/runtime/backend/runtime-message.d.ts +1 -0
  47. package/dist/runtime/backend/runtime-message.js +5 -0
  48. package/dist/runtime/backend/runtime-values.d.ts +1 -0
  49. package/dist/runtime/backend/runtime-values.js +2 -1
  50. package/dist/runtime/channels/channel-clients.d.ts +1 -0
  51. package/dist/runtime/channels/channel-clients.js +58 -21
  52. package/dist/runtime/channels/channel-dispatch-pipeline.d.ts +3 -2
  53. package/dist/runtime/channels/channel-dispatch-pipeline.js +20 -11
  54. package/dist/runtime/channels/channel-dispatch-services.d.ts +1 -0
  55. package/dist/runtime/channels/channel-dispatch-services.js +45 -0
  56. package/dist/runtime/channels/channel-dispatchers.d.ts +1 -1
  57. package/dist/runtime/channels/channel-dispatchers.js +27 -26
  58. package/dist/runtime/channels/channel-envelope-inspection.d.ts +1 -2
  59. package/dist/runtime/channels/channel-envelope-inspection.js +1 -16
  60. package/dist/runtime/channels/channel-envelope.d.ts +1 -0
  61. package/dist/runtime/channels/channel-envelope.js +83 -8
  62. package/dist/runtime/channels/channel-outbound-operations.d.ts +2 -2
  63. package/dist/runtime/channels/channel-outbound-operations.js +8 -8
  64. package/dist/runtime/channels/channel-runtime-manager.d.ts +6 -6
  65. package/dist/runtime/channels/channel-runtime-manager.js +12 -12
  66. package/dist/runtime/channels/channel-transports.d.ts +18 -15
  67. package/dist/runtime/channels/channel-transports.js +48 -31
  68. package/dist/runtime/channels/local-spot-route-transport.d.ts +1 -1
  69. package/dist/runtime/channels/local-spot-route-transport.js +2 -1
  70. package/dist/runtime/channels/router-socket-spot-route-transport.d.ts +2 -2
  71. package/dist/runtime/channels/router-socket-spot-route-transport.js +4 -4
  72. package/dist/runtime/channels/source-spot-router.d.ts +2 -2
  73. package/dist/runtime/channels/source-spot-router.js +4 -4
  74. package/dist/runtime/channels/spot-node-route-transport.d.ts +2 -2
  75. package/dist/runtime/channels/spot-node-route-transport.js +4 -4
  76. package/dist/runtime/channels/spot-route-bridge-transport.d.ts +2 -2
  77. package/dist/runtime/channels/spot-route-bridge-transport.js +4 -4
  78. package/dist/runtime/channels/spot-route-dispatch-strategy.d.ts +5 -4
  79. package/dist/runtime/channels/spot-route-dispatch-strategy.js +18 -18
  80. package/dist/runtime/execution/serial-execution-queue.d.ts +1 -0
  81. package/dist/runtime/execution/serial-execution-queue.js +1 -0
  82. package/dist/runtime/foundation/actor-join-recovery-codec.js +2 -2
  83. package/dist/runtime/foundation/durable-service-request.d.ts +14 -0
  84. package/dist/runtime/foundation/durable-service-request.js +98 -0
  85. package/dist/runtime/foundation/operation-identity.d.ts +1 -0
  86. package/dist/runtime/foundation/operation-identity.js +5 -1
  87. package/dist/runtime/foundation/raw-service-mesh-runtime.d.ts +22 -5
  88. package/dist/runtime/foundation/raw-service-mesh-runtime.js +356 -232
  89. package/dist/runtime/foundation/service-relocation-object-owner.d.ts +1 -0
  90. package/dist/runtime/foundation/service-relocation-object-owner.js +1 -0
  91. package/dist/runtime/foundation/service-relocation-runtime.d.ts +2 -0
  92. package/dist/runtime/foundation/service-relocation-runtime.js +13 -1
  93. package/dist/runtime/foundation/service-runtime-contracts.d.ts +2 -0
  94. package/dist/runtime/foundation/service-stateful-runtime.d.ts +4 -4
  95. package/dist/runtime/foundation/service-stateful-runtime.js +44 -103
  96. package/dist/runtime/foundation/service-stateful-wire-codec.d.ts +0 -5
  97. package/dist/runtime/foundation/service-topology-registry.d.ts +12 -2
  98. package/dist/runtime/foundation/service-topology-registry.js +61 -27
  99. package/dist/runtime/foundation/service-wire-m6a-codec.d.ts +3 -3
  100. package/dist/runtime/foundation/service-wire-m6a-codec.js +36 -38
  101. package/dist/runtime/handlers/handler-instance-scope.d.ts +8 -0
  102. package/dist/runtime/handlers/handler-instance-scope.js +54 -11
  103. package/dist/runtime/host/actor-runtime-options-factory.js +2 -2
  104. package/dist/runtime/host/application-job-queue.d.ts +19 -7
  105. package/dist/runtime/host/application-job-queue.js +150 -42
  106. package/dist/runtime/host/entry-actor-runtime.d.ts +1 -0
  107. package/dist/runtime/host/entry-actor-runtime.js +3 -0
  108. package/dist/runtime/host/index.d.ts +7 -1
  109. package/dist/runtime/host/index.js +142 -118
  110. package/dist/runtime/host/remote-bound-session-relay.js +2 -18
  111. package/dist/runtime/host/route-mesh-runtime.js +1 -1
  112. package/dist/runtime/host/service-relocation-control.d.ts +1 -0
  113. package/dist/runtime/host/service-relocation-control.js +10 -4
  114. package/dist/runtime/host/service-relocation-host-runtime.d.ts +6 -8
  115. package/dist/runtime/host/service-relocation-host-runtime.js +213 -241
  116. package/dist/runtime/host/spot-address-transport.js +3 -2
  117. package/dist/runtime/host/spot-runtime-options-factory.js +1 -0
  118. package/dist/runtime/locations/actor-location-claims.d.ts +2 -2
  119. package/dist/runtime/locations/actor-location-claims.js +34 -19
  120. package/dist/runtime/locations/lifecycle.d.ts +1 -2
  121. package/dist/runtime/locations/lifecycle.js +2 -5
  122. package/dist/runtime/locations/runtime.d.ts +1 -1
  123. package/dist/runtime/locations/runtime.js +24 -23
  124. package/dist/runtime/messaging/framework-json-v1.d.ts +4 -6
  125. package/dist/runtime/messaging/framework-json-v1.js +38 -294
  126. package/dist/runtime/messaging/packet-name.d.ts +1 -1
  127. package/dist/runtime/messaging/packet-name.js +8 -24
  128. package/dist/runtime/messaging/request-result.d.ts +2 -0
  129. package/dist/runtime/messaging/request-result.js +54 -0
  130. package/dist/runtime/messaging/submission-result.d.ts +1 -0
  131. package/dist/runtime/messaging/submission-result.js +5 -2
  132. package/dist/runtime/protocol/service_wire_codec.generated.d.ts +15 -0
  133. package/dist/runtime/protocol/service_wire_codec.generated.js +144 -0
  134. package/dist/runtime/protocol/service_wire_pilot_codec.generated.d.ts +9 -0
  135. package/dist/runtime/protocol/service_wire_pilot_codec.generated.js +14 -1
  136. package/dist/runtime/spots/formal-remote-actor-admission-registry.d.ts +7 -2
  137. package/dist/runtime/spots/formal-remote-actor-admission-registry.js +33 -19
  138. package/dist/runtime/spots/index.d.ts +3 -0
  139. package/dist/runtime/spots/index.js +9 -2
  140. package/dist/runtime/spots/spot-activation.d.ts +1 -0
  141. package/dist/runtime/spots/spot-activation.js +17 -8
  142. package/dist/runtime/spots/spot-entry-activation.js +6 -2
  143. package/dist/runtime/spots/spot-handler-registry.d.ts +3 -1
  144. package/dist/runtime/spots/spot-handler-registry.js +18 -8
  145. package/dist/runtime/spots/spot-node-autoconnect.js +4 -3
  146. package/dist/runtime/spots/spot-outbound.d.ts +3 -0
  147. package/dist/runtime/spots/spot-outbound.js +24 -15
  148. package/dist/runtime/spots/spot-routed-spot-packet-dispatch.d.ts +1 -0
  149. package/dist/runtime/spots/spot-routed-spot-packet-dispatch.js +1 -1
  150. package/dist/runtime/spots/spot-runtime-ports.d.ts +1 -0
  151. package/dist/runtime/spots/spot-subscription-dispatch.js +0 -3
  152. package/dist/runtime/spots/spot-timer.js +1 -0
  153. package/dist/runtime/streams/stream-session-runtime.d.ts +1 -1
  154. package/dist/runtime/streams/stream-session-runtime.js +13 -27
  155. package/package.json +2 -2
  156. package/src/contracts/Actors/ZLinkActorClient.ts +2 -1
  157. package/src/contracts/Channels/Calls.ts +2 -1
  158. package/src/contracts/Common/ZLinkMessageMetadata.ts +13 -8
  159. package/src/contracts/Handlers/Attributes.ts +14 -21
  160. package/src/contracts/Handlers/JsonContract.ts +8 -216
  161. package/src/contracts/Spots/Contracts.ts +2 -1
  162. package/src/nest-integration.ts +1 -0
  163. package/src/runtime/actors/actor-client.ts +40 -16
  164. package/src/runtime/actors/actor-handoff.ts +9 -4
  165. package/src/runtime/actors/actor-join-relocation.ts +1 -0
  166. package/src/runtime/actors/actor-local-native-join.ts +17 -26
  167. package/src/runtime/actors/actor-remote-wire.ts +17 -0
  168. package/src/runtime/actors/actor-routed-join-transport.ts +14 -4
  169. package/src/runtime/actors/actor-routed-json-request.ts +10 -2
  170. package/src/runtime/actors/index.ts +19 -5
  171. package/src/runtime/actors/spot-actor-dispatch.ts +4 -2
  172. package/src/runtime/admission.ts +18 -5
  173. package/src/runtime/application-jobs/application-ingress-record-owner.ts +41 -25
  174. package/src/runtime/application-jobs/application-job-queue-scope.ts +51 -22
  175. package/src/runtime/application-jobs/contracts.ts +14 -1
  176. package/src/runtime/backend/contracts/index.ts +53 -14
  177. package/src/runtime/backend/mesh-completion-table.ts +156 -57
  178. package/src/runtime/backend/mesh-dispatch-pump.ts +40 -10
  179. package/src/runtime/backend/node/node-backend-adapter-support.ts +17 -8
  180. package/src/runtime/backend/node/node-dealer-channel-client-transport.ts +12 -2
  181. package/src/runtime/backend/node/node-raw-binding-port.ts +57 -30
  182. package/src/runtime/backend/node/node-raw-mesh-backend.ts +128 -65
  183. package/src/runtime/backend/node/node-socket-backend-adapter.ts +21 -6
  184. package/src/runtime/backend/raw-binding-port.ts +7 -2
  185. package/src/runtime/backend/runtime-message.ts +6 -0
  186. package/src/runtime/backend/runtime-values.ts +1 -0
  187. package/src/runtime/channels/channel-clients.ts +90 -41
  188. package/src/runtime/channels/channel-dispatch-pipeline.ts +69 -34
  189. package/src/runtime/channels/channel-dispatch-services.ts +69 -1
  190. package/src/runtime/channels/channel-dispatchers.ts +29 -27
  191. package/src/runtime/channels/channel-envelope-inspection.ts +2 -16
  192. package/src/runtime/channels/channel-envelope.ts +133 -8
  193. package/src/runtime/channels/channel-outbound-operations.ts +22 -8
  194. package/src/runtime/channels/channel-runtime-manager.ts +29 -12
  195. package/src/runtime/channels/channel-transports.ts +128 -60
  196. package/src/runtime/channels/local-spot-route-transport.ts +3 -1
  197. package/src/runtime/channels/router-socket-spot-route-transport.ts +13 -4
  198. package/src/runtime/channels/source-spot-router.ts +8 -4
  199. package/src/runtime/channels/spot-node-route-transport.ts +8 -4
  200. package/src/runtime/channels/spot-route-bridge-transport.ts +6 -4
  201. package/src/runtime/channels/spot-route-dispatch-strategy.ts +47 -18
  202. package/src/runtime/execution/serial-execution-queue.ts +2 -0
  203. package/src/runtime/foundation/actor-join-recovery-codec.ts +2 -2
  204. package/src/runtime/foundation/durable-service-request.ts +137 -0
  205. package/src/runtime/foundation/operation-identity.ts +5 -1
  206. package/src/runtime/foundation/raw-service-mesh-runtime.ts +484 -293
  207. package/src/runtime/foundation/service-relocation-object-owner.ts +2 -0
  208. package/src/runtime/foundation/service-relocation-runtime.ts +18 -1
  209. package/src/runtime/foundation/service-runtime-contracts.ts +7 -1
  210. package/src/runtime/foundation/service-stateful-runtime.ts +67 -125
  211. package/src/runtime/foundation/service-stateful-wire-codec.ts +0 -5
  212. package/src/runtime/foundation/service-topology-registry.ts +91 -36
  213. package/src/runtime/foundation/service-wire-m6a-codec.ts +57 -38
  214. package/src/runtime/handlers/handler-instance-scope.ts +67 -16
  215. package/src/runtime/host/actor-runtime-options-factory.ts +13 -2
  216. package/src/runtime/host/application-job-queue.ts +175 -41
  217. package/src/runtime/host/entry-actor-runtime.ts +4 -0
  218. package/src/runtime/host/index.ts +201 -156
  219. package/src/runtime/host/remote-bound-session-relay.ts +2 -23
  220. package/src/runtime/host/route-mesh-runtime.ts +1 -1
  221. package/src/runtime/host/service-relocation-control.ts +11 -5
  222. package/src/runtime/host/service-relocation-host-runtime.ts +315 -291
  223. package/src/runtime/host/spot-address-transport.ts +4 -2
  224. package/src/runtime/host/spot-runtime-options-factory.ts +2 -0
  225. package/src/runtime/locations/actor-location-claims.ts +52 -30
  226. package/src/runtime/locations/lifecycle.ts +8 -26
  227. package/src/runtime/locations/runtime.ts +28 -24
  228. package/src/runtime/messaging/framework-json-v1.ts +5 -325
  229. package/src/runtime/messaging/packet-name.ts +5 -25
  230. package/src/runtime/messaging/request-result.ts +58 -0
  231. package/src/runtime/messaging/submission-result.ts +5 -1
  232. package/src/runtime/protocol/service_wire_codec.generated.ts +131 -1
  233. package/src/runtime/protocol/service_wire_pilot_codec.generated.ts +4 -4
  234. package/src/runtime/spots/formal-remote-actor-admission-registry.ts +43 -23
  235. package/src/runtime/spots/index.ts +14 -2
  236. package/src/runtime/spots/spot-activation.ts +28 -10
  237. package/src/runtime/spots/spot-entry-activation.ts +9 -2
  238. package/src/runtime/spots/spot-handler-registry.ts +41 -8
  239. package/src/runtime/spots/spot-node-autoconnect.ts +6 -2
  240. package/src/runtime/spots/spot-outbound.ts +36 -16
  241. package/src/runtime/spots/spot-routed-spot-packet-dispatch.ts +2 -1
  242. package/src/runtime/spots/spot-runtime-ports.ts +1 -0
  243. package/src/runtime/spots/spot-subscription-dispatch.ts +0 -3
  244. package/src/runtime/spots/spot-timer.ts +5 -1
  245. package/src/runtime/streams/stream-session-runtime.ts +12 -29
@@ -30,8 +30,10 @@ class ZLinkChannelDispatchPipeline {
30
30
  }
31
31
  try {
32
32
  const flow = (0, flow_context_1.createInboundFlow)(dispatch.fields.flowId, dispatch.fields.flowOrigin, this.options.dispatchErrors.flow.flowCreationEnabled(), undefined);
33
- const invocation = await (0, flow_context_1.runWithFlow)(flow, () => this.invoke(dispatch.envelope, dispatch.codecs, dispatch.handler, dispatch.context, dispatch.fields, dispatch.signal));
34
- if (invocation.handlerInvoked) {
33
+ const invocation = await (flow === undefined
34
+ ? this.invoke(dispatch.envelope, dispatch.codecs, dispatch.handler, dispatch.context, dispatch.fields, dispatch.signal)
35
+ : (0, flow_context_1.runWithFlow)(flow, () => this.invoke(dispatch.envelope, dispatch.codecs, dispatch.handler, dispatch.context, dispatch.fields, dispatch.signal)));
36
+ if (invocation !== HANDLER_FILTER_REJECTED) {
35
37
  this.trace(ZLinkDispatchOptions_1.ZLinkRuntimeMessageFlowOutcome.Completed, dispatch.fields);
36
38
  }
37
39
  }
@@ -58,11 +60,13 @@ class ZLinkChannelDispatchPipeline {
58
60
  let reply;
59
61
  try {
60
62
  const flow = (0, flow_context_1.createInboundFlow)(dispatch.fields.flowId, dispatch.fields.flowOrigin, this.options.dispatchErrors.flow.flowCreationEnabled(), undefined);
61
- const invocation = await (0, flow_context_1.runWithFlow)(flow, () => this.invoke(dispatch.envelope, dispatch.codecs, dispatch.handler, dispatch.context, dispatch.fields, dispatch.signal));
62
- if (!invocation.handlerInvoked) {
63
+ const invocation = await (flow === undefined
64
+ ? this.invoke(dispatch.envelope, dispatch.codecs, dispatch.handler, dispatch.context, dispatch.fields, dispatch.signal)
65
+ : (0, flow_context_1.runWithFlow)(flow, () => this.invoke(dispatch.envelope, dispatch.codecs, dispatch.handler, dispatch.context, dispatch.fields, dispatch.signal)));
66
+ if (invocation === HANDLER_FILTER_REJECTED) {
63
67
  throw (0, framework_errors_internal_1.createInternalFrameworkException)(framework_errors_internal_1.ZLinkFrameworkInternalErrorKind.RequestRejected, `A handler filter rejected '${this.options.channelName}:${dispatch.fields.packetName}'.`);
64
68
  }
65
- reply = invocation.value;
69
+ reply = invocation;
66
70
  }
67
71
  catch (error) {
68
72
  try {
@@ -78,7 +82,9 @@ class ZLinkChannelDispatchPipeline {
78
82
  return;
79
83
  }
80
84
  try {
81
- await dispatch.writeReply(reply);
85
+ const written = dispatch.writeReply(reply);
86
+ if (written !== undefined)
87
+ await written;
82
88
  this.trace(ZLinkDispatchOptions_1.ZLinkRuntimeMessageFlowOutcome.Replied, dispatch.fields);
83
89
  }
84
90
  catch (error) {
@@ -99,8 +105,7 @@ class ZLinkChannelDispatchPipeline {
99
105
  */
100
106
  async dispatchMalformed(input) {
101
107
  const { info } = input;
102
- const isRequest = info.kind === 1 /* ZLinkChannelMessageKind.Request */ ||
103
- (info.kind === undefined && input.transportRequest);
108
+ const isRequest = input.transportRequest;
104
109
  let replied = false;
105
110
  if (isRequest && input.writeProtocolError !== undefined && info.correlationId !== undefined) {
106
111
  const protocolError = new contracts_1.ZLinkFrameworkException(contracts_1.ZLinkFrameworkErrorKind.ProtocolError, `Channel '${this.options.channelName}' received a malformed envelope.`);
@@ -126,15 +131,18 @@ class ZLinkChannelDispatchPipeline {
126
131
  error: input.error
127
132
  });
128
133
  }
129
- async invoke(envelope, codecs, handler, context, fields, signal) {
134
+ invoke(envelope, codecs, handler, context, fields, signal) {
130
135
  (0, application_job_queue_scope_1.releaseApplicationJobPermitBeforeHandler)();
131
136
  if (this.filters.length === 0) {
132
137
  // Fast path for the dominant unfiltered dispatch: skip the filter
133
138
  // context object and chain machinery entirely.
134
139
  const payload = (0, channel_envelope_1.decodeChannelPayload)(envelope, codecs);
135
140
  this.trace(ZLinkDispatchOptions_1.ZLinkRuntimeMessageFlowOutcome.Dispatched, fields);
136
- return { handlerInvoked: true, value: await handler.handle(payload, context) };
141
+ return handler.handle(payload, context);
137
142
  }
143
+ return this.invokeFiltered(envelope, codecs, handler, context, fields, signal);
144
+ }
145
+ async invokeFiltered(envelope, codecs, handler, context, fields, signal) {
138
146
  let value;
139
147
  const handlerInvoked = await (0, handlers_1.invokeZLinkHandlerFilters)(this.filters, this.createFilterContext(context, fields), async () => {
140
148
  // Filters are the channel admission gate. Decode only after they have
@@ -143,7 +151,7 @@ class ZLinkChannelDispatchPipeline {
143
151
  this.trace(ZLinkDispatchOptions_1.ZLinkRuntimeMessageFlowOutcome.Dispatched, fields);
144
152
  value = await handler.handle(payload, context);
145
153
  }, signal);
146
- return { handlerInvoked, value };
154
+ return handlerInvoked ? value : HANDLER_FILTER_REJECTED;
147
155
  }
148
156
  createFilterContext(context, fields) {
149
157
  const dispatchKind = this.dispatchKind(context, fields);
@@ -222,6 +230,7 @@ class ZLinkChannelDispatchPipeline {
222
230
  }
223
231
  }
224
232
  exports.ZLinkChannelDispatchPipeline = ZLinkChannelDispatchPipeline;
233
+ const HANDLER_FILTER_REJECTED = Symbol('handler-filter-rejected');
225
234
  const DEFAULT_UNHANDLED_DISPATCH = {
226
235
  request: contracts_1.ZLinkUnhandledDispatchAction.ReplyError,
227
236
  send: contracts_1.ZLinkUnhandledDispatchAction.LogAndDrop,
@@ -43,6 +43,7 @@ export declare class ZLinkChannelDispatchServices {
43
43
  channelSendHandler(handlerType: Type): ZLinkChannelSendHandler;
44
44
  routeRequestHandler(handlerType: Type): ZLinkRouteRuntimeRequestHandler;
45
45
  routeSendHandler(handlerType: Type): ZLinkRouteRuntimeSendHandler;
46
+ private invokeScopeFreeHandler;
46
47
  private invokeHandlerFilters;
47
48
  private withHandlerScope;
48
49
  beginOutbound(outcome: ZLinkMessageFlowOutcome, result?: ZLinkRuntimeMessageFlowResult): ZLinkChannelOutboundTracePoint | undefined;
@@ -48,6 +48,13 @@ class ZLinkChannelDispatchServices {
48
48
  return this.handlerFiltersValue;
49
49
  }
50
50
  channelRequestHandler(handlerType) {
51
+ const activate = this.registration.filterTypes.length === 0
52
+ ? (0, handler_instance_scope_1.prepareHandlerInstance)(this.providerResolver, handlerType)
53
+ : undefined;
54
+ if (activate !== undefined)
55
+ return {
56
+ handle: (payload, context) => this.invokeScopeFreeHandler(activate, payload, context)
57
+ };
51
58
  return {
52
59
  handle: (payload, context) => this.withHandlerScope(context, async (scope) => {
53
60
  const handler = await scope.resolve(handlerType);
@@ -56,6 +63,13 @@ class ZLinkChannelDispatchServices {
56
63
  };
57
64
  }
58
65
  channelSendHandler(handlerType) {
66
+ const activate = this.registration.filterTypes.length === 0
67
+ ? (0, handler_instance_scope_1.prepareHandlerInstance)(this.providerResolver, handlerType)
68
+ : undefined;
69
+ if (activate !== undefined)
70
+ return {
71
+ handle: (payload, context) => this.invokeScopeFreeHandler(activate, payload, context)
72
+ };
59
73
  return {
60
74
  handle: (payload, context) => this.withHandlerScope(context, async (scope) => {
61
75
  const handler = await scope.resolve(handlerType);
@@ -64,6 +78,13 @@ class ZLinkChannelDispatchServices {
64
78
  };
65
79
  }
66
80
  routeRequestHandler(handlerType) {
81
+ const activate = this.registration.filterTypes.length === 0
82
+ ? (0, handler_instance_scope_1.prepareHandlerInstance)(this.providerResolver, handlerType)
83
+ : undefined;
84
+ if (activate !== undefined)
85
+ return {
86
+ handle: (payload, context) => this.invokeScopeFreeHandler(activate, payload, context)
87
+ };
67
88
  return {
68
89
  handle: (payload, context) => this.withHandlerScope(context, async (scope) => {
69
90
  const handler = await scope.resolve(handlerType);
@@ -72,6 +93,13 @@ class ZLinkChannelDispatchServices {
72
93
  };
73
94
  }
74
95
  routeSendHandler(handlerType) {
96
+ const activate = this.registration.filterTypes.length === 0
97
+ ? (0, handler_instance_scope_1.prepareHandlerInstance)(this.providerResolver, handlerType)
98
+ : undefined;
99
+ if (activate !== undefined)
100
+ return {
101
+ handle: (payload, context) => this.invokeScopeFreeHandler(activate, payload, context)
102
+ };
75
103
  return {
76
104
  handle: (payload, context) => this.withHandlerScope(context, async (scope) => {
77
105
  const handler = await scope.resolve(handlerType);
@@ -79,6 +107,23 @@ class ZLinkChannelDispatchServices {
79
107
  })
80
108
  };
81
109
  }
110
+ invokeScopeFreeHandler(activate, payload, context) {
111
+ const handler = activate();
112
+ const cleanup = (0, handler_instance_scope_1.handlerInstanceCleanup)(handler);
113
+ if (cleanup === undefined)
114
+ return handler.handle(payload, context);
115
+ let result;
116
+ try {
117
+ result = handler.handle(payload, context);
118
+ }
119
+ catch (error) {
120
+ const disposed = cleanup.call(handler);
121
+ return Promise.resolve(disposed).then(() => {
122
+ throw error;
123
+ });
124
+ }
125
+ return Promise.resolve(result).finally(() => cleanup.call(handler));
126
+ }
82
127
  async invokeHandlerFilters(context, next, signal) {
83
128
  const scoped = (0, handler_filter_scope_1.handlerFilterScope)(this.providerResolver);
84
129
  if (scoped !== undefined) {
@@ -1,6 +1,6 @@
1
1
  import type { RoutingId, ZLinkMessageContext, ZLinkHandlerFilter, ZLinkPublishMessageContext, ZLinkRouteMessageContext, ZLinkUnhandledDispatchOptions } from '../../contracts';
2
2
  import type { Message } from '../../contracts/Common/Message';
3
- import type { ReceiveRecord } from '../foundation/service-runtime-contracts';
3
+ import { type ReceiveRecord } from '../foundation/service-runtime-contracts';
4
4
  import { type ZLinkRouteChannelOptions } from '../configuration';
5
5
  import type { ZLinkBackendSpotRouteBridge } from '../backend/contracts';
6
6
  import type { ZLinkRuntimeMetrics } from '../diagnostics';
@@ -5,12 +5,14 @@ exports.collectRouteChannelHandlers = collectRouteChannelHandlers;
5
5
  const contracts_1 = require("../../contracts");
6
6
  const ZLinkDispatchOptions_1 = require("../../contracts/Dispatch/ZLinkDispatchOptions");
7
7
  const runtime_values_1 = require("../backend/runtime-values");
8
+ const service_runtime_contracts_1 = require("../foundation/service-runtime-contracts");
8
9
  const configuration_1 = require("../configuration");
9
10
  const channel_envelope_1 = require("./channel-envelope");
10
11
  const channel_envelope_inspection_1 = require("./channel-envelope-inspection");
11
12
  const channel_multipart_1 = require("./channel-multipart");
12
13
  const channel_framework_packets_1 = require("./channel-framework-packets");
13
14
  const channel_dispatch_pipeline_1 = require("./channel-dispatch-pipeline");
15
+ const completedChannelReply = Promise.resolve();
14
16
  class ZLinkChannelRequestDispatcher {
15
17
  options;
16
18
  pipeline;
@@ -49,7 +51,7 @@ class ZLinkChannelRequestDispatcher {
49
51
  await this.pipeline.dispatchMalformed({
50
52
  info,
51
53
  error,
52
- transportRequest: replyToken !== null,
54
+ transportRequest: replyToken != null,
53
55
  writeProtocolError: replyToken === null
54
56
  ? undefined
55
57
  : (protocolError) => this.submitReply((0, channel_multipart_1.appendParts)(router.reply(received.routingId, replyToken), (0, channel_envelope_1.encodeChannelErrorReplyParts)((0, channel_envelope_inspection_1.malformedProtocolErrorRequestHeader)(this.options.channelName, info), protocolError)), signal)
@@ -124,9 +126,9 @@ class ZLinkChannelRequestDispatcher {
124
126
  writeError: (error) => this.submitReply((0, channel_multipart_1.appendParts)(router.reply(received.routingId, replyToken), (0, channel_envelope_1.encodeChannelErrorReplyParts)(envelope.header, error)), signal)
125
127
  });
126
128
  }
127
- async dispatchMesh(record, signal) {
129
+ dispatchMesh(record, signal) {
128
130
  if (record.parts.length === 0 || record.parts[0].data().length === 0) {
129
- return;
131
+ return completedChannelReply;
130
132
  }
131
133
  let envelope;
132
134
  try {
@@ -134,16 +136,15 @@ class ZLinkChannelRequestDispatcher {
134
136
  }
135
137
  catch (error) {
136
138
  const info = (0, channel_envelope_inspection_1.inspectMalformedChannelHeader)(record.parts, this.flowEnabled());
137
- await this.pipeline.dispatchMalformed({
139
+ return this.pipeline.dispatchMalformed({
138
140
  info,
139
141
  error,
140
- transportRequest: false,
142
+ transportRequest: isMeshRequest(record),
141
143
  sourceRid: record.sourceNodeRid == null ? undefined : String(record.sourceNodeRid),
142
144
  writeProtocolError: async (protocolError) => {
143
145
  requireMeshReplyAccepted(record.reply((0, channel_envelope_1.encodeChannelErrorReplyParts)((0, channel_envelope_inspection_1.malformedProtocolErrorRequestHeader)(this.options.channelName, info), protocolError)));
144
146
  }
145
147
  });
146
- return;
147
148
  }
148
149
  const packetName = envelope.packetName;
149
150
  if (packetName === undefined) {
@@ -151,7 +152,7 @@ class ZLinkChannelRequestDispatcher {
151
152
  }
152
153
  const correlationId = envelope.header.correlationId ?? undefined;
153
154
  if (envelope.header.kind === 3 /* ZLinkChannelMessageKind.Command */) {
154
- await this.pipeline.dispatchOneWay({
155
+ return this.pipeline.dispatchOneWay({
155
156
  fields: {
156
157
  messageKind: ZLinkDispatchOptions_1.ZLinkDispatchMessageKind.Send,
157
158
  packetName,
@@ -165,10 +166,9 @@ class ZLinkChannelRequestDispatcher {
165
166
  context: this.createMeshContext(envelope, record.sourceNodeRid),
166
167
  signal
167
168
  });
168
- return;
169
169
  }
170
170
  if (envelope.header.kind !== 1 /* ZLinkChannelMessageKind.Request */) {
171
- return;
171
+ return completedChannelReply;
172
172
  }
173
173
  const fields = {
174
174
  messageKind: ZLinkDispatchOptions_1.ZLinkDispatchMessageKind.Request,
@@ -177,7 +177,7 @@ class ZLinkChannelRequestDispatcher {
177
177
  flowId: envelope.header.flowId,
178
178
  flowOrigin: envelope.header.flowOrigin
179
179
  };
180
- await this.pipeline.dispatchRequest({
180
+ return this.pipeline.dispatchRequest({
181
181
  fields,
182
182
  envelope,
183
183
  codecs: this.options.codecs,
@@ -185,10 +185,10 @@ class ZLinkChannelRequestDispatcher {
185
185
  context: this.createMeshContext(envelope, record.sourceNodeRid),
186
186
  signal,
187
187
  missingHandlerMessage: `No channel request handler is registered for '${this.options.channelName}:${packetName}'.`,
188
- writeReply: async (reply) => {
188
+ writeReply: (reply) => {
189
189
  requireMeshReplyAccepted(record.reply((0, channel_envelope_1.encodeChannelReplyParts)(envelope.header, reply, this.options.codecs)));
190
190
  },
191
- writeError: async (error) => {
191
+ writeError: (error) => {
192
192
  requireMeshReplyAccepted(record.reply((0, channel_envelope_1.encodeChannelErrorReplyParts)(envelope.header, error)));
193
193
  }
194
194
  });
@@ -198,7 +198,7 @@ class ZLinkChannelRequestDispatcher {
198
198
  if (operation.submit() === false) {
199
199
  throw new configuration_1.ZLinkConfigurationException('Channel reply was not accepted by Core.');
200
200
  }
201
- return Promise.resolve();
201
+ return completedChannelReply;
202
202
  }
203
203
  createMeshContext(envelope, sourceNodeRid) {
204
204
  const base = {
@@ -381,7 +381,7 @@ class ZLinkRoutePacketDispatcher {
381
381
  await this.pipeline.dispatchMalformed({
382
382
  info,
383
383
  error,
384
- transportRequest: replyToken !== null,
384
+ transportRequest: replyToken != null,
385
385
  sourceRid: String(received.routingId),
386
386
  writeProtocolError: replyToken === null
387
387
  ? undefined
@@ -452,9 +452,9 @@ class ZLinkRoutePacketDispatcher {
452
452
  writeError: (error) => this.submitReply((0, channel_multipart_1.appendParts)(router.reply(received.routingId, replyToken), (0, channel_envelope_1.encodeChannelErrorReplyParts)(envelope.header, error)))
453
453
  });
454
454
  }
455
- async dispatchMesh(record, signal) {
455
+ dispatchMesh(record, signal) {
456
456
  if (record.parts.length === 0 || record.parts[0].data().length === 0) {
457
- return;
457
+ return completedChannelReply;
458
458
  }
459
459
  let envelope;
460
460
  try {
@@ -462,16 +462,15 @@ class ZLinkRoutePacketDispatcher {
462
462
  }
463
463
  catch (error) {
464
464
  const info = (0, channel_envelope_inspection_1.inspectMalformedChannelHeader)(record.parts, this.flowEnabled());
465
- await this.pipeline.dispatchMalformed({
465
+ return this.pipeline.dispatchMalformed({
466
466
  info,
467
467
  error,
468
- transportRequest: false,
468
+ transportRequest: isMeshRequest(record),
469
469
  sourceRid: record.sourceNodeRid == null ? undefined : String(record.sourceNodeRid),
470
470
  writeProtocolError: async (protocolError) => {
471
471
  requireMeshReplyAccepted(record.reply((0, channel_envelope_1.encodeChannelErrorReplyParts)((0, channel_envelope_inspection_1.malformedProtocolErrorRequestHeader)(this.routerChannelId, info), protocolError)));
472
472
  }
473
473
  });
474
- return;
475
474
  }
476
475
  const packetName = envelope.packetName;
477
476
  if (packetName === undefined) {
@@ -480,11 +479,10 @@ class ZLinkRoutePacketDispatcher {
480
479
  const sourceNodeRid = String(record.sourceNodeRid ?? '');
481
480
  const correlationId = envelope.header.correlationId ?? undefined;
482
481
  if (envelope.header.kind === 3 /* ZLinkChannelMessageKind.Command */) {
483
- await this.dispatchMeshCommand(envelope, packetName, sourceNodeRid, record.sourceNodeRid, signal);
484
- return;
482
+ return this.dispatchMeshCommand(envelope, packetName, sourceNodeRid, record.sourceNodeRid, signal);
485
483
  }
486
484
  if (envelope.header.kind !== 1 /* ZLinkChannelMessageKind.Request */) {
487
- return;
485
+ return completedChannelReply;
488
486
  }
489
487
  const fields = {
490
488
  messageKind: ZLinkDispatchOptions_1.ZLinkDispatchMessageKind.Request,
@@ -495,7 +493,7 @@ class ZLinkRoutePacketDispatcher {
495
493
  flowOrigin: envelope.header.flowOrigin
496
494
  };
497
495
  const codecs = (0, channel_framework_packets_1.codecsForFrameworkPacket)(packetName, this.codecs);
498
- await this.pipeline.dispatchRequest({
496
+ return this.pipeline.dispatchRequest({
499
497
  fields,
500
498
  envelope,
501
499
  codecs,
@@ -503,10 +501,10 @@ class ZLinkRoutePacketDispatcher {
503
501
  context: this.createRouteContext(envelope, record.sourceNodeRid),
504
502
  signal,
505
503
  missingHandlerMessage: `No routed request handler is registered for '${this.routerChannelId}:${packetName}'.`,
506
- writeReply: async (reply) => {
504
+ writeReply: (reply) => {
507
505
  requireMeshReplyAccepted(record.reply((0, channel_envelope_1.encodeChannelReplyParts)(envelope.header, reply, codecs)));
508
506
  },
509
- writeError: async (error) => {
507
+ writeError: (error) => {
510
508
  requireMeshReplyAccepted(record.reply((0, channel_envelope_1.encodeChannelErrorReplyParts)(envelope.header, error)));
511
509
  }
512
510
  });
@@ -558,7 +556,7 @@ class ZLinkRoutePacketDispatcher {
558
556
  if (operation.submit() === false) {
559
557
  throw new configuration_1.ZLinkConfigurationException('Route reply was not accepted by Core.');
560
558
  }
561
- return Promise.resolve();
559
+ return completedChannelReply;
562
560
  }
563
561
  createRouteContext(envelope, sourceRid) {
564
562
  const sourceNodeRid = String(sourceRid ?? '');
@@ -573,3 +571,6 @@ class ZLinkRoutePacketDispatcher {
573
571
  }
574
572
  }
575
573
  exports.ZLinkRoutePacketDispatcher = ZLinkRoutePacketDispatcher;
574
+ function isMeshRequest(record) {
575
+ return record.kind === service_runtime_contracts_1.ReceiveKind.NodeRequest || record.kind === service_runtime_contracts_1.ReceiveKind.ChannelRequest;
576
+ }
@@ -1,6 +1,6 @@
1
1
  import type { Message } from '../../contracts/Common/Message';
2
2
  import type { ZLinkFlowOrigin } from '../../contracts';
3
- import { ZLinkChannelMessageKind, type ZLinkChannelEnvelopeHeader } from './channel-envelope';
3
+ import { type ZLinkChannelEnvelopeHeader } from './channel-envelope';
4
4
  export declare function tryDecodeChannelHeader(parts: readonly Message[], flowEnabled?: boolean): ZLinkChannelEnvelopeHeader | undefined;
5
5
  /**
6
6
  * Identifiers salvaged from a malformed channel envelope. Spec 27 §7: a
@@ -9,7 +9,6 @@ export declare function tryDecodeChannelHeader(parts: readonly Message[], flowEn
9
9
  * present only when it is individually well-formed.
10
10
  */
11
11
  export interface ZLinkMalformedChannelHeaderInfo {
12
- readonly kind?: ZLinkChannelMessageKind;
13
12
  readonly channelName?: string;
14
13
  readonly messageName?: string;
15
14
  readonly correlationId?: string;
@@ -29,15 +29,12 @@ function inspectMalformedChannelHeader(parts, flowEnabled) {
29
29
  catch {
30
30
  return {};
31
31
  }
32
- if (header.formatMarker !== channel_envelope_1.ZLINK_CHANNEL_FORMAT_MARKER)
33
- return {};
34
32
  const flowId = typeof header.flowId === 'string' && CHANNEL_FLOW_ID_PATTERN.test(header.flowId)
35
33
  ? header.flowId
36
34
  : undefined;
37
35
  const flowOrigin = salvageFlowOrigin(header.flowOrigin);
38
36
  const flowPairValid = flowEnabled && flowId !== undefined && flowOrigin !== undefined;
39
37
  return {
40
- kind: salvageChannelKind(header.kind),
41
38
  channelName: salvageString(header.channelName),
42
39
  messageName: salvageString(header.messageName),
43
40
  correlationId: salvageCorrelationId(header.correlationId),
@@ -66,23 +63,11 @@ function malformedProtocolErrorRequestHeader(channelName, info) {
66
63
  };
67
64
  }
68
65
  const CHANNEL_FLOW_ID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/;
69
- function salvageChannelKind(value) {
70
- return value === 1 /* ZLinkChannelMessageKind.Request */ ||
71
- value === 2 /* ZLinkChannelMessageKind.Response */ ||
72
- value === 3 /* ZLinkChannelMessageKind.Command */ ||
73
- value === 4 /* ZLinkChannelMessageKind.Publish */ ||
74
- value === 5 /* ZLinkChannelMessageKind.Error */
75
- ? value
76
- : undefined;
77
- }
78
66
  function salvageString(value) {
79
67
  return typeof value === 'string' && value.length > 0 ? value : undefined;
80
68
  }
81
69
  function salvageCorrelationId(value) {
82
- if (typeof value !== 'string')
83
- return undefined;
84
- const byteLength = Buffer.byteLength(value, 'utf8');
85
- return byteLength >= 1 && byteLength <= 64 && /^[\x00-\x7f]*$/.test(value) ? value : undefined;
70
+ return typeof value === 'string' && (0, channel_envelope_1.isValidChannelCorrelationId)(value) ? value : undefined;
86
71
  }
87
72
  function salvageFlowOrigin(value) {
88
73
  switch (value) {
@@ -71,3 +71,4 @@ export declare function decodeChannelEnvelope(parts: readonly Message[], decoded
71
71
  export declare function decodeChannelPayload(envelope: ZLinkChannelEnvelope, codecs?: ZLinkChannelEnvelopeCodecRegistry): unknown;
72
72
  export declare function closeMessages(parts: readonly MessageLike[]): void;
73
73
  export declare function decodeChannelHeader(parts: readonly Message[], flowEnabled?: boolean): ZLinkChannelEnvelopeHeader;
74
+ export declare function isValidChannelCorrelationId(value: string): boolean;
@@ -13,6 +13,8 @@ exports.decodeChannelEnvelope = decodeChannelEnvelope;
13
13
  exports.decodeChannelPayload = decodeChannelPayload;
14
14
  exports.closeMessages = closeMessages;
15
15
  exports.decodeChannelHeader = decodeChannelHeader;
16
+ exports.isValidChannelCorrelationId = isValidChannelCorrelationId;
17
+ const runtime_message_1 = require("../backend/runtime-message");
16
18
  const node_crypto_1 = require("node:crypto");
17
19
  const node_buffer_1 = require("node:buffer");
18
20
  const contracts_1 = require("../../contracts");
@@ -34,6 +36,13 @@ exports.ZLINK_CHANNEL_FORMAT_MARKER = 0xf2;
34
36
  const EMPTY_OUTBOUND_METADATA = new Map();
35
37
  exports.JSON_CONTENT_TYPE = 'application/json';
36
38
  exports.BINARY_CONTENT_TYPE = 'application/octet-stream';
39
+ const preparedChannelHeaders = new WeakMap();
40
+ const CHANNEL_CORRELATION_FIELD = ',"correlationId":';
41
+ const CHANNEL_DEADLINE_FIELD = ',"deadline":';
42
+ const CHANNEL_CORRELATION_TEXT_LENGTH = 32;
43
+ const PREPARED_CHANNEL_CORRELATION = '0'.repeat(CHANNEL_CORRELATION_TEXT_LENGTH);
44
+ const PREPARED_CHANNEL_DEADLINE = '2000-01-01T00:00:00.000Z';
45
+ const CHANNEL_CORRELATION_TEXT = /^[0-9a-f]{32}$/;
37
46
  function newChannelCorrelationId() {
38
47
  return (0, node_crypto_1.randomUUID)().replaceAll('-', '');
39
48
  }
@@ -56,7 +65,7 @@ function encodeChannelEnvelopePartsAtDeadline(kind, channelName, packetName, pay
56
65
  const flow = createFlow ? (0, flow_context_1.currentOrCreateFlow)('Application') : undefined;
57
66
  const envelopeCorrelationId = correlationIdForOutboundKind(kind, correlationId);
58
67
  return [
59
- encodeChannelHeader(kind, channelName, messageName, encoded.contentType, envelopeCorrelationId, deadlineUnixMs === undefined ? null : new Date(deadlineUnixMs).toISOString(), topic ?? null, null, null, undefined, applicationMetadataRecord(metadata), flow?.flowId, flow?.flowOrigin),
68
+ encodeChannelHeader(kind, channelName, messageName, encoded.contentType, envelopeCorrelationId, deadlineUnixMs === undefined ? null : new Date(deadlineUnixMs).toISOString(), topic ?? null, null, null, undefined, applicationMetadataRecord(metadata), flow?.flowId, flow?.flowOrigin, codecs),
60
69
  encoded.message
61
70
  ];
62
71
  }
@@ -72,7 +81,7 @@ function encodeChannelPublishEnvelopeParts(channelName, topic, packetName, paylo
72
81
  function encodeChannelReplyParts(request, payload, codecs) {
73
82
  const encoded = encodePayload(payload ?? Buffer.alloc(0), (0, channel_framework_packets_1.codecsForFrameworkPacket)(request.messageName, codecs), request.messageName, 'reply');
74
83
  return [
75
- encodeChannelHeader(2 /* ZLinkChannelMessageKind.Response */, request.channelName, request.messageName, encoded.contentType, request.correlationId, null, null, undefined, undefined, undefined, EMPTY_APPLICATION_METADATA, request.flowId, request.flowOrigin),
84
+ encodeChannelHeader(2 /* ZLinkChannelMessageKind.Response */, request.channelName, request.messageName, encoded.contentType, request.correlationId, null, null, undefined, undefined, undefined, EMPTY_APPLICATION_METADATA, request.flowId, request.flowOrigin, codecs),
76
85
  encoded.message
77
86
  ];
78
87
  }
@@ -137,7 +146,7 @@ function decodeChannelReply(parts, codecs) {
137
146
  return undefined;
138
147
  }
139
148
  if (header.contentType === exports.BINARY_CONTENT_TYPE) {
140
- return Buffer.from(parts[1].data());
149
+ return runtime_message_1.ZLinkBufferMessage.retainPayload(parts[1]);
141
150
  }
142
151
  if (serializer !== undefined) {
143
152
  return serializer.deserialize(contracts_1.ZLinkEncodedPayload.from(parts[1].data()), Object);
@@ -270,7 +279,33 @@ function isMessage(value) {
270
279
  function encodeJsonBytes(value, schema) {
271
280
  return Buffer.from((0, framework_json_v1_1.stringifyFrameworkJsonV1)(value, schema));
272
281
  }
273
- function encodeChannelHeader(kind, channelName, messageName, contentType, correlationId, deadline, topic, errorCode, errorMessage, source, metadata, flowId, flowOrigin) {
282
+ function encodeChannelHeader(kind, channelName, messageName, contentType, correlationId, deadline, topic, errorCode, errorMessage, source, metadata, flowId, flowOrigin, codecs) {
283
+ if (codecs !== undefined &&
284
+ metadata === EMPTY_APPLICATION_METADATA &&
285
+ flowId === undefined &&
286
+ flowOrigin === undefined &&
287
+ topic === null &&
288
+ source === undefined &&
289
+ ((kind === 3 /* ZLinkChannelMessageKind.Command */ &&
290
+ correlationId === null &&
291
+ deadline === null &&
292
+ errorCode === null &&
293
+ errorMessage === null) ||
294
+ (kind === 1 /* ZLinkChannelMessageKind.Request */ &&
295
+ correlationId !== null &&
296
+ CHANNEL_CORRELATION_TEXT.test(correlationId) &&
297
+ deadline !== null &&
298
+ deadline.length === PREPARED_CHANNEL_DEADLINE.length &&
299
+ errorCode === null &&
300
+ errorMessage === null) ||
301
+ (kind === 2 /* ZLinkChannelMessageKind.Response */ &&
302
+ correlationId !== null &&
303
+ CHANNEL_CORRELATION_TEXT.test(correlationId) &&
304
+ deadline === null &&
305
+ errorCode === undefined &&
306
+ errorMessage === undefined))) {
307
+ return preparedChannelHeader(codecs, kind, channelName, messageName, contentType, correlationId, deadline, errorCode, errorMessage);
308
+ }
274
309
  // The wire has a fixed field order. Measure escaped UTF-8 first, then write
275
310
  // each field once into the only header Buffer: no header object, whole JSON
276
311
  // string, or post-encode byte copy exists on the outbound path.
@@ -281,6 +316,42 @@ function encodeChannelHeader(kind, channelName, messageName, contentType, correl
281
316
  writeChannelHeader(writer, kind, channelName, messageName, contentType, correlationId, deadline, topic, errorCode, errorMessage, source, metadata, flowId, flowOrigin);
282
317
  return result;
283
318
  }
319
+ function preparedChannelHeader(codecs, kind, channelName, messageName, contentType, correlationId, deadline, errorCode, errorMessage) {
320
+ let channels = preparedChannelHeaders.get(codecs.serializers);
321
+ if (channels === undefined)
322
+ preparedChannelHeaders.set(codecs.serializers, (channels = new Map()));
323
+ let packets = channels.get(channelName);
324
+ if (packets === undefined)
325
+ channels.set(channelName, (packets = new Map()));
326
+ let contentTypes = packets.get(messageName);
327
+ if (contentTypes === undefined)
328
+ packets.set(messageName, (contentTypes = new Map()));
329
+ let kinds = contentTypes.get(contentType);
330
+ if (kinds === undefined)
331
+ contentTypes.set(contentType, (kinds = new Map()));
332
+ let deadlines = kinds.get(kind);
333
+ if (deadlines === undefined)
334
+ kinds.set(kind, (deadlines = new Map()));
335
+ const hasDeadline = deadline !== null;
336
+ let prepared = deadlines.get(hasDeadline);
337
+ if (prepared === undefined) {
338
+ const bytes = encodeChannelHeader(kind, channelName, messageName, contentType, correlationId === null ? null : PREPARED_CHANNEL_CORRELATION, hasDeadline ? PREPARED_CHANNEL_DEADLINE : null, null, errorCode, errorMessage, undefined, EMPTY_APPLICATION_METADATA, undefined, undefined);
339
+ prepared = {
340
+ bytes,
341
+ correlationOffset: bytes.indexOf(CHANNEL_CORRELATION_FIELD) + CHANNEL_CORRELATION_FIELD.length + 1,
342
+ deadlineOffset: bytes.indexOf(CHANNEL_DEADLINE_FIELD) + CHANNEL_DEADLINE_FIELD.length + 1
343
+ };
344
+ deadlines.set(hasDeadline, prepared);
345
+ }
346
+ if (correlationId === null)
347
+ return prepared.bytes;
348
+ const bytes = Buffer.alloc(prepared.bytes.byteLength);
349
+ prepared.bytes.copy(bytes);
350
+ bytes.write(correlationId, prepared.correlationOffset, CHANNEL_CORRELATION_TEXT_LENGTH, 'ascii');
351
+ if (deadline !== null)
352
+ bytes.write(deadline, prepared.deadlineOffset, PREPARED_CHANNEL_DEADLINE.length, 'ascii');
353
+ return bytes;
354
+ }
284
355
  function writeChannelHeader(writer, kind, channelName, messageName, contentType, correlationId, deadline, topic, errorCode, errorMessage, source, metadata, flowId, flowOrigin) {
285
356
  writer.append('{"formatMarker":');
286
357
  writer.append(String(exports.ZLINK_CHANNEL_FORMAT_MARKER));
@@ -292,9 +363,9 @@ function writeChannelHeader(writer, kind, channelName, messageName, contentType,
292
363
  writer.string(messageName);
293
364
  writer.append(',"contentType":');
294
365
  writer.string(contentType);
295
- writer.append(',"correlationId":');
366
+ writer.append(CHANNEL_CORRELATION_FIELD);
296
367
  writer.nullableString(correlationId);
297
- writer.append(',"deadline":');
368
+ writer.append(CHANNEL_DEADLINE_FIELD);
298
369
  writer.nullableString(deadline);
299
370
  writer.append(',"topic":');
300
371
  writer.nullableString(topic);
@@ -681,9 +752,13 @@ function validateCorrelationForKind(kind, correlationId) {
681
752
  throw new configuration_1.ZLinkConfigurationException(`Channel ${channelKindName(kind)} must not contain correlationId.`);
682
753
  }
683
754
  }
755
+ const MAXIMUM_CORRELATION_ID_BYTES = 64;
756
+ function isValidChannelCorrelationId(value) {
757
+ const byteLength = Buffer.byteLength(value, 'utf8');
758
+ return (byteLength >= 1 && byteLength <= MAXIMUM_CORRELATION_ID_BYTES && /^[\x00-\x7f]*$/.test(value));
759
+ }
684
760
  function validateCorrelationValue(correlationId) {
685
- const byteLength = Buffer.byteLength(correlationId, 'utf8');
686
- if (byteLength < 1 || byteLength > 64 || !/^[\x00-\x7f]*$/.test(correlationId)) {
761
+ if (!isValidChannelCorrelationId(correlationId)) {
687
762
  throw new configuration_1.ZLinkConfigurationException('Channel envelope correlationId must be a non-empty ASCII value of at most 64 bytes.');
688
763
  }
689
764
  }
@@ -13,7 +13,7 @@ export declare class ZLinkChannelOutboundOperations {
13
13
  send(channelName: string, packetName: string | undefined, message: unknown, metadata?: ReadonlyMap<string, string>): Promise<ZLinkSubmitResult>;
14
14
  private sendScoped;
15
15
  private traceSend;
16
- request<TReply>(channelName: string, packetName: string | undefined, request: unknown, timeoutMs: number | undefined, signal?: AbortSignal, metadata?: ReadonlyMap<string, string>): Promise<TReply>;
16
+ request<TReply>(channelName: string, packetName: string | undefined, request: unknown, timeoutMs: number | undefined, signal?: AbortSignal, metadata?: ReadonlyMap<string, string>, onAdmitted?: () => void): Promise<TReply>;
17
17
  private requestScoped;
18
18
  tryPublish(channelName: string, topic: string, packetName: string | undefined, event: unknown, metadata?: ReadonlyMap<string, string>): ZLinkSubmitResult;
19
19
  private tryPublishScoped;
@@ -22,7 +22,7 @@ export declare class ZLinkChannelOutboundOperations {
22
22
  routeSubmit(routerChannelId: string, targetNodeRid: string, packetName: string | undefined, message: unknown, metadata?: ReadonlyMap<string, string>): Promise<ZLinkSubmitResult>;
23
23
  private routeSubmitScoped;
24
24
  private traceRouteSend;
25
- routeRequest<TReply>(routerChannelId: string, targetNodeRid: string, packetName: string | undefined, request: unknown, timeoutMs: number | undefined, signal?: AbortSignal, metadata?: ReadonlyMap<string, string>): Promise<TReply>;
25
+ routeRequest<TReply>(routerChannelId: string, targetNodeRid: string, packetName: string | undefined, request: unknown, timeoutMs: number | undefined, signal?: AbortSignal, metadata?: ReadonlyMap<string, string>, onAdmitted?: () => void): Promise<TReply>;
26
26
  private routeRequestScoped;
27
27
  private measureRequest;
28
28
  }