@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.
- package/LICENSE +150 -68
- package/dist/.tsbuildinfo +1 -1
- package/dist/contracts/Actors/ZLinkActorClient.d.ts +2 -1
- package/dist/contracts/Channels/Calls.d.ts +2 -1
- package/dist/contracts/Common/ZLinkMessageMetadata.js +11 -5
- package/dist/contracts/Handlers/Attributes.d.ts +5 -13
- package/dist/contracts/Handlers/Attributes.js +7 -11
- package/dist/contracts/Handlers/JsonContract.d.ts +2 -46
- package/dist/contracts/Handlers/JsonContract.js +4 -153
- package/dist/contracts/Spots/Contracts.d.ts +2 -1
- package/dist/nest-integration.d.ts +1 -1
- package/dist/nest-integration.js +2 -1
- package/dist/runtime/actors/actor-client.d.ts +1 -1
- package/dist/runtime/actors/actor-client.js +14 -12
- package/dist/runtime/actors/actor-handoff.d.ts +1 -1
- package/dist/runtime/actors/actor-handoff.js +7 -4
- package/dist/runtime/actors/actor-join-relocation.d.ts +1 -0
- package/dist/runtime/actors/actor-local-native-join.js +9 -12
- package/dist/runtime/actors/actor-remote-wire.js +15 -0
- package/dist/runtime/actors/actor-routed-join-transport.d.ts +6 -2
- package/dist/runtime/actors/actor-routed-json-request.d.ts +2 -0
- package/dist/runtime/actors/index.d.ts +2 -1
- package/dist/runtime/actors/index.js +18 -6
- package/dist/runtime/actors/spot-actor-dispatch.js +2 -2
- package/dist/runtime/admission.d.ts +1 -1
- package/dist/runtime/admission.js +15 -5
- package/dist/runtime/application-jobs/application-ingress-record-owner.d.ts +6 -8
- package/dist/runtime/application-jobs/application-ingress-record-owner.js +39 -22
- package/dist/runtime/application-jobs/application-job-queue-scope.d.ts +2 -1
- package/dist/runtime/application-jobs/application-job-queue-scope.js +37 -22
- package/dist/runtime/application-jobs/contracts.d.ts +10 -1
- package/dist/runtime/backend/contracts/index.d.ts +18 -9
- package/dist/runtime/backend/mesh-completion-table.d.ts +9 -1
- package/dist/runtime/backend/mesh-completion-table.js +149 -49
- package/dist/runtime/backend/mesh-dispatch-pump.d.ts +3 -0
- package/dist/runtime/backend/mesh-dispatch-pump.js +32 -11
- package/dist/runtime/backend/node/node-backend-adapter-support.d.ts +2 -2
- package/dist/runtime/backend/node/node-backend-adapter-support.js +16 -9
- package/dist/runtime/backend/node/node-dealer-channel-client-transport.d.ts +1 -1
- package/dist/runtime/backend/node/node-dealer-channel-client-transport.js +5 -2
- package/dist/runtime/backend/node/node-raw-binding-port.js +42 -22
- package/dist/runtime/backend/node/node-raw-mesh-backend.d.ts +13 -5
- package/dist/runtime/backend/node/node-raw-mesh-backend.js +69 -51
- package/dist/runtime/backend/node/node-socket-backend-adapter.js +6 -6
- package/dist/runtime/backend/raw-binding-port.d.ts +2 -2
- package/dist/runtime/backend/runtime-message.d.ts +1 -0
- package/dist/runtime/backend/runtime-message.js +5 -0
- package/dist/runtime/backend/runtime-values.d.ts +1 -0
- package/dist/runtime/backend/runtime-values.js +2 -1
- package/dist/runtime/channels/channel-clients.d.ts +1 -0
- package/dist/runtime/channels/channel-clients.js +58 -21
- package/dist/runtime/channels/channel-dispatch-pipeline.d.ts +3 -2
- package/dist/runtime/channels/channel-dispatch-pipeline.js +20 -11
- package/dist/runtime/channels/channel-dispatch-services.d.ts +1 -0
- package/dist/runtime/channels/channel-dispatch-services.js +45 -0
- package/dist/runtime/channels/channel-dispatchers.d.ts +1 -1
- package/dist/runtime/channels/channel-dispatchers.js +27 -26
- package/dist/runtime/channels/channel-envelope-inspection.d.ts +1 -2
- package/dist/runtime/channels/channel-envelope-inspection.js +1 -16
- package/dist/runtime/channels/channel-envelope.d.ts +1 -0
- package/dist/runtime/channels/channel-envelope.js +83 -8
- package/dist/runtime/channels/channel-outbound-operations.d.ts +2 -2
- package/dist/runtime/channels/channel-outbound-operations.js +8 -8
- package/dist/runtime/channels/channel-runtime-manager.d.ts +6 -6
- package/dist/runtime/channels/channel-runtime-manager.js +12 -12
- package/dist/runtime/channels/channel-transports.d.ts +18 -15
- package/dist/runtime/channels/channel-transports.js +48 -31
- package/dist/runtime/channels/local-spot-route-transport.d.ts +1 -1
- package/dist/runtime/channels/local-spot-route-transport.js +2 -1
- package/dist/runtime/channels/router-socket-spot-route-transport.d.ts +2 -2
- package/dist/runtime/channels/router-socket-spot-route-transport.js +4 -4
- package/dist/runtime/channels/source-spot-router.d.ts +2 -2
- package/dist/runtime/channels/source-spot-router.js +4 -4
- package/dist/runtime/channels/spot-node-route-transport.d.ts +2 -2
- package/dist/runtime/channels/spot-node-route-transport.js +4 -4
- package/dist/runtime/channels/spot-route-bridge-transport.d.ts +2 -2
- package/dist/runtime/channels/spot-route-bridge-transport.js +4 -4
- package/dist/runtime/channels/spot-route-dispatch-strategy.d.ts +5 -4
- package/dist/runtime/channels/spot-route-dispatch-strategy.js +18 -18
- package/dist/runtime/execution/serial-execution-queue.d.ts +1 -0
- package/dist/runtime/execution/serial-execution-queue.js +1 -0
- package/dist/runtime/foundation/actor-join-recovery-codec.js +2 -2
- package/dist/runtime/foundation/durable-service-request.d.ts +14 -0
- package/dist/runtime/foundation/durable-service-request.js +98 -0
- package/dist/runtime/foundation/operation-identity.d.ts +1 -0
- package/dist/runtime/foundation/operation-identity.js +5 -1
- package/dist/runtime/foundation/raw-service-mesh-runtime.d.ts +22 -5
- package/dist/runtime/foundation/raw-service-mesh-runtime.js +356 -232
- package/dist/runtime/foundation/service-relocation-object-owner.d.ts +1 -0
- package/dist/runtime/foundation/service-relocation-object-owner.js +1 -0
- package/dist/runtime/foundation/service-relocation-runtime.d.ts +2 -0
- package/dist/runtime/foundation/service-relocation-runtime.js +13 -1
- package/dist/runtime/foundation/service-runtime-contracts.d.ts +2 -0
- package/dist/runtime/foundation/service-stateful-runtime.d.ts +4 -4
- package/dist/runtime/foundation/service-stateful-runtime.js +44 -103
- package/dist/runtime/foundation/service-stateful-wire-codec.d.ts +0 -5
- package/dist/runtime/foundation/service-topology-registry.d.ts +12 -2
- package/dist/runtime/foundation/service-topology-registry.js +61 -27
- package/dist/runtime/foundation/service-wire-m6a-codec.d.ts +3 -3
- package/dist/runtime/foundation/service-wire-m6a-codec.js +36 -38
- package/dist/runtime/handlers/handler-instance-scope.d.ts +8 -0
- package/dist/runtime/handlers/handler-instance-scope.js +54 -11
- package/dist/runtime/host/actor-runtime-options-factory.js +2 -2
- package/dist/runtime/host/application-job-queue.d.ts +19 -7
- package/dist/runtime/host/application-job-queue.js +150 -42
- package/dist/runtime/host/entry-actor-runtime.d.ts +1 -0
- package/dist/runtime/host/entry-actor-runtime.js +3 -0
- package/dist/runtime/host/index.d.ts +7 -1
- package/dist/runtime/host/index.js +142 -118
- package/dist/runtime/host/remote-bound-session-relay.js +2 -18
- package/dist/runtime/host/route-mesh-runtime.js +1 -1
- package/dist/runtime/host/service-relocation-control.d.ts +1 -0
- package/dist/runtime/host/service-relocation-control.js +10 -4
- package/dist/runtime/host/service-relocation-host-runtime.d.ts +6 -8
- package/dist/runtime/host/service-relocation-host-runtime.js +213 -241
- package/dist/runtime/host/spot-address-transport.js +3 -2
- package/dist/runtime/host/spot-runtime-options-factory.js +1 -0
- package/dist/runtime/locations/actor-location-claims.d.ts +2 -2
- package/dist/runtime/locations/actor-location-claims.js +34 -19
- package/dist/runtime/locations/lifecycle.d.ts +1 -2
- package/dist/runtime/locations/lifecycle.js +2 -5
- package/dist/runtime/locations/runtime.d.ts +1 -1
- package/dist/runtime/locations/runtime.js +24 -23
- package/dist/runtime/messaging/framework-json-v1.d.ts +4 -6
- package/dist/runtime/messaging/framework-json-v1.js +38 -294
- package/dist/runtime/messaging/packet-name.d.ts +1 -1
- package/dist/runtime/messaging/packet-name.js +8 -24
- package/dist/runtime/messaging/request-result.d.ts +2 -0
- package/dist/runtime/messaging/request-result.js +54 -0
- package/dist/runtime/messaging/submission-result.d.ts +1 -0
- package/dist/runtime/messaging/submission-result.js +5 -2
- package/dist/runtime/protocol/service_wire_codec.generated.d.ts +15 -0
- package/dist/runtime/protocol/service_wire_codec.generated.js +144 -0
- package/dist/runtime/protocol/service_wire_pilot_codec.generated.d.ts +9 -0
- package/dist/runtime/protocol/service_wire_pilot_codec.generated.js +14 -1
- package/dist/runtime/spots/formal-remote-actor-admission-registry.d.ts +7 -2
- package/dist/runtime/spots/formal-remote-actor-admission-registry.js +33 -19
- package/dist/runtime/spots/index.d.ts +3 -0
- package/dist/runtime/spots/index.js +9 -2
- package/dist/runtime/spots/spot-activation.d.ts +1 -0
- package/dist/runtime/spots/spot-activation.js +17 -8
- package/dist/runtime/spots/spot-entry-activation.js +6 -2
- package/dist/runtime/spots/spot-handler-registry.d.ts +3 -1
- package/dist/runtime/spots/spot-handler-registry.js +18 -8
- package/dist/runtime/spots/spot-node-autoconnect.js +4 -3
- package/dist/runtime/spots/spot-outbound.d.ts +3 -0
- package/dist/runtime/spots/spot-outbound.js +24 -15
- package/dist/runtime/spots/spot-routed-spot-packet-dispatch.d.ts +1 -0
- package/dist/runtime/spots/spot-routed-spot-packet-dispatch.js +1 -1
- package/dist/runtime/spots/spot-runtime-ports.d.ts +1 -0
- package/dist/runtime/spots/spot-subscription-dispatch.js +0 -3
- package/dist/runtime/spots/spot-timer.js +1 -0
- package/dist/runtime/streams/stream-session-runtime.d.ts +1 -1
- package/dist/runtime/streams/stream-session-runtime.js +13 -27
- package/package.json +2 -2
- package/src/contracts/Actors/ZLinkActorClient.ts +2 -1
- package/src/contracts/Channels/Calls.ts +2 -1
- package/src/contracts/Common/ZLinkMessageMetadata.ts +13 -8
- package/src/contracts/Handlers/Attributes.ts +14 -21
- package/src/contracts/Handlers/JsonContract.ts +8 -216
- package/src/contracts/Spots/Contracts.ts +2 -1
- package/src/nest-integration.ts +1 -0
- package/src/runtime/actors/actor-client.ts +40 -16
- package/src/runtime/actors/actor-handoff.ts +9 -4
- package/src/runtime/actors/actor-join-relocation.ts +1 -0
- package/src/runtime/actors/actor-local-native-join.ts +17 -26
- package/src/runtime/actors/actor-remote-wire.ts +17 -0
- package/src/runtime/actors/actor-routed-join-transport.ts +14 -4
- package/src/runtime/actors/actor-routed-json-request.ts +10 -2
- package/src/runtime/actors/index.ts +19 -5
- package/src/runtime/actors/spot-actor-dispatch.ts +4 -2
- package/src/runtime/admission.ts +18 -5
- package/src/runtime/application-jobs/application-ingress-record-owner.ts +41 -25
- package/src/runtime/application-jobs/application-job-queue-scope.ts +51 -22
- package/src/runtime/application-jobs/contracts.ts +14 -1
- package/src/runtime/backend/contracts/index.ts +53 -14
- package/src/runtime/backend/mesh-completion-table.ts +156 -57
- package/src/runtime/backend/mesh-dispatch-pump.ts +40 -10
- package/src/runtime/backend/node/node-backend-adapter-support.ts +17 -8
- package/src/runtime/backend/node/node-dealer-channel-client-transport.ts +12 -2
- package/src/runtime/backend/node/node-raw-binding-port.ts +57 -30
- package/src/runtime/backend/node/node-raw-mesh-backend.ts +128 -65
- package/src/runtime/backend/node/node-socket-backend-adapter.ts +21 -6
- package/src/runtime/backend/raw-binding-port.ts +7 -2
- package/src/runtime/backend/runtime-message.ts +6 -0
- package/src/runtime/backend/runtime-values.ts +1 -0
- package/src/runtime/channels/channel-clients.ts +90 -41
- package/src/runtime/channels/channel-dispatch-pipeline.ts +69 -34
- package/src/runtime/channels/channel-dispatch-services.ts +69 -1
- package/src/runtime/channels/channel-dispatchers.ts +29 -27
- package/src/runtime/channels/channel-envelope-inspection.ts +2 -16
- package/src/runtime/channels/channel-envelope.ts +133 -8
- package/src/runtime/channels/channel-outbound-operations.ts +22 -8
- package/src/runtime/channels/channel-runtime-manager.ts +29 -12
- package/src/runtime/channels/channel-transports.ts +128 -60
- package/src/runtime/channels/local-spot-route-transport.ts +3 -1
- package/src/runtime/channels/router-socket-spot-route-transport.ts +13 -4
- package/src/runtime/channels/source-spot-router.ts +8 -4
- package/src/runtime/channels/spot-node-route-transport.ts +8 -4
- package/src/runtime/channels/spot-route-bridge-transport.ts +6 -4
- package/src/runtime/channels/spot-route-dispatch-strategy.ts +47 -18
- package/src/runtime/execution/serial-execution-queue.ts +2 -0
- package/src/runtime/foundation/actor-join-recovery-codec.ts +2 -2
- package/src/runtime/foundation/durable-service-request.ts +137 -0
- package/src/runtime/foundation/operation-identity.ts +5 -1
- package/src/runtime/foundation/raw-service-mesh-runtime.ts +484 -293
- package/src/runtime/foundation/service-relocation-object-owner.ts +2 -0
- package/src/runtime/foundation/service-relocation-runtime.ts +18 -1
- package/src/runtime/foundation/service-runtime-contracts.ts +7 -1
- package/src/runtime/foundation/service-stateful-runtime.ts +67 -125
- package/src/runtime/foundation/service-stateful-wire-codec.ts +0 -5
- package/src/runtime/foundation/service-topology-registry.ts +91 -36
- package/src/runtime/foundation/service-wire-m6a-codec.ts +57 -38
- package/src/runtime/handlers/handler-instance-scope.ts +67 -16
- package/src/runtime/host/actor-runtime-options-factory.ts +13 -2
- package/src/runtime/host/application-job-queue.ts +175 -41
- package/src/runtime/host/entry-actor-runtime.ts +4 -0
- package/src/runtime/host/index.ts +201 -156
- package/src/runtime/host/remote-bound-session-relay.ts +2 -23
- package/src/runtime/host/route-mesh-runtime.ts +1 -1
- package/src/runtime/host/service-relocation-control.ts +11 -5
- package/src/runtime/host/service-relocation-host-runtime.ts +315 -291
- package/src/runtime/host/spot-address-transport.ts +4 -2
- package/src/runtime/host/spot-runtime-options-factory.ts +2 -0
- package/src/runtime/locations/actor-location-claims.ts +52 -30
- package/src/runtime/locations/lifecycle.ts +8 -26
- package/src/runtime/locations/runtime.ts +28 -24
- package/src/runtime/messaging/framework-json-v1.ts +5 -325
- package/src/runtime/messaging/packet-name.ts +5 -25
- package/src/runtime/messaging/request-result.ts +58 -0
- package/src/runtime/messaging/submission-result.ts +5 -1
- package/src/runtime/protocol/service_wire_codec.generated.ts +131 -1
- package/src/runtime/protocol/service_wire_pilot_codec.generated.ts +4 -4
- package/src/runtime/spots/formal-remote-actor-admission-registry.ts +43 -23
- package/src/runtime/spots/index.ts +14 -2
- package/src/runtime/spots/spot-activation.ts +28 -10
- package/src/runtime/spots/spot-entry-activation.ts +9 -2
- package/src/runtime/spots/spot-handler-registry.ts +41 -8
- package/src/runtime/spots/spot-node-autoconnect.ts +6 -2
- package/src/runtime/spots/spot-outbound.ts +36 -16
- package/src/runtime/spots/spot-routed-spot-packet-dispatch.ts +2 -1
- package/src/runtime/spots/spot-runtime-ports.ts +1 -0
- package/src/runtime/spots/spot-subscription-dispatch.ts +0 -3
- package/src/runtime/spots/spot-timer.ts +5 -1
- 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 (
|
|
34
|
-
|
|
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 (
|
|
62
|
-
|
|
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
|
|
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
|
-
|
|
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 =
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
139
|
+
return this.pipeline.dispatchMalformed({
|
|
138
140
|
info,
|
|
139
141
|
error,
|
|
140
|
-
transportRequest:
|
|
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
|
-
|
|
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
|
-
|
|
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:
|
|
188
|
+
writeReply: (reply) => {
|
|
189
189
|
requireMeshReplyAccepted(record.reply((0, channel_envelope_1.encodeChannelReplyParts)(envelope.header, reply, this.options.codecs)));
|
|
190
190
|
},
|
|
191
|
-
writeError:
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
465
|
+
return this.pipeline.dispatchMalformed({
|
|
466
466
|
info,
|
|
467
467
|
error,
|
|
468
|
-
transportRequest:
|
|
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
|
-
|
|
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
|
-
|
|
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:
|
|
504
|
+
writeReply: (reply) => {
|
|
507
505
|
requireMeshReplyAccepted(record.reply((0, channel_envelope_1.encodeChannelReplyParts)(envelope.header, reply, codecs)));
|
|
508
506
|
},
|
|
509
|
-
writeError:
|
|
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
|
|
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 {
|
|
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
|
-
|
|
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
|
|
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(
|
|
366
|
+
writer.append(CHANNEL_CORRELATION_FIELD);
|
|
296
367
|
writer.nullableString(correlationId);
|
|
297
|
-
writer.append(
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
}
|