@zlink-systems/framework 0.10.0
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 +105 -0
- package/dist/.tsbuildinfo +1 -0
- package/dist/contracts/Actors/ZLinkActor.d.ts +7 -0
- package/dist/contracts/Actors/ZLinkActor.js +2 -0
- package/dist/contracts/Actors/ZLinkActorClient.d.ts +15 -0
- package/dist/contracts/Actors/ZLinkActorClient.js +2 -0
- package/dist/contracts/Actors/ZLinkActorContext.d.ts +14 -0
- package/dist/contracts/Actors/ZLinkActorContext.js +2 -0
- package/dist/contracts/Actors/ZLinkActorFactory.d.ts +34 -0
- package/dist/contracts/Actors/ZLinkActorFactory.js +2 -0
- package/dist/contracts/Actors/ZLinkActorManager.d.ts +34 -0
- package/dist/contracts/Actors/ZLinkActorManager.js +2 -0
- package/dist/contracts/Actors/index.d.ts +5 -0
- package/dist/contracts/Actors/index.js +21 -0
- package/dist/contracts/Channels/Calls.d.ts +28 -0
- package/dist/contracts/Channels/Calls.js +2 -0
- package/dist/contracts/Channels/IZLinkChannelClient.d.ts +5 -0
- package/dist/contracts/Channels/IZLinkChannelClient.js +2 -0
- package/dist/contracts/Channels/IZLinkFanoutClient.d.ts +11 -0
- package/dist/contracts/Channels/IZLinkFanoutClient.js +2 -0
- package/dist/contracts/Channels/RouteCalls.d.ts +11 -0
- package/dist/contracts/Channels/RouteCalls.js +2 -0
- package/dist/contracts/Channels/index.d.ts +4 -0
- package/dist/contracts/Channels/index.js +20 -0
- package/dist/contracts/Codecs/IZLinkCodecRegistryBuilder.d.ts +14 -0
- package/dist/contracts/Codecs/IZLinkCodecRegistryBuilder.js +2 -0
- package/dist/contracts/Codecs/ZLinkMessageSerializer.d.ts +5 -0
- package/dist/contracts/Codecs/ZLinkMessageSerializer.js +2 -0
- package/dist/contracts/Codecs/index.d.ts +2 -0
- package/dist/contracts/Codecs/index.js +18 -0
- package/dist/contracts/Common/ActorRef.d.ts +7 -0
- package/dist/contracts/Common/ActorRef.js +2 -0
- package/dist/contracts/Common/CoreTypes.d.ts +6 -0
- package/dist/contracts/Common/CoreTypes.js +2 -0
- package/dist/contracts/Common/Message.d.ts +9 -0
- package/dist/contracts/Common/Message.js +2 -0
- package/dist/contracts/Common/ZLinkEncodedPayload.d.ts +12 -0
- package/dist/contracts/Common/ZLinkEncodedPayload.js +41 -0
- package/dist/contracts/Common/ZLinkMessage.d.ts +25 -0
- package/dist/contracts/Common/ZLinkMessage.js +127 -0
- package/dist/contracts/Common/ZLinkMessageMetadata.d.ts +10 -0
- package/dist/contracts/Common/ZLinkMessageMetadata.js +49 -0
- package/dist/contracts/Common/ZLinkProviderResolver.d.ts +5 -0
- package/dist/contracts/Common/ZLinkProviderResolver.js +2 -0
- package/dist/contracts/Common/encoded-payload-storage.d.ts +3 -0
- package/dist/contracts/Common/encoded-payload-storage.js +18 -0
- package/dist/contracts/Common/index.d.ts +5 -0
- package/dist/contracts/Common/index.js +24 -0
- package/dist/contracts/Configuration/Builders.d.ts +153 -0
- package/dist/contracts/Configuration/Builders.js +2 -0
- package/dist/contracts/Configuration/CodecContentType.d.ts +2 -0
- package/dist/contracts/Configuration/CodecContentType.js +68 -0
- package/dist/contracts/Configuration/CodecSerializerSelection.d.ts +9 -0
- package/dist/contracts/Configuration/CodecSerializerSelection.js +15 -0
- package/dist/contracts/Configuration/Configs.d.ts +23 -0
- package/dist/contracts/Configuration/Configs.js +2 -0
- package/dist/contracts/Configuration/ConfigurationException.d.ts +3 -0
- package/dist/contracts/Configuration/ConfigurationException.js +10 -0
- package/dist/contracts/Configuration/Connections.d.ts +5 -0
- package/dist/contracts/Configuration/Connections.js +2 -0
- package/dist/contracts/Configuration/DiagnosticsValidation.d.ts +3 -0
- package/dist/contracts/Configuration/DiagnosticsValidation.js +23 -0
- package/dist/contracts/Configuration/EndpointNotation.d.ts +77 -0
- package/dist/contracts/Configuration/EndpointNotation.js +218 -0
- package/dist/contracts/Configuration/InternalDefaults.d.ts +7 -0
- package/dist/contracts/Configuration/InternalDefaults.js +47 -0
- package/dist/contracts/Configuration/ObjectRoles.d.ts +38 -0
- package/dist/contracts/Configuration/ObjectRoles.js +13 -0
- package/dist/contracts/Configuration/Registration.d.ts +11 -0
- package/dist/contracts/Configuration/Registration.js +162 -0
- package/dist/contracts/Configuration/RegistrationBuilderPolicy.d.ts +14 -0
- package/dist/contracts/Configuration/RegistrationBuilderPolicy.js +61 -0
- package/dist/contracts/Configuration/RegistrationBuilders.d.ts +61 -0
- package/dist/contracts/Configuration/RegistrationBuilders.js +1181 -0
- package/dist/contracts/Configuration/RegistrationCodecRegistry.d.ts +19 -0
- package/dist/contracts/Configuration/RegistrationCodecRegistry.js +79 -0
- package/dist/contracts/Configuration/RegistrationNormalizers.d.ts +23 -0
- package/dist/contracts/Configuration/RegistrationNormalizers.js +319 -0
- package/dist/contracts/Configuration/RegistrationTypes.d.ts +414 -0
- package/dist/contracts/Configuration/RegistrationTypes.js +2 -0
- package/dist/contracts/Configuration/RegistrationValidators.d.ts +2 -0
- package/dist/contracts/Configuration/RegistrationValidators.js +461 -0
- package/dist/contracts/Configuration/RouteChannelInternalState.d.ts +10 -0
- package/dist/contracts/Configuration/RouteChannelInternalState.js +39 -0
- package/dist/contracts/Configuration/RuntimeEndpointConnections.d.ts +9 -0
- package/dist/contracts/Configuration/RuntimeEndpointConnections.js +80 -0
- package/dist/contracts/Configuration/SendTimeoutValidation.d.ts +2 -0
- package/dist/contracts/Configuration/SendTimeoutValidation.js +16 -0
- package/dist/contracts/Configuration/TimerRegistrationValidator.d.ts +2 -0
- package/dist/contracts/Configuration/TimerRegistrationValidator.js +24 -0
- package/dist/contracts/Configuration/index.d.ts +5 -0
- package/dist/contracts/Configuration/index.js +18 -0
- package/dist/contracts/Dispatch/ZLinkDispatchOptions.d.ts +181 -0
- package/dist/contracts/Dispatch/ZLinkDispatchOptions.js +89 -0
- package/dist/contracts/Dispatch/ZLinkFlowOrigin.d.ts +1 -0
- package/dist/contracts/Dispatch/ZLinkFlowOrigin.js +2 -0
- package/dist/contracts/Dispatch/index.d.ts +2 -0
- package/dist/contracts/Dispatch/index.js +18 -0
- package/dist/contracts/Errors/ZLinkFrameworkException.d.ts +20 -0
- package/dist/contracts/Errors/ZLinkFrameworkException.js +29 -0
- package/dist/contracts/Errors/index.d.ts +1 -0
- package/dist/contracts/Errors/index.js +6 -0
- package/dist/contracts/Eventing/Metrics.d.ts +29 -0
- package/dist/contracts/Eventing/Metrics.js +4 -0
- package/dist/contracts/Eventing/index.d.ts +1 -0
- package/dist/contracts/Eventing/index.js +17 -0
- package/dist/contracts/Handlers/Attributes.d.ts +24 -0
- package/dist/contracts/Handlers/Attributes.js +84 -0
- package/dist/contracts/Handlers/Contexts.d.ts +18 -0
- package/dist/contracts/Handlers/Contexts.js +2 -0
- package/dist/contracts/Handlers/IZLinkChannelHandlers.d.ts +43 -0
- package/dist/contracts/Handlers/IZLinkChannelHandlers.js +2 -0
- package/dist/contracts/Handlers/IZLinkHandlerFilter.d.ts +15 -0
- package/dist/contracts/Handlers/IZLinkHandlerFilter.js +11 -0
- package/dist/contracts/Handlers/JsonContract.d.ts +46 -0
- package/dist/contracts/Handlers/JsonContract.js +137 -0
- package/dist/contracts/Handlers/ZLinkHandlerFilterNext.d.ts +1 -0
- package/dist/contracts/Handlers/ZLinkHandlerFilterNext.js +2 -0
- package/dist/contracts/Handlers/index.d.ts +5 -0
- package/dist/contracts/Handlers/index.js +33 -0
- package/dist/contracts/Locations/ActorTransfer.d.ts +41 -0
- package/dist/contracts/Locations/ActorTransfer.js +2 -0
- package/dist/contracts/Locations/Authority.d.ts +296 -0
- package/dist/contracts/Locations/Authority.js +17 -0
- package/dist/contracts/Locations/Diagnostics.d.ts +42 -0
- package/dist/contracts/Locations/Diagnostics.js +12 -0
- package/dist/contracts/Locations/Keys.d.ts +86 -0
- package/dist/contracts/Locations/Keys.js +2 -0
- package/dist/contracts/Locations/Models.d.ts +7 -0
- package/dist/contracts/Locations/Models.js +23 -0
- package/dist/contracts/Locations/Options.d.ts +23 -0
- package/dist/contracts/Locations/Options.js +20 -0
- package/dist/contracts/Locations/Readiness.d.ts +5 -0
- package/dist/contracts/Locations/Readiness.js +2 -0
- package/dist/contracts/Locations/RelocationStore.d.ts +38 -0
- package/dist/contracts/Locations/RelocationStore.js +2 -0
- package/dist/contracts/Locations/Resolvers.d.ts +4 -0
- package/dist/contracts/Locations/Resolvers.js +2 -0
- package/dist/contracts/Locations/Rows.d.ts +152 -0
- package/dist/contracts/Locations/Rows.js +19 -0
- package/dist/contracts/Locations/RuntimeQuery.d.ts +25 -0
- package/dist/contracts/Locations/RuntimeQuery.js +2 -0
- package/dist/contracts/Locations/Stores.d.ts +88 -0
- package/dist/contracts/Locations/Stores.js +2 -0
- package/dist/contracts/Locations/Values.d.ts +27 -0
- package/dist/contracts/Locations/Values.js +36 -0
- package/dist/contracts/Locations/Watch.d.ts +14 -0
- package/dist/contracts/Locations/Watch.js +12 -0
- package/dist/contracts/Locations/Writes.d.ts +48 -0
- package/dist/contracts/Locations/Writes.js +15 -0
- package/dist/contracts/Locations/index.d.ts +12 -0
- package/dist/contracts/Locations/index.js +30 -0
- package/dist/contracts/RouteMesh/Contracts.d.ts +102 -0
- package/dist/contracts/RouteMesh/Contracts.js +39 -0
- package/dist/contracts/RouteMesh/RuntimeTopology.d.ts +165 -0
- package/dist/contracts/RouteMesh/RuntimeTopology.js +38 -0
- package/dist/contracts/RouteMesh/index.d.ts +2 -0
- package/dist/contracts/RouteMesh/index.js +18 -0
- package/dist/contracts/Spots/Builders.d.ts +10 -0
- package/dist/contracts/Spots/Builders.js +2 -0
- package/dist/contracts/Spots/Contracts.d.ts +110 -0
- package/dist/contracts/Spots/Contracts.js +9 -0
- package/dist/contracts/Spots/SpotKind.d.ts +8 -0
- package/dist/contracts/Spots/SpotKind.js +28 -0
- package/dist/contracts/Spots/ZLinkSpot.d.ts +62 -0
- package/dist/contracts/Spots/ZLinkSpot.js +15 -0
- package/dist/contracts/Spots/index.d.ts +3 -0
- package/dist/contracts/Spots/index.js +19 -0
- package/dist/contracts/Streams/BoundSessionContracts.d.ts +8 -0
- package/dist/contracts/Streams/BoundSessionContracts.js +2 -0
- package/dist/contracts/Streams/IZLinkSession.d.ts +44 -0
- package/dist/contracts/Streams/IZLinkSession.js +2 -0
- package/dist/contracts/Streams/IZLinkSessionActor.d.ts +15 -0
- package/dist/contracts/Streams/IZLinkSessionActor.js +2 -0
- package/dist/contracts/Streams/IZLinkSessionPacketHandler.d.ts +9 -0
- package/dist/contracts/Streams/IZLinkSessionPacketHandler.js +2 -0
- package/dist/contracts/Streams/IZLinkStream.d.ts +9 -0
- package/dist/contracts/Streams/IZLinkStream.js +2 -0
- package/dist/contracts/Streams/ZLinkMessageMetadata.d.ts +1 -0
- package/dist/contracts/Streams/ZLinkMessageMetadata.js +2 -0
- package/dist/contracts/Streams/ZLinkStreamCompression.d.ts +8 -0
- package/dist/contracts/Streams/ZLinkStreamCompression.js +2 -0
- package/dist/contracts/Streams/ZLinkStreamError.d.ts +8 -0
- package/dist/contracts/Streams/ZLinkStreamError.js +8 -0
- package/dist/contracts/Streams/index.d.ts +8 -0
- package/dist/contracts/Streams/index.js +24 -0
- package/dist/contracts/Timers/IZLinkTimer.d.ts +5 -0
- package/dist/contracts/Timers/IZLinkTimer.js +2 -0
- package/dist/contracts/Timers/ZLinkTimerOptions.d.ts +10 -0
- package/dist/contracts/Timers/ZLinkTimerOptions.js +9 -0
- package/dist/contracts/Timers/ZLinkTimerTick.d.ts +12 -0
- package/dist/contracts/Timers/ZLinkTimerTick.js +2 -0
- package/dist/contracts/Timers/index.d.ts +3 -0
- package/dist/contracts/Timers/index.js +19 -0
- package/dist/contracts/index.d.ts +25 -0
- package/dist/contracts/index.js +45 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +17 -0
- package/dist/internal.d.ts +26 -0
- package/dist/internal.js +48 -0
- package/dist/location-store-integration.d.ts +5 -0
- package/dist/location-store-integration.js +31 -0
- package/dist/nest-integration.d.ts +49 -0
- package/dist/nest-integration.js +143 -0
- package/dist/runtime/abort.d.ts +13 -0
- package/dist/runtime/abort.js +71 -0
- package/dist/runtime/actors/actor-authority-payload-codec.d.ts +33 -0
- package/dist/runtime/actors/actor-authority-payload-codec.js +366 -0
- package/dist/runtime/actors/actor-authority-publication.d.ts +28 -0
- package/dist/runtime/actors/actor-authority-publication.js +207 -0
- package/dist/runtime/actors/actor-client.d.ts +36 -0
- package/dist/runtime/actors/actor-client.js +612 -0
- package/dist/runtime/actors/actor-context.d.ts +26 -0
- package/dist/runtime/actors/actor-context.js +433 -0
- package/dist/runtime/actors/actor-creation.d.ts +19 -0
- package/dist/runtime/actors/actor-creation.js +158 -0
- package/dist/runtime/actors/actor-execution-context.d.ts +6 -0
- package/dist/runtime/actors/actor-execution-context.js +27 -0
- package/dist/runtime/actors/actor-handoff.d.ts +191 -0
- package/dist/runtime/actors/actor-handoff.js +1252 -0
- package/dist/runtime/actors/actor-join-deferred-scope.d.ts +11 -0
- package/dist/runtime/actors/actor-join-deferred-scope.js +144 -0
- package/dist/runtime/actors/actor-join-relocation.d.ts +38 -0
- package/dist/runtime/actors/actor-join-relocation.js +2 -0
- package/dist/runtime/actors/actor-lifecycle-snapshot.d.ts +21 -0
- package/dist/runtime/actors/actor-lifecycle-snapshot.js +58 -0
- package/dist/runtime/actors/actor-local-native-join.d.ts +27 -0
- package/dist/runtime/actors/actor-local-native-join.js +409 -0
- package/dist/runtime/actors/actor-mailbox.d.ts +10 -0
- package/dist/runtime/actors/actor-mailbox.js +53 -0
- package/dist/runtime/actors/actor-message-follow-context.d.ts +46 -0
- package/dist/runtime/actors/actor-message-follow-context.js +257 -0
- package/dist/runtime/actors/actor-native-lookup.d.ts +4 -0
- package/dist/runtime/actors/actor-native-lookup.js +30 -0
- package/dist/runtime/actors/actor-packet-relay-wire.d.ts +73 -0
- package/dist/runtime/actors/actor-packet-relay-wire.js +144 -0
- package/dist/runtime/actors/actor-remote-joiner.d.ts +37 -0
- package/dist/runtime/actors/actor-remote-joiner.js +122 -0
- package/dist/runtime/actors/actor-remote-wire.d.ts +73 -0
- package/dist/runtime/actors/actor-remote-wire.js +84 -0
- package/dist/runtime/actors/actor-retry-delay.d.ts +5 -0
- package/dist/runtime/actors/actor-retry-delay.js +40 -0
- package/dist/runtime/actors/actor-routed-join-transport.d.ts +33 -0
- package/dist/runtime/actors/actor-routed-join-transport.js +2 -0
- package/dist/runtime/actors/actor-routed-json-request.d.ts +11 -0
- package/dist/runtime/actors/actor-routed-json-request.js +39 -0
- package/dist/runtime/actors/actor-runtime-contracts.d.ts +63 -0
- package/dist/runtime/actors/actor-runtime-contracts.js +2 -0
- package/dist/runtime/actors/actor-runtime-state.d.ts +152 -0
- package/dist/runtime/actors/actor-runtime-state.js +545 -0
- package/dist/runtime/actors/actor-source-transfer.d.ts +27 -0
- package/dist/runtime/actors/actor-source-transfer.js +2 -0
- package/dist/runtime/actors/actor-transfer-registry.d.ts +18 -0
- package/dist/runtime/actors/actor-transfer-registry.js +71 -0
- package/dist/runtime/actors/actor-transport-delivery-gate.d.ts +6 -0
- package/dist/runtime/actors/actor-transport-delivery-gate.js +4 -0
- package/dist/runtime/actors/bound-session-wire.d.ts +81 -0
- package/dist/runtime/actors/bound-session-wire.js +184 -0
- package/dist/runtime/actors/deferred-join-accepted-journal.d.ts +47 -0
- package/dist/runtime/actors/deferred-join-accepted-journal.js +962 -0
- package/dist/runtime/actors/index.d.ts +79 -0
- package/dist/runtime/actors/index.js +639 -0
- package/dist/runtime/actors/post-commit-actor-binder.d.ts +18 -0
- package/dist/runtime/actors/post-commit-actor-binder.js +68 -0
- package/dist/runtime/actors/post-commit-actor-location.d.ts +19 -0
- package/dist/runtime/actors/post-commit-actor-location.js +72 -0
- package/dist/runtime/actors/spot-actor-dispatch.d.ts +59 -0
- package/dist/runtime/actors/spot-actor-dispatch.js +179 -0
- package/dist/runtime/actors/transferred-actor-rollback.d.ts +16 -0
- package/dist/runtime/actors/transferred-actor-rollback.js +91 -0
- package/dist/runtime/admission.d.ts +20 -0
- package/dist/runtime/admission.js +166 -0
- package/dist/runtime/application-jobs/application-ingress-record-owner.d.ts +57 -0
- package/dist/runtime/application-jobs/application-ingress-record-owner.js +185 -0
- package/dist/runtime/application-jobs/application-job-queue-handler-start-gate.d.ts +8 -0
- package/dist/runtime/application-jobs/application-job-queue-handler-start-gate.js +8 -0
- package/dist/runtime/application-jobs/application-job-queue-scope.d.ts +17 -0
- package/dist/runtime/application-jobs/application-job-queue-scope.js +57 -0
- package/dist/runtime/application-jobs/contracts.d.ts +19 -0
- package/dist/runtime/application-jobs/contracts.js +2 -0
- package/dist/runtime/application-jobs/receive-flow-controller.d.ts +32 -0
- package/dist/runtime/application-jobs/receive-flow-controller.js +165 -0
- package/dist/runtime/backend/contracts/index.d.ts +487 -0
- package/dist/runtime/backend/contracts/index.js +29 -0
- package/dist/runtime/backend/index.d.ts +9 -0
- package/dist/runtime/backend/index.js +25 -0
- package/dist/runtime/backend/mesh-actor-session-node-adapter.d.ts +3 -0
- package/dist/runtime/backend/mesh-actor-session-node-adapter.js +51 -0
- package/dist/runtime/backend/mesh-completion-table.d.ts +34 -0
- package/dist/runtime/backend/mesh-completion-table.js +124 -0
- package/dist/runtime/backend/mesh-dispatch-pump.d.ts +48 -0
- package/dist/runtime/backend/mesh-dispatch-pump.js +322 -0
- package/dist/runtime/backend/mesh-record-dispatcher.d.ts +19 -0
- package/dist/runtime/backend/mesh-record-dispatcher.js +53 -0
- package/dist/runtime/backend/node/index.d.ts +4 -0
- package/dist/runtime/backend/node/index.js +22 -0
- package/dist/runtime/backend/node/node-backend-adapter-factory.d.ts +12 -0
- package/dist/runtime/backend/node/node-backend-adapter-factory.js +161 -0
- package/dist/runtime/backend/node/node-backend-adapter-support.d.ts +52 -0
- package/dist/runtime/backend/node/node-backend-adapter-support.js +203 -0
- package/dist/runtime/backend/node/node-dealer-channel-client-transport.d.ts +13 -0
- package/dist/runtime/backend/node/node-dealer-channel-client-transport.js +52 -0
- package/dist/runtime/backend/node/node-mesh-backend-adapter.d.ts +11 -0
- package/dist/runtime/backend/node/node-mesh-backend-adapter.js +23 -0
- package/dist/runtime/backend/node/node-monitor-backend-adapter.d.ts +6 -0
- package/dist/runtime/backend/node/node-monitor-backend-adapter.js +38 -0
- package/dist/runtime/backend/node/node-raw-binding-port.d.ts +8 -0
- package/dist/runtime/backend/node/node-raw-binding-port.js +411 -0
- package/dist/runtime/backend/node/node-raw-mesh-backend.d.ts +266 -0
- package/dist/runtime/backend/node/node-raw-mesh-backend.js +1707 -0
- package/dist/runtime/backend/node/node-socket-backend-adapter.d.ts +9 -0
- package/dist/runtime/backend/node/node-socket-backend-adapter.js +286 -0
- package/dist/runtime/backend/node-backend-adapter.d.ts +9 -0
- package/dist/runtime/backend/node-backend-adapter.js +12 -0
- package/dist/runtime/backend/raw-binding-port.d.ts +58 -0
- package/dist/runtime/backend/raw-binding-port.js +2 -0
- package/dist/runtime/backend/runtime-message.d.ts +14 -0
- package/dist/runtime/backend/runtime-message.js +44 -0
- package/dist/runtime/backend/runtime-values.d.ts +78 -0
- package/dist/runtime/backend/runtime-values.js +66 -0
- package/dist/runtime/channels/channel-autoconnect.d.ts +14 -0
- package/dist/runtime/channels/channel-autoconnect.js +23 -0
- package/dist/runtime/channels/channel-clients.d.ts +50 -0
- package/dist/runtime/channels/channel-clients.js +329 -0
- package/dist/runtime/channels/channel-dispatch-pipeline.d.ts +76 -0
- package/dist/runtime/channels/channel-dispatch-pipeline.js +237 -0
- package/dist/runtime/channels/channel-dispatch-services.d.ts +52 -0
- package/dist/runtime/channels/channel-dispatch-services.js +132 -0
- package/dist/runtime/channels/channel-dispatchers.d.ts +125 -0
- package/dist/runtime/channels/channel-dispatchers.js +575 -0
- package/dist/runtime/channels/channel-envelope-inspection.d.ts +25 -0
- package/dist/runtime/channels/channel-envelope-inspection.js +96 -0
- package/dist/runtime/channels/channel-envelope.d.ts +73 -0
- package/dist/runtime/channels/channel-envelope.js +546 -0
- package/dist/runtime/channels/channel-framework-packets.d.ts +2 -0
- package/dist/runtime/channels/channel-framework-packets.js +6 -0
- package/dist/runtime/channels/channel-multipart.d.ts +16 -0
- package/dist/runtime/channels/channel-multipart.js +31 -0
- package/dist/runtime/channels/channel-outbound-operations.d.ts +33 -0
- package/dist/runtime/channels/channel-outbound-operations.js +343 -0
- package/dist/runtime/channels/channel-receive-loops.d.ts +151 -0
- package/dist/runtime/channels/channel-receive-loops.js +728 -0
- package/dist/runtime/channels/channel-receive-task-tracker.d.ts +14 -0
- package/dist/runtime/channels/channel-receive-task-tracker.js +37 -0
- package/dist/runtime/channels/channel-runtime-lifecycle.d.ts +77 -0
- package/dist/runtime/channels/channel-runtime-lifecycle.js +630 -0
- package/dist/runtime/channels/channel-runtime-manager.d.ts +84 -0
- package/dist/runtime/channels/channel-runtime-manager.js +193 -0
- package/dist/runtime/channels/channel-socket-options.d.ts +18 -0
- package/dist/runtime/channels/channel-socket-options.js +119 -0
- package/dist/runtime/channels/channel-socket-registry.d.ts +157 -0
- package/dist/runtime/channels/channel-socket-registry.js +1428 -0
- package/dist/runtime/channels/channel-transports.d.ts +126 -0
- package/dist/runtime/channels/channel-transports.js +448 -0
- package/dist/runtime/channels/client-server-location-runtime.d.ts +41 -0
- package/dist/runtime/channels/client-server-location-runtime.js +465 -0
- package/dist/runtime/channels/client-server-service-wire.d.ts +48 -0
- package/dist/runtime/channels/client-server-service-wire.js +306 -0
- package/dist/runtime/channels/dispatch-error-reporter.d.ts +22 -0
- package/dist/runtime/channels/dispatch-error-reporter.js +133 -0
- package/dist/runtime/channels/fanout-location-runtime.d.ts +38 -0
- package/dist/runtime/channels/fanout-location-runtime.js +356 -0
- package/dist/runtime/channels/fanout-service-wire.d.ts +12 -0
- package/dist/runtime/channels/fanout-service-wire.js +29 -0
- package/dist/runtime/channels/handler-filter-scope.d.ts +8 -0
- package/dist/runtime/channels/handler-filter-scope.js +11 -0
- package/dist/runtime/channels/index.d.ts +9 -0
- package/dist/runtime/channels/index.js +30 -0
- package/dist/runtime/channels/local-spot-route-transport.d.ts +9 -0
- package/dist/runtime/channels/local-spot-route-transport.js +40 -0
- package/dist/runtime/channels/route-disconnected-error.d.ts +3 -0
- package/dist/runtime/channels/route-disconnected-error.js +10 -0
- package/dist/runtime/channels/route-member-snapshot.d.ts +10 -0
- package/dist/runtime/channels/route-member-snapshot.js +55 -0
- package/dist/runtime/channels/router-socket-spot-route-transport.d.ts +12 -0
- package/dist/runtime/channels/router-socket-spot-route-transport.js +43 -0
- package/dist/runtime/channels/source-spot-router.d.ts +10 -0
- package/dist/runtime/channels/source-spot-router.js +46 -0
- package/dist/runtime/channels/spot-direct-envelope.d.ts +5 -0
- package/dist/runtime/channels/spot-direct-envelope.js +29 -0
- package/dist/runtime/channels/spot-node-route-transport.d.ts +13 -0
- package/dist/runtime/channels/spot-node-route-transport.js +60 -0
- package/dist/runtime/channels/spot-route-bridge-transport.d.ts +14 -0
- package/dist/runtime/channels/spot-route-bridge-transport.js +58 -0
- package/dist/runtime/channels/spot-route-dispatch-strategy.d.ts +50 -0
- package/dist/runtime/channels/spot-route-dispatch-strategy.js +128 -0
- package/dist/runtime/channels/spot-route-target-resolver.d.ts +16 -0
- package/dist/runtime/channels/spot-route-target-resolver.js +92 -0
- package/dist/runtime/codecs/index.d.ts +14 -0
- package/dist/runtime/codecs/index.js +44 -0
- package/dist/runtime/configuration/index.d.ts +1 -0
- package/dist/runtime/configuration/index.js +17 -0
- package/dist/runtime/diagnostics/dispatch-error-port.d.ts +8 -0
- package/dist/runtime/diagnostics/dispatch-error-port.js +2 -0
- package/dist/runtime/diagnostics/flow-context.d.ts +21 -0
- package/dist/runtime/diagnostics/flow-context.js +68 -0
- package/dist/runtime/diagnostics/index.d.ts +82 -0
- package/dist/runtime/diagnostics/index.js +335 -0
- package/dist/runtime/diagnostics/internal-event-contracts.d.ts +139 -0
- package/dist/runtime/diagnostics/internal-event-contracts.js +68 -0
- package/dist/runtime/diagnostics/message-flow.d.ts +55 -0
- package/dist/runtime/diagnostics/message-flow.js +420 -0
- package/dist/runtime/diagnostics/runtime-metrics.d.ts +123 -0
- package/dist/runtime/diagnostics/runtime-metrics.js +454 -0
- package/dist/runtime/diagnostics/runtime-observation-queue.d.ts +58 -0
- package/dist/runtime/diagnostics/runtime-observation-queue.js +324 -0
- package/dist/runtime/diagnostics/topology-runtime-projections.d.ts +33 -0
- package/dist/runtime/diagnostics/topology-runtime-projections.js +255 -0
- package/dist/runtime/execution/index.d.ts +114 -0
- package/dist/runtime/execution/index.js +363 -0
- package/dist/runtime/execution/serial-execution-queue.d.ts +94 -0
- package/dist/runtime/execution/serial-execution-queue.js +411 -0
- package/dist/runtime/execution/serial-work-size.d.ts +4 -0
- package/dist/runtime/execution/serial-work-size.js +28 -0
- package/dist/runtime/execution/state-lane.d.ts +28 -0
- package/dist/runtime/execution/state-lane.js +105 -0
- package/dist/runtime/foundation/actor-join-recovery-codec.d.ts +72 -0
- package/dist/runtime/foundation/actor-join-recovery-codec.js +333 -0
- package/dist/runtime/foundation/event-loop-resources.d.ts +37 -0
- package/dist/runtime/foundation/event-loop-resources.js +163 -0
- package/dist/runtime/foundation/index.d.ts +18 -0
- package/dist/runtime/foundation/index.js +34 -0
- package/dist/runtime/foundation/message-follow-suppression-registry.d.ts +38 -0
- package/dist/runtime/foundation/message-follow-suppression-registry.js +89 -0
- package/dist/runtime/foundation/operation-identity.d.ts +12 -0
- package/dist/runtime/foundation/operation-identity.js +33 -0
- package/dist/runtime/foundation/operation-registry.d.ts +42 -0
- package/dist/runtime/foundation/operation-registry.js +146 -0
- package/dist/runtime/foundation/raw-service-mesh-runtime.d.ts +143 -0
- package/dist/runtime/foundation/raw-service-mesh-runtime.js +1349 -0
- package/dist/runtime/foundation/route-mesh-connection-policy.d.ts +3 -0
- package/dist/runtime/foundation/route-mesh-connection-policy.js +13 -0
- package/dist/runtime/foundation/runtime-state-projections.d.ts +13 -0
- package/dist/runtime/foundation/runtime-state-projections.js +44 -0
- package/dist/runtime/foundation/service-authority-payload-codec.d.ts +56 -0
- package/dist/runtime/foundation/service-authority-payload-codec.js +411 -0
- package/dist/runtime/foundation/service-discovery-registry.d.ts +42 -0
- package/dist/runtime/foundation/service-discovery-registry.js +175 -0
- package/dist/runtime/foundation/service-instance-activation-recovery-codec.d.ts +19 -0
- package/dist/runtime/foundation/service-instance-activation-recovery-codec.js +287 -0
- package/dist/runtime/foundation/service-liveness-registry.d.ts +28 -0
- package/dist/runtime/foundation/service-liveness-registry.js +109 -0
- package/dist/runtime/foundation/service-mailbox.d.ts +60 -0
- package/dist/runtime/foundation/service-mailbox.js +283 -0
- package/dist/runtime/foundation/service-maintenance-runtime.d.ts +45 -0
- package/dist/runtime/foundation/service-maintenance-runtime.js +198 -0
- package/dist/runtime/foundation/service-metadata-codec.d.ts +2 -0
- package/dist/runtime/foundation/service-metadata-codec.js +69 -0
- package/dist/runtime/foundation/service-relocation-aggregate-committer.d.ts +35 -0
- package/dist/runtime/foundation/service-relocation-aggregate-committer.js +139 -0
- package/dist/runtime/foundation/service-relocation-coordinator.d.ts +19 -0
- package/dist/runtime/foundation/service-relocation-coordinator.js +16 -0
- package/dist/runtime/foundation/service-relocation-object-owner.d.ts +71 -0
- package/dist/runtime/foundation/service-relocation-object-owner.js +242 -0
- package/dist/runtime/foundation/service-relocation-runtime.d.ts +143 -0
- package/dist/runtime/foundation/service-relocation-runtime.js +1080 -0
- package/dist/runtime/foundation/service-runtime-contracts.d.ts +332 -0
- package/dist/runtime/foundation/service-runtime-contracts.js +66 -0
- package/dist/runtime/foundation/service-session-binding-ingress-port.d.ts +23 -0
- package/dist/runtime/foundation/service-session-binding-ingress-port.js +11 -0
- package/dist/runtime/foundation/service-stateful-registry.d.ts +142 -0
- package/dist/runtime/foundation/service-stateful-registry.js +465 -0
- package/dist/runtime/foundation/service-stateful-runtime.d.ts +393 -0
- package/dist/runtime/foundation/service-stateful-runtime.js +3898 -0
- package/dist/runtime/foundation/service-stateful-wire-codec.d.ts +597 -0
- package/dist/runtime/foundation/service-stateful-wire-codec.js +2006 -0
- package/dist/runtime/foundation/service-topology-registry.d.ts +68 -0
- package/dist/runtime/foundation/service-topology-registry.js +393 -0
- package/dist/runtime/foundation/service-weighted-selection.d.ts +14 -0
- package/dist/runtime/foundation/service-weighted-selection.js +128 -0
- package/dist/runtime/foundation/service-wire-binary-primitives.d.ts +10 -0
- package/dist/runtime/foundation/service-wire-binary-primitives.js +53 -0
- package/dist/runtime/foundation/service-wire-codec.d.ts +22 -0
- package/dist/runtime/foundation/service-wire-codec.js +67 -0
- package/dist/runtime/foundation/service-wire-constants.generated.d.ts +110 -0
- package/dist/runtime/foundation/service-wire-constants.generated.js +132 -0
- package/dist/runtime/foundation/service-wire-m6a-codec.d.ts +102 -0
- package/dist/runtime/foundation/service-wire-m6a-codec.js +568 -0
- package/dist/runtime/framework-errors-internal.d.ts +95 -0
- package/dist/runtime/framework-errors-internal.js +301 -0
- package/dist/runtime/handlers/handler-instance-scope.d.ts +11 -0
- package/dist/runtime/handlers/handler-instance-scope.js +284 -0
- package/dist/runtime/handlers/index.d.ts +13 -0
- package/dist/runtime/handlers/index.js +57 -0
- package/dist/runtime/host/actor-packet-relay.d.ts +60 -0
- package/dist/runtime/host/actor-packet-relay.js +664 -0
- package/dist/runtime/host/actor-placement-coordinator.d.ts +32 -0
- package/dist/runtime/host/actor-placement-coordinator.js +386 -0
- package/dist/runtime/host/actor-runtime-options-factory.d.ts +65 -0
- package/dist/runtime/host/actor-runtime-options-factory.js +160 -0
- package/dist/runtime/host/actor-transfer-authority-runtime.d.ts +26 -0
- package/dist/runtime/host/actor-transfer-authority-runtime.js +138 -0
- package/dist/runtime/host/actor-transfer-runtime.d.ts +149 -0
- package/dist/runtime/host/actor-transfer-runtime.js +1245 -0
- package/dist/runtime/host/application-job-queue.d.ts +99 -0
- package/dist/runtime/host/application-job-queue.js +409 -0
- package/dist/runtime/host/bound-session-relay.d.ts +41 -0
- package/dist/runtime/host/bound-session-relay.js +52 -0
- package/dist/runtime/host/bounded-replay-map.d.ts +12 -0
- package/dist/runtime/host/bounded-replay-map.js +42 -0
- package/dist/runtime/host/channel-runtime-options-factory.d.ts +22 -0
- package/dist/runtime/host/channel-runtime-options-factory.js +76 -0
- package/dist/runtime/host/entry-actor-runtime.d.ts +30 -0
- package/dist/runtime/host/entry-actor-runtime.js +80 -0
- package/dist/runtime/host/host-capacity-status.d.ts +11 -0
- package/dist/runtime/host/host-capacity-status.js +85 -0
- package/dist/runtime/host/index.d.ts +188 -0
- package/dist/runtime/host/index.js +2552 -0
- package/dist/runtime/host/instance-activation-authority.d.ts +33 -0
- package/dist/runtime/host/instance-activation-authority.js +496 -0
- package/dist/runtime/host/location-runtime-owner.d.ts +48 -0
- package/dist/runtime/host/location-runtime-owner.js +227 -0
- package/dist/runtime/host/mesh-router-resolver.d.ts +16 -0
- package/dist/runtime/host/mesh-router-resolver.js +108 -0
- package/dist/runtime/host/relocation-direct-transfer.d.ts +81 -0
- package/dist/runtime/host/relocation-direct-transfer.js +240 -0
- package/dist/runtime/host/relocation-integrity-fault-gate.d.ts +6 -0
- package/dist/runtime/host/relocation-integrity-fault-gate.js +5 -0
- package/dist/runtime/host/relocation-state-adapter.d.ts +8 -0
- package/dist/runtime/host/relocation-state-adapter.js +13 -0
- package/dist/runtime/host/remote-actor-join-receiver.d.ts +47 -0
- package/dist/runtime/host/remote-actor-join-receiver.js +161 -0
- package/dist/runtime/host/remote-actor-packet-target-store.d.ts +29 -0
- package/dist/runtime/host/remote-actor-packet-target-store.js +185 -0
- package/dist/runtime/host/remote-bound-session-relay.d.ts +58 -0
- package/dist/runtime/host/remote-bound-session-relay.js +540 -0
- package/dist/runtime/host/route-mesh-runtime-options.d.ts +9 -0
- package/dist/runtime/host/route-mesh-runtime-options.js +41 -0
- package/dist/runtime/host/route-mesh-runtime.d.ts +76 -0
- package/dist/runtime/host/route-mesh-runtime.js +746 -0
- package/dist/runtime/host/runtime-shutdown.d.ts +33 -0
- package/dist/runtime/host/runtime-shutdown.js +68 -0
- package/dist/runtime/host/service-relocation-control.d.ts +7 -0
- package/dist/runtime/host/service-relocation-control.js +24 -0
- package/dist/runtime/host/service-relocation-host-runtime.d.ts +241 -0
- package/dist/runtime/host/service-relocation-host-runtime.js +4113 -0
- package/dist/runtime/host/spot-address-transport.d.ts +47 -0
- package/dist/runtime/host/spot-address-transport.js +601 -0
- package/dist/runtime/host/spot-node-runtime-options-factory.d.ts +38 -0
- package/dist/runtime/host/spot-node-runtime-options-factory.js +36 -0
- package/dist/runtime/host/spot-runtime-options-factory.d.ts +48 -0
- package/dist/runtime/host/spot-runtime-options-factory.js +169 -0
- package/dist/runtime/host/stateful-authority-route-runtime.d.ts +34 -0
- package/dist/runtime/host/stateful-authority-route-runtime.js +440 -0
- package/dist/runtime/host/user-spot-creation-coordinator.d.ts +69 -0
- package/dist/runtime/host/user-spot-creation-coordinator.js +759 -0
- package/dist/runtime/locations/actor-location-claims.d.ts +43 -0
- package/dist/runtime/locations/actor-location-claims.js +319 -0
- package/dist/runtime/locations/actor-session-route-claims.d.ts +10 -0
- package/dist/runtime/locations/actor-session-route-claims.js +51 -0
- package/dist/runtime/locations/aggregate-inventory-store.d.ts +18 -0
- package/dist/runtime/locations/aggregate-inventory-store.js +399 -0
- package/dist/runtime/locations/authority-key-codec.d.ts +6 -0
- package/dist/runtime/locations/authority-key-codec.js +78 -0
- package/dist/runtime/locations/auto-connect-loop.d.ts +37 -0
- package/dist/runtime/locations/auto-connect-loop.js +112 -0
- package/dist/runtime/locations/auto-connect-planner.d.ts +9 -0
- package/dist/runtime/locations/auto-connect-planner.js +137 -0
- package/dist/runtime/locations/auto-connect-reconciler.d.ts +57 -0
- package/dist/runtime/locations/auto-connect-reconciler.js +358 -0
- package/dist/runtime/locations/auto-connect-types.d.ts +42 -0
- package/dist/runtime/locations/auto-connect-types.js +2 -0
- package/dist/runtime/locations/auto-connect.d.ts +4 -0
- package/dist/runtime/locations/auto-connect.js +20 -0
- package/dist/runtime/locations/canonical-codec.d.ts +7 -0
- package/dist/runtime/locations/canonical-codec.js +48 -0
- package/dist/runtime/locations/domain-store-contract.d.ts +34 -0
- package/dist/runtime/locations/domain-store-contract.js +2 -0
- package/dist/runtime/locations/in-memory-authority-store.d.ts +51 -0
- package/dist/runtime/locations/in-memory-authority-store.js +895 -0
- package/dist/runtime/locations/in-memory-location-store.d.ts +78 -0
- package/dist/runtime/locations/in-memory-location-store.js +1008 -0
- package/dist/runtime/locations/in-memory-provider-location-store.d.ts +19 -0
- package/dist/runtime/locations/in-memory-provider-location-store.js +183 -0
- package/dist/runtime/locations/index.d.ts +11 -0
- package/dist/runtime/locations/index.js +27 -0
- package/dist/runtime/locations/internal-location-contracts.d.ts +7 -0
- package/dist/runtime/locations/internal-location-contracts.js +21 -0
- package/dist/runtime/locations/internal-store-contracts.d.ts +35 -0
- package/dist/runtime/locations/internal-store-contracts.js +2 -0
- package/dist/runtime/locations/key-codec.d.ts +13 -0
- package/dist/runtime/locations/key-codec.js +41 -0
- package/dist/runtime/locations/lease-tracker.d.ts +36 -0
- package/dist/runtime/locations/lease-tracker.js +155 -0
- package/dist/runtime/locations/lifecycle-runtime.d.ts +19 -0
- package/dist/runtime/locations/lifecycle-runtime.js +2 -0
- package/dist/runtime/locations/lifecycle.d.ts +40 -0
- package/dist/runtime/locations/lifecycle.js +120 -0
- package/dist/runtime/locations/location-store-repository.d.ts +72 -0
- package/dist/runtime/locations/location-store-repository.js +3198 -0
- package/dist/runtime/locations/relocation-blob.d.ts +7 -0
- package/dist/runtime/locations/relocation-blob.js +24 -0
- package/dist/runtime/locations/resolvers.d.ts +145 -0
- package/dist/runtime/locations/resolvers.js +693 -0
- package/dist/runtime/locations/runtime.d.ts +144 -0
- package/dist/runtime/locations/runtime.js +792 -0
- package/dist/runtime/locations/spot-location-claims.d.ts +36 -0
- package/dist/runtime/locations/spot-location-claims.js +305 -0
- package/dist/runtime/messaging/creation-payload-codec.d.ts +4 -0
- package/dist/runtime/messaging/creation-payload-codec.js +40 -0
- package/dist/runtime/messaging/framework-json-v1.d.ts +7 -0
- package/dist/runtime/messaging/framework-json-v1.js +296 -0
- package/dist/runtime/messaging/index.d.ts +1 -0
- package/dist/runtime/messaging/index.js +2 -0
- package/dist/runtime/messaging/packet-name.d.ts +4 -0
- package/dist/runtime/messaging/packet-name.js +79 -0
- package/dist/runtime/messaging/payload-codec.d.ts +25 -0
- package/dist/runtime/messaging/payload-codec.js +255 -0
- package/dist/runtime/messaging/submission-result.d.ts +15 -0
- package/dist/runtime/messaging/submission-result.js +37 -0
- package/dist/runtime/protocol/service_wire_pilot_codec.generated.d.ts +395 -0
- package/dist/runtime/protocol/service_wire_pilot_codec.generated.js +645 -0
- package/dist/runtime/routing-id.d.ts +8 -0
- package/dist/runtime/routing-id.js +112 -0
- package/dist/runtime/spots/formal-remote-actor-admission-registry.d.ts +124 -0
- package/dist/runtime/spots/formal-remote-actor-admission-registry.js +269 -0
- package/dist/runtime/spots/formal-remote-actor-transfer-registry.d.ts +33 -0
- package/dist/runtime/spots/formal-remote-actor-transfer-registry.js +94 -0
- package/dist/runtime/spots/index.d.ts +247 -0
- package/dist/runtime/spots/index.js +2090 -0
- package/dist/runtime/spots/spot-activation-registry.d.ts +47 -0
- package/dist/runtime/spots/spot-activation-registry.js +272 -0
- package/dist/runtime/spots/spot-activation-state.d.ts +104 -0
- package/dist/runtime/spots/spot-activation-state.js +288 -0
- package/dist/runtime/spots/spot-activation.d.ts +89 -0
- package/dist/runtime/spots/spot-activation.js +601 -0
- package/dist/runtime/spots/spot-actor-admission-coordinator.d.ts +20 -0
- package/dist/runtime/spots/spot-actor-admission-coordinator.js +194 -0
- package/dist/runtime/spots/spot-actor-join-dispatch.d.ts +83 -0
- package/dist/runtime/spots/spot-actor-join-dispatch.js +185 -0
- package/dist/runtime/spots/spot-actor-lifecycle-drain.d.ts +22 -0
- package/dist/runtime/spots/spot-actor-lifecycle-drain.js +51 -0
- package/dist/runtime/spots/spot-actor-membership.d.ts +39 -0
- package/dist/runtime/spots/spot-actor-membership.js +179 -0
- package/dist/runtime/spots/spot-actor-packet-dispatch.d.ts +91 -0
- package/dist/runtime/spots/spot-actor-packet-dispatch.js +315 -0
- package/dist/runtime/spots/spot-actor-packet-drain.d.ts +40 -0
- package/dist/runtime/spots/spot-actor-packet-drain.js +235 -0
- package/dist/runtime/spots/spot-actor-packet-relay-dispatch.d.ts +18 -0
- package/dist/runtime/spots/spot-actor-packet-relay-dispatch.js +110 -0
- package/dist/runtime/spots/spot-closing.d.ts +2 -0
- package/dist/runtime/spots/spot-closing.js +30 -0
- package/dist/runtime/spots/spot-context.d.ts +46 -0
- package/dist/runtime/spots/spot-context.js +113 -0
- package/dist/runtime/spots/spot-entry-activation.d.ts +107 -0
- package/dist/runtime/spots/spot-entry-activation.js +342 -0
- package/dist/runtime/spots/spot-handle.d.ts +28 -0
- package/dist/runtime/spots/spot-handle.js +38 -0
- package/dist/runtime/spots/spot-handler-registry.d.ts +52 -0
- package/dist/runtime/spots/spot-handler-registry.js +155 -0
- package/dist/runtime/spots/spot-lifecycle-metrics.d.ts +8 -0
- package/dist/runtime/spots/spot-lifecycle-metrics.js +16 -0
- package/dist/runtime/spots/spot-location-claim.d.ts +25 -0
- package/dist/runtime/spots/spot-location-claim.js +55 -0
- package/dist/runtime/spots/spot-manager-internal-contracts.d.ts +10 -0
- package/dist/runtime/spots/spot-manager-internal-contracts.js +2 -0
- package/dist/runtime/spots/spot-manager-public.d.ts +32 -0
- package/dist/runtime/spots/spot-manager-public.js +219 -0
- package/dist/runtime/spots/spot-native-actor-join-admission.d.ts +26 -0
- package/dist/runtime/spots/spot-native-actor-join-admission.js +105 -0
- package/dist/runtime/spots/spot-native-flags.d.ts +2 -0
- package/dist/runtime/spots/spot-native-flags.js +5 -0
- package/dist/runtime/spots/spot-node-autoconnect.d.ts +23 -0
- package/dist/runtime/spots/spot-node-autoconnect.js +246 -0
- package/dist/runtime/spots/spot-node-runtime-manager.d.ts +137 -0
- package/dist/runtime/spots/spot-node-runtime-manager.js +1111 -0
- package/dist/runtime/spots/spot-outbound.d.ts +78 -0
- package/dist/runtime/spots/spot-outbound.js +460 -0
- package/dist/runtime/spots/spot-provider.d.ts +4 -0
- package/dist/runtime/spots/spot-provider.js +28 -0
- package/dist/runtime/spots/spot-publisher-transport.d.ts +14 -0
- package/dist/runtime/spots/spot-publisher-transport.js +28 -0
- package/dist/runtime/spots/spot-remote-codec.d.ts +50 -0
- package/dist/runtime/spots/spot-remote-codec.js +190 -0
- package/dist/runtime/spots/spot-remote-route-codec.d.ts +47 -0
- package/dist/runtime/spots/spot-remote-route-codec.js +168 -0
- package/dist/runtime/spots/spot-route-packet-dispatch.d.ts +25 -0
- package/dist/runtime/spots/spot-route-packet-dispatch.js +238 -0
- package/dist/runtime/spots/spot-route-replies.d.ts +17 -0
- package/dist/runtime/spots/spot-route-replies.js +76 -0
- package/dist/runtime/spots/spot-route-reply-wire.d.ts +10 -0
- package/dist/runtime/spots/spot-route-reply-wire.js +6 -0
- package/dist/runtime/spots/spot-routed-actor-admission.d.ts +36 -0
- package/dist/runtime/spots/spot-routed-actor-admission.js +240 -0
- package/dist/runtime/spots/spot-routed-bound-session-dispatch.d.ts +19 -0
- package/dist/runtime/spots/spot-routed-bound-session-dispatch.js +46 -0
- package/dist/runtime/spots/spot-routed-frame-dispatch.d.ts +54 -0
- package/dist/runtime/spots/spot-routed-frame-dispatch.js +162 -0
- package/dist/runtime/spots/spot-routed-spot-packet-dispatch.d.ts +43 -0
- package/dist/runtime/spots/spot-routed-spot-packet-dispatch.js +152 -0
- package/dist/runtime/spots/spot-routing-internal.d.ts +28 -0
- package/dist/runtime/spots/spot-routing-internal.js +2 -0
- package/dist/runtime/spots/spot-runtime-ports.d.ts +64 -0
- package/dist/runtime/spots/spot-runtime-ports.js +2 -0
- package/dist/runtime/spots/spot-serial-executor.d.ts +38 -0
- package/dist/runtime/spots/spot-serial-executor.js +133 -0
- package/dist/runtime/spots/spot-serial-turn-executor.d.ts +54 -0
- package/dist/runtime/spots/spot-serial-turn-executor.js +219 -0
- package/dist/runtime/spots/spot-subscription-dispatch.d.ts +32 -0
- package/dist/runtime/spots/spot-subscription-dispatch.js +194 -0
- package/dist/runtime/spots/spot-timer.d.ts +110 -0
- package/dist/runtime/spots/spot-timer.js +419 -0
- package/dist/runtime/streams/actor-session-binding-registry.d.ts +193 -0
- package/dist/runtime/streams/actor-session-binding-registry.js +1127 -0
- package/dist/runtime/streams/actor-session-binding-runtime-owner.d.ts +20 -0
- package/dist/runtime/streams/actor-session-binding-runtime-owner.js +19 -0
- package/dist/runtime/streams/actor-session-lifecycle-coordinator.d.ts +4 -0
- package/dist/runtime/streams/actor-session-lifecycle-coordinator.js +24 -0
- package/dist/runtime/streams/bound-actor-relay-sender.d.ts +29 -0
- package/dist/runtime/streams/bound-actor-relay-sender.js +181 -0
- package/dist/runtime/streams/bound-session-response-target.d.ts +25 -0
- package/dist/runtime/streams/bound-session-response-target.js +54 -0
- package/dist/runtime/streams/bound-session-service.d.ts +48 -0
- package/dist/runtime/streams/bound-session-service.js +201 -0
- package/dist/runtime/streams/index.d.ts +152 -0
- package/dist/runtime/streams/index.js +338 -0
- package/dist/runtime/streams/managed-stream.d.ts +53 -0
- package/dist/runtime/streams/managed-stream.js +329 -0
- package/dist/runtime/streams/native-fallback-bound-session.d.ts +24 -0
- package/dist/runtime/streams/native-fallback-bound-session.js +201 -0
- package/dist/runtime/streams/protocol.d.ts +67 -0
- package/dist/runtime/streams/protocol.js +244 -0
- package/dist/runtime/streams/session-actor-coordinator.d.ts +56 -0
- package/dist/runtime/streams/session-actor-coordinator.js +371 -0
- package/dist/runtime/streams/session-calls.d.ts +59 -0
- package/dist/runtime/streams/session-calls.js +123 -0
- package/dist/runtime/streams/session-context.d.ts +108 -0
- package/dist/runtime/streams/session-context.js +377 -0
- package/dist/runtime/streams/session-local-actors.d.ts +10 -0
- package/dist/runtime/streams/session-local-actors.js +26 -0
- package/dist/runtime/streams/session-provider.d.ts +4 -0
- package/dist/runtime/streams/session-provider.js +30 -0
- package/dist/runtime/streams/session-requests.d.ts +25 -0
- package/dist/runtime/streams/session-requests.js +100 -0
- package/dist/runtime/streams/session-serial-executor.d.ts +12 -0
- package/dist/runtime/streams/session-serial-executor.js +58 -0
- package/dist/runtime/streams/stream-binding-runtime-ports.d.ts +62 -0
- package/dist/runtime/streams/stream-binding-runtime-ports.js +2 -0
- package/dist/runtime/streams/stream-frame-factory.d.ts +44 -0
- package/dist/runtime/streams/stream-frame-factory.js +149 -0
- package/dist/runtime/streams/stream-message-utils.d.ts +5 -0
- package/dist/runtime/streams/stream-message-utils.js +74 -0
- package/dist/runtime/streams/stream-session-runtime.d.ts +166 -0
- package/dist/runtime/streams/stream-session-runtime.js +1144 -0
- package/dist/runtime/workers/index.d.ts +38 -0
- package/dist/runtime/workers/index.js +474 -0
- package/package.json +19 -0
- package/src/contracts/Actors/ZLinkActor.ts +8 -0
- package/src/contracts/Actors/ZLinkActorClient.ts +18 -0
- package/src/contracts/Actors/ZLinkActorContext.ts +15 -0
- package/src/contracts/Actors/ZLinkActorFactory.ts +41 -0
- package/src/contracts/Actors/ZLinkActorManager.ts +31 -0
- package/src/contracts/Actors/index.ts +5 -0
- package/src/contracts/Channels/Calls.ts +33 -0
- package/src/contracts/Channels/IZLinkChannelClient.ts +6 -0
- package/src/contracts/Channels/IZLinkFanoutClient.ts +13 -0
- package/src/contracts/Channels/RouteCalls.ts +13 -0
- package/src/contracts/Channels/index.ts +4 -0
- package/src/contracts/Codecs/IZLinkCodecRegistryBuilder.ts +22 -0
- package/src/contracts/Codecs/ZLinkMessageSerializer.ts +6 -0
- package/src/contracts/Codecs/index.ts +2 -0
- package/src/contracts/Common/ActorRef.ts +8 -0
- package/src/contracts/Common/CoreTypes.ts +6 -0
- package/src/contracts/Common/Message.ts +9 -0
- package/src/contracts/Common/ZLinkEncodedPayload.ts +47 -0
- package/src/contracts/Common/ZLinkMessage.ts +135 -0
- package/src/contracts/Common/ZLinkMessageMetadata.ts +77 -0
- package/src/contracts/Common/ZLinkProviderResolver.ts +6 -0
- package/src/contracts/Common/encoded-payload-storage.ts +16 -0
- package/src/contracts/Common/index.ts +5 -0
- package/src/contracts/Configuration/Builders.ts +200 -0
- package/src/contracts/Configuration/CodecContentType.ts +68 -0
- package/src/contracts/Configuration/CodecSerializerSelection.ts +28 -0
- package/src/contracts/Configuration/Configs.ts +27 -0
- package/src/contracts/Configuration/ConfigurationException.ts +6 -0
- package/src/contracts/Configuration/Connections.ts +5 -0
- package/src/contracts/Configuration/DiagnosticsValidation.ts +25 -0
- package/src/contracts/Configuration/EndpointNotation.ts +232 -0
- package/src/contracts/Configuration/InternalDefaults.ts +13 -0
- package/src/contracts/Configuration/ObjectRoles.ts +47 -0
- package/src/contracts/Configuration/Registration.ts +191 -0
- package/src/contracts/Configuration/RegistrationBuilderPolicy.ts +76 -0
- package/src/contracts/Configuration/RegistrationBuilders.ts +1705 -0
- package/src/contracts/Configuration/RegistrationCodecRegistry.ts +118 -0
- package/src/contracts/Configuration/RegistrationNormalizers.ts +404 -0
- package/src/contracts/Configuration/RegistrationTypes.ts +499 -0
- package/src/contracts/Configuration/RegistrationValidators.ts +698 -0
- package/src/contracts/Configuration/RouteChannelInternalState.ts +50 -0
- package/src/contracts/Configuration/RuntimeEndpointConnections.ts +91 -0
- package/src/contracts/Configuration/SendTimeoutValidation.ts +15 -0
- package/src/contracts/Configuration/TimerRegistrationValidator.ts +37 -0
- package/src/contracts/Configuration/index.ts +35 -0
- package/src/contracts/Dispatch/ZLinkDispatchOptions.ts +222 -0
- package/src/contracts/Dispatch/ZLinkFlowOrigin.ts +1 -0
- package/src/contracts/Dispatch/index.ts +2 -0
- package/src/contracts/Errors/ZLinkFrameworkException.ts +27 -0
- package/src/contracts/Errors/index.ts +4 -0
- package/src/contracts/Eventing/Metrics.ts +27 -0
- package/src/contracts/Eventing/index.ts +1 -0
- package/src/contracts/Handlers/Attributes.ts +111 -0
- package/src/contracts/Handlers/Contexts.ts +21 -0
- package/src/contracts/Handlers/IZLinkChannelHandlers.ts +69 -0
- package/src/contracts/Handlers/IZLinkHandlerFilter.ts +22 -0
- package/src/contracts/Handlers/JsonContract.ts +172 -0
- package/src/contracts/Handlers/ZLinkHandlerFilterNext.ts +1 -0
- package/src/contracts/Handlers/index.ts +17 -0
- package/src/contracts/Locations/ActorTransfer.ts +84 -0
- package/src/contracts/Locations/Authority.ts +308 -0
- package/src/contracts/Locations/Diagnostics.ts +48 -0
- package/src/contracts/Locations/Keys.ts +93 -0
- package/src/contracts/Locations/Models.ts +7 -0
- package/src/contracts/Locations/Options.ts +42 -0
- package/src/contracts/Locations/Readiness.ts +11 -0
- package/src/contracts/Locations/RelocationStore.ts +51 -0
- package/src/contracts/Locations/Resolvers.ts +8 -0
- package/src/contracts/Locations/Rows.ts +164 -0
- package/src/contracts/Locations/RuntimeQuery.ts +56 -0
- package/src/contracts/Locations/Stores.ts +92 -0
- package/src/contracts/Locations/Values.ts +32 -0
- package/src/contracts/Locations/Watch.ts +16 -0
- package/src/contracts/Locations/Writes.ts +56 -0
- package/src/contracts/Locations/index.ts +48 -0
- package/src/contracts/RouteMesh/Contracts.ts +145 -0
- package/src/contracts/RouteMesh/RuntimeTopology.ts +201 -0
- package/src/contracts/RouteMesh/index.ts +2 -0
- package/src/contracts/Spots/Builders.ts +11 -0
- package/src/contracts/Spots/Contracts.ts +150 -0
- package/src/contracts/Spots/SpotKind.ts +24 -0
- package/src/contracts/Spots/ZLinkSpot.ts +88 -0
- package/src/contracts/Spots/index.ts +3 -0
- package/src/contracts/Streams/BoundSessionContracts.ts +9 -0
- package/src/contracts/Streams/IZLinkSession.ts +52 -0
- package/src/contracts/Streams/IZLinkSessionActor.ts +17 -0
- package/src/contracts/Streams/IZLinkSessionPacketHandler.ts +11 -0
- package/src/contracts/Streams/IZLinkStream.ts +10 -0
- package/src/contracts/Streams/ZLinkMessageMetadata.ts +1 -0
- package/src/contracts/Streams/ZLinkStreamCompression.ts +9 -0
- package/src/contracts/Streams/ZLinkStreamError.ts +9 -0
- package/src/contracts/Streams/index.ts +8 -0
- package/src/contracts/Timers/IZLinkTimer.ts +5 -0
- package/src/contracts/Timers/ZLinkTimerOptions.ts +11 -0
- package/src/contracts/Timers/ZLinkTimerTick.ts +12 -0
- package/src/contracts/Timers/index.ts +3 -0
- package/src/contracts/index.ts +71 -0
- package/src/index.ts +1 -0
- package/src/internal.ts +29 -0
- package/src/location-store-integration.ts +51 -0
- package/src/nest-integration.ts +251 -0
- package/src/runtime/abort.ts +70 -0
- package/src/runtime/actors/actor-authority-payload-codec.ts +454 -0
- package/src/runtime/actors/actor-authority-publication.ts +277 -0
- package/src/runtime/actors/actor-client.ts +1018 -0
- package/src/runtime/actors/actor-context.ts +583 -0
- package/src/runtime/actors/actor-creation.ts +254 -0
- package/src/runtime/actors/actor-execution-context.ts +38 -0
- package/src/runtime/actors/actor-handoff.ts +1911 -0
- package/src/runtime/actors/actor-join-deferred-scope.ts +183 -0
- package/src/runtime/actors/actor-join-relocation.ts +39 -0
- package/src/runtime/actors/actor-lifecycle-snapshot.ts +90 -0
- package/src/runtime/actors/actor-local-native-join.ts +725 -0
- package/src/runtime/actors/actor-mailbox.ts +92 -0
- package/src/runtime/actors/actor-message-follow-context.ts +347 -0
- package/src/runtime/actors/actor-native-lookup.ts +38 -0
- package/src/runtime/actors/actor-packet-relay-wire.ts +223 -0
- package/src/runtime/actors/actor-remote-joiner.ts +238 -0
- package/src/runtime/actors/actor-remote-wire.ts +169 -0
- package/src/runtime/actors/actor-retry-delay.ts +37 -0
- package/src/runtime/actors/actor-routed-join-transport.ts +58 -0
- package/src/runtime/actors/actor-routed-json-request.ts +44 -0
- package/src/runtime/actors/actor-runtime-contracts.ts +126 -0
- package/src/runtime/actors/actor-runtime-state.ts +805 -0
- package/src/runtime/actors/actor-source-transfer.ts +62 -0
- package/src/runtime/actors/actor-transfer-registry.ts +112 -0
- package/src/runtime/actors/actor-transport-delivery-gate.ts +17 -0
- package/src/runtime/actors/bound-session-wire.ts +257 -0
- package/src/runtime/actors/deferred-join-accepted-journal.ts +1319 -0
- package/src/runtime/actors/index.ts +972 -0
- package/src/runtime/actors/post-commit-actor-binder.ts +70 -0
- package/src/runtime/actors/post-commit-actor-location.ts +114 -0
- package/src/runtime/actors/spot-actor-dispatch.ts +362 -0
- package/src/runtime/actors/transferred-actor-rollback.ts +123 -0
- package/src/runtime/admission.ts +192 -0
- package/src/runtime/application-jobs/application-ingress-record-owner.ts +216 -0
- package/src/runtime/application-jobs/application-job-queue-handler-start-gate.ts +10 -0
- package/src/runtime/application-jobs/application-job-queue-scope.ts +64 -0
- package/src/runtime/application-jobs/contracts.ts +26 -0
- package/src/runtime/application-jobs/receive-flow-controller.ts +188 -0
- package/src/runtime/backend/contracts/index.ts +765 -0
- package/src/runtime/backend/index.ts +9 -0
- package/src/runtime/backend/mesh-actor-session-node-adapter.ts +73 -0
- package/src/runtime/backend/mesh-completion-table.ts +165 -0
- package/src/runtime/backend/mesh-dispatch-pump.ts +363 -0
- package/src/runtime/backend/mesh-record-dispatcher.ts +65 -0
- package/src/runtime/backend/node/index.ts +4 -0
- package/src/runtime/backend/node/node-backend-adapter-factory.ts +204 -0
- package/src/runtime/backend/node/node-backend-adapter-support.ts +257 -0
- package/src/runtime/backend/node/node-dealer-channel-client-transport.ts +133 -0
- package/src/runtime/backend/node/node-mesh-backend-adapter.ts +44 -0
- package/src/runtime/backend/node/node-monitor-backend-adapter.ts +39 -0
- package/src/runtime/backend/node/node-raw-binding-port.contract.ts +21 -0
- package/src/runtime/backend/node/node-raw-binding-port.ts +518 -0
- package/src/runtime/backend/node/node-raw-mesh-backend.ts +2669 -0
- package/src/runtime/backend/node/node-socket-backend-adapter.ts +372 -0
- package/src/runtime/backend/node-backend-adapter.ts +19 -0
- package/src/runtime/backend/raw-binding-port.ts +69 -0
- package/src/runtime/backend/runtime-message.ts +51 -0
- package/src/runtime/backend/runtime-values.ts +107 -0
- package/src/runtime/channels/channel-autoconnect.ts +46 -0
- package/src/runtime/channels/channel-clients.ts +527 -0
- package/src/runtime/channels/channel-dispatch-pipeline.ts +408 -0
- package/src/runtime/channels/channel-dispatch-services.ts +234 -0
- package/src/runtime/channels/channel-dispatchers.ts +790 -0
- package/src/runtime/channels/channel-envelope-inspection.ts +125 -0
- package/src/runtime/channels/channel-envelope.ts +743 -0
- package/src/runtime/channels/channel-framework-packets.ts +8 -0
- package/src/runtime/channels/channel-multipart.ts +61 -0
- package/src/runtime/channels/channel-outbound-operations.ts +584 -0
- package/src/runtime/channels/channel-receive-loops.ts +901 -0
- package/src/runtime/channels/channel-receive-task-tracker.ts +39 -0
- package/src/runtime/channels/channel-runtime-lifecycle.ts +969 -0
- package/src/runtime/channels/channel-runtime-manager.ts +444 -0
- package/src/runtime/channels/channel-socket-options.ts +153 -0
- package/src/runtime/channels/channel-socket-registry.ts +1837 -0
- package/src/runtime/channels/channel-transports.ts +1154 -0
- package/src/runtime/channels/client-server-location-runtime.ts +576 -0
- package/src/runtime/channels/client-server-service-wire.ts +390 -0
- package/src/runtime/channels/dispatch-error-reporter.ts +165 -0
- package/src/runtime/channels/fanout-location-runtime.ts +459 -0
- package/src/runtime/channels/fanout-service-wire.ts +43 -0
- package/src/runtime/channels/handler-filter-scope.ts +29 -0
- package/src/runtime/channels/index.ts +45 -0
- package/src/runtime/channels/local-spot-route-transport.ts +59 -0
- package/src/runtime/channels/route-disconnected-error.ts +6 -0
- package/src/runtime/channels/route-member-snapshot.ts +55 -0
- package/src/runtime/channels/router-socket-spot-route-transport.ts +77 -0
- package/src/runtime/channels/source-spot-router.ts +89 -0
- package/src/runtime/channels/spot-direct-envelope.ts +44 -0
- package/src/runtime/channels/spot-node-route-transport.ts +92 -0
- package/src/runtime/channels/spot-route-bridge-transport.ts +75 -0
- package/src/runtime/channels/spot-route-dispatch-strategy.ts +329 -0
- package/src/runtime/channels/spot-route-target-resolver.ts +101 -0
- package/src/runtime/codecs/index.ts +69 -0
- package/src/runtime/configuration/index.ts +1 -0
- package/src/runtime/diagnostics/dispatch-error-port.ts +8 -0
- package/src/runtime/diagnostics/flow-context.ts +84 -0
- package/src/runtime/diagnostics/index.ts +441 -0
- package/src/runtime/diagnostics/internal-event-contracts.ts +135 -0
- package/src/runtime/diagnostics/message-flow.ts +560 -0
- package/src/runtime/diagnostics/runtime-metrics.ts +601 -0
- package/src/runtime/diagnostics/runtime-observation-queue.ts +362 -0
- package/src/runtime/diagnostics/topology-runtime-projections.ts +298 -0
- package/src/runtime/execution/index.ts +466 -0
- package/src/runtime/execution/serial-execution-queue.ts +534 -0
- package/src/runtime/execution/serial-work-size.ts +31 -0
- package/src/runtime/execution/state-lane.ts +116 -0
- package/src/runtime/foundation/actor-join-recovery-codec.ts +465 -0
- package/src/runtime/foundation/event-loop-resources.ts +162 -0
- package/src/runtime/foundation/index.ts +18 -0
- package/src/runtime/foundation/message-follow-suppression-registry.ts +130 -0
- package/src/runtime/foundation/operation-identity.ts +49 -0
- package/src/runtime/foundation/operation-registry.ts +162 -0
- package/src/runtime/foundation/raw-service-mesh-runtime.ts +1771 -0
- package/src/runtime/foundation/route-mesh-connection-policy.ts +28 -0
- package/src/runtime/foundation/runtime-state-projections.ts +68 -0
- package/src/runtime/foundation/service-authority-payload-codec.ts +566 -0
- package/src/runtime/foundation/service-discovery-registry.ts +263 -0
- package/src/runtime/foundation/service-instance-activation-recovery-codec.ts +329 -0
- package/src/runtime/foundation/service-liveness-registry.ts +144 -0
- package/src/runtime/foundation/service-mailbox.ts +369 -0
- package/src/runtime/foundation/service-maintenance-runtime.ts +242 -0
- package/src/runtime/foundation/service-metadata-codec.ts +75 -0
- package/src/runtime/foundation/service-relocation-aggregate-committer.ts +218 -0
- package/src/runtime/foundation/service-relocation-coordinator.ts +37 -0
- package/src/runtime/foundation/service-relocation-object-owner.ts +428 -0
- package/src/runtime/foundation/service-relocation-runtime.ts +1407 -0
- package/src/runtime/foundation/service-runtime-contracts.ts +423 -0
- package/src/runtime/foundation/service-session-binding-ingress-port.ts +45 -0
- package/src/runtime/foundation/service-stateful-registry.ts +664 -0
- package/src/runtime/foundation/service-stateful-runtime.ts +5753 -0
- package/src/runtime/foundation/service-stateful-wire-codec.ts +3008 -0
- package/src/runtime/foundation/service-topology-registry.ts +599 -0
- package/src/runtime/foundation/service-weighted-selection.ts +166 -0
- package/src/runtime/foundation/service-wire-binary-primitives.ts +80 -0
- package/src/runtime/foundation/service-wire-codec.ts +91 -0
- package/src/runtime/foundation/service-wire-constants.generated.ts +131 -0
- package/src/runtime/foundation/service-wire-m6a-codec.ts +647 -0
- package/src/runtime/framework-errors-internal.ts +338 -0
- package/src/runtime/handlers/handler-instance-scope.ts +372 -0
- package/src/runtime/handlers/index.ts +93 -0
- package/src/runtime/host/actor-packet-relay.ts +1070 -0
- package/src/runtime/host/actor-placement-coordinator.ts +573 -0
- package/src/runtime/host/actor-runtime-options-factory.ts +282 -0
- package/src/runtime/host/actor-transfer-authority-runtime.ts +225 -0
- package/src/runtime/host/actor-transfer-runtime.ts +1958 -0
- package/src/runtime/host/application-job-queue.ts +518 -0
- package/src/runtime/host/bound-session-relay.ts +94 -0
- package/src/runtime/host/bounded-replay-map.ts +42 -0
- package/src/runtime/host/channel-runtime-options-factory.ts +104 -0
- package/src/runtime/host/entry-actor-runtime.ts +115 -0
- package/src/runtime/host/host-capacity-status.ts +103 -0
- package/src/runtime/host/index.ts +3492 -0
- package/src/runtime/host/instance-activation-authority.ts +658 -0
- package/src/runtime/host/location-runtime-owner.ts +313 -0
- package/src/runtime/host/mesh-router-resolver.ts +114 -0
- package/src/runtime/host/relocation-direct-transfer.ts +273 -0
- package/src/runtime/host/relocation-integrity-fault-gate.ts +8 -0
- package/src/runtime/host/relocation-state-adapter.ts +24 -0
- package/src/runtime/host/remote-actor-join-receiver.ts +264 -0
- package/src/runtime/host/remote-actor-packet-target-store.ts +244 -0
- package/src/runtime/host/remote-bound-session-relay.ts +900 -0
- package/src/runtime/host/route-mesh-runtime-options.ts +46 -0
- package/src/runtime/host/route-mesh-runtime.ts +891 -0
- package/src/runtime/host/runtime-shutdown.ts +101 -0
- package/src/runtime/host/service-relocation-control.ts +28 -0
- package/src/runtime/host/service-relocation-host-runtime.ts +5817 -0
- package/src/runtime/host/spot-address-transport.ts +997 -0
- package/src/runtime/host/spot-node-runtime-options-factory.ts +82 -0
- package/src/runtime/host/spot-runtime-options-factory.ts +286 -0
- package/src/runtime/host/stateful-authority-route-runtime.ts +662 -0
- package/src/runtime/host/user-spot-creation-coordinator.ts +1176 -0
- package/src/runtime/locations/actor-location-claims.ts +426 -0
- package/src/runtime/locations/actor-session-route-claims.ts +64 -0
- package/src/runtime/locations/aggregate-inventory-store.ts +581 -0
- package/src/runtime/locations/authority-key-codec.ts +80 -0
- package/src/runtime/locations/auto-connect-loop.ts +131 -0
- package/src/runtime/locations/auto-connect-planner.ts +178 -0
- package/src/runtime/locations/auto-connect-reconciler.ts +425 -0
- package/src/runtime/locations/auto-connect-types.ts +62 -0
- package/src/runtime/locations/auto-connect.ts +4 -0
- package/src/runtime/locations/canonical-codec.ts +54 -0
- package/src/runtime/locations/domain-store-contract.ts +149 -0
- package/src/runtime/locations/in-memory-authority-store.ts +1172 -0
- package/src/runtime/locations/in-memory-location-store.ts +1467 -0
- package/src/runtime/locations/in-memory-provider-location-store.ts +213 -0
- package/src/runtime/locations/index.ts +11 -0
- package/src/runtime/locations/internal-location-contracts.ts +22 -0
- package/src/runtime/locations/internal-store-contracts.ts +90 -0
- package/src/runtime/locations/key-codec.ts +61 -0
- package/src/runtime/locations/lease-tracker.ts +221 -0
- package/src/runtime/locations/lifecycle-runtime.ts +44 -0
- package/src/runtime/locations/lifecycle.ts +272 -0
- package/src/runtime/locations/location-store-repository.ts +4211 -0
- package/src/runtime/locations/relocation-blob.ts +36 -0
- package/src/runtime/locations/resolvers.ts +1054 -0
- package/src/runtime/locations/runtime.ts +1126 -0
- package/src/runtime/locations/spot-location-claims.ts +435 -0
- package/src/runtime/messaging/creation-payload-codec.ts +59 -0
- package/src/runtime/messaging/framework-json-v1.ts +307 -0
- package/src/runtime/messaging/index.ts +1 -0
- package/src/runtime/messaging/packet-name.ts +94 -0
- package/src/runtime/messaging/payload-codec.ts +418 -0
- package/src/runtime/messaging/submission-result.ts +61 -0
- package/src/runtime/protocol/service_wire_pilot_codec.generated.ts +189 -0
- package/src/runtime/routing-id.ts +125 -0
- package/src/runtime/spots/formal-remote-actor-admission-registry.ts +418 -0
- package/src/runtime/spots/formal-remote-actor-transfer-registry.ts +147 -0
- package/src/runtime/spots/index.ts +3303 -0
- package/src/runtime/spots/spot-activation-registry.ts +335 -0
- package/src/runtime/spots/spot-activation-state.ts +414 -0
- package/src/runtime/spots/spot-activation.ts +1027 -0
- package/src/runtime/spots/spot-actor-admission-coordinator.ts +354 -0
- package/src/runtime/spots/spot-actor-join-dispatch.ts +303 -0
- package/src/runtime/spots/spot-actor-lifecycle-drain.ts +79 -0
- package/src/runtime/spots/spot-actor-membership.ts +266 -0
- package/src/runtime/spots/spot-actor-packet-dispatch.ts +593 -0
- package/src/runtime/spots/spot-actor-packet-drain.ts +328 -0
- package/src/runtime/spots/spot-actor-packet-relay-dispatch.ts +162 -0
- package/src/runtime/spots/spot-closing.ts +34 -0
- package/src/runtime/spots/spot-context.ts +259 -0
- package/src/runtime/spots/spot-entry-activation.ts +551 -0
- package/src/runtime/spots/spot-handle.ts +101 -0
- package/src/runtime/spots/spot-handler-registry.ts +273 -0
- package/src/runtime/spots/spot-lifecycle-metrics.ts +15 -0
- package/src/runtime/spots/spot-location-claim.ts +86 -0
- package/src/runtime/spots/spot-manager-internal-contracts.ts +11 -0
- package/src/runtime/spots/spot-manager-public.ts +361 -0
- package/src/runtime/spots/spot-native-actor-join-admission.ts +151 -0
- package/src/runtime/spots/spot-native-flags.ts +4 -0
- package/src/runtime/spots/spot-node-autoconnect.ts +325 -0
- package/src/runtime/spots/spot-node-runtime-manager.ts +1573 -0
- package/src/runtime/spots/spot-outbound.ts +761 -0
- package/src/runtime/spots/spot-provider.ts +36 -0
- package/src/runtime/spots/spot-publisher-transport.ts +69 -0
- package/src/runtime/spots/spot-remote-codec.ts +308 -0
- package/src/runtime/spots/spot-remote-route-codec.ts +284 -0
- package/src/runtime/spots/spot-route-packet-dispatch.ts +359 -0
- package/src/runtime/spots/spot-route-replies.ts +126 -0
- package/src/runtime/spots/spot-route-reply-wire.ts +15 -0
- package/src/runtime/spots/spot-routed-actor-admission.ts +351 -0
- package/src/runtime/spots/spot-routed-bound-session-dispatch.ts +132 -0
- package/src/runtime/spots/spot-routed-frame-dispatch.ts +250 -0
- package/src/runtime/spots/spot-routed-spot-packet-dispatch.ts +254 -0
- package/src/runtime/spots/spot-routing-internal.ts +33 -0
- package/src/runtime/spots/spot-runtime-ports.ts +196 -0
- package/src/runtime/spots/spot-serial-executor.ts +170 -0
- package/src/runtime/spots/spot-serial-turn-executor.ts +319 -0
- package/src/runtime/spots/spot-subscription-dispatch.ts +252 -0
- package/src/runtime/spots/spot-timer.ts +609 -0
- package/src/runtime/streams/actor-session-binding-registry.ts +1691 -0
- package/src/runtime/streams/actor-session-binding-runtime-owner.ts +78 -0
- package/src/runtime/streams/actor-session-lifecycle-coordinator.ts +20 -0
- package/src/runtime/streams/bound-actor-relay-sender.ts +275 -0
- package/src/runtime/streams/bound-session-response-target.ts +91 -0
- package/src/runtime/streams/bound-session-service.ts +500 -0
- package/src/runtime/streams/index.ts +706 -0
- package/src/runtime/streams/managed-stream.ts +509 -0
- package/src/runtime/streams/native-fallback-bound-session.ts +321 -0
- package/src/runtime/streams/protocol.ts +291 -0
- package/src/runtime/streams/session-actor-coordinator.ts +605 -0
- package/src/runtime/streams/session-calls.ts +221 -0
- package/src/runtime/streams/session-context.ts +609 -0
- package/src/runtime/streams/session-local-actors.ts +30 -0
- package/src/runtime/streams/session-provider.ts +50 -0
- package/src/runtime/streams/session-requests.ts +109 -0
- package/src/runtime/streams/session-serial-executor.ts +97 -0
- package/src/runtime/streams/stream-binding-runtime-ports.ts +106 -0
- package/src/runtime/streams/stream-frame-factory.ts +255 -0
- package/src/runtime/streams/stream-message-utils.ts +89 -0
- package/src/runtime/streams/stream-session-runtime.ts +1420 -0
- package/src/runtime/workers/index.ts +580 -0
- package/tsconfig.json +17 -0
|
@@ -0,0 +1,3492 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ZLinkFrameworkInternalErrorKind,
|
|
3
|
+
createInternalFrameworkException,
|
|
4
|
+
internalFrameworkWireReply
|
|
5
|
+
} from '../framework-errors-internal';
|
|
6
|
+
import { randomBytes, randomUUID } from 'node:crypto';
|
|
7
|
+
import { ZLinkBufferMessage as RuntimeMessage } from '../backend/runtime-message';
|
|
8
|
+
import {
|
|
9
|
+
RequestResult,
|
|
10
|
+
SubmitResult,
|
|
11
|
+
type ZLinkBackendMessageLike as MessageLike
|
|
12
|
+
} from '../backend/runtime-values';
|
|
13
|
+
import {
|
|
14
|
+
OperationKind,
|
|
15
|
+
ReceiveKind,
|
|
16
|
+
type ReadyRecord,
|
|
17
|
+
type ReceiveRecord
|
|
18
|
+
} from '../foundation/service-runtime-contracts';
|
|
19
|
+
import type { ServiceMessageFollowRecord } from '../foundation/service-stateful-wire-codec';
|
|
20
|
+
import {
|
|
21
|
+
runtimeAcceptsWork,
|
|
22
|
+
runtimeStateIsReady
|
|
23
|
+
} from '../foundation/runtime-state-projections';
|
|
24
|
+
import { createDeadlineExceededError, isDeadlineExceededError } from '../abort';
|
|
25
|
+
import {
|
|
26
|
+
meshActorSessionNodeAdapter,
|
|
27
|
+
ZLinkNodeBackendAdapterFactory
|
|
28
|
+
} from '../backend';
|
|
29
|
+
import type {
|
|
30
|
+
ZLinkBackendAdapterFactory,
|
|
31
|
+
ZLinkBackendContext,
|
|
32
|
+
ZLinkBackendMeshNode
|
|
33
|
+
} from '../backend';
|
|
34
|
+
|
|
35
|
+
const LEGACY_MESH_SEND_TIMEOUT_MS = 1000;
|
|
36
|
+
import type { ZLinkFrameworkRegistration } from '../configuration';
|
|
37
|
+
import type {
|
|
38
|
+
ActorRef,
|
|
39
|
+
RoutingId,
|
|
40
|
+
ZLinkMeshNodeDescriptor,
|
|
41
|
+
ZLinkClientServerRuntime,
|
|
42
|
+
ZLinkFanoutRuntime,
|
|
43
|
+
ZLinkFrameworkRuntime,
|
|
44
|
+
ZLinkFrameworkLifecycleOptions,
|
|
45
|
+
ZLinkFrameworkRelocationOptions,
|
|
46
|
+
ZLinkFrameworkRelocationResult,
|
|
47
|
+
ZLinkObservedStatus,
|
|
48
|
+
ZLinkFrameworkRuntimeStatus,
|
|
49
|
+
ZLinkFrameworkTerminationResult,
|
|
50
|
+
ZLinkRouteMeshRuntime
|
|
51
|
+
} from '../../contracts';
|
|
52
|
+
import type {
|
|
53
|
+
ZLinkLocationOwnerToken
|
|
54
|
+
} from '../../contracts/Locations';
|
|
55
|
+
import type { ZLinkProviderResolver } from '../../contracts/Common/ZLinkProviderResolver';
|
|
56
|
+
import type { Type } from '../../contracts/Common/CoreTypes';
|
|
57
|
+
import type { ZLinkRuntimeEventPublisher } from '../diagnostics';
|
|
58
|
+
import type { ZLinkSpotRouteResolver } from '../spots/spot-routing-internal';
|
|
59
|
+
import {
|
|
60
|
+
ZLinkFrameworkRelocationMode,
|
|
61
|
+
ZLinkFrameworkRelocationOutcome,
|
|
62
|
+
ZLinkFrameworkRelocationReason,
|
|
63
|
+
ZLinkFrameworkRuntimeState,
|
|
64
|
+
ZLinkFrameworkTerminationOutcome,
|
|
65
|
+
ZLinkFrameworkTerminationReason,
|
|
66
|
+
ZLinkObjectRole,
|
|
67
|
+
ZLinkPeerState,
|
|
68
|
+
ZLinkSpotKind,
|
|
69
|
+
zlinkMessageMetadata,
|
|
70
|
+
ZLinkSpotCreateState
|
|
71
|
+
} from '../../contracts';
|
|
72
|
+
import { ZLinkSubmitStatus } from '../messaging/submission-result';
|
|
73
|
+
import {
|
|
74
|
+
ZLinkRuntimeMessageFlowOutcome as ZLinkMessageFlowOutcome,
|
|
75
|
+
ZLinkDispatchErrorSurface,
|
|
76
|
+
ZLinkDispatchMessageKind
|
|
77
|
+
} from '../../contracts/Dispatch/ZLinkDispatchOptions';
|
|
78
|
+
import type { ZLinkMessageFlowControl, ZLinkMessageFlowLogMode } from '../../contracts';
|
|
79
|
+
import { requireMessageFlowLogMode } from '../../contracts/Configuration/DiagnosticsValidation';
|
|
80
|
+
import {
|
|
81
|
+
DefaultZLinkChannelRuntimeOptions,
|
|
82
|
+
ZLinkDispatchErrorReporter,
|
|
83
|
+
ZLinkChannelRuntimeManager,
|
|
84
|
+
ZLinkRuntimeRouteTransport,
|
|
85
|
+
type ZLinkDispatchErrorSink
|
|
86
|
+
} from '../channels';
|
|
87
|
+
import {
|
|
88
|
+
decodeChannelEnvelope,
|
|
89
|
+
decodeChannelPayload,
|
|
90
|
+
encodeChannelErrorReplyParts,
|
|
91
|
+
encodeChannelReplyParts
|
|
92
|
+
} from '../channels/channel-envelope';
|
|
93
|
+
import {
|
|
94
|
+
ZLINK_REMOTE_ACTOR_PACKET_RELAY_PACKET
|
|
95
|
+
} from '../actors';
|
|
96
|
+
import {
|
|
97
|
+
ZLINK_INTERNAL_ACTOR_TRANSPORT_DELIVERY_GATE,
|
|
98
|
+
type ZLinkInternalActorTransportDeliveryGate
|
|
99
|
+
} from '../actors/actor-transport-delivery-gate';
|
|
100
|
+
import {
|
|
101
|
+
ZLINK_INTERNAL_APPLICATION_JOB_QUEUE_HANDLER_START_GATE,
|
|
102
|
+
type ZLinkInternalApplicationJobQueueHandlerStartGate
|
|
103
|
+
} from '../application-jobs/application-job-queue-handler-start-gate';
|
|
104
|
+
import {
|
|
105
|
+
ZLinkFrameworkExecutionState,
|
|
106
|
+
ZLinkRuntimeTaskErrorSink
|
|
107
|
+
} from '../execution';
|
|
108
|
+
import {
|
|
109
|
+
createDiagnosticsContext,
|
|
110
|
+
createInboundFlow,
|
|
111
|
+
currentOrCreateFlow,
|
|
112
|
+
DefaultZLinkRuntimeEventPublisher,
|
|
113
|
+
flowIfEnabled,
|
|
114
|
+
runWithFlow,
|
|
115
|
+
type ZLinkDiagnosticsContext,
|
|
116
|
+
type ZLinkMessageFlowModeCell,
|
|
117
|
+
type ZLinkRuntimeMetricMeshSnapshot,
|
|
118
|
+
ZLinkRuntimeMetrics
|
|
119
|
+
} from '../diagnostics';
|
|
120
|
+
import {
|
|
121
|
+
ZLinkClientServerRuntimeProjection,
|
|
122
|
+
ZLinkFanoutRuntimeProjection
|
|
123
|
+
} from '../diagnostics/topology-runtime-projections';
|
|
124
|
+
import { RuntimeEventQueue } from '../diagnostics/runtime-observation-queue';
|
|
125
|
+
import {
|
|
126
|
+
DefaultZLinkSpotManager,
|
|
127
|
+
ZLinkPublicSpotManager,
|
|
128
|
+
ZLinkRuntimeSpotPublisherTransport,
|
|
129
|
+
ZLinkSpotNodeRuntimeManager,
|
|
130
|
+
type ZLinkDetachedTaskRunner,
|
|
131
|
+
type ZLinkSpotManagerOptions
|
|
132
|
+
} from '../spots';
|
|
133
|
+
import type {
|
|
134
|
+
DefaultZLinkActorManager,
|
|
135
|
+
ZLinkActorManagerOptions
|
|
136
|
+
} from '../actors';
|
|
137
|
+
import {
|
|
138
|
+
messageFollowOwnerNodeRid,
|
|
139
|
+
ownerFence
|
|
140
|
+
} from '../actors/actor-message-follow-context';
|
|
141
|
+
import {
|
|
142
|
+
DefaultZLinkActorClient,
|
|
143
|
+
ZLinkActorHandoffCoordinator,
|
|
144
|
+
ZLinkActorTransferRegistry,
|
|
145
|
+
decodeRemoteActorSourceLeaveTerminal,
|
|
146
|
+
isActorAuthorityPayload,
|
|
147
|
+
publishInitialActorAuthority,
|
|
148
|
+
rewriteActorAuthorityOwner
|
|
149
|
+
} from '../actors';
|
|
150
|
+
import {
|
|
151
|
+
DefaultZLinkBoundSessionFactory,
|
|
152
|
+
type DefaultZLinkBoundSession,
|
|
153
|
+
type ZLinkStreamPayloadCodec,
|
|
154
|
+
ZLinkStreamBindingRuntime,
|
|
155
|
+
ZLinkStreamRuntimeManager
|
|
156
|
+
} from '../streams';
|
|
157
|
+
import {
|
|
158
|
+
ZLinkOwnerCleanupError,
|
|
159
|
+
ZLinkAuthoritySpotRouteResolver,
|
|
160
|
+
type ZLinkLocationRuntime,
|
|
161
|
+
type ZLinkStoreLocationResolvers
|
|
162
|
+
} from '../locations';
|
|
163
|
+
import {
|
|
164
|
+
zlinkDefaultLocationOptions,
|
|
165
|
+
type ZLinkLocationRuntimeQuery
|
|
166
|
+
} from '../../contracts/Locations';
|
|
167
|
+
import { ZLinkActorRuntimeOptionsFactory } from './actor-runtime-options-factory';
|
|
168
|
+
import { ZLinkActorTransferRuntime } from './actor-transfer-runtime';
|
|
169
|
+
import { ZLinkActorTransferAuthorityRuntime } from './actor-transfer-authority-runtime';
|
|
170
|
+
import { ZLinkEntryActorRuntimeService } from './entry-actor-runtime';
|
|
171
|
+
import { ZLinkLocationRuntimeOwner } from './location-runtime-owner';
|
|
172
|
+
import { MeshRouterResolver } from './mesh-router-resolver';
|
|
173
|
+
import { ZLinkBoundSessionRelay } from './bound-session-relay';
|
|
174
|
+
import {
|
|
175
|
+
decodeRoutingId,
|
|
176
|
+
encodeRoutingIdStorageHex,
|
|
177
|
+
routingIdsEqual
|
|
178
|
+
} from '../routing-id';
|
|
179
|
+
import {
|
|
180
|
+
rewriteServiceAuthorityOwner
|
|
181
|
+
} from '../foundation/service-authority-payload-codec';
|
|
182
|
+
import {
|
|
183
|
+
replaceServiceRelocationAuthorityApplicationPayload,
|
|
184
|
+
serviceRelocationAuthorityApplicationPayload
|
|
185
|
+
} from '../foundation/service-relocation-runtime';
|
|
186
|
+
import { ZLinkSpotRuntimeOptionsFactory } from './spot-runtime-options-factory';
|
|
187
|
+
import { ZLinkChannelRuntimeOptionsFactory } from './channel-runtime-options-factory';
|
|
188
|
+
import { ZLinkSpotNodeRuntimeOptionsFactory } from './spot-node-runtime-options-factory';
|
|
189
|
+
import { rollbackRuntimeStart, stopRuntimeParts } from './runtime-shutdown';
|
|
190
|
+
import { ZLinkRuntimeAdmissionGate } from '../admission';
|
|
191
|
+
import {
|
|
192
|
+
ZLinkRetiringRollbackError,
|
|
193
|
+
ZLinkRouteMeshRuntimeCoordinator
|
|
194
|
+
} from './route-mesh-runtime';
|
|
195
|
+
import { ZLinkConfigurationException } from '../../contracts/Configuration/ConfigurationException';
|
|
196
|
+
import { ZLinkStatefulAuthorityRouteRuntime } from './stateful-authority-route-runtime';
|
|
197
|
+
import { ZLinkInstanceActivationAuthority } from './instance-activation-authority';
|
|
198
|
+
import type {
|
|
199
|
+
ServiceAsyncInstanceActivationAuthority,
|
|
200
|
+
ServiceInstanceApplicationLifecycle
|
|
201
|
+
} from '../foundation/service-stateful-runtime';
|
|
202
|
+
import {
|
|
203
|
+
hasObjectClientCapability,
|
|
204
|
+
ZLinkHostSpotAddressTransport
|
|
205
|
+
} from './spot-address-transport';
|
|
206
|
+
import { ZLinkUserSpotCreationCoordinator } from './user-spot-creation-coordinator';
|
|
207
|
+
import { ZLinkActorPlacementCoordinator } from './actor-placement-coordinator';
|
|
208
|
+
import {
|
|
209
|
+
decodeFrameworkPayloadMessage,
|
|
210
|
+
encodeFrameworkPayloadMessage
|
|
211
|
+
} from '../messaging/payload-codec';
|
|
212
|
+
import {
|
|
213
|
+
decodeFrameworkCreationPayload,
|
|
214
|
+
encodeFrameworkCreationPayload
|
|
215
|
+
} from '../messaging/creation-payload-codec';
|
|
216
|
+
import { DefaultZLinkRouteMeshRuntimeOptions } from './route-mesh-runtime-options';
|
|
217
|
+
import {
|
|
218
|
+
ZLinkHostServiceRelocationRuntime,
|
|
219
|
+
ZLinkRelocationStateIncompatibleError
|
|
220
|
+
} from './service-relocation-host-runtime';
|
|
221
|
+
import {
|
|
222
|
+
ApplicationJobQueue,
|
|
223
|
+
nodeEffectiveProcessorCount,
|
|
224
|
+
resolveApplicationJobQueueConfiguration
|
|
225
|
+
} from './application-job-queue';
|
|
226
|
+
import { runWithApplicationJobPermit } from '../application-jobs/application-job-queue-scope';
|
|
227
|
+
import { HostCapacityStatusProjection } from './host-capacity-status';
|
|
228
|
+
|
|
229
|
+
export interface ZLinkFrameworkRuntimeLifecycle {
|
|
230
|
+
readonly isStarted: boolean;
|
|
231
|
+
readonly locationRuntimeQuery?: ZLinkLocationRuntimeQuery;
|
|
232
|
+
start(): Promise<void>;
|
|
233
|
+
stop(): Promise<void>;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
export interface ZLinkFrameworkRuntimeHostOptions {
|
|
237
|
+
readonly registration: ZLinkFrameworkRegistration;
|
|
238
|
+
readonly lifecycleSink?: string[];
|
|
239
|
+
readonly providerResolver?: ZLinkProviderResolver;
|
|
240
|
+
readonly runtimeEventPublisher?: ZLinkRuntimeEventPublisher;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
export class ZLinkFrameworkRuntimeHost implements
|
|
244
|
+
ZLinkFrameworkRuntimeLifecycle,
|
|
245
|
+
ZLinkFrameworkRuntime,
|
|
246
|
+
ZLinkMessageFlowControl {
|
|
247
|
+
private readonly backendAdapterFactory: ZLinkBackendAdapterFactory;
|
|
248
|
+
private readonly lifecycleSink?: string[];
|
|
249
|
+
private executionState?: ZLinkFrameworkExecutionState;
|
|
250
|
+
private runtimeState = ZLinkFrameworkRuntimeState.Preparing;
|
|
251
|
+
private runtimeSequence = 0n;
|
|
252
|
+
private readonly runtimeObservationSource = Symbol('zlink.framework-runtime');
|
|
253
|
+
private runtimeDeadline?: Date;
|
|
254
|
+
private runtimeRelocationResult?: ZLinkFrameworkRelocationResult;
|
|
255
|
+
private runtimeTerminationResult?: ZLinkFrameworkTerminationResult;
|
|
256
|
+
private relocationOperation?: Promise<ZLinkFrameworkRelocationResult>;
|
|
257
|
+
private relocationStopStarting?: AbortController;
|
|
258
|
+
private relocationOperationKey?: string;
|
|
259
|
+
private relocationOperationStartedAt?: number;
|
|
260
|
+
private shutdownOperation?: Promise<ZLinkFrameworkTerminationResult>;
|
|
261
|
+
private shutdownOperationStartedAt?: number;
|
|
262
|
+
private relocationTargetApplicationVersion?: bigint;
|
|
263
|
+
private readonly runtimeObservers = new Set<RuntimeEventQueue<ZLinkFrameworkRuntimeStatus>>();
|
|
264
|
+
private channelRuntime?: ZLinkChannelRuntimeManager;
|
|
265
|
+
private spotNodeRuntime?: ZLinkSpotNodeRuntimeManager;
|
|
266
|
+
private streamRuntime?: ZLinkStreamRuntimeManager;
|
|
267
|
+
private statefulAuthorityRoutes?: ZLinkStatefulAuthorityRouteRuntime;
|
|
268
|
+
private readonly locationOwner: ZLinkLocationRuntimeOwner;
|
|
269
|
+
private readonly meshRouters: MeshRouterResolver;
|
|
270
|
+
private readonly boundSessionRelay: ZLinkBoundSessionRelay;
|
|
271
|
+
private readonly actorHandoff: ZLinkActorHandoffCoordinator;
|
|
272
|
+
private readonly actorTransferRegistry: ZLinkActorTransferRegistry;
|
|
273
|
+
private readonly actorTransferRuntime: ZLinkActorTransferRuntime;
|
|
274
|
+
private readonly actorTransferAuthorityRuntime: ZLinkActorTransferAuthorityRuntime;
|
|
275
|
+
private readonly serviceRelocation: ZLinkHostServiceRelocationRuntime;
|
|
276
|
+
private readonly entryActorRuntime: ZLinkEntryActorRuntimeService;
|
|
277
|
+
private actorManager?: DefaultZLinkActorManager;
|
|
278
|
+
private actorPlacement?: ZLinkActorPlacementCoordinator;
|
|
279
|
+
private spotManager?: DefaultZLinkSpotManager;
|
|
280
|
+
private ownerLeaseRecoveryRuntime?: ZLinkLocationRuntime;
|
|
281
|
+
private ownerLeaseRecoveryHandler?: () => void;
|
|
282
|
+
private ownerLeaseFailureHandler?: () => void;
|
|
283
|
+
private registerUserSpotHandlers?: (runtime: ZLinkSpotNodeRuntimeManager) => void;
|
|
284
|
+
private readonly destroyedActorRefs = new Map<string, ActorRef>();
|
|
285
|
+
private readonly runtimeEventPublisher: ZLinkRuntimeEventPublisher;
|
|
286
|
+
private readonly metrics: ZLinkRuntimeMetrics;
|
|
287
|
+
private readonly applicationJobQueue: ApplicationJobQueue;
|
|
288
|
+
private readonly capacityStatus: HostCapacityStatusProjection;
|
|
289
|
+
private readonly metricRegistrations: import('../diagnostics').ZLinkRuntimeMetricRegistration[] = [];
|
|
290
|
+
private readonly admission = new ZLinkRuntimeAdmissionGate();
|
|
291
|
+
private cachedLocationSpotRouteResolver?: ZLinkSpotRouteResolver;
|
|
292
|
+
private actorClientLocationResolver?: ZLinkStoreLocationResolvers;
|
|
293
|
+
// Shared, runtime-mutable message-flow mode cell — installed once so
|
|
294
|
+
// setMessageFlowMode flips every surface live. Seeded from config at start().
|
|
295
|
+
private readonly messageFlowModeCell: ZLinkMessageFlowModeCell = {
|
|
296
|
+
mode: 'errors'
|
|
297
|
+
};
|
|
298
|
+
private readonly dispatchErrorReporters = new WeakMap<ZLinkDispatchErrorSink, ZLinkDispatchErrorReporter>();
|
|
299
|
+
private readonly runtimeOrPreStartErrorSink: ZLinkDispatchErrorSink = {
|
|
300
|
+
reportRuntimeTaskException: (taskName: string, error: unknown) =>
|
|
301
|
+
(this.errorSink ?? this.preStartErrorSink).reportRuntimeTaskException(taskName, error)
|
|
302
|
+
};
|
|
303
|
+
private cachedDiagnosticsContext?: ZLinkDiagnosticsContext;
|
|
304
|
+
private readonly preStartErrorSink = new ZLinkRuntimeTaskErrorSink();
|
|
305
|
+
readonly channelTransport = () => this.channelRuntime;
|
|
306
|
+
readonly channelRuntimeOptions = new DefaultZLinkChannelRuntimeOptions(() => this.channelRuntime);
|
|
307
|
+
readonly routeMeshRuntimeOptions =
|
|
308
|
+
new DefaultZLinkRouteMeshRuntimeOptions(() => this.spotNodeRuntime);
|
|
309
|
+
readonly routeTransport: ZLinkRuntimeRouteTransport;
|
|
310
|
+
readonly spotAddressTransport: ZLinkHostSpotAddressTransport;
|
|
311
|
+
readonly spotPublisherTransport = new ZLinkRuntimeSpotPublisherTransport(() => this.spotNodeRuntime);
|
|
312
|
+
readonly streamBindingRuntime: ZLinkStreamBindingRuntime;
|
|
313
|
+
readonly boundSessionFactory: DefaultZLinkBoundSessionFactory;
|
|
314
|
+
readonly spotRouterChannelIdForMesh: (meshName: string) => string;
|
|
315
|
+
readonly routeMeshRuntime: ZLinkRouteMeshRuntime;
|
|
316
|
+
readonly clientServerRuntime: ZLinkClientServerRuntime;
|
|
317
|
+
readonly fanoutRuntime: ZLinkFanoutRuntime;
|
|
318
|
+
private readonly routeMeshCoordinator: ZLinkRouteMeshRuntimeCoordinator;
|
|
319
|
+
constructor(readonly options: ZLinkFrameworkRuntimeHostOptions, internalOptions?: unknown) {
|
|
320
|
+
this.backendAdapterFactory = resolveBackendAdapterFactory(internalOptions);
|
|
321
|
+
this.lifecycleSink = options.lifecycleSink;
|
|
322
|
+
this.runtimeEventPublisher = options.runtimeEventPublisher ?? new DefaultZLinkRuntimeEventPublisher();
|
|
323
|
+
this.metrics = new ZLinkRuntimeMetrics(options.registration.metrics?.meterProvider);
|
|
324
|
+
this.applicationJobQueue = new ApplicationJobQueue(
|
|
325
|
+
resolveApplicationJobQueueConfiguration(
|
|
326
|
+
options.registration.applicationJobQueue,
|
|
327
|
+
() => nodeEffectiveProcessorCount(options.registration.worker?.maxThreads)
|
|
328
|
+
),
|
|
329
|
+
undefined,
|
|
330
|
+
() => {
|
|
331
|
+
try {
|
|
332
|
+
return this.options.providerResolver?.get?.(
|
|
333
|
+
ZLINK_INTERNAL_APPLICATION_JOB_QUEUE_HANDLER_START_GATE as unknown as
|
|
334
|
+
Type<ZLinkInternalApplicationJobQueueHandlerStartGate>
|
|
335
|
+
)?.shouldHoldPermitBeforeHandler() === true;
|
|
336
|
+
} catch {
|
|
337
|
+
return false;
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
);
|
|
341
|
+
this.capacityStatus = new HostCapacityStatusProjection(
|
|
342
|
+
options.registration.coreHwm,
|
|
343
|
+
this.applicationJobQueue
|
|
344
|
+
);
|
|
345
|
+
this.clientServerRuntime = new ZLinkClientServerRuntimeProjection(
|
|
346
|
+
() => this.channelRuntime,
|
|
347
|
+
() => this.runtimeState
|
|
348
|
+
);
|
|
349
|
+
this.fanoutRuntime = new ZLinkFanoutRuntimeProjection(
|
|
350
|
+
() => this.channelRuntime,
|
|
351
|
+
() => this.runtimeState
|
|
352
|
+
);
|
|
353
|
+
this.meshRouters = new MeshRouterResolver(options.registration);
|
|
354
|
+
this.spotRouterChannelIdForMesh = this.meshRouters.spotRouterChannelIdByMesh();
|
|
355
|
+
const sendTimeoutMsForSpotMesh = (meshName: string): number =>
|
|
356
|
+
options.registration.spotNodes.get(meshName)?.router?.sendTimeoutMs
|
|
357
|
+
?? LEGACY_MESH_SEND_TIMEOUT_MS;
|
|
358
|
+
const sendTimeoutMsForSpotRouteChannel = (routeChannelId: string): number => {
|
|
359
|
+
const routeChannel = options.registration.routeChannelOptions.get(routeChannelId);
|
|
360
|
+
if (routeChannel !== undefined) {
|
|
361
|
+
return routeChannel.sendTimeoutMs ?? LEGACY_MESH_SEND_TIMEOUT_MS;
|
|
362
|
+
}
|
|
363
|
+
return sendTimeoutMsForSpotMesh(routeChannelId);
|
|
364
|
+
};
|
|
365
|
+
const defaultSpotSendTimeoutMs = Math.max(
|
|
366
|
+
LEGACY_MESH_SEND_TIMEOUT_MS,
|
|
367
|
+
...[...options.registration.spotNodes.values()].map(node =>
|
|
368
|
+
node.router?.sendTimeoutMs ?? LEGACY_MESH_SEND_TIMEOUT_MS
|
|
369
|
+
),
|
|
370
|
+
...[...options.registration.routeChannelOptions.values()].map(route =>
|
|
371
|
+
route.sendTimeoutMs ?? LEGACY_MESH_SEND_TIMEOUT_MS
|
|
372
|
+
)
|
|
373
|
+
);
|
|
374
|
+
this.routeTransport = new ZLinkRuntimeRouteTransport(
|
|
375
|
+
() => this.channelRuntime,
|
|
376
|
+
(routerChannelId) => this.meshRouters.canUseRouterChannel(routerChannelId),
|
|
377
|
+
() => this.spotNodeRuntime,
|
|
378
|
+
{ serializers: options.registration.messageSerializers },
|
|
379
|
+
(meshName, targetNodeRid) =>
|
|
380
|
+
this.meshRouters.classifyManualNodeTarget(meshName, targetNodeRid),
|
|
381
|
+
(meshName, sourceNodeRid, parts) =>
|
|
382
|
+
this.submitLocalMeshRoute(meshName, sourceNodeRid, parts),
|
|
383
|
+
this.metrics
|
|
384
|
+
);
|
|
385
|
+
this.spotAddressTransport = new ZLinkHostSpotAddressTransport({
|
|
386
|
+
resolver: () => this.createLocationSpotRouteResolver(),
|
|
387
|
+
routed: this.routeTransport,
|
|
388
|
+
meshNames: () => [...this.options.registration.spotNodes]
|
|
389
|
+
.filter(([, node]) => hasObjectClientCapability(node.objectRole))
|
|
390
|
+
.map(([meshName]) => meshName),
|
|
391
|
+
isMeshConfigured: (meshName) => this.options.registration.spotNodes.has(meshName),
|
|
392
|
+
meshNode: (meshName) => this.spotNodeRuntime?.meshNode(meshName),
|
|
393
|
+
completions: (meshName) => this.spotNodeRuntime?.meshCompletionTable(meshName),
|
|
394
|
+
codecs: { serializers: options.registration.messageSerializers },
|
|
395
|
+
defaultRequestTimeoutMs: options.registration.requestTimeoutMs ?? 30_000,
|
|
396
|
+
defaultSendTimeoutMs: defaultSpotSendTimeoutMs,
|
|
397
|
+
sendTimeoutMsForMesh: sendTimeoutMsForSpotMesh,
|
|
398
|
+
sendTimeoutMsForRouteChannel: sendTimeoutMsForSpotRouteChannel,
|
|
399
|
+
dispatchErrors: this.createDispatchErrorReporter(this.runtimeOrPreStartErrorSink)
|
|
400
|
+
});
|
|
401
|
+
this.locationOwner = new ZLinkLocationRuntimeOwner({
|
|
402
|
+
registration: options.registration,
|
|
403
|
+
runtimeEventPublisher: this.runtimeEventPublisher,
|
|
404
|
+
metrics: this.metrics,
|
|
405
|
+
fallbackNodeRid: `node-${randomUUID()}`,
|
|
406
|
+
rewriteAuthorityPayloadForOwner
|
|
407
|
+
});
|
|
408
|
+
this.streamBindingRuntime = new ZLinkStreamBindingRuntime({
|
|
409
|
+
streamPayloadCodec: resolveStreamPayloadCodec(options.registration),
|
|
410
|
+
streamCompression: options.registration.streamCompression,
|
|
411
|
+
messageSerializers: options.registration.messageSerializers,
|
|
412
|
+
sessionRelocationSealTimeoutMs:
|
|
413
|
+
options.registration.locations.options.sessionRelocationSealTimeoutMs
|
|
414
|
+
?? zlinkDefaultLocationOptions.sessionRelocationSealTimeoutMs,
|
|
415
|
+
metrics: this.metrics,
|
|
416
|
+
flowCreationEnabled: () => this.flowCreationEnabled(),
|
|
417
|
+
errorSink: () => this.errorSink ?? this.preStartErrorSink,
|
|
418
|
+
nativeActorNodeProvider: () => this.spotNodeRuntime?.primaryMeshNode,
|
|
419
|
+
nativeActorMeshNameProvider: () => this.meshRouters.primaryMeshName(),
|
|
420
|
+
actorAuthorityFenceResolver: async (actorId, signal) => {
|
|
421
|
+
const resolution = await this.createActorLocationResolver()
|
|
422
|
+
?.resolveDirectActorRoute(actorId, signal);
|
|
423
|
+
return resolution === undefined || resolution.kind !== 'ready'
|
|
424
|
+
? undefined
|
|
425
|
+
: {
|
|
426
|
+
authorityOwnerGeneration: resolution.route.authorityOwnerGeneration,
|
|
427
|
+
ownerLeaseGeneration: resolution.route.ownerLeaseGeneration,
|
|
428
|
+
ownerId: resolution.route.ownerId,
|
|
429
|
+
ownerNodeGeneration: resolution.route.ownerNodeGeneration,
|
|
430
|
+
authorityStoreVersion: resolution.route.authorityStoreVersion,
|
|
431
|
+
actorType: resolution.route.actorType
|
|
432
|
+
};
|
|
433
|
+
},
|
|
434
|
+
confirmRemoteActorSessionBinding: (actor, sessionRid, signal, options) => {
|
|
435
|
+
const sessionNode = this.spotNodeRuntime?.primaryMeshNode;
|
|
436
|
+
return sessionNode === undefined
|
|
437
|
+
? Promise.resolve()
|
|
438
|
+
: this.boundSessionRelay.actorPackets.confirmRemoteSessionBinding(
|
|
439
|
+
actor,
|
|
440
|
+
sessionNode.status().routingId as never,
|
|
441
|
+
sessionRid,
|
|
442
|
+
signal,
|
|
443
|
+
options
|
|
444
|
+
);
|
|
445
|
+
},
|
|
446
|
+
relay: (actor, header, payload, signal) =>
|
|
447
|
+
this.boundSessionRelay.actorPackets.relayActorPacket(actor, header, payload, signal),
|
|
448
|
+
notifyDisconnected: (actor, signal) =>
|
|
449
|
+
this.boundSessionRelay.actorPackets.notifyBoundActorDisconnected(actor, signal)
|
|
450
|
+
});
|
|
451
|
+
this.actorHandoff = new ZLinkActorHandoffCoordinator({
|
|
452
|
+
routedTransport: this.routeTransport,
|
|
453
|
+
messageFollowDurationMs: options.registration.locations.options.messageFollowDurationMs,
|
|
454
|
+
requestTimeoutMs: options.registration.requestTimeoutMs,
|
|
455
|
+
requestSource: (actorId) => {
|
|
456
|
+
const owner = this.locationOwner.currentRuntime?.currentOwnerToken;
|
|
457
|
+
const state = this.actorManager?.getState(actorId);
|
|
458
|
+
const current = state?.nativeActorRef;
|
|
459
|
+
const meshName = state?.meshName;
|
|
460
|
+
const node = meshName === undefined
|
|
461
|
+
? undefined
|
|
462
|
+
: this.spotNodeRuntime?.meshNode(meshName)?.status();
|
|
463
|
+
if (owner === undefined
|
|
464
|
+
|| state === undefined
|
|
465
|
+
|| current === undefined
|
|
466
|
+
|| meshName === undefined
|
|
467
|
+
|| node === undefined
|
|
468
|
+
|| state.locationGeneration === undefined
|
|
469
|
+
|| state.ownerLeaseGeneration === undefined
|
|
470
|
+
|| state.ownerLeaseGeneration !== owner.leaseGeneration
|
|
471
|
+
|| !routingIdsEqual(node.routingId, current.nodeRid)) {
|
|
472
|
+
throw new ZLinkConfigurationException(
|
|
473
|
+
`Actor '${actorId}' handoff requires a committed source owner fence.`
|
|
474
|
+
);
|
|
475
|
+
}
|
|
476
|
+
return {
|
|
477
|
+
meshName,
|
|
478
|
+
objectGeneration: current.generation,
|
|
479
|
+
ownerId: owner.ownerId,
|
|
480
|
+
ownerLeaseGeneration: state.ownerLeaseGeneration,
|
|
481
|
+
nodeRid: String(current.nodeRid),
|
|
482
|
+
nodeRidHex: encodeRoutingIdStorageHex(current.nodeRid),
|
|
483
|
+
nodeGeneration: node.lifecycleGeneration,
|
|
484
|
+
authorityOwnerGeneration: state.locationGeneration
|
|
485
|
+
};
|
|
486
|
+
},
|
|
487
|
+
validateReplySource: (source) => {
|
|
488
|
+
const owner = this.locationOwner.currentRuntime?.currentOwnerToken;
|
|
489
|
+
const node = this.spotNodeRuntime?.meshNode(source.meshName)?.status();
|
|
490
|
+
if (owner === undefined || node === undefined
|
|
491
|
+
|| owner.ownerId !== source.ownerId
|
|
492
|
+
|| owner.leaseGeneration !== source.ownerLeaseGeneration
|
|
493
|
+
|| node.lifecycleGeneration !== source.nodeGeneration) {
|
|
494
|
+
return false;
|
|
495
|
+
}
|
|
496
|
+
return routingIdsEqual(
|
|
497
|
+
node.routingId,
|
|
498
|
+
decodeRoutingId(source.nodeRid, source.nodeRidHex)
|
|
499
|
+
);
|
|
500
|
+
},
|
|
501
|
+
onMarker: (marker, actorId, index, context) => {
|
|
502
|
+
if (marker === 'message_follow_relay' && context !== undefined) {
|
|
503
|
+
this.options.providerResolver?.get?.(
|
|
504
|
+
ZLINK_INTERNAL_ACTOR_TRANSPORT_DELIVERY_GATE as unknown as
|
|
505
|
+
Type<ZLinkInternalActorTransportDeliveryGate>
|
|
506
|
+
)?.recordMessageFollowRelay?.(actorId, context);
|
|
507
|
+
}
|
|
508
|
+
if (marker === 'message_follow_route_removed') {
|
|
509
|
+
this.serviceRelocation.completeActorJoinSourceCleanup(actorId);
|
|
510
|
+
}
|
|
511
|
+
this.publishActorHandoffEvent({ marker, actorId, index });
|
|
512
|
+
},
|
|
513
|
+
onRequestFrame: (actorId, index, requestSeq, flags) => {
|
|
514
|
+
this.publishActorHandoffEvent({
|
|
515
|
+
marker: 'handoff_request_frame',
|
|
516
|
+
actorId,
|
|
517
|
+
index,
|
|
518
|
+
requestSeq: requestSeq?.toString(),
|
|
519
|
+
flags
|
|
520
|
+
});
|
|
521
|
+
},
|
|
522
|
+
onMessageFollowRelayed: async (
|
|
523
|
+
actorId,
|
|
524
|
+
targetActorRef,
|
|
525
|
+
context,
|
|
526
|
+
origin,
|
|
527
|
+
queuedMessages,
|
|
528
|
+
queuedBytes
|
|
529
|
+
) => {
|
|
530
|
+
try {
|
|
531
|
+
const objectGeneration = BigInt(context.objectGeneration);
|
|
532
|
+
if (targetActorRef.objectGeneration !== objectGeneration) {
|
|
533
|
+
throw new Error(
|
|
534
|
+
`Actor Message Follow changed object generation for '${actorId}'.`
|
|
535
|
+
);
|
|
536
|
+
}
|
|
537
|
+
const sent = await this.spotNodeRuntime?.sendMessageFollowNotification(
|
|
538
|
+
messageFollowOwnerNodeRid(context.sourceOwner),
|
|
539
|
+
origin.sourceNodeRid,
|
|
540
|
+
{
|
|
541
|
+
source: {
|
|
542
|
+
kind: 'actor',
|
|
543
|
+
actor: {
|
|
544
|
+
actorId,
|
|
545
|
+
generation: objectGeneration,
|
|
546
|
+
nodeRid: messageFollowOwnerNodeRid(context.sourceOwner)
|
|
547
|
+
},
|
|
548
|
+
targetNodeRid: messageFollowOwnerNodeRid(context.sourceOwner),
|
|
549
|
+
targetNodeGeneration: BigInt(context.sourceOwner.nodeGeneration),
|
|
550
|
+
authorityOwnerGeneration: BigInt(
|
|
551
|
+
context.sourceOwner.authorityOwnerGeneration
|
|
552
|
+
),
|
|
553
|
+
ownerLeaseGeneration: BigInt(context.sourceOwner.ownerLeaseGeneration)
|
|
554
|
+
},
|
|
555
|
+
target: {
|
|
556
|
+
kind: 'actor',
|
|
557
|
+
actor: {
|
|
558
|
+
actorId,
|
|
559
|
+
generation: objectGeneration,
|
|
560
|
+
nodeRid: messageFollowOwnerNodeRid(context.targetOwner)
|
|
561
|
+
},
|
|
562
|
+
targetNodeRid: messageFollowOwnerNodeRid(context.targetOwner),
|
|
563
|
+
targetNodeGeneration: BigInt(context.targetOwner.nodeGeneration),
|
|
564
|
+
authorityOwnerGeneration: BigInt(
|
|
565
|
+
context.targetOwner.authorityOwnerGeneration
|
|
566
|
+
),
|
|
567
|
+
ownerLeaseGeneration: BigInt(context.targetOwner.ownerLeaseGeneration)
|
|
568
|
+
},
|
|
569
|
+
hopCount: context.hopCount,
|
|
570
|
+
queuedMessages,
|
|
571
|
+
queuedBytes,
|
|
572
|
+
originalOperation: origin.originalOperation,
|
|
573
|
+
originalReplyRouteId: origin.originalReplyRouteId
|
|
574
|
+
}
|
|
575
|
+
);
|
|
576
|
+
if (sent !== true) {
|
|
577
|
+
throw new Error(
|
|
578
|
+
`Actor Message Follow source runtime '${context.sourceOwner.nodeRid}' is unavailable.`
|
|
579
|
+
);
|
|
580
|
+
}
|
|
581
|
+
return true;
|
|
582
|
+
} catch (error) {
|
|
583
|
+
this.runtimeOrPreStartErrorSink.reportRuntimeTaskException(
|
|
584
|
+
'actor Message Follow notification',
|
|
585
|
+
error
|
|
586
|
+
);
|
|
587
|
+
return false;
|
|
588
|
+
}
|
|
589
|
+
},
|
|
590
|
+
isStaleActorRef: (actorId, actorRef) => {
|
|
591
|
+
const state = this.actorManager?.getState(actorId);
|
|
592
|
+
const current = state?.nativeActorRef;
|
|
593
|
+
if (actorRef === undefined) return state?.remoteActorPacketTarget !== undefined;
|
|
594
|
+
return current !== undefined && (
|
|
595
|
+
current.generation !== actorRef.objectGeneration ||
|
|
596
|
+
!routingIdsEqual(current.nodeRid, actorRef.nodeRid)
|
|
597
|
+
);
|
|
598
|
+
},
|
|
599
|
+
isCurrentHandoffTarget: (actorId, spotId) => {
|
|
600
|
+
const currentSpotId = this.actorManager?.getState(actorId)?.spotId;
|
|
601
|
+
return currentSpotId !== undefined && String(currentSpotId) === spotId;
|
|
602
|
+
},
|
|
603
|
+
isCurrentActorRef: (actorId, actorRef) => {
|
|
604
|
+
const current = this.actorManager?.getState(actorId)?.nativeActorRef;
|
|
605
|
+
return current !== undefined
|
|
606
|
+
&& current.generation === actorRef.objectGeneration
|
|
607
|
+
&& routingIdsEqual(current.nodeRid, actorRef.nodeRid);
|
|
608
|
+
},
|
|
609
|
+
currentOwnerFence: (actorId) => {
|
|
610
|
+
const state = this.actorManager?.getState(actorId);
|
|
611
|
+
const current = state?.nativeActorRef;
|
|
612
|
+
const owner = this.locationOwner.currentRuntime?.currentOwnerToken;
|
|
613
|
+
const node = state?.meshName === undefined
|
|
614
|
+
? undefined
|
|
615
|
+
: this.spotNodeRuntime?.meshNode(state.meshName)?.status();
|
|
616
|
+
if (state === undefined || current === undefined || owner === undefined
|
|
617
|
+
|| node === undefined || state.locationGeneration === undefined
|
|
618
|
+
|| state.ownerLeaseGeneration === undefined
|
|
619
|
+
|| !routingIdsEqual(node.routingId, current.nodeRid)) {
|
|
620
|
+
return undefined;
|
|
621
|
+
}
|
|
622
|
+
return ownerFence({
|
|
623
|
+
ownerId: owner.ownerId,
|
|
624
|
+
ownerLeaseGeneration: state.ownerLeaseGeneration,
|
|
625
|
+
nodeRid: String(current.nodeRid),
|
|
626
|
+
nodeRidHex: encodeRoutingIdStorageHex(current.nodeRid),
|
|
627
|
+
nodeGeneration: node.lifecycleGeneration,
|
|
628
|
+
authorityOwnerGeneration: state.locationGeneration
|
|
629
|
+
});
|
|
630
|
+
}
|
|
631
|
+
});
|
|
632
|
+
this.actorTransferRegistry = new ZLinkActorTransferRegistry(
|
|
633
|
+
options.registration.spotNodes,
|
|
634
|
+
options.providerResolver,
|
|
635
|
+
options.registration.messageSerializers
|
|
636
|
+
);
|
|
637
|
+
this.boundSessionFactory = new DefaultZLinkBoundSessionFactory(this.streamBindingRuntime);
|
|
638
|
+
this.boundSessionRelay = new ZLinkBoundSessionRelay({
|
|
639
|
+
requestTimeoutMs: options.registration.requestTimeoutMs,
|
|
640
|
+
sessionRelocationSealTimeoutMs:
|
|
641
|
+
options.registration.locations.options.sessionRelocationSealTimeoutMs
|
|
642
|
+
?? zlinkDefaultLocationOptions.sessionRelocationSealTimeoutMs,
|
|
643
|
+
routeTransport: this.routeTransport,
|
|
644
|
+
streamBindingRuntime: () => this.streamBindingRuntime,
|
|
645
|
+
meshRouters: this.meshRouters,
|
|
646
|
+
actorManager: () => this.actorManager,
|
|
647
|
+
spotManager: () => this.spotManager,
|
|
648
|
+
spotNodeRuntime: () => this.spotNodeRuntime,
|
|
649
|
+
detachedTaskRunner: this.detachedTaskRunner(),
|
|
650
|
+
actorSessionNode: (actorId) => {
|
|
651
|
+
const state = this.actorManager?.getState(actorId);
|
|
652
|
+
const meshName = state?.meshName
|
|
653
|
+
?? (state?.actorType === undefined
|
|
654
|
+
? undefined
|
|
655
|
+
: this.meshRouters.actorMeshName(state.actorType));
|
|
656
|
+
const runtime = this.spotNodeRuntime;
|
|
657
|
+
const node = meshName === undefined || typeof runtime?.meshNode !== 'function'
|
|
658
|
+
? runtime?.primaryMeshNode
|
|
659
|
+
: runtime.meshNode(meshName);
|
|
660
|
+
return node === undefined
|
|
661
|
+
? undefined
|
|
662
|
+
: meshActorSessionNodeAdapter(
|
|
663
|
+
node,
|
|
664
|
+
meshName === undefined || typeof runtime?.meshCompletionTable !== 'function'
|
|
665
|
+
? runtime?.primaryMeshCompletions
|
|
666
|
+
: runtime.meshCompletionTable(meshName)
|
|
667
|
+
);
|
|
668
|
+
},
|
|
669
|
+
actorLocationResolver: () => this.createActorLocationResolver(),
|
|
670
|
+
authorityStore: () => this.locationOwner.currentStores?.locationStore,
|
|
671
|
+
flowCreationEnabled: () => this.flowCreationEnabled(),
|
|
672
|
+
destroyedActorRefs: this.destroyedActorRefs,
|
|
673
|
+
errorSink: () => this.errorSink ?? this.preStartErrorSink,
|
|
674
|
+
boundSessionFactory: (actorId) => {
|
|
675
|
+
const factory = this.createActorManagerOptions().boundSessionFactory;
|
|
676
|
+
if (factory === undefined) {
|
|
677
|
+
throw new Error('Bound session factory is not configured.');
|
|
678
|
+
}
|
|
679
|
+
return factory(actorId) as DefaultZLinkBoundSession;
|
|
680
|
+
}
|
|
681
|
+
});
|
|
682
|
+
this.entryActorRuntime = new ZLinkEntryActorRuntimeService({
|
|
683
|
+
actorManager: () => this.actorManager,
|
|
684
|
+
spotManager: () => this.spotManager,
|
|
685
|
+
spotNodeRuntime: () => this.spotNodeRuntime,
|
|
686
|
+
streamBindingRuntime: this.streamBindingRuntime,
|
|
687
|
+
boundSessionRelay: this.boundSessionRelay,
|
|
688
|
+
reportPostCommitError: (error) =>
|
|
689
|
+
(this.errorSink ?? this.preStartErrorSink).reportRuntimeTaskException('entry actor commit', error),
|
|
690
|
+
shutdownSignal: () => this.executionState?.abortController.signal
|
|
691
|
+
});
|
|
692
|
+
this.actorTransferRuntime = new ZLinkActorTransferRuntime({
|
|
693
|
+
routeTransport: this.routeTransport,
|
|
694
|
+
messageSerializers: options.registration.messageSerializers,
|
|
695
|
+
spotManager: () => this.spotManager,
|
|
696
|
+
actorManager: () => this.actorManager,
|
|
697
|
+
primaryMeshNode: () => this.requirePrimaryMeshNode(),
|
|
698
|
+
notifyEntrySpotActorLeft: (actor, signal) =>
|
|
699
|
+
this.spotNodeRuntime?.notifyPrimaryEntrySpotActorLeft(actor, signal) ?? Promise.resolve(),
|
|
700
|
+
restoreEntrySpotActorJoined: (actor, signal) =>
|
|
701
|
+
this.spotNodeRuntime?.notifyPrimaryEntrySpotActorJoined(actor, signal) ?? Promise.resolve(),
|
|
702
|
+
locationLifecycle: () => this.locationOwner.currentLifecycle,
|
|
703
|
+
spotRouteResolver: () => this.createLocationSpotRouteResolver(),
|
|
704
|
+
actorHandoff: this.actorHandoff,
|
|
705
|
+
actorTransferRegistry: this.actorTransferRegistry,
|
|
706
|
+
authorityStore: () => this.locationOwner.currentStores?.locationStore,
|
|
707
|
+
currentOwner: () => this.locationOwner.currentRuntime?.currentOwnerToken,
|
|
708
|
+
relocationStore: () =>
|
|
709
|
+
this.options.registration.locations.relocationStoreInstance,
|
|
710
|
+
liveDescriptors: (meshName, signal) => {
|
|
711
|
+
const runtime = this.locationOwner.currentRuntime;
|
|
712
|
+
if (runtime === undefined) {
|
|
713
|
+
throw new Error('Session owner liveness is unavailable without a Location runtime.');
|
|
714
|
+
}
|
|
715
|
+
return runtime.listLiveMeshNodes(meshName, signal);
|
|
716
|
+
},
|
|
717
|
+
sessionRelocationWire: () => this.serviceRelocation,
|
|
718
|
+
clearRemoteActorPacketTarget: (actorId) =>
|
|
719
|
+
this.boundSessionRelay.clearRemoteActorPacketTarget(actorId),
|
|
720
|
+
prepareApplicationJob: async (preparationSignal) => {
|
|
721
|
+
const runtimeSignal = this.executionState?.abortController.signal;
|
|
722
|
+
const signal = runtimeSignal === undefined
|
|
723
|
+
? preparationSignal
|
|
724
|
+
: AbortSignal.any([runtimeSignal, preparationSignal]);
|
|
725
|
+
const permit = await this.applicationJobQueue.acquire(signal);
|
|
726
|
+
let state: 'ready' | 'running' | 'closed' = 'ready';
|
|
727
|
+
let closedReason: unknown;
|
|
728
|
+
let abort: (() => void) | undefined;
|
|
729
|
+
const cancel = (reason?: unknown): void => {
|
|
730
|
+
if (state !== 'ready') return;
|
|
731
|
+
state = 'closed';
|
|
732
|
+
closedReason = reason;
|
|
733
|
+
if (abort !== undefined) signal.removeEventListener('abort', abort);
|
|
734
|
+
permit.releaseAfterInternalProcessing();
|
|
735
|
+
};
|
|
736
|
+
try {
|
|
737
|
+
if (signal.aborted) {
|
|
738
|
+
cancel(signal.reason);
|
|
739
|
+
throw signal.reason;
|
|
740
|
+
}
|
|
741
|
+
permit.markApplicationQueued();
|
|
742
|
+
abort = () => cancel(signal.reason);
|
|
743
|
+
signal.addEventListener('abort', abort, { once: true });
|
|
744
|
+
} catch (error) {
|
|
745
|
+
cancel(error);
|
|
746
|
+
throw error;
|
|
747
|
+
}
|
|
748
|
+
return {
|
|
749
|
+
run: async <T>(operation: () => Promise<T>): Promise<T> => {
|
|
750
|
+
if (state !== 'ready') {
|
|
751
|
+
throw closedReason ?? new Error('Prepared application job is no longer runnable.');
|
|
752
|
+
}
|
|
753
|
+
state = 'running';
|
|
754
|
+
signal.removeEventListener('abort', abort);
|
|
755
|
+
try {
|
|
756
|
+
return await runWithApplicationJobPermit(permit, operation);
|
|
757
|
+
} finally {
|
|
758
|
+
state = 'closed';
|
|
759
|
+
}
|
|
760
|
+
},
|
|
761
|
+
cancel
|
|
762
|
+
};
|
|
763
|
+
},
|
|
764
|
+
reportPostCommitError: (error) =>
|
|
765
|
+
(this.errorSink ?? this.preStartErrorSink).reportRuntimeTaskException('source actor departure', error),
|
|
766
|
+
onSourceDepartureCompleted: (actorId) =>
|
|
767
|
+
this.publishActorHandoffEvent({ marker: 'source_cleanup', actorId }),
|
|
768
|
+
shutdownSignal: () => this.executionState?.abortController.signal,
|
|
769
|
+
metrics: this.metrics
|
|
770
|
+
});
|
|
771
|
+
this.serviceRelocation = new ZLinkHostServiceRelocationRuntime({
|
|
772
|
+
registration: options.registration,
|
|
773
|
+
providerResolver: options.providerResolver,
|
|
774
|
+
locationStore: () => this.locationOwner.currentStores?.locationStore,
|
|
775
|
+
currentOwner: () => this.locationOwner.currentRuntime?.currentOwnerToken,
|
|
776
|
+
liveDescriptors: (meshName, signal) =>
|
|
777
|
+
this.locationOwner.currentRuntime?.listLiveMeshNodes(meshName, signal)
|
|
778
|
+
?? Promise.resolve([]),
|
|
779
|
+
localDescriptor: (meshName) =>
|
|
780
|
+
this.spotNodeRuntime?.meshNodeDescriptor(meshName),
|
|
781
|
+
meshNode: (meshName) => this.spotNodeRuntime?.meshNode(meshName),
|
|
782
|
+
completions: (meshName) => this.spotNodeRuntime?.meshCompletionTable(meshName),
|
|
783
|
+
spotManager: () => this.spotManager,
|
|
784
|
+
spotNodeRuntime: () => this.spotNodeRuntime,
|
|
785
|
+
actorManager: () => this.actorManager,
|
|
786
|
+
actorTransfer: this.actorTransferRuntime,
|
|
787
|
+
boundSessionRelocation: {
|
|
788
|
+
receiveSeal: (value, signal) =>
|
|
789
|
+
this.boundSessionRelay.boundSessions.receiveServiceWireSessionRelocationSeal(value, signal),
|
|
790
|
+
receiveRoute: value =>
|
|
791
|
+
this.boundSessionRelay.boundSessions.receiveServiceWireSessionRelocationRoute(value),
|
|
792
|
+
clear: () =>
|
|
793
|
+
this.boundSessionRelay.boundSessions.clearServiceWireSessionRelocations()
|
|
794
|
+
},
|
|
795
|
+
trackInstanceSpot: (input) =>
|
|
796
|
+
this.locationOwner.currentLifecycle?.trackInstanceSpot(input),
|
|
797
|
+
invalidateActorRoute: (actorId) =>
|
|
798
|
+
this.actorClientLocationResolver?.invalidateActorRoute(actorId),
|
|
799
|
+
reconcileStatefulAuthorityRoutes: (signal) =>
|
|
800
|
+
this.statefulAuthorityRoutes?.reconcile(signal) ?? Promise.resolve(),
|
|
801
|
+
runtimeEventPublisher: this.runtimeEventPublisher,
|
|
802
|
+
metrics: this.metrics
|
|
803
|
+
});
|
|
804
|
+
this.actorTransferAuthorityRuntime = new ZLinkActorTransferAuthorityRuntime({
|
|
805
|
+
store: () => this.locationOwner.actorTransferStore() as never,
|
|
806
|
+
recoveryOwnerId: () => this.locationOwner.currentRuntime?.ownerId,
|
|
807
|
+
recoveryLeaseTtlMs: {
|
|
808
|
+
...zlinkDefaultLocationOptions,
|
|
809
|
+
...options.registration.locations.options
|
|
810
|
+
}.ownerLeaseTtlMs
|
|
811
|
+
});
|
|
812
|
+
this.routeMeshCoordinator = new ZLinkRouteMeshRuntimeCoordinator({
|
|
813
|
+
meshNames: [...options.registration.spotNodes.keys()],
|
|
814
|
+
meshOptions: options.registration.spotNodes,
|
|
815
|
+
meshNode: (meshName) => this.spotNodeRuntime?.meshNode(meshName),
|
|
816
|
+
meshNodeDescriptor: (meshName) =>
|
|
817
|
+
this.spotNodeRuntime?.meshNodeDescriptor(meshName),
|
|
818
|
+
localPlacementCounts: (meshName) => {
|
|
819
|
+
const spotManager = this.spotManager;
|
|
820
|
+
const actorManager = this.actorManager;
|
|
821
|
+
if (spotManager === undefined || actorManager === undefined) return undefined;
|
|
822
|
+
return {
|
|
823
|
+
activeActorCount: actorManager.activeActorCount(meshName),
|
|
824
|
+
activeSpotCount: spotManager.activeSpotCount(meshName)
|
|
825
|
+
};
|
|
826
|
+
},
|
|
827
|
+
isLocationStoreHealthy: () => {
|
|
828
|
+
if (!hasConfiguredLocationStore(options.registration)) {
|
|
829
|
+
return true;
|
|
830
|
+
}
|
|
831
|
+
const runtime = this.locationOwner.currentRuntime;
|
|
832
|
+
return runtime !== undefined
|
|
833
|
+
&& runtime.ownerLeaseUsable
|
|
834
|
+
&& runtime.lastError === undefined;
|
|
835
|
+
},
|
|
836
|
+
hostState: () => this.runtimeState,
|
|
837
|
+
admission: this.admission,
|
|
838
|
+
publishRetiring: (meshName, signal) =>
|
|
839
|
+
this.publishMeshRetiring(meshName, signal),
|
|
840
|
+
rollbackRetiring: (meshName, signal) =>
|
|
841
|
+
this.publishMeshServing(meshName, signal),
|
|
842
|
+
publishDraining: (meshName, signal) =>
|
|
843
|
+
this.publishMeshDraining(meshName, signal),
|
|
844
|
+
publishHostDraining: (signal) => this.publishHostDraining(signal),
|
|
845
|
+
drainResources: (meshName, signal, stopStartingSignal) =>
|
|
846
|
+
this.performMeshDrain(meshName, signal, stopStartingSignal),
|
|
847
|
+
shutdownResources: (meshName, signal) => this.performMeshShutdown(meshName, signal),
|
|
848
|
+
cleanupHostResources: (signal) => this.cleanupOwnerForDrain(signal),
|
|
849
|
+
forceStopResources: (meshName) => this.forceStopMesh(meshName)
|
|
850
|
+
});
|
|
851
|
+
this.metricRegistrations.push(
|
|
852
|
+
this.metrics.registerHostState(() => runtimeStateMetricName(this.runtimeState)),
|
|
853
|
+
this.metrics.registerHostCapacity(() =>
|
|
854
|
+
this.capacityStatus.snapshot(this.context?.getCoreHwmBudgetSnapshot())),
|
|
855
|
+
this.metrics.registerApplicationJobQueuePressure(() =>
|
|
856
|
+
this.applicationJobQueue.snapshot()),
|
|
857
|
+
this.metrics.registerMeshSnapshots(() => this.runtimeMetricMeshSnapshots())
|
|
858
|
+
);
|
|
859
|
+
this.routeMeshRuntime = this.routeMeshCoordinator;
|
|
860
|
+
}
|
|
861
|
+
|
|
862
|
+
get isStarted(): boolean {
|
|
863
|
+
return this.executionState !== undefined;
|
|
864
|
+
}
|
|
865
|
+
|
|
866
|
+
get status(): ZLinkFrameworkRuntimeStatus {
|
|
867
|
+
return {
|
|
868
|
+
state: this.runtimeState,
|
|
869
|
+
isReady: runtimeStateIsReady(this.runtimeState),
|
|
870
|
+
acceptingWork: runtimeAcceptsWork(
|
|
871
|
+
this.runtimeState,
|
|
872
|
+
this.admission.acceptsNewWork
|
|
873
|
+
),
|
|
874
|
+
capacity: this.capacityStatus.snapshot(this.context?.getCoreHwmBudgetSnapshot()),
|
|
875
|
+
safeToShutdown: this.serviceRelocation.isSafeToShutdown(),
|
|
876
|
+
deadline: this.runtimeDeadline,
|
|
877
|
+
relocationResult: this.runtimeRelocationResult,
|
|
878
|
+
terminationResult: this.runtimeTerminationResult,
|
|
879
|
+
sequence: this.runtimeSequence,
|
|
880
|
+
observedAt: new Date()
|
|
881
|
+
};
|
|
882
|
+
}
|
|
883
|
+
|
|
884
|
+
observe(signal?: AbortSignal): AsyncIterable<ZLinkObservedStatus<ZLinkFrameworkRuntimeStatus>> {
|
|
885
|
+
const queue = new RuntimeEventQueue<ZLinkFrameworkRuntimeStatus>(undefined, signal);
|
|
886
|
+
this.runtimeObservers.add(queue);
|
|
887
|
+
queue.onClose(() => this.runtimeObservers.delete(queue));
|
|
888
|
+
return queue;
|
|
889
|
+
}
|
|
890
|
+
|
|
891
|
+
resetCapacityMetrics(): void {
|
|
892
|
+
const context = this.context;
|
|
893
|
+
if (context === undefined) {
|
|
894
|
+
throw new Error('Capacity metrics reset requires a started Framework runtime.');
|
|
895
|
+
}
|
|
896
|
+
this.capacityStatus.reset(() => context.resetCoreHwmBudgetMetrics());
|
|
897
|
+
}
|
|
898
|
+
|
|
899
|
+
relocate(options: ZLinkFrameworkRelocationOptions): Promise<ZLinkFrameworkRelocationResult> {
|
|
900
|
+
const effectiveTargetApplicationVersion = validateRelocationOptions(
|
|
901
|
+
options,
|
|
902
|
+
this.options.registration.applicationVersion
|
|
903
|
+
);
|
|
904
|
+
const deadlineMs = options.deadlineMs ?? 30_000;
|
|
905
|
+
if (!Number.isFinite(deadlineMs) || deadlineMs <= 0) {
|
|
906
|
+
return Promise.reject(new RangeError('Relocation deadlineMs must be greater than zero.'));
|
|
907
|
+
}
|
|
908
|
+
if (this.runtimeRelocationResult?.outcome === ZLinkFrameworkRelocationOutcome.Relocated) {
|
|
909
|
+
return Promise.resolve(this.runtimeRelocationResult);
|
|
910
|
+
}
|
|
911
|
+
if (this.shutdownOperation !== undefined) {
|
|
912
|
+
return Promise.resolve({
|
|
913
|
+
mode: options.mode,
|
|
914
|
+
effectiveTargetApplicationVersion,
|
|
915
|
+
outcome: ZLinkFrameworkRelocationOutcome.Blocked,
|
|
916
|
+
reason: ZLinkFrameworkRelocationReason.ShutdownRequested
|
|
917
|
+
});
|
|
918
|
+
}
|
|
919
|
+
const operationKey = `${options.mode}:${effectiveTargetApplicationVersion}`;
|
|
920
|
+
if (this.relocationOperation !== undefined) {
|
|
921
|
+
if (this.relocationOperationKey === operationKey) {
|
|
922
|
+
return waitForRuntimeOperation(this.relocationOperation, options.signal);
|
|
923
|
+
}
|
|
924
|
+
return Promise.resolve({
|
|
925
|
+
mode: options.mode,
|
|
926
|
+
effectiveTargetApplicationVersion,
|
|
927
|
+
outcome: ZLinkFrameworkRelocationOutcome.Blocked,
|
|
928
|
+
reason: ZLinkFrameworkRelocationReason.OperationInProgress
|
|
929
|
+
});
|
|
930
|
+
}
|
|
931
|
+
if (this.runtimeState !== ZLinkFrameworkRuntimeState.Serving) {
|
|
932
|
+
return Promise.resolve({
|
|
933
|
+
mode: options.mode,
|
|
934
|
+
effectiveTargetApplicationVersion,
|
|
935
|
+
outcome: ZLinkFrameworkRelocationOutcome.Blocked,
|
|
936
|
+
reason: this.runtimeState === ZLinkFrameworkRuntimeState.Relocating
|
|
937
|
+
? ZLinkFrameworkRelocationReason.OperationInProgress
|
|
938
|
+
: ZLinkFrameworkRelocationReason.RuntimeNotReady
|
|
939
|
+
});
|
|
940
|
+
}
|
|
941
|
+
if (hasUnsupportedManualTopology(this.options.registration)) {
|
|
942
|
+
return Promise.resolve({
|
|
943
|
+
mode: options.mode,
|
|
944
|
+
effectiveTargetApplicationVersion,
|
|
945
|
+
outcome: ZLinkFrameworkRelocationOutcome.Blocked,
|
|
946
|
+
reason: ZLinkFrameworkRelocationReason.ManualTopologyUnsupported
|
|
947
|
+
});
|
|
948
|
+
}
|
|
949
|
+
this.runtimeDeadline = new Date(Date.now() + deadlineMs);
|
|
950
|
+
this.relocationTargetApplicationVersion = effectiveTargetApplicationVersion;
|
|
951
|
+
this.relocationOperationKey = operationKey;
|
|
952
|
+
this.relocationOperationStartedAt = performance.now();
|
|
953
|
+
this.relocationStopStarting = new AbortController();
|
|
954
|
+
this.relocationOperation = this.runRelocation(
|
|
955
|
+
options.mode,
|
|
956
|
+
effectiveTargetApplicationVersion,
|
|
957
|
+
deadlineMs,
|
|
958
|
+
this.relocationStopStarting.signal
|
|
959
|
+
);
|
|
960
|
+
return waitForRuntimeOperation(this.relocationOperation, options.signal);
|
|
961
|
+
}
|
|
962
|
+
|
|
963
|
+
shutdown(options?: ZLinkFrameworkLifecycleOptions): Promise<ZLinkFrameworkTerminationResult> {
|
|
964
|
+
const deadlineMs = options?.deadlineMs ?? 30_000;
|
|
965
|
+
if (!Number.isFinite(deadlineMs) || deadlineMs <= 0) {
|
|
966
|
+
return Promise.reject(new RangeError('Shutdown deadlineMs must be greater than zero.'));
|
|
967
|
+
}
|
|
968
|
+
if (this.shutdownOperation === undefined) {
|
|
969
|
+
this.runtimeDeadline = new Date(Date.now() + deadlineMs);
|
|
970
|
+
this.relocationStopStarting?.abort(new Error('Shutdown requested.'));
|
|
971
|
+
this.shutdownOperationStartedAt = performance.now();
|
|
972
|
+
this.shutdownOperation = this.runShutdown(deadlineMs);
|
|
973
|
+
}
|
|
974
|
+
return waitForRuntimeOperation(this.shutdownOperation, options?.signal);
|
|
975
|
+
}
|
|
976
|
+
|
|
977
|
+
private async runRelocation(
|
|
978
|
+
mode: ZLinkFrameworkRelocationMode,
|
|
979
|
+
effectiveTargetApplicationVersion: bigint,
|
|
980
|
+
deadlineMs: number,
|
|
981
|
+
stopStartingSignal: AbortSignal
|
|
982
|
+
): Promise<ZLinkFrameworkRelocationResult> {
|
|
983
|
+
if (!this.isStarted) {
|
|
984
|
+
return this.completeRelocation(blockedRelocation(
|
|
985
|
+
mode,
|
|
986
|
+
effectiveTargetApplicationVersion,
|
|
987
|
+
ZLinkFrameworkRelocationReason.RuntimeNotReady
|
|
988
|
+
));
|
|
989
|
+
}
|
|
990
|
+
const deadlineAtMs = performance.now() + deadlineMs;
|
|
991
|
+
const remainingDeadlineMs = () => Math.max(1, deadlineAtMs - performance.now());
|
|
992
|
+
try {
|
|
993
|
+
// Runtime weight changes publish a newer descriptor asynchronously. A
|
|
994
|
+
// maintenance operation must observe that publication before it writes
|
|
995
|
+
// Retiring/Draining, otherwise two descriptor revisions can race and
|
|
996
|
+
// make a valid drain look like a Store failure.
|
|
997
|
+
await this.spotNodeRuntime?.waitForRuntimeWeightPublication();
|
|
998
|
+
const blocker = await this.preflightAutomaticPeerReadiness(
|
|
999
|
+
deadlineAtMs,
|
|
1000
|
+
effectiveTargetApplicationVersion
|
|
1001
|
+
);
|
|
1002
|
+
if (blocker !== undefined) {
|
|
1003
|
+
return this.resetBlockedRelocation(blockedRelocation(
|
|
1004
|
+
mode,
|
|
1005
|
+
effectiveTargetApplicationVersion,
|
|
1006
|
+
blocker
|
|
1007
|
+
));
|
|
1008
|
+
}
|
|
1009
|
+
const descriptorPreparation = await this.routeMeshCoordinator.prepareHostRetire(
|
|
1010
|
+
remainingDeadlineMs()
|
|
1011
|
+
);
|
|
1012
|
+
if (descriptorPreparation !== 'prepared') {
|
|
1013
|
+
return this.resetBlockedRelocation(blockedRelocation(
|
|
1014
|
+
mode,
|
|
1015
|
+
effectiveTargetApplicationVersion,
|
|
1016
|
+
descriptorPreparation === 'deadline_exceeded'
|
|
1017
|
+
? ZLinkFrameworkRelocationReason.DeadlineExceeded
|
|
1018
|
+
: ZLinkFrameworkRelocationReason.StoreUnavailable
|
|
1019
|
+
));
|
|
1020
|
+
}
|
|
1021
|
+
this.setRuntimeState(ZLinkFrameworkRuntimeState.Relocating);
|
|
1022
|
+
const drained = await this.routeMeshCoordinator.relocateHost(
|
|
1023
|
+
remainingDeadlineMs(),
|
|
1024
|
+
stopStartingSignal
|
|
1025
|
+
);
|
|
1026
|
+
if (drained.kind === 'forceStopped') {
|
|
1027
|
+
return this.resetBlockedRelocation(blockedRelocation(
|
|
1028
|
+
mode,
|
|
1029
|
+
effectiveTargetApplicationVersion,
|
|
1030
|
+
stopStartingSignal.aborted
|
|
1031
|
+
? ZLinkFrameworkRelocationReason.ShutdownRequested
|
|
1032
|
+
: drained.error instanceof ZLinkRelocationStateIncompatibleError
|
|
1033
|
+
? ZLinkFrameworkRelocationReason.StateIncompatible
|
|
1034
|
+
: relocationReason(drained.reason)
|
|
1035
|
+
));
|
|
1036
|
+
}
|
|
1037
|
+
await this.publishHostRelocated();
|
|
1038
|
+
return this.completeRelocation({
|
|
1039
|
+
mode,
|
|
1040
|
+
effectiveTargetApplicationVersion,
|
|
1041
|
+
outcome: ZLinkFrameworkRelocationOutcome.Relocated,
|
|
1042
|
+
reason: ZLinkFrameworkRelocationReason.None
|
|
1043
|
+
});
|
|
1044
|
+
} catch (error) {
|
|
1045
|
+
const result = blockedRelocation(
|
|
1046
|
+
mode,
|
|
1047
|
+
effectiveTargetApplicationVersion,
|
|
1048
|
+
stopStartingSignal.aborted
|
|
1049
|
+
? ZLinkFrameworkRelocationReason.ShutdownRequested
|
|
1050
|
+
: isDeadlineExceededError(error)
|
|
1051
|
+
? ZLinkFrameworkRelocationReason.DeadlineExceeded
|
|
1052
|
+
: error instanceof ZLinkRelocationStateIncompatibleError
|
|
1053
|
+
? ZLinkFrameworkRelocationReason.StateIncompatible
|
|
1054
|
+
: ZLinkFrameworkRelocationReason.RelocationFailed
|
|
1055
|
+
);
|
|
1056
|
+
return error instanceof ZLinkRetiringRollbackError
|
|
1057
|
+
? this.completeRelocation(result)
|
|
1058
|
+
: this.resetBlockedRelocation(result);
|
|
1059
|
+
}
|
|
1060
|
+
}
|
|
1061
|
+
|
|
1062
|
+
private async runShutdown(deadlineMs: number): Promise<ZLinkFrameworkTerminationResult> {
|
|
1063
|
+
const deadlineAtMs = performance.now() + deadlineMs;
|
|
1064
|
+
try {
|
|
1065
|
+
this.admission.close();
|
|
1066
|
+
this.setRuntimeState(ZLinkFrameworkRuntimeState.Draining);
|
|
1067
|
+
if (this.relocationOperation !== undefined
|
|
1068
|
+
&& this.relocationStopStarting?.signal.aborted === true) {
|
|
1069
|
+
await this.relocationOperation;
|
|
1070
|
+
}
|
|
1071
|
+
// Seal application admission before the public status reports that the
|
|
1072
|
+
// host no longer accepts work. This prevents status polling from racing
|
|
1073
|
+
// with the coordinator's synchronous seal step.
|
|
1074
|
+
const unscopedStreamDrain = this.streamRuntime?.notifyUnscopedServerDrain();
|
|
1075
|
+
const shutdown = this.routeMeshCoordinator.shutdownHost(
|
|
1076
|
+
this.runtimeDeadline!,
|
|
1077
|
+
undefined,
|
|
1078
|
+
Math.max(0, deadlineAtMs - performance.now())
|
|
1079
|
+
);
|
|
1080
|
+
const drain = await shutdown;
|
|
1081
|
+
await unscopedStreamDrain;
|
|
1082
|
+
await this.stop();
|
|
1083
|
+
if (drain.kind === 'forceStopped') {
|
|
1084
|
+
return this.completeTermination({
|
|
1085
|
+
outcome: ZLinkFrameworkTerminationOutcome.ForceStopped,
|
|
1086
|
+
reason: drain.reason === 'deadline_exceeded'
|
|
1087
|
+
? ZLinkFrameworkTerminationReason.DeadlineExceeded
|
|
1088
|
+
: ZLinkFrameworkTerminationReason.TeardownFailed
|
|
1089
|
+
});
|
|
1090
|
+
}
|
|
1091
|
+
if (performance.now() >= deadlineAtMs) {
|
|
1092
|
+
throw createDeadlineExceededError('Shutdown resource cleanup exceeded its deadline.');
|
|
1093
|
+
}
|
|
1094
|
+
return this.completeTermination({
|
|
1095
|
+
outcome: ZLinkFrameworkTerminationOutcome.Stopped,
|
|
1096
|
+
reason: ZLinkFrameworkTerminationReason.None
|
|
1097
|
+
});
|
|
1098
|
+
} catch (error) {
|
|
1099
|
+
await this.stop().catch(() => undefined);
|
|
1100
|
+
return this.completeTermination({
|
|
1101
|
+
outcome: ZLinkFrameworkTerminationOutcome.ForceStopped,
|
|
1102
|
+
reason: isDeadlineExceededError(error)
|
|
1103
|
+
? ZLinkFrameworkTerminationReason.DeadlineExceeded
|
|
1104
|
+
: ZLinkFrameworkTerminationReason.TeardownFailed
|
|
1105
|
+
});
|
|
1106
|
+
}
|
|
1107
|
+
}
|
|
1108
|
+
|
|
1109
|
+
private resetBlockedRelocation(
|
|
1110
|
+
result: ZLinkFrameworkRelocationResult
|
|
1111
|
+
): ZLinkFrameworkRelocationResult {
|
|
1112
|
+
this.recordRelocationResult(result);
|
|
1113
|
+
if (this.runtimeState === ZLinkFrameworkRuntimeState.Relocating) {
|
|
1114
|
+
this.setRuntimeState(ZLinkFrameworkRuntimeState.Serving);
|
|
1115
|
+
}
|
|
1116
|
+
this.runtimeDeadline = undefined;
|
|
1117
|
+
this.relocationTargetApplicationVersion = undefined;
|
|
1118
|
+
this.relocationStopStarting = undefined;
|
|
1119
|
+
this.relocationOperation = undefined;
|
|
1120
|
+
this.relocationOperationKey = undefined;
|
|
1121
|
+
this.relocationOperationStartedAt = undefined;
|
|
1122
|
+
return result;
|
|
1123
|
+
}
|
|
1124
|
+
|
|
1125
|
+
private completeRelocation(
|
|
1126
|
+
result: ZLinkFrameworkRelocationResult
|
|
1127
|
+
): ZLinkFrameworkRelocationResult {
|
|
1128
|
+
this.runtimeRelocationResult = result;
|
|
1129
|
+
this.runtimeDeadline = undefined;
|
|
1130
|
+
this.recordRelocationResult(result);
|
|
1131
|
+
this.setRuntimeState(result.outcome === ZLinkFrameworkRelocationOutcome.Relocated
|
|
1132
|
+
? ZLinkFrameworkRuntimeState.Relocated
|
|
1133
|
+
: ZLinkFrameworkRuntimeState.Error);
|
|
1134
|
+
return result;
|
|
1135
|
+
}
|
|
1136
|
+
|
|
1137
|
+
private recordRelocationResult(result: ZLinkFrameworkRelocationResult): void {
|
|
1138
|
+
if (this.relocationOperationStartedAt !== undefined) {
|
|
1139
|
+
this.metrics.duration(
|
|
1140
|
+
'zlink.host.relocation.duration',
|
|
1141
|
+
Math.max(0, performance.now() - this.relocationOperationStartedAt) / 1000,
|
|
1142
|
+
{
|
|
1143
|
+
mode: relocationModeMetricName(result.mode),
|
|
1144
|
+
outcome: result.outcome === ZLinkFrameworkRelocationOutcome.Relocated
|
|
1145
|
+
? 'relocated'
|
|
1146
|
+
: 'blocked'
|
|
1147
|
+
}
|
|
1148
|
+
);
|
|
1149
|
+
}
|
|
1150
|
+
if (result.outcome === ZLinkFrameworkRelocationOutcome.Blocked) {
|
|
1151
|
+
this.metrics.count('zlink.host.relocation.blocked', 1, {
|
|
1152
|
+
mode: relocationModeMetricName(result.mode),
|
|
1153
|
+
reason: relocationReasonMetricName(result.reason)
|
|
1154
|
+
});
|
|
1155
|
+
}
|
|
1156
|
+
void this.runtimeEventPublisher.publish({
|
|
1157
|
+
sourceName: 'zlink.runtime.host',
|
|
1158
|
+
timestamp: new Date(),
|
|
1159
|
+
identifier: 'zlink.runtime.host.relocation_changed',
|
|
1160
|
+
mode: result.mode,
|
|
1161
|
+
effectiveTargetApplicationVersion: result.effectiveTargetApplicationVersion,
|
|
1162
|
+
outcome: result.outcome,
|
|
1163
|
+
reason: result.reason
|
|
1164
|
+
});
|
|
1165
|
+
}
|
|
1166
|
+
|
|
1167
|
+
private completeTermination(
|
|
1168
|
+
result: ZLinkFrameworkTerminationResult
|
|
1169
|
+
): ZLinkFrameworkTerminationResult {
|
|
1170
|
+
this.runtimeTerminationResult = result;
|
|
1171
|
+
this.runtimeDeadline = undefined;
|
|
1172
|
+
if (this.shutdownOperationStartedAt !== undefined) {
|
|
1173
|
+
this.metrics.duration(
|
|
1174
|
+
'zlink.host.shutdown.duration',
|
|
1175
|
+
Math.max(0, performance.now() - this.shutdownOperationStartedAt) / 1000,
|
|
1176
|
+
{
|
|
1177
|
+
outcome: result.outcome === ZLinkFrameworkTerminationOutcome.Stopped
|
|
1178
|
+
? 'stopped'
|
|
1179
|
+
: 'force_stopped'
|
|
1180
|
+
}
|
|
1181
|
+
);
|
|
1182
|
+
}
|
|
1183
|
+
if (result.outcome === ZLinkFrameworkTerminationOutcome.ForceStopped) {
|
|
1184
|
+
this.metrics.count('zlink.host.shutdown.forced', 1, {
|
|
1185
|
+
reason: terminationReasonMetricName(result.reason)
|
|
1186
|
+
});
|
|
1187
|
+
}
|
|
1188
|
+
void this.runtimeEventPublisher.publish({
|
|
1189
|
+
sourceName: 'zlink.runtime.host',
|
|
1190
|
+
timestamp: new Date(),
|
|
1191
|
+
identifier: 'zlink.runtime.host.termination_changed',
|
|
1192
|
+
outcome: result.outcome,
|
|
1193
|
+
reason: result.reason
|
|
1194
|
+
});
|
|
1195
|
+
this.setRuntimeState(ZLinkFrameworkRuntimeState.Stopped);
|
|
1196
|
+
return result;
|
|
1197
|
+
}
|
|
1198
|
+
|
|
1199
|
+
private setRuntimeState(state: ZLinkFrameworkRuntimeState): void {
|
|
1200
|
+
if (this.runtimeState === state) return;
|
|
1201
|
+
this.runtimeState = state;
|
|
1202
|
+
this.runtimeSequence += 1n;
|
|
1203
|
+
this.notifyTopologyHostStateChanged();
|
|
1204
|
+
const status = this.status;
|
|
1205
|
+
for (const observer of this.runtimeObservers) {
|
|
1206
|
+
if (state === ZLinkFrameworkRuntimeState.Stopped) {
|
|
1207
|
+
observer.seal(status, this.runtimeObservationSource);
|
|
1208
|
+
} else {
|
|
1209
|
+
observer.push(status, this.runtimeObservationSource);
|
|
1210
|
+
}
|
|
1211
|
+
}
|
|
1212
|
+
if (state === ZLinkFrameworkRuntimeState.Stopped) {
|
|
1213
|
+
this.runtimeObservers.clear();
|
|
1214
|
+
}
|
|
1215
|
+
}
|
|
1216
|
+
|
|
1217
|
+
private notifyTopologyHostStateChanged(): void {
|
|
1218
|
+
const callbacks = [
|
|
1219
|
+
() => this.routeMeshCoordinator.hostStateChanged(),
|
|
1220
|
+
() => (this.clientServerRuntime as ZLinkClientServerRuntimeProjection)
|
|
1221
|
+
.hostStateChanged(),
|
|
1222
|
+
() => (this.fanoutRuntime as ZLinkFanoutRuntimeProjection)
|
|
1223
|
+
.hostStateChanged()
|
|
1224
|
+
];
|
|
1225
|
+
for (const callback of callbacks) {
|
|
1226
|
+
try {
|
|
1227
|
+
callback();
|
|
1228
|
+
} catch (error) {
|
|
1229
|
+
try {
|
|
1230
|
+
this.runtimeOrPreStartErrorSink.reportRuntimeTaskException(
|
|
1231
|
+
'topology lifecycle observation',
|
|
1232
|
+
error
|
|
1233
|
+
);
|
|
1234
|
+
} catch {
|
|
1235
|
+
// Monitoring must not change the host lifecycle result.
|
|
1236
|
+
}
|
|
1237
|
+
}
|
|
1238
|
+
}
|
|
1239
|
+
}
|
|
1240
|
+
|
|
1241
|
+
private stopTopologyObservers(): void {
|
|
1242
|
+
const callbacks = [
|
|
1243
|
+
() => this.routeMeshCoordinator.stopObservers(),
|
|
1244
|
+
() => (this.clientServerRuntime as ZLinkClientServerRuntimeProjection)
|
|
1245
|
+
.stopObservers(),
|
|
1246
|
+
() => (this.fanoutRuntime as ZLinkFanoutRuntimeProjection)
|
|
1247
|
+
.stopObservers()
|
|
1248
|
+
];
|
|
1249
|
+
for (const callback of callbacks) {
|
|
1250
|
+
try {
|
|
1251
|
+
callback();
|
|
1252
|
+
} catch (error) {
|
|
1253
|
+
try {
|
|
1254
|
+
this.runtimeOrPreStartErrorSink.reportRuntimeTaskException(
|
|
1255
|
+
'topology observer shutdown',
|
|
1256
|
+
error
|
|
1257
|
+
);
|
|
1258
|
+
} catch {
|
|
1259
|
+
// Monitoring must not change the host lifecycle result.
|
|
1260
|
+
}
|
|
1261
|
+
}
|
|
1262
|
+
}
|
|
1263
|
+
}
|
|
1264
|
+
|
|
1265
|
+
private publishActorHandoffEvent(event: {
|
|
1266
|
+
readonly marker: string;
|
|
1267
|
+
readonly actorId: string;
|
|
1268
|
+
readonly index?: number;
|
|
1269
|
+
readonly requestSeq?: string;
|
|
1270
|
+
readonly flags?: number;
|
|
1271
|
+
}): void {
|
|
1272
|
+
void this.runtimeEventPublisher.publish({
|
|
1273
|
+
sourceName: 'zlink.framework.actor-handoff',
|
|
1274
|
+
timestamp: new Date(),
|
|
1275
|
+
...event
|
|
1276
|
+
});
|
|
1277
|
+
}
|
|
1278
|
+
|
|
1279
|
+
get locationRuntimeQuery(): ZLinkLocationRuntimeQuery | undefined {
|
|
1280
|
+
return this.ensureLocationRuntime();
|
|
1281
|
+
}
|
|
1282
|
+
|
|
1283
|
+
/**
|
|
1284
|
+
* Runtime toggle (ZLinkMessageFlowControl): flip the shared live-mode cell so every
|
|
1285
|
+
* surface starts/stops tracing without a restart. Do not call this synchronous
|
|
1286
|
+
* bridge from a framework execution context such as a handler or callback; use
|
|
1287
|
+
* setMessageFlowModeAsync there.
|
|
1288
|
+
*/
|
|
1289
|
+
setMessageFlowMode(mode: ZLinkMessageFlowLogMode): void {
|
|
1290
|
+
void this.setMessageFlowModeAsync(mode);
|
|
1291
|
+
}
|
|
1292
|
+
|
|
1293
|
+
setMessageFlowModeAsync(mode: ZLinkMessageFlowLogMode): Promise<void> {
|
|
1294
|
+
this.messageFlowModeCell.mode = requireMessageFlowLogMode(mode);
|
|
1295
|
+
return Promise.resolve();
|
|
1296
|
+
}
|
|
1297
|
+
|
|
1298
|
+
messageFlowMode(): ZLinkMessageFlowLogMode {
|
|
1299
|
+
return this.messageFlowModeCell.mode;
|
|
1300
|
+
}
|
|
1301
|
+
|
|
1302
|
+
get context(): ZLinkBackendContext | undefined {
|
|
1303
|
+
return this.executionState?.context as ZLinkBackendContext | undefined;
|
|
1304
|
+
}
|
|
1305
|
+
|
|
1306
|
+
get taskRunner(): ZLinkFrameworkExecutionState['taskRunner'] | undefined {
|
|
1307
|
+
return this.executionState?.taskRunner;
|
|
1308
|
+
}
|
|
1309
|
+
|
|
1310
|
+
get errorSink(): ZLinkFrameworkExecutionState['errorSink'] | undefined {
|
|
1311
|
+
return this.executionState?.errorSink;
|
|
1312
|
+
}
|
|
1313
|
+
|
|
1314
|
+
async start(): Promise<void> {
|
|
1315
|
+
await this.runLifecycle(() => this.startCore());
|
|
1316
|
+
}
|
|
1317
|
+
|
|
1318
|
+
private async startCore(): Promise<void> {
|
|
1319
|
+
if (this.executionState !== undefined) {
|
|
1320
|
+
return;
|
|
1321
|
+
}
|
|
1322
|
+
|
|
1323
|
+
this.setRuntimeState(ZLinkFrameworkRuntimeState.Preparing);
|
|
1324
|
+
this.lifecycleSink?.push('framework:start');
|
|
1325
|
+
const channelAdapter = this.backendAdapterFactory.createChannelAdapter();
|
|
1326
|
+
const context = channelAdapter.createContext();
|
|
1327
|
+
const coreHwm = this.options.registration.coreHwm;
|
|
1328
|
+
if (coreHwm !== undefined) {
|
|
1329
|
+
context.configureCoreHwm(coreHwm);
|
|
1330
|
+
}
|
|
1331
|
+
let channelRuntime: ZLinkChannelRuntimeManager | undefined;
|
|
1332
|
+
let spotNodeRuntime: ZLinkSpotNodeRuntimeManager | undefined;
|
|
1333
|
+
let streamRuntime: ZLinkStreamRuntimeManager | undefined;
|
|
1334
|
+
let startedLocationRuntime: ZLinkLocationRuntime | undefined;
|
|
1335
|
+
let statefulAuthorityRoutes: ZLinkStatefulAuthorityRouteRuntime | undefined;
|
|
1336
|
+
try {
|
|
1337
|
+
this.executionState = new ZLinkFrameworkExecutionState(context);
|
|
1338
|
+
// Seed the shared live-mode cell from the configured mode (default errorsOnly).
|
|
1339
|
+
this.messageFlowModeCell.mode =
|
|
1340
|
+
this.options.registration.dispatch?.diagnostics.messageFlow ??
|
|
1341
|
+
'errors';
|
|
1342
|
+
const dispatchErrors = this.createDispatchErrorReporter(this.executionState.errorSink);
|
|
1343
|
+
channelRuntime = new ZLinkChannelRuntimeManager(
|
|
1344
|
+
this.options.registration,
|
|
1345
|
+
channelAdapter,
|
|
1346
|
+
context,
|
|
1347
|
+
this.options.providerResolver,
|
|
1348
|
+
this.createChannelRuntimeOptions()
|
|
1349
|
+
);
|
|
1350
|
+
this.channelRuntime = channelRuntime;
|
|
1351
|
+
channelRuntime.prepareMeshDispatch(this.executionState.taskRunner);
|
|
1352
|
+
spotNodeRuntime = new ZLinkSpotNodeRuntimeManager(
|
|
1353
|
+
this.createSpotNodeRuntimeOptions(context, dispatchErrors)
|
|
1354
|
+
);
|
|
1355
|
+
await spotNodeRuntime.start();
|
|
1356
|
+
this.spotNodeRuntime = spotNodeRuntime;
|
|
1357
|
+
this.registerUserSpotHandlers?.(spotNodeRuntime);
|
|
1358
|
+
channelRuntime.bindRouteMeshRouters();
|
|
1359
|
+
// Start bound receivers before publishing Serving descriptors. A
|
|
1360
|
+
// discovered ClientServer endpoint must already be able to dispatch.
|
|
1361
|
+
this.executionState.listenerTasks.push(...channelRuntime.start(this.executionState.taskRunner));
|
|
1362
|
+
const locationRuntime = await this.locationOwner.startForRuntime(
|
|
1363
|
+
this.meshRouters.primaryMeshName(),
|
|
1364
|
+
spotNodeRuntime,
|
|
1365
|
+
channelRuntime
|
|
1366
|
+
);
|
|
1367
|
+
startedLocationRuntime = locationRuntime;
|
|
1368
|
+
if (locationRuntime !== undefined) {
|
|
1369
|
+
this.installOwnerLeaseRecoveryPublication(locationRuntime, spotNodeRuntime, channelRuntime);
|
|
1370
|
+
}
|
|
1371
|
+
const locationStore = this.locationOwner.currentStores?.locationStore;
|
|
1372
|
+
if (locationStore !== undefined && locationRuntime?.ownerLeaseUsable !== false) {
|
|
1373
|
+
await spotNodeRuntime.publishMeshNodeState(
|
|
1374
|
+
ZLinkFrameworkRuntimeState.Preparing,
|
|
1375
|
+
this.executionState.abortController.signal
|
|
1376
|
+
);
|
|
1377
|
+
if (this.requiresStatefulAuthorityRuntime()) {
|
|
1378
|
+
this.installLocationBackedAuthorities(locationStore, spotNodeRuntime);
|
|
1379
|
+
statefulAuthorityRoutes = this.createStatefulAuthorityRoutes(
|
|
1380
|
+
locationStore,
|
|
1381
|
+
spotNodeRuntime
|
|
1382
|
+
);
|
|
1383
|
+
await statefulAuthorityRoutes.start(this.executionState.abortController.signal);
|
|
1384
|
+
this.statefulAuthorityRoutes = statefulAuthorityRoutes;
|
|
1385
|
+
}
|
|
1386
|
+
}
|
|
1387
|
+
streamRuntime = new ZLinkStreamRuntimeManager({
|
|
1388
|
+
registration: this.options.registration,
|
|
1389
|
+
backendAdapterFactory: this.backendAdapterFactory,
|
|
1390
|
+
context,
|
|
1391
|
+
bindingRuntime: this.streamBindingRuntime,
|
|
1392
|
+
providerResolver: this.options.providerResolver,
|
|
1393
|
+
dispatchErrors,
|
|
1394
|
+
metrics: this.metrics,
|
|
1395
|
+
applicationJobQueue: this.applicationJobQueue,
|
|
1396
|
+
acceptNewSession: (meshName) => meshName === undefined
|
|
1397
|
+
? this.admission.acceptsNewWork
|
|
1398
|
+
: this.admission.accepts(meshName),
|
|
1399
|
+
primaryMeshName: this.meshRouters.primaryMeshName(),
|
|
1400
|
+
nativeMeshNode: spotNodeRuntime.primaryMeshNode,
|
|
1401
|
+
meshCompletions: spotNodeRuntime.primaryMeshCompletions,
|
|
1402
|
+
nativeMeshNodeForName: (meshName) => spotNodeRuntime?.meshNode(meshName),
|
|
1403
|
+
meshCompletionsForName: (meshName) => spotNodeRuntime?.meshCompletionTable(meshName)
|
|
1404
|
+
});
|
|
1405
|
+
streamRuntime.start();
|
|
1406
|
+
this.streamRuntime = streamRuntime;
|
|
1407
|
+
if (locationRuntime === undefined || locationRuntime.ownerLeaseUsable) {
|
|
1408
|
+
await spotNodeRuntime.publishMeshNodeState(
|
|
1409
|
+
ZLinkFrameworkRuntimeState.Serving,
|
|
1410
|
+
this.executionState.abortController.signal
|
|
1411
|
+
);
|
|
1412
|
+
}
|
|
1413
|
+
this.routeMeshCoordinator.markServing();
|
|
1414
|
+
this.setRuntimeState(ZLinkFrameworkRuntimeState.Serving);
|
|
1415
|
+
this.lifecycleSink?.push('framework:started');
|
|
1416
|
+
} catch (error) {
|
|
1417
|
+
await statefulAuthorityRoutes?.stop();
|
|
1418
|
+
await rollbackRuntimeStart({
|
|
1419
|
+
context,
|
|
1420
|
+
startedLocationRuntime,
|
|
1421
|
+
streamRuntime,
|
|
1422
|
+
spotNodeRuntime,
|
|
1423
|
+
channelRuntime,
|
|
1424
|
+
ownedStores: registeredRuntimeStores(this.options.registration)
|
|
1425
|
+
});
|
|
1426
|
+
this.executionState = undefined;
|
|
1427
|
+
this.channelRuntime = undefined;
|
|
1428
|
+
this.spotNodeRuntime = undefined;
|
|
1429
|
+
this.streamRuntime = undefined;
|
|
1430
|
+
this.statefulAuthorityRoutes = undefined;
|
|
1431
|
+
this.removeOwnerLeaseRecoveryPublication();
|
|
1432
|
+
this.locationOwner.clearForStop();
|
|
1433
|
+
this.cachedLocationSpotRouteResolver = undefined;
|
|
1434
|
+
throw error;
|
|
1435
|
+
}
|
|
1436
|
+
}
|
|
1437
|
+
|
|
1438
|
+
async stop(): Promise<void> {
|
|
1439
|
+
await this.runLifecycle(() => this.stopCore());
|
|
1440
|
+
}
|
|
1441
|
+
|
|
1442
|
+
private runtimeMetricMeshSnapshots(): readonly ZLinkRuntimeMetricMeshSnapshot[] {
|
|
1443
|
+
const snapshots: ZLinkRuntimeMetricMeshSnapshot[] = [];
|
|
1444
|
+
for (const [meshName, options] of this.options.registration.spotNodes) {
|
|
1445
|
+
let status;
|
|
1446
|
+
try {
|
|
1447
|
+
status = this.routeMeshCoordinator.snapshot(meshName);
|
|
1448
|
+
} catch {
|
|
1449
|
+
continue;
|
|
1450
|
+
}
|
|
1451
|
+
const descriptor = this.spotNodeRuntime?.meshNodeDescriptor(meshName);
|
|
1452
|
+
const hasManual = (options.router?.manualConnections?.length ?? 0) > 0
|
|
1453
|
+
|| (options.router?.manualPeerConnections?.length ?? 0) > 0
|
|
1454
|
+
|| (options.pubSub?.manualConnections?.length ?? 0) > 0;
|
|
1455
|
+
const hasDiscovery = hasConfiguredLocationStore(this.options.registration);
|
|
1456
|
+
const source = hasManual && hasDiscovery
|
|
1457
|
+
? 'manual_and_redis'
|
|
1458
|
+
: hasManual ? 'manual' : 'redis';
|
|
1459
|
+
const emptyCapacity = { active: 0, reserved: 0, limit: 0 };
|
|
1460
|
+
snapshots.push({
|
|
1461
|
+
meshName,
|
|
1462
|
+
source,
|
|
1463
|
+
configuredPeers: status.peers.length,
|
|
1464
|
+
connectedPeers: status.peers.filter(peer => peer.state !== ZLinkPeerState.NotConnected).length,
|
|
1465
|
+
readyPeers: status.readyPeerCount,
|
|
1466
|
+
channels: status.channels.map(channel => ({
|
|
1467
|
+
channelName: channel.channelName,
|
|
1468
|
+
readyMembers: channel.readyTargetCount
|
|
1469
|
+
})),
|
|
1470
|
+
actorCapacity: descriptor?.populationCapacity.actors ?? emptyCapacity,
|
|
1471
|
+
spotCapacity: descriptor?.populationCapacity.spots ?? emptyCapacity,
|
|
1472
|
+
spotTypeCapacities: (descriptor?.populationCapacity.spotTypes ?? []).map(capacity => ({
|
|
1473
|
+
spotKind: capacity.objectKind === 'instance_spot' ? 'instance' : 'user',
|
|
1474
|
+
stableType: capacity.stableType,
|
|
1475
|
+
active: capacity.active,
|
|
1476
|
+
reserved: capacity.reserved,
|
|
1477
|
+
limit: capacity.limit
|
|
1478
|
+
})),
|
|
1479
|
+
activation: descriptor?.activationConcurrency ?? { active: 0, limit: 0 },
|
|
1480
|
+
instanceSpots: []
|
|
1481
|
+
});
|
|
1482
|
+
}
|
|
1483
|
+
return snapshots;
|
|
1484
|
+
}
|
|
1485
|
+
|
|
1486
|
+
private async stopCore(): Promise<void> {
|
|
1487
|
+
const state = this.executionState;
|
|
1488
|
+
if (state === undefined) {
|
|
1489
|
+
return;
|
|
1490
|
+
}
|
|
1491
|
+
|
|
1492
|
+
const channelRuntime = this.channelRuntime;
|
|
1493
|
+
const spotNodeRuntime = this.spotNodeRuntime;
|
|
1494
|
+
const streamRuntime = this.streamRuntime;
|
|
1495
|
+
const statefulAuthorityRoutes = this.statefulAuthorityRoutes;
|
|
1496
|
+
this.stopTopologyObservers();
|
|
1497
|
+
this.removeOwnerLeaseRecoveryPublication();
|
|
1498
|
+
const locationSnapshot = this.locationOwner.clearForStop();
|
|
1499
|
+
this.executionState = undefined;
|
|
1500
|
+
this.channelRuntime = undefined;
|
|
1501
|
+
this.spotNodeRuntime = undefined;
|
|
1502
|
+
this.streamRuntime = undefined;
|
|
1503
|
+
this.statefulAuthorityRoutes = undefined;
|
|
1504
|
+
this.cachedLocationSpotRouteResolver = undefined;
|
|
1505
|
+
this.lifecycleSink?.push('framework:stop');
|
|
1506
|
+
await statefulAuthorityRoutes?.stop();
|
|
1507
|
+
await stopRuntimeParts({
|
|
1508
|
+
state,
|
|
1509
|
+
locationSnapshot,
|
|
1510
|
+
cleanupDeadline: this.runtimeDeadline,
|
|
1511
|
+
streamRuntime,
|
|
1512
|
+
spotNodeRuntime,
|
|
1513
|
+
channelRuntime,
|
|
1514
|
+
serviceRelocation: this.serviceRelocation,
|
|
1515
|
+
ownedStores: registeredRuntimeStores(this.options.registration)
|
|
1516
|
+
});
|
|
1517
|
+
this.lifecycleSink?.push('framework:stopped');
|
|
1518
|
+
if (this.shutdownOperation === undefined) {
|
|
1519
|
+
this.setRuntimeState(ZLinkFrameworkRuntimeState.Stopped);
|
|
1520
|
+
}
|
|
1521
|
+
}
|
|
1522
|
+
|
|
1523
|
+
private installOwnerLeaseRecoveryPublication(
|
|
1524
|
+
runtime: ZLinkLocationRuntime,
|
|
1525
|
+
spotNodeRuntime: ZLinkSpotNodeRuntimeManager,
|
|
1526
|
+
channelRuntime: ZLinkChannelRuntimeManager
|
|
1527
|
+
): void {
|
|
1528
|
+
let publishing = false;
|
|
1529
|
+
let lastPublishedOwnerToken = runtime.currentOwnerToken;
|
|
1530
|
+
let recoveryRequired = false;
|
|
1531
|
+
let recoveringServices: Promise<void> | undefined;
|
|
1532
|
+
let stoppingServices: Promise<void> | undefined;
|
|
1533
|
+
let transportFence = Promise.resolve();
|
|
1534
|
+
const handler = () => {
|
|
1535
|
+
const ownerToken = runtime.currentOwnerToken;
|
|
1536
|
+
if (
|
|
1537
|
+
publishing
|
|
1538
|
+
|| ownerToken === undefined
|
|
1539
|
+
|| (ownerToken === lastPublishedOwnerToken && !recoveryRequired)
|
|
1540
|
+
) return;
|
|
1541
|
+
if (runtime.ownerLeaseUsable === false) return;
|
|
1542
|
+
publishing = true;
|
|
1543
|
+
const signal = this.executionState?.abortController.signal;
|
|
1544
|
+
const recoverServices = async (): Promise<void> => {
|
|
1545
|
+
if (stoppingServices !== undefined) {
|
|
1546
|
+
await stoppingServices;
|
|
1547
|
+
stoppingServices = undefined;
|
|
1548
|
+
}
|
|
1549
|
+
if (this.statefulAuthorityRoutes !== undefined) return;
|
|
1550
|
+
const store = this.locationOwner.currentStores?.locationStore;
|
|
1551
|
+
if (store === undefined || this.executionState === undefined) return;
|
|
1552
|
+
if (recoveringServices !== undefined) return await recoveringServices;
|
|
1553
|
+
recoveringServices = (async () => {
|
|
1554
|
+
if (this.requiresStatefulAuthorityRuntime()) {
|
|
1555
|
+
const routes = this.createStatefulAuthorityRoutes(store, spotNodeRuntime);
|
|
1556
|
+
await routes.start(this.executionState?.abortController.signal);
|
|
1557
|
+
this.statefulAuthorityRoutes = routes;
|
|
1558
|
+
}
|
|
1559
|
+
})();
|
|
1560
|
+
try {
|
|
1561
|
+
await recoveringServices;
|
|
1562
|
+
} finally {
|
|
1563
|
+
recoveringServices = undefined;
|
|
1564
|
+
}
|
|
1565
|
+
};
|
|
1566
|
+
void transportFence
|
|
1567
|
+
.then(() => spotNodeRuntime.publishMeshNodeState(
|
|
1568
|
+
ZLinkFrameworkRuntimeState.Preparing,
|
|
1569
|
+
signal
|
|
1570
|
+
))
|
|
1571
|
+
.then(() => recoverServices())
|
|
1572
|
+
.then(() => {
|
|
1573
|
+
const currentOwnerToken = runtime.currentOwnerToken;
|
|
1574
|
+
if (runtime.ownerLeaseUsable === false
|
|
1575
|
+
|| currentOwnerToken === undefined
|
|
1576
|
+
|| currentOwnerToken.ownerId !== ownerToken.ownerId
|
|
1577
|
+
|| currentOwnerToken.leaseGeneration !== ownerToken.leaseGeneration) {
|
|
1578
|
+
throw new Error('Owner lease changed during recovery.');
|
|
1579
|
+
}
|
|
1580
|
+
return spotNodeRuntime.publishMeshNodeState(this.runtimeState, signal);
|
|
1581
|
+
})
|
|
1582
|
+
.then(() => spotNodeRuntime.startLocationAutoConnect(signal))
|
|
1583
|
+
.then(() => channelRuntime.reclaimLocationOwnerRows(signal))
|
|
1584
|
+
.then(() => this.locationOwner.currentLifecycle?.reclaimOwnerRows() ?? Promise.resolve())
|
|
1585
|
+
.then(
|
|
1586
|
+
() => {
|
|
1587
|
+
lastPublishedOwnerToken = ownerToken;
|
|
1588
|
+
recoveryRequired = false;
|
|
1589
|
+
publishing = false;
|
|
1590
|
+
},
|
|
1591
|
+
error => {
|
|
1592
|
+
this.runtimeOrPreStartErrorSink.reportRuntimeTaskException(
|
|
1593
|
+
'owner lease recovery',
|
|
1594
|
+
error
|
|
1595
|
+
);
|
|
1596
|
+
publishing = false;
|
|
1597
|
+
}
|
|
1598
|
+
);
|
|
1599
|
+
};
|
|
1600
|
+
this.ownerLeaseRecoveryRuntime = runtime;
|
|
1601
|
+
this.ownerLeaseRecoveryHandler = handler;
|
|
1602
|
+
const failureHandler = () => {
|
|
1603
|
+
recoveryRequired = true;
|
|
1604
|
+
if (runtime.ownerLeaseUsable) return;
|
|
1605
|
+
// A Store failure invalidates new ownership and discovery work, but it
|
|
1606
|
+
// must not tear down transports that were already established. The
|
|
1607
|
+
// auto-connect reconciler applies storeFailureGraceMs to the last
|
|
1608
|
+
// complete descriptor set; fencing here would bypass that contract and
|
|
1609
|
+
// make existing requests fail during the grace window.
|
|
1610
|
+
const routes = this.statefulAuthorityRoutes;
|
|
1611
|
+
if (routes === undefined) return;
|
|
1612
|
+
this.statefulAuthorityRoutes = undefined;
|
|
1613
|
+
stoppingServices = routes.stop();
|
|
1614
|
+
void stoppingServices.catch(error =>
|
|
1615
|
+
this.runtimeOrPreStartErrorSink.reportRuntimeTaskException(
|
|
1616
|
+
'stateful authority route fencing',
|
|
1617
|
+
error
|
|
1618
|
+
));
|
|
1619
|
+
};
|
|
1620
|
+
this.ownerLeaseFailureHandler = failureHandler;
|
|
1621
|
+
runtime.addOwnerLeaseRenewedHandler(handler);
|
|
1622
|
+
if (typeof runtime.addOwnerLeaseRenewalFailedHandler === 'function') {
|
|
1623
|
+
runtime.addOwnerLeaseRenewalFailedHandler(failureHandler);
|
|
1624
|
+
}
|
|
1625
|
+
}
|
|
1626
|
+
|
|
1627
|
+
private createStatefulAuthorityRoutes(
|
|
1628
|
+
locationStore: import('../locations/domain-store-contract').ZLinkDomainLocationStore,
|
|
1629
|
+
spotNodeRuntime: ZLinkSpotNodeRuntimeManager
|
|
1630
|
+
): ZLinkStatefulAuthorityRouteRuntime {
|
|
1631
|
+
return new ZLinkStatefulAuthorityRouteRuntime({
|
|
1632
|
+
store: locationStore,
|
|
1633
|
+
creationStore: locationStore,
|
|
1634
|
+
relocationStore: this.options.registration.locations.relocationStoreInstance,
|
|
1635
|
+
meshNodes: spotNodeRuntime.meshNodesByName,
|
|
1636
|
+
pollingIntervalMs:
|
|
1637
|
+
this.options.registration.locations.options.pollingIntervalMs
|
|
1638
|
+
?? zlinkDefaultLocationOptions.pollingIntervalMs,
|
|
1639
|
+
pageSize: 1000,
|
|
1640
|
+
reportError: (error) =>
|
|
1641
|
+
this.runtimeOrPreStartErrorSink.reportRuntimeTaskException(
|
|
1642
|
+
'stateful authority route reconciliation',
|
|
1643
|
+
error
|
|
1644
|
+
),
|
|
1645
|
+
onSpotRouteChanged: (spotId) =>
|
|
1646
|
+
this.cachedLocationSpotRouteResolver?.invalidate?.(spotId)
|
|
1647
|
+
});
|
|
1648
|
+
}
|
|
1649
|
+
|
|
1650
|
+
private requiresStatefulAuthorityRuntime(): boolean {
|
|
1651
|
+
for (const options of this.options.registration.spotNodes.values()) {
|
|
1652
|
+
if (Object.keys(options.spotFactoryRegistrations ?? {}).length > 0
|
|
1653
|
+
|| Object.keys(options.instanceSpotFactoryRegistrations ?? {}).length > 0
|
|
1654
|
+
|| Object.keys(options.actorFactoryRegistrations ?? {}).length > 0) {
|
|
1655
|
+
return true;
|
|
1656
|
+
}
|
|
1657
|
+
}
|
|
1658
|
+
return false;
|
|
1659
|
+
}
|
|
1660
|
+
|
|
1661
|
+
private installLocationBackedAuthorities(
|
|
1662
|
+
locationStore: import('../locations/domain-store-contract').ZLinkDomainLocationStore,
|
|
1663
|
+
spotNodeRuntime: ZLinkSpotNodeRuntimeManager
|
|
1664
|
+
): void {
|
|
1665
|
+
for (const [meshName, node] of spotNodeRuntime.meshNodesByName) {
|
|
1666
|
+
const activationNode = node as typeof node & {
|
|
1667
|
+
registerAsyncInstanceActivationAuthority?: (
|
|
1668
|
+
authority: ServiceAsyncInstanceActivationAuthority
|
|
1669
|
+
) => void;
|
|
1670
|
+
registerInstanceIntent: (
|
|
1671
|
+
instanceType: string,
|
|
1672
|
+
route: import('../foundation/service-stateful-wire-codec').ServiceInstanceRouteFence,
|
|
1673
|
+
expectedCurrentRoute?: import('../foundation/service-stateful-wire-codec').ServiceInstanceRouteFence | null
|
|
1674
|
+
) => void;
|
|
1675
|
+
registerInstanceApplicationLifecycle?: (
|
|
1676
|
+
lifecycle: ServiceInstanceApplicationLifecycle
|
|
1677
|
+
) => void;
|
|
1678
|
+
};
|
|
1679
|
+
const spotManager = this.spotManager;
|
|
1680
|
+
if (spotManager !== undefined) {
|
|
1681
|
+
this.registerInstanceApplicationLifecycle(meshName, activationNode, spotManager);
|
|
1682
|
+
}
|
|
1683
|
+
activationNode.registerAsyncInstanceActivationAuthority?.(
|
|
1684
|
+
new ZLinkInstanceActivationAuthority({
|
|
1685
|
+
store: locationStore,
|
|
1686
|
+
relocationStore: this.options.registration.locations.relocationStoreInstance,
|
|
1687
|
+
meshName,
|
|
1688
|
+
owner: () => this.locationOwner.currentRuntime?.currentOwnerToken,
|
|
1689
|
+
metrics: this.metrics,
|
|
1690
|
+
onReady: (target, route) => {
|
|
1691
|
+
activationNode.registerInstanceIntent(target.stableType, route);
|
|
1692
|
+
this.locationOwner.currentLifecycle?.trackInstanceSpot({
|
|
1693
|
+
meshName,
|
|
1694
|
+
spotId: target.targetSpotId,
|
|
1695
|
+
stableType: target.stableType,
|
|
1696
|
+
nodeRid: route.targetNodeRid,
|
|
1697
|
+
nodeGeneration: route.targetNodeGeneration,
|
|
1698
|
+
objectGeneration: route.objectGeneration,
|
|
1699
|
+
authorityOwnerGeneration: route.authorityOwnerGeneration,
|
|
1700
|
+
ownerId: route.ownerId,
|
|
1701
|
+
ownerLeaseGeneration: route.leaseGeneration,
|
|
1702
|
+
storeVersion: route.storeVersion,
|
|
1703
|
+
deactivate: async () => {
|
|
1704
|
+
await spotManager?.close(meshName, target.targetSpotId as never);
|
|
1705
|
+
}
|
|
1706
|
+
});
|
|
1707
|
+
}
|
|
1708
|
+
})
|
|
1709
|
+
);
|
|
1710
|
+
}
|
|
1711
|
+
}
|
|
1712
|
+
|
|
1713
|
+
private removeOwnerLeaseRecoveryPublication(): void {
|
|
1714
|
+
if (this.ownerLeaseRecoveryRuntime !== undefined && this.ownerLeaseRecoveryHandler !== undefined) {
|
|
1715
|
+
this.ownerLeaseRecoveryRuntime.removeOwnerLeaseRenewedHandler(this.ownerLeaseRecoveryHandler);
|
|
1716
|
+
}
|
|
1717
|
+
if (this.ownerLeaseRecoveryRuntime !== undefined && this.ownerLeaseFailureHandler !== undefined) {
|
|
1718
|
+
if (typeof this.ownerLeaseRecoveryRuntime.removeOwnerLeaseRenewalFailedHandler === 'function') {
|
|
1719
|
+
this.ownerLeaseRecoveryRuntime.removeOwnerLeaseRenewalFailedHandler(this.ownerLeaseFailureHandler);
|
|
1720
|
+
}
|
|
1721
|
+
}
|
|
1722
|
+
this.ownerLeaseRecoveryRuntime = undefined;
|
|
1723
|
+
this.ownerLeaseRecoveryHandler = undefined;
|
|
1724
|
+
this.ownerLeaseFailureHandler = undefined;
|
|
1725
|
+
}
|
|
1726
|
+
|
|
1727
|
+
async onApplicationBootstrap(): Promise<void> {
|
|
1728
|
+
await this.start();
|
|
1729
|
+
}
|
|
1730
|
+
|
|
1731
|
+
async onApplicationShutdown(): Promise<void> {
|
|
1732
|
+
await this.shutdown();
|
|
1733
|
+
}
|
|
1734
|
+
|
|
1735
|
+
private async performMeshDrain(
|
|
1736
|
+
meshName: string,
|
|
1737
|
+
signal: AbortSignal,
|
|
1738
|
+
stopStartingSignal?: AbortSignal
|
|
1739
|
+
): Promise<void> {
|
|
1740
|
+
await this.serviceRelocation.relocateMesh(
|
|
1741
|
+
meshName,
|
|
1742
|
+
this.relocationTargetApplicationVersion,
|
|
1743
|
+
signal,
|
|
1744
|
+
stopStartingSignal
|
|
1745
|
+
);
|
|
1746
|
+
}
|
|
1747
|
+
|
|
1748
|
+
private async performMeshShutdown(meshName: string, signal: AbortSignal): Promise<void> {
|
|
1749
|
+
await this.spotManager?.drainForShutdown(meshName, signal, this.runtimeDeadline);
|
|
1750
|
+
await awaitWithDrainSignal(
|
|
1751
|
+
this.streamRuntime?.notifyServerDrain(meshName),
|
|
1752
|
+
signal
|
|
1753
|
+
);
|
|
1754
|
+
}
|
|
1755
|
+
|
|
1756
|
+
private async publishMeshRetiring(
|
|
1757
|
+
meshName: string,
|
|
1758
|
+
signal?: AbortSignal
|
|
1759
|
+
): Promise<void> {
|
|
1760
|
+
await this.spotNodeRuntime?.publishMeshNodeState(
|
|
1761
|
+
ZLinkFrameworkRuntimeState.Relocating,
|
|
1762
|
+
signal,
|
|
1763
|
+
meshName
|
|
1764
|
+
);
|
|
1765
|
+
}
|
|
1766
|
+
|
|
1767
|
+
private async publishMeshServing(
|
|
1768
|
+
meshName: string,
|
|
1769
|
+
signal?: AbortSignal
|
|
1770
|
+
): Promise<void> {
|
|
1771
|
+
await this.spotNodeRuntime?.reconcileAndPublishMeshNodeState(
|
|
1772
|
+
ZLinkFrameworkRuntimeState.Serving,
|
|
1773
|
+
meshName,
|
|
1774
|
+
signal
|
|
1775
|
+
);
|
|
1776
|
+
// A failed relocation rolls the local object barriers back before the
|
|
1777
|
+
// descriptor is published as Serving. Reconcile the durable authority
|
|
1778
|
+
// routes before returning so the next local request cannot observe the
|
|
1779
|
+
// brief window where the Location row is ready but the route cache still
|
|
1780
|
+
// reflects the failed capture.
|
|
1781
|
+
await this.statefulAuthorityRoutes?.reconcile(signal);
|
|
1782
|
+
}
|
|
1783
|
+
|
|
1784
|
+
private async publishMeshDraining(
|
|
1785
|
+
meshName: string,
|
|
1786
|
+
signal?: AbortSignal
|
|
1787
|
+
): Promise<void> {
|
|
1788
|
+
const node = this.spotNodeRuntime?.meshNode(meshName);
|
|
1789
|
+
if (node !== undefined) {
|
|
1790
|
+
await node.publishDraining?.();
|
|
1791
|
+
}
|
|
1792
|
+
await this.spotNodeRuntime?.publishMeshNodeState(
|
|
1793
|
+
ZLinkFrameworkRuntimeState.Draining,
|
|
1794
|
+
signal,
|
|
1795
|
+
meshName
|
|
1796
|
+
);
|
|
1797
|
+
}
|
|
1798
|
+
|
|
1799
|
+
private async preflightAutomaticPeerReadiness(
|
|
1800
|
+
deadlineAt: number,
|
|
1801
|
+
targetApplicationVersion: bigint
|
|
1802
|
+
): Promise<ZLinkFrameworkRelocationReason | undefined> {
|
|
1803
|
+
// A host with no local stateful workload has nothing to move. The public
|
|
1804
|
+
// Relocate contract completes that case without requiring a replacement
|
|
1805
|
+
// target; the host drain still publishes its retiring state below.
|
|
1806
|
+
if (!this.hasLocalStatefulRelocationWork()) return undefined;
|
|
1807
|
+
if (this.options.registration.spotNodes.size === 0) return undefined;
|
|
1808
|
+
const location = this.locationOwner.currentRuntime;
|
|
1809
|
+
if (location === undefined) return ZLinkFrameworkRelocationReason.StoreUnavailable;
|
|
1810
|
+
|
|
1811
|
+
let storeUnavailable = false;
|
|
1812
|
+
while (performance.now() < deadlineAt) {
|
|
1813
|
+
try {
|
|
1814
|
+
if (await this.hasExactAutomaticPeerReadiness(
|
|
1815
|
+
location,
|
|
1816
|
+
targetApplicationVersion
|
|
1817
|
+
)) return undefined;
|
|
1818
|
+
storeUnavailable = false;
|
|
1819
|
+
} catch {
|
|
1820
|
+
storeUnavailable = true;
|
|
1821
|
+
}
|
|
1822
|
+
await new Promise((resolve) => setTimeout(
|
|
1823
|
+
resolve,
|
|
1824
|
+
Math.min(
|
|
1825
|
+
this.options.registration.locations.options.pollingIntervalMs
|
|
1826
|
+
?? zlinkDefaultLocationOptions.pollingIntervalMs,
|
|
1827
|
+
Math.max(1, deadlineAt - performance.now())
|
|
1828
|
+
)
|
|
1829
|
+
));
|
|
1830
|
+
}
|
|
1831
|
+
return storeUnavailable
|
|
1832
|
+
? ZLinkFrameworkRelocationReason.StoreUnavailable
|
|
1833
|
+
: ZLinkFrameworkRelocationReason.TargetUnavailable;
|
|
1834
|
+
}
|
|
1835
|
+
|
|
1836
|
+
private hasLocalStatefulRelocationWork(): boolean {
|
|
1837
|
+
const spotManager = this.spotManager;
|
|
1838
|
+
if (spotManager !== undefined) {
|
|
1839
|
+
for (const meshName of this.options.registration.spotNodes.keys()) {
|
|
1840
|
+
if (spotManager.relocationActivations(meshName).length > 0) return true;
|
|
1841
|
+
}
|
|
1842
|
+
}
|
|
1843
|
+
return this.actorManager?.snapshotStates().some((state) => state.hasActorOrCreation) ?? false;
|
|
1844
|
+
}
|
|
1845
|
+
|
|
1846
|
+
private async hasExactAutomaticPeerReadiness(
|
|
1847
|
+
location: Pick<ZLinkLocationRuntime, 'listLiveMeshNodes'>,
|
|
1848
|
+
targetApplicationVersion: bigint
|
|
1849
|
+
): Promise<boolean> {
|
|
1850
|
+
for (const [meshName, registration] of this.options.registration.spotNodes) {
|
|
1851
|
+
if ((registration.router?.manualConnections?.length ?? 0) > 0
|
|
1852
|
+
|| (registration.router?.manualPeerConnections?.length ?? 0) > 0) {
|
|
1853
|
+
continue;
|
|
1854
|
+
}
|
|
1855
|
+
const node = this.spotNodeRuntime?.meshNode(meshName);
|
|
1856
|
+
if (node === undefined) return false;
|
|
1857
|
+
const local = node.status();
|
|
1858
|
+
const localDescriptor = this.spotNodeRuntime?.meshNodeDescriptor(meshName);
|
|
1859
|
+
if (localDescriptor === undefined) return false;
|
|
1860
|
+
const descriptors = await location.listLiveMeshNodes(meshName);
|
|
1861
|
+
const peers = node.peers();
|
|
1862
|
+
if (!hasExactPeerReadiness(descriptors, {
|
|
1863
|
+
...local,
|
|
1864
|
+
applicationVersion: targetApplicationVersion,
|
|
1865
|
+
maintenanceWave: localDescriptor.maintenanceWave
|
|
1866
|
+
}, peers)) return false;
|
|
1867
|
+
}
|
|
1868
|
+
return true;
|
|
1869
|
+
}
|
|
1870
|
+
|
|
1871
|
+
private async publishHostRelocated(): Promise<void> {
|
|
1872
|
+
await Promise.all([...this.options.registration.spotNodes.keys()].map(meshName =>
|
|
1873
|
+
this.spotNodeRuntime?.publishMeshNodeState(
|
|
1874
|
+
ZLinkFrameworkRuntimeState.Relocated,
|
|
1875
|
+
undefined,
|
|
1876
|
+
meshName
|
|
1877
|
+
)));
|
|
1878
|
+
}
|
|
1879
|
+
|
|
1880
|
+
private async publishHostDraining(signal: AbortSignal): Promise<void> {
|
|
1881
|
+
try {
|
|
1882
|
+
const runtime = this.locationOwner.currentRuntime;
|
|
1883
|
+
if (runtime !== undefined && !await runtime.publishDraining(signal)) {
|
|
1884
|
+
throw new Error('Draining descriptor publication returned false.');
|
|
1885
|
+
}
|
|
1886
|
+
} catch (error) {
|
|
1887
|
+
throw new ZLinkDrainingStatePublishError(error);
|
|
1888
|
+
}
|
|
1889
|
+
}
|
|
1890
|
+
|
|
1891
|
+
private async cleanupOwnerForDrain(signal: AbortSignal): Promise<void> {
|
|
1892
|
+
const runtime = this.locationOwner.currentRuntime;
|
|
1893
|
+
if (runtime === undefined) return;
|
|
1894
|
+
try {
|
|
1895
|
+
await runtime.cleanupOwner(signal);
|
|
1896
|
+
} catch (error) {
|
|
1897
|
+
throw new ZLinkOwnerCleanupError(error);
|
|
1898
|
+
}
|
|
1899
|
+
}
|
|
1900
|
+
|
|
1901
|
+
private async forceStopMesh(meshName: string): Promise<void> {
|
|
1902
|
+
await waitForForcedSessionNotification(this.streamRuntime?.notifyServerDrain(meshName));
|
|
1903
|
+
await this.spotManager?.drainForShutdown(meshName, undefined, this.runtimeDeadline);
|
|
1904
|
+
}
|
|
1905
|
+
|
|
1906
|
+
private registerInstanceApplicationLifecycle(
|
|
1907
|
+
meshName: string,
|
|
1908
|
+
node: ZLinkBackendMeshNode,
|
|
1909
|
+
spotManager: DefaultZLinkSpotManager
|
|
1910
|
+
): void {
|
|
1911
|
+
const activationNode = node as typeof node & {
|
|
1912
|
+
registerInstanceApplicationLifecycle?: (
|
|
1913
|
+
lifecycle: ServiceInstanceApplicationLifecycle
|
|
1914
|
+
) => void;
|
|
1915
|
+
};
|
|
1916
|
+
activationNode.registerInstanceApplicationLifecycle?.({
|
|
1917
|
+
isMaterialized: (target) =>
|
|
1918
|
+
spotManager.isInstanceMaterialized(
|
|
1919
|
+
meshName,
|
|
1920
|
+
target.stableType,
|
|
1921
|
+
target.targetSpotId as never
|
|
1922
|
+
),
|
|
1923
|
+
isMaterializing: (target) =>
|
|
1924
|
+
spotManager.isInstanceMaterializing(
|
|
1925
|
+
meshName,
|
|
1926
|
+
target.targetSpotId as never
|
|
1927
|
+
),
|
|
1928
|
+
isClosing: (target) =>
|
|
1929
|
+
spotManager.isInstanceClosing(
|
|
1930
|
+
meshName,
|
|
1931
|
+
target.targetSpotId as never
|
|
1932
|
+
),
|
|
1933
|
+
isIdleEvicting: (target) =>
|
|
1934
|
+
spotManager.isInstanceSpotIdleEvicting(
|
|
1935
|
+
meshName,
|
|
1936
|
+
target.targetSpotId as never
|
|
1937
|
+
),
|
|
1938
|
+
beginIdleEviction: (target) =>
|
|
1939
|
+
spotManager.beginInstanceSpotIdleEviction(
|
|
1940
|
+
meshName,
|
|
1941
|
+
target.targetSpotId as never
|
|
1942
|
+
),
|
|
1943
|
+
materialize: (target, objectGeneration) =>
|
|
1944
|
+
spotManager.materializeInstance(
|
|
1945
|
+
meshName,
|
|
1946
|
+
target.stableType,
|
|
1947
|
+
target.targetSpotId as never,
|
|
1948
|
+
objectGeneration,
|
|
1949
|
+
this.executionState?.abortController.signal
|
|
1950
|
+
),
|
|
1951
|
+
discard: (target) =>
|
|
1952
|
+
spotManager.discardInstance(meshName, target.targetSpotId as never),
|
|
1953
|
+
beginTerminal: (target) =>
|
|
1954
|
+
spotManager.beginInstanceTerminal(
|
|
1955
|
+
meshName,
|
|
1956
|
+
target.targetSpotId as never,
|
|
1957
|
+
target.objectGeneration
|
|
1958
|
+
),
|
|
1959
|
+
completeTerminal: (target) =>
|
|
1960
|
+
spotManager.completeInstanceTerminal(
|
|
1961
|
+
meshName,
|
|
1962
|
+
target.targetSpotId as never,
|
|
1963
|
+
target.objectGeneration
|
|
1964
|
+
)
|
|
1965
|
+
});
|
|
1966
|
+
}
|
|
1967
|
+
|
|
1968
|
+
setActorManager(actorManager: DefaultZLinkActorManager): void {
|
|
1969
|
+
this.actorManager = actorManager;
|
|
1970
|
+
}
|
|
1971
|
+
|
|
1972
|
+
setSpotManager(spotManager: DefaultZLinkSpotManager): void {
|
|
1973
|
+
this.spotManager = spotManager;
|
|
1974
|
+
for (const [meshName, node] of this.spotNodeRuntime?.meshNodesByName ?? []) {
|
|
1975
|
+
this.registerInstanceApplicationLifecycle(meshName, node, spotManager);
|
|
1976
|
+
}
|
|
1977
|
+
}
|
|
1978
|
+
|
|
1979
|
+
createActorManagerOptions(): Pick<
|
|
1980
|
+
ZLinkActorManagerOptions,
|
|
1981
|
+
| 'joinCoordinator'
|
|
1982
|
+
| 'actorMeshNameProvider'
|
|
1983
|
+
| 'actorLeaveSpot'
|
|
1984
|
+
| 'messageSerializers'
|
|
1985
|
+
| 'nativeActorNode'
|
|
1986
|
+
| 'nativeActorNodeProvider'
|
|
1987
|
+
| 'actorCreatedNodeRidProvider'
|
|
1988
|
+
| 'actorRefResolver'
|
|
1989
|
+
| 'actorCreatedNotifier'
|
|
1990
|
+
| 'actorDestroyedCleanup'
|
|
1991
|
+
| 'locationLifecycle'
|
|
1992
|
+
| 'boundSessionFactory'
|
|
1993
|
+
| 'shutdownSignal'
|
|
1994
|
+
| 'admission'
|
|
1995
|
+
| 'placementCreate'
|
|
1996
|
+
> {
|
|
1997
|
+
this.ensureLocationRuntime();
|
|
1998
|
+
return {
|
|
1999
|
+
...this.actorRuntimeOptionsFactory().createActorManagerOptions(),
|
|
2000
|
+
placementCreate: async (actorId, actorType, createOnly, call, signal) => {
|
|
2001
|
+
const placement = this.actorPlacement;
|
|
2002
|
+
if (placement === undefined) {
|
|
2003
|
+
throw new ZLinkConfigurationException(
|
|
2004
|
+
'Actor placement runtime is not initialized.'
|
|
2005
|
+
);
|
|
2006
|
+
}
|
|
2007
|
+
const requestPayload = encodeFrameworkCreationPayload(
|
|
2008
|
+
call.request,
|
|
2009
|
+
this.options.registration.messageSerializers
|
|
2010
|
+
);
|
|
2011
|
+
return await placement.create(
|
|
2012
|
+
actorId,
|
|
2013
|
+
actorType,
|
|
2014
|
+
createOnly,
|
|
2015
|
+
call.meshName,
|
|
2016
|
+
requestPayload,
|
|
2017
|
+
call.timeoutMs,
|
|
2018
|
+
signal
|
|
2019
|
+
);
|
|
2020
|
+
}
|
|
2021
|
+
};
|
|
2022
|
+
}
|
|
2023
|
+
|
|
2024
|
+
createActorClientOptions(): ConstructorParameters<typeof DefaultZLinkActorClient>[0] {
|
|
2025
|
+
this.ensureLocationRuntime();
|
|
2026
|
+
const options = this.actorRuntimeOptionsFactory().createActorClientOptions();
|
|
2027
|
+
this.actorClientLocationResolver = options.locationResolver();
|
|
2028
|
+
return options;
|
|
2029
|
+
}
|
|
2030
|
+
|
|
2031
|
+
createLocationHandleResolver(): ZLinkStoreLocationResolvers | undefined {
|
|
2032
|
+
this.ensureLocationRuntime();
|
|
2033
|
+
return this.locationOwner.createRefResolver(this.meshRouters.spotLocationMeshNames());
|
|
2034
|
+
}
|
|
2035
|
+
|
|
2036
|
+
createSpotManagerOptions(): Partial<ZLinkSpotManagerOptions> {
|
|
2037
|
+
this.ensureLocationRuntime();
|
|
2038
|
+
return {
|
|
2039
|
+
...new ZLinkSpotRuntimeOptionsFactory({
|
|
2040
|
+
registration: this.options.registration,
|
|
2041
|
+
channelTransport: this.channelTransport,
|
|
2042
|
+
routeTransport: this.routeTransport,
|
|
2043
|
+
addressTransport: this.spotAddressTransport,
|
|
2044
|
+
spotPublisherTransport: this.spotPublisherTransport,
|
|
2045
|
+
meshRouters: this.meshRouters,
|
|
2046
|
+
runtimeEventPublisher: this.runtimeEventPublisher,
|
|
2047
|
+
spotNodeRuntime: () => this.spotNodeRuntime,
|
|
2048
|
+
actorManager: () => this.actorManager,
|
|
2049
|
+
// User Spot visibility is published only by the generic authority
|
|
2050
|
+
// coordinator after application initialization. The legacy location
|
|
2051
|
+
// claim would expose a Creating object before that Ready barrier.
|
|
2052
|
+
locationLifecycle: () => undefined,
|
|
2053
|
+
releaseInstanceAuthority: (meshName, spotId, objectGeneration) =>
|
|
2054
|
+
this.locationOwner.currentLifecycle?.releaseSpot(meshName, spotId, objectGeneration)
|
|
2055
|
+
?? Promise.resolve(),
|
|
2056
|
+
beginInstanceIdleClosingAuthority: (meshName, spotId) =>
|
|
2057
|
+
this.locationOwner.currentLifecycle?.beginInstanceSpotClosing(meshName, spotId)
|
|
2058
|
+
?? Promise.resolve(undefined),
|
|
2059
|
+
beginInstanceClosingAuthority: (meshName, spotId) =>
|
|
2060
|
+
this.locationOwner.currentLifecycle?.beginInstanceSpotClosing(meshName, spotId)
|
|
2061
|
+
?? Promise.resolve(undefined),
|
|
2062
|
+
createLocationSpotRouteResolver: () => this.createLocationSpotRouteResolver(),
|
|
2063
|
+
boundSessionRelay: this.boundSessionRelay,
|
|
2064
|
+
actorHandoff: this.actorHandoff,
|
|
2065
|
+
dispatchErrorReporter: (errorSink) => this.createDispatchErrorReporter(errorSink),
|
|
2066
|
+
runtimeOrPreStartErrorSink: this.runtimeOrPreStartErrorSink,
|
|
2067
|
+
detachedTaskRunner: this.detachedTaskRunner(),
|
|
2068
|
+
metrics: this.metrics,
|
|
2069
|
+
admission: this.admission,
|
|
2070
|
+
statefulExecutionAllowed: () => {
|
|
2071
|
+
const locationRuntime = this.locationOwner.currentRuntime;
|
|
2072
|
+
if (locationRuntime !== undefined) return locationRuntime.ownerLeaseUsable;
|
|
2073
|
+
// A host configured with a Location Store must not execute stateful
|
|
2074
|
+
// timers while its lease runtime is unavailable. Hosts without a
|
|
2075
|
+
// Location Store have no owner lease to fence.
|
|
2076
|
+
return this.locationOwner.currentStores?.locationStore === undefined;
|
|
2077
|
+
}
|
|
2078
|
+
}).create(this.actorTransferRuntime),
|
|
2079
|
+
activationConcurrencyLimitProvider: (meshName: string) =>
|
|
2080
|
+
this.options.registration.spotNodes.get(meshName)?.activationConcurrencyLimit ?? 128,
|
|
2081
|
+
onInstanceActivationConcurrencyChanged: (meshName: string) => {
|
|
2082
|
+
void this.spotNodeRuntime?.publishMeshNodeState(
|
|
2083
|
+
this.runtimeState,
|
|
2084
|
+
this.executionState?.abortController.signal,
|
|
2085
|
+
meshName
|
|
2086
|
+
).catch(() => undefined);
|
|
2087
|
+
}
|
|
2088
|
+
};
|
|
2089
|
+
}
|
|
2090
|
+
|
|
2091
|
+
createPublicSpotManager(local: DefaultZLinkSpotManager): import('../../contracts').ZLinkSpotManager {
|
|
2092
|
+
const locationStore = this.locationOwner.locationStore();
|
|
2093
|
+
if (locationStore === undefined) {
|
|
2094
|
+
throw new ZLinkConfigurationException(
|
|
2095
|
+
'User Spot creation requires a Location Store.'
|
|
2096
|
+
);
|
|
2097
|
+
}
|
|
2098
|
+
this.actorPlacement ??= new ZLinkActorPlacementCoordinator({
|
|
2099
|
+
store: locationStore,
|
|
2100
|
+
remoteCreate: (meshName, targetNodeRid, request, timeoutMs) => {
|
|
2101
|
+
const node = this.spotNodeRuntime?.meshNode(meshName);
|
|
2102
|
+
if (node === undefined) {
|
|
2103
|
+
throw createInternalFrameworkException(
|
|
2104
|
+
ZLinkFrameworkInternalErrorKind.ObjectClientNotConfigured,
|
|
2105
|
+
`RouteMesh '${meshName}' has no local client node.`
|
|
2106
|
+
);
|
|
2107
|
+
}
|
|
2108
|
+
return node.requestActorCreate(targetNodeRid, request, timeoutMs);
|
|
2109
|
+
},
|
|
2110
|
+
decodeRemoteReply: payload => {
|
|
2111
|
+
const message = RuntimeMessage.from(payload);
|
|
2112
|
+
try {
|
|
2113
|
+
return decodeFrameworkPayloadMessage(
|
|
2114
|
+
message,
|
|
2115
|
+
this.options.registration.messageSerializers
|
|
2116
|
+
);
|
|
2117
|
+
} finally {
|
|
2118
|
+
message.close();
|
|
2119
|
+
}
|
|
2120
|
+
},
|
|
2121
|
+
target: async (requestedMesh, stableType, signal, excludedNodeRids) => {
|
|
2122
|
+
const clientMeshes = [...this.options.registration.spotNodes]
|
|
2123
|
+
.filter(([, node]) => hasObjectClientCapability(node.objectRole))
|
|
2124
|
+
.map(([meshName]) => meshName);
|
|
2125
|
+
const meshes = requestedMesh === undefined ? clientMeshes : [requestedMesh];
|
|
2126
|
+
if (meshes.length === 0) {
|
|
2127
|
+
throw createInternalFrameworkException(
|
|
2128
|
+
ZLinkFrameworkInternalErrorKind.ObjectClientNotConfigured,
|
|
2129
|
+
'No object-client RouteMesh is configured.'
|
|
2130
|
+
);
|
|
2131
|
+
}
|
|
2132
|
+
if (requestedMesh === undefined && meshes.length > 1) {
|
|
2133
|
+
throw createInternalFrameworkException(
|
|
2134
|
+
ZLinkFrameworkInternalErrorKind.MeshSelectionRequired,
|
|
2135
|
+
'Multiple object-client RouteMeshes are configured; call inMesh(...).'
|
|
2136
|
+
);
|
|
2137
|
+
}
|
|
2138
|
+
const meshName = meshes[0]!;
|
|
2139
|
+
if (!clientMeshes.includes(meshName)) {
|
|
2140
|
+
throw createInternalFrameworkException(
|
|
2141
|
+
ZLinkFrameworkInternalErrorKind.ObjectClientNotConfigured,
|
|
2142
|
+
`RouteMesh '${meshName}' has no object-client role.`
|
|
2143
|
+
);
|
|
2144
|
+
}
|
|
2145
|
+
const meshNode = this.spotNodeRuntime?.meshNode(meshName);
|
|
2146
|
+
const descriptors = (await locationStore.listMeshNodes(meshName, undefined, signal)).items;
|
|
2147
|
+
const selected = await selectReadyLocationPlacementDescriptor(
|
|
2148
|
+
descriptors,
|
|
2149
|
+
meshNode,
|
|
2150
|
+
signal,
|
|
2151
|
+
descriptor => {
|
|
2152
|
+
const capability = descriptor.objectCapabilities.find(candidate =>
|
|
2153
|
+
candidate.objectKind === 'actor'
|
|
2154
|
+
&& candidate.stableType === stableType);
|
|
2155
|
+
const actors = descriptor.populationCapacity.actors;
|
|
2156
|
+
return descriptor.state === ZLinkFrameworkRuntimeState.Serving
|
|
2157
|
+
&& descriptor.objectRole === 'server'
|
|
2158
|
+
&& descriptor.placementWeight > 0
|
|
2159
|
+
&& descriptor.entrySpotId !== undefined
|
|
2160
|
+
&& excludedNodeRids?.has(String(descriptor.rid)) !== true
|
|
2161
|
+
&& (actors.limit === 0 || actors.active + actors.reserved < actors.limit)
|
|
2162
|
+
&& capability !== undefined;
|
|
2163
|
+
}
|
|
2164
|
+
);
|
|
2165
|
+
if (selected === undefined) return undefined;
|
|
2166
|
+
const localStatus = meshNode?.status();
|
|
2167
|
+
return {
|
|
2168
|
+
meshName,
|
|
2169
|
+
nodeRid: selected.rid,
|
|
2170
|
+
nodeGeneration: selected.lifecycleGeneration,
|
|
2171
|
+
entrySpotId: selected.entrySpotId!,
|
|
2172
|
+
owner: {
|
|
2173
|
+
ownerId: selected.ownerId,
|
|
2174
|
+
leaseGeneration: selected.leaseGeneration
|
|
2175
|
+
},
|
|
2176
|
+
isLocal: localStatus !== undefined
|
|
2177
|
+
&& String(localStatus.routingId) === String(selected.rid)
|
|
2178
|
+
&& localStatus.lifecycleGeneration === selected.lifecycleGeneration
|
|
2179
|
+
};
|
|
2180
|
+
}
|
|
2181
|
+
});
|
|
2182
|
+
const coordinator = new ZLinkUserSpotCreationCoordinator({
|
|
2183
|
+
store: locationStore,
|
|
2184
|
+
publishReadyRoute: (meshName, route) => {
|
|
2185
|
+
this.cachedLocationSpotRouteResolver?.invalidate?.(route.spot.spotId);
|
|
2186
|
+
this.spotNodeRuntime?.meshNode(meshName)?.rememberSpotRoute?.(route);
|
|
2187
|
+
},
|
|
2188
|
+
forgetReadyRoute: (meshName, route) => {
|
|
2189
|
+
this.cachedLocationSpotRouteResolver?.invalidate?.(route.spot.spotId);
|
|
2190
|
+
this.spotNodeRuntime?.meshNode(meshName)?.forgetSpotRoute?.(
|
|
2191
|
+
route.spot,
|
|
2192
|
+
route.authorityOwnerGeneration,
|
|
2193
|
+
route.storeVersion
|
|
2194
|
+
);
|
|
2195
|
+
},
|
|
2196
|
+
remoteCreate: (meshName, targetNodeRid, request, timeoutMs) => {
|
|
2197
|
+
const node = this.spotNodeRuntime?.meshNode(meshName);
|
|
2198
|
+
if (node === undefined) {
|
|
2199
|
+
throw createInternalFrameworkException(
|
|
2200
|
+
ZLinkFrameworkInternalErrorKind.ObjectClientNotConfigured,
|
|
2201
|
+
`RouteMesh '${meshName}' has no local client node.`
|
|
2202
|
+
);
|
|
2203
|
+
}
|
|
2204
|
+
return node.requestUserSpotCreate(targetNodeRid, request, timeoutMs);
|
|
2205
|
+
},
|
|
2206
|
+
decodeRemoteReply: payload => {
|
|
2207
|
+
const message = RuntimeMessage.from(payload);
|
|
2208
|
+
try {
|
|
2209
|
+
return decodeFrameworkPayloadMessage(
|
|
2210
|
+
message,
|
|
2211
|
+
this.options.registration.messageSerializers
|
|
2212
|
+
);
|
|
2213
|
+
} finally {
|
|
2214
|
+
message.close();
|
|
2215
|
+
}
|
|
2216
|
+
},
|
|
2217
|
+
target: async (request, signal, excludedNodeRids) => {
|
|
2218
|
+
const clientMeshes = [...this.options.registration.spotNodes]
|
|
2219
|
+
.filter(([, node]) => hasObjectClientCapability(node.objectRole))
|
|
2220
|
+
.map(([meshName]) => meshName);
|
|
2221
|
+
const meshes = request.meshName === undefined ? clientMeshes : [request.meshName];
|
|
2222
|
+
if (meshes.length === 0) {
|
|
2223
|
+
throw createInternalFrameworkException(
|
|
2224
|
+
ZLinkFrameworkInternalErrorKind.ObjectClientNotConfigured,
|
|
2225
|
+
'No object-client RouteMesh is configured.'
|
|
2226
|
+
);
|
|
2227
|
+
}
|
|
2228
|
+
if (request.meshName === undefined && meshes.length > 1) {
|
|
2229
|
+
throw createInternalFrameworkException(
|
|
2230
|
+
ZLinkFrameworkInternalErrorKind.MeshSelectionRequired,
|
|
2231
|
+
'Multiple object-client RouteMeshes are configured; call inMesh(...).'
|
|
2232
|
+
);
|
|
2233
|
+
}
|
|
2234
|
+
const meshName = meshes[0]!;
|
|
2235
|
+
if (!this.options.registration.spotNodes.has(meshName)) {
|
|
2236
|
+
throw createInternalFrameworkException(
|
|
2237
|
+
ZLinkFrameworkInternalErrorKind.MeshNotFound,
|
|
2238
|
+
`RouteMesh '${meshName}' is not configured.`
|
|
2239
|
+
);
|
|
2240
|
+
}
|
|
2241
|
+
if (!clientMeshes.includes(meshName)) {
|
|
2242
|
+
throw createInternalFrameworkException(
|
|
2243
|
+
ZLinkFrameworkInternalErrorKind.ObjectClientNotConfigured,
|
|
2244
|
+
`RouteMesh '${meshName}' has no object-client role.`
|
|
2245
|
+
);
|
|
2246
|
+
}
|
|
2247
|
+
const meshNode = this.spotNodeRuntime?.meshNode(meshName);
|
|
2248
|
+
const descriptors = (await locationStore.listMeshNodes(meshName, undefined, signal)).items;
|
|
2249
|
+
const selected = await selectReadyLocationPlacementDescriptor(
|
|
2250
|
+
descriptors,
|
|
2251
|
+
meshNode,
|
|
2252
|
+
signal,
|
|
2253
|
+
descriptor => {
|
|
2254
|
+
const capability = descriptor.objectCapabilities.find(candidate =>
|
|
2255
|
+
candidate.objectKind === 'user_spot'
|
|
2256
|
+
&& candidate.stableType === request.stableType);
|
|
2257
|
+
const spotTypeCapacity = descriptor.populationCapacity.spotTypes.find(candidate =>
|
|
2258
|
+
candidate.objectKind === 'user_spot'
|
|
2259
|
+
&& candidate.stableType === request.stableType);
|
|
2260
|
+
const spots = descriptor.populationCapacity.spots;
|
|
2261
|
+
return descriptor.state === 1
|
|
2262
|
+
&& descriptor.objectRole === 'server'
|
|
2263
|
+
&& descriptor.placementWeight > 0
|
|
2264
|
+
&& excludedNodeRids?.has(String(descriptor.rid)) !== true
|
|
2265
|
+
&& (spots.limit === 0 || spots.active + spots.reserved < spots.limit)
|
|
2266
|
+
&& capability !== undefined
|
|
2267
|
+
&& (spotTypeCapacity === undefined
|
|
2268
|
+
|| spotTypeCapacity.limit === 0
|
|
2269
|
+
|| spotTypeCapacity.active + spotTypeCapacity.reserved
|
|
2270
|
+
< spotTypeCapacity.limit);
|
|
2271
|
+
}
|
|
2272
|
+
);
|
|
2273
|
+
if (selected === undefined) return undefined;
|
|
2274
|
+
const localStatus = meshNode?.status();
|
|
2275
|
+
return {
|
|
2276
|
+
meshName,
|
|
2277
|
+
nodeRid: selected.rid,
|
|
2278
|
+
nodeGeneration: selected.lifecycleGeneration,
|
|
2279
|
+
owner: {
|
|
2280
|
+
ownerId: selected.ownerId,
|
|
2281
|
+
leaseGeneration: selected.leaseGeneration
|
|
2282
|
+
},
|
|
2283
|
+
isLocal: localStatus !== undefined
|
|
2284
|
+
&& String(localStatus.routingId) === String(selected.rid)
|
|
2285
|
+
&& localStatus.lifecycleGeneration === selected.lifecycleGeneration
|
|
2286
|
+
};
|
|
2287
|
+
}
|
|
2288
|
+
});
|
|
2289
|
+
const factories = new Map(
|
|
2290
|
+
[...this.options.registration.spotNodes].map(([meshName, node]) => [
|
|
2291
|
+
meshName,
|
|
2292
|
+
new Map(Object.entries(node.spotFactoryRegistrations ?? {}))
|
|
2293
|
+
])
|
|
2294
|
+
);
|
|
2295
|
+
const registerUserSpotHandlers = (runtime: ZLinkSpotNodeRuntimeManager) => {
|
|
2296
|
+
for (const [meshName] of this.options.registration.spotNodes) {
|
|
2297
|
+
const node = runtime.meshNode(meshName);
|
|
2298
|
+
if (node === undefined) continue;
|
|
2299
|
+
node.registerUserSpotOperationHandler({
|
|
2300
|
+
create: async (record, signal) => {
|
|
2301
|
+
const coordinated = await coordinator.handleRemoteCreate(
|
|
2302
|
+
record,
|
|
2303
|
+
async (requestPayload, authority, createSignal) => {
|
|
2304
|
+
const selected = factories.get(meshName)?.get(record.stableType);
|
|
2305
|
+
if (selected === undefined) {
|
|
2306
|
+
throw new ZLinkConfigurationException(
|
|
2307
|
+
`User Spot factory '${record.stableType}' is not registered on RouteMesh '${meshName}'.`
|
|
2308
|
+
);
|
|
2309
|
+
}
|
|
2310
|
+
const request = decodeFrameworkCreationPayload(
|
|
2311
|
+
requestPayload,
|
|
2312
|
+
this.options.registration.messageSerializers
|
|
2313
|
+
);
|
|
2314
|
+
local.beginUserSpotPublication(meshName, record.spotId as never);
|
|
2315
|
+
try {
|
|
2316
|
+
const result = await local.getOrCreateWithAuthority(
|
|
2317
|
+
meshName,
|
|
2318
|
+
selected.implementation as never,
|
|
2319
|
+
record.spotId as never,
|
|
2320
|
+
request,
|
|
2321
|
+
{
|
|
2322
|
+
stableType: record.stableType,
|
|
2323
|
+
objectGeneration: authority.objectGeneration,
|
|
2324
|
+
authorityOwnerGeneration: authority.authorityOwnerGeneration
|
|
2325
|
+
},
|
|
2326
|
+
createSignal
|
|
2327
|
+
);
|
|
2328
|
+
return {
|
|
2329
|
+
...result,
|
|
2330
|
+
publication: {
|
|
2331
|
+
publish: () => local.publishUserSpot(meshName, record.spotId as never),
|
|
2332
|
+
abort: () => local.abortUserSpotPublication(meshName, record.spotId as never)
|
|
2333
|
+
}
|
|
2334
|
+
};
|
|
2335
|
+
} catch (error) {
|
|
2336
|
+
local.abortUserSpotPublication(meshName, record.spotId as never);
|
|
2337
|
+
throw error;
|
|
2338
|
+
}
|
|
2339
|
+
},
|
|
2340
|
+
async cleanupSignal => {
|
|
2341
|
+
await local.close(meshName, record.spotId as never, cleanupSignal);
|
|
2342
|
+
},
|
|
2343
|
+
signal
|
|
2344
|
+
);
|
|
2345
|
+
const reply = coordinated.result.reply;
|
|
2346
|
+
let payload;
|
|
2347
|
+
if (
|
|
2348
|
+
reply !== undefined
|
|
2349
|
+
&& coordinated.result.state !== ZLinkSpotCreateState.Existing
|
|
2350
|
+
) {
|
|
2351
|
+
const message = encodeFrameworkPayloadMessage(
|
|
2352
|
+
reply,
|
|
2353
|
+
this.options.registration.messageSerializers
|
|
2354
|
+
);
|
|
2355
|
+
try {
|
|
2356
|
+
payload = {
|
|
2357
|
+
packetName: 'ZLinkFrameworkUserSpotReply',
|
|
2358
|
+
contentType: 'application/octet-stream',
|
|
2359
|
+
payload: Buffer.from(message.data())
|
|
2360
|
+
};
|
|
2361
|
+
} finally {
|
|
2362
|
+
message.close();
|
|
2363
|
+
}
|
|
2364
|
+
}
|
|
2365
|
+
return {
|
|
2366
|
+
terminalResult: RequestResult.Ok,
|
|
2367
|
+
failureCode: 0,
|
|
2368
|
+
tail: {
|
|
2369
|
+
kind: 'userSpotCreate' as const,
|
|
2370
|
+
createResult: coordinated.result.state === ZLinkSpotCreateState.Existing
|
|
2371
|
+
? 'existing' as const
|
|
2372
|
+
: coordinated.result.state === ZLinkSpotCreateState.Created
|
|
2373
|
+
? 'created' as const
|
|
2374
|
+
: 'rejected' as const,
|
|
2375
|
+
spotId: String(coordinated.spot.spotId),
|
|
2376
|
+
objectGeneration: coordinated.spot.objectGeneration
|
|
2377
|
+
},
|
|
2378
|
+
...(payload === undefined ? {} : { payload })
|
|
2379
|
+
};
|
|
2380
|
+
},
|
|
2381
|
+
createActor: async (record, signal) => {
|
|
2382
|
+
const actorPlacement = this.actorPlacement;
|
|
2383
|
+
const actors = this.actorManager;
|
|
2384
|
+
if (actorPlacement === undefined || actors === undefined) {
|
|
2385
|
+
throw new ZLinkConfigurationException(
|
|
2386
|
+
'Actor placement target runtime is not initialized.'
|
|
2387
|
+
);
|
|
2388
|
+
}
|
|
2389
|
+
return await actorPlacement.handleRemoteCreate(
|
|
2390
|
+
record,
|
|
2391
|
+
async (requestPayload, authority, createSignal) => {
|
|
2392
|
+
const request = decodeFrameworkCreationPayload(
|
|
2393
|
+
requestPayload,
|
|
2394
|
+
this.options.registration.messageSerializers
|
|
2395
|
+
);
|
|
2396
|
+
const entrySpot = node.entrySpot().status();
|
|
2397
|
+
const nativeActorRef = node.restoreActorAuthority?.(
|
|
2398
|
+
record.actorId,
|
|
2399
|
+
record.stableType,
|
|
2400
|
+
authority.objectGeneration,
|
|
2401
|
+
authority.authorityOwnerGeneration,
|
|
2402
|
+
String(entrySpot.routingId),
|
|
2403
|
+
entrySpot.lifecycleGeneration,
|
|
2404
|
+
1n
|
|
2405
|
+
);
|
|
2406
|
+
if (nativeActorRef === undefined) {
|
|
2407
|
+
throw new ZLinkConfigurationException(
|
|
2408
|
+
'Remote Actor creation requires native authority restoration support.'
|
|
2409
|
+
);
|
|
2410
|
+
}
|
|
2411
|
+
const local = await actors.createReservedActorResult(
|
|
2412
|
+
record.actorId,
|
|
2413
|
+
record.stableType,
|
|
2414
|
+
request,
|
|
2415
|
+
createSignal,
|
|
2416
|
+
nativeActorRef
|
|
2417
|
+
);
|
|
2418
|
+
if (local.status === 'rejected') {
|
|
2419
|
+
let reply: Buffer | undefined;
|
|
2420
|
+
if (local.reply !== undefined) {
|
|
2421
|
+
const encoded = encodeFrameworkPayloadMessage(
|
|
2422
|
+
local.reply,
|
|
2423
|
+
this.options.registration.messageSerializers
|
|
2424
|
+
);
|
|
2425
|
+
try {
|
|
2426
|
+
reply = Buffer.from(encoded.data());
|
|
2427
|
+
} finally {
|
|
2428
|
+
encoded.close();
|
|
2429
|
+
}
|
|
2430
|
+
}
|
|
2431
|
+
return {
|
|
2432
|
+
result: 'rejected' as const,
|
|
2433
|
+
...(reply === undefined ? {} : { reply })
|
|
2434
|
+
};
|
|
2435
|
+
}
|
|
2436
|
+
if (
|
|
2437
|
+
local.actorRef.objectGeneration !== authority.objectGeneration
|
|
2438
|
+
|| String(local.actorRef.nodeRid) !== record.reservation.targetNodeRid
|
|
2439
|
+
) {
|
|
2440
|
+
throw createInternalFrameworkException(
|
|
2441
|
+
ZLinkFrameworkInternalErrorKind.ActorCreateFailed,
|
|
2442
|
+
`Actor '${record.actorId}' native authority does not match its placement reservation.`
|
|
2443
|
+
);
|
|
2444
|
+
}
|
|
2445
|
+
let reply: Buffer | undefined;
|
|
2446
|
+
if (local.reply !== undefined) {
|
|
2447
|
+
const encoded = encodeFrameworkPayloadMessage(
|
|
2448
|
+
local.reply,
|
|
2449
|
+
this.options.registration.messageSerializers
|
|
2450
|
+
);
|
|
2451
|
+
try {
|
|
2452
|
+
reply = Buffer.from(encoded.data());
|
|
2453
|
+
} finally {
|
|
2454
|
+
encoded.close();
|
|
2455
|
+
}
|
|
2456
|
+
}
|
|
2457
|
+
return {
|
|
2458
|
+
result: 'created' as const,
|
|
2459
|
+
actor: {
|
|
2460
|
+
...local.actorRef,
|
|
2461
|
+
meshName
|
|
2462
|
+
},
|
|
2463
|
+
entrySpotId: String(entrySpot.routingId),
|
|
2464
|
+
entrySpotGeneration: entrySpot.lifecycleGeneration,
|
|
2465
|
+
...(reply === undefined ? {} : { reply }),
|
|
2466
|
+
onPublished: () => actors.adoptCreatedAuthority(
|
|
2467
|
+
record.actorId,
|
|
2468
|
+
authority.authorityOwnerGeneration,
|
|
2469
|
+
authority.ownerLeaseGeneration
|
|
2470
|
+
)
|
|
2471
|
+
};
|
|
2472
|
+
},
|
|
2473
|
+
signal
|
|
2474
|
+
);
|
|
2475
|
+
},
|
|
2476
|
+
close: async (record, signal) => {
|
|
2477
|
+
if (!local.hasActiveSpot(record.target.spotId as never)) {
|
|
2478
|
+
throw createInternalFrameworkException(
|
|
2479
|
+
ZLinkFrameworkInternalErrorKind.SpotMoving,
|
|
2480
|
+
`User Spot '${record.target.spotId}' is not materialized on its authority owner.`,
|
|
2481
|
+
true
|
|
2482
|
+
);
|
|
2483
|
+
}
|
|
2484
|
+
if (!local.canCloseUserSpot(meshName, record.target.spotId as never)) {
|
|
2485
|
+
return {
|
|
2486
|
+
terminalResult: RequestResult.Ok,
|
|
2487
|
+
failureCode: 0,
|
|
2488
|
+
tail: {
|
|
2489
|
+
kind: 'userSpotClose' as const,
|
|
2490
|
+
closed: false
|
|
2491
|
+
}
|
|
2492
|
+
};
|
|
2493
|
+
}
|
|
2494
|
+
return {
|
|
2495
|
+
terminalResult: RequestResult.Ok,
|
|
2496
|
+
failureCode: 0,
|
|
2497
|
+
tail: {
|
|
2498
|
+
kind: 'userSpotClose' as const,
|
|
2499
|
+
closed: await coordinator.handleRemoteClose(
|
|
2500
|
+
record,
|
|
2501
|
+
(spot, closeSignal) => local.close(
|
|
2502
|
+
spot.meshName,
|
|
2503
|
+
spot.spotId,
|
|
2504
|
+
closeSignal
|
|
2505
|
+
),
|
|
2506
|
+
signal
|
|
2507
|
+
)
|
|
2508
|
+
}
|
|
2509
|
+
};
|
|
2510
|
+
}
|
|
2511
|
+
});
|
|
2512
|
+
}
|
|
2513
|
+
};
|
|
2514
|
+
this.registerUserSpotHandlers = registerUserSpotHandlers;
|
|
2515
|
+
if (this.spotNodeRuntime !== undefined) {
|
|
2516
|
+
registerUserSpotHandlers(this.spotNodeRuntime);
|
|
2517
|
+
}
|
|
2518
|
+
return new ZLinkPublicSpotManager({
|
|
2519
|
+
local,
|
|
2520
|
+
coordinator,
|
|
2521
|
+
factories,
|
|
2522
|
+
resolver: () => this.createLocationSpotRouteResolver(),
|
|
2523
|
+
forgetReadyRoute: (spot, snapshot) => {
|
|
2524
|
+
coordinator.forgetReadyRoute(spot.spotId, snapshot);
|
|
2525
|
+
},
|
|
2526
|
+
isLocalNode: (meshName, nodeRid) => {
|
|
2527
|
+
const status = this.spotNodeRuntime?.meshNode(meshName)?.status();
|
|
2528
|
+
return status !== undefined && String(status.routingId) === String(nodeRid);
|
|
2529
|
+
},
|
|
2530
|
+
remoteClose: (meshName, targetNodeRid, request, timeoutMs) => {
|
|
2531
|
+
const node = this.spotNodeRuntime?.meshNode(meshName);
|
|
2532
|
+
if (node === undefined) {
|
|
2533
|
+
throw createInternalFrameworkException(
|
|
2534
|
+
ZLinkFrameworkInternalErrorKind.ObjectClientNotConfigured,
|
|
2535
|
+
`RouteMesh '${meshName}' has no local client node.`
|
|
2536
|
+
);
|
|
2537
|
+
}
|
|
2538
|
+
return node.requestUserSpotClose(targetNodeRid, request, timeoutMs);
|
|
2539
|
+
},
|
|
2540
|
+
defaultTimeoutMs: this.options.registration.requestTimeoutMs ?? 30_000,
|
|
2541
|
+
messageSerializers: this.options.registration.messageSerializers
|
|
2542
|
+
});
|
|
2543
|
+
}
|
|
2544
|
+
|
|
2545
|
+
private actorRuntimeOptionsFactory(): ZLinkActorRuntimeOptionsFactory {
|
|
2546
|
+
return new ZLinkActorRuntimeOptionsFactory({
|
|
2547
|
+
registration: this.options.registration,
|
|
2548
|
+
messageFlow: () =>
|
|
2549
|
+
this.createDispatchErrorReporter(this.runtimeOrPreStartErrorSink).flow,
|
|
2550
|
+
routeTransport: this.routeTransport,
|
|
2551
|
+
streamBindingRuntime: this.streamBindingRuntime,
|
|
2552
|
+
providerResolver: this.options.providerResolver,
|
|
2553
|
+
spotManager: () => this.spotManager,
|
|
2554
|
+
actorManager: () => this.actorManager,
|
|
2555
|
+
primaryMeshNode: () => this.requirePrimaryMeshNode(),
|
|
2556
|
+
primaryMeshNodeOrUndefined: () => this.spotNodeRuntime?.primaryMeshNode,
|
|
2557
|
+
primaryMeshCompletions: () => this.spotNodeRuntime?.primaryMeshCompletions,
|
|
2558
|
+
meshNode: (meshName) => this.spotNodeRuntime?.meshNode(meshName),
|
|
2559
|
+
meshCompletions: (meshName) => this.spotNodeRuntime?.meshCompletionTable(meshName),
|
|
2560
|
+
notifyEntrySpotActorCreated: (nodeRid, actor, createRequest, signal) =>
|
|
2561
|
+
this.spotNodeRuntime?.notifyEntrySpotActorCreated(nodeRid, actor, createRequest, signal)
|
|
2562
|
+
?? Promise.resolve(undefined),
|
|
2563
|
+
locationLifecycle: () => this.locationOwner.currentLifecycle,
|
|
2564
|
+
primaryMeshName: () => this.meshRouters.primaryMeshName(),
|
|
2565
|
+
actorMeshName: (actorType) => this.meshRouters.actorMeshName(actorType),
|
|
2566
|
+
createLocationSpotRouteResolver: () => this.createLocationSpotRouteResolver(),
|
|
2567
|
+
createActorLocationResolver: () => this.createActorLocationResolver(),
|
|
2568
|
+
forgetDestroyedActorRef: (actorId) => this.destroyedActorRefs.delete(actorId),
|
|
2569
|
+
rememberDestroyedActorRef: (actorId, actorRef) => this.destroyedActorRefs.set(actorId, actorRef),
|
|
2570
|
+
invalidateActorRoute: (actorId) => this.actorClientLocationResolver?.invalidateActorRoute(actorId),
|
|
2571
|
+
publishActorAuthority: async (actorType, actorRef, ownerNodeGeneration, signal) => {
|
|
2572
|
+
const store = this.locationOwner.currentStores?.locationStore;
|
|
2573
|
+
if (store === undefined) return;
|
|
2574
|
+
const owner = this.locationOwner.currentRuntime?.currentOwnerToken;
|
|
2575
|
+
const meshName = this.meshRouters.actorMeshName(actorType);
|
|
2576
|
+
if (owner === undefined || meshName === undefined) {
|
|
2577
|
+
throw new ZLinkConfigurationException(
|
|
2578
|
+
`Actor '${actorRef.actorId}' authority requires an active owner and Actor RouteMesh.`
|
|
2579
|
+
);
|
|
2580
|
+
}
|
|
2581
|
+
const entrySpotId = this.spotNodeRuntime?.entrySpotIdForMesh(meshName);
|
|
2582
|
+
if (entrySpotId === undefined) {
|
|
2583
|
+
throw new ZLinkConfigurationException(
|
|
2584
|
+
`Actor '${actorRef.actorId}' authority requires its RouteMesh Entry Spot.`
|
|
2585
|
+
);
|
|
2586
|
+
}
|
|
2587
|
+
await publishInitialActorAuthority(store, {
|
|
2588
|
+
actorType,
|
|
2589
|
+
actor: actorRef,
|
|
2590
|
+
meshName,
|
|
2591
|
+
ownerNodeGeneration,
|
|
2592
|
+
owner,
|
|
2593
|
+
spotId: entrySpotId,
|
|
2594
|
+
spotGeneration: ownerNodeGeneration,
|
|
2595
|
+
spotKind: ZLinkSpotKind.Entry
|
|
2596
|
+
}, signal);
|
|
2597
|
+
this.actorClientLocationResolver?.invalidateActorRoute(actorRef.actorId);
|
|
2598
|
+
},
|
|
2599
|
+
reportPostCommitError: (error) =>
|
|
2600
|
+
this.runtimeOrPreStartErrorSink.reportRuntimeTaskException('post-commit actor binding', error),
|
|
2601
|
+
reportBoundSessionSendError: (error) =>
|
|
2602
|
+
this.runtimeOrPreStartErrorSink.reportRuntimeTaskException('bound session one-way submit', error),
|
|
2603
|
+
actorHandoff: this.actorHandoff,
|
|
2604
|
+
actorTransferRuntime: this.actorTransferRuntime,
|
|
2605
|
+
actorJoinRelocation: this.serviceRelocation,
|
|
2606
|
+
actorTransferRegistry: this.actorTransferRegistry,
|
|
2607
|
+
shutdownSignal: () => this.executionState?.abortController.signal,
|
|
2608
|
+
metrics: this.metrics,
|
|
2609
|
+
admission: this.admission,
|
|
2610
|
+
actorPacketTargetForState: (actorId) =>
|
|
2611
|
+
this.boundSessionRelay.actorPackets.actorPacketTargetForState(actorId),
|
|
2612
|
+
flowCreationEnabled: () => this.flowCreationEnabled(),
|
|
2613
|
+
traceBoundSessionSend: (actorId, packetName) => {
|
|
2614
|
+
const flow = this.createDispatchErrorReporter(this.runtimeOrPreStartErrorSink).flow;
|
|
2615
|
+
flowIfEnabled(flow, ZLinkMessageFlowOutcome.Sent)?.trace({
|
|
2616
|
+
outcome: ZLinkMessageFlowOutcome.Sent,
|
|
2617
|
+
surface: ZLinkDispatchErrorSurface.SpotActor,
|
|
2618
|
+
messageKind: ZLinkDispatchMessageKind.ActorSend,
|
|
2619
|
+
packetName,
|
|
2620
|
+
actorId
|
|
2621
|
+
});
|
|
2622
|
+
}
|
|
2623
|
+
});
|
|
2624
|
+
}
|
|
2625
|
+
|
|
2626
|
+
private createChannelRuntimeOptions() {
|
|
2627
|
+
return new ZLinkChannelRuntimeOptionsFactory({
|
|
2628
|
+
monitoringAdapter: this.backendAdapterFactory.createMonitoringAdapter(),
|
|
2629
|
+
messageFlowModeCell: this.messageFlowModeCell,
|
|
2630
|
+
boundSessionRelay: this.boundSessionRelay,
|
|
2631
|
+
applicationJobQueue: this.applicationJobQueue,
|
|
2632
|
+
spotManager: () => this.spotManager,
|
|
2633
|
+
oneWayFailureSink: (error) =>
|
|
2634
|
+
this.runtimeOrPreStartErrorSink.reportRuntimeTaskException('channel one-way submit', error)
|
|
2635
|
+
}).create();
|
|
2636
|
+
}
|
|
2637
|
+
|
|
2638
|
+
private createSpotNodeRuntimeOptions(
|
|
2639
|
+
context: ZLinkBackendContext,
|
|
2640
|
+
dispatchErrors: ZLinkDispatchErrorReporter
|
|
2641
|
+
) {
|
|
2642
|
+
const options = new ZLinkSpotNodeRuntimeOptionsFactory({
|
|
2643
|
+
registration: this.options.registration,
|
|
2644
|
+
backendAdapterFactory: this.backendAdapterFactory,
|
|
2645
|
+
context,
|
|
2646
|
+
channelTransport: this.channelTransport,
|
|
2647
|
+
routeTransport: this.routeTransport,
|
|
2648
|
+
spotPublisherTransport: this.spotPublisherTransport,
|
|
2649
|
+
meshRouters: this.meshRouters,
|
|
2650
|
+
providerResolver: this.options.providerResolver,
|
|
2651
|
+
dispatchErrors,
|
|
2652
|
+
runtimeEventPublisher: this.runtimeEventPublisher,
|
|
2653
|
+
entryActorRuntime: this.entryActorRuntime,
|
|
2654
|
+
actorTransferRuntime: this.actorTransferRuntime,
|
|
2655
|
+
boundSessionRelay: this.boundSessionRelay,
|
|
2656
|
+
actorHandoff: this.actorHandoff,
|
|
2657
|
+
detachedTaskRunner: this.detachedTaskRunner(),
|
|
2658
|
+
metrics: this.metrics,
|
|
2659
|
+
applicationJobQueue: this.applicationJobQueue,
|
|
2660
|
+
applicationJobReceiveFlowFailureSink: (error) =>
|
|
2661
|
+
this.runtimeOrPreStartErrorSink.reportRuntimeTaskException(
|
|
2662
|
+
'RouteMesh receive-flow configuration',
|
|
2663
|
+
error
|
|
2664
|
+
)
|
|
2665
|
+
}).create();
|
|
2666
|
+
return {
|
|
2667
|
+
...options,
|
|
2668
|
+
peerAdmissionSealed: (meshName: string) => !this.admission.accepts(meshName),
|
|
2669
|
+
messageFollowReceiver: (record: ServiceMessageFollowRecord) => {
|
|
2670
|
+
if (record.source.kind === 'actor') {
|
|
2671
|
+
this.actorClientLocationResolver?.invalidateActorRouteIfMatches({
|
|
2672
|
+
actorId: record.source.actor.actorId,
|
|
2673
|
+
objectGeneration: record.source.actor.generation,
|
|
2674
|
+
targetNodeRid: record.source.targetNodeRid,
|
|
2675
|
+
targetNodeGeneration: record.source.targetNodeGeneration,
|
|
2676
|
+
authorityOwnerGeneration: record.source.authorityOwnerGeneration,
|
|
2677
|
+
ownerLeaseGeneration: record.source.ownerLeaseGeneration
|
|
2678
|
+
});
|
|
2679
|
+
return;
|
|
2680
|
+
}
|
|
2681
|
+
this.actorClientLocationResolver?.invalidateSpotRouteIfMatches({
|
|
2682
|
+
spotId: record.source.spot.spotId,
|
|
2683
|
+
objectGeneration: record.source.spot.generation,
|
|
2684
|
+
targetNodeRid: record.source.targetNodeRid,
|
|
2685
|
+
targetNodeGeneration: record.source.targetNodeGeneration,
|
|
2686
|
+
authorityOwnerGeneration: record.source.authorityOwnerGeneration,
|
|
2687
|
+
ownerLeaseGeneration: record.source.ownerLeaseGeneration
|
|
2688
|
+
});
|
|
2689
|
+
},
|
|
2690
|
+
meshRecordDispatcher: (meshName: string, owner: ReadyRecord, record: ReceiveRecord) =>
|
|
2691
|
+
this.dispatchMeshRecord(meshName, owner, record, this.executionState?.abortController.signal),
|
|
2692
|
+
instanceActivationConcurrencyProvider: (meshName: string) => {
|
|
2693
|
+
return this.spotManager?.instanceActivationConcurrency(meshName)
|
|
2694
|
+
?? { active: 0, limit: this.options.registration.spotNodes.get(meshName)?.activationConcurrencyLimit ?? 128 };
|
|
2695
|
+
}
|
|
2696
|
+
};
|
|
2697
|
+
}
|
|
2698
|
+
|
|
2699
|
+
private async dispatchMeshRecord(
|
|
2700
|
+
meshName: string,
|
|
2701
|
+
owner: ReadyRecord,
|
|
2702
|
+
record: ReceiveRecord,
|
|
2703
|
+
signal?: AbortSignal
|
|
2704
|
+
): Promise<void> {
|
|
2705
|
+
if (record.operationKind === OperationKind.ActorJoin) {
|
|
2706
|
+
if (this.spotManager === undefined) {
|
|
2707
|
+
throw new ZLinkConfigurationException('MeshNode Actor join dispatch requires the Spot manager.');
|
|
2708
|
+
}
|
|
2709
|
+
return this.spotManager.dispatchMeshActorJoin(meshName, owner, record);
|
|
2710
|
+
}
|
|
2711
|
+
if (record.kind === ReceiveKind.ActorBinding) {
|
|
2712
|
+
if (record.kindData?.kind !== 'actorBinding') {
|
|
2713
|
+
throw new ZLinkConfigurationException(
|
|
2714
|
+
'MeshNode Actor binding record has no binding generation.'
|
|
2715
|
+
);
|
|
2716
|
+
}
|
|
2717
|
+
const binding = record.kindData;
|
|
2718
|
+
const replyBindingFailure = (
|
|
2719
|
+
kind: ZLinkFrameworkInternalErrorKind,
|
|
2720
|
+
message: string
|
|
2721
|
+
): void => {
|
|
2722
|
+
const terminal = kind === ZLinkFrameworkInternalErrorKind.ActorGenerationStale
|
|
2723
|
+
? { terminalResult: RequestResult.InvalidState, failureCode: 0 }
|
|
2724
|
+
: internalFrameworkWireReply(createInternalFrameworkException(kind, message));
|
|
2725
|
+
if (
|
|
2726
|
+
record.replyFailure?.(terminal.terminalResult, terminal.failureCode)
|
|
2727
|
+
!== SubmitResult.Ok
|
|
2728
|
+
) {
|
|
2729
|
+
throw new ZLinkConfigurationException(
|
|
2730
|
+
`MeshNode Actor binding target '${binding.actor.actorId}' failure acknowledgement failed.`
|
|
2731
|
+
);
|
|
2732
|
+
}
|
|
2733
|
+
};
|
|
2734
|
+
const replyBindingSuccess = (): void => {
|
|
2735
|
+
if (record.reply(Buffer.alloc(0)) !== SubmitResult.Ok) {
|
|
2736
|
+
throw new ZLinkConfigurationException(
|
|
2737
|
+
`MeshNode Actor binding target '${binding.actor.actorId}' acknowledgement failed.`
|
|
2738
|
+
);
|
|
2739
|
+
}
|
|
2740
|
+
};
|
|
2741
|
+
const state = this.actorManager?.getState(binding.actor.actorId);
|
|
2742
|
+
const nativeActorRef = state?.nativeActorRef;
|
|
2743
|
+
if (
|
|
2744
|
+
state === undefined
|
|
2745
|
+
|| nativeActorRef === undefined
|
|
2746
|
+
|| nativeActorRef.actorId !== binding.actor.actorId
|
|
2747
|
+
|| !routingIdsEqual(nativeActorRef.nodeRid, binding.actor.nodeRid)
|
|
2748
|
+
) {
|
|
2749
|
+
replyBindingFailure(
|
|
2750
|
+
ZLinkFrameworkInternalErrorKind.ActorLocationStale,
|
|
2751
|
+
`Actor '${binding.actor.actorId}' binding target is no longer current.`
|
|
2752
|
+
);
|
|
2753
|
+
return;
|
|
2754
|
+
}
|
|
2755
|
+
if (nativeActorRef.generation !== binding.actor.generation) {
|
|
2756
|
+
replyBindingFailure(
|
|
2757
|
+
ZLinkFrameworkInternalErrorKind.ActorGenerationStale,
|
|
2758
|
+
`Actor '${binding.actor.actorId}' binding object generation is stale.`
|
|
2759
|
+
);
|
|
2760
|
+
return;
|
|
2761
|
+
}
|
|
2762
|
+
const node = state.meshName === meshName
|
|
2763
|
+
? this.spotNodeRuntime?.meshNode(meshName)
|
|
2764
|
+
: undefined;
|
|
2765
|
+
const localStatus = node?.status();
|
|
2766
|
+
// ownsLocation tracks local cleanup responsibility, not Actor authority.
|
|
2767
|
+
// A relocation target can exact-read committed authority without owning that cleanup.
|
|
2768
|
+
if (
|
|
2769
|
+
localStatus === undefined
|
|
2770
|
+
|| !routingIdsEqual(localStatus.routingId, binding.actor.nodeRid)
|
|
2771
|
+
|| localStatus.lifecycleGeneration !== binding.actorNodeGeneration
|
|
2772
|
+
|| state.locationGeneration !== binding.authorityOwnerGeneration
|
|
2773
|
+
|| state.isMoving
|
|
2774
|
+
) {
|
|
2775
|
+
replyBindingFailure(
|
|
2776
|
+
ZLinkFrameworkInternalErrorKind.ActorLocationStale,
|
|
2777
|
+
`Actor '${binding.actor.actorId}' binding authority fence is stale.`
|
|
2778
|
+
);
|
|
2779
|
+
return;
|
|
2780
|
+
}
|
|
2781
|
+
const sessionOwnerIsLocal = routingIdsEqual(
|
|
2782
|
+
localStatus.routingId,
|
|
2783
|
+
binding.sessionNodeRid
|
|
2784
|
+
) && localStatus.lifecycleGeneration === binding.sessionOwnerNodeGeneration;
|
|
2785
|
+
if (binding.transition === 'tombstone') {
|
|
2786
|
+
const actorRef: ActorRef = {
|
|
2787
|
+
actorId: binding.actor.actorId,
|
|
2788
|
+
objectGeneration: binding.actor.generation,
|
|
2789
|
+
meshName,
|
|
2790
|
+
nodeRid: binding.actor.nodeRid
|
|
2791
|
+
};
|
|
2792
|
+
if (sessionOwnerIsLocal) {
|
|
2793
|
+
await this.streamBindingRuntime.retireRemoteBinding(
|
|
2794
|
+
actorRef,
|
|
2795
|
+
binding.sessionRid,
|
|
2796
|
+
binding.bindingGeneration,
|
|
2797
|
+
signal
|
|
2798
|
+
);
|
|
2799
|
+
}
|
|
2800
|
+
state.retireBoundSessionBinding(binding);
|
|
2801
|
+
replyBindingSuccess();
|
|
2802
|
+
return;
|
|
2803
|
+
}
|
|
2804
|
+
const target = this.boundSessionRelay.boundSessions.resolveRemoteBoundSessionTarget(
|
|
2805
|
+
binding.sessionNodeRid,
|
|
2806
|
+
binding.sessionRid
|
|
2807
|
+
);
|
|
2808
|
+
if (target === undefined) {
|
|
2809
|
+
replyBindingFailure(
|
|
2810
|
+
ZLinkFrameworkInternalErrorKind.ActorLocationStale,
|
|
2811
|
+
`Actor '${binding.actor.actorId}' Session route is unavailable.`
|
|
2812
|
+
);
|
|
2813
|
+
return;
|
|
2814
|
+
}
|
|
2815
|
+
const installed = state.installBoundSessionBinding({
|
|
2816
|
+
...target,
|
|
2817
|
+
sessionNodeRid: binding.sessionNodeRid,
|
|
2818
|
+
sessionRid: binding.sessionRid,
|
|
2819
|
+
sessionOwnerNodeGeneration: binding.sessionOwnerNodeGeneration,
|
|
2820
|
+
sessionOwnerId: binding.sessionOwnerId,
|
|
2821
|
+
sessionOwnerLeaseGeneration: binding.sessionOwnerLeaseGeneration,
|
|
2822
|
+
bindingGeneration: binding.bindingGeneration
|
|
2823
|
+
});
|
|
2824
|
+
if (!installed) {
|
|
2825
|
+
replyBindingFailure(
|
|
2826
|
+
ZLinkFrameworkInternalErrorKind.ActorLocationStale,
|
|
2827
|
+
`Actor '${binding.actor.actorId}' Session binding generation is stale.`
|
|
2828
|
+
);
|
|
2829
|
+
return;
|
|
2830
|
+
}
|
|
2831
|
+
replyBindingSuccess();
|
|
2832
|
+
return Promise.resolve();
|
|
2833
|
+
}
|
|
2834
|
+
switch (record.kind) {
|
|
2835
|
+
case ReceiveKind.TransferControl:
|
|
2836
|
+
if (record.kindData?.kind !== 'transferControl') {
|
|
2837
|
+
throw new ZLinkConfigurationException('MeshNode transfer control record has no typed control payload.');
|
|
2838
|
+
}
|
|
2839
|
+
return this.actorTransferAuthorityRuntime.handle(meshName, record.kindData, signal);
|
|
2840
|
+
case ReceiveKind.ChannelSend:
|
|
2841
|
+
case ReceiveKind.ChannelRequest: {
|
|
2842
|
+
const channelRuntime = this.channelRuntime;
|
|
2843
|
+
if (channelRuntime === undefined) {
|
|
2844
|
+
throw new ZLinkConfigurationException('MeshNode channel dispatch requires the channel runtime.');
|
|
2845
|
+
}
|
|
2846
|
+
return this.admission.run(meshName, 'RouteMesh channel dispatch', () =>
|
|
2847
|
+
channelRuntime.dispatchMeshChannel(meshName, record, signal));
|
|
2848
|
+
}
|
|
2849
|
+
case ReceiveKind.NodeSend:
|
|
2850
|
+
case ReceiveKind.NodeRequest: {
|
|
2851
|
+
if (await this.serviceRelocation.tryHandleControl(meshName, record, signal)) {
|
|
2852
|
+
return;
|
|
2853
|
+
}
|
|
2854
|
+
if (record.kind === ReceiveKind.NodeRequest && record.parts.length === 1) {
|
|
2855
|
+
const terminal = decodeRemoteActorSourceLeaveTerminal(record.parts[0]!.data());
|
|
2856
|
+
if (terminal !== undefined) {
|
|
2857
|
+
if (
|
|
2858
|
+
await this.spotManager?.completeFormalSourceLeaveTerminal(
|
|
2859
|
+
terminal.actorId,
|
|
2860
|
+
terminal.transferId,
|
|
2861
|
+
terminal.succeeded
|
|
2862
|
+
) !== true
|
|
2863
|
+
) {
|
|
2864
|
+
throw new ZLinkConfigurationException(
|
|
2865
|
+
`Actor '${terminal.actorId}' has no matching formal transfer terminal gate.`
|
|
2866
|
+
);
|
|
2867
|
+
}
|
|
2868
|
+
if (record.reply(Buffer.alloc(0)) !== SubmitResult.Ok) {
|
|
2869
|
+
throw new ZLinkConfigurationException(
|
|
2870
|
+
`Actor '${terminal.actorId}' formal transfer terminal acknowledgement failed.`
|
|
2871
|
+
);
|
|
2872
|
+
}
|
|
2873
|
+
return Promise.resolve();
|
|
2874
|
+
}
|
|
2875
|
+
}
|
|
2876
|
+
const channelRuntime = this.channelRuntime;
|
|
2877
|
+
if (channelRuntime === undefined) {
|
|
2878
|
+
throw new ZLinkConfigurationException('MeshNode node-direct dispatch requires the channel runtime.');
|
|
2879
|
+
}
|
|
2880
|
+
return this.admission.run(meshName, 'RouteMesh node dispatch', () =>
|
|
2881
|
+
channelRuntime.dispatchMeshRoute(meshName, record, signal));
|
|
2882
|
+
}
|
|
2883
|
+
case ReceiveKind.SpotSend:
|
|
2884
|
+
case ReceiveKind.SpotRequest:
|
|
2885
|
+
case ReceiveKind.SpotMulticast:
|
|
2886
|
+
return this.admission.run(meshName, 'RouteMesh Spot dispatch', () =>
|
|
2887
|
+
this.dispatchMeshSpotRecord(meshName, owner, record));
|
|
2888
|
+
case ReceiveKind.InstanceSpotActivation:
|
|
2889
|
+
if (this.spotManager === undefined) {
|
|
2890
|
+
throw new ZLinkConfigurationException(
|
|
2891
|
+
'MeshNode Instance Spot dispatch requires the Spot manager.'
|
|
2892
|
+
);
|
|
2893
|
+
}
|
|
2894
|
+
return this.admission.run(meshName, 'RouteMesh Instance Spot dispatch', () =>
|
|
2895
|
+
this.spotManager!.dispatchMeshInstance(meshName, owner, record));
|
|
2896
|
+
case ReceiveKind.SpotControl:
|
|
2897
|
+
if (this.spotManager === undefined) {
|
|
2898
|
+
throw new ZLinkConfigurationException('MeshNode Spot control dispatch requires the Spot manager.');
|
|
2899
|
+
}
|
|
2900
|
+
return this.spotManager.dispatchMeshSpotControl(meshName, owner, record);
|
|
2901
|
+
case ReceiveKind.ActorSend:
|
|
2902
|
+
case ReceiveKind.ActorRequest:
|
|
2903
|
+
if (this.spotManager === undefined) {
|
|
2904
|
+
throw new ZLinkConfigurationException('MeshNode Actor dispatch requires the Spot manager.');
|
|
2905
|
+
}
|
|
2906
|
+
return this.admission.run(meshName, 'RouteMesh Actor dispatch', () =>
|
|
2907
|
+
this.spotManager!.dispatchMeshActor(meshName, owner, record));
|
|
2908
|
+
case ReceiveKind.SendReady:
|
|
2909
|
+
return Promise.resolve();
|
|
2910
|
+
default:
|
|
2911
|
+
throw new ZLinkConfigurationException(
|
|
2912
|
+
`MeshNode record kind '${record.kind}' does not yet have a registered framework consumer.`
|
|
2913
|
+
);
|
|
2914
|
+
}
|
|
2915
|
+
}
|
|
2916
|
+
|
|
2917
|
+
private submitLocalMeshRoute(
|
|
2918
|
+
meshName: string,
|
|
2919
|
+
sourceNodeRid: string,
|
|
2920
|
+
parts: readonly MessageLike[]
|
|
2921
|
+
) {
|
|
2922
|
+
const state = this.executionState;
|
|
2923
|
+
const channelRuntime = this.channelRuntime;
|
|
2924
|
+
if (state === undefined || channelRuntime === undefined || !this.admission.accepts(meshName)) {
|
|
2925
|
+
return { status: ZLinkSubmitStatus.Shutdown } as const;
|
|
2926
|
+
}
|
|
2927
|
+
if (!channelRuntime.canDispatchLocalMeshRoute(meshName)) {
|
|
2928
|
+
return { status: ZLinkSubmitStatus.TargetNotFound } as const;
|
|
2929
|
+
}
|
|
2930
|
+
const claim = this.admission.claim(meshName, 'RouteMesh local node dispatch');
|
|
2931
|
+
const ownedParts: RuntimeMessage[] = [];
|
|
2932
|
+
try {
|
|
2933
|
+
for (const part of parts) {
|
|
2934
|
+
ownedParts.push(RuntimeMessage.from(
|
|
2935
|
+
typeof (part as { data?: unknown }).data === 'function'
|
|
2936
|
+
? (part as { data(): Buffer }).data()
|
|
2937
|
+
: part
|
|
2938
|
+
));
|
|
2939
|
+
}
|
|
2940
|
+
} catch (error) {
|
|
2941
|
+
for (const part of ownedParts) part.close();
|
|
2942
|
+
claim.close();
|
|
2943
|
+
throw error;
|
|
2944
|
+
}
|
|
2945
|
+
try {
|
|
2946
|
+
state.taskRunner.runDetached('mesh-node-local-route-dispatch', async () => {
|
|
2947
|
+
try {
|
|
2948
|
+
const permit = await this.applicationJobQueue.acquire(
|
|
2949
|
+
state.abortController.signal
|
|
2950
|
+
);
|
|
2951
|
+
permit.markApplicationQueued();
|
|
2952
|
+
await runWithApplicationJobPermit(permit, () =>
|
|
2953
|
+
channelRuntime.dispatchLocalMeshRoute(meshName, sourceNodeRid, ownedParts));
|
|
2954
|
+
} finally {
|
|
2955
|
+
for (const part of ownedParts) part.close();
|
|
2956
|
+
claim.close();
|
|
2957
|
+
}
|
|
2958
|
+
});
|
|
2959
|
+
} catch (error) {
|
|
2960
|
+
for (const part of ownedParts) part.close();
|
|
2961
|
+
claim.close();
|
|
2962
|
+
throw error;
|
|
2963
|
+
}
|
|
2964
|
+
return { status: ZLinkSubmitStatus.Submitted } as const;
|
|
2965
|
+
}
|
|
2966
|
+
|
|
2967
|
+
private async dispatchMeshSpotRecord(
|
|
2968
|
+
meshName: string,
|
|
2969
|
+
owner: ReadyRecord,
|
|
2970
|
+
record: ReceiveRecord
|
|
2971
|
+
): Promise<void> {
|
|
2972
|
+
const envelope = decodeChannelEnvelope(record.parts, undefined, this.flowCreationEnabled());
|
|
2973
|
+
if (envelope.packetName === ZLINK_REMOTE_ACTOR_PACKET_RELAY_PACKET) {
|
|
2974
|
+
const payload = decodeChannelPayload(
|
|
2975
|
+
envelope,
|
|
2976
|
+
{ serializers: this.options.registration.messageSerializers }
|
|
2977
|
+
);
|
|
2978
|
+
const context = {
|
|
2979
|
+
meshName,
|
|
2980
|
+
packetName: envelope.packetName,
|
|
2981
|
+
contentType: envelope.header.contentType,
|
|
2982
|
+
sourceNodeRid: String(record.sourceNodeRid ?? '') as RoutingId,
|
|
2983
|
+
metadata: zlinkMessageMetadata(envelope.header.metadata),
|
|
2984
|
+
correlationId: envelope.header.correlationId ?? undefined
|
|
2985
|
+
};
|
|
2986
|
+
try {
|
|
2987
|
+
const response = await this.boundSessionRelay.actorPackets
|
|
2988
|
+
.receiveRemoteActorPacketRelay(payload, context);
|
|
2989
|
+
if (record.kind === ReceiveKind.SpotRequest) {
|
|
2990
|
+
record.reply(encodeChannelReplyParts(envelope.header, response));
|
|
2991
|
+
}
|
|
2992
|
+
} catch (error) {
|
|
2993
|
+
if (record.kind !== ReceiveKind.SpotRequest) {
|
|
2994
|
+
throw error;
|
|
2995
|
+
}
|
|
2996
|
+
record.reply(encodeChannelErrorReplyParts(
|
|
2997
|
+
envelope.header,
|
|
2998
|
+
error instanceof Error ? error.message : String(error)
|
|
2999
|
+
));
|
|
3000
|
+
}
|
|
3001
|
+
return;
|
|
3002
|
+
}
|
|
3003
|
+
if (await this.spotNodeRuntime?.dispatchEntrySpotRecord(meshName, owner, record) === true) {
|
|
3004
|
+
return;
|
|
3005
|
+
}
|
|
3006
|
+
if (this.spotManager === undefined) {
|
|
3007
|
+
throw new ZLinkConfigurationException('MeshNode Spot dispatch requires the Spot manager.');
|
|
3008
|
+
}
|
|
3009
|
+
await this.spotManager.dispatchMeshSpot(meshName, owner, record);
|
|
3010
|
+
}
|
|
3011
|
+
|
|
3012
|
+
private createDispatchErrorReporter(errorSink: ZLinkDispatchErrorSink): ZLinkDispatchErrorReporter {
|
|
3013
|
+
const existing = this.dispatchErrorReporters.get(errorSink);
|
|
3014
|
+
if (existing !== undefined) {
|
|
3015
|
+
return existing;
|
|
3016
|
+
}
|
|
3017
|
+
const reporter = new ZLinkDispatchErrorReporter(
|
|
3018
|
+
undefined,
|
|
3019
|
+
undefined,
|
|
3020
|
+
errorSink,
|
|
3021
|
+
this.diagnosticsContext(),
|
|
3022
|
+
this.metrics
|
|
3023
|
+
);
|
|
3024
|
+
this.dispatchErrorReporters.set(errorSink, reporter);
|
|
3025
|
+
return reporter;
|
|
3026
|
+
}
|
|
3027
|
+
|
|
3028
|
+
private detachedTaskRunner(): ZLinkDetachedTaskRunner {
|
|
3029
|
+
return {
|
|
3030
|
+
runDetached: (taskName, callback) => {
|
|
3031
|
+
const runner = this.executionState?.taskRunner;
|
|
3032
|
+
if (runner !== undefined) {
|
|
3033
|
+
runner.runDetached(taskName, () => callback());
|
|
3034
|
+
return;
|
|
3035
|
+
}
|
|
3036
|
+
void callback().catch((error) =>
|
|
3037
|
+
this.preStartErrorSink.reportRuntimeTaskException(taskName, error));
|
|
3038
|
+
}
|
|
3039
|
+
};
|
|
3040
|
+
}
|
|
3041
|
+
|
|
3042
|
+
private diagnosticsContext(): ZLinkDiagnosticsContext {
|
|
3043
|
+
this.cachedDiagnosticsContext ??= createDiagnosticsContext(
|
|
3044
|
+
this.options.registration.dispatch,
|
|
3045
|
+
this.options.providerResolver,
|
|
3046
|
+
this.messageFlowModeCell
|
|
3047
|
+
);
|
|
3048
|
+
return this.cachedDiagnosticsContext;
|
|
3049
|
+
}
|
|
3050
|
+
|
|
3051
|
+
private flowCreationEnabled(): boolean {
|
|
3052
|
+
const mode = this.executionState === undefined
|
|
3053
|
+
? this.options.registration.dispatch?.diagnostics.messageFlow ?? 'errors'
|
|
3054
|
+
: this.messageFlowModeCell.mode;
|
|
3055
|
+
return mode !== 'off';
|
|
3056
|
+
}
|
|
3057
|
+
|
|
3058
|
+
private runLifecycle<T>(operation: () => T): T {
|
|
3059
|
+
const current = currentOrCreateFlow('Lifecycle', false);
|
|
3060
|
+
const flow = current?.flowOrigin === 'Lifecycle'
|
|
3061
|
+
? current
|
|
3062
|
+
: createInboundFlow(undefined, 'Lifecycle', this.flowCreationEnabled());
|
|
3063
|
+
return runWithFlow(flow, operation);
|
|
3064
|
+
}
|
|
3065
|
+
|
|
3066
|
+
requirePrimaryMeshNode() {
|
|
3067
|
+
const node = this.spotNodeRuntime?.primaryMeshNode;
|
|
3068
|
+
if (node === undefined) {
|
|
3069
|
+
throw new Error('Primary Entry Spot node is not started.');
|
|
3070
|
+
}
|
|
3071
|
+
return node;
|
|
3072
|
+
}
|
|
3073
|
+
|
|
3074
|
+
private ensureLocationRuntime(): ZLinkLocationRuntime | undefined {
|
|
3075
|
+
return this.locationOwner.ensureRuntime(this.meshRouters.primaryMeshName());
|
|
3076
|
+
}
|
|
3077
|
+
|
|
3078
|
+
private createLocationSpotRouteResolver(): ZLinkSpotRouteResolver | undefined {
|
|
3079
|
+
if (this.cachedLocationSpotRouteResolver !== undefined) {
|
|
3080
|
+
return this.cachedLocationSpotRouteResolver;
|
|
3081
|
+
}
|
|
3082
|
+
this.ensureLocationRuntime();
|
|
3083
|
+
const legacy = this.locationOwner.createSpotRouteResolver(
|
|
3084
|
+
this.meshRouters.spotLocationMeshNames(),
|
|
3085
|
+
this.meshRouters.spotRouterChannelIdByMesh(),
|
|
3086
|
+
(spotId) => this.spotManager?.resolveLocalSpotRoute(spotId)
|
|
3087
|
+
);
|
|
3088
|
+
const authority = this.locationOwner.currentStores?.locationStore;
|
|
3089
|
+
const resolver = authority === undefined
|
|
3090
|
+
? legacy
|
|
3091
|
+
: new ZLinkAuthoritySpotRouteResolver(
|
|
3092
|
+
authority,
|
|
3093
|
+
this.meshRouters.spotRouterChannelIdByMesh(),
|
|
3094
|
+
legacy,
|
|
3095
|
+
this.locationOwner.currentLeaseTracker,
|
|
3096
|
+
this.options.registration.locations.options.routeCacheMaxAgeMs,
|
|
3097
|
+
undefined,
|
|
3098
|
+
async (meshName, nodeRid, expectedLifecycleGeneration, signal) => {
|
|
3099
|
+
const descriptor = (await authority.listMeshNodes(
|
|
3100
|
+
meshName,
|
|
3101
|
+
undefined,
|
|
3102
|
+
signal
|
|
3103
|
+
)).items.find((candidate) =>
|
|
3104
|
+
routingIdsEqual(candidate.rid, nodeRid)
|
|
3105
|
+
&& candidate.lifecycleGeneration === expectedLifecycleGeneration
|
|
3106
|
+
);
|
|
3107
|
+
return descriptor?.state;
|
|
3108
|
+
}
|
|
3109
|
+
);
|
|
3110
|
+
this.cachedLocationSpotRouteResolver = resolver;
|
|
3111
|
+
this.locationOwner.setSpotRouteInvalidator(
|
|
3112
|
+
resolver === undefined ? undefined : spotId => resolver.invalidate?.(spotId)
|
|
3113
|
+
);
|
|
3114
|
+
return resolver;
|
|
3115
|
+
}
|
|
3116
|
+
|
|
3117
|
+
private createActorLocationResolver(): ZLinkStoreLocationResolvers | undefined {
|
|
3118
|
+
return this.locationOwner.createActorLocationResolver(
|
|
3119
|
+
this.meshRouters.spotLocationMeshNames()
|
|
3120
|
+
);
|
|
3121
|
+
}
|
|
3122
|
+
|
|
3123
|
+
}
|
|
3124
|
+
|
|
3125
|
+
export function hasUnsupportedManualTopology(
|
|
3126
|
+
registration: ZLinkFrameworkRegistration
|
|
3127
|
+
): boolean {
|
|
3128
|
+
if ([...registration.routeChannelOptions.values()].some((route) =>
|
|
3129
|
+
(route.manualConnections?.length ?? 0) > 0)) {
|
|
3130
|
+
return true;
|
|
3131
|
+
}
|
|
3132
|
+
|
|
3133
|
+
for (const node of registration.spotNodes.values()) {
|
|
3134
|
+
if ((node.router?.manualConnections?.length ?? 0) > 0
|
|
3135
|
+
|| (node.router?.manualPeerConnections?.length ?? 0) > 0) {
|
|
3136
|
+
return true;
|
|
3137
|
+
}
|
|
3138
|
+
}
|
|
3139
|
+
|
|
3140
|
+
for (const channel of registration.channels.values()) {
|
|
3141
|
+
if ((channel.client?.manualConnections?.length ?? 0) > 0
|
|
3142
|
+
|| (channel.subscriber?.manualConnections?.length ?? 0) > 0) {
|
|
3143
|
+
return true;
|
|
3144
|
+
}
|
|
3145
|
+
if (channel.publisher !== undefined
|
|
3146
|
+
&& !registration.locations.useInMemoryStores
|
|
3147
|
+
&& registration.locations.storeInstance === undefined) {
|
|
3148
|
+
return true;
|
|
3149
|
+
}
|
|
3150
|
+
}
|
|
3151
|
+
|
|
3152
|
+
return false;
|
|
3153
|
+
}
|
|
3154
|
+
|
|
3155
|
+
function hasConfiguredLocationStore(registration: ZLinkFrameworkRegistration): boolean {
|
|
3156
|
+
return registration.locations.useInMemoryStores
|
|
3157
|
+
|| registration.locations.storeInstance !== undefined;
|
|
3158
|
+
}
|
|
3159
|
+
|
|
3160
|
+
export function hasExactPeerReadiness(
|
|
3161
|
+
descriptors: readonly ZLinkMeshNodeDescriptor[],
|
|
3162
|
+
local: {
|
|
3163
|
+
readonly routingId: unknown;
|
|
3164
|
+
readonly lifecycleGeneration: bigint;
|
|
3165
|
+
readonly applicationVersion?: bigint;
|
|
3166
|
+
readonly maintenanceWave?: string;
|
|
3167
|
+
},
|
|
3168
|
+
peers: readonly {
|
|
3169
|
+
readonly routingId: unknown | null;
|
|
3170
|
+
readonly lifecycleGeneration: bigint;
|
|
3171
|
+
readonly state: number;
|
|
3172
|
+
}[]
|
|
3173
|
+
): boolean {
|
|
3174
|
+
const replacementDescriptors = descriptors.filter((descriptor) =>
|
|
3175
|
+
!(String(descriptor.rid) === String(local.routingId)
|
|
3176
|
+
&& descriptor.lifecycleGeneration === local.lifecycleGeneration)
|
|
3177
|
+
&& descriptor.state === ZLinkFrameworkRuntimeState.Serving
|
|
3178
|
+
&& local.applicationVersion !== undefined
|
|
3179
|
+
&& descriptor.applicationVersion === local.applicationVersion
|
|
3180
|
+
&& descriptor.objectRole === ZLinkObjectRole.Server
|
|
3181
|
+
&& (local.maintenanceWave === undefined
|
|
3182
|
+
|| descriptor.maintenanceWave !== local.maintenanceWave));
|
|
3183
|
+
return replacementDescriptors.length > 0
|
|
3184
|
+
&& replacementDescriptors.some((descriptor) =>
|
|
3185
|
+
peers.some((peer) => peer.routingId !== null
|
|
3186
|
+
&& String(peer.routingId) === String(descriptor.rid)
|
|
3187
|
+
&& peer.lifecycleGeneration === descriptor.lifecycleGeneration
|
|
3188
|
+
&& peer.state === 3));
|
|
3189
|
+
}
|
|
3190
|
+
|
|
3191
|
+
export {
|
|
3192
|
+
ZLinkActorTransferAuthorityRuntime,
|
|
3193
|
+
transferIdString
|
|
3194
|
+
} from './actor-transfer-authority-runtime';
|
|
3195
|
+
export {
|
|
3196
|
+
ZLinkRetiringRollbackError,
|
|
3197
|
+
ZLinkRouteMeshRuntimeCoordinator
|
|
3198
|
+
} from './route-mesh-runtime';
|
|
3199
|
+
export {
|
|
3200
|
+
ZLinkRelocationStateIncompatibleError
|
|
3201
|
+
} from './service-relocation-host-runtime';
|
|
3202
|
+
export {
|
|
3203
|
+
ZLinkHostSpotAddressTransport,
|
|
3204
|
+
type ZLinkHostSpotAddressTransportOptions
|
|
3205
|
+
} from './spot-address-transport';
|
|
3206
|
+
export {
|
|
3207
|
+
ZLinkUserSpotCreationCoordinator,
|
|
3208
|
+
type ZLinkUserSpotCreationCoordinatorOptions,
|
|
3209
|
+
type ZLinkUserSpotCreationRequest,
|
|
3210
|
+
type ZLinkUserSpotCreationResult
|
|
3211
|
+
} from './user-spot-creation-coordinator';
|
|
3212
|
+
|
|
3213
|
+
async function waitForForcedSessionNotification(operation: Promise<void> | undefined): Promise<void> {
|
|
3214
|
+
if (operation === undefined) return;
|
|
3215
|
+
let timeoutHandle: ReturnType<typeof setTimeout> | undefined;
|
|
3216
|
+
const timeout = new Promise<void>((resolve) => {
|
|
3217
|
+
timeoutHandle = setTimeout(resolve, 100);
|
|
3218
|
+
});
|
|
3219
|
+
try {
|
|
3220
|
+
await Promise.race([operation.catch(() => undefined), timeout]);
|
|
3221
|
+
} finally {
|
|
3222
|
+
if (timeoutHandle !== undefined) clearTimeout(timeoutHandle);
|
|
3223
|
+
}
|
|
3224
|
+
}
|
|
3225
|
+
|
|
3226
|
+
async function awaitWithDrainSignal(
|
|
3227
|
+
operation: Promise<void> | undefined,
|
|
3228
|
+
signal: AbortSignal
|
|
3229
|
+
): Promise<void> {
|
|
3230
|
+
if (operation === undefined) return;
|
|
3231
|
+
if (signal.aborted) throw signal.reason;
|
|
3232
|
+
await new Promise<void>((resolve, reject) => {
|
|
3233
|
+
const onAbort = () => {
|
|
3234
|
+
reject(signal.reason);
|
|
3235
|
+
};
|
|
3236
|
+
signal.addEventListener('abort', onAbort, { once: true });
|
|
3237
|
+
void operation.then(
|
|
3238
|
+
() => {
|
|
3239
|
+
signal.removeEventListener('abort', onAbort);
|
|
3240
|
+
resolve();
|
|
3241
|
+
},
|
|
3242
|
+
error => {
|
|
3243
|
+
signal.removeEventListener('abort', onAbort);
|
|
3244
|
+
reject(error);
|
|
3245
|
+
}
|
|
3246
|
+
);
|
|
3247
|
+
});
|
|
3248
|
+
}
|
|
3249
|
+
|
|
3250
|
+
class ZLinkDrainingStatePublishError extends Error {
|
|
3251
|
+
constructor(cause: unknown) {
|
|
3252
|
+
super('Failed to publish draining peer rows.', { cause });
|
|
3253
|
+
this.name = 'ZLinkDrainingStatePublishError';
|
|
3254
|
+
}
|
|
3255
|
+
}
|
|
3256
|
+
|
|
3257
|
+
function resolveBackendAdapterFactory(internalOptions: unknown): ZLinkBackendAdapterFactory {
|
|
3258
|
+
if (
|
|
3259
|
+
typeof internalOptions === 'object'
|
|
3260
|
+
&& internalOptions !== null
|
|
3261
|
+
&& 'backendAdapterFactory' in internalOptions
|
|
3262
|
+
) {
|
|
3263
|
+
const factory = (internalOptions as { readonly backendAdapterFactory?: ZLinkBackendAdapterFactory }).backendAdapterFactory;
|
|
3264
|
+
if (factory !== undefined) {
|
|
3265
|
+
return factory;
|
|
3266
|
+
}
|
|
3267
|
+
}
|
|
3268
|
+
return new ZLinkNodeBackendAdapterFactory();
|
|
3269
|
+
}
|
|
3270
|
+
|
|
3271
|
+
function resolveStreamPayloadCodec(registration: ZLinkFrameworkRegistration): ZLinkStreamPayloadCodec | undefined {
|
|
3272
|
+
const codec = registration.codecs.streamCodecs.values().next().value;
|
|
3273
|
+
if (isStreamPayloadCodec(codec)) {
|
|
3274
|
+
return codec;
|
|
3275
|
+
}
|
|
3276
|
+
return undefined;
|
|
3277
|
+
}
|
|
3278
|
+
|
|
3279
|
+
function runtimeStateMetricName(state: ZLinkFrameworkRuntimeState): string {
|
|
3280
|
+
switch (state) {
|
|
3281
|
+
case ZLinkFrameworkRuntimeState.Preparing: return 'preparing';
|
|
3282
|
+
case ZLinkFrameworkRuntimeState.Serving: return 'serving';
|
|
3283
|
+
case ZLinkFrameworkRuntimeState.Relocating: return 'relocating';
|
|
3284
|
+
case ZLinkFrameworkRuntimeState.Relocated: return 'relocated';
|
|
3285
|
+
case ZLinkFrameworkRuntimeState.Draining: return 'draining';
|
|
3286
|
+
case ZLinkFrameworkRuntimeState.Stopped: return 'stopped';
|
|
3287
|
+
case ZLinkFrameworkRuntimeState.Error: return 'error';
|
|
3288
|
+
}
|
|
3289
|
+
}
|
|
3290
|
+
|
|
3291
|
+
function relocationModeMetricName(mode: ZLinkFrameworkRelocationMode): string {
|
|
3292
|
+
return mode === ZLinkFrameworkRelocationMode.RollingUpdate
|
|
3293
|
+
? 'rolling_update'
|
|
3294
|
+
: 'planned_maintenance';
|
|
3295
|
+
}
|
|
3296
|
+
|
|
3297
|
+
function relocationReasonMetricName(reason: ZLinkFrameworkRelocationReason): string {
|
|
3298
|
+
switch (reason) {
|
|
3299
|
+
case ZLinkFrameworkRelocationReason.None: return 'none';
|
|
3300
|
+
case ZLinkFrameworkRelocationReason.TargetUnavailable: return 'target_unavailable';
|
|
3301
|
+
case ZLinkFrameworkRelocationReason.StoreUnavailable: return 'store_unavailable';
|
|
3302
|
+
case ZLinkFrameworkRelocationReason.RelocationDisabled: return 'relocation_disabled';
|
|
3303
|
+
case ZLinkFrameworkRelocationReason.StateIncompatible: return 'state_incompatible';
|
|
3304
|
+
case ZLinkFrameworkRelocationReason.DeadlineExceeded: return 'deadline_exceeded';
|
|
3305
|
+
case ZLinkFrameworkRelocationReason.RelocationFailed: return 'relocation_failed';
|
|
3306
|
+
case ZLinkFrameworkRelocationReason.RuntimeNotReady: return 'runtime_not_ready';
|
|
3307
|
+
case ZLinkFrameworkRelocationReason.ManualTopologyUnsupported: return 'manual_topology_unsupported';
|
|
3308
|
+
case ZLinkFrameworkRelocationReason.ShutdownRequested: return 'shutdown_requested';
|
|
3309
|
+
case ZLinkFrameworkRelocationReason.OperationInProgress: return 'operation_in_progress';
|
|
3310
|
+
}
|
|
3311
|
+
}
|
|
3312
|
+
|
|
3313
|
+
function terminationReasonMetricName(reason: ZLinkFrameworkTerminationReason): string {
|
|
3314
|
+
switch (reason) {
|
|
3315
|
+
case ZLinkFrameworkTerminationReason.None: return 'none';
|
|
3316
|
+
case ZLinkFrameworkTerminationReason.DeadlineExceeded: return 'deadline_exceeded';
|
|
3317
|
+
case ZLinkFrameworkTerminationReason.TeardownFailed: return 'teardown_failed';
|
|
3318
|
+
}
|
|
3319
|
+
}
|
|
3320
|
+
|
|
3321
|
+
function isStreamPayloadCodec(codec: unknown): codec is ZLinkStreamPayloadCodec {
|
|
3322
|
+
return typeof codec === 'object'
|
|
3323
|
+
&& codec !== null
|
|
3324
|
+
&& typeof (codec as { encode?: unknown }).encode === 'function';
|
|
3325
|
+
}
|
|
3326
|
+
|
|
3327
|
+
function selectLocationPlacementDescriptor(
|
|
3328
|
+
descriptors: readonly ZLinkMeshNodeDescriptor[]
|
|
3329
|
+
): ZLinkMeshNodeDescriptor | undefined {
|
|
3330
|
+
const total = descriptors.reduce(
|
|
3331
|
+
(sum, descriptor) => sum + BigInt(descriptor.placementWeight),
|
|
3332
|
+
0n
|
|
3333
|
+
);
|
|
3334
|
+
if (total === 0n) return undefined;
|
|
3335
|
+
let point = randomBigIntBelow(total);
|
|
3336
|
+
for (const descriptor of descriptors) {
|
|
3337
|
+
const weight = BigInt(descriptor.placementWeight);
|
|
3338
|
+
if (point < weight) return descriptor;
|
|
3339
|
+
point -= weight;
|
|
3340
|
+
}
|
|
3341
|
+
return descriptors.at(-1);
|
|
3342
|
+
}
|
|
3343
|
+
|
|
3344
|
+
async function selectReadyLocationPlacementDescriptor(
|
|
3345
|
+
descriptors: readonly ZLinkMeshNodeDescriptor[],
|
|
3346
|
+
node: ZLinkBackendMeshNode | undefined,
|
|
3347
|
+
signal: AbortSignal | undefined,
|
|
3348
|
+
isEligible: (descriptor: ZLinkMeshNodeDescriptor) => boolean
|
|
3349
|
+
): Promise<ZLinkMeshNodeDescriptor | undefined> {
|
|
3350
|
+
const eligible = descriptors.filter(isEligible);
|
|
3351
|
+
if (eligible.length === 0) return undefined;
|
|
3352
|
+
for (;;) {
|
|
3353
|
+
const localStatus = node?.status();
|
|
3354
|
+
const selected = selectLocationPlacementDescriptor(
|
|
3355
|
+
eligible.filter(descriptor => isPlacementTargetReady(node, localStatus, descriptor))
|
|
3356
|
+
);
|
|
3357
|
+
if (selected !== undefined) return selected;
|
|
3358
|
+
try {
|
|
3359
|
+
await waitForPlacementReadiness(signal);
|
|
3360
|
+
} catch {
|
|
3361
|
+
return undefined;
|
|
3362
|
+
}
|
|
3363
|
+
}
|
|
3364
|
+
}
|
|
3365
|
+
|
|
3366
|
+
function isPlacementTargetReady(
|
|
3367
|
+
node: ZLinkBackendMeshNode | undefined,
|
|
3368
|
+
localStatus: ReturnType<ZLinkBackendMeshNode['status']> | undefined,
|
|
3369
|
+
descriptor: ZLinkMeshNodeDescriptor
|
|
3370
|
+
): boolean {
|
|
3371
|
+
if (node === undefined) return true;
|
|
3372
|
+
if (localStatus !== undefined
|
|
3373
|
+
&& String(localStatus.routingId) === String(descriptor.rid)
|
|
3374
|
+
&& localStatus.lifecycleGeneration === descriptor.lifecycleGeneration) {
|
|
3375
|
+
return true;
|
|
3376
|
+
}
|
|
3377
|
+
return node.isPeerRouteReady?.(descriptor.rid, descriptor.lifecycleGeneration) ?? true;
|
|
3378
|
+
}
|
|
3379
|
+
|
|
3380
|
+
function waitForPlacementReadiness(signal?: AbortSignal): Promise<void> {
|
|
3381
|
+
if (signal?.aborted === true) return Promise.reject(signal.reason);
|
|
3382
|
+
return new Promise<void>((resolve, reject) => {
|
|
3383
|
+
const timer = setTimeout(() => {
|
|
3384
|
+
signal?.removeEventListener('abort', abort);
|
|
3385
|
+
resolve();
|
|
3386
|
+
}, 10);
|
|
3387
|
+
const abort = () => {
|
|
3388
|
+
clearTimeout(timer);
|
|
3389
|
+
signal?.removeEventListener('abort', abort);
|
|
3390
|
+
reject(signal?.reason);
|
|
3391
|
+
};
|
|
3392
|
+
signal?.addEventListener('abort', abort, { once: true });
|
|
3393
|
+
});
|
|
3394
|
+
}
|
|
3395
|
+
|
|
3396
|
+
function randomBigIntBelow(exclusiveUpperBound: bigint): bigint {
|
|
3397
|
+
if (exclusiveUpperBound <= 0n) {
|
|
3398
|
+
throw new RangeError('Random selection upper bound must be positive.');
|
|
3399
|
+
}
|
|
3400
|
+
const bitLength = exclusiveUpperBound.toString(2).length;
|
|
3401
|
+
const byteLength = Math.ceil(bitLength / 8);
|
|
3402
|
+
const highBitMask = 0xff >> (byteLength * 8 - bitLength);
|
|
3403
|
+
for (;;) {
|
|
3404
|
+
const bytes = randomBytes(byteLength);
|
|
3405
|
+
bytes[0] = bytes[0]! & highBitMask;
|
|
3406
|
+
const value = BigInt(`0x${bytes.toString('hex')}`);
|
|
3407
|
+
if (value < exclusiveUpperBound) return value;
|
|
3408
|
+
}
|
|
3409
|
+
}
|
|
3410
|
+
|
|
3411
|
+
function relocationReason(reason: string): ZLinkFrameworkRelocationReason {
|
|
3412
|
+
switch (reason) {
|
|
3413
|
+
case 'deadline_exceeded': return ZLinkFrameworkRelocationReason.DeadlineExceeded;
|
|
3414
|
+
case 'store_unavailable': return ZLinkFrameworkRelocationReason.StoreUnavailable;
|
|
3415
|
+
case 'target_unavailable': return ZLinkFrameworkRelocationReason.TargetUnavailable;
|
|
3416
|
+
default: return ZLinkFrameworkRelocationReason.RelocationFailed;
|
|
3417
|
+
}
|
|
3418
|
+
}
|
|
3419
|
+
|
|
3420
|
+
function rewriteAuthorityPayloadForOwner(
|
|
3421
|
+
payload: Uint8Array,
|
|
3422
|
+
owner: ZLinkLocationOwnerToken
|
|
3423
|
+
): Uint8Array {
|
|
3424
|
+
const applicationPayload = serviceRelocationAuthorityApplicationPayload(payload);
|
|
3425
|
+
const rewritten = isActorAuthorityPayload(applicationPayload)
|
|
3426
|
+
? rewriteActorAuthorityOwner(applicationPayload, owner)
|
|
3427
|
+
: rewriteServiceAuthorityOwner(applicationPayload, owner) ?? applicationPayload;
|
|
3428
|
+
return replaceServiceRelocationAuthorityApplicationPayload(payload, rewritten);
|
|
3429
|
+
}
|
|
3430
|
+
|
|
3431
|
+
function validateRelocationOptions(
|
|
3432
|
+
options: ZLinkFrameworkRelocationOptions | undefined,
|
|
3433
|
+
sourceApplicationVersion: bigint
|
|
3434
|
+
): bigint {
|
|
3435
|
+
if (options === undefined) {
|
|
3436
|
+
throw new TypeError('Relocation mode is required.');
|
|
3437
|
+
}
|
|
3438
|
+
const mode = options.mode as number;
|
|
3439
|
+
if (mode !== ZLinkFrameworkRelocationMode.PlannedMaintenance
|
|
3440
|
+
&& mode !== ZLinkFrameworkRelocationMode.RollingUpdate) {
|
|
3441
|
+
throw new TypeError('Relocation mode is required.');
|
|
3442
|
+
}
|
|
3443
|
+
if (options.mode === ZLinkFrameworkRelocationMode.PlannedMaintenance) {
|
|
3444
|
+
if (options.targetApplicationVersion !== undefined) {
|
|
3445
|
+
throw new TypeError(
|
|
3446
|
+
'PlannedMaintenance relocation cannot define targetApplicationVersion.');
|
|
3447
|
+
}
|
|
3448
|
+
return sourceApplicationVersion;
|
|
3449
|
+
}
|
|
3450
|
+
if (typeof options.targetApplicationVersion !== 'bigint'
|
|
3451
|
+
|| options.targetApplicationVersion <= sourceApplicationVersion) {
|
|
3452
|
+
throw new TypeError(
|
|
3453
|
+
'RollingUpdate relocation requires a targetApplicationVersion greater than the source version.');
|
|
3454
|
+
}
|
|
3455
|
+
return options.targetApplicationVersion;
|
|
3456
|
+
}
|
|
3457
|
+
|
|
3458
|
+
function blockedRelocation(
|
|
3459
|
+
mode: ZLinkFrameworkRelocationMode,
|
|
3460
|
+
effectiveTargetApplicationVersion: bigint,
|
|
3461
|
+
reason: ZLinkFrameworkRelocationReason
|
|
3462
|
+
): ZLinkFrameworkRelocationResult {
|
|
3463
|
+
return {
|
|
3464
|
+
mode,
|
|
3465
|
+
effectiveTargetApplicationVersion,
|
|
3466
|
+
outcome: ZLinkFrameworkRelocationOutcome.Blocked,
|
|
3467
|
+
reason
|
|
3468
|
+
};
|
|
3469
|
+
}
|
|
3470
|
+
|
|
3471
|
+
function waitForRuntimeOperation<T>(
|
|
3472
|
+
operation: Promise<T>,
|
|
3473
|
+
signal?: AbortSignal
|
|
3474
|
+
): Promise<T> {
|
|
3475
|
+
if (signal === undefined) return operation;
|
|
3476
|
+
signal.throwIfAborted();
|
|
3477
|
+
return new Promise((resolve, reject) => {
|
|
3478
|
+
const aborted = () => reject(signal.reason);
|
|
3479
|
+
signal.addEventListener('abort', aborted, { once: true });
|
|
3480
|
+
operation.then(resolve, reject).finally(() => signal.removeEventListener('abort', aborted));
|
|
3481
|
+
});
|
|
3482
|
+
}
|
|
3483
|
+
|
|
3484
|
+
function registeredRuntimeStores(
|
|
3485
|
+
registration: ZLinkFrameworkRegistration
|
|
3486
|
+
): readonly { dispose?(): void | Promise<void> }[] {
|
|
3487
|
+
const stores = [
|
|
3488
|
+
registration.locations.storeInstance,
|
|
3489
|
+
registration.locations.relocationStoreInstance
|
|
3490
|
+
];
|
|
3491
|
+
return stores.filter((store): store is NonNullable<typeof store> => store !== undefined);
|
|
3492
|
+
}
|