@zlink-systems/framework 0.30.0 → 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/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/ZLinkEncodedPayload.d.ts +6 -0
- package/dist/contracts/Common/ZLinkEncodedPayload.js +18 -3
- package/dist/contracts/Common/ZLinkMessageMetadata.js +11 -5
- 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/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/Locations/Rows.d.ts +2 -0
- package/dist/contracts/Spots/Contracts.d.ts +6 -1
- package/dist/contracts/Spots/ZLinkSpot.d.ts +3 -3
- package/dist/nest-integration.d.ts +1 -1
- package/dist/nest-integration.js +2 -1
- 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 +1 -2
- package/dist/runtime/actors/actor-client.js +52 -57
- 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 +8 -4
- package/dist/runtime/actors/actor-handoff.js +219 -92
- package/dist/runtime/actors/actor-join-relocation.d.ts +3 -0
- package/dist/runtime/actors/actor-local-native-join.js +13 -12
- package/dist/runtime/actors/actor-mailbox.js +27 -1
- package/dist/runtime/actors/actor-remote-joiner.js +3 -1
- package/dist/runtime/actors/actor-remote-wire.js +15 -0
- package/dist/runtime/actors/actor-reply.d.ts +4 -0
- package/dist/runtime/actors/actor-reply.js +29 -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/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 +8 -3
- package/dist/runtime/actors/index.js +55 -27
- package/dist/runtime/actors/session-disconnected-wire.d.ts +8 -0
- package/dist/runtime/actors/session-disconnected-wire.js +48 -0
- package/dist/runtime/actors/spot-actor-dispatch.js +2 -2
- package/dist/runtime/admission.d.ts +9 -1
- package/dist/runtime/admission.js +56 -23
- 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 +15 -1
- package/dist/runtime/application-jobs/application-job-queue-scope.js +61 -20
- package/dist/runtime/application-jobs/contracts.d.ts +12 -1
- package/dist/runtime/backend/contracts/index.d.ts +37 -12
- package/dist/runtime/backend/mesh-actor-session-node-adapter.js +2 -2
- package/dist/runtime/backend/mesh-completion-table.d.ts +9 -1
- package/dist/runtime/backend/mesh-completion-table.js +154 -49
- package/dist/runtime/backend/mesh-dispatch-pump.d.ts +28 -1
- package/dist/runtime/backend/mesh-dispatch-pump.js +208 -101
- 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 +124 -72
- package/dist/runtime/backend/node/node-raw-mesh-backend.d.ts +46 -13
- package/dist/runtime/backend/node/node-raw-mesh-backend.js +181 -164
- package/dist/runtime/backend/node/node-socket-backend-adapter.d.ts +1 -1
- package/dist/runtime/backend/node/node-socket-backend-adapter.js +11 -11
- 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 +2 -0
- package/dist/runtime/channels/channel-clients.js +75 -23
- package/dist/runtime/channels/channel-dispatch-pipeline.d.ts +25 -5
- package/dist/runtime/channels/channel-dispatch-pipeline.js +111 -56
- 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 +4 -3
- package/dist/runtime/channels/channel-dispatchers.js +62 -54
- 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 +2 -0
- package/dist/runtime/channels/channel-envelope.js +146 -28
- 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-lifecycle.d.ts +4 -3
- package/dist/runtime/channels/channel-runtime-lifecycle.js +19 -24
- package/dist/runtime/channels/channel-runtime-manager.d.ts +9 -8
- package/dist/runtime/channels/channel-runtime-manager.js +16 -16
- package/dist/runtime/channels/channel-transports.d.ts +18 -16
- package/dist/runtime/channels/channel-transports.js +77 -58
- 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/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/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 +5 -0
- package/dist/runtime/execution/serial-execution-queue.js +22 -2
- package/dist/runtime/execution/state-lane.d.ts +2 -0
- package/dist/runtime/execution/state-lane.js +5 -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/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 +61 -8
- package/dist/runtime/foundation/raw-service-mesh-runtime.js +486 -266
- 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 +3 -3
- package/dist/runtime/foundation/service-relocation-object-owner.js +48 -34
- package/dist/runtime/foundation/service-relocation-runtime.d.ts +2 -0
- package/dist/runtime/foundation/service-relocation-runtime.js +20 -4
- package/dist/runtime/foundation/service-runtime-contracts.d.ts +10 -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 +75 -9
- package/dist/runtime/foundation/service-stateful-runtime.js +486 -218
- package/dist/runtime/foundation/service-stateful-wire-codec.d.ts +14 -6
- package/dist/runtime/foundation/service-stateful-wire-codec.js +48 -27
- 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-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 +13 -3
- package/dist/runtime/foundation/service-wire-m6a-codec.js +189 -78
- 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-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-runtime-options-factory.js +2 -2
- 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 +40 -7
- package/dist/runtime/host/application-job-queue.js +137 -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 +12 -2
- package/dist/runtime/host/index.js +300 -202
- 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 +73 -208
- package/dist/runtime/host/route-mesh-runtime.d.ts +2 -2
- package/dist/runtime/host/route-mesh-runtime.js +6 -4
- 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-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 +22 -14
- package/dist/runtime/host/service-relocation-host-runtime.js +754 -599
- package/dist/runtime/host/spot-address-transport.js +3 -2
- package/dist/runtime/host/spot-runtime-options-factory.js +16 -7
- package/dist/runtime/host/user-spot-creation-coordinator.js +33 -84
- 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/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/lifecycle.d.ts +1 -2
- package/dist/runtime/locations/lifecycle.js +2 -5
- 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 +7 -3
- package/dist/runtime/locations/runtime.js +61 -53
- 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/payload-codec.d.ts +7 -1
- package/dist/runtime/messaging/payload-codec.js +7 -6
- package/dist/runtime/messaging/request-result.d.ts +2 -0
- package/dist/runtime/messaging/request-result.js +57 -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 +34 -1
- package/dist/runtime/protocol/service_wire_codec.generated.js +229 -0
- package/dist/runtime/protocol/service_wire_pilot_codec.generated.d.ts +16 -1
- package/dist/runtime/protocol/service_wire_pilot_codec.generated.js +37 -8
- package/dist/runtime/spots/formal-remote-actor-admission-registry.d.ts +7 -2
- package/dist/runtime/spots/formal-remote-actor-admission-registry.js +36 -21
- package/dist/runtime/spots/index.d.ts +21 -11
- package/dist/runtime/spots/index.js +243 -178
- 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 +7 -3
- package/dist/runtime/spots/spot-activation.js +140 -52
- 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 +20 -11
- package/dist/runtime/spots/spot-handler-registry.d.ts +7 -4
- package/dist/runtime/spots/spot-handler-registry.js +24 -10
- 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 +22 -42
- 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.d.ts +3 -0
- package/dist/runtime/spots/spot-outbound.js +27 -18
- package/dist/runtime/spots/spot-remote-codec.js +5 -1
- 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 -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 -4
- package/dist/runtime/spots/spot-timer.d.ts +57 -5
- package/dist/runtime/spots/spot-timer.js +288 -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.d.ts +1 -1
- package/dist/runtime/streams/stream-session-runtime.js +14 -31
- package/dist/runtime/workers/index.js +1 -1
- package/package.json +3 -3
- package/src/contracts/Actors/ZLinkActorClient.ts +2 -1
- package/src/contracts/Channels/Calls.ts +2 -1
- package/src/contracts/Common/ZLinkEncodedPayload.ts +24 -4
- package/src/contracts/Common/ZLinkMessageMetadata.ts +13 -8
- 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/Handlers/Attributes.ts +14 -21
- package/src/contracts/Handlers/JsonContract.ts +8 -216
- package/src/contracts/Locations/Rows.ts +2 -0
- package/src/contracts/Spots/Contracts.ts +10 -1
- package/src/contracts/Spots/ZLinkSpot.ts +3 -3
- package/src/nest-integration.ts +1 -0
- package/src/runtime/abort.ts +12 -0
- package/src/runtime/actors/actor-authority-publication.ts +3 -2
- package/src/runtime/actors/actor-client.ts +100 -85
- package/src/runtime/actors/actor-context.ts +49 -9
- package/src/runtime/actors/actor-handoff.ts +291 -110
- package/src/runtime/actors/actor-join-relocation.ts +3 -0
- package/src/runtime/actors/actor-local-native-join.ts +21 -26
- package/src/runtime/actors/actor-mailbox.ts +40 -2
- package/src/runtime/actors/actor-remote-joiner.ts +6 -1
- package/src/runtime/actors/actor-remote-wire.ts +17 -0
- package/src/runtime/actors/actor-reply.ts +42 -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/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 +60 -32
- package/src/runtime/actors/session-disconnected-wire.ts +66 -0
- package/src/runtime/actors/spot-actor-dispatch.ts +4 -2
- package/src/runtime/admission.ts +69 -21
- package/src/runtime/application-jobs/application-ingress-record-owner.ts +41 -25
- package/src/runtime/application-jobs/application-job-queue-scope.ts +83 -22
- package/src/runtime/application-jobs/contracts.ts +16 -1
- package/src/runtime/backend/contracts/index.ts +92 -18
- package/src/runtime/backend/mesh-actor-session-node-adapter.ts +5 -3
- package/src/runtime/backend/mesh-completion-table.ts +160 -57
- package/src/runtime/backend/mesh-dispatch-pump.ts +237 -108
- 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 +148 -85
- package/src/runtime/backend/node/node-raw-mesh-backend.ts +315 -201
- package/src/runtime/backend/node/node-socket-backend-adapter.ts +26 -11
- 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 +132 -58
- package/src/runtime/channels/channel-dispatch-pipeline.ts +198 -114
- package/src/runtime/channels/channel-dispatch-services.ts +69 -1
- package/src/runtime/channels/channel-dispatchers.ts +136 -90
- package/src/runtime/channels/channel-envelope-inspection.ts +2 -16
- package/src/runtime/channels/channel-envelope.ts +225 -31
- package/src/runtime/channels/channel-outbound-operations.ts +22 -8
- package/src/runtime/channels/channel-runtime-lifecycle.ts +13 -13
- package/src/runtime/channels/channel-runtime-manager.ts +41 -17
- package/src/runtime/channels/channel-transports.ts +171 -112
- 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/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/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 +33 -4
- package/src/runtime/execution/state-lane.ts +7 -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/operation-registry.ts +98 -20
- package/src/runtime/foundation/raw-service-mesh-runtime.ts +704 -336
- 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 +55 -36
- package/src/runtime/foundation/service-relocation-runtime.ts +25 -4
- package/src/runtime/foundation/service-runtime-contracts.ts +19 -2
- 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 +732 -275
- package/src/runtime/foundation/service-stateful-wire-codec.ts +49 -16
- package/src/runtime/foundation/service-topology-registry.ts +91 -36
- 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 +231 -76
- package/src/runtime/handlers/handler-instance-scope.ts +67 -16
- 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-runtime-options-factory.ts +13 -2
- package/src/runtime/host/actor-transfer-runtime.ts +104 -430
- package/src/runtime/host/application-job-queue.ts +160 -41
- package/src/runtime/host/entry-actor-runtime.ts +4 -0
- package/src/runtime/host/index.ts +473 -271
- 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 +88 -271
- package/src/runtime/host/route-mesh-runtime.ts +12 -6
- package/src/runtime/host/runtime-shutdown.ts +15 -4
- package/src/runtime/host/service-relocation-control.ts +11 -5
- package/src/runtime/host/service-relocation-host-runtime.ts +1092 -759
- package/src/runtime/host/spot-address-transport.ts +4 -2
- package/src/runtime/host/spot-runtime-options-factory.ts +20 -7
- package/src/runtime/host/user-spot-creation-coordinator.ts +41 -100
- package/src/runtime/locations/actor-location-claims.ts +52 -30
- 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/lifecycle.ts +8 -26
- 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 +98 -64
- package/src/runtime/messaging/framework-json-v1.ts +5 -325
- package/src/runtime/messaging/packet-name.ts +5 -25
- package/src/runtime/messaging/payload-codec.ts +8 -11
- package/src/runtime/messaging/request-result.ts +62 -0
- package/src/runtime/messaging/submission-result.ts +5 -1
- package/src/runtime/protocol/service_wire_codec.generated.ts +218 -5
- package/src/runtime/protocol/service_wire_pilot_codec.generated.ts +16 -13
- package/src/runtime/spots/formal-remote-actor-admission-registry.ts +46 -25
- package/src/runtime/spots/index.ts +389 -283
- 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 +198 -96
- 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 +33 -21
- package/src/runtime/spots/spot-handler-registry.ts +56 -12
- 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 +28 -47
- package/src/runtime/spots/spot-node-runtime-manager.ts +197 -67
- package/src/runtime/spots/spot-outbound.ts +39 -19
- package/src/runtime/spots/spot-remote-codec.ts +9 -2
- package/src/runtime/spots/spot-routed-spot-packet-dispatch.ts +2 -1
- package/src/runtime/spots/spot-runtime-ports.ts +1 -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 -4
- package/src/runtime/spots/spot-timer.ts +418 -158
- 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 +13 -34
- package/src/runtime/workers/index.ts +1 -1
|
@@ -6,6 +6,7 @@ const application_ingress_record_owner_1 = require("../application-jobs/applicat
|
|
|
6
6
|
const submission_result_1 = require("../messaging/submission-result");
|
|
7
7
|
const runtime_values_1 = require("../backend/runtime-values");
|
|
8
8
|
const service_wire_codec_generated_1 = require("../protocol/service_wire_codec.generated");
|
|
9
|
+
const service_wire_binary_primitives_1 = require("./service-wire-binary-primitives");
|
|
9
10
|
const operation_registry_1 = require("./operation-registry");
|
|
10
11
|
const service_liveness_registry_1 = require("./service-liveness-registry");
|
|
11
12
|
const service_mailbox_1 = require("./service-mailbox");
|
|
@@ -17,6 +18,7 @@ const nativeErrnoValues = node_os_1.constants.errno;
|
|
|
17
18
|
// Framework error code 13 (RequestTargetNotFound) is encoded as 14 on a
|
|
18
19
|
// RequestResult.NotFound reply. Boundary transport results keep failureCode 0.
|
|
19
20
|
const RAW_MESH_RECEIVE_RECORD_BUDGET = 64;
|
|
21
|
+
const NODE_SEND_HEADER = (0, service_wire_m6a_codec_1.encodeNodeSendHeader)();
|
|
20
22
|
const RAW_MESH_RECEIVE_BYTE_BUDGET = 4 * 1024 * 1024;
|
|
21
23
|
exports.RAW_MESH_RECEIVE_TIME_BUDGET_MS = 2;
|
|
22
24
|
const REQUEST_TARGET_NOT_FOUND_FAILURE_CODE = service_wire_constants_generated_1.ServiceWireFrameworkErrorCode.requestTargetNotFound;
|
|
@@ -37,6 +39,7 @@ class RawServiceMeshRuntime {
|
|
|
37
39
|
expectedPeers = new Map();
|
|
38
40
|
endpointOnlyPeers = new Set();
|
|
39
41
|
peerConnectionIntentRemoved = new Set();
|
|
42
|
+
peerRouteChanged = new Set();
|
|
40
43
|
/**
|
|
41
44
|
* The last observed Core selected route of each RID (Core ROUTER §10.1):
|
|
42
45
|
* RID -> route generation. Only `observeSelectedRoutes` replaces it.
|
|
@@ -44,10 +47,12 @@ class RawServiceMeshRuntime {
|
|
|
44
47
|
selectedRoutes = new Map();
|
|
45
48
|
bindingPort;
|
|
46
49
|
applicationJobQueue;
|
|
50
|
+
nodeMailboxOwner;
|
|
47
51
|
peerAdmissionSealed;
|
|
48
52
|
applicationJobStop = new AbortController();
|
|
49
53
|
receiveAcquisition;
|
|
50
54
|
receivePermit;
|
|
55
|
+
receiveRotation;
|
|
51
56
|
controlSends = new Map();
|
|
52
57
|
infrastructureFailure;
|
|
53
58
|
onReceiveReady;
|
|
@@ -62,12 +67,14 @@ class RawServiceMeshRuntime {
|
|
|
62
67
|
router;
|
|
63
68
|
nextCorrelation = 1n;
|
|
64
69
|
serviceIngress;
|
|
70
|
+
serviceIngressAccepts;
|
|
65
71
|
closed = false;
|
|
66
72
|
constructor(options) {
|
|
67
73
|
this.onReceiveReady = options.onReceiveReady;
|
|
68
74
|
this.infrastructureTaskRunner = options.infrastructureTaskRunner;
|
|
69
75
|
this.operations = new operation_registry_1.OperationRegistry(undefined, options.onPendingOperationsChanged);
|
|
70
76
|
this.descriptor = options.descriptor;
|
|
77
|
+
this.nodeMailboxOwner = `node:${options.descriptor.nodeRoutingId}`;
|
|
71
78
|
this.topology = new service_topology_registry_1.ServiceTopologyRegistry(options.descriptor);
|
|
72
79
|
this.mailbox = new service_mailbox_1.ServiceMailbox(options.onMailboxReady);
|
|
73
80
|
this.liveness = new service_liveness_registry_1.ServiceLivenessRegistry(options.probeIntervalMs, options.peerTimeoutMs);
|
|
@@ -170,13 +177,15 @@ class RawServiceMeshRuntime {
|
|
|
170
177
|
router.disconnectRid(nodeRoutingId);
|
|
171
178
|
}
|
|
172
179
|
else {
|
|
173
|
-
|
|
180
|
+
try {
|
|
181
|
+
router.disconnect(endpoint);
|
|
182
|
+
}
|
|
183
|
+
catch (error) {
|
|
184
|
+
if (!isAlreadyDisconnectedError(error))
|
|
185
|
+
throw error;
|
|
186
|
+
}
|
|
174
187
|
}
|
|
175
188
|
}
|
|
176
|
-
catch (error) {
|
|
177
|
-
if (!isAlreadyDisconnectedError(error))
|
|
178
|
-
throw error;
|
|
179
|
-
}
|
|
180
189
|
finally {
|
|
181
190
|
if (current !== undefined)
|
|
182
191
|
this.removePeer(current);
|
|
@@ -222,6 +231,58 @@ class RawServiceMeshRuntime {
|
|
|
222
231
|
this.peerConnectionIntentRemoved.delete(listener);
|
|
223
232
|
};
|
|
224
233
|
}
|
|
234
|
+
observePeerRoute(nodeRoutingId) {
|
|
235
|
+
const selected = this.selectedRoutes.get(nodeRoutingId);
|
|
236
|
+
const admitted = this.topology.admittedPeer(nodeRoutingId)?.liveness?.connectionId;
|
|
237
|
+
return {
|
|
238
|
+
generation: selected ?? (typeof admitted === 'bigint' ? admitted : undefined),
|
|
239
|
+
ready: admitted !== undefined && (selected === undefined || admitted === selected)
|
|
240
|
+
};
|
|
241
|
+
}
|
|
242
|
+
async waitForPeerRoute(nodeRoutingId, lifecycleGeneration, deadlineUnixMs, signal) {
|
|
243
|
+
const remaining = deadlineUnixMs - BigInt(Date.now());
|
|
244
|
+
if (remaining <= 0n)
|
|
245
|
+
throw new operation_registry_1.OperationTimeoutError(0n);
|
|
246
|
+
const pending = this.operations.register(Number(remaining));
|
|
247
|
+
const check = () => {
|
|
248
|
+
if (this.isPeerRouteReady(nodeRoutingId, lifecycleGeneration)) {
|
|
249
|
+
this.operations.complete(pending.id, { terminalResult: runtime_values_1.RequestResult.Ok, failureCode: 0 });
|
|
250
|
+
}
|
|
251
|
+
};
|
|
252
|
+
const unsubscribe = this.observePeerRouteChanged((rid) => {
|
|
253
|
+
if (rid === nodeRoutingId)
|
|
254
|
+
check();
|
|
255
|
+
});
|
|
256
|
+
const abort = () => this.operations.fail(pending.id, signal?.reason);
|
|
257
|
+
signal?.addEventListener('abort', abort, { once: true });
|
|
258
|
+
try {
|
|
259
|
+
if (signal?.aborted === true)
|
|
260
|
+
abort();
|
|
261
|
+
else
|
|
262
|
+
check();
|
|
263
|
+
await pending.promise;
|
|
264
|
+
}
|
|
265
|
+
finally {
|
|
266
|
+
unsubscribe();
|
|
267
|
+
signal?.removeEventListener('abort', abort);
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
get requestStopSignal() {
|
|
271
|
+
return this.applicationJobStop.signal;
|
|
272
|
+
}
|
|
273
|
+
observePeerRouteChanged(listener) {
|
|
274
|
+
this.peerRouteChanged.add(listener);
|
|
275
|
+
return () => {
|
|
276
|
+
this.peerRouteChanged.delete(listener);
|
|
277
|
+
};
|
|
278
|
+
}
|
|
279
|
+
hasSelectedPeerRoute(nodeRoutingId) {
|
|
280
|
+
return this.selectedRoutes.has(nodeRoutingId);
|
|
281
|
+
}
|
|
282
|
+
notifyPeerRouteChanged(nodeRoutingId) {
|
|
283
|
+
for (const listener of this.peerRouteChanged)
|
|
284
|
+
listener(nodeRoutingId);
|
|
285
|
+
}
|
|
225
286
|
notifyPeerConnectionIntentRemoved(nodeRoutingId) {
|
|
226
287
|
// Only the logical owner's removal publishes lifecycle termination.
|
|
227
288
|
// A physical disconnect alone retains the connection expectation.
|
|
@@ -231,26 +292,34 @@ class RawServiceMeshRuntime {
|
|
|
231
292
|
listener(nodeRoutingId);
|
|
232
293
|
}
|
|
233
294
|
announcePeer(nodeRoutingId) {
|
|
234
|
-
|
|
295
|
+
if (this.closed)
|
|
296
|
+
return false;
|
|
235
297
|
const generation = this.selectedRoutes.get(nodeRoutingId);
|
|
236
|
-
if (
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
298
|
+
if (generation === undefined)
|
|
299
|
+
return false;
|
|
300
|
+
const key = controlSendKey(nodeRoutingId, service_wire_m6a_codec_1.M6aServiceWireCommand.hello);
|
|
301
|
+
if (!this.isPeerAnnouncementCurrent(nodeRoutingId, generation)) {
|
|
302
|
+
this.controlSends.delete(key);
|
|
303
|
+
return false;
|
|
304
|
+
}
|
|
305
|
+
const current = () => this.isPeerAnnouncementCurrent(nodeRoutingId, generation);
|
|
306
|
+
const existing = this.controlSends.get(key);
|
|
307
|
+
const hello = existing?.current?.() === true
|
|
308
|
+
? existing.hello
|
|
309
|
+
: (0, service_wire_m6a_codec_1.encodeRouteMeshAdmission)(service_wire_m6a_codec_1.M6aServiceWireCommand.hello, this.topology.localDescriptor());
|
|
310
|
+
return this.startControlSend(nodeRoutingId, service_wire_m6a_codec_1.M6aServiceWireCommand.hello, () => this.submitControl(nodeRoutingId, [hello]), current, hello);
|
|
311
|
+
}
|
|
312
|
+
isPeerAnnouncementCurrent(nodeRoutingId, generation) {
|
|
313
|
+
const admission = this.topology.routeAdmission(nodeRoutingId);
|
|
314
|
+
return (this.selectedRoutes.get(nodeRoutingId) === generation &&
|
|
315
|
+
!(admission?.connectionId === routeConnectionId(generation) &&
|
|
316
|
+
admission.remoteAdmitReceived === true) &&
|
|
317
|
+
this.peerAdmissionSealed?.() !== true);
|
|
249
318
|
}
|
|
250
319
|
isPeerRouteReady(nodeRoutingId, lifecycleGeneration) {
|
|
251
320
|
// Admission is bound to the observed selected route: the route observer
|
|
252
321
|
// removes the peer when that route ends or is replaced.
|
|
253
|
-
const peer = this.topology.
|
|
322
|
+
const peer = this.topology.admittedPeer(nodeRoutingId);
|
|
254
323
|
return (peer !== undefined &&
|
|
255
324
|
(lifecycleGeneration === undefined ||
|
|
256
325
|
peer.descriptor.lifecycleGeneration === lifecycleGeneration));
|
|
@@ -287,22 +356,22 @@ class RawServiceMeshRuntime {
|
|
|
287
356
|
// placement and channel selectors therefore need the new mutable fields
|
|
288
357
|
// on that same connection before the next request is selected; waiting for
|
|
289
358
|
// a reconnect would leave a race where a drained node is selected again.
|
|
359
|
+
await this.publishLocalDescriptor(this.topology.peers().map((peer) => peer.descriptor.nodeRoutingId));
|
|
360
|
+
}
|
|
361
|
+
async publishLocalDescriptor(targets) {
|
|
290
362
|
const update = (0, service_wire_m6a_codec_1.encodeRouteMeshAdmission)(service_wire_m6a_codec_1.M6aServiceWireCommand.update, this.topology.localDescriptor());
|
|
291
|
-
for (const
|
|
292
|
-
await this.
|
|
363
|
+
for (const target of targets) {
|
|
364
|
+
await this.sendService(target, [update]);
|
|
293
365
|
}
|
|
294
366
|
}
|
|
295
367
|
replaceDiscoveredNotRequired(descriptors) {
|
|
296
368
|
this.topology.replaceDiscoveredNotRequired(descriptors);
|
|
297
369
|
}
|
|
298
370
|
isObjectClientNodeDirectTarget(nodeRoutingId) {
|
|
299
|
-
|
|
300
|
-
? this.topology.localDescriptor()
|
|
301
|
-
: this.topology.knownDescriptor(nodeRoutingId);
|
|
302
|
-
return descriptor?.objectRole === 'client';
|
|
371
|
+
return this.topology.isObjectClientNodeDirectTarget(nodeRoutingId);
|
|
303
372
|
}
|
|
304
|
-
|
|
305
|
-
return this.send(targetNodeRoutingId, [
|
|
373
|
+
sendToNode(targetNodeRoutingId, payload) {
|
|
374
|
+
return this.send(targetNodeRoutingId, [NODE_SEND_HEADER, this.applicationFrame(payload)]);
|
|
306
375
|
}
|
|
307
376
|
async sendToChannel(channelName, payload) {
|
|
308
377
|
const selection = this.selectChannelTarget(channelName);
|
|
@@ -317,17 +386,42 @@ class RawServiceMeshRuntime {
|
|
|
317
386
|
? runtime_values_1.SubmitResult.Ok
|
|
318
387
|
: runtime_values_1.SubmitResult.NotConnected;
|
|
319
388
|
}
|
|
320
|
-
requestToNode(targetNodeRoutingId, payload, timeoutMs) {
|
|
321
|
-
return this.requestToTarget(targetNodeRoutingId, payload, timeoutMs);
|
|
389
|
+
requestToNode(targetNodeRoutingId, payload, timeoutMs, onAdmitted, observer, operationKind) {
|
|
390
|
+
return this.requestToTarget(targetNodeRoutingId, payload, timeoutMs, undefined, onAdmitted, observer, operationKind);
|
|
322
391
|
}
|
|
323
|
-
requestToChannel(channelName, payload, timeoutMs) {
|
|
392
|
+
requestToChannel(channelName, payload, timeoutMs, onAdmitted, observer, operationKind) {
|
|
324
393
|
const selection = this.selectChannelTarget(channelName);
|
|
325
394
|
if (selection.kind !== 'selected') {
|
|
326
|
-
const pending = this.
|
|
327
|
-
this.
|
|
395
|
+
const pending = this.registerRequest(timeoutMs, observer, operationKind);
|
|
396
|
+
this.completeRequest(pending, selection.requestResult);
|
|
328
397
|
return pending;
|
|
329
398
|
}
|
|
330
|
-
return this.requestToTarget(selection.peer.descriptor.nodeRoutingId, payload, timeoutMs, channelName);
|
|
399
|
+
return this.requestToTarget(selection.peer.descriptor.nodeRoutingId, payload, timeoutMs, channelName, onAdmitted, observer, operationKind);
|
|
400
|
+
}
|
|
401
|
+
/**
|
|
402
|
+
* One pending entry per request: an observed request reports its terminal
|
|
403
|
+
* to the caller's observer; any other request keeps the Promise contract.
|
|
404
|
+
*/
|
|
405
|
+
registerRequest(timeoutMs, observer, operationKind) {
|
|
406
|
+
return observer === undefined
|
|
407
|
+
? this.operations.register(timeoutMs)
|
|
408
|
+
: { id: this.operations.registerObserved(timeoutMs, observer, operationKind) };
|
|
409
|
+
}
|
|
410
|
+
/**
|
|
411
|
+
* An observed caller learns the operation id only when the request call
|
|
412
|
+
* returns, so a terminal decided inside that call is delivered after it.
|
|
413
|
+
*/
|
|
414
|
+
completeRequest(pending, result) {
|
|
415
|
+
if (pending.promise === undefined)
|
|
416
|
+
queueMicrotask(() => this.operations.complete(pending.id, result));
|
|
417
|
+
else
|
|
418
|
+
this.operations.complete(pending.id, result);
|
|
419
|
+
}
|
|
420
|
+
failRequest(pending, error) {
|
|
421
|
+
if (pending.promise === undefined)
|
|
422
|
+
queueMicrotask(() => this.operations.fail(pending.id, error));
|
|
423
|
+
else
|
|
424
|
+
this.operations.fail(pending.id, error);
|
|
331
425
|
}
|
|
332
426
|
selectChannelTarget(channelName) {
|
|
333
427
|
const selected = this.topology.selectChannel(channelName, (peer) => this.isPeerRouteReady(peer.descriptor.nodeRoutingId));
|
|
@@ -348,11 +442,12 @@ class RawServiceMeshRuntime {
|
|
|
348
442
|
}
|
|
349
443
|
};
|
|
350
444
|
}
|
|
351
|
-
setServiceIngress(handler) {
|
|
445
|
+
setServiceIngress(handler, accepts) {
|
|
352
446
|
if (this.serviceIngress !== undefined && this.serviceIngress !== handler) {
|
|
353
447
|
throw new Error('Raw service ingress is already registered.');
|
|
354
448
|
}
|
|
355
449
|
this.serviceIngress = handler;
|
|
450
|
+
this.serviceIngressAccepts = accepts;
|
|
356
451
|
}
|
|
357
452
|
async reserveLocalIngress(signal) {
|
|
358
453
|
const waitSignal = signal === undefined
|
|
@@ -362,11 +457,17 @@ class RawServiceMeshRuntime {
|
|
|
362
457
|
return application_ingress_record_owner_1.ApplicationIngressRecordOwner.create(this.applicationJobQueue, permit, { close() { } });
|
|
363
458
|
}
|
|
364
459
|
async sendService(targetNodeRoutingId, parts) {
|
|
365
|
-
|
|
460
|
+
try {
|
|
461
|
+
await this.requireStarted().send(targetNodeRoutingId, parts);
|
|
462
|
+
return true;
|
|
463
|
+
}
|
|
464
|
+
catch (error) {
|
|
465
|
+
return this.sendFailure(error);
|
|
466
|
+
}
|
|
366
467
|
}
|
|
367
|
-
requestService(targetNodeRoutingId, parts, timeoutMs) {
|
|
368
|
-
const admission = this.topology.
|
|
369
|
-
return this.requireStarted().request(targetNodeRoutingId, parts, timeoutMs, admission?.recordReceived);
|
|
468
|
+
requestService(targetNodeRoutingId, parts, timeoutMs, onAdmitted) {
|
|
469
|
+
const admission = this.topology.admittedPeer(targetNodeRoutingId)?.liveness;
|
|
470
|
+
return this.requireStarted().request(targetNodeRoutingId, parts, timeoutMs, admission?.recordReceived, onAdmitted);
|
|
370
471
|
}
|
|
371
472
|
replyService(record, parts) {
|
|
372
473
|
if (record.requestSequence === undefined) {
|
|
@@ -423,51 +524,59 @@ class RawServiceMeshRuntime {
|
|
|
423
524
|
const observe = (_source, byteCount) => {
|
|
424
525
|
bytes += byteCount;
|
|
425
526
|
};
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
527
|
+
const rotation = (this.receiveRotation ??= this.applicationJobQueue.createReceiveRotation(RAW_MESH_RECEIVE_RECORD_BUDGET, 'remote'));
|
|
528
|
+
if (receiveReady)
|
|
529
|
+
rotation.reserve();
|
|
530
|
+
try {
|
|
531
|
+
while (receiveReady && messages < RAW_MESH_RECEIVE_RECORD_BUDGET && !this.closed) {
|
|
532
|
+
const received = this.receiveOne(performance.now(), observe, rotation);
|
|
533
|
+
const result = received instanceof Promise ? await received : received;
|
|
534
|
+
if (result === 'noData') {
|
|
535
|
+
receiveReady = false;
|
|
536
|
+
break;
|
|
537
|
+
}
|
|
538
|
+
messages += 1;
|
|
539
|
+
// Core owns the per-peer fair-queue cursor. The Framework limit bounds
|
|
540
|
+
// the entire round, so changing peers does not renew its byte/count budget.
|
|
541
|
+
if (bytes >= RAW_MESH_RECEIVE_BYTE_BUDGET ||
|
|
542
|
+
performance.now() - startedAtMs >= exports.RAW_MESH_RECEIVE_TIME_BUDGET_MS)
|
|
543
|
+
break;
|
|
431
544
|
}
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
if (bytes >= RAW_MESH_RECEIVE_BYTE_BUDGET ||
|
|
436
|
-
performance.now() - startedAtMs >= exports.RAW_MESH_RECEIVE_TIME_BUDGET_MS)
|
|
437
|
-
break;
|
|
545
|
+
}
|
|
546
|
+
finally {
|
|
547
|
+
rotation.releaseUnused();
|
|
438
548
|
}
|
|
439
549
|
if (!this.closed) {
|
|
440
|
-
for (const nodeRoutingId of this.expectedPeers.keys()) {
|
|
441
|
-
if (this.topology.peer(nodeRoutingId) === undefined)
|
|
442
|
-
await this.announcePeer(nodeRoutingId);
|
|
443
|
-
}
|
|
444
550
|
this.tickLiveness();
|
|
445
551
|
}
|
|
446
552
|
return receiveReady && messages > 0;
|
|
447
553
|
}
|
|
448
|
-
|
|
554
|
+
receiveOne(nowMs, observe, rotation) {
|
|
449
555
|
const router = this.requireStarted();
|
|
450
556
|
this.observeInfrastructureFailure();
|
|
451
|
-
|
|
557
|
+
let permit = this.receivePermit;
|
|
558
|
+
this.receivePermit = undefined;
|
|
559
|
+
permit ??= rotation?.take();
|
|
560
|
+
if (permit === undefined && this.receiveAcquisition === undefined) {
|
|
452
561
|
let resolveAcquisition;
|
|
453
562
|
let rejectAcquisition;
|
|
454
|
-
|
|
455
|
-
resolveAcquisition = resolve;
|
|
456
|
-
rejectAcquisition = reject;
|
|
457
|
-
});
|
|
458
|
-
const permit = this.applicationJobQueue.acquireOrResume((permit) => {
|
|
563
|
+
permit = this.applicationJobQueue.acquireOrResume((permit) => {
|
|
459
564
|
this.receiveAcquisition = undefined;
|
|
460
|
-
if (this.closed)
|
|
565
|
+
if (this.closed) {
|
|
461
566
|
permit.releaseAfterInternalProcessing();
|
|
567
|
+
permit.releaseStorage?.();
|
|
568
|
+
}
|
|
462
569
|
else {
|
|
463
570
|
this.receivePermit = permit;
|
|
464
571
|
this.onReceiveReady?.();
|
|
465
572
|
}
|
|
466
|
-
resolveAcquisition(permit);
|
|
467
|
-
}, rejectAcquisition, this.applicationJobStop.signal, 'remote');
|
|
468
|
-
if (permit
|
|
469
|
-
|
|
470
|
-
|
|
573
|
+
resolveAcquisition?.(permit);
|
|
574
|
+
}, (error) => rejectAcquisition?.(error), this.applicationJobStop.signal, 'remote');
|
|
575
|
+
if (permit === undefined) {
|
|
576
|
+
const acquisition = new Promise((resolve, reject) => {
|
|
577
|
+
resolveAcquisition = resolve;
|
|
578
|
+
rejectAcquisition = reject;
|
|
579
|
+
});
|
|
471
580
|
this.receiveAcquisition = acquisition;
|
|
472
581
|
acquisition.catch((error) => {
|
|
473
582
|
this.receiveAcquisition = undefined;
|
|
@@ -476,12 +585,11 @@ class RawServiceMeshRuntime {
|
|
|
476
585
|
});
|
|
477
586
|
}
|
|
478
587
|
}
|
|
479
|
-
const permit = this.receivePermit;
|
|
480
|
-
this.receivePermit = undefined;
|
|
481
588
|
if (permit === undefined)
|
|
482
589
|
return 'noData';
|
|
483
590
|
if (this.closed) {
|
|
484
591
|
permit.releaseAfterInternalProcessing();
|
|
592
|
+
permit.releaseStorage?.();
|
|
485
593
|
return 'noData';
|
|
486
594
|
}
|
|
487
595
|
let received;
|
|
@@ -490,23 +598,44 @@ class RawServiceMeshRuntime {
|
|
|
490
598
|
}
|
|
491
599
|
catch (error) {
|
|
492
600
|
permit.releaseAfterInternalProcessing();
|
|
601
|
+
permit.releaseStorage?.();
|
|
493
602
|
throw error;
|
|
494
603
|
}
|
|
495
604
|
if (received === undefined) {
|
|
496
605
|
permit.releaseAfterInternalProcessing();
|
|
606
|
+
permit.releaseStorage?.();
|
|
497
607
|
return 'noData';
|
|
498
608
|
}
|
|
499
609
|
const applicationJobOwner = application_ingress_record_owner_1.ApplicationIngressRecordOwner.create(this.applicationJobQueue, permit, received);
|
|
610
|
+
let result;
|
|
611
|
+
try {
|
|
612
|
+
result = this.processReceived(received, nowMs, applicationJobOwner);
|
|
613
|
+
}
|
|
614
|
+
catch (error) {
|
|
615
|
+
applicationJobOwner.close();
|
|
616
|
+
throw error;
|
|
617
|
+
}
|
|
618
|
+
return result instanceof Promise
|
|
619
|
+
? result.then((value) => this.finishReceive(received, applicationJobOwner, observe, value), (error) => {
|
|
620
|
+
applicationJobOwner.close();
|
|
621
|
+
throw error;
|
|
622
|
+
})
|
|
623
|
+
: this.finishReceive(received, applicationJobOwner, observe, result);
|
|
624
|
+
}
|
|
625
|
+
finishReceive(received, owner, observe, result) {
|
|
500
626
|
try {
|
|
501
|
-
|
|
502
|
-
if (result === 'protocolError') {
|
|
627
|
+
if (result === 'protocolError')
|
|
503
628
|
this.reportProtocolError(received);
|
|
629
|
+
if (observe !== undefined) {
|
|
630
|
+
let bytes = 0;
|
|
631
|
+
for (const part of received.parts)
|
|
632
|
+
bytes += part.byteLength;
|
|
633
|
+
observe(received.sourceRid, bytes);
|
|
504
634
|
}
|
|
505
|
-
observe?.(received.sourceRid, received.parts.reduce((sum, part) => sum + part.byteLength, 0));
|
|
506
635
|
return result;
|
|
507
636
|
}
|
|
508
637
|
finally {
|
|
509
|
-
|
|
638
|
+
owner.close();
|
|
510
639
|
}
|
|
511
640
|
}
|
|
512
641
|
reportProtocolError(received) {
|
|
@@ -545,61 +674,19 @@ class RawServiceMeshRuntime {
|
|
|
545
674
|
throw error;
|
|
546
675
|
}
|
|
547
676
|
}
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
return (await this.sendControl(received.sourceRid, [
|
|
554
|
-
(0, service_wire_m6a_codec_1.encodeRouteMeshAdmission)(service_wire_m6a_codec_1.M6aServiceWireCommand.hello, this.topology.localDescriptor())
|
|
555
|
-
]))
|
|
556
|
-
? 'infrastructure'
|
|
557
|
-
: 'dropped';
|
|
558
|
-
}
|
|
677
|
+
processReceived(received, nowMs, applicationJobOwner) {
|
|
678
|
+
const peer = this.topology.admittedPeer(received.sourceRid);
|
|
679
|
+
const currentSource = peer?.liveness !== undefined && peer.liveness.connectionId === received.routeGeneration;
|
|
680
|
+
if (received.parts.length === 0)
|
|
681
|
+
return currentSource ? 'protocolError' : 'dropped';
|
|
559
682
|
try {
|
|
560
683
|
const header = (0, service_wire_m6a_codec_1.decodeHeader)(received.parts[0]);
|
|
561
684
|
if (header.command === service_wire_m6a_codec_1.M6aServiceWireCommand.hello && this.peerAdmissionSealed?.() === true) {
|
|
562
685
|
return 'dropped';
|
|
563
686
|
}
|
|
564
687
|
if (header.command === service_wire_m6a_codec_1.M6aServiceWireCommand.hello ||
|
|
565
|
-
header.command === service_wire_m6a_codec_1.M6aServiceWireCommand.admit
|
|
566
|
-
header.
|
|
567
|
-
if (received.parts.length !== 1)
|
|
568
|
-
return 'protocolError';
|
|
569
|
-
const descriptor = (0, service_wire_m6a_codec_1.decodeRouteMeshAdmission)(received.parts[0], header.command, received.sourceRid);
|
|
570
|
-
const expected = this.expectedPeers.get(received.sourceRid);
|
|
571
|
-
if (expected !== undefined &&
|
|
572
|
-
(expected.meshName !== descriptor.meshName ||
|
|
573
|
-
expected.nodeRoutingId !== descriptor.nodeRoutingId)) {
|
|
574
|
-
await this.sendControl(received.sourceRid, [
|
|
575
|
-
(0, service_wire_m6a_codec_1.encodeReject)((0, service_wire_codec_generated_1.enumWireRejectReason)('identityMismatch'))
|
|
576
|
-
]);
|
|
577
|
-
return 'infrastructure';
|
|
578
|
-
}
|
|
579
|
-
const result = this.admitPeer(descriptor, received.routeGeneration, nowMs, expected);
|
|
580
|
-
if (result !== 'admitted' && result !== 'notRequired') {
|
|
581
|
-
const detail = result === 'invalidDescriptor'
|
|
582
|
-
? describeInvalidAdmissionDescriptor(descriptor, expected, this.topology.peer(descriptor.nodeRoutingId)?.descriptor)
|
|
583
|
-
: undefined;
|
|
584
|
-
console.warn(`RouteMesh admission rejected peer '${received.sourceRid}' as ${result}` +
|
|
585
|
-
(detail === undefined ? '.' : ` (${detail}).`));
|
|
586
|
-
await this.sendControl(received.sourceRid, [(0, service_wire_m6a_codec_1.encodeReject)(admissionReason(result))]);
|
|
587
|
-
return 'infrastructure';
|
|
588
|
-
}
|
|
589
|
-
if (result === 'admitted')
|
|
590
|
-
this.selectBilateralConnection(descriptor);
|
|
591
|
-
if (header.command === service_wire_m6a_codec_1.M6aServiceWireCommand.hello) {
|
|
592
|
-
// Hello supplies only the sender's descriptor. Even NotRequired
|
|
593
|
-
// peers must receive ours before the intent owner closes transport;
|
|
594
|
-
// submitting a response does not guarantee delivery before close.
|
|
595
|
-
await this.sendControl(received.sourceRid, [
|
|
596
|
-
(0, service_wire_m6a_codec_1.encodeRouteMeshAdmission)(service_wire_m6a_codec_1.M6aServiceWireCommand.admit, this.topology.localDescriptor())
|
|
597
|
-
]);
|
|
598
|
-
}
|
|
599
|
-
else if (result === 'notRequired') {
|
|
600
|
-
this.retireNotRequiredExpectedPeer(received.sourceRid, descriptor.advertisedEndpoint);
|
|
601
|
-
}
|
|
602
|
-
return 'infrastructure';
|
|
688
|
+
header.command === service_wire_m6a_codec_1.M6aServiceWireCommand.admit) {
|
|
689
|
+
return this.processAdmission(received, header, nowMs).catch((error) => this.receiveProtocolFailure(error));
|
|
603
690
|
}
|
|
604
691
|
if (header.command === service_wire_m6a_codec_1.M6aServiceWireCommand.reject) {
|
|
605
692
|
if (received.parts.length !== 1)
|
|
@@ -607,47 +694,123 @@ class RawServiceMeshRuntime {
|
|
|
607
694
|
(0, service_wire_m6a_codec_1.decodeReject)(received.parts[0]);
|
|
608
695
|
return 'infrastructure';
|
|
609
696
|
}
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
if (
|
|
614
|
-
this.
|
|
697
|
+
if (!currentSource)
|
|
698
|
+
return 'dropped';
|
|
699
|
+
this.liveness.recordReceived(peer.liveness, nowMs);
|
|
700
|
+
if (header.command === service_wire_m6a_codec_1.M6aServiceWireCommand.update) {
|
|
701
|
+
return this.processAdmission(received, header, nowMs).catch((error) => this.receiveProtocolFailure(error));
|
|
702
|
+
}
|
|
615
703
|
if (header.command === service_wire_m6a_codec_1.M6aServiceWireCommand.livenessProbe ||
|
|
616
704
|
header.command === service_wire_m6a_codec_1.M6aServiceWireCommand.livenessAck) {
|
|
617
|
-
|
|
618
|
-
return 'protocolError';
|
|
619
|
-
const record = livenessCodec.decodeLivenessRecord(received.parts[0]);
|
|
620
|
-
if (record.command === service_wire_m6a_codec_1.M6aServiceWireCommand.livenessProbe) {
|
|
621
|
-
const ack = this.liveness.acknowledgeProbe(received.sourceRid, received.routeGeneration, record.probeId);
|
|
622
|
-
if (ack === undefined)
|
|
623
|
-
return 'protocolError';
|
|
624
|
-
const sent = await this.sendControl(received.sourceRid, [
|
|
625
|
-
livenessCodec.encodeLivenessRecord({
|
|
626
|
-
command: service_wire_m6a_codec_1.M6aServiceWireCommand.livenessAck,
|
|
627
|
-
probeId: record.probeId
|
|
628
|
-
})
|
|
629
|
-
]);
|
|
630
|
-
if (!sent)
|
|
631
|
-
return 'dropped';
|
|
632
|
-
}
|
|
633
|
-
else {
|
|
634
|
-
this.liveness.acknowledge(received.sourceRid, received.routeGeneration, record.probeId, nowMs);
|
|
635
|
-
}
|
|
636
|
-
return 'infrastructure';
|
|
705
|
+
return this.processLiveness(received, nowMs).catch((error) => this.receiveProtocolFailure(error));
|
|
637
706
|
}
|
|
638
|
-
const stateful =
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
707
|
+
const stateful = this.serviceIngress !== undefined && this.serviceIngressAccepts?.(header.command) !== false
|
|
708
|
+
? this.serviceIngress({
|
|
709
|
+
command: header.command,
|
|
710
|
+
flags: header.flags,
|
|
711
|
+
sourceRoutingId: received.sourceRid,
|
|
712
|
+
sourceNodeGeneration: peer.descriptor.lifecycleGeneration,
|
|
713
|
+
sourceRoute: received.sourceRoute,
|
|
714
|
+
...(received.reply === undefined ? {} : { reply: received.reply }),
|
|
715
|
+
...(received.requestSeq === undefined
|
|
716
|
+
? {}
|
|
717
|
+
: { requestSequence: received.requestSeq }),
|
|
718
|
+
parts: received.parts,
|
|
719
|
+
applicationJobOwner
|
|
720
|
+
})
|
|
721
|
+
: undefined;
|
|
722
|
+
if (stateful instanceof Promise)
|
|
723
|
+
return stateful.then((result) => result ?? this.processApplicationReceived(received, header, applicationJobOwner), (error) => this.receiveProtocolFailure(error));
|
|
649
724
|
if (stateful !== undefined)
|
|
650
725
|
return stateful;
|
|
726
|
+
return this.processApplicationReceived(received, header, applicationJobOwner);
|
|
727
|
+
}
|
|
728
|
+
catch (error) {
|
|
729
|
+
if (!currentSource && error instanceof service_wire_m6a_codec_1.ServiceWireProtocolError)
|
|
730
|
+
return 'dropped';
|
|
731
|
+
return this.receiveProtocolFailure(error);
|
|
732
|
+
}
|
|
733
|
+
}
|
|
734
|
+
receiveProtocolFailure(error) {
|
|
735
|
+
if (error instanceof service_wire_m6a_codec_1.ServiceWireProtocolError)
|
|
736
|
+
return 'protocolError';
|
|
737
|
+
throw error;
|
|
738
|
+
}
|
|
739
|
+
async processAdmission(received, header, nowMs) {
|
|
740
|
+
if (received.parts.length !== 1)
|
|
741
|
+
return 'protocolError';
|
|
742
|
+
const descriptor = (0, service_wire_m6a_codec_1.decodeRouteMeshAdmission)(received.parts[0], header.command, received.sourceRid);
|
|
743
|
+
const expected = this.expectedPeers.get(received.sourceRid);
|
|
744
|
+
if (expected !== undefined &&
|
|
745
|
+
(expected.meshName !== descriptor.meshName ||
|
|
746
|
+
expected.nodeRoutingId !== descriptor.nodeRoutingId)) {
|
|
747
|
+
await this.sendControl(received.sourceRid, [
|
|
748
|
+
(0, service_wire_m6a_codec_1.encodeReject)((0, service_wire_codec_generated_1.enumWireRejectReason)('identityMismatch'))
|
|
749
|
+
]);
|
|
750
|
+
return 'infrastructure';
|
|
751
|
+
}
|
|
752
|
+
const helloKey = controlSendKey(received.sourceRid, service_wire_m6a_codec_1.M6aServiceWireCommand.hello);
|
|
753
|
+
const exchange = this.controlSends.get(helloKey);
|
|
754
|
+
const result = this.admitPeer(descriptor, received.routeGeneration, nowMs, expected, header.command, received.parts[0].subarray(service_wire_binary_primitives_1.SERVICE_WIRE_PREFIX_SIZE));
|
|
755
|
+
if (result !== 'admitted' && result !== 'notRequired') {
|
|
756
|
+
const detail = result === 'invalidDescriptor'
|
|
757
|
+
? describeInvalidAdmissionDescriptor(descriptor, expected, this.topology.peer(descriptor.nodeRoutingId)?.descriptor)
|
|
758
|
+
: undefined;
|
|
759
|
+
console.warn(`RouteMesh admission rejected peer '${received.sourceRid}' as ${result}` +
|
|
760
|
+
(detail === undefined ? '.' : ` (${detail}).`));
|
|
761
|
+
await this.sendControl(received.sourceRid, [(0, service_wire_m6a_codec_1.encodeReject)(admissionReason(result))]);
|
|
762
|
+
return 'infrastructure';
|
|
763
|
+
}
|
|
764
|
+
if (result === 'admitted')
|
|
765
|
+
this.selectBilateralConnection(descriptor);
|
|
766
|
+
if (header.command === service_wire_m6a_codec_1.M6aServiceWireCommand.hello) {
|
|
767
|
+
// Hello supplies only the sender's descriptor. Even NotRequired
|
|
768
|
+
// peers must receive ours before the intent owner closes transport;
|
|
769
|
+
// submitting a response does not guarantee delivery before close.
|
|
770
|
+
const local = exchange?.current?.() === true && exchange.hello !== undefined
|
|
771
|
+
? (0, service_wire_m6a_codec_1.decodeRouteMeshAdmission)(exchange.hello, service_wire_m6a_codec_1.M6aServiceWireCommand.hello, this.descriptor.nodeRoutingId)
|
|
772
|
+
: this.topology.localDescriptor();
|
|
773
|
+
await this.sendControl(received.sourceRid, [
|
|
774
|
+
(0, service_wire_m6a_codec_1.encodeRouteMeshAdmission)(service_wire_m6a_codec_1.M6aServiceWireCommand.admit, local)
|
|
775
|
+
]);
|
|
776
|
+
}
|
|
777
|
+
else if (header.command === service_wire_m6a_codec_1.M6aServiceWireCommand.admit) {
|
|
778
|
+
this.controlSends.delete(helloKey);
|
|
779
|
+
this.refreshAdmissionPending(nowMs);
|
|
780
|
+
if (result === 'notRequired') {
|
|
781
|
+
this.retireNotRequiredExpectedPeer(received.sourceRid, descriptor.advertisedEndpoint);
|
|
782
|
+
}
|
|
783
|
+
else if (exchange?.hello !== undefined &&
|
|
784
|
+
(0, service_wire_m6a_codec_1.decodeRouteMeshAdmission)(exchange.hello, service_wire_m6a_codec_1.M6aServiceWireCommand.hello, this.descriptor.nodeRoutingId).descriptorRevision < this.descriptor.descriptorRevision) {
|
|
785
|
+
await this.publishLocalDescriptor([received.sourceRid]);
|
|
786
|
+
}
|
|
787
|
+
}
|
|
788
|
+
return 'infrastructure';
|
|
789
|
+
}
|
|
790
|
+
async processLiveness(received, nowMs) {
|
|
791
|
+
if (received.parts.length !== 1)
|
|
792
|
+
return 'protocolError';
|
|
793
|
+
const record = livenessCodec.decodeLivenessRecord(received.parts[0]);
|
|
794
|
+
if (record.command === service_wire_m6a_codec_1.M6aServiceWireCommand.livenessProbe) {
|
|
795
|
+
const ack = this.liveness.acknowledgeProbe(received.sourceRid, received.routeGeneration, record.probeId);
|
|
796
|
+
if (ack === undefined)
|
|
797
|
+
return 'protocolError';
|
|
798
|
+
const sent = await this.sendControl(received.sourceRid, [
|
|
799
|
+
livenessCodec.encodeLivenessRecord({
|
|
800
|
+
command: service_wire_m6a_codec_1.M6aServiceWireCommand.livenessAck,
|
|
801
|
+
probeId: record.probeId
|
|
802
|
+
})
|
|
803
|
+
]);
|
|
804
|
+
if (!sent)
|
|
805
|
+
return 'dropped';
|
|
806
|
+
}
|
|
807
|
+
else {
|
|
808
|
+
this.liveness.acknowledge(received.sourceRid, received.routeGeneration, record.probeId, nowMs);
|
|
809
|
+
}
|
|
810
|
+
return 'infrastructure';
|
|
811
|
+
}
|
|
812
|
+
processApplicationReceived(received, header, applicationJobOwner) {
|
|
813
|
+
try {
|
|
651
814
|
if (header.flags === 0 &&
|
|
652
815
|
// A bare infrastructure control is normally exactly one frame, but a
|
|
653
816
|
// relocation Prepare now rides its bound-session journal as
|
|
@@ -663,7 +826,7 @@ class RawServiceMeshRuntime {
|
|
|
663
826
|
received.parts.length >= 1 &&
|
|
664
827
|
isBareInfrastructureControl(header.command)) {
|
|
665
828
|
const accepted = this.mailbox.tryEnqueue({
|
|
666
|
-
owner:
|
|
829
|
+
owner: this.nodeMailboxOwner,
|
|
667
830
|
domain: 'infrastructure',
|
|
668
831
|
parts: received.parts,
|
|
669
832
|
sourceRoutingId: received.sourceRid,
|
|
@@ -675,62 +838,60 @@ class RawServiceMeshRuntime {
|
|
|
675
838
|
}
|
|
676
839
|
if (header.flags !== 0 ||
|
|
677
840
|
received.parts.length !== 2 ||
|
|
678
|
-
!
|
|
679
|
-
service_wire_m6a_codec_1.M6aServiceWireCommand.nodeSend,
|
|
680
|
-
service_wire_m6a_codec_1.M6aServiceWireCommand.nodeRequest,
|
|
681
|
-
service_wire_m6a_codec_1.M6aServiceWireCommand.channelSend,
|
|
682
|
-
service_wire_m6a_codec_1.M6aServiceWireCommand.channelRequest
|
|
683
|
-
].includes(header.command)) {
|
|
841
|
+
!isApplicationEnvelopeCommand(header.command)) {
|
|
684
842
|
return 'protocolError';
|
|
685
843
|
}
|
|
686
844
|
let owner;
|
|
687
845
|
let correlation;
|
|
688
846
|
if (header.command === service_wire_m6a_codec_1.M6aServiceWireCommand.nodeSend) {
|
|
689
|
-
owner =
|
|
847
|
+
owner = this.nodeMailboxOwner;
|
|
690
848
|
}
|
|
691
849
|
else if (header.command === service_wire_m6a_codec_1.M6aServiceWireCommand.nodeRequest) {
|
|
692
|
-
owner =
|
|
693
|
-
correlation = (0, service_wire_m6a_codec_1.decodeNodeRequestHeader)(received.parts[0]);
|
|
850
|
+
owner = this.nodeMailboxOwner;
|
|
851
|
+
correlation = (0, service_wire_m6a_codec_1.decodeNodeRequestHeader)(received.parts[0], header);
|
|
694
852
|
}
|
|
695
853
|
else if (header.command === service_wire_m6a_codec_1.M6aServiceWireCommand.channelSend) {
|
|
696
|
-
owner = `channel:${(0, service_wire_m6a_codec_1.decodeChannelSendHeader)(received.parts[0])}`;
|
|
854
|
+
owner = `channel:${(0, service_wire_m6a_codec_1.decodeChannelSendHeader)(received.parts[0], header)}`;
|
|
697
855
|
}
|
|
698
856
|
else {
|
|
699
|
-
const channel = (0, service_wire_m6a_codec_1.decodeChannelRequestHeader)(received.parts[0]);
|
|
857
|
+
const channel = (0, service_wire_m6a_codec_1.decodeChannelRequestHeader)(received.parts[0], header);
|
|
700
858
|
owner = `channel:${channel.channelName}`;
|
|
701
859
|
correlation = channel.correlation;
|
|
702
860
|
}
|
|
703
|
-
const
|
|
704
|
-
|
|
705
|
-
owner,
|
|
706
|
-
|
|
707
|
-
|
|
861
|
+
const job = applicationJobOwner.acquire('application');
|
|
862
|
+
return job instanceof Promise
|
|
863
|
+
? job.then((permit) => this.enqueueOrdinaryRecord(received, owner, correlation, permit))
|
|
864
|
+
: this.enqueueOrdinaryRecord(received, owner, correlation, job);
|
|
865
|
+
}
|
|
866
|
+
catch (error) {
|
|
867
|
+
return this.receiveProtocolFailure(error);
|
|
868
|
+
}
|
|
869
|
+
}
|
|
870
|
+
enqueueOrdinaryRecord(received, owner, correlation, applicationJob) {
|
|
871
|
+
const accepted = this.mailbox.tryEnqueue({
|
|
872
|
+
owner,
|
|
873
|
+
domain: 'application',
|
|
874
|
+
parts: received.parts,
|
|
875
|
+
sourceRoutingId: received.sourceRid,
|
|
876
|
+
sourceRoute: received.sourceRoute,
|
|
877
|
+
reply: received.reply,
|
|
878
|
+
requestSequence: received.requestSeq,
|
|
879
|
+
correlation,
|
|
880
|
+
applicationJob
|
|
881
|
+
});
|
|
882
|
+
if (accepted)
|
|
883
|
+
return 'application';
|
|
884
|
+
applicationJob.close();
|
|
885
|
+
if (correlation !== undefined && received.requestSeq !== undefined) {
|
|
886
|
+
this.replyService({
|
|
708
887
|
sourceRoutingId: received.sourceRid,
|
|
709
888
|
sourceRoute: received.sourceRoute,
|
|
710
|
-
...(received.reply === undefined ? {} : { reply: received.reply }),
|
|
711
889
|
requestSequence: received.requestSeq,
|
|
712
|
-
...(
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
if (accepted)
|
|
716
|
-
return 'application';
|
|
717
|
-
applicationJob.close();
|
|
718
|
-
if (correlation !== undefined && received.requestSeq !== undefined) {
|
|
719
|
-
this.replyService({
|
|
720
|
-
sourceRoutingId: received.sourceRid,
|
|
721
|
-
sourceRoute: received.sourceRoute,
|
|
722
|
-
requestSequence: received.requestSeq,
|
|
723
|
-
...(received.reply === undefined ? {} : { reply: received.reply })
|
|
724
|
-
}, [(0, service_wire_m6a_codec_1.encodeReplyHeader)(correlation, runtime_values_1.RequestResult.NotConnected, 0)]);
|
|
725
|
-
return 'infrastructure';
|
|
726
|
-
}
|
|
727
|
-
return 'dropped';
|
|
728
|
-
}
|
|
729
|
-
catch (error) {
|
|
730
|
-
if (error instanceof service_wire_m6a_codec_1.ServiceWireProtocolError)
|
|
731
|
-
return 'protocolError';
|
|
732
|
-
throw error;
|
|
890
|
+
...(received.reply === undefined ? {} : { reply: received.reply })
|
|
891
|
+
}, [(0, service_wire_m6a_codec_1.encodeReplyHeader)(correlation, runtime_values_1.RequestResult.NotConnected, 0)]);
|
|
892
|
+
return 'infrastructure';
|
|
733
893
|
}
|
|
894
|
+
return 'dropped';
|
|
734
895
|
}
|
|
735
896
|
expireOperations(nowMs, turnDeadlineMs) {
|
|
736
897
|
return this.operations.expire(nowMs, turnDeadlineMs);
|
|
@@ -738,9 +899,38 @@ class RawServiceMeshRuntime {
|
|
|
738
899
|
get pendingOperationCount() {
|
|
739
900
|
return this.operations.size;
|
|
740
901
|
}
|
|
902
|
+
cancelPendingOperations(reason) {
|
|
903
|
+
this.operations.failAll(reason);
|
|
904
|
+
}
|
|
905
|
+
/**
|
|
906
|
+
* The next management deadline of this node (spec 08 §4.2): request expiry,
|
|
907
|
+
* liveness probe or timeout, or an owned HELLO exchange still awaiting
|
|
908
|
+
* ADMIT, which keeps the existing announce cadence.
|
|
909
|
+
*/
|
|
910
|
+
nextMaintenanceDeadlineMs(nowMs) {
|
|
911
|
+
this.refreshAdmissionPending(nowMs);
|
|
912
|
+
return Math.min(this.operations.nextDeadlineMs(), this.liveness.nextDeadlineMs());
|
|
913
|
+
}
|
|
914
|
+
refreshAdmissionPending(nowMs) {
|
|
915
|
+
let pending = false;
|
|
916
|
+
if (!this.closed && this.controlSends.size !== 0) {
|
|
917
|
+
for (const nodeRoutingId of this.selectedRoutes.keys()) {
|
|
918
|
+
const exchange = this.controlSends.get(controlSendKey(nodeRoutingId, service_wire_m6a_codec_1.M6aServiceWireCommand.hello));
|
|
919
|
+
if (exchange?.current?.() === true) {
|
|
920
|
+
pending = true;
|
|
921
|
+
break;
|
|
922
|
+
}
|
|
923
|
+
}
|
|
924
|
+
}
|
|
925
|
+
this.liveness.setAdmissionPending(pending, nowMs);
|
|
926
|
+
}
|
|
741
927
|
tickLiveness(nowMs = performance.now()) {
|
|
928
|
+
const admissionDue = this.liveness.tickAdmission(nowMs);
|
|
742
929
|
const result = this.liveness.tick(nowMs);
|
|
743
930
|
this.requireStarted();
|
|
931
|
+
if (admissionDue)
|
|
932
|
+
for (const nodeRoutingId of this.selectedRoutes.keys())
|
|
933
|
+
void this.announcePeer(nodeRoutingId);
|
|
744
934
|
for (const probe of result.probes) {
|
|
745
935
|
const parts = [
|
|
746
936
|
livenessCodec.encodeLivenessRecord({
|
|
@@ -777,10 +967,8 @@ class RawServiceMeshRuntime {
|
|
|
777
967
|
for (const [nodeRoutingId, generation] of this.selectedRoutes) {
|
|
778
968
|
if (observed.get(nodeRoutingId) === generation)
|
|
779
969
|
continue;
|
|
970
|
+
this.controlSends.delete(controlSendKey(nodeRoutingId, service_wire_m6a_codec_1.M6aServiceWireCommand.hello));
|
|
780
971
|
changes++;
|
|
781
|
-
const expected = this.expectedPeers.get(nodeRoutingId);
|
|
782
|
-
if (expected !== undefined)
|
|
783
|
-
delete expected.helloSubmittedGeneration;
|
|
784
972
|
const peer = this.topology.peer(nodeRoutingId);
|
|
785
973
|
if (peer?.liveness?.connectionId === generation) {
|
|
786
974
|
this.removePeer(peer);
|
|
@@ -795,9 +983,12 @@ class RawServiceMeshRuntime {
|
|
|
795
983
|
selected.push(nodeRoutingId);
|
|
796
984
|
}
|
|
797
985
|
this.selectedRoutes = observed;
|
|
986
|
+
for (const nodeRoutingId of selected)
|
|
987
|
+
this.notifyPeerRouteChanged(nodeRoutingId);
|
|
798
988
|
// A new selected route admits only through a new handshake.
|
|
799
989
|
for (const nodeRoutingId of selected)
|
|
800
990
|
await this.announcePeer(nodeRoutingId);
|
|
991
|
+
this.refreshAdmissionPending(performance.now());
|
|
801
992
|
return changes;
|
|
802
993
|
}
|
|
803
994
|
close() {
|
|
@@ -806,9 +997,11 @@ class RawServiceMeshRuntime {
|
|
|
806
997
|
this.closed = true;
|
|
807
998
|
this.applicationJobStop.abort(new Error('Raw service runtime application job admission stopped.'));
|
|
808
999
|
this.receivePermit?.releaseAfterInternalProcessing();
|
|
1000
|
+
this.receivePermit?.releaseStorage?.();
|
|
809
1001
|
this.receivePermit = undefined;
|
|
810
1002
|
for (const send of this.controlSends.values())
|
|
811
1003
|
delete send.next;
|
|
1004
|
+
this.controlSends.clear();
|
|
812
1005
|
this.mailbox.close();
|
|
813
1006
|
this.operations.close('Raw service runtime closed.');
|
|
814
1007
|
this.serviceIngress = undefined;
|
|
@@ -822,13 +1015,12 @@ class RawServiceMeshRuntime {
|
|
|
822
1015
|
this.router = undefined;
|
|
823
1016
|
this.host = undefined;
|
|
824
1017
|
}
|
|
825
|
-
requestToTarget(targetNodeRoutingId, payload, timeoutMs, channelName) {
|
|
1018
|
+
requestToTarget(targetNodeRoutingId, payload, timeoutMs, channelName, onAdmitted, observer, operationKind) {
|
|
826
1019
|
const correlation = this.nextCorrelation++;
|
|
827
1020
|
const header = channelName === undefined
|
|
828
1021
|
? (0, service_wire_m6a_codec_1.encodeNodeRequestHeader)(correlation)
|
|
829
1022
|
: (0, service_wire_m6a_codec_1.encodeChannelRequestHeader)(correlation, channelName);
|
|
830
1023
|
const encodedPayload = this.applicationFrame(payload);
|
|
831
|
-
const pending = this.operations.register(timeoutMs);
|
|
832
1024
|
let selectedTargetNodeRoutingId = targetNodeRoutingId;
|
|
833
1025
|
if (selectedTargetNodeRoutingId !== this.descriptor.nodeRoutingId &&
|
|
834
1026
|
!this.isPeerRouteReady(selectedTargetNodeRoutingId)) {
|
|
@@ -855,6 +1047,9 @@ class RawServiceMeshRuntime {
|
|
|
855
1047
|
}
|
|
856
1048
|
}
|
|
857
1049
|
if (selectedTargetNodeRoutingId === this.descriptor.nodeRoutingId) {
|
|
1050
|
+
// The local admission path aborts its capacity wait on the terminal
|
|
1051
|
+
// Promise, so a local request always keeps the Promise entry.
|
|
1052
|
+
const pending = this.operations.register(timeoutMs);
|
|
858
1053
|
const parts = [header, encodedPayload];
|
|
859
1054
|
const capacityStop = new AbortController();
|
|
860
1055
|
void pending.promise.finally(() => capacityStop.abort()).catch(() => undefined);
|
|
@@ -888,6 +1083,9 @@ class RawServiceMeshRuntime {
|
|
|
888
1083
|
failureCode: 0
|
|
889
1084
|
});
|
|
890
1085
|
}
|
|
1086
|
+
else {
|
|
1087
|
+
onAdmitted?.();
|
|
1088
|
+
}
|
|
891
1089
|
}
|
|
892
1090
|
finally {
|
|
893
1091
|
applicationJobOwner.close();
|
|
@@ -895,12 +1093,13 @@ class RawServiceMeshRuntime {
|
|
|
895
1093
|
})().catch((error) => this.operations.fail(pending.id, error));
|
|
896
1094
|
return pending;
|
|
897
1095
|
}
|
|
898
|
-
const
|
|
1096
|
+
const pending = this.registerRequest(timeoutMs, observer, operationKind);
|
|
1097
|
+
const selectedPeer = this.topology.admittedPeer(selectedTargetNodeRoutingId);
|
|
899
1098
|
if (selectedPeer === undefined) {
|
|
900
1099
|
// Logical target selection is the requester's decision: an RID that is
|
|
901
1100
|
// not an admitted peer is not a target. Whether an admitted target's
|
|
902
1101
|
// route can carry the request is Core's REQUEST result.
|
|
903
|
-
this.
|
|
1102
|
+
this.completeRequest(pending, {
|
|
904
1103
|
terminalResult: runtime_values_1.RequestResult.NotFound,
|
|
905
1104
|
failureCode: REQUEST_TARGET_NOT_FOUND_FAILURE_CODE
|
|
906
1105
|
});
|
|
@@ -909,10 +1108,10 @@ class RawServiceMeshRuntime {
|
|
|
909
1108
|
const parts = [header, encodedPayload];
|
|
910
1109
|
let request;
|
|
911
1110
|
try {
|
|
912
|
-
request = this.requireStarted().request(selectedTargetNodeRoutingId, parts, timeoutMs, selectedPeer.liveness?.recordReceived);
|
|
1111
|
+
request = this.requireStarted().request(selectedTargetNodeRoutingId, parts, timeoutMs, selectedPeer.liveness?.recordReceived, onAdmitted);
|
|
913
1112
|
}
|
|
914
1113
|
catch (error) {
|
|
915
|
-
this.
|
|
1114
|
+
this.failRequest(pending, error);
|
|
916
1115
|
return pending;
|
|
917
1116
|
}
|
|
918
1117
|
void request.then((replyParts) => {
|
|
@@ -958,24 +1157,22 @@ class RawServiceMeshRuntime {
|
|
|
958
1157
|
applicationPayload(payload) {
|
|
959
1158
|
return Buffer.isBuffer(payload) ? (0, service_wire_m6a_codec_1.decodeApplicationPayloadView)(payload) : payload;
|
|
960
1159
|
}
|
|
961
|
-
admitPeer(descriptor, connectionId, nowMs, expected) {
|
|
1160
|
+
admitPeer(descriptor, connectionId, nowMs, expected, command = service_wire_m6a_codec_1.M6aServiceWireCommand.hello, descriptorBytes) {
|
|
962
1161
|
const previous = this.topology.peer(descriptor.nodeRoutingId);
|
|
963
|
-
|
|
964
|
-
previous.descriptor.lifecycleGeneration === descriptor.lifecycleGeneration &&
|
|
965
|
-
(descriptor.descriptorRevision < previous.descriptor.descriptorRevision ||
|
|
966
|
-
(descriptor.descriptorRevision === previous.descriptor.descriptorRevision &&
|
|
967
|
-
!(0, service_topology_registry_1.sameServiceNodeDescriptor)(previous.descriptor, descriptor)))) {
|
|
968
|
-
throw new service_wire_m6a_codec_1.ServiceWireProtocolError(`RouteMesh peer '${descriptor.nodeRoutingId}' descriptor revision is stale or conflicting.`);
|
|
969
|
-
}
|
|
970
|
-
const topologyConnectionId = typeof connectionId === 'bigint' ? `route:${connectionId}` : connectionId;
|
|
1162
|
+
const topologyConnectionId = typeof connectionId === 'bigint' ? routeConnectionId(connectionId) : connectionId;
|
|
971
1163
|
const result = this.topology.admit(descriptor, topologyConnectionId, expected, () => {
|
|
972
1164
|
const admission = this.liveness.admit(descriptor.nodeRoutingId, connectionId, nowMs);
|
|
973
1165
|
this.liveness.recordReceived(admission, nowMs);
|
|
974
1166
|
return admission;
|
|
975
|
-
});
|
|
1167
|
+
}, command, descriptorBytes);
|
|
1168
|
+
if (result === 'staleDescriptor') {
|
|
1169
|
+
throw new service_wire_m6a_codec_1.ServiceWireProtocolError(`RouteMesh peer '${descriptor.nodeRoutingId}' descriptor revision is stale or conflicting.`);
|
|
1170
|
+
}
|
|
976
1171
|
if (result === 'notRequired' && previous !== undefined) {
|
|
977
1172
|
this.liveness.disconnect(descriptor.nodeRoutingId, previous.liveness?.connectionId ?? previous.connectionId);
|
|
978
1173
|
}
|
|
1174
|
+
if (result === 'admitted')
|
|
1175
|
+
this.notifyPeerRouteChanged(descriptor.nodeRoutingId);
|
|
979
1176
|
return result;
|
|
980
1177
|
}
|
|
981
1178
|
retireNotRequiredExpectedPeer(nodeRoutingId, advertisedEndpoint) {
|
|
@@ -1020,7 +1217,7 @@ class RawServiceMeshRuntime {
|
|
|
1020
1217
|
async sendControl(targetNodeRoutingId, parts) {
|
|
1021
1218
|
return this.startControlSend(targetNodeRoutingId, (0, service_wire_m6a_codec_1.decodeHeader)(parts[0]).command, () => this.submitControl(targetNodeRoutingId, parts));
|
|
1022
1219
|
}
|
|
1023
|
-
submitControl(target, parts
|
|
1220
|
+
submitControl(target, parts) {
|
|
1024
1221
|
let submission;
|
|
1025
1222
|
try {
|
|
1026
1223
|
submission = this.requireStarted().submitSend(target, parts);
|
|
@@ -1028,19 +1225,17 @@ class RawServiceMeshRuntime {
|
|
|
1028
1225
|
catch (error) {
|
|
1029
1226
|
return this.sendFailure(error);
|
|
1030
1227
|
}
|
|
1031
|
-
if (submission.result === runtime_values_1.SubmitResult.Ok)
|
|
1032
|
-
accepted?.();
|
|
1033
|
-
return true;
|
|
1034
|
-
}
|
|
1035
|
-
return submission.admitted.then(() => {
|
|
1036
|
-
accepted?.();
|
|
1228
|
+
if (submission.result === runtime_values_1.SubmitResult.Ok)
|
|
1037
1229
|
return true;
|
|
1038
|
-
|
|
1230
|
+
return submission.admitted.then(() => true, (error) => this.sendFailure(error));
|
|
1039
1231
|
}
|
|
1040
|
-
startControlSend(target, command, attempt, current) {
|
|
1041
|
-
const key =
|
|
1232
|
+
startControlSend(target, command, attempt, current, hello) {
|
|
1233
|
+
const key = controlSendKey(target, command);
|
|
1234
|
+
if (command === service_wire_m6a_codec_1.M6aServiceWireCommand.hello)
|
|
1235
|
+
this.liveness.setAdmissionPending(true, performance.now());
|
|
1042
1236
|
const existing = this.controlSends.get(key);
|
|
1043
1237
|
if (existing !== undefined &&
|
|
1238
|
+
existing.task !== undefined &&
|
|
1044
1239
|
(command !== service_wire_m6a_codec_1.M6aServiceWireCommand.hello || existing.current?.() === true)) {
|
|
1045
1240
|
if (command !== service_wire_m6a_codec_1.M6aServiceWireCommand.hello) {
|
|
1046
1241
|
existing.next = attempt;
|
|
@@ -1049,35 +1244,45 @@ class RawServiceMeshRuntime {
|
|
|
1049
1244
|
return true;
|
|
1050
1245
|
}
|
|
1051
1246
|
const first = attempt();
|
|
1052
|
-
if (typeof first === 'boolean')
|
|
1247
|
+
if (typeof first === 'boolean') {
|
|
1248
|
+
if (hello !== undefined)
|
|
1249
|
+
this.controlSends.set(key, { current, hello });
|
|
1053
1250
|
return first;
|
|
1251
|
+
}
|
|
1054
1252
|
const owner = this;
|
|
1055
|
-
const state = {
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
if (owner.controlSends.get(key) === state)
|
|
1064
|
-
owner.controlSends.delete(key);
|
|
1065
|
-
return accepted;
|
|
1066
|
-
})
|
|
1253
|
+
const state = { current, hello };
|
|
1254
|
+
const completeSend = () => {
|
|
1255
|
+
if (owner.controlSends.get(key) !== state)
|
|
1256
|
+
return;
|
|
1257
|
+
if (hello !== undefined && current?.() === true)
|
|
1258
|
+
delete state.task;
|
|
1259
|
+
else
|
|
1260
|
+
owner.controlSends.delete(key);
|
|
1067
1261
|
};
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1262
|
+
const task = first.then(function drain(accepted) {
|
|
1263
|
+
if (!owner.closed && state.next !== undefined) {
|
|
1264
|
+
const next = state.next;
|
|
1265
|
+
delete state.next;
|
|
1266
|
+
return Promise.resolve(next()).then(drain);
|
|
1267
|
+
}
|
|
1268
|
+
completeSend();
|
|
1269
|
+
return accepted;
|
|
1074
1270
|
});
|
|
1075
|
-
|
|
1076
|
-
|
|
1271
|
+
state.task = task;
|
|
1272
|
+
this.controlSends.set(key, state);
|
|
1273
|
+
task.then(() => { }, (error) => {
|
|
1274
|
+
completeSend();
|
|
1275
|
+
this.reportInfrastructureFailure(error);
|
|
1077
1276
|
});
|
|
1078
1277
|
return true;
|
|
1079
1278
|
}
|
|
1080
1279
|
reportInfrastructureFailure(error) {
|
|
1280
|
+
if (this.infrastructureTaskRunner !== undefined) {
|
|
1281
|
+
this.infrastructureTaskRunner.runDetached('RouteMesh infrastructure', async () => {
|
|
1282
|
+
throw error;
|
|
1283
|
+
});
|
|
1284
|
+
return;
|
|
1285
|
+
}
|
|
1081
1286
|
this.infrastructureFailure = {
|
|
1082
1287
|
error: this.infrastructureFailure === undefined
|
|
1083
1288
|
? error
|
|
@@ -1092,13 +1297,15 @@ class RawServiceMeshRuntime {
|
|
|
1092
1297
|
throw failure.error;
|
|
1093
1298
|
}
|
|
1094
1299
|
send(targetNodeRoutingId, parts) {
|
|
1095
|
-
|
|
1096
|
-
.
|
|
1097
|
-
.
|
|
1098
|
-
|
|
1099
|
-
|
|
1300
|
+
try {
|
|
1301
|
+
const submission = this.requireStarted().submitSend(targetNodeRoutingId, parts);
|
|
1302
|
+
if (submission.result === runtime_values_1.SubmitResult.Ok)
|
|
1303
|
+
return true;
|
|
1304
|
+
return submission.admitted.then(() => true, (error) => this.sendFailure(error));
|
|
1305
|
+
}
|
|
1306
|
+
catch (error) {
|
|
1100
1307
|
return this.sendFailure(error);
|
|
1101
|
-
}
|
|
1308
|
+
}
|
|
1102
1309
|
}
|
|
1103
1310
|
sendFailure(error) {
|
|
1104
1311
|
if ((0, runtime_values_1.isZLinkBackendResultError)(error) && error.operation === 'submit') {
|
|
@@ -1110,25 +1317,38 @@ class RawServiceMeshRuntime {
|
|
|
1110
1317
|
}
|
|
1111
1318
|
}
|
|
1112
1319
|
exports.RawServiceMeshRuntime = RawServiceMeshRuntime;
|
|
1320
|
+
function controlSendKey(target, command) {
|
|
1321
|
+
return `${command}:${target}`;
|
|
1322
|
+
}
|
|
1323
|
+
function routeConnectionId(generation) {
|
|
1324
|
+
return `route:${generation}`;
|
|
1325
|
+
}
|
|
1113
1326
|
/**
|
|
1114
1327
|
* Relocation and bound-Session controls are service-wire records themselves,
|
|
1115
1328
|
* not application NodeSend(16) envelopes. Keep this list closed: a bare
|
|
1116
1329
|
* record outside the frozen control vocabulary remains a protocol error.
|
|
1117
1330
|
*/
|
|
1331
|
+
const BARE_INFRASTRUCTURE_CONTROLS = new Set([
|
|
1332
|
+
service_wire_constants_generated_1.ServiceWireCommand.relocationReady,
|
|
1333
|
+
service_wire_constants_generated_1.ServiceWireCommand.relocationData,
|
|
1334
|
+
service_wire_constants_generated_1.ServiceWireCommand.replyRelay,
|
|
1335
|
+
service_wire_constants_generated_1.ServiceWireCommand.relocationCutover,
|
|
1336
|
+
service_wire_constants_generated_1.ServiceWireCommand.relocationPrepare,
|
|
1337
|
+
service_wire_constants_generated_1.ServiceWireCommand.sessionRelocationSeal,
|
|
1338
|
+
service_wire_constants_generated_1.ServiceWireCommand.sessionRelocationSealed,
|
|
1339
|
+
service_wire_constants_generated_1.ServiceWireCommand.sessionRelocationRoute,
|
|
1340
|
+
service_wire_constants_generated_1.ServiceWireCommand.replyRelayAck,
|
|
1341
|
+
service_wire_constants_generated_1.ServiceWireCommand.relocationState,
|
|
1342
|
+
service_wire_constants_generated_1.ServiceWireCommand.relocationFailed
|
|
1343
|
+
]);
|
|
1118
1344
|
function isBareInfrastructureControl(command) {
|
|
1119
|
-
return
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
service_wire_constants_generated_1.ServiceWireCommand.sessionRelocationSealed,
|
|
1127
|
-
service_wire_constants_generated_1.ServiceWireCommand.sessionRelocationRoute,
|
|
1128
|
-
service_wire_constants_generated_1.ServiceWireCommand.replyRelayAck,
|
|
1129
|
-
service_wire_constants_generated_1.ServiceWireCommand.relocationState,
|
|
1130
|
-
service_wire_constants_generated_1.ServiceWireCommand.relocationFailed
|
|
1131
|
-
].includes(command);
|
|
1345
|
+
return BARE_INFRASTRUCTURE_CONTROLS.has(command);
|
|
1346
|
+
}
|
|
1347
|
+
function isApplicationEnvelopeCommand(command) {
|
|
1348
|
+
return (command === service_wire_m6a_codec_1.M6aServiceWireCommand.nodeSend ||
|
|
1349
|
+
command === service_wire_m6a_codec_1.M6aServiceWireCommand.nodeRequest ||
|
|
1350
|
+
command === service_wire_m6a_codec_1.M6aServiceWireCommand.channelSend ||
|
|
1351
|
+
command === service_wire_m6a_codec_1.M6aServiceWireCommand.channelRequest);
|
|
1132
1352
|
}
|
|
1133
1353
|
function protocolCommand(parts) {
|
|
1134
1354
|
if (parts.length === 0)
|