@zlink-systems/framework 0.30.1 → 0.30.2
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/dist/.tsbuildinfo +1 -1
- package/dist/contracts/Common/ZLinkEncodedPayload.d.ts +6 -0
- package/dist/contracts/Common/ZLinkEncodedPayload.js +18 -3
- package/dist/contracts/Common/encoded-payload-storage.d.ts +1 -1
- package/dist/contracts/Common/encoded-payload-storage.js +5 -2
- package/dist/contracts/Configuration/Builders.d.ts +1 -1
- package/dist/contracts/Configuration/RegistrationBuilderPolicy.d.ts +2 -1
- package/dist/contracts/Configuration/RegistrationBuilderPolicy.js +5 -1
- package/dist/contracts/Configuration/RegistrationBuilders.js +2 -2
- package/dist/contracts/Configuration/RegistrationTypes.d.ts +1 -0
- package/dist/contracts/Dispatch/ZLinkDispatchOptions.d.ts +2 -2
- package/dist/contracts/Locations/Rows.d.ts +2 -0
- package/dist/contracts/Spots/Contracts.d.ts +4 -0
- package/dist/contracts/Spots/ZLinkSpot.d.ts +3 -3
- package/dist/runtime/abort.d.ts +5 -0
- package/dist/runtime/abort.js +10 -0
- package/dist/runtime/actors/actor-authority-publication.js +3 -2
- package/dist/runtime/actors/actor-client.d.ts +0 -1
- package/dist/runtime/actors/actor-client.js +38 -45
- package/dist/runtime/actors/actor-context.d.ts +2 -0
- package/dist/runtime/actors/actor-context.js +46 -9
- package/dist/runtime/actors/actor-handoff.d.ts +7 -3
- package/dist/runtime/actors/actor-handoff.js +212 -88
- package/dist/runtime/actors/actor-join-relocation.d.ts +2 -0
- package/dist/runtime/actors/actor-local-native-join.js +4 -0
- package/dist/runtime/actors/actor-mailbox.js +27 -1
- package/dist/runtime/actors/actor-remote-joiner.js +3 -1
- package/dist/runtime/actors/actor-reply.d.ts +4 -0
- package/dist/runtime/actors/actor-reply.js +29 -0
- package/dist/runtime/actors/actor-runtime-contracts.d.ts +2 -0
- package/dist/runtime/actors/actor-runtime-state.js +2 -20
- package/dist/runtime/actors/actor-source-transfer.d.ts +1 -17
- package/dist/runtime/actors/index.d.ts +6 -2
- package/dist/runtime/actors/index.js +37 -21
- package/dist/runtime/actors/session-disconnected-wire.d.ts +8 -0
- package/dist/runtime/actors/session-disconnected-wire.js +48 -0
- package/dist/runtime/admission.d.ts +9 -1
- package/dist/runtime/admission.js +55 -32
- package/dist/runtime/application-jobs/application-job-queue-scope.d.ts +13 -0
- package/dist/runtime/application-jobs/application-job-queue-scope.js +27 -1
- package/dist/runtime/application-jobs/contracts.d.ts +2 -0
- package/dist/runtime/backend/contracts/index.d.ts +19 -3
- package/dist/runtime/backend/mesh-actor-session-node-adapter.js +2 -2
- package/dist/runtime/backend/mesh-completion-table.js +5 -0
- package/dist/runtime/backend/mesh-dispatch-pump.d.ts +26 -2
- package/dist/runtime/backend/mesh-dispatch-pump.js +193 -107
- package/dist/runtime/backend/node/node-raw-binding-port.js +90 -58
- package/dist/runtime/backend/node/node-raw-mesh-backend.d.ts +33 -8
- package/dist/runtime/backend/node/node-raw-mesh-backend.js +142 -143
- package/dist/runtime/backend/node/node-socket-backend-adapter.d.ts +1 -1
- package/dist/runtime/backend/node/node-socket-backend-adapter.js +5 -5
- package/dist/runtime/channels/channel-clients.d.ts +1 -0
- package/dist/runtime/channels/channel-clients.js +20 -5
- package/dist/runtime/channels/channel-dispatch-pipeline.d.ts +22 -3
- package/dist/runtime/channels/channel-dispatch-pipeline.js +103 -57
- package/dist/runtime/channels/channel-dispatchers.d.ts +3 -2
- package/dist/runtime/channels/channel-dispatchers.js +44 -37
- package/dist/runtime/channels/channel-envelope.d.ts +1 -0
- package/dist/runtime/channels/channel-envelope.js +74 -31
- package/dist/runtime/channels/channel-runtime-lifecycle.d.ts +4 -3
- package/dist/runtime/channels/channel-runtime-lifecycle.js +19 -24
- package/dist/runtime/channels/channel-runtime-manager.d.ts +3 -2
- package/dist/runtime/channels/channel-runtime-manager.js +4 -4
- package/dist/runtime/channels/channel-transports.d.ts +0 -1
- package/dist/runtime/channels/channel-transports.js +35 -33
- package/dist/runtime/channels/client-server-location-runtime.js +5 -4
- package/dist/runtime/channels/dispatch-error-reporter.d.ts +2 -1
- package/dist/runtime/channels/dispatch-error-reporter.js +2 -1
- package/dist/runtime/channels/fanout-location-runtime.d.ts +1 -1
- package/dist/runtime/channels/fanout-location-runtime.js +3 -3
- package/dist/runtime/diagnostics/flow-context.js +19 -7
- package/dist/runtime/diagnostics/index.js +4 -9
- package/dist/runtime/diagnostics/message-flow.d.ts +8 -0
- package/dist/runtime/diagnostics/message-flow.js +35 -5
- package/dist/runtime/diagnostics/runtime-metrics.d.ts +2 -2
- package/dist/runtime/diagnostics/runtime-metrics.js +10 -8
- package/dist/runtime/execution/index.d.ts +4 -2
- package/dist/runtime/execution/index.js +33 -10
- package/dist/runtime/execution/serial-execution-queue.d.ts +4 -0
- package/dist/runtime/execution/serial-execution-queue.js +21 -2
- package/dist/runtime/execution/state-lane.d.ts +2 -0
- package/dist/runtime/execution/state-lane.js +5 -0
- package/dist/runtime/foundation/operation-registry.d.ts +25 -1
- package/dist/runtime/foundation/operation-registry.js +86 -18
- package/dist/runtime/foundation/raw-service-mesh-runtime.d.ts +39 -3
- package/dist/runtime/foundation/raw-service-mesh-runtime.js +151 -55
- package/dist/runtime/foundation/service-liveness-registry.d.ts +12 -1
- package/dist/runtime/foundation/service-liveness-registry.js +38 -0
- package/dist/runtime/foundation/service-mailbox.d.ts +7 -0
- package/dist/runtime/foundation/service-maintenance-runtime.js +1 -6
- package/dist/runtime/foundation/service-relocation-object-owner.d.ts +2 -3
- package/dist/runtime/foundation/service-relocation-object-owner.js +48 -35
- package/dist/runtime/foundation/service-relocation-runtime.js +7 -3
- package/dist/runtime/foundation/service-runtime-contracts.d.ts +8 -1
- package/dist/runtime/foundation/service-session-binding-ingress-port.d.ts +2 -1
- package/dist/runtime/foundation/service-stateful-registry.d.ts +5 -4
- package/dist/runtime/foundation/service-stateful-registry.js +24 -26
- package/dist/runtime/foundation/service-stateful-runtime.d.ts +72 -6
- package/dist/runtime/foundation/service-stateful-runtime.js +444 -117
- package/dist/runtime/foundation/service-stateful-wire-codec.d.ts +14 -1
- package/dist/runtime/foundation/service-stateful-wire-codec.js +48 -27
- package/dist/runtime/foundation/service-wire-binary-primitives.d.ts +6 -1
- package/dist/runtime/foundation/service-wire-binary-primitives.js +27 -11
- package/dist/runtime/foundation/service-wire-constants.generated.d.ts +1 -0
- package/dist/runtime/foundation/service-wire-constants.generated.js +1 -0
- package/dist/runtime/foundation/service-wire-m6a-codec.d.ts +10 -0
- package/dist/runtime/foundation/service-wire-m6a-codec.js +166 -53
- package/dist/runtime/host/actor-packet-relay.d.ts +6 -4
- package/dist/runtime/host/actor-packet-relay.js +59 -72
- package/dist/runtime/host/actor-placement-coordinator.js +25 -8
- package/dist/runtime/host/actor-transfer-runtime.d.ts +7 -31
- package/dist/runtime/host/actor-transfer-runtime.js +85 -331
- package/dist/runtime/host/application-job-queue.d.ts +24 -3
- package/dist/runtime/host/application-job-queue.js +28 -41
- package/dist/runtime/host/index.d.ts +5 -1
- package/dist/runtime/host/index.js +171 -97
- package/dist/runtime/host/location-runtime-owner.js +2 -6
- package/dist/runtime/host/mesh-router-resolver.d.ts +4 -0
- package/dist/runtime/host/mesh-router-resolver.js +14 -6
- package/dist/runtime/host/remote-bound-session-relay.d.ts +2 -4
- package/dist/runtime/host/remote-bound-session-relay.js +71 -190
- package/dist/runtime/host/route-mesh-runtime.d.ts +2 -2
- package/dist/runtime/host/route-mesh-runtime.js +5 -3
- package/dist/runtime/host/runtime-shutdown.d.ts +1 -0
- package/dist/runtime/host/runtime-shutdown.js +3 -2
- package/dist/runtime/host/service-relocation-host-runtime.d.ts +17 -7
- package/dist/runtime/host/service-relocation-host-runtime.js +550 -367
- package/dist/runtime/host/spot-runtime-options-factory.js +15 -7
- package/dist/runtime/host/user-spot-creation-coordinator.js +33 -84
- package/dist/runtime/locations/auto-connect-loop.d.ts +2 -0
- package/dist/runtime/locations/auto-connect-loop.js +22 -14
- package/dist/runtime/locations/auto-connect-reconciler.js +0 -6
- package/dist/runtime/locations/auto-connect-types.d.ts +0 -1
- package/dist/runtime/locations/descriptor-publication.d.ts +4 -0
- package/dist/runtime/locations/descriptor-publication.js +11 -0
- package/dist/runtime/locations/domain-store-contract.d.ts +1 -0
- package/dist/runtime/locations/in-memory-authority-store.d.ts +7 -1
- package/dist/runtime/locations/in-memory-authority-store.js +56 -19
- package/dist/runtime/locations/in-memory-location-store.js +1 -10
- package/dist/runtime/locations/index.d.ts +1 -0
- package/dist/runtime/locations/index.js +1 -0
- package/dist/runtime/locations/lease-tracker.js +1 -6
- package/dist/runtime/locations/location-store-repository.d.ts +51 -1
- package/dist/runtime/locations/location-store-repository.js +363 -139
- package/dist/runtime/locations/relocation-blob.d.ts +18 -1
- package/dist/runtime/locations/relocation-blob.js +52 -1
- package/dist/runtime/locations/request-source-resolver.d.ts +37 -0
- package/dist/runtime/locations/request-source-resolver.js +80 -0
- package/dist/runtime/locations/resolvers.js +1 -1
- package/dist/runtime/locations/runtime.d.ts +6 -2
- package/dist/runtime/locations/runtime.js +37 -30
- package/dist/runtime/messaging/payload-codec.d.ts +7 -1
- package/dist/runtime/messaging/payload-codec.js +7 -6
- package/dist/runtime/messaging/request-result.js +29 -26
- package/dist/runtime/protocol/service_wire_codec.generated.d.ts +19 -1
- package/dist/runtime/protocol/service_wire_codec.generated.js +85 -0
- package/dist/runtime/protocol/service_wire_pilot_codec.generated.d.ts +7 -1
- package/dist/runtime/protocol/service_wire_pilot_codec.generated.js +23 -7
- package/dist/runtime/spots/formal-remote-actor-admission-registry.js +3 -2
- package/dist/runtime/spots/index.d.ts +18 -11
- package/dist/runtime/spots/index.js +234 -176
- package/dist/runtime/spots/spot-activation-registry.d.ts +4 -2
- package/dist/runtime/spots/spot-activation-registry.js +21 -11
- package/dist/runtime/spots/spot-activation-state.d.ts +1 -1
- package/dist/runtime/spots/spot-activation-state.js +7 -7
- package/dist/runtime/spots/spot-activation.d.ts +6 -3
- package/dist/runtime/spots/spot-activation.js +123 -44
- package/dist/runtime/spots/spot-actor-admission-coordinator.d.ts +1 -0
- package/dist/runtime/spots/spot-actor-admission-coordinator.js +13 -22
- package/dist/runtime/spots/spot-actor-membership.d.ts +0 -1
- package/dist/runtime/spots/spot-actor-membership.js +0 -8
- package/dist/runtime/spots/spot-actor-packet-dispatch.js +33 -8
- package/dist/runtime/spots/spot-actor-packet-drain.js +5 -33
- package/dist/runtime/spots/spot-entry-activation.d.ts +2 -0
- package/dist/runtime/spots/spot-entry-activation.js +14 -9
- package/dist/runtime/spots/spot-handler-registry.d.ts +4 -3
- package/dist/runtime/spots/spot-handler-registry.js +6 -2
- package/dist/runtime/spots/spot-manager-internal-contracts.d.ts +2 -2
- package/dist/runtime/spots/spot-manager-public.js +2 -2
- package/dist/runtime/spots/spot-node-autoconnect.d.ts +2 -1
- package/dist/runtime/spots/spot-node-autoconnect.js +18 -39
- package/dist/runtime/spots/spot-node-runtime-manager.d.ts +19 -2
- package/dist/runtime/spots/spot-node-runtime-manager.js +115 -50
- package/dist/runtime/spots/spot-outbound.js +3 -3
- package/dist/runtime/spots/spot-remote-codec.js +5 -1
- package/dist/runtime/spots/spot-runtime-ports.d.ts +0 -1
- package/dist/runtime/spots/spot-serial-executor.d.ts +10 -0
- package/dist/runtime/spots/spot-serial-executor.js +61 -8
- package/dist/runtime/spots/spot-serial-turn-executor.js +19 -2
- package/dist/runtime/spots/spot-subscription-dispatch.js +1 -1
- package/dist/runtime/spots/spot-timer.d.ts +57 -5
- package/dist/runtime/spots/spot-timer.js +287 -103
- package/dist/runtime/streams/actor-session-binding-registry.d.ts +42 -11
- package/dist/runtime/streams/actor-session-binding-registry.js +165 -48
- package/dist/runtime/streams/actor-session-binding-runtime-owner.d.ts +8 -4
- package/dist/runtime/streams/bound-actor-relay-sender.d.ts +2 -1
- package/dist/runtime/streams/bound-actor-relay-sender.js +15 -8
- package/dist/runtime/streams/bound-session-service.d.ts +1 -1
- package/dist/runtime/streams/bound-session-service.js +6 -11
- package/dist/runtime/streams/index.d.ts +3 -2
- package/dist/runtime/streams/index.js +6 -4
- package/dist/runtime/streams/managed-stream.js +3 -2
- package/dist/runtime/streams/native-fallback-bound-session.js +8 -73
- package/dist/runtime/streams/session-actor-coordinator.d.ts +2 -8
- package/dist/runtime/streams/session-actor-coordinator.js +15 -32
- package/dist/runtime/streams/stream-binding-runtime-ports.d.ts +3 -10
- package/dist/runtime/streams/stream-session-runtime.js +1 -4
- package/dist/runtime/workers/index.js +1 -1
- package/package.json +3 -3
- package/src/contracts/Common/ZLinkEncodedPayload.ts +24 -4
- package/src/contracts/Common/encoded-payload-storage.ts +6 -3
- package/src/contracts/Configuration/Builders.ts +4 -1
- package/src/contracts/Configuration/RegistrationBuilderPolicy.ts +7 -2
- package/src/contracts/Configuration/RegistrationBuilders.ts +6 -2
- package/src/contracts/Configuration/RegistrationTypes.ts +1 -0
- package/src/contracts/Dispatch/ZLinkDispatchOptions.ts +2 -1
- package/src/contracts/Locations/Rows.ts +2 -0
- package/src/contracts/Spots/Contracts.ts +8 -0
- package/src/contracts/Spots/ZLinkSpot.ts +3 -3
- package/src/runtime/abort.ts +12 -0
- package/src/runtime/actors/actor-authority-publication.ts +3 -2
- package/src/runtime/actors/actor-client.ts +61 -70
- package/src/runtime/actors/actor-context.ts +49 -9
- package/src/runtime/actors/actor-handoff.ts +282 -106
- package/src/runtime/actors/actor-join-relocation.ts +2 -0
- package/src/runtime/actors/actor-local-native-join.ts +4 -0
- package/src/runtime/actors/actor-mailbox.ts +40 -2
- package/src/runtime/actors/actor-remote-joiner.ts +6 -1
- package/src/runtime/actors/actor-reply.ts +42 -0
- package/src/runtime/actors/actor-runtime-contracts.ts +2 -0
- package/src/runtime/actors/actor-runtime-state.ts +2 -20
- package/src/runtime/actors/actor-source-transfer.ts +1 -34
- package/src/runtime/actors/index.ts +41 -27
- package/src/runtime/actors/session-disconnected-wire.ts +66 -0
- package/src/runtime/admission.ts +69 -34
- package/src/runtime/application-jobs/application-job-queue-scope.ts +33 -1
- package/src/runtime/application-jobs/contracts.ts +2 -0
- package/src/runtime/backend/contracts/index.ts +39 -4
- package/src/runtime/backend/mesh-actor-session-node-adapter.ts +5 -3
- package/src/runtime/backend/mesh-completion-table.ts +4 -0
- package/src/runtime/backend/mesh-dispatch-pump.ts +223 -124
- package/src/runtime/backend/node/node-raw-binding-port.ts +106 -70
- package/src/runtime/backend/node/node-raw-mesh-backend.ts +221 -170
- package/src/runtime/backend/node/node-socket-backend-adapter.ts +5 -5
- package/src/runtime/channels/channel-clients.ts +49 -24
- package/src/runtime/channels/channel-dispatch-pipeline.ts +173 -124
- package/src/runtime/channels/channel-dispatchers.ts +116 -72
- package/src/runtime/channels/channel-envelope.ts +105 -36
- package/src/runtime/channels/channel-runtime-lifecycle.ts +13 -13
- package/src/runtime/channels/channel-runtime-manager.ts +12 -5
- package/src/runtime/channels/channel-transports.ts +49 -58
- package/src/runtime/channels/client-server-location-runtime.ts +11 -10
- package/src/runtime/channels/dispatch-error-reporter.ts +4 -2
- package/src/runtime/channels/fanout-location-runtime.ts +17 -9
- package/src/runtime/diagnostics/flow-context.ts +20 -7
- package/src/runtime/diagnostics/index.ts +1 -7
- package/src/runtime/diagnostics/message-flow.ts +47 -9
- package/src/runtime/diagnostics/runtime-metrics.ts +12 -10
- package/src/runtime/execution/index.ts +40 -14
- package/src/runtime/execution/serial-execution-queue.ts +31 -4
- package/src/runtime/execution/state-lane.ts +7 -0
- package/src/runtime/foundation/operation-registry.ts +98 -20
- package/src/runtime/foundation/raw-service-mesh-runtime.ts +244 -67
- package/src/runtime/foundation/service-liveness-registry.ts +39 -0
- package/src/runtime/foundation/service-mailbox.ts +8 -0
- package/src/runtime/foundation/service-maintenance-runtime.ts +1 -8
- package/src/runtime/foundation/service-relocation-object-owner.ts +54 -37
- package/src/runtime/foundation/service-relocation-runtime.ts +7 -3
- package/src/runtime/foundation/service-runtime-contracts.ts +12 -1
- package/src/runtime/foundation/service-session-binding-ingress-port.ts +2 -1
- package/src/runtime/foundation/service-stateful-registry.ts +38 -35
- package/src/runtime/foundation/service-stateful-runtime.ts +667 -152
- package/src/runtime/foundation/service-stateful-wire-codec.ts +49 -11
- package/src/runtime/foundation/service-wire-binary-primitives.ts +35 -12
- package/src/runtime/foundation/service-wire-constants.generated.ts +1 -0
- package/src/runtime/foundation/service-wire-m6a-codec.ts +187 -51
- package/src/runtime/host/actor-packet-relay.ts +113 -94
- package/src/runtime/host/actor-placement-coordinator.ts +31 -8
- package/src/runtime/host/actor-transfer-runtime.ts +104 -430
- package/src/runtime/host/application-job-queue.ts +29 -44
- package/src/runtime/host/index.ts +286 -129
- package/src/runtime/host/location-runtime-owner.ts +2 -6
- package/src/runtime/host/mesh-router-resolver.ts +13 -5
- package/src/runtime/host/remote-bound-session-relay.ts +86 -248
- package/src/runtime/host/route-mesh-runtime.ts +11 -5
- package/src/runtime/host/runtime-shutdown.ts +15 -4
- package/src/runtime/host/service-relocation-host-runtime.ts +784 -475
- package/src/runtime/host/spot-runtime-options-factory.ts +18 -7
- package/src/runtime/host/user-spot-creation-coordinator.ts +41 -100
- package/src/runtime/locations/auto-connect-loop.ts +22 -14
- package/src/runtime/locations/auto-connect-reconciler.ts +0 -6
- package/src/runtime/locations/auto-connect-types.ts +0 -1
- package/src/runtime/locations/descriptor-publication.ts +7 -0
- package/src/runtime/locations/domain-store-contract.ts +5 -0
- package/src/runtime/locations/in-memory-authority-store.ts +85 -23
- package/src/runtime/locations/in-memory-location-store.ts +1 -12
- package/src/runtime/locations/index.ts +1 -0
- package/src/runtime/locations/lease-tracker.ts +2 -9
- package/src/runtime/locations/location-store-repository.ts +628 -152
- package/src/runtime/locations/relocation-blob.ts +75 -1
- package/src/runtime/locations/request-source-resolver.ts +138 -0
- package/src/runtime/locations/resolvers.ts +2 -2
- package/src/runtime/locations/runtime.ts +70 -40
- package/src/runtime/messaging/payload-codec.ts +8 -11
- package/src/runtime/messaging/request-result.ts +33 -29
- package/src/runtime/protocol/service_wire_codec.generated.ts +87 -4
- package/src/runtime/protocol/service_wire_pilot_codec.generated.ts +13 -10
- package/src/runtime/spots/formal-remote-actor-admission-registry.ts +3 -2
- package/src/runtime/spots/index.ts +375 -281
- package/src/runtime/spots/spot-activation-registry.ts +25 -13
- package/src/runtime/spots/spot-activation-state.ts +12 -19
- package/src/runtime/spots/spot-activation.ts +170 -86
- package/src/runtime/spots/spot-actor-admission-coordinator.ts +25 -55
- package/src/runtime/spots/spot-actor-membership.ts +0 -15
- package/src/runtime/spots/spot-actor-packet-dispatch.ts +56 -11
- package/src/runtime/spots/spot-actor-packet-drain.ts +9 -52
- package/src/runtime/spots/spot-entry-activation.ts +24 -19
- package/src/runtime/spots/spot-handler-registry.ts +15 -4
- package/src/runtime/spots/spot-manager-internal-contracts.ts +2 -2
- package/src/runtime/spots/spot-manager-public.ts +2 -2
- package/src/runtime/spots/spot-node-autoconnect.ts +22 -45
- package/src/runtime/spots/spot-node-runtime-manager.ts +197 -67
- package/src/runtime/spots/spot-outbound.ts +3 -3
- package/src/runtime/spots/spot-remote-codec.ts +9 -2
- package/src/runtime/spots/spot-runtime-ports.ts +0 -1
- package/src/runtime/spots/spot-serial-executor.ts +97 -25
- package/src/runtime/spots/spot-serial-turn-executor.ts +22 -3
- package/src/runtime/spots/spot-subscription-dispatch.ts +1 -1
- package/src/runtime/spots/spot-timer.ts +413 -157
- package/src/runtime/streams/actor-session-binding-registry.ts +236 -64
- package/src/runtime/streams/actor-session-binding-runtime-owner.ts +16 -8
- package/src/runtime/streams/bound-actor-relay-sender.ts +23 -9
- package/src/runtime/streams/bound-session-service.ts +7 -10
- package/src/runtime/streams/index.ts +12 -6
- package/src/runtime/streams/managed-stream.ts +4 -2
- package/src/runtime/streams/native-fallback-bound-session.ts +14 -103
- package/src/runtime/streams/session-actor-coordinator.ts +39 -88
- package/src/runtime/streams/stream-binding-runtime-ports.ts +3 -9
- package/src/runtime/streams/stream-session-runtime.ts +1 -5
- package/src/runtime/workers/index.ts +1 -1
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { ZLinkMeshDispatchAdmission } from '../admission';
|
|
1
2
|
import type {
|
|
2
3
|
RoutingId,
|
|
3
4
|
ZLinkMessageContext,
|
|
@@ -40,7 +41,8 @@ import {
|
|
|
40
41
|
import { codecsForFrameworkPacket } from './channel-framework-packets';
|
|
41
42
|
import {
|
|
42
43
|
ZLinkChannelDispatchPipeline,
|
|
43
|
-
type ZLinkChannelDispatchFields
|
|
44
|
+
type ZLinkChannelDispatchFields,
|
|
45
|
+
type ZLinkRequestDispatch
|
|
44
46
|
} from './channel-dispatch-pipeline';
|
|
45
47
|
|
|
46
48
|
export interface ZLinkChannelRequestDispatcherOptions {
|
|
@@ -238,7 +240,11 @@ export class ZLinkChannelRequestDispatcher {
|
|
|
238
240
|
});
|
|
239
241
|
}
|
|
240
242
|
|
|
241
|
-
dispatchMesh(
|
|
243
|
+
dispatchMesh(
|
|
244
|
+
record: ReceiveRecord,
|
|
245
|
+
signal?: AbortSignal,
|
|
246
|
+
admit?: ZLinkMeshDispatchAdmission
|
|
247
|
+
): void | Promise<void> {
|
|
242
248
|
if (record.parts.length === 0 || record.parts[0].data().length === 0) {
|
|
243
249
|
return completedChannelReply;
|
|
244
250
|
}
|
|
@@ -270,20 +276,23 @@ export class ZLinkChannelRequestDispatcher {
|
|
|
270
276
|
}
|
|
271
277
|
const correlationId = envelope.header.correlationId ?? undefined;
|
|
272
278
|
if (envelope.header.kind === ZLinkChannelMessageKind.Command) {
|
|
273
|
-
return this.pipeline.dispatchOneWay(
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
279
|
+
return this.pipeline.dispatchOneWay(
|
|
280
|
+
{
|
|
281
|
+
fields: {
|
|
282
|
+
messageKind: ZLinkDispatchMessageKind.Send,
|
|
283
|
+
packetName,
|
|
284
|
+
correlationId,
|
|
285
|
+
flowId: envelope.header.flowId,
|
|
286
|
+
flowOrigin: envelope.header.flowOrigin
|
|
287
|
+
},
|
|
288
|
+
envelope,
|
|
289
|
+
codecs: this.options.codecs,
|
|
290
|
+
handler: this.options.sendHandlers?.get(packetName),
|
|
291
|
+
context: this.createMeshContext(envelope, record.sourceNodeRid),
|
|
292
|
+
signal
|
|
280
293
|
},
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
handler: this.options.sendHandlers?.get(packetName),
|
|
284
|
-
context: this.createMeshContext(envelope, record.sourceNodeRid),
|
|
285
|
-
signal
|
|
286
|
-
});
|
|
294
|
+
admit
|
|
295
|
+
);
|
|
287
296
|
}
|
|
288
297
|
if (envelope.header.kind !== ZLinkChannelMessageKind.Request) {
|
|
289
298
|
return completedChannelReply;
|
|
@@ -295,25 +304,20 @@ export class ZLinkChannelRequestDispatcher {
|
|
|
295
304
|
flowId: envelope.header.flowId,
|
|
296
305
|
flowOrigin: envelope.header.flowOrigin
|
|
297
306
|
};
|
|
298
|
-
return this.pipeline.dispatchRequest(
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
requireMeshReplyAccepted(
|
|
313
|
-
record.reply(encodeChannelErrorReplyParts(envelope.header, error))
|
|
314
|
-
);
|
|
315
|
-
}
|
|
316
|
-
});
|
|
307
|
+
return this.pipeline.dispatchRequest(
|
|
308
|
+
new ZLinkMeshRequestDispatch(
|
|
309
|
+
fields,
|
|
310
|
+
envelope,
|
|
311
|
+
this.options.codecs,
|
|
312
|
+
this.options.handlers.get(packetName),
|
|
313
|
+
this.createMeshContext(envelope, record.sourceNodeRid),
|
|
314
|
+
signal,
|
|
315
|
+
record,
|
|
316
|
+
'channel',
|
|
317
|
+
this.options.channelName
|
|
318
|
+
),
|
|
319
|
+
admit
|
|
320
|
+
);
|
|
317
321
|
}
|
|
318
322
|
|
|
319
323
|
private submitReply(
|
|
@@ -350,6 +354,43 @@ export class ZLinkChannelRequestDispatcher {
|
|
|
350
354
|
}
|
|
351
355
|
}
|
|
352
356
|
|
|
357
|
+
/**
|
|
358
|
+
* One mesh request handed to the dispatch pipeline. The reply writers are
|
|
359
|
+
* methods over the received record instead of per-message closures, and the
|
|
360
|
+
* missing-handler text is built only when no handler exists.
|
|
361
|
+
*/
|
|
362
|
+
class ZLinkMeshRequestDispatch<
|
|
363
|
+
TContext extends ZLinkMessageContext
|
|
364
|
+
> implements ZLinkRequestDispatch<TContext> {
|
|
365
|
+
constructor(
|
|
366
|
+
readonly fields: ZLinkChannelDispatchFields,
|
|
367
|
+
readonly envelope: ReturnType<typeof decodeChannelEnvelope>,
|
|
368
|
+
readonly codecs: ZLinkChannelEnvelopeCodecRegistry | undefined,
|
|
369
|
+
readonly handler: ZLinkRequestDispatch<TContext>['handler'],
|
|
370
|
+
readonly context: TContext,
|
|
371
|
+
readonly signal: AbortSignal | undefined,
|
|
372
|
+
private readonly record: ReceiveRecord,
|
|
373
|
+
private readonly handlerSurface: 'channel' | 'routed',
|
|
374
|
+
private readonly channelName: string
|
|
375
|
+
) {}
|
|
376
|
+
|
|
377
|
+
get missingHandlerMessage(): string {
|
|
378
|
+
return `No ${this.handlerSurface} request handler is registered for '${this.channelName}:${this.fields.packetName}'.`;
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
writeReply(reply: unknown): void {
|
|
382
|
+
requireMeshReplyAccepted(
|
|
383
|
+
this.record.reply(encodeChannelReplyParts(this.envelope.header, reply, this.codecs))
|
|
384
|
+
);
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
writeError(error: unknown): void {
|
|
388
|
+
requireMeshReplyAccepted(
|
|
389
|
+
this.record.reply(encodeChannelErrorReplyParts(this.envelope.header, error))
|
|
390
|
+
);
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
|
|
353
394
|
function requireMeshReplyAccepted(result: number): void {
|
|
354
395
|
if (result !== SubmitResult.Ok) {
|
|
355
396
|
throw new ZLinkConfigurationException(
|
|
@@ -685,7 +726,11 @@ export class ZLinkRoutePacketDispatcher {
|
|
|
685
726
|
});
|
|
686
727
|
}
|
|
687
728
|
|
|
688
|
-
dispatchMesh(
|
|
729
|
+
dispatchMesh(
|
|
730
|
+
record: ReceiveRecord,
|
|
731
|
+
signal?: AbortSignal,
|
|
732
|
+
admit?: ZLinkMeshDispatchAdmission
|
|
733
|
+
): void | Promise<void> {
|
|
689
734
|
if (record.parts.length === 0 || record.parts[0].data().length === 0) {
|
|
690
735
|
return completedChannelReply;
|
|
691
736
|
}
|
|
@@ -723,7 +768,8 @@ export class ZLinkRoutePacketDispatcher {
|
|
|
723
768
|
packetName,
|
|
724
769
|
sourceNodeRid,
|
|
725
770
|
record.sourceNodeRid,
|
|
726
|
-
signal
|
|
771
|
+
signal,
|
|
772
|
+
admit
|
|
727
773
|
);
|
|
728
774
|
}
|
|
729
775
|
if (envelope.header.kind !== ZLinkChannelMessageKind.Request) {
|
|
@@ -737,26 +783,20 @@ export class ZLinkRoutePacketDispatcher {
|
|
|
737
783
|
flowId: envelope.header.flowId,
|
|
738
784
|
flowOrigin: envelope.header.flowOrigin
|
|
739
785
|
};
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
writeError: (error) => {
|
|
755
|
-
requireMeshReplyAccepted(
|
|
756
|
-
record.reply(encodeChannelErrorReplyParts(envelope.header, error))
|
|
757
|
-
);
|
|
758
|
-
}
|
|
759
|
-
});
|
|
786
|
+
return this.pipeline.dispatchRequest(
|
|
787
|
+
new ZLinkMeshRequestDispatch(
|
|
788
|
+
fields,
|
|
789
|
+
envelope,
|
|
790
|
+
codecsForFrameworkPacket(packetName, this.codecs),
|
|
791
|
+
this.requestHandlers.get(packetName),
|
|
792
|
+
this.createRouteContext(envelope, record.sourceNodeRid),
|
|
793
|
+
signal,
|
|
794
|
+
record,
|
|
795
|
+
'routed',
|
|
796
|
+
this.routerChannelId
|
|
797
|
+
),
|
|
798
|
+
admit
|
|
799
|
+
);
|
|
760
800
|
}
|
|
761
801
|
|
|
762
802
|
async dispatchLocalCommand(
|
|
@@ -801,23 +841,27 @@ export class ZLinkRoutePacketDispatcher {
|
|
|
801
841
|
packetName: string,
|
|
802
842
|
sourceRid: string,
|
|
803
843
|
sourceNodeRid: unknown,
|
|
804
|
-
signal?: AbortSignal
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
844
|
+
signal?: AbortSignal,
|
|
845
|
+
admit?: ZLinkMeshDispatchAdmission
|
|
846
|
+
): void | Promise<void> {
|
|
847
|
+
return this.pipeline.dispatchOneWay(
|
|
848
|
+
{
|
|
849
|
+
fields: {
|
|
850
|
+
messageKind: ZLinkDispatchMessageKind.Send,
|
|
851
|
+
packetName,
|
|
852
|
+
sourceRid,
|
|
853
|
+
correlationId: envelope.header.correlationId ?? undefined,
|
|
854
|
+
flowId: envelope.header.flowId,
|
|
855
|
+
flowOrigin: envelope.header.flowOrigin
|
|
856
|
+
},
|
|
857
|
+
envelope,
|
|
858
|
+
codecs: codecsForFrameworkPacket(packetName, this.codecs),
|
|
859
|
+
handler: this.sendHandlers.get(packetName),
|
|
860
|
+
context: this.createRouteContext(envelope, sourceNodeRid),
|
|
861
|
+
signal
|
|
814
862
|
},
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
handler: this.sendHandlers.get(packetName),
|
|
818
|
-
context: this.createRouteContext(envelope, sourceNodeRid),
|
|
819
|
-
signal
|
|
820
|
-
});
|
|
863
|
+
admit
|
|
864
|
+
);
|
|
821
865
|
}
|
|
822
866
|
|
|
823
867
|
private submitReply(operation: ZLinkMultipartReplyOperation): Promise<void> {
|
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
import type { Message } from '../../contracts/Common/Message';
|
|
2
2
|
import { ZLinkBufferMessage } from '../backend/runtime-message';
|
|
3
3
|
import type { ZLinkBackendMessageLike as MessageLike } from '../backend/runtime-values';
|
|
4
|
-
import {
|
|
4
|
+
import { randomBytes } from 'node:crypto';
|
|
5
5
|
import { isUtf8 } from 'node:buffer';
|
|
6
6
|
import {
|
|
7
7
|
ZLinkFrameworkErrorKind,
|
|
8
8
|
ZLinkFrameworkException,
|
|
9
|
-
ZLinkEncodedPayload,
|
|
10
9
|
type ZLinkMessageSerializer,
|
|
11
10
|
type ZLinkFlowOrigin
|
|
12
11
|
} from '../../contracts';
|
|
@@ -18,7 +17,10 @@ import {
|
|
|
18
17
|
createInternalFrameworkException
|
|
19
18
|
} from '../framework-errors-internal';
|
|
20
19
|
import { resolveFrameworkPacketName } from '../messaging/packet-name';
|
|
21
|
-
import {
|
|
20
|
+
import {
|
|
21
|
+
encodedPayloadFromOwned,
|
|
22
|
+
selectSerializerWithContentType
|
|
23
|
+
} from '../messaging/payload-codec';
|
|
22
24
|
import { isCanonicalCodecContentType } from '../../contracts/Configuration/CodecContentType';
|
|
23
25
|
import { parseFrameworkJsonV1, stringifyFrameworkJsonV1 } from '../messaging/framework-json-v1';
|
|
24
26
|
import { currentOrCreateFlow } from '../diagnostics/flow-context';
|
|
@@ -75,9 +77,14 @@ interface PreparedChannelHeader {
|
|
|
75
77
|
readonly bytes: Buffer;
|
|
76
78
|
readonly correlationOffset: number;
|
|
77
79
|
readonly deadlineOffset: number;
|
|
80
|
+
readonly flowOffset: number;
|
|
78
81
|
}
|
|
79
82
|
|
|
80
|
-
|
|
83
|
+
/** Per kind, deadline presence and flow origin (`undefined` when the header carries no flow). */
|
|
84
|
+
type PreparedHeaderVariants = Map<
|
|
85
|
+
ZLinkChannelMessageKind,
|
|
86
|
+
Map<boolean, Map<ZLinkFlowOrigin | undefined, PreparedChannelHeader>>
|
|
87
|
+
>;
|
|
81
88
|
const preparedChannelHeaders = new WeakMap<
|
|
82
89
|
ReadonlyMap<string, ZLinkMessageSerializer>,
|
|
83
90
|
Map<string, Map<string, Map<string, PreparedHeaderVariants>>>
|
|
@@ -88,9 +95,24 @@ const CHANNEL_CORRELATION_TEXT_LENGTH = 32;
|
|
|
88
95
|
const PREPARED_CHANNEL_CORRELATION = '0'.repeat(CHANNEL_CORRELATION_TEXT_LENGTH);
|
|
89
96
|
const PREPARED_CHANNEL_DEADLINE = '2000-01-01T00:00:00.000Z';
|
|
90
97
|
const CHANNEL_CORRELATION_TEXT = /^[0-9a-f]{32}$/;
|
|
98
|
+
const CHANNEL_FLOW_FIELD = ',"flowId":';
|
|
99
|
+
// A flow id is a lowercase UUIDv7 (spec 27 §3): fixed 36 JSON-safe ASCII bytes.
|
|
100
|
+
const PREPARED_CHANNEL_FLOW = '00000000-0000-7000-8000-000000000000';
|
|
101
|
+
const CHANNEL_FLOW_TEXT = /^[0-9a-f-]{36}$/;
|
|
102
|
+
|
|
103
|
+
// A per-process random 64-bit prefix followed by a per-process counter, both
|
|
104
|
+
// as lowercase hex: unique among the runtime's pending requests (spec 06-obs/04
|
|
105
|
+
// §3) without drawing random bytes for every request — the shape Java
|
|
106
|
+
// ZLinkServiceOperationIds uses.
|
|
107
|
+
const CHANNEL_CORRELATION_PREFIX = randomBytes(CHANNEL_CORRELATION_TEXT_LENGTH / 4).toString('hex');
|
|
108
|
+
let channelCorrelationCounter = 0;
|
|
91
109
|
|
|
92
110
|
export function newChannelCorrelationId(): string {
|
|
93
|
-
|
|
111
|
+
channelCorrelationCounter += 1;
|
|
112
|
+
return (
|
|
113
|
+
CHANNEL_CORRELATION_PREFIX +
|
|
114
|
+
channelCorrelationCounter.toString(16).padStart(CHANNEL_CORRELATION_TEXT_LENGTH / 2, '0')
|
|
115
|
+
);
|
|
94
116
|
}
|
|
95
117
|
|
|
96
118
|
export function encodeChannelEnvelopeParts(
|
|
@@ -276,6 +298,10 @@ const ERROR_KIND_BY_WIRE_NAME: ReadonlyMap<string, ZLinkFrameworkErrorKind> = ne
|
|
|
276
298
|
ERROR_KIND_WIRE_NAMES.map((name, kind) => [name, kind as ZLinkFrameworkErrorKind])
|
|
277
299
|
);
|
|
278
300
|
|
|
301
|
+
export function channelErrorKindFromCode(code: string): ZLinkFrameworkErrorKind | undefined {
|
|
302
|
+
return ERROR_KIND_BY_WIRE_NAME.get(code);
|
|
303
|
+
}
|
|
304
|
+
|
|
279
305
|
export function channelErrorCodeName(kind: ZLinkFrameworkErrorKind): string {
|
|
280
306
|
return ERROR_KIND_WIRE_NAMES[kind] ?? 'internal_failure';
|
|
281
307
|
}
|
|
@@ -350,7 +376,7 @@ export function decodeChannelReply<TReply>(
|
|
|
350
376
|
}
|
|
351
377
|
if (serializer !== undefined) {
|
|
352
378
|
return serializer.deserialize<TReply>(
|
|
353
|
-
|
|
379
|
+
encodedPayloadFromOwned(parts[1].data()),
|
|
354
380
|
Object as never
|
|
355
381
|
);
|
|
356
382
|
}
|
|
@@ -373,7 +399,7 @@ function decodeChannelError(header: ZLinkChannelEnvelopeHeader): ZLinkChannelDec
|
|
|
373
399
|
// Cross-language contract: errorCode carries the snake_case wire name.
|
|
374
400
|
// An unknown name degrades to InternalFailure, matching the C++
|
|
375
401
|
// request_failure_mapper fallback for unrecognized codes.
|
|
376
|
-
const publicKind =
|
|
402
|
+
const publicKind = channelErrorKindFromCode(code) ?? ZLinkFrameworkErrorKind.InternalFailure;
|
|
377
403
|
failure = new ZLinkFrameworkException(publicKind, message);
|
|
378
404
|
}
|
|
379
405
|
// Cross-language contract (.NET ZLinkErrorOriginWire.RemoteReplyOrigin /
|
|
@@ -424,7 +450,7 @@ export function decodeChannelPayload(
|
|
|
424
450
|
}
|
|
425
451
|
const serializer = codecs?.serializers.get(envelope.header.contentType);
|
|
426
452
|
if (serializer !== undefined) {
|
|
427
|
-
return serializer.deserialize(
|
|
453
|
+
return serializer.deserialize(encodedPayloadFromOwned(envelope.payload), Object as never);
|
|
428
454
|
}
|
|
429
455
|
if (envelope.header.contentType === BINARY_CONTENT_TYPE) {
|
|
430
456
|
// The receive loop owns the Message for the duration of dispatch, so
|
|
@@ -544,8 +570,9 @@ function encodeChannelHeader(
|
|
|
544
570
|
if (
|
|
545
571
|
codecs !== undefined &&
|
|
546
572
|
metadata === EMPTY_APPLICATION_METADATA &&
|
|
547
|
-
flowId === undefined
|
|
548
|
-
|
|
573
|
+
(flowId === undefined
|
|
574
|
+
? flowOrigin === undefined
|
|
575
|
+
: flowOrigin !== undefined && CHANNEL_FLOW_TEXT.test(flowId)) &&
|
|
549
576
|
topic === null &&
|
|
550
577
|
source === undefined &&
|
|
551
578
|
((kind === ZLinkChannelMessageKind.Command &&
|
|
@@ -576,7 +603,9 @@ function encodeChannelHeader(
|
|
|
576
603
|
correlationId,
|
|
577
604
|
deadline,
|
|
578
605
|
errorCode,
|
|
579
|
-
errorMessage
|
|
606
|
+
errorMessage,
|
|
607
|
+
flowId,
|
|
608
|
+
flowOrigin
|
|
580
609
|
);
|
|
581
610
|
}
|
|
582
611
|
// The wire has a fixed field order. Measure escaped UTF-8 first, then write
|
|
@@ -629,7 +658,9 @@ function preparedChannelHeader(
|
|
|
629
658
|
correlationId: string | null,
|
|
630
659
|
deadline: string | null,
|
|
631
660
|
errorCode: string | null | undefined,
|
|
632
|
-
errorMessage: string | null | undefined
|
|
661
|
+
errorMessage: string | null | undefined,
|
|
662
|
+
flowId: string | undefined,
|
|
663
|
+
flowOrigin: ZLinkFlowOrigin | undefined
|
|
633
664
|
): Buffer {
|
|
634
665
|
let channels = preparedChannelHeaders.get(codecs.serializers);
|
|
635
666
|
if (channels === undefined)
|
|
@@ -643,7 +674,9 @@ function preparedChannelHeader(
|
|
|
643
674
|
let deadlines = kinds.get(kind);
|
|
644
675
|
if (deadlines === undefined) kinds.set(kind, (deadlines = new Map()));
|
|
645
676
|
const hasDeadline = deadline !== null;
|
|
646
|
-
let
|
|
677
|
+
let flows = deadlines.get(hasDeadline);
|
|
678
|
+
if (flows === undefined) deadlines.set(hasDeadline, (flows = new Map()));
|
|
679
|
+
let prepared = flows.get(flowOrigin);
|
|
647
680
|
if (prepared === undefined) {
|
|
648
681
|
const bytes = encodeChannelHeader(
|
|
649
682
|
kind,
|
|
@@ -657,23 +690,32 @@ function preparedChannelHeader(
|
|
|
657
690
|
errorMessage,
|
|
658
691
|
undefined,
|
|
659
692
|
EMPTY_APPLICATION_METADATA,
|
|
660
|
-
undefined,
|
|
661
|
-
|
|
693
|
+
flowOrigin === undefined ? undefined : PREPARED_CHANNEL_FLOW,
|
|
694
|
+
flowOrigin
|
|
662
695
|
);
|
|
663
696
|
prepared = {
|
|
664
697
|
bytes,
|
|
665
698
|
correlationOffset:
|
|
666
699
|
bytes.indexOf(CHANNEL_CORRELATION_FIELD) + CHANNEL_CORRELATION_FIELD.length + 1,
|
|
667
|
-
deadlineOffset: bytes.indexOf(CHANNEL_DEADLINE_FIELD) + CHANNEL_DEADLINE_FIELD.length + 1
|
|
700
|
+
deadlineOffset: bytes.indexOf(CHANNEL_DEADLINE_FIELD) + CHANNEL_DEADLINE_FIELD.length + 1,
|
|
701
|
+
flowOffset: bytes.indexOf(CHANNEL_FLOW_FIELD) + CHANNEL_FLOW_FIELD.length + 1
|
|
668
702
|
};
|
|
669
|
-
|
|
703
|
+
flows.set(flowOrigin, prepared);
|
|
670
704
|
}
|
|
671
|
-
if (correlationId === null) return prepared.bytes;
|
|
672
|
-
const bytes = Buffer.
|
|
705
|
+
if (correlationId === null && flowId === undefined) return prepared.bytes;
|
|
706
|
+
const bytes = Buffer.allocUnsafe(prepared.bytes.byteLength);
|
|
673
707
|
prepared.bytes.copy(bytes);
|
|
674
|
-
|
|
708
|
+
if (correlationId !== null)
|
|
709
|
+
bytes.write(
|
|
710
|
+
correlationId,
|
|
711
|
+
prepared.correlationOffset,
|
|
712
|
+
CHANNEL_CORRELATION_TEXT_LENGTH,
|
|
713
|
+
'ascii'
|
|
714
|
+
);
|
|
675
715
|
if (deadline !== null)
|
|
676
716
|
bytes.write(deadline, prepared.deadlineOffset, PREPARED_CHANNEL_DEADLINE.length, 'ascii');
|
|
717
|
+
if (flowId !== undefined)
|
|
718
|
+
bytes.write(flowId, prepared.flowOffset, PREPARED_CHANNEL_FLOW.length, 'ascii');
|
|
677
719
|
return bytes;
|
|
678
720
|
}
|
|
679
721
|
|
|
@@ -859,13 +901,18 @@ function parseWireJson(payload: string, schema?: ZLinkJsonSchema): unknown {
|
|
|
859
901
|
}
|
|
860
902
|
|
|
861
903
|
function parseChannelHeaderBytes(payload: Buffer): unknown {
|
|
904
|
+
const reader = new CanonicalChannelHeaderReader(payload);
|
|
905
|
+
const canonical = tryParseCanonicalChannelHeader(reader);
|
|
906
|
+
// An all-ASCII canonical header is valid UTF-8 by construction; any other
|
|
907
|
+
// header is checked before it is decoded.
|
|
908
|
+
if (canonical !== undefined && !reader.sawNonAscii) return canonical;
|
|
862
909
|
if (!isUtf8(payload)) {
|
|
863
910
|
throw new ZLinkFrameworkException(
|
|
864
911
|
ZLinkFrameworkErrorKind.ProtocolError,
|
|
865
912
|
'Channel envelope header must contain valid UTF-8.'
|
|
866
913
|
);
|
|
867
914
|
}
|
|
868
|
-
return
|
|
915
|
+
return canonical ?? parseFrameworkJsonV1(payload.toString());
|
|
869
916
|
}
|
|
870
917
|
|
|
871
918
|
/**
|
|
@@ -874,8 +921,9 @@ function parseChannelHeaderBytes(payload: Buffer): unknown {
|
|
|
874
921
|
* framework-json-v1 parser, which remains the sole authority for JSON
|
|
875
922
|
* failures and unknown properties. Header metadata accepts every valid string key.
|
|
876
923
|
*/
|
|
877
|
-
function tryParseCanonicalChannelHeader(
|
|
878
|
-
|
|
924
|
+
function tryParseCanonicalChannelHeader(
|
|
925
|
+
reader: CanonicalChannelHeaderReader
|
|
926
|
+
): Record<string, unknown> | undefined {
|
|
879
927
|
if (!reader.consume('{"formatMarker":242,"kind":')) return undefined;
|
|
880
928
|
const kind = reader.readSingleDigit();
|
|
881
929
|
if (kind === undefined || !reader.consume(',"channelName":')) return undefined;
|
|
@@ -902,20 +950,31 @@ function tryParseCanonicalChannelHeader(payload: Buffer): Record<string, unknown
|
|
|
902
950
|
deadline: deadline === NULL_JSON_STRING ? null : deadline,
|
|
903
951
|
topic: topic === NULL_JSON_STRING ? null : topic
|
|
904
952
|
};
|
|
905
|
-
if (!reader.readOptionalNullableString('errorCode', header))
|
|
906
|
-
|
|
907
|
-
if (!reader.readOptionalNullableString('
|
|
953
|
+
if (!reader.readOptionalNullableString(CANONICAL_ERROR_CODE, 'errorCode', header))
|
|
954
|
+
return undefined;
|
|
955
|
+
if (!reader.readOptionalNullableString(CANONICAL_ERROR_MESSAGE, 'errorMessage', header))
|
|
956
|
+
return undefined;
|
|
957
|
+
if (!reader.readOptionalNullableString(CANONICAL_SOURCE, 'source', header)) return undefined;
|
|
958
|
+
// Empty metadata validates to the shared empty record.
|
|
908
959
|
if (!reader.consume(',"metadata":{}')) return undefined;
|
|
909
|
-
|
|
910
|
-
if (!reader.
|
|
911
|
-
|
|
960
|
+
if (!reader.readOptionalString(CANONICAL_FLOW_ID, 'flowId', header)) return undefined;
|
|
961
|
+
if (!reader.readOptionalSingleDigit(CANONICAL_FLOW_ORIGIN, 'flowOrigin', header))
|
|
962
|
+
return undefined;
|
|
912
963
|
return reader.consume('}') && reader.atEnd() ? header : undefined;
|
|
913
964
|
}
|
|
914
965
|
|
|
966
|
+
const CANONICAL_ERROR_CODE = ',"errorCode":';
|
|
967
|
+
const CANONICAL_ERROR_MESSAGE = ',"errorMessage":';
|
|
968
|
+
const CANONICAL_SOURCE = ',"source":';
|
|
969
|
+
const CANONICAL_FLOW_ID = ',"flowId":';
|
|
970
|
+
const CANONICAL_FLOW_ORIGIN = ',"flowOrigin":';
|
|
971
|
+
|
|
915
972
|
const NULL_JSON_STRING = Symbol('null JSON string');
|
|
916
973
|
|
|
917
974
|
class CanonicalChannelHeaderReader {
|
|
918
975
|
private index = 0;
|
|
976
|
+
/** A string held a byte outside ASCII, so the caller must still check UTF-8. */
|
|
977
|
+
sawNonAscii = false;
|
|
919
978
|
|
|
920
979
|
constructor(private readonly bytes: Buffer) {}
|
|
921
980
|
|
|
@@ -944,13 +1003,19 @@ class CanonicalChannelHeaderReader {
|
|
|
944
1003
|
if (this.bytes[this.index] !== 0x22) return undefined;
|
|
945
1004
|
const start = this.index;
|
|
946
1005
|
this.index += 1;
|
|
1006
|
+
let hasEscape = false;
|
|
947
1007
|
while (this.index < this.bytes.length) {
|
|
948
1008
|
const value = this.bytes[this.index++]!;
|
|
949
1009
|
if (value === 0x22) {
|
|
950
|
-
|
|
1010
|
+
// Without escapes the JSON string is its own bytes; decode them once.
|
|
1011
|
+
return hasEscape
|
|
1012
|
+
? (JSON.parse(this.bytes.toString('utf8', start, this.index)) as string)
|
|
1013
|
+
: this.bytes.toString(this.sawNonAscii ? 'utf8' : 'latin1', start + 1, this.index - 1);
|
|
951
1014
|
}
|
|
952
1015
|
if (value < 0x20) return undefined;
|
|
1016
|
+
if (value >= 0x80) this.sawNonAscii = true;
|
|
953
1017
|
if (value !== 0x5c) continue;
|
|
1018
|
+
hasEscape = true;
|
|
954
1019
|
if (this.index === this.bytes.length) return undefined;
|
|
955
1020
|
const escaped = this.bytes[this.index++]!;
|
|
956
1021
|
if (escaped === 0x75) {
|
|
@@ -980,24 +1045,28 @@ class CanonicalChannelHeaderReader {
|
|
|
980
1045
|
return this.readString();
|
|
981
1046
|
}
|
|
982
1047
|
|
|
983
|
-
readOptionalNullableString(
|
|
984
|
-
|
|
1048
|
+
readOptionalNullableString(
|
|
1049
|
+
token: string,
|
|
1050
|
+
name: string,
|
|
1051
|
+
target: Record<string, unknown>
|
|
1052
|
+
): boolean {
|
|
1053
|
+
if (!this.consume(token)) return true;
|
|
985
1054
|
const value = this.readNullableString();
|
|
986
1055
|
if (value === undefined) return false;
|
|
987
1056
|
target[name] = value === NULL_JSON_STRING ? null : value;
|
|
988
1057
|
return true;
|
|
989
1058
|
}
|
|
990
1059
|
|
|
991
|
-
readOptionalString(name: string, target: Record<string, unknown>): boolean {
|
|
992
|
-
if (!this.consume(
|
|
1060
|
+
readOptionalString(token: string, name: string, target: Record<string, unknown>): boolean {
|
|
1061
|
+
if (!this.consume(token)) return true;
|
|
993
1062
|
const value = this.readString();
|
|
994
1063
|
if (value === undefined) return false;
|
|
995
1064
|
target[name] = value;
|
|
996
1065
|
return true;
|
|
997
1066
|
}
|
|
998
1067
|
|
|
999
|
-
readOptionalSingleDigit(name: string, target: Record<string, unknown>): boolean {
|
|
1000
|
-
if (!this.consume(
|
|
1068
|
+
readOptionalSingleDigit(token: string, name: string, target: Record<string, unknown>): boolean {
|
|
1069
|
+
if (!this.consume(token)) return true;
|
|
1001
1070
|
const value = this.readSingleDigit();
|
|
1002
1071
|
if (value === undefined) return false;
|
|
1003
1072
|
target[name] = value;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { ZLinkMeshDispatchAdmission } from '../admission';
|
|
1
2
|
import { RuntimeDisposal } from '../disposal';
|
|
2
3
|
import type { ZLinkLocationOptionOverrides } from '../../contracts/Locations/Options';
|
|
3
4
|
import type { ZLinkRequestHandler, ZLinkSendHandler } from '../../contracts/Handlers';
|
|
@@ -50,12 +51,9 @@ import {
|
|
|
50
51
|
endpointConnections
|
|
51
52
|
} from '../../contracts/Configuration/RuntimeEndpointConnections';
|
|
52
53
|
import type { ApplicationJobQueue } from '../host/application-job-queue';
|
|
53
|
-
import {
|
|
54
|
-
import { ZLinkStateLane } from '../execution/state-lane';
|
|
54
|
+
import { startOutsideStateLane, ZLinkStateLane } from '../execution/state-lane';
|
|
55
55
|
import { ZLinkSerialExecutionQueue } from '../execution/serial-execution-queue';
|
|
56
56
|
|
|
57
|
-
const detachedStateLaneResource = new AsyncResource('zlink:channel-runtime-lifecycle');
|
|
58
|
-
|
|
59
57
|
interface ManualFanoutSubscriberState {
|
|
60
58
|
readonly channelName: string;
|
|
61
59
|
readonly endpoint: string;
|
|
@@ -349,8 +347,9 @@ export class ZLinkChannelRuntimeLifecycle {
|
|
|
349
347
|
dispatchMeshChannel(
|
|
350
348
|
meshName: string,
|
|
351
349
|
record: ReceiveRecord,
|
|
352
|
-
signal?: AbortSignal
|
|
353
|
-
|
|
350
|
+
signal?: AbortSignal,
|
|
351
|
+
admit?: ZLinkMeshDispatchAdmission
|
|
352
|
+
): void | Promise<void> {
|
|
354
353
|
const channelName = record.channelName;
|
|
355
354
|
if (channelName === null) {
|
|
356
355
|
throw new ZLinkConfigurationException('MeshNode channel record is missing channelName.');
|
|
@@ -361,17 +360,22 @@ export class ZLinkChannelRuntimeLifecycle {
|
|
|
361
360
|
`RouteMesh '${meshName}' channel '${channelName}' has no registered handlers.`
|
|
362
361
|
);
|
|
363
362
|
}
|
|
364
|
-
return dispatcher.dispatchMesh(record, signal);
|
|
363
|
+
return dispatcher.dispatchMesh(record, signal, admit);
|
|
365
364
|
}
|
|
366
365
|
|
|
367
|
-
dispatchMeshRoute(
|
|
366
|
+
dispatchMeshRoute(
|
|
367
|
+
meshName: string,
|
|
368
|
+
record: ReceiveRecord,
|
|
369
|
+
signal?: AbortSignal,
|
|
370
|
+
admit?: ZLinkMeshDispatchAdmission
|
|
371
|
+
): void | Promise<void> {
|
|
368
372
|
const dispatcher = this.meshRouteDispatchers.get(meshName);
|
|
369
373
|
if (dispatcher === undefined) {
|
|
370
374
|
throw new ZLinkConfigurationException(
|
|
371
375
|
`RouteMesh '${meshName}' has no registered node-direct handlers.`
|
|
372
376
|
);
|
|
373
377
|
}
|
|
374
|
-
return dispatcher.dispatchMesh(record, signal);
|
|
378
|
+
return dispatcher.dispatchMesh(record, signal, admit);
|
|
375
379
|
}
|
|
376
380
|
|
|
377
381
|
dispatchLocalMeshRoute(
|
|
@@ -1060,7 +1064,3 @@ function hasFanoutLocationTopology(registration: ZLinkFrameworkRegistration): bo
|
|
|
1060
1064
|
}
|
|
1061
1065
|
return false;
|
|
1062
1066
|
}
|
|
1063
|
-
|
|
1064
|
-
function startOutsideStateLane<T>(work: () => T): T {
|
|
1065
|
-
return detachedStateLaneResource.runInAsyncScope(work);
|
|
1066
|
-
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { ZLinkMeshDispatchAdmission } from '../admission';
|
|
1
2
|
import type { ZLinkListenerRecords } from '../foundation/listener-records';
|
|
2
3
|
import type { ZLinkLocationOptionOverrides } from '../../contracts/Locations/Options';
|
|
3
4
|
import type { RoutingId } from '../../contracts';
|
|
@@ -207,13 +208,19 @@ export class ZLinkChannelRuntimeManager {
|
|
|
207
208
|
dispatchMeshChannel(
|
|
208
209
|
meshName: string,
|
|
209
210
|
record: ReceiveRecord,
|
|
210
|
-
signal?: AbortSignal
|
|
211
|
-
|
|
212
|
-
|
|
211
|
+
signal?: AbortSignal,
|
|
212
|
+
admit?: ZLinkMeshDispatchAdmission
|
|
213
|
+
): void | Promise<void> {
|
|
214
|
+
return this.lifecycle.dispatchMeshChannel(meshName, record, signal, admit);
|
|
213
215
|
}
|
|
214
216
|
|
|
215
|
-
dispatchMeshRoute(
|
|
216
|
-
|
|
217
|
+
dispatchMeshRoute(
|
|
218
|
+
meshName: string,
|
|
219
|
+
record: ReceiveRecord,
|
|
220
|
+
signal?: AbortSignal,
|
|
221
|
+
admit?: ZLinkMeshDispatchAdmission
|
|
222
|
+
): void | Promise<void> {
|
|
223
|
+
return this.lifecycle.dispatchMeshRoute(meshName, record, signal, admit);
|
|
217
224
|
}
|
|
218
225
|
|
|
219
226
|
dispatchLocalMeshRoute(
|