@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,3303 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
ActorRef,
|
|
3
|
+
RoutingId,
|
|
4
|
+
Type,
|
|
5
|
+
ZLinkMessageSerializer,
|
|
6
|
+
ZLinkInstanceSpot,
|
|
7
|
+
ZLinkActor,
|
|
8
|
+
ZLinkChannelClient,
|
|
9
|
+
ZLinkFanoutClient,
|
|
10
|
+
ZLinkSpot,
|
|
11
|
+
ZLinkSpotActorJoinResult,
|
|
12
|
+
ZLinkSpotInfo,
|
|
13
|
+
ZLinkSpotPublisherClient,
|
|
14
|
+
} from '../../contracts';
|
|
15
|
+
import type { ZLinkProviderResolver } from '../../contracts/Common/ZLinkProviderResolver';
|
|
16
|
+
import type {
|
|
17
|
+
ZLinkSpotActorRequestHandlerRegistration,
|
|
18
|
+
ZLinkSpotActorSendHandlerRegistration,
|
|
19
|
+
ZLinkSpotPacketHandlerRegistration,
|
|
20
|
+
ZLinkSpotSubscriptionHandlerRegistration,
|
|
21
|
+
ZLinkSpotTimerHandlerRegistration
|
|
22
|
+
} from '../../contracts/Configuration/RegistrationTypes';
|
|
23
|
+
export { createSpotHandle, resolveSpotHandle } from './spot-handle';
|
|
24
|
+
export { requestToSpotHandle, sendToSpotHandle } from './spot-outbound';
|
|
25
|
+
export { ZLinkSpotRoutedBoundSessionDispatch } from './spot-routed-bound-session-dispatch';
|
|
26
|
+
export { ZLinkSpotActorAdmissionCoordinator } from './spot-actor-admission-coordinator';
|
|
27
|
+
import type { ZLinkSpotRouteResolver, ZLinkSpotRouteTarget } from './spot-routing-internal';
|
|
28
|
+
import type { Message } from '../../contracts/Common/Message';
|
|
29
|
+
import type { ZLinkMessageFollowOrigin } from '../foundation/service-runtime-contracts';
|
|
30
|
+
import { awaitWithAbort, isAbortError, throwIfAborted } from '../abort';
|
|
31
|
+
import {
|
|
32
|
+
ZLinkMessage,
|
|
33
|
+
ZLinkFrameworkException,
|
|
34
|
+
ZLinkFrameworkErrorKind,
|
|
35
|
+
ZLinkSpotCloseReason,
|
|
36
|
+
ZLinkSpotKind
|
|
37
|
+
} from '../../contracts';
|
|
38
|
+
import {
|
|
39
|
+
ZLinkRuntimeMessageFlowOutcome as ZLinkMessageFlowOutcome,
|
|
40
|
+
ZLinkRuntimeDispatchErrorAction as ZLinkDispatchErrorAction,
|
|
41
|
+
ZLinkRuntimeDispatchErrorReason as ZLinkDispatchErrorReason,
|
|
42
|
+
ZLinkDispatchErrorSurface,
|
|
43
|
+
ZLinkDispatchMessageKind
|
|
44
|
+
} from '../../contracts/Dispatch/ZLinkDispatchOptions';
|
|
45
|
+
import {
|
|
46
|
+
createInboundFlow,
|
|
47
|
+
flowIfEnabled,
|
|
48
|
+
runWithFlow,
|
|
49
|
+
type ZLinkRuntimeEventPublisher
|
|
50
|
+
} from '../diagnostics';
|
|
51
|
+
import { ZLinkBufferMessage as RuntimeMessage } from '../backend/runtime-message';
|
|
52
|
+
import { SubmitResult } from '../backend/runtime-values';
|
|
53
|
+
import {
|
|
54
|
+
ActorLifecycleKind,
|
|
55
|
+
OperationKind,
|
|
56
|
+
ReceiveKind,
|
|
57
|
+
type ReadyRecord,
|
|
58
|
+
type ReceiveRecord
|
|
59
|
+
} from '../foundation/service-runtime-contracts';
|
|
60
|
+
import { zlinkMetadataByteLength, zlinkSerialWorkOptions } from '../execution/serial-work-size';
|
|
61
|
+
import {
|
|
62
|
+
ZLinkConfigurationException
|
|
63
|
+
} from '../configuration';
|
|
64
|
+
import {
|
|
65
|
+
ZLinkFrameworkInternalErrorKind,
|
|
66
|
+
createInternalFrameworkException,
|
|
67
|
+
internalFrameworkErrorKind,
|
|
68
|
+
internalFrameworkWireReply
|
|
69
|
+
} from '../framework-errors-internal';
|
|
70
|
+
import type {
|
|
71
|
+
ZLinkBackendSpot,
|
|
72
|
+
ZLinkBackendSpotNode
|
|
73
|
+
} from '../backend/contracts';
|
|
74
|
+
|
|
75
|
+
import { ZLinkDispatchErrorReporter } from '../channels';
|
|
76
|
+
import { ZLinkWorkerRuntime } from '../workers';
|
|
77
|
+
import {
|
|
78
|
+
type ZLinkActorHandoffPrefixAdmission,
|
|
79
|
+
type ZLinkActorHandoffPrefixRecord,
|
|
80
|
+
type ZLinkDeferredJoinAcceptedRoot,
|
|
81
|
+
type ZLinkRemoteBoundSessionTarget
|
|
82
|
+
} from '../actors';
|
|
83
|
+
import type { ZLinkLocationLifecycle } from '../locations';
|
|
84
|
+
import {
|
|
85
|
+
encodeFrameworkPayload,
|
|
86
|
+
encodeFrameworkPayloadMessage,
|
|
87
|
+
frameworkPayloadContentType,
|
|
88
|
+
wrapFrameworkPayloadMessage
|
|
89
|
+
} from '../messaging/payload-codec';
|
|
90
|
+
import {
|
|
91
|
+
decodeChannelEnvelope,
|
|
92
|
+
decodeChannelPayload,
|
|
93
|
+
encodeChannelErrorReplyParts,
|
|
94
|
+
encodeChannelReplyParts
|
|
95
|
+
} from '../channels/channel-envelope';
|
|
96
|
+
import {
|
|
97
|
+
decodeStreamHeader,
|
|
98
|
+
encodeStreamHeader,
|
|
99
|
+
streamCodecForContentType,
|
|
100
|
+
ZLinkStreamHeaderFlags,
|
|
101
|
+
ZLinkStreamMessageKind
|
|
102
|
+
} from '../streams/protocol';
|
|
103
|
+
import {
|
|
104
|
+
REMOTE_ACTOR_JOIN_PACKET,
|
|
105
|
+
REMOTE_ACTOR_JOIN_ABORT,
|
|
106
|
+
REMOTE_ACTOR_JOIN_ADMISSION,
|
|
107
|
+
REMOTE_ACTOR_JOIN_COMMIT,
|
|
108
|
+
type ZLinkRemoteActorJoinWirePayload
|
|
109
|
+
} from '../actors/actor-remote-wire';
|
|
110
|
+
import { replayActorHandoffBacklog, type ZLinkActorHandoffPacket } from '../actors/actor-handoff';
|
|
111
|
+
import {
|
|
112
|
+
decodeHandoffBacklog,
|
|
113
|
+
decodeRemoteActorRef,
|
|
114
|
+
decodeRemoteBoundSessionTarget
|
|
115
|
+
} from './spot-remote-codec';
|
|
116
|
+
import { decodeRoutingId, encodeRoutingIdStorageHex } from '../routing-id';
|
|
117
|
+
import type {
|
|
118
|
+
CanonicalActorJoinRecovery
|
|
119
|
+
} from '../foundation/actor-join-recovery-codec';
|
|
120
|
+
import { SERVICE_FRAMEWORK_MULTIPART_CONTENT_TYPE } from '../foundation/service-wire-constants.generated';
|
|
121
|
+
|
|
122
|
+
export { ZLinkSpotSerialTurnExecutor } from './spot-serial-turn-executor';
|
|
123
|
+
export { ZLinkSpotSerialExecutor } from './spot-serial-executor';
|
|
124
|
+
export {
|
|
125
|
+
ZLinkManagedTimer,
|
|
126
|
+
ZLinkSpotTimerRegistry
|
|
127
|
+
} from './spot-timer';
|
|
128
|
+
export {
|
|
129
|
+
DefaultZLinkSpotOutbound,
|
|
130
|
+
type ZLinkSpotAddressCallOptions,
|
|
131
|
+
type ZLinkSpotAddressTransport,
|
|
132
|
+
type ZLinkSpotRoutedRequestOptions,
|
|
133
|
+
type ZLinkSpotRoutedSendOptions,
|
|
134
|
+
type ZLinkSpotRoutedTransport
|
|
135
|
+
} from './spot-outbound';
|
|
136
|
+
import {
|
|
137
|
+
type ZLinkSpotRoutedTransport
|
|
138
|
+
} from './spot-outbound';
|
|
139
|
+
export {
|
|
140
|
+
DefaultZLinkSpotHandlerRegistry,
|
|
141
|
+
type ZLinkSpotHandlerRegistration
|
|
142
|
+
} from './spot-handler-registry';
|
|
143
|
+
export { ZLinkRuntimeSpotPublisherTransport } from './spot-publisher-transport';
|
|
144
|
+
import {
|
|
145
|
+
ZLinkSpotActivationRegistry
|
|
146
|
+
} from './spot-activation-registry';
|
|
147
|
+
import {
|
|
148
|
+
ZLinkSpotCloseOccupiedError,
|
|
149
|
+
type ZLinkSpotActivation
|
|
150
|
+
} from './spot-activation-state';
|
|
151
|
+
import {
|
|
152
|
+
ZLinkSpotActivationLifecycle,
|
|
153
|
+
type ZLinkNativeSpotAuthority
|
|
154
|
+
} from './spot-activation';
|
|
155
|
+
import { ZLinkSpotActorMembership, type ZLinkActorJoinRollback } from './spot-actor-membership';
|
|
156
|
+
import { ZLinkFormalRemoteActorTransferRegistry } from './formal-remote-actor-transfer-registry';
|
|
157
|
+
import {
|
|
158
|
+
ZLinkFormalRemoteActorAdmissionRegistry,
|
|
159
|
+
type ZLinkFormalRemoteActorAdmissionResult,
|
|
160
|
+
type ZLinkFormalRemoteActorAdmissionRecord
|
|
161
|
+
} from './formal-remote-actor-admission-registry';
|
|
162
|
+
import type {
|
|
163
|
+
ZLinkSpotActorHandoffRuntime,
|
|
164
|
+
ZLinkSpotActorTransferRuntime,
|
|
165
|
+
ZLinkSpotBoundSessionRuntime
|
|
166
|
+
} from './spot-runtime-ports';
|
|
167
|
+
import type { ZLinkRuntimeAdmissionGate } from '../admission';
|
|
168
|
+
import type { ZLinkDetachedTaskRunner } from './spot-actor-join-dispatch';
|
|
169
|
+
import type { ZLinkLocalSpotCreateResult } from './spot-manager-internal-contracts';
|
|
170
|
+
export type { ZLinkLocalSpotCreateResult } from './spot-manager-internal-contracts';
|
|
171
|
+
export type { ZLinkDetachedTaskRunner } from './spot-actor-join-dispatch';
|
|
172
|
+
import { ZLinkSpotLocationClaim } from './spot-location-claim';
|
|
173
|
+
import { ZLinkRoutedSpotPacketDispatch } from './spot-routed-spot-packet-dispatch';
|
|
174
|
+
export { ZLinkEntrySpotActivation } from './spot-entry-activation';
|
|
175
|
+
export {
|
|
176
|
+
createFrameworkEntrySpotId,
|
|
177
|
+
ZLinkSpotNodeRuntimeManager,
|
|
178
|
+
type ZLinkSpotNodeRuntimeManagerOptions
|
|
179
|
+
} from './spot-node-runtime-manager';
|
|
180
|
+
export {
|
|
181
|
+
ZLinkPublicSpotManager,
|
|
182
|
+
type ZLinkPublicSpotManagerOptions
|
|
183
|
+
} from './spot-manager-public';
|
|
184
|
+
|
|
185
|
+
export interface ZLinkSpotManagerOptions {
|
|
186
|
+
readonly spotFactories: readonly Type<ZLinkSpot>[];
|
|
187
|
+
readonly instanceSpotFactories?: ReadonlyMap<
|
|
188
|
+
string,
|
|
189
|
+
ReadonlyMap<string, Type<ZLinkInstanceSpot>>
|
|
190
|
+
>;
|
|
191
|
+
readonly instanceSpotIdleTimeoutMs?: ReadonlyMap<string, number>;
|
|
192
|
+
readonly spotTimerHandlers?: readonly ZLinkSpotTimerHandlerRegistration[];
|
|
193
|
+
readonly spotPacketHandlers?: readonly ZLinkSpotPacketHandlerRegistration[];
|
|
194
|
+
readonly spotSubscriptionHandlers?: readonly ZLinkSpotSubscriptionHandlerRegistration[];
|
|
195
|
+
readonly spotActorSendHandlers?: readonly ZLinkSpotActorSendHandlerRegistration[];
|
|
196
|
+
readonly spotActorRequestHandlers?: readonly ZLinkSpotActorRequestHandlerRegistration[];
|
|
197
|
+
readonly nodeRid?: RoutingId;
|
|
198
|
+
readonly nodeRidProvider?: (meshName: string) => RoutingId | undefined;
|
|
199
|
+
readonly nodeGenerationProvider?: (meshName: string) => bigint | undefined;
|
|
200
|
+
readonly entryNodeRid?: RoutingId;
|
|
201
|
+
readonly entryNodeRidProvider?: () => RoutingId | undefined;
|
|
202
|
+
readonly entrySpotIdProvider?: (meshName: string) => string | undefined;
|
|
203
|
+
readonly entrySpotCallbacks?: {
|
|
204
|
+
onLeaveActor(
|
|
205
|
+
actor: ZLinkActor,
|
|
206
|
+
signal?: AbortSignal,
|
|
207
|
+
actorRef?: ActorRef,
|
|
208
|
+
membershipEpoch?: bigint
|
|
209
|
+
): Promise<void>;
|
|
210
|
+
};
|
|
211
|
+
readonly dispatchEntryActorPacket?: (
|
|
212
|
+
actorId: string,
|
|
213
|
+
parts: readonly Message[],
|
|
214
|
+
returnResponse?: boolean,
|
|
215
|
+
remoteBoundSessionTarget?: ZLinkRemoteBoundSessionTarget,
|
|
216
|
+
fallbackActorRef?: ActorRef,
|
|
217
|
+
requestTerminal?: (response: unknown) => Promise<void> | void,
|
|
218
|
+
messageFollowOrigin?: ZLinkMessageFollowOrigin
|
|
219
|
+
) => Promise<unknown>;
|
|
220
|
+
/**
|
|
221
|
+
* Commits a stateful MeshNode Actor return to the Entry Spot after the
|
|
222
|
+
* stateful reply has committed Core membership.
|
|
223
|
+
*/
|
|
224
|
+
readonly dispatchEntryActorJoin?: (
|
|
225
|
+
meshName: string,
|
|
226
|
+
actor: ZLinkActor,
|
|
227
|
+
handoffBacklog?: readonly ZLinkActorHandoffPacket[]
|
|
228
|
+
) => Promise<void>;
|
|
229
|
+
readonly actorCountProvider?: (spotId: RoutingId) => number;
|
|
230
|
+
readonly userSpotExecutionMode?: (
|
|
231
|
+
meshName: string,
|
|
232
|
+
spotType: Type<ZLinkSpot>
|
|
233
|
+
) => import('../../contracts').ZLinkUserSpotExecutionMode;
|
|
234
|
+
readonly userSpotRelocationCoordinationMode?: (
|
|
235
|
+
meshName: string,
|
|
236
|
+
spotType: Type<ZLinkSpot>
|
|
237
|
+
) => import('../../contracts').ZLinkSpotRelocationCoordinationMode;
|
|
238
|
+
readonly actorDispatchOwnerResolver?: (actorId: string) => {
|
|
239
|
+
readonly actorRef?: ActorRef;
|
|
240
|
+
readonly spotId?: RoutingId;
|
|
241
|
+
};
|
|
242
|
+
readonly actorBindingGenerationObserver?: (actorId: string, generation: bigint) => void;
|
|
243
|
+
readonly channelClient?: ZLinkChannelClient;
|
|
244
|
+
readonly fanoutClient?: ZLinkFanoutClient;
|
|
245
|
+
readonly spotPublisherClient?: ZLinkSpotPublisherClient;
|
|
246
|
+
readonly spotRouteResolver?: ZLinkSpotRouteResolver;
|
|
247
|
+
readonly routedTransport?: ZLinkSpotRoutedTransport;
|
|
248
|
+
readonly addressTransport?: import('./spot-outbound').ZLinkSpotAddressTransport;
|
|
249
|
+
readonly spotRouterChannelIdForMesh?: (meshName: string) => string;
|
|
250
|
+
readonly channelMeshNameForChannel?: (channelName: string) => string | undefined;
|
|
251
|
+
readonly providerResolver?: ZLinkProviderResolver;
|
|
252
|
+
readonly dispatchErrors?: ZLinkDispatchErrorReporter;
|
|
253
|
+
readonly runtimeEventPublisher?: ZLinkRuntimeEventPublisher;
|
|
254
|
+
readonly workerRuntime?: ZLinkWorkerRuntime;
|
|
255
|
+
readonly messageSerializers?: ReadonlyMap<string, ZLinkMessageSerializer>;
|
|
256
|
+
readonly locationLifecycle?: ZLinkLocationLifecycle;
|
|
257
|
+
readonly releaseInstanceAuthority?: (
|
|
258
|
+
meshName: string,
|
|
259
|
+
spotId: RoutingId,
|
|
260
|
+
objectGeneration: bigint
|
|
261
|
+
) => Promise<void>;
|
|
262
|
+
readonly beginInstanceIdleClosingAuthority?: (
|
|
263
|
+
meshName: string,
|
|
264
|
+
spotId: RoutingId
|
|
265
|
+
) => Promise<{ restoreReady(): Promise<void> } | undefined>;
|
|
266
|
+
readonly beginInstanceClosingAuthority?: (
|
|
267
|
+
meshName: string,
|
|
268
|
+
spotId: RoutingId
|
|
269
|
+
) => Promise<{ restoreReady(): Promise<void> } | undefined>;
|
|
270
|
+
readonly instanceSpotApplicationTargetProvider?: (
|
|
271
|
+
meshName: string,
|
|
272
|
+
spotId: RoutingId
|
|
273
|
+
) => { readonly stableType: string; readonly objectGeneration: bigint } | undefined;
|
|
274
|
+
readonly instanceSpotApplicationQuiescenceProvider?: (
|
|
275
|
+
meshName: string,
|
|
276
|
+
spotId: RoutingId,
|
|
277
|
+
signal?: AbortSignal
|
|
278
|
+
) => Promise<void>;
|
|
279
|
+
// Backs each user Spot with a core-native Spot object (registered for join
|
|
280
|
+
// routing by rid) so actor-join admission uses the same recv/reply round-trip
|
|
281
|
+
// as the Entry Spot and .NET, for local and remote callers alike.
|
|
282
|
+
readonly createNativeSpot?: (
|
|
283
|
+
meshName: string,
|
|
284
|
+
spotId: RoutingId,
|
|
285
|
+
authority?: ZLinkNativeSpotAuthority
|
|
286
|
+
) => ZLinkBackendSpot | undefined;
|
|
287
|
+
readonly createReceived?: () => import('../backend').ZLinkBackendReceived;
|
|
288
|
+
readonly createTopicMessage?: () => import('../backend').ZLinkBackendTopicMessage;
|
|
289
|
+
readonly nativeSpotNodeProvider?: (meshName: string) => ZLinkBackendSpotNode | undefined;
|
|
290
|
+
readonly actorResolver?: (actorId: string) => ZLinkActor | undefined;
|
|
291
|
+
readonly canonicalActorJoinResolver?: (fence: {
|
|
292
|
+
readonly actorId: string;
|
|
293
|
+
readonly actorNodeRid: string;
|
|
294
|
+
readonly actorGeneration: bigint;
|
|
295
|
+
readonly actorNodeGeneration: bigint;
|
|
296
|
+
readonly authorityOwnerGeneration: bigint;
|
|
297
|
+
readonly ownerLeaseGeneration: bigint;
|
|
298
|
+
}) => Promise<{ readonly actorType: string }>;
|
|
299
|
+
readonly actorLifecycleResolver?: (actorId: string) => ZLinkActor | undefined;
|
|
300
|
+
readonly detachedTaskRunner?: ZLinkDetachedTaskRunner;
|
|
301
|
+
readonly actorTransferRuntime?: ZLinkSpotActorTransferRuntime;
|
|
302
|
+
readonly boundSessionRuntime?: ZLinkSpotBoundSessionRuntime;
|
|
303
|
+
readonly actorHandoffRuntime?: ZLinkSpotActorHandoffRuntime;
|
|
304
|
+
readonly metrics?: import('../diagnostics').ZLinkRuntimeMetrics;
|
|
305
|
+
readonly admission?: ZLinkRuntimeAdmissionGate;
|
|
306
|
+
readonly statefulExecutionAllowed?: () => boolean;
|
|
307
|
+
readonly activationConcurrencyLimitProvider?: (meshName: string) => number;
|
|
308
|
+
readonly onInstanceActivationConcurrencyChanged?: (meshName: string) => void;
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
export class DefaultZLinkSpotManager {
|
|
312
|
+
private readonly factories: ReadonlySet<Type<ZLinkSpot>>;
|
|
313
|
+
private readonly activations: ZLinkSpotActivationRegistry;
|
|
314
|
+
private readonly workerRuntime: ZLinkWorkerRuntime;
|
|
315
|
+
private readonly locationClaim: ZLinkSpotLocationClaim;
|
|
316
|
+
private readonly routedSpotPackets: ZLinkRoutedSpotPacketDispatch;
|
|
317
|
+
private readonly actorMembership: ZLinkSpotActorMembership;
|
|
318
|
+
private readonly activationLifecycle: ZLinkSpotActivationLifecycle;
|
|
319
|
+
private readonly formalRemoteTransfers = new ZLinkFormalRemoteActorTransferRegistry();
|
|
320
|
+
private readonly formalRemoteActorAdmissions = new ZLinkFormalRemoteActorAdmissionRegistry();
|
|
321
|
+
private readonly pendingInstanceMaterializations = new Map<
|
|
322
|
+
string,
|
|
323
|
+
Promise<ZLinkSpotActivation>
|
|
324
|
+
>();
|
|
325
|
+
// Parallel index keyed by `${meshName}\0${spotId}` so per-activation
|
|
326
|
+
// callbacks (isInstanceMaterializing, sibling-generation lookups) resolve
|
|
327
|
+
// in O(1) instead of scanning every pending key.
|
|
328
|
+
private readonly pendingInstanceMaterializationsByPrefix = new Map<
|
|
329
|
+
string,
|
|
330
|
+
Map<string, Promise<ZLinkSpotActivation>>
|
|
331
|
+
>();
|
|
332
|
+
private readonly instanceActivationGates = new Map<string, {
|
|
333
|
+
readonly meshName: string;
|
|
334
|
+
readonly limit: number;
|
|
335
|
+
active: number;
|
|
336
|
+
// Tombstone slots + head cursor keep abort O(1) and admit O(1) amortized
|
|
337
|
+
// instead of indexOf/splice + shift scans under a cancellation storm.
|
|
338
|
+
readonly waiters: Array<{
|
|
339
|
+
resolve: (release: () => void) => void;
|
|
340
|
+
reject: (error: unknown) => void;
|
|
341
|
+
signal?: AbortSignal;
|
|
342
|
+
abort?: () => void;
|
|
343
|
+
} | undefined>;
|
|
344
|
+
waiterHead: number;
|
|
345
|
+
}>();
|
|
346
|
+
private readonly pendingInstanceCloses = new Map<string, Promise<boolean>>();
|
|
347
|
+
private readonly pendingInstanceTerminals = new Map<string, number>();
|
|
348
|
+
private readonly pendingInstanceTerminalGenerations = new Map<string, Map<string, number>>();
|
|
349
|
+
private readonly deferredInstanceAuthorityReleases = new Map<string, Set<bigint>>();
|
|
350
|
+
private idleSweepTimer?: ReturnType<typeof setTimeout>;
|
|
351
|
+
private idleSweepRunning = false;
|
|
352
|
+
|
|
353
|
+
constructor(
|
|
354
|
+
private readonly options: ZLinkSpotManagerOptions,
|
|
355
|
+
timerClock?: import('./spot-timer').ZLinkTimerClock
|
|
356
|
+
) {
|
|
357
|
+
this.activations = new ZLinkSpotActivationRegistry(options.metrics);
|
|
358
|
+
this.factories = new Set(options.spotFactories);
|
|
359
|
+
this.workerRuntime = options.workerRuntime ?? new ZLinkWorkerRuntime();
|
|
360
|
+
this.locationClaim = new ZLinkSpotLocationClaim({
|
|
361
|
+
lifecycle: options.locationLifecycle,
|
|
362
|
+
nodeRid: options.nodeRid,
|
|
363
|
+
nodeRidProvider: options.nodeRidProvider,
|
|
364
|
+
nodeGenerationProvider: options.nodeGenerationProvider
|
|
365
|
+
});
|
|
366
|
+
this.routedSpotPackets = new ZLinkRoutedSpotPacketDispatch({
|
|
367
|
+
resolveActivation: (spotId) => this.activations.resolveUnique(spotId),
|
|
368
|
+
claimApplicationWork: options.admission === undefined
|
|
369
|
+
? undefined
|
|
370
|
+
: (meshName) => options.admission!.claim(meshName, 'Spot route dispatch'),
|
|
371
|
+
providerResolver: options.providerResolver,
|
|
372
|
+
dispatchErrors: options.dispatchErrors
|
|
373
|
+
});
|
|
374
|
+
this.actorMembership = new ZLinkSpotActorMembership({
|
|
375
|
+
resolveActivation: (spotId, meshName) => meshName === undefined
|
|
376
|
+
? this.activations.resolveUnique(spotId)
|
|
377
|
+
: this.activations.resolve(meshName, spotId),
|
|
378
|
+
providerResolver: options.providerResolver,
|
|
379
|
+
messageSerializers: options.messageSerializers,
|
|
380
|
+
dispatchErrors: options.dispatchErrors,
|
|
381
|
+
entrySpotCallbacks: options.entrySpotCallbacks,
|
|
382
|
+
nodeRid: options.nodeRid,
|
|
383
|
+
nodeRidProvider: options.nodeRidProvider,
|
|
384
|
+
entryNodeRid: options.entryNodeRid,
|
|
385
|
+
entryNodeRidProvider: options.entryNodeRidProvider,
|
|
386
|
+
entrySpotIdProvider: options.entrySpotIdProvider,
|
|
387
|
+
spotRouteResolver: options.spotRouteResolver,
|
|
388
|
+
actorTransferRuntime: options.actorTransferRuntime
|
|
389
|
+
});
|
|
390
|
+
this.activationLifecycle = new ZLinkSpotActivationLifecycle({
|
|
391
|
+
timerClock,
|
|
392
|
+
spotTimerHandlers: options.spotTimerHandlers,
|
|
393
|
+
spotPacketHandlers: options.spotPacketHandlers,
|
|
394
|
+
spotSubscriptionHandlers: options.spotSubscriptionHandlers,
|
|
395
|
+
spotActorSendHandlers: options.spotActorSendHandlers,
|
|
396
|
+
spotActorRequestHandlers: options.spotActorRequestHandlers,
|
|
397
|
+
nodeRid: options.nodeRid,
|
|
398
|
+
nodeRidProvider: options.nodeRidProvider,
|
|
399
|
+
actorCountProvider: options.actorCountProvider,
|
|
400
|
+
userSpotExecutionMode: options.userSpotExecutionMode,
|
|
401
|
+
userSpotRelocationCoordinationMode: options.userSpotRelocationCoordinationMode,
|
|
402
|
+
channelClient: options.channelClient,
|
|
403
|
+
fanoutClient: options.fanoutClient,
|
|
404
|
+
spotPublisherClient: options.spotPublisherClient,
|
|
405
|
+
routedTransport: options.routedTransport,
|
|
406
|
+
addressTransport: options.addressTransport,
|
|
407
|
+
spotRouterChannelIdForMesh: options.spotRouterChannelIdForMesh,
|
|
408
|
+
providerResolver: options.providerResolver,
|
|
409
|
+
dispatchErrors: options.dispatchErrors,
|
|
410
|
+
runtimeEventPublisher: options.runtimeEventPublisher,
|
|
411
|
+
workerRuntime: this.workerRuntime,
|
|
412
|
+
messageSerializers: options.messageSerializers,
|
|
413
|
+
locationClaim: this.locationClaim,
|
|
414
|
+
createNativeSpot: options.createNativeSpot,
|
|
415
|
+
createReceived: options.createReceived,
|
|
416
|
+
createTopicMessage: options.createTopicMessage,
|
|
417
|
+
nativeSpotNodeProvider: options.nativeSpotNodeProvider,
|
|
418
|
+
actorResolver: options.actorResolver,
|
|
419
|
+
detachedTaskRunner: options.detachedTaskRunner,
|
|
420
|
+
actorTransferRuntime: options.actorTransferRuntime,
|
|
421
|
+
boundSessionRuntime: options.boundSessionRuntime,
|
|
422
|
+
actorHandoffRuntime: options.actorHandoffRuntime,
|
|
423
|
+
admission: options.admission,
|
|
424
|
+
statefulExecutionAllowed: options.statefulExecutionAllowed,
|
|
425
|
+
leaveActor: (spotId, actor, signal, meshName) =>
|
|
426
|
+
this.actorMembership.leaveActor(spotId, actor, signal, meshName),
|
|
427
|
+
closeSpot: (meshName, spotId, signal, reason) =>
|
|
428
|
+
this.closeWithReason(meshName, spotId, signal, reason),
|
|
429
|
+
registerActivation: (activation) => {
|
|
430
|
+
this.activations.register(activation);
|
|
431
|
+
this.scheduleIdleSweep();
|
|
432
|
+
},
|
|
433
|
+
// Spec 15 §4.2 relocation temporary queue: production ingress
|
|
434
|
+
// consults the same admission attempts registered on Accepted
|
|
435
|
+
// (`formalRemoteActorAdmissions.begin`, in dispatchMeshActorJoin)
|
|
436
|
+
// instead of dropping an arrival for an Actor that has not yet
|
|
437
|
+
// cut over locally.
|
|
438
|
+
routeToActorJoinPrewarm: (actorId, objectGeneration, arrival) =>
|
|
439
|
+
this.formalRemoteActorAdmissions.routeIngress(actorId, objectGeneration, arrival),
|
|
440
|
+
releaseLocation: (activation, meshName, spotId) => {
|
|
441
|
+
if (activation.domain.kind === 'user') {
|
|
442
|
+
return this.locationClaim.release(meshName, spotId);
|
|
443
|
+
}
|
|
444
|
+
const currentApplication = this.options.instanceSpotApplicationTargetProvider?.(
|
|
445
|
+
meshName,
|
|
446
|
+
spotId
|
|
447
|
+
);
|
|
448
|
+
if (currentApplication !== undefined
|
|
449
|
+
&& currentApplication.objectGeneration !== activation.domain.objectGeneration) {
|
|
450
|
+
// A superseded local application must not release the authority row
|
|
451
|
+
// that now belongs to the newer object generation.
|
|
452
|
+
return Promise.resolve();
|
|
453
|
+
}
|
|
454
|
+
const key = `${meshName}\0${String(spotId)}`;
|
|
455
|
+
const objectGeneration = activation.domain.objectGeneration;
|
|
456
|
+
if (this.pendingInstanceTerminals.has(key)) {
|
|
457
|
+
this.deferInstanceAuthorityRelease(key, objectGeneration);
|
|
458
|
+
return Promise.resolve();
|
|
459
|
+
}
|
|
460
|
+
this.removeDeferredInstanceAuthorityRelease(key, objectGeneration);
|
|
461
|
+
return this.releaseInstanceAuthority(meshName, spotId, objectGeneration);
|
|
462
|
+
},
|
|
463
|
+
metrics: options.metrics
|
|
464
|
+
});
|
|
465
|
+
this.scheduleIdleSweep();
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
entrySpotIdForMesh(meshName: string): string | undefined {
|
|
469
|
+
return this.options.entrySpotIdProvider?.(meshName);
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
relocationActivations(meshName: string): readonly ZLinkSpotActivation[] {
|
|
473
|
+
return this.activations.activeActivations().filter(activation =>
|
|
474
|
+
activation.meshName === meshName
|
|
475
|
+
&& this.activations.resolve(meshName, activation.spotId) === activation);
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
activeSpotCount(meshName: string): number {
|
|
479
|
+
return this.activations.list(meshName).length;
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
instanceActivationConcurrency(meshName: string): { readonly active: number; readonly limit: number } {
|
|
483
|
+
const limit = this.options.activationConcurrencyLimitProvider?.(meshName) ?? 128;
|
|
484
|
+
return { active: this.instanceActivationGates.get(meshName)?.active ?? 0, limit };
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
resolveRelocationActivation(
|
|
488
|
+
meshName: string,
|
|
489
|
+
spotId: RoutingId
|
|
490
|
+
): ZLinkSpotActivation | undefined {
|
|
491
|
+
return this.activations.resolve(meshName, spotId);
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
async prepareRelocationSpot(
|
|
495
|
+
meshName: string,
|
|
496
|
+
objectKind: 'user_spot' | 'instance_spot',
|
|
497
|
+
stableType: string,
|
|
498
|
+
implementation: Type<ZLinkSpot | ZLinkInstanceSpot>,
|
|
499
|
+
spotId: RoutingId,
|
|
500
|
+
objectGeneration: bigint,
|
|
501
|
+
authorityOwnerGeneration: bigint,
|
|
502
|
+
signal?: AbortSignal
|
|
503
|
+
): Promise<ZLinkSpotActivation> {
|
|
504
|
+
this.activations.stage(meshName, spotId);
|
|
505
|
+
try {
|
|
506
|
+
return await this.activationLifecycle.materializeRelocation(
|
|
507
|
+
meshName,
|
|
508
|
+
objectKind,
|
|
509
|
+
stableType,
|
|
510
|
+
implementation,
|
|
511
|
+
spotId,
|
|
512
|
+
objectGeneration,
|
|
513
|
+
authorityOwnerGeneration,
|
|
514
|
+
signal
|
|
515
|
+
);
|
|
516
|
+
} catch (error) {
|
|
517
|
+
this.activations.abandonStage(meshName, spotId);
|
|
518
|
+
throw error;
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
async publishRelocationSpot(
|
|
523
|
+
activation: ZLinkSpotActivation,
|
|
524
|
+
beforeAdmission?: () => Promise<void>
|
|
525
|
+
): Promise<void> {
|
|
526
|
+
await activation.serial.execute(() => activation.spot.onInitialize?.());
|
|
527
|
+
await beforeAdmission?.();
|
|
528
|
+
this.activations.publish(activation.meshName, activation.spotId);
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
async abortRelocationSpot(activation: ZLinkSpotActivation): Promise<void> {
|
|
532
|
+
this.activations.detachRelocated(activation.meshName, activation.spotId);
|
|
533
|
+
await activation.timers.dispose();
|
|
534
|
+
await activation.nativeSpot?.dispose();
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
async completeRelocationSource(
|
|
538
|
+
activation: ZLinkSpotActivation
|
|
539
|
+
): Promise<void> {
|
|
540
|
+
this.activations.detachRelocated(activation.meshName, activation.spotId);
|
|
541
|
+
await activation.nativeSpot?.dispose();
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
async materializeInstance(
|
|
545
|
+
meshName: string,
|
|
546
|
+
instanceType: string,
|
|
547
|
+
spotId: RoutingId,
|
|
548
|
+
objectGeneration: bigint,
|
|
549
|
+
signal?: AbortSignal
|
|
550
|
+
): Promise<void> {
|
|
551
|
+
const existing = this.pendingInstanceMaterializations.get(
|
|
552
|
+
instanceMaterializationKey(meshName, spotId, objectGeneration)
|
|
553
|
+
);
|
|
554
|
+
if (existing !== undefined) {
|
|
555
|
+
await awaitWithAbort(existing, signal);
|
|
556
|
+
return;
|
|
557
|
+
}
|
|
558
|
+
const release = await this.acquireInstanceActivation(meshName, signal);
|
|
559
|
+
try {
|
|
560
|
+
await this.materializeInstanceCore(meshName, instanceType, spotId, objectGeneration, signal);
|
|
561
|
+
} finally {
|
|
562
|
+
release();
|
|
563
|
+
}
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
private async materializeInstanceCore(
|
|
567
|
+
meshName: string,
|
|
568
|
+
instanceType: string,
|
|
569
|
+
spotId: RoutingId,
|
|
570
|
+
objectGeneration: bigint,
|
|
571
|
+
signal?: AbortSignal
|
|
572
|
+
): Promise<void> {
|
|
573
|
+
const factory = this.requireInstanceFactory(meshName, instanceType);
|
|
574
|
+
const key = `${meshName}\0${String(spotId)}`;
|
|
575
|
+
const materializationKey = instanceMaterializationKey(meshName, spotId, objectGeneration);
|
|
576
|
+
const materializationPrefix = instanceMaterializationPrefix(meshName, spotId);
|
|
577
|
+
for (;;) {
|
|
578
|
+
// A close seals admission before cleanup removes the activation. An
|
|
579
|
+
// explicit Instance intent arriving at that boundary must wait for the
|
|
580
|
+
// old resources to be released before materializing the replacement.
|
|
581
|
+
// This is lifecycle convergence; it does not resubmit application work.
|
|
582
|
+
const pendingClose = this.pendingInstanceCloses.get(key);
|
|
583
|
+
if (pendingClose !== undefined) {
|
|
584
|
+
await awaitWithAbort(pendingClose, signal);
|
|
585
|
+
continue;
|
|
586
|
+
}
|
|
587
|
+
const closing = this.activations.closingOperation(meshName, spotId);
|
|
588
|
+
if (closing !== undefined) {
|
|
589
|
+
await awaitWithAbort(closing.ready, signal);
|
|
590
|
+
continue;
|
|
591
|
+
}
|
|
592
|
+
|
|
593
|
+
const current = this.activations.resolve(meshName, spotId);
|
|
594
|
+
if (current !== undefined) {
|
|
595
|
+
if (current.spotType !== factory) {
|
|
596
|
+
throw new ZLinkConfigurationException(
|
|
597
|
+
`Instance Spot '${String(spotId)}' is assigned to another type.`
|
|
598
|
+
);
|
|
599
|
+
}
|
|
600
|
+
if (current.objectGeneration === objectGeneration) return;
|
|
601
|
+
if (
|
|
602
|
+
current.objectGeneration === undefined
|
|
603
|
+
|| current.objectGeneration > objectGeneration
|
|
604
|
+
) {
|
|
605
|
+
throw createInternalFrameworkException(
|
|
606
|
+
ZLinkFrameworkInternalErrorKind.SpotGenerationStale,
|
|
607
|
+
`Instance Spot '${String(spotId)}' has a newer application generation.`
|
|
608
|
+
);
|
|
609
|
+
}
|
|
610
|
+
// A newer authority route may become visible while the previous
|
|
611
|
+
// application factory is still completing. Dispose that older
|
|
612
|
+
// activation before publishing the requested generation. The
|
|
613
|
+
// generation-aware release callback prevents this cleanup from
|
|
614
|
+
// releasing the newer authority row.
|
|
615
|
+
await this.discardInstance(meshName, spotId);
|
|
616
|
+
continue;
|
|
617
|
+
}
|
|
618
|
+
|
|
619
|
+
const lifecycleActivation = this.activations.activeActivations().find((activation) =>
|
|
620
|
+
activation.meshName === meshName && String(activation.spotId) === String(spotId)
|
|
621
|
+
);
|
|
622
|
+
if (lifecycleActivation?.isIdleEvicting === true) {
|
|
623
|
+
throw createInternalFrameworkException(
|
|
624
|
+
ZLinkFrameworkInternalErrorKind.SpotGenerationStale,
|
|
625
|
+
`Instance Spot '${String(spotId)}' is entering idle eviction.`
|
|
626
|
+
);
|
|
627
|
+
}
|
|
628
|
+
|
|
629
|
+
let pending = this.pendingInstanceMaterializations.get(materializationKey);
|
|
630
|
+
if (pending === undefined) {
|
|
631
|
+
const siblings = this.pendingInstanceMaterializationsByPrefix.get(materializationPrefix);
|
|
632
|
+
const otherPending = siblings === undefined
|
|
633
|
+
? undefined
|
|
634
|
+
: siblings.values().next().value;
|
|
635
|
+
if (otherPending !== undefined) {
|
|
636
|
+
await awaitWithAbort(otherPending, signal);
|
|
637
|
+
continue;
|
|
638
|
+
}
|
|
639
|
+
}
|
|
640
|
+
if (pending === undefined) {
|
|
641
|
+
const metric = this.options.metrics?.startInstanceSpotActivation(meshName, instanceType);
|
|
642
|
+
pending = this.activationLifecycle.materializeInstance(
|
|
643
|
+
meshName,
|
|
644
|
+
instanceType,
|
|
645
|
+
factory,
|
|
646
|
+
spotId,
|
|
647
|
+
objectGeneration,
|
|
648
|
+
signal
|
|
649
|
+
).then(
|
|
650
|
+
activation => {
|
|
651
|
+
metric?.complete('ready');
|
|
652
|
+
return activation;
|
|
653
|
+
},
|
|
654
|
+
error => {
|
|
655
|
+
metric?.complete(instanceActivationOutcome(error));
|
|
656
|
+
throw error;
|
|
657
|
+
}
|
|
658
|
+
);
|
|
659
|
+
this.pendingInstanceMaterializations.set(materializationKey, pending);
|
|
660
|
+
let siblings = this.pendingInstanceMaterializationsByPrefix.get(materializationPrefix);
|
|
661
|
+
if (siblings === undefined) {
|
|
662
|
+
siblings = new Map();
|
|
663
|
+
this.pendingInstanceMaterializationsByPrefix.set(materializationPrefix, siblings);
|
|
664
|
+
}
|
|
665
|
+
siblings.set(materializationKey, pending);
|
|
666
|
+
void pending.finally(() => {
|
|
667
|
+
if (this.pendingInstanceMaterializations.get(materializationKey) === pending) {
|
|
668
|
+
this.pendingInstanceMaterializations.delete(materializationKey);
|
|
669
|
+
}
|
|
670
|
+
const bucket = this.pendingInstanceMaterializationsByPrefix.get(materializationPrefix);
|
|
671
|
+
if (bucket !== undefined && bucket.get(materializationKey) === pending) {
|
|
672
|
+
bucket.delete(materializationKey);
|
|
673
|
+
if (bucket.size === 0) {
|
|
674
|
+
this.pendingInstanceMaterializationsByPrefix.delete(materializationPrefix);
|
|
675
|
+
}
|
|
676
|
+
}
|
|
677
|
+
}).catch(() => undefined);
|
|
678
|
+
}
|
|
679
|
+
await pending;
|
|
680
|
+
return;
|
|
681
|
+
}
|
|
682
|
+
}
|
|
683
|
+
|
|
684
|
+
private async acquireInstanceActivation(
|
|
685
|
+
meshName: string,
|
|
686
|
+
signal?: AbortSignal
|
|
687
|
+
): Promise<() => void> {
|
|
688
|
+
let gate = this.instanceActivationGates.get(meshName);
|
|
689
|
+
if (gate === undefined) {
|
|
690
|
+
gate = {
|
|
691
|
+
meshName,
|
|
692
|
+
limit: this.options.activationConcurrencyLimitProvider?.(meshName) ?? 128,
|
|
693
|
+
active: 0,
|
|
694
|
+
waiters: [],
|
|
695
|
+
waiterHead: 0
|
|
696
|
+
};
|
|
697
|
+
this.instanceActivationGates.set(meshName, gate);
|
|
698
|
+
}
|
|
699
|
+
if (signal?.aborted === true) throw signal.reason;
|
|
700
|
+
if (gate.active < gate.limit) {
|
|
701
|
+
gate.active += 1;
|
|
702
|
+
this.options.onInstanceActivationConcurrencyChanged?.(meshName);
|
|
703
|
+
return () => this.releaseInstanceActivation(gate!);
|
|
704
|
+
}
|
|
705
|
+
return new Promise<() => void>((resolve, reject) => {
|
|
706
|
+
const waiter = { resolve, reject, signal, abort: undefined as (() => void) | undefined };
|
|
707
|
+
const slot = gate!.waiters.length;
|
|
708
|
+
waiter.abort = () => {
|
|
709
|
+
if (gate!.waiters[slot] === waiter) gate!.waiters[slot] = undefined;
|
|
710
|
+
reject(signal?.reason);
|
|
711
|
+
};
|
|
712
|
+
signal?.addEventListener('abort', waiter.abort, { once: true });
|
|
713
|
+
gate!.waiters.push(waiter);
|
|
714
|
+
});
|
|
715
|
+
}
|
|
716
|
+
|
|
717
|
+
private releaseInstanceActivation(gate: {
|
|
718
|
+
readonly meshName: string;
|
|
719
|
+
readonly limit: number;
|
|
720
|
+
active: number;
|
|
721
|
+
readonly waiters: Array<{
|
|
722
|
+
resolve: (release: () => void) => void;
|
|
723
|
+
reject: (error: unknown) => void;
|
|
724
|
+
signal?: AbortSignal;
|
|
725
|
+
abort?: () => void;
|
|
726
|
+
} | undefined>;
|
|
727
|
+
waiterHead: number;
|
|
728
|
+
}): void {
|
|
729
|
+
while (gate.waiterHead < gate.waiters.length) {
|
|
730
|
+
const waiter = gate.waiters[gate.waiterHead];
|
|
731
|
+
gate.waiters[gate.waiterHead] = undefined;
|
|
732
|
+
gate.waiterHead += 1;
|
|
733
|
+
if (gate.waiterHead >= gate.waiters.length) {
|
|
734
|
+
gate.waiters.length = 0;
|
|
735
|
+
gate.waiterHead = 0;
|
|
736
|
+
}
|
|
737
|
+
if (waiter === undefined) continue;
|
|
738
|
+
if (waiter.abort !== undefined) waiter.signal?.removeEventListener('abort', waiter.abort);
|
|
739
|
+
waiter.resolve(() => this.releaseInstanceActivation(gate));
|
|
740
|
+
return;
|
|
741
|
+
}
|
|
742
|
+
gate.waiters.length = 0;
|
|
743
|
+
gate.waiterHead = 0;
|
|
744
|
+
gate.active -= 1;
|
|
745
|
+
this.options.onInstanceActivationConcurrencyChanged?.(gate.meshName);
|
|
746
|
+
}
|
|
747
|
+
|
|
748
|
+
isInstanceMaterialized(
|
|
749
|
+
meshName: string,
|
|
750
|
+
instanceType: string,
|
|
751
|
+
spotId: RoutingId
|
|
752
|
+
): boolean {
|
|
753
|
+
const activation = this.activations.resolve(meshName, spotId);
|
|
754
|
+
return activation !== undefined
|
|
755
|
+
&& activation.spotType === this.requireInstanceFactory(meshName, instanceType);
|
|
756
|
+
}
|
|
757
|
+
|
|
758
|
+
isInstanceMaterializing(meshName: string, spotId: RoutingId): boolean {
|
|
759
|
+
const prefix = instanceMaterializationPrefix(meshName, spotId);
|
|
760
|
+
return (this.pendingInstanceMaterializationsByPrefix.get(prefix)?.size ?? 0) > 0;
|
|
761
|
+
}
|
|
762
|
+
|
|
763
|
+
isInstanceClosing(meshName: string, spotId: RoutingId): boolean {
|
|
764
|
+
const key = `${meshName}\0${String(spotId)}`;
|
|
765
|
+
return this.pendingInstanceCloses.has(key)
|
|
766
|
+
|| this.activations.closingOperation(meshName, spotId) !== undefined;
|
|
767
|
+
}
|
|
768
|
+
|
|
769
|
+
async discardInstance(meshName: string, spotId: RoutingId): Promise<void> {
|
|
770
|
+
const activation = this.activations.resolve(meshName, spotId);
|
|
771
|
+
if (activation === undefined) return;
|
|
772
|
+
activation.requestClose();
|
|
773
|
+
const operation = this.activations.startClose(
|
|
774
|
+
meshName,
|
|
775
|
+
spotId,
|
|
776
|
+
(current) => this.activationLifecycle.discardInstance(current),
|
|
777
|
+
() => true
|
|
778
|
+
);
|
|
779
|
+
await operation?.ready;
|
|
780
|
+
}
|
|
781
|
+
|
|
782
|
+
isInstanceSpotIdleEvicting(meshName: string, spotId: RoutingId): boolean {
|
|
783
|
+
const activation = this.activations.activeActivations().find((candidate) =>
|
|
784
|
+
candidate.meshName === meshName && String(candidate.spotId) === String(spotId)
|
|
785
|
+
);
|
|
786
|
+
return activation !== undefined
|
|
787
|
+
&& activation.domain.kind === 'instance'
|
|
788
|
+
&& activation.isIdleEvicting;
|
|
789
|
+
}
|
|
790
|
+
|
|
791
|
+
beginInstanceSpotIdleEviction(meshName: string, spotId: RoutingId): boolean {
|
|
792
|
+
const activation = this.activations.activeActivations().find((candidate) =>
|
|
793
|
+
candidate.meshName === meshName && String(candidate.spotId) === String(spotId)
|
|
794
|
+
);
|
|
795
|
+
if (
|
|
796
|
+
activation === undefined
|
|
797
|
+
|| activation.domain.kind !== 'instance'
|
|
798
|
+
|| !activation.isIdleFor(
|
|
799
|
+
performance.now(),
|
|
800
|
+
this.options.instanceSpotIdleTimeoutMs?.get(meshName) ?? 0
|
|
801
|
+
)
|
|
802
|
+
) {
|
|
803
|
+
return false;
|
|
804
|
+
}
|
|
805
|
+
return activation.beginIdleEviction();
|
|
806
|
+
}
|
|
807
|
+
|
|
808
|
+
async completeInstanceTerminal(
|
|
809
|
+
meshName: string,
|
|
810
|
+
spotId: RoutingId,
|
|
811
|
+
objectGeneration: bigint
|
|
812
|
+
): Promise<boolean> {
|
|
813
|
+
const key = `${meshName}\0${String(spotId)}`;
|
|
814
|
+
const pending = this.pendingInstanceTerminals.get(key);
|
|
815
|
+
if (pending === undefined) return false;
|
|
816
|
+
this.removePendingInstanceTerminalGeneration(key, objectGeneration);
|
|
817
|
+
if (pending > 1) {
|
|
818
|
+
this.pendingInstanceTerminals.set(key, pending - 1);
|
|
819
|
+
return false;
|
|
820
|
+
}
|
|
821
|
+
this.pendingInstanceTerminals.delete(key);
|
|
822
|
+
this.pendingInstanceTerminalGenerations.delete(key);
|
|
823
|
+
const pendingClose = this.pendingInstanceCloses.get(key);
|
|
824
|
+
if (pendingClose !== undefined) {
|
|
825
|
+
this.deferInstanceAuthorityRelease(key, objectGeneration);
|
|
826
|
+
await pendingClose;
|
|
827
|
+
return true;
|
|
828
|
+
}
|
|
829
|
+
const deferredRelease = this.deferredInstanceAuthorityReleases.get(key)?.has(objectGeneration) === true;
|
|
830
|
+
if (
|
|
831
|
+
!deferredRelease
|
|
832
|
+
&& this.activations.closingOperation(meshName, spotId) === undefined
|
|
833
|
+
) {
|
|
834
|
+
return false;
|
|
835
|
+
}
|
|
836
|
+
const currentApplication = this.options.instanceSpotApplicationTargetProvider?.(meshName, spotId);
|
|
837
|
+
if (
|
|
838
|
+
currentApplication !== undefined
|
|
839
|
+
&& currentApplication.objectGeneration !== objectGeneration
|
|
840
|
+
) {
|
|
841
|
+
this.removeDeferredInstanceAuthorityRelease(key, objectGeneration);
|
|
842
|
+
return false;
|
|
843
|
+
}
|
|
844
|
+
this.removeDeferredInstanceAuthorityRelease(key, objectGeneration);
|
|
845
|
+
await this.releaseInstanceAuthority(meshName, spotId, objectGeneration);
|
|
846
|
+
return true;
|
|
847
|
+
}
|
|
848
|
+
|
|
849
|
+
beginInstanceTerminal(meshName: string, spotId: RoutingId, objectGeneration: bigint): void {
|
|
850
|
+
const key = `${meshName}\0${String(spotId)}`;
|
|
851
|
+
this.pendingInstanceTerminals.set(
|
|
852
|
+
key,
|
|
853
|
+
(this.pendingInstanceTerminals.get(key) ?? 0) + 1
|
|
854
|
+
);
|
|
855
|
+
const generations = this.pendingInstanceTerminalGenerations.get(key) ?? new Map<string, number>();
|
|
856
|
+
const generationKey = objectGeneration.toString();
|
|
857
|
+
generations.set(generationKey, (generations.get(generationKey) ?? 0) + 1);
|
|
858
|
+
this.pendingInstanceTerminalGenerations.set(key, generations);
|
|
859
|
+
}
|
|
860
|
+
|
|
861
|
+
private deferInstanceAuthorityRelease(key: string, objectGeneration: bigint): void {
|
|
862
|
+
const generations = this.deferredInstanceAuthorityReleases.get(key) ?? new Set<bigint>();
|
|
863
|
+
generations.add(objectGeneration);
|
|
864
|
+
this.deferredInstanceAuthorityReleases.set(key, generations);
|
|
865
|
+
}
|
|
866
|
+
|
|
867
|
+
private removeDeferredInstanceAuthorityRelease(key: string, objectGeneration: bigint): void {
|
|
868
|
+
const generations = this.deferredInstanceAuthorityReleases.get(key);
|
|
869
|
+
if (generations === undefined) return;
|
|
870
|
+
generations.delete(objectGeneration);
|
|
871
|
+
if (generations.size === 0) this.deferredInstanceAuthorityReleases.delete(key);
|
|
872
|
+
}
|
|
873
|
+
|
|
874
|
+
private removePendingInstanceTerminalGeneration(key: string, objectGeneration: bigint): void {
|
|
875
|
+
const generations = this.pendingInstanceTerminalGenerations.get(key);
|
|
876
|
+
if (generations === undefined) return;
|
|
877
|
+
const generationKey = objectGeneration.toString();
|
|
878
|
+
const pending = generations.get(generationKey);
|
|
879
|
+
if (pending === undefined || pending <= 1) generations.delete(generationKey);
|
|
880
|
+
else generations.set(generationKey, pending - 1);
|
|
881
|
+
}
|
|
882
|
+
|
|
883
|
+
private releaseInstanceAuthority(
|
|
884
|
+
meshName: string,
|
|
885
|
+
spotId: RoutingId,
|
|
886
|
+
objectGeneration: bigint
|
|
887
|
+
): Promise<void> {
|
|
888
|
+
return this.options.releaseInstanceAuthority?.(meshName, spotId, objectGeneration)
|
|
889
|
+
?? Promise.resolve();
|
|
890
|
+
}
|
|
891
|
+
|
|
892
|
+
private requireInstanceFactory(
|
|
893
|
+
meshName: string,
|
|
894
|
+
instanceType: string
|
|
895
|
+
): Type<ZLinkInstanceSpot> {
|
|
896
|
+
const factory = this.options.instanceSpotFactories?.get(meshName)?.get(instanceType);
|
|
897
|
+
if (factory === undefined) {
|
|
898
|
+
throw new ZLinkConfigurationException(
|
|
899
|
+
`Instance Spot factory '${instanceType}' is not registered on RouteMesh '${meshName}'.`
|
|
900
|
+
);
|
|
901
|
+
}
|
|
902
|
+
return factory;
|
|
903
|
+
}
|
|
904
|
+
|
|
905
|
+
private scheduleIdleSweep(): void {
|
|
906
|
+
if (this.idleSweepTimer !== undefined) return;
|
|
907
|
+
if (!this.hasIdleSweepTarget()) return;
|
|
908
|
+
const delays = [...(this.options.instanceSpotIdleTimeoutMs?.values() ?? [])]
|
|
909
|
+
.filter((value) => value > 0);
|
|
910
|
+
if (delays.length === 0) return;
|
|
911
|
+
const delay = Math.max(1, Math.min(...delays));
|
|
912
|
+
const timer = setTimeout(() => {
|
|
913
|
+
this.idleSweepTimer = undefined;
|
|
914
|
+
void this.runIdleSweep();
|
|
915
|
+
}, delay);
|
|
916
|
+
timer.unref();
|
|
917
|
+
this.idleSweepTimer = timer;
|
|
918
|
+
}
|
|
919
|
+
|
|
920
|
+
private hasIdleSweepTarget(): boolean {
|
|
921
|
+
return this.activations.hasActiveActivations();
|
|
922
|
+
}
|
|
923
|
+
|
|
924
|
+
private async runIdleSweep(): Promise<void> {
|
|
925
|
+
if (this.idleSweepRunning) return;
|
|
926
|
+
this.idleSweepRunning = true;
|
|
927
|
+
try {
|
|
928
|
+
const now = performance.now();
|
|
929
|
+
for (const activation of this.activations.nextActiveActivationBatch()) {
|
|
930
|
+
const timeoutMs = this.options.instanceSpotIdleTimeoutMs?.get(activation.meshName) ?? 0;
|
|
931
|
+
if (
|
|
932
|
+
timeoutMs <= 0
|
|
933
|
+
|| activation.domain.kind !== 'instance'
|
|
934
|
+
|| !activation.isIdleFor(now, timeoutMs)
|
|
935
|
+
|| !activation.beginIdleEviction()
|
|
936
|
+
) {
|
|
937
|
+
continue;
|
|
938
|
+
}
|
|
939
|
+
let durableClosing: { restoreReady(): Promise<void> } | undefined;
|
|
940
|
+
try {
|
|
941
|
+
durableClosing = await (
|
|
942
|
+
this.options.beginInstanceIdleClosingAuthority?.(
|
|
943
|
+
activation.meshName,
|
|
944
|
+
activation.spotId
|
|
945
|
+
) ?? Promise.resolve({ restoreReady: async () => undefined })
|
|
946
|
+
);
|
|
947
|
+
} catch (error) {
|
|
948
|
+
activation.abortIdleEviction();
|
|
949
|
+
throw error;
|
|
950
|
+
}
|
|
951
|
+
if (durableClosing === undefined) {
|
|
952
|
+
activation.abortIdleEviction();
|
|
953
|
+
continue;
|
|
954
|
+
}
|
|
955
|
+
const close = this.closeWithReason(
|
|
956
|
+
activation.meshName,
|
|
957
|
+
activation.spotId,
|
|
958
|
+
undefined,
|
|
959
|
+
ZLinkSpotCloseReason.IdleEvicted
|
|
960
|
+
);
|
|
961
|
+
const run = async () => {
|
|
962
|
+
try {
|
|
963
|
+
const closed = await close;
|
|
964
|
+
if (!closed) {
|
|
965
|
+
await durableClosing.restoreReady();
|
|
966
|
+
activation.abortIdleEviction();
|
|
967
|
+
}
|
|
968
|
+
} catch (error) {
|
|
969
|
+
if (error instanceof ZLinkSpotCloseOccupiedError) {
|
|
970
|
+
await durableClosing.restoreReady();
|
|
971
|
+
}
|
|
972
|
+
activation.abortIdleEviction();
|
|
973
|
+
throw error;
|
|
974
|
+
}
|
|
975
|
+
};
|
|
976
|
+
this.options.detachedTaskRunner?.runDetached(
|
|
977
|
+
`instance idle eviction ${String(activation.spotId)}`,
|
|
978
|
+
run
|
|
979
|
+
);
|
|
980
|
+
if (this.options.detachedTaskRunner === undefined) {
|
|
981
|
+
void run().catch(() => undefined);
|
|
982
|
+
}
|
|
983
|
+
}
|
|
984
|
+
} finally {
|
|
985
|
+
this.idleSweepRunning = false;
|
|
986
|
+
this.scheduleIdleSweep();
|
|
987
|
+
}
|
|
988
|
+
}
|
|
989
|
+
|
|
990
|
+
async create<TSpot extends ZLinkSpot>(
|
|
991
|
+
meshName: string,
|
|
992
|
+
spotType: Type<TSpot>,
|
|
993
|
+
signal?: AbortSignal
|
|
994
|
+
): Promise<ZLinkLocalSpotCreateResult>;
|
|
995
|
+
async create<TSpot extends ZLinkSpot>(
|
|
996
|
+
meshName: string,
|
|
997
|
+
spotType: Type<TSpot>,
|
|
998
|
+
request: ZLinkMessage,
|
|
999
|
+
signal?: AbortSignal
|
|
1000
|
+
): Promise<ZLinkLocalSpotCreateResult>;
|
|
1001
|
+
async create<TSpot extends ZLinkSpot, TRequest>(
|
|
1002
|
+
meshName: string,
|
|
1003
|
+
spotType: Type<TSpot>,
|
|
1004
|
+
request: TRequest,
|
|
1005
|
+
signal?: AbortSignal
|
|
1006
|
+
): Promise<ZLinkLocalSpotCreateResult>;
|
|
1007
|
+
async create<TSpot extends ZLinkSpot, TRequest>(
|
|
1008
|
+
meshName: string,
|
|
1009
|
+
spotType: Type<TSpot>,
|
|
1010
|
+
requestOrSignal?: ZLinkMessage | TRequest | AbortSignal,
|
|
1011
|
+
signal?: AbortSignal
|
|
1012
|
+
): Promise<ZLinkLocalSpotCreateResult> {
|
|
1013
|
+
requireMeshName(meshName);
|
|
1014
|
+
const args = normalizeSpotCreateArgs(requestOrSignal, signal);
|
|
1015
|
+
this.options.admission?.requireRequest('SPOT create', meshName);
|
|
1016
|
+
const spotId = this.activations.allocateSpotId(meshName);
|
|
1017
|
+
const ownedRequest = args.request === undefined
|
|
1018
|
+
? RuntimeMessage.from(Buffer.alloc(0))
|
|
1019
|
+
: encodeFrameworkPayloadMessage(args.request, this.options.messageSerializers);
|
|
1020
|
+
try {
|
|
1021
|
+
return await this.createActivation(meshName, spotType, spotId, ownedRequest, args.signal);
|
|
1022
|
+
} finally {
|
|
1023
|
+
ownedRequest.close();
|
|
1024
|
+
}
|
|
1025
|
+
}
|
|
1026
|
+
|
|
1027
|
+
async getOrCreate<TSpot extends ZLinkSpot>(
|
|
1028
|
+
meshName: string,
|
|
1029
|
+
spotType: Type<TSpot>,
|
|
1030
|
+
spotId: RoutingId,
|
|
1031
|
+
signal?: AbortSignal
|
|
1032
|
+
): Promise<ZLinkLocalSpotCreateResult>;
|
|
1033
|
+
async getOrCreate<TSpot extends ZLinkSpot>(
|
|
1034
|
+
meshName: string,
|
|
1035
|
+
spotType: Type<TSpot>,
|
|
1036
|
+
spotId: RoutingId,
|
|
1037
|
+
request: ZLinkMessage,
|
|
1038
|
+
signal?: AbortSignal
|
|
1039
|
+
): Promise<ZLinkLocalSpotCreateResult>;
|
|
1040
|
+
async getOrCreate<TSpot extends ZLinkSpot, TRequest>(
|
|
1041
|
+
meshName: string,
|
|
1042
|
+
spotType: Type<TSpot>,
|
|
1043
|
+
spotId: RoutingId,
|
|
1044
|
+
request: TRequest,
|
|
1045
|
+
signal?: AbortSignal
|
|
1046
|
+
): Promise<ZLinkLocalSpotCreateResult>;
|
|
1047
|
+
async getOrCreate<TSpot extends ZLinkSpot, TRequest>(
|
|
1048
|
+
meshName: string,
|
|
1049
|
+
spotType: Type<TSpot>,
|
|
1050
|
+
spotId: RoutingId,
|
|
1051
|
+
requestOrSignal?: ZLinkMessage | TRequest | AbortSignal,
|
|
1052
|
+
signal?: AbortSignal
|
|
1053
|
+
): Promise<ZLinkLocalSpotCreateResult> {
|
|
1054
|
+
return await this.getOrCreateWithAuthority(
|
|
1055
|
+
meshName,
|
|
1056
|
+
spotType,
|
|
1057
|
+
spotId,
|
|
1058
|
+
requestOrSignal,
|
|
1059
|
+
undefined,
|
|
1060
|
+
signal
|
|
1061
|
+
);
|
|
1062
|
+
}
|
|
1063
|
+
|
|
1064
|
+
async getOrCreateWithAuthority<TSpot extends ZLinkSpot, TRequest>(
|
|
1065
|
+
meshName: string,
|
|
1066
|
+
spotType: Type<TSpot>,
|
|
1067
|
+
spotId: RoutingId,
|
|
1068
|
+
requestOrSignal: ZLinkMessage | TRequest | AbortSignal | undefined,
|
|
1069
|
+
authority: ZLinkNativeSpotAuthority | undefined,
|
|
1070
|
+
signal?: AbortSignal
|
|
1071
|
+
): Promise<ZLinkLocalSpotCreateResult> {
|
|
1072
|
+
requireMeshName(meshName);
|
|
1073
|
+
const args = normalizeSpotCreateArgs(requestOrSignal, signal);
|
|
1074
|
+
throwIfAborted(args.signal);
|
|
1075
|
+
const operation = this.activations.getOrBegin(meshName, spotType, spotId, async () => {
|
|
1076
|
+
this.options.admission?.requireRequest('SPOT create', meshName);
|
|
1077
|
+
const ownedRequest = args.request === undefined
|
|
1078
|
+
? RuntimeMessage.from(Buffer.alloc(0))
|
|
1079
|
+
: encodeFrameworkPayloadMessage(args.request, this.options.messageSerializers);
|
|
1080
|
+
try {
|
|
1081
|
+
return await this.createActivation(
|
|
1082
|
+
meshName,
|
|
1083
|
+
spotType,
|
|
1084
|
+
spotId,
|
|
1085
|
+
ownedRequest,
|
|
1086
|
+
undefined,
|
|
1087
|
+
authority
|
|
1088
|
+
);
|
|
1089
|
+
} finally {
|
|
1090
|
+
ownedRequest.close();
|
|
1091
|
+
}
|
|
1092
|
+
});
|
|
1093
|
+
return await awaitWithAbort(operation.ready, args.signal);
|
|
1094
|
+
}
|
|
1095
|
+
|
|
1096
|
+
async find(meshName: string, spotId: RoutingId): Promise<ZLinkSpotInfo | null> {
|
|
1097
|
+
requireMeshName(meshName);
|
|
1098
|
+
return this.activations.has(meshName, spotId) ? { spotId } : null;
|
|
1099
|
+
}
|
|
1100
|
+
|
|
1101
|
+
async list(meshName: string): Promise<readonly ZLinkSpotInfo[]> {
|
|
1102
|
+
requireMeshName(meshName);
|
|
1103
|
+
return this.activations.list(meshName);
|
|
1104
|
+
}
|
|
1105
|
+
|
|
1106
|
+
async drainForShutdown(meshName: string, signal?: AbortSignal, deadline?: Date): Promise<void> {
|
|
1107
|
+
const results = await Promise.allSettled(this.activations.activeActivations()
|
|
1108
|
+
.filter(activation => activation.meshName === meshName)
|
|
1109
|
+
.map(activation => this.closeWithReason(
|
|
1110
|
+
meshName, activation.spotId, signal, ZLinkSpotCloseReason.HostShutdown, deadline
|
|
1111
|
+
)));
|
|
1112
|
+
const errors = results
|
|
1113
|
+
.filter((result): result is PromiseRejectedResult => result.status === 'rejected')
|
|
1114
|
+
.map(result => result.reason);
|
|
1115
|
+
if (errors.length === 1) throw errors[0];
|
|
1116
|
+
if (errors.length > 1) throw new AggregateError(errors, 'Spot shutdown cleanup failed.');
|
|
1117
|
+
}
|
|
1118
|
+
|
|
1119
|
+
async close(meshName: string, spotId: RoutingId, signal?: AbortSignal): Promise<boolean> {
|
|
1120
|
+
return await this.closeWithReason(
|
|
1121
|
+
meshName,
|
|
1122
|
+
spotId,
|
|
1123
|
+
signal,
|
|
1124
|
+
ZLinkSpotCloseReason.ExplicitClose
|
|
1125
|
+
);
|
|
1126
|
+
}
|
|
1127
|
+
|
|
1128
|
+
private async closeWithReason(
|
|
1129
|
+
meshName: string,
|
|
1130
|
+
spotId: RoutingId,
|
|
1131
|
+
signal?: AbortSignal,
|
|
1132
|
+
reason = ZLinkSpotCloseReason.ExplicitClose,
|
|
1133
|
+
deadline?: Date
|
|
1134
|
+
): Promise<boolean> {
|
|
1135
|
+
requireMeshName(meshName);
|
|
1136
|
+
const key = `${meshName}\0${String(spotId)}`;
|
|
1137
|
+
const closing = this.activations.closingOperation(meshName, spotId);
|
|
1138
|
+
if (closing !== undefined) {
|
|
1139
|
+
return await closing.ready;
|
|
1140
|
+
}
|
|
1141
|
+
const pendingClose = this.pendingInstanceCloses.get(key);
|
|
1142
|
+
if (pendingClose !== undefined) {
|
|
1143
|
+
const pendingActivation = this.activations.resolve(meshName, spotId);
|
|
1144
|
+
if (pendingActivation?.serial.isCurrentTurn === true) return true;
|
|
1145
|
+
return await pendingClose;
|
|
1146
|
+
}
|
|
1147
|
+
const activation = this.activations.resolve(meshName, spotId);
|
|
1148
|
+
if (activation === undefined) {
|
|
1149
|
+
return false;
|
|
1150
|
+
}
|
|
1151
|
+
const currentTurn = activation.serial.isCurrentTurn;
|
|
1152
|
+
const isInstance = activation.domain.kind === 'instance';
|
|
1153
|
+
const beginClose = () => {
|
|
1154
|
+
const seal = activation.sealExecution();
|
|
1155
|
+
const operation = this.activations.startClose(
|
|
1156
|
+
meshName,
|
|
1157
|
+
spotId,
|
|
1158
|
+
(target) => this.activationLifecycle.closeAfterSeal(target, seal, signal, reason, deadline),
|
|
1159
|
+
(target) => this.activationLifecycle.resourcesReleased(target),
|
|
1160
|
+
reason
|
|
1161
|
+
);
|
|
1162
|
+
if (operation === undefined) {
|
|
1163
|
+
activation.abortExecutionSeal(seal);
|
|
1164
|
+
}
|
|
1165
|
+
return operation;
|
|
1166
|
+
};
|
|
1167
|
+
|
|
1168
|
+
if (isInstance) {
|
|
1169
|
+
const beginAuthorityClose = reason === ZLinkSpotCloseReason.ExplicitClose
|
|
1170
|
+
? this.options.beginInstanceClosingAuthority
|
|
1171
|
+
: undefined;
|
|
1172
|
+
// Register the close gate before waiting for the current application
|
|
1173
|
+
// and activation-authority terminal completions. A close requested from
|
|
1174
|
+
// a handler cannot publish Closing until that handler's durable inbox
|
|
1175
|
+
// completion has removed the recovery fence.
|
|
1176
|
+
const trackedClosePromise = (async () => {
|
|
1177
|
+
const waitForApplication = this.options.instanceSpotApplicationQuiescenceProvider?.(
|
|
1178
|
+
meshName,
|
|
1179
|
+
spotId,
|
|
1180
|
+
signal
|
|
1181
|
+
);
|
|
1182
|
+
if (waitForApplication !== undefined) {
|
|
1183
|
+
await waitForApplication;
|
|
1184
|
+
}
|
|
1185
|
+
const closingAuthority = beginAuthorityClose === undefined
|
|
1186
|
+
? undefined
|
|
1187
|
+
: await beginAuthorityClose(meshName, spotId);
|
|
1188
|
+
if (beginAuthorityClose !== undefined && closingAuthority === undefined) {
|
|
1189
|
+
return false;
|
|
1190
|
+
}
|
|
1191
|
+
const operation = beginClose();
|
|
1192
|
+
if (operation === undefined) {
|
|
1193
|
+
await closingAuthority?.restoreReady();
|
|
1194
|
+
return false;
|
|
1195
|
+
}
|
|
1196
|
+
const closed = await operation.ready;
|
|
1197
|
+
if (!closed) await closingAuthority?.restoreReady();
|
|
1198
|
+
return closed;
|
|
1199
|
+
})().finally(() => {
|
|
1200
|
+
if (this.pendingInstanceCloses.get(key) === trackedClosePromise) {
|
|
1201
|
+
this.pendingInstanceCloses.delete(key);
|
|
1202
|
+
}
|
|
1203
|
+
});
|
|
1204
|
+
this.pendingInstanceCloses.set(key, trackedClosePromise);
|
|
1205
|
+
if (currentTurn) {
|
|
1206
|
+
// The current turn must return before its terminal completion can
|
|
1207
|
+
// release the activation recovery fence and allow the durable close
|
|
1208
|
+
// CAS. The registered close gate prevents a second admission while
|
|
1209
|
+
// that detached close finishes.
|
|
1210
|
+
this.options.detachedTaskRunner?.runDetached(
|
|
1211
|
+
`instance spot close ${String(spotId)}`,
|
|
1212
|
+
async () => { await trackedClosePromise; }
|
|
1213
|
+
);
|
|
1214
|
+
if (this.options.detachedTaskRunner === undefined) {
|
|
1215
|
+
void trackedClosePromise.catch(() => undefined);
|
|
1216
|
+
}
|
|
1217
|
+
return true;
|
|
1218
|
+
}
|
|
1219
|
+
return await trackedClosePromise;
|
|
1220
|
+
}
|
|
1221
|
+
|
|
1222
|
+
const operation = beginClose();
|
|
1223
|
+
if (operation === undefined) {
|
|
1224
|
+
return false;
|
|
1225
|
+
}
|
|
1226
|
+
if (currentTurn) {
|
|
1227
|
+
if (operation.started) {
|
|
1228
|
+
this.options.detachedTaskRunner?.runDetached(
|
|
1229
|
+
`spot close ${String(spotId)}`,
|
|
1230
|
+
async () => { await operation.ready; }
|
|
1231
|
+
);
|
|
1232
|
+
if (this.options.detachedTaskRunner === undefined) {
|
|
1233
|
+
void operation.ready.catch(() => undefined);
|
|
1234
|
+
}
|
|
1235
|
+
}
|
|
1236
|
+
return true;
|
|
1237
|
+
}
|
|
1238
|
+
return await operation.ready;
|
|
1239
|
+
}
|
|
1240
|
+
|
|
1241
|
+
async executeOnSpot<TSpot extends ZLinkSpot, TResult>(
|
|
1242
|
+
spotType: Type<TSpot>,
|
|
1243
|
+
spotId: RoutingId,
|
|
1244
|
+
operation: (spot: TSpot) => Promise<TResult> | TResult,
|
|
1245
|
+
signal?: AbortSignal
|
|
1246
|
+
): Promise<TResult> {
|
|
1247
|
+
throwIfAborted(signal);
|
|
1248
|
+
const activation = this.activations.resolveUnique(spotId);
|
|
1249
|
+
if (activation === undefined) {
|
|
1250
|
+
throw new ZLinkConfigurationException(`Spot '${spotId}' is not active.`);
|
|
1251
|
+
}
|
|
1252
|
+
if (activation.spotType !== spotType) {
|
|
1253
|
+
throw new ZLinkConfigurationException(`Spot '${spotId}' has a different spot type.`);
|
|
1254
|
+
}
|
|
1255
|
+
if (activation.serial.isCurrentTurn) {
|
|
1256
|
+
throw createInternalFrameworkException(
|
|
1257
|
+
ZLinkFrameworkInternalErrorKind.InvalidOperation,
|
|
1258
|
+
`Spot '${String(spotId)}' cannot start a public operation from its current serial turn.`
|
|
1259
|
+
);
|
|
1260
|
+
}
|
|
1261
|
+
return activation.serial.execute(() => operation(activation.spot as TSpot));
|
|
1262
|
+
}
|
|
1263
|
+
|
|
1264
|
+
hasActiveSpot(spotId: RoutingId): boolean {
|
|
1265
|
+
return this.activations.resolveUnique(spotId) !== undefined;
|
|
1266
|
+
}
|
|
1267
|
+
|
|
1268
|
+
canCloseUserSpot(meshName: string, spotId: RoutingId): boolean {
|
|
1269
|
+
return this.activations.canClose(meshName, spotId);
|
|
1270
|
+
}
|
|
1271
|
+
|
|
1272
|
+
beginUserSpotPublication(meshName: string, spotId: RoutingId): void {
|
|
1273
|
+
this.activations.stage(meshName, spotId);
|
|
1274
|
+
}
|
|
1275
|
+
|
|
1276
|
+
publishUserSpot(meshName: string, spotId: RoutingId): void {
|
|
1277
|
+
this.activations.publish(meshName, spotId);
|
|
1278
|
+
}
|
|
1279
|
+
|
|
1280
|
+
abortUserSpotPublication(meshName: string, spotId: RoutingId): void {
|
|
1281
|
+
this.activations.abandonStage(meshName, spotId);
|
|
1282
|
+
}
|
|
1283
|
+
|
|
1284
|
+
resolveLocalSpotRoute(spotId: RoutingId): ZLinkSpotRouteTarget | undefined {
|
|
1285
|
+
const activation = this.activations.resolveUnique(spotId);
|
|
1286
|
+
const generation = activation?.nativeSpot?.lifecycleGeneration;
|
|
1287
|
+
if (activation === undefined || generation === undefined || generation <= 0n) {
|
|
1288
|
+
return undefined;
|
|
1289
|
+
}
|
|
1290
|
+
const nodeRid = this.options.nodeRidProvider?.(activation.meshName) ?? this.options.nodeRid;
|
|
1291
|
+
if (nodeRid === undefined) {
|
|
1292
|
+
return undefined;
|
|
1293
|
+
}
|
|
1294
|
+
return {
|
|
1295
|
+
routerChannelId: this.options.spotRouterChannelIdForMesh?.(activation.meshName) ?? activation.meshName,
|
|
1296
|
+
targetNodeRid: nodeRid,
|
|
1297
|
+
spotId: activation.spotId,
|
|
1298
|
+
spotKind: ZLinkSpotKind.User,
|
|
1299
|
+
targetSpotGeneration: generation
|
|
1300
|
+
};
|
|
1301
|
+
}
|
|
1302
|
+
|
|
1303
|
+
async admitActorJoin(
|
|
1304
|
+
spotId: RoutingId,
|
|
1305
|
+
actor: ZLinkActor,
|
|
1306
|
+
request: Message,
|
|
1307
|
+
commit: (spot: ZLinkSpot) => Promise<ZLinkActorJoinRollback | void> | ZLinkActorJoinRollback | void,
|
|
1308
|
+
signal?: AbortSignal,
|
|
1309
|
+
leaveSource?: () => Promise<void>,
|
|
1310
|
+
contentType = 'application/json'
|
|
1311
|
+
): Promise<ZLinkSpotActorJoinResult> {
|
|
1312
|
+
const meshName = this.activations.resolveUnique(spotId)?.meshName;
|
|
1313
|
+
this.options.admission?.requireRequest('Actor join admission', meshName);
|
|
1314
|
+
return await this.actorMembership.admitActorJoin(
|
|
1315
|
+
spotId,
|
|
1316
|
+
actor,
|
|
1317
|
+
request,
|
|
1318
|
+
commit,
|
|
1319
|
+
signal,
|
|
1320
|
+
leaveSource,
|
|
1321
|
+
contentType
|
|
1322
|
+
);
|
|
1323
|
+
}
|
|
1324
|
+
|
|
1325
|
+
async leaveActor(
|
|
1326
|
+
spotId: RoutingId,
|
|
1327
|
+
actor: ZLinkActor,
|
|
1328
|
+
signal?: AbortSignal
|
|
1329
|
+
): Promise<void> {
|
|
1330
|
+
const meshName = this.activations.resolveUnique(spotId)?.meshName;
|
|
1331
|
+
await this.actorMembership.leaveActor(spotId, actor, signal, meshName);
|
|
1332
|
+
}
|
|
1333
|
+
|
|
1334
|
+
async leaveActorInMesh(
|
|
1335
|
+
meshName: string,
|
|
1336
|
+
spotId: RoutingId,
|
|
1337
|
+
actor: ZLinkActor,
|
|
1338
|
+
signal?: AbortSignal
|
|
1339
|
+
): Promise<void> {
|
|
1340
|
+
requireMeshName(meshName);
|
|
1341
|
+
await this.actorMembership.leaveActor(spotId, actor, signal, meshName);
|
|
1342
|
+
}
|
|
1343
|
+
|
|
1344
|
+
async notifyActorLeftAfterTransfer(
|
|
1345
|
+
spotId: RoutingId,
|
|
1346
|
+
actor: ZLinkActor,
|
|
1347
|
+
signal?: AbortSignal
|
|
1348
|
+
): Promise<void> {
|
|
1349
|
+
await this.actorMembership.notifyActorLeftAfterTransfer(spotId, actor, signal);
|
|
1350
|
+
}
|
|
1351
|
+
|
|
1352
|
+
async prepareActorLeaveForTransfer(
|
|
1353
|
+
spotId: RoutingId,
|
|
1354
|
+
actor: ZLinkActor,
|
|
1355
|
+
signal?: AbortSignal
|
|
1356
|
+
): Promise<void> {
|
|
1357
|
+
await this.actorMembership.prepareActorLeaveForTransfer(spotId, actor, signal);
|
|
1358
|
+
}
|
|
1359
|
+
|
|
1360
|
+
async commitActorLeaveAfterTransfer(spotId: RoutingId, actorId: string): Promise<void> {
|
|
1361
|
+
await this.actorMembership.commitActorLeaveAfterTransfer(spotId, actorId);
|
|
1362
|
+
}
|
|
1363
|
+
|
|
1364
|
+
async restoreActorAfterFailedTransfer(
|
|
1365
|
+
spotId: RoutingId,
|
|
1366
|
+
actor: ZLinkActor,
|
|
1367
|
+
signal?: AbortSignal
|
|
1368
|
+
): Promise<void> {
|
|
1369
|
+
await this.actorMembership.restoreActorAfterFailedTransfer(spotId, actor, signal);
|
|
1370
|
+
}
|
|
1371
|
+
|
|
1372
|
+
async beginActorTransfer(spotId: RoutingId, actorId: string): Promise<void> {
|
|
1373
|
+
await this.actorMembership.beginActorTransfer(spotId, actorId);
|
|
1374
|
+
}
|
|
1375
|
+
|
|
1376
|
+
async cancelActorTransfer(spotId: RoutingId, actorId: string): Promise<void> {
|
|
1377
|
+
await this.actorMembership.cancelActorTransfer(spotId, actorId);
|
|
1378
|
+
}
|
|
1379
|
+
|
|
1380
|
+
async notifyJoinedSpotActorDisconnected(
|
|
1381
|
+
spotId: RoutingId,
|
|
1382
|
+
actor: ZLinkActor,
|
|
1383
|
+
signal?: AbortSignal
|
|
1384
|
+
): Promise<boolean> {
|
|
1385
|
+
return await this.actorMembership.notifyJoinedActorDisconnected(spotId, actor, signal);
|
|
1386
|
+
}
|
|
1387
|
+
|
|
1388
|
+
dispatchRoutedActorPacket(
|
|
1389
|
+
spotId: RoutingId,
|
|
1390
|
+
actorId: string,
|
|
1391
|
+
parts: readonly Message[],
|
|
1392
|
+
returnResponse = false,
|
|
1393
|
+
remoteBoundSessionTarget?: ZLinkRemoteBoundSessionTarget,
|
|
1394
|
+
fallbackActorRef?: ActorRef
|
|
1395
|
+
): Promise<unknown> {
|
|
1396
|
+
const activation = this.activations.resolveUnique(spotId);
|
|
1397
|
+
if (activation === undefined) {
|
|
1398
|
+
throw new ZLinkConfigurationException(`Spot '${spotId}' is not active.`);
|
|
1399
|
+
}
|
|
1400
|
+
return this.dispatchActorPacket(
|
|
1401
|
+
activation,
|
|
1402
|
+
actorId,
|
|
1403
|
+
parts,
|
|
1404
|
+
returnResponse,
|
|
1405
|
+
remoteBoundSessionTarget,
|
|
1406
|
+
fallbackActorRef
|
|
1407
|
+
);
|
|
1408
|
+
}
|
|
1409
|
+
|
|
1410
|
+
/** @internal Replays a record already owned by the Actor handoff queue. */
|
|
1411
|
+
dispatchRoutedActorPacketDirect(
|
|
1412
|
+
spotId: RoutingId,
|
|
1413
|
+
actorId: string,
|
|
1414
|
+
parts: readonly Message[],
|
|
1415
|
+
returnResponse = false,
|
|
1416
|
+
remoteBoundSessionTarget?: ZLinkRemoteBoundSessionTarget,
|
|
1417
|
+
fallbackActorRef?: ActorRef
|
|
1418
|
+
): Promise<unknown> {
|
|
1419
|
+
const activation = this.activations.resolveUnique(spotId);
|
|
1420
|
+
if (activation === undefined) {
|
|
1421
|
+
throw new ZLinkConfigurationException(`Spot '${spotId}' is not active.`);
|
|
1422
|
+
}
|
|
1423
|
+
return this.activationLifecycle.dispatchActorPacketDirect(
|
|
1424
|
+
activation,
|
|
1425
|
+
actorId,
|
|
1426
|
+
parts,
|
|
1427
|
+
returnResponse,
|
|
1428
|
+
remoteBoundSessionTarget,
|
|
1429
|
+
fallbackActorRef
|
|
1430
|
+
);
|
|
1431
|
+
}
|
|
1432
|
+
|
|
1433
|
+
/** @internal Atomically restores one durable packet prefix to an Actor FIFO. */
|
|
1434
|
+
admitRoutedActorPacketPrefix(
|
|
1435
|
+
spotId: RoutingId,
|
|
1436
|
+
actorId: string,
|
|
1437
|
+
records: readonly ZLinkActorHandoffPrefixRecord[]
|
|
1438
|
+
): ZLinkActorHandoffPrefixAdmission {
|
|
1439
|
+
const activation = this.activations.resolveUnique(spotId);
|
|
1440
|
+
if (activation === undefined) {
|
|
1441
|
+
throw new ZLinkConfigurationException(`Spot '${spotId}' is not active.`);
|
|
1442
|
+
}
|
|
1443
|
+
return this.activationLifecycle.admitActorPacketPrefix(
|
|
1444
|
+
activation,
|
|
1445
|
+
actorId,
|
|
1446
|
+
records
|
|
1447
|
+
);
|
|
1448
|
+
}
|
|
1449
|
+
|
|
1450
|
+
async dispatchRoutedSpotSend(
|
|
1451
|
+
spotId: RoutingId,
|
|
1452
|
+
packetName: string | undefined,
|
|
1453
|
+
message: unknown,
|
|
1454
|
+
context: {
|
|
1455
|
+
readonly channelName: string;
|
|
1456
|
+
readonly contentType?: string;
|
|
1457
|
+
readonly workOptions?: import('../execution/serial-execution-queue').ZLinkSerialWorkOptions;
|
|
1458
|
+
readonly admissionTimeoutMs?: number;
|
|
1459
|
+
readonly signal?: AbortSignal;
|
|
1460
|
+
}
|
|
1461
|
+
): Promise<void> {
|
|
1462
|
+
await this.routedSpotPackets.send(spotId, packetName, message, context);
|
|
1463
|
+
}
|
|
1464
|
+
|
|
1465
|
+
async dispatchRoutedSpotRequest<TReply>(
|
|
1466
|
+
spotId: RoutingId,
|
|
1467
|
+
packetName: string | undefined,
|
|
1468
|
+
request: unknown,
|
|
1469
|
+
context: {
|
|
1470
|
+
readonly channelName: string;
|
|
1471
|
+
readonly contentType?: string;
|
|
1472
|
+
readonly workOptions?: import('../execution/serial-execution-queue').ZLinkSerialWorkOptions;
|
|
1473
|
+
readonly admissionTimeoutMs?: number;
|
|
1474
|
+
readonly signal?: AbortSignal;
|
|
1475
|
+
}
|
|
1476
|
+
): Promise<TReply> {
|
|
1477
|
+
return await this.routedSpotPackets.request<TReply>(spotId, packetName, request, context);
|
|
1478
|
+
}
|
|
1479
|
+
|
|
1480
|
+
async dispatchMeshSpot(meshName: string, owner: ReadyRecord, record: ReceiveRecord): Promise<void> {
|
|
1481
|
+
const spotId = owner.spotId as unknown as RoutingId | null;
|
|
1482
|
+
if (spotId === null) {
|
|
1483
|
+
throw new ZLinkConfigurationException('MeshNode Spot record is missing the owner Spot RID.');
|
|
1484
|
+
}
|
|
1485
|
+
if (record.kind === ReceiveKind.SpotMulticast) {
|
|
1486
|
+
const activation = this.activations.resolve(meshName, spotId);
|
|
1487
|
+
if (activation?.actorDispatch === undefined) {
|
|
1488
|
+
throw new ZLinkConfigurationException(
|
|
1489
|
+
`MeshNode Spot multicast target '${String(spotId)}' is not active.`
|
|
1490
|
+
);
|
|
1491
|
+
}
|
|
1492
|
+
if (record.topic === null || record.topic.length === 0) {
|
|
1493
|
+
throw new ZLinkConfigurationException('MeshNode Spot multicast record is missing its topic.');
|
|
1494
|
+
}
|
|
1495
|
+
await activation.actorDispatch.dispatchSubscriptionRecord(
|
|
1496
|
+
record.topic,
|
|
1497
|
+
record.parts,
|
|
1498
|
+
record.sourceNodeRid as unknown as RoutingId | null
|
|
1499
|
+
);
|
|
1500
|
+
return;
|
|
1501
|
+
}
|
|
1502
|
+
const envelope = decodeChannelEnvelope(
|
|
1503
|
+
record.parts,
|
|
1504
|
+
undefined,
|
|
1505
|
+
this.options.dispatchErrors?.flow.flowCreationEnabled() ?? true
|
|
1506
|
+
);
|
|
1507
|
+
const packetName = envelope.packetName;
|
|
1508
|
+
const codecs = this.options.messageSerializers === undefined
|
|
1509
|
+
? undefined
|
|
1510
|
+
: { serializers: this.options.messageSerializers };
|
|
1511
|
+
const decodePayload = () => decodeChannelPayload(envelope, codecs);
|
|
1512
|
+
const context = {
|
|
1513
|
+
channelName: envelope.header.channelName,
|
|
1514
|
+
contentType: envelope.header.contentType,
|
|
1515
|
+
workOptions: zlinkSerialWorkOptions(
|
|
1516
|
+
envelope.payload.byteLength,
|
|
1517
|
+
record.applicationMetadata?.byteLength ?? zlinkMetadataByteLength(envelope.header.metadata)
|
|
1518
|
+
)
|
|
1519
|
+
};
|
|
1520
|
+
if (record.kind === ReceiveKind.SpotSend) {
|
|
1521
|
+
await this.ensureInstanceApplicationActivation(meshName, spotId);
|
|
1522
|
+
await this.routedSpotPackets.sendEncoded(spotId, packetName, decodePayload, context);
|
|
1523
|
+
return;
|
|
1524
|
+
}
|
|
1525
|
+
if (record.kind !== ReceiveKind.SpotRequest) {
|
|
1526
|
+
throw new ZLinkConfigurationException(`Unsupported MeshNode Spot record kind '${record.kind}'.`);
|
|
1527
|
+
}
|
|
1528
|
+
try {
|
|
1529
|
+
await this.ensureInstanceApplicationActivation(meshName, spotId);
|
|
1530
|
+
const response = await this.routedSpotPackets.requestEncoded(
|
|
1531
|
+
spotId,
|
|
1532
|
+
packetName,
|
|
1533
|
+
decodePayload,
|
|
1534
|
+
context
|
|
1535
|
+
);
|
|
1536
|
+
requireMeshSpotReply(record.reply(encodeChannelReplyParts(envelope.header, response, codecs)));
|
|
1537
|
+
} catch (error) {
|
|
1538
|
+
requireMeshSpotReply(record.reply(encodeChannelErrorReplyParts(
|
|
1539
|
+
envelope.header,
|
|
1540
|
+
error instanceof Error ? error.message : String(error)
|
|
1541
|
+
)));
|
|
1542
|
+
}
|
|
1543
|
+
}
|
|
1544
|
+
|
|
1545
|
+
private async ensureInstanceApplicationActivation(
|
|
1546
|
+
meshName: string,
|
|
1547
|
+
spotId: RoutingId
|
|
1548
|
+
): Promise<void> {
|
|
1549
|
+
let target = this.options.instanceSpotApplicationTargetProvider?.(meshName, spotId);
|
|
1550
|
+
if (target === undefined) return;
|
|
1551
|
+
for (;;) {
|
|
1552
|
+
const current = this.activations.resolve(meshName, spotId);
|
|
1553
|
+
if (
|
|
1554
|
+
current !== undefined
|
|
1555
|
+
&& current.objectGeneration === target.objectGeneration
|
|
1556
|
+
&& current.spotType === this.requireInstanceFactory(meshName, target.stableType)
|
|
1557
|
+
) return;
|
|
1558
|
+
await this.materializeInstance(
|
|
1559
|
+
meshName,
|
|
1560
|
+
target.stableType,
|
|
1561
|
+
spotId,
|
|
1562
|
+
target.objectGeneration
|
|
1563
|
+
);
|
|
1564
|
+
const latest = this.options.instanceSpotApplicationTargetProvider?.(meshName, spotId);
|
|
1565
|
+
if (latest === undefined) {
|
|
1566
|
+
throw createInternalFrameworkException(
|
|
1567
|
+
ZLinkFrameworkInternalErrorKind.SpotMoving,
|
|
1568
|
+
`Instance Spot target '${String(spotId)}' no longer has a Ready application target.`
|
|
1569
|
+
);
|
|
1570
|
+
}
|
|
1571
|
+
if (latest.objectGeneration === target.objectGeneration) return;
|
|
1572
|
+
target = latest;
|
|
1573
|
+
}
|
|
1574
|
+
}
|
|
1575
|
+
|
|
1576
|
+
async dispatchMeshInstance(
|
|
1577
|
+
meshName: string,
|
|
1578
|
+
owner: ReadyRecord,
|
|
1579
|
+
record: ReceiveRecord
|
|
1580
|
+
): Promise<void> {
|
|
1581
|
+
const spotId = owner.spotId as unknown as RoutingId | null;
|
|
1582
|
+
if (spotId === null) {
|
|
1583
|
+
throw new ZLinkConfigurationException(
|
|
1584
|
+
'MeshNode Instance Spot record is missing the owner Spot RID.'
|
|
1585
|
+
);
|
|
1586
|
+
}
|
|
1587
|
+
const envelope = decodeChannelEnvelope(
|
|
1588
|
+
record.parts,
|
|
1589
|
+
undefined,
|
|
1590
|
+
this.options.dispatchErrors?.flow.flowCreationEnabled() ?? true
|
|
1591
|
+
);
|
|
1592
|
+
const inboundFlow = createInboundFlow(
|
|
1593
|
+
envelope.header.flowId,
|
|
1594
|
+
envelope.header.flowOrigin,
|
|
1595
|
+
this.options.dispatchErrors?.flow.flowCreationEnabled() ?? true
|
|
1596
|
+
);
|
|
1597
|
+
await runWithFlow(inboundFlow, async () => {
|
|
1598
|
+
const request = record.operationKind === OperationKind.InstanceSpotRequest;
|
|
1599
|
+
this.traceInstanceMessage(
|
|
1600
|
+
ZLinkMessageFlowOutcome.Received,
|
|
1601
|
+
meshName,
|
|
1602
|
+
spotId,
|
|
1603
|
+
record,
|
|
1604
|
+
envelope,
|
|
1605
|
+
'activating'
|
|
1606
|
+
);
|
|
1607
|
+
try {
|
|
1608
|
+
await this.ensureInstanceApplicationActivation(meshName, spotId);
|
|
1609
|
+
const activation = this.activations.resolve(meshName, spotId);
|
|
1610
|
+
if (activation === undefined || activation.domain.kind !== 'instance') {
|
|
1611
|
+
throw new ZLinkConfigurationException(
|
|
1612
|
+
`MeshNode Instance Spot target '${String(spotId)}' is not active.`
|
|
1613
|
+
);
|
|
1614
|
+
}
|
|
1615
|
+
const target = this.options.instanceSpotApplicationTargetProvider?.(meshName, spotId);
|
|
1616
|
+
if (target !== undefined
|
|
1617
|
+
&& activation.domain.objectGeneration !== target.objectGeneration) {
|
|
1618
|
+
throw createInternalFrameworkException(
|
|
1619
|
+
ZLinkFrameworkInternalErrorKind.SpotGenerationStale,
|
|
1620
|
+
`Instance Spot target '${String(spotId)}' application generation is stale.`
|
|
1621
|
+
);
|
|
1622
|
+
}
|
|
1623
|
+
const codecs = this.options.messageSerializers === undefined
|
|
1624
|
+
? undefined
|
|
1625
|
+
: { serializers: this.options.messageSerializers };
|
|
1626
|
+
const decodePayload = () => decodeChannelPayload(envelope, codecs);
|
|
1627
|
+
const context = {
|
|
1628
|
+
channelName: envelope.header.channelName,
|
|
1629
|
+
contentType: envelope.header.contentType,
|
|
1630
|
+
awaitFirstHandlerTurn: record.kind === ReceiveKind.InstanceSpotActivation,
|
|
1631
|
+
workOptions: zlinkSerialWorkOptions(
|
|
1632
|
+
envelope.payload.byteLength,
|
|
1633
|
+
record.applicationMetadata?.byteLength ?? zlinkMetadataByteLength(envelope.header.metadata)
|
|
1634
|
+
)
|
|
1635
|
+
};
|
|
1636
|
+
this.traceInstanceMessage(
|
|
1637
|
+
ZLinkMessageFlowOutcome.Admitted,
|
|
1638
|
+
meshName,
|
|
1639
|
+
spotId,
|
|
1640
|
+
record,
|
|
1641
|
+
envelope,
|
|
1642
|
+
'ready',
|
|
1643
|
+
target?.stableType
|
|
1644
|
+
);
|
|
1645
|
+
if (!request) {
|
|
1646
|
+
this.traceInstanceMessage(
|
|
1647
|
+
ZLinkMessageFlowOutcome.Dispatched,
|
|
1648
|
+
meshName,
|
|
1649
|
+
spotId,
|
|
1650
|
+
record,
|
|
1651
|
+
envelope,
|
|
1652
|
+
'ready',
|
|
1653
|
+
target?.stableType
|
|
1654
|
+
);
|
|
1655
|
+
await this.routedSpotPackets.sendEncoded(spotId, envelope.packetName, decodePayload, context);
|
|
1656
|
+
this.traceInstanceMessage(
|
|
1657
|
+
ZLinkMessageFlowOutcome.Completed,
|
|
1658
|
+
meshName,
|
|
1659
|
+
spotId,
|
|
1660
|
+
record,
|
|
1661
|
+
envelope,
|
|
1662
|
+
'ready',
|
|
1663
|
+
target?.stableType
|
|
1664
|
+
);
|
|
1665
|
+
return;
|
|
1666
|
+
}
|
|
1667
|
+
this.traceInstanceMessage(
|
|
1668
|
+
ZLinkMessageFlowOutcome.Dispatched,
|
|
1669
|
+
meshName,
|
|
1670
|
+
spotId,
|
|
1671
|
+
record,
|
|
1672
|
+
envelope,
|
|
1673
|
+
'ready',
|
|
1674
|
+
target?.stableType
|
|
1675
|
+
);
|
|
1676
|
+
const response = await this.routedSpotPackets.requestEncoded(
|
|
1677
|
+
spotId,
|
|
1678
|
+
envelope.packetName,
|
|
1679
|
+
decodePayload,
|
|
1680
|
+
context
|
|
1681
|
+
);
|
|
1682
|
+
requireMeshSpotReply(record.reply(encodeChannelReplyParts(envelope.header, response, codecs)));
|
|
1683
|
+
this.traceInstanceMessage(
|
|
1684
|
+
ZLinkMessageFlowOutcome.Replied,
|
|
1685
|
+
meshName,
|
|
1686
|
+
spotId,
|
|
1687
|
+
record,
|
|
1688
|
+
envelope,
|
|
1689
|
+
'ready',
|
|
1690
|
+
target?.stableType
|
|
1691
|
+
);
|
|
1692
|
+
} catch (error) {
|
|
1693
|
+
const reason = instanceDispatchErrorReason(error);
|
|
1694
|
+
if (!request) {
|
|
1695
|
+
this.traceInstanceMessage(
|
|
1696
|
+
ZLinkMessageFlowOutcome.Dropped,
|
|
1697
|
+
meshName,
|
|
1698
|
+
spotId,
|
|
1699
|
+
record,
|
|
1700
|
+
envelope,
|
|
1701
|
+
'closing',
|
|
1702
|
+
undefined,
|
|
1703
|
+
reason
|
|
1704
|
+
);
|
|
1705
|
+
return;
|
|
1706
|
+
}
|
|
1707
|
+
this.options.dispatchErrors?.report({
|
|
1708
|
+
surface: ZLinkDispatchErrorSurface.InstanceSpot,
|
|
1709
|
+
messageKind: ZLinkDispatchMessageKind.Request,
|
|
1710
|
+
packetName: envelope.packetName,
|
|
1711
|
+
channelName: envelope.header.channelName,
|
|
1712
|
+
meshName,
|
|
1713
|
+
correlationId: envelope.header.correlationId ?? undefined,
|
|
1714
|
+
sourceRid: record.sourceNodeRid === null ? undefined : String(record.sourceNodeRid),
|
|
1715
|
+
spotId: String(spotId),
|
|
1716
|
+
instanceSpotType: this.options.instanceSpotApplicationTargetProvider?.(meshName, spotId)?.stableType,
|
|
1717
|
+
activationState: 'closing',
|
|
1718
|
+
flowId: envelope.header.flowId,
|
|
1719
|
+
flowOrigin: envelope.header.flowOrigin,
|
|
1720
|
+
reason,
|
|
1721
|
+
action: ZLinkDispatchErrorAction.ReplyError,
|
|
1722
|
+
error
|
|
1723
|
+
});
|
|
1724
|
+
requireMeshSpotReply(record.reply(encodeChannelErrorReplyParts(
|
|
1725
|
+
envelope.header,
|
|
1726
|
+
error instanceof Error ? error.message : String(error)
|
|
1727
|
+
)));
|
|
1728
|
+
}
|
|
1729
|
+
});
|
|
1730
|
+
}
|
|
1731
|
+
|
|
1732
|
+
private traceInstanceMessage(
|
|
1733
|
+
outcome: ZLinkMessageFlowOutcome,
|
|
1734
|
+
meshName: string,
|
|
1735
|
+
spotId: RoutingId,
|
|
1736
|
+
record: ReceiveRecord,
|
|
1737
|
+
envelope: ReturnType<typeof decodeChannelEnvelope>,
|
|
1738
|
+
activationState: 'activating' | 'ready' | 'closing',
|
|
1739
|
+
instanceSpotType?: string,
|
|
1740
|
+
errorReason?: ZLinkDispatchErrorReason
|
|
1741
|
+
): void {
|
|
1742
|
+
const flow = flowIfEnabled(
|
|
1743
|
+
this.options.dispatchErrors?.flow,
|
|
1744
|
+
outcome,
|
|
1745
|
+
undefined,
|
|
1746
|
+
envelope.header.flowId
|
|
1747
|
+
);
|
|
1748
|
+
if (flow === undefined) return;
|
|
1749
|
+
flow.trace({
|
|
1750
|
+
outcome,
|
|
1751
|
+
surface: ZLinkDispatchErrorSurface.InstanceSpot,
|
|
1752
|
+
messageKind: record.operationKind === OperationKind.InstanceSpotRequest
|
|
1753
|
+
? ZLinkDispatchMessageKind.Request
|
|
1754
|
+
: ZLinkDispatchMessageKind.Send,
|
|
1755
|
+
packetName: envelope.packetName,
|
|
1756
|
+
channelName: envelope.header.channelName,
|
|
1757
|
+
meshName,
|
|
1758
|
+
correlationId: envelope.header.correlationId ?? undefined,
|
|
1759
|
+
sourceRid: record.sourceNodeRid === null ? undefined : String(record.sourceNodeRid),
|
|
1760
|
+
spotId: String(spotId),
|
|
1761
|
+
instanceSpotType,
|
|
1762
|
+
activationState,
|
|
1763
|
+
flowId: envelope.header.flowId,
|
|
1764
|
+
flowOrigin: envelope.header.flowOrigin,
|
|
1765
|
+
errorReason
|
|
1766
|
+
});
|
|
1767
|
+
}
|
|
1768
|
+
|
|
1769
|
+
async dispatchMeshActor(meshName: string, owner: ReadyRecord, record: ReceiveRecord): Promise<void> {
|
|
1770
|
+
const spotId = owner.spotId as unknown as RoutingId | null;
|
|
1771
|
+
const entrySpotId = this.options.entryNodeRidProvider?.() ?? this.options.entryNodeRid;
|
|
1772
|
+
const targetsEntrySpot = spotId === null
|
|
1773
|
+
|| (entrySpotId !== undefined && spotId === entrySpotId);
|
|
1774
|
+
const actor = owner.actor;
|
|
1775
|
+
if (actor === null) {
|
|
1776
|
+
throw new ZLinkConfigurationException('MeshNode Actor record is missing its Actor owner.');
|
|
1777
|
+
}
|
|
1778
|
+
const request = record.kind === ReceiveKind.ActorRequest;
|
|
1779
|
+
if (record.sourceBindingGeneration > 0n) {
|
|
1780
|
+
this.options.actorBindingGenerationObserver?.(actor.actorId, record.sourceBindingGeneration);
|
|
1781
|
+
}
|
|
1782
|
+
const resolvedOwner = this.options.actorDispatchOwnerResolver?.(actor.actorId);
|
|
1783
|
+
const resolvedActorRef = resolvedOwner?.actorRef ?? {
|
|
1784
|
+
actorId: actor.actorId,
|
|
1785
|
+
objectGeneration: actor.generation,
|
|
1786
|
+
meshName,
|
|
1787
|
+
nodeRid: String(actor.nodeRid)
|
|
1788
|
+
};
|
|
1789
|
+
const responseActorRef = record.sourceBindingGeneration > 0n
|
|
1790
|
+
? {
|
|
1791
|
+
...resolvedActorRef,
|
|
1792
|
+
bindingGeneration: record.sourceBindingGeneration
|
|
1793
|
+
} as ActorRef
|
|
1794
|
+
: resolvedActorRef;
|
|
1795
|
+
const ownerActorRef = responseActorRef;
|
|
1796
|
+
const requestTerminalState = { prepared: false, submitted: false };
|
|
1797
|
+
const requestTerminal = request
|
|
1798
|
+
? Object.assign(
|
|
1799
|
+
(response: unknown, preparedReply?: unknown) => {
|
|
1800
|
+
const encoded = preparedReply === undefined
|
|
1801
|
+
? this.encodeMeshActorReply(
|
|
1802
|
+
record.parts[0],
|
|
1803
|
+
ZLinkStreamMessageKind.Response,
|
|
1804
|
+
response
|
|
1805
|
+
)
|
|
1806
|
+
: preparedReply as readonly Buffer[];
|
|
1807
|
+
requireMeshSpotReply(record.reply(encoded));
|
|
1808
|
+
requestTerminalState.submitted = true;
|
|
1809
|
+
},
|
|
1810
|
+
{
|
|
1811
|
+
prepare: (response: unknown): readonly Buffer[] => {
|
|
1812
|
+
const encoded = this.encodeMeshActorReply(
|
|
1813
|
+
record.parts[0],
|
|
1814
|
+
ZLinkStreamMessageKind.Response,
|
|
1815
|
+
response
|
|
1816
|
+
);
|
|
1817
|
+
requestTerminalState.prepared = true;
|
|
1818
|
+
return encoded;
|
|
1819
|
+
}
|
|
1820
|
+
}
|
|
1821
|
+
)
|
|
1822
|
+
: undefined;
|
|
1823
|
+
try {
|
|
1824
|
+
if (this.formalRemoteTransfers.has(actor.actorId)) {
|
|
1825
|
+
throw new Error(
|
|
1826
|
+
`Actor '${actor.actorId}' target transfer reconciliation is not complete.`
|
|
1827
|
+
);
|
|
1828
|
+
}
|
|
1829
|
+
const response = targetsEntrySpot
|
|
1830
|
+
? await this.options.dispatchEntryActorPacket?.(
|
|
1831
|
+
actor.actorId,
|
|
1832
|
+
record.parts,
|
|
1833
|
+
request,
|
|
1834
|
+
undefined,
|
|
1835
|
+
ownerActorRef,
|
|
1836
|
+
requestTerminal,
|
|
1837
|
+
record.messageFollowOrigin
|
|
1838
|
+
)
|
|
1839
|
+
: await this.dispatchMeshActorPacket(
|
|
1840
|
+
meshName,
|
|
1841
|
+
spotId,
|
|
1842
|
+
actor.actorId,
|
|
1843
|
+
record.parts,
|
|
1844
|
+
request,
|
|
1845
|
+
ownerActorRef,
|
|
1846
|
+
requestTerminal,
|
|
1847
|
+
record.messageFollowOrigin
|
|
1848
|
+
);
|
|
1849
|
+
if (targetsEntrySpot && this.options.dispatchEntryActorPacket === undefined) {
|
|
1850
|
+
throw new ZLinkConfigurationException('MeshNode Entry Spot Actor dispatch is not configured.');
|
|
1851
|
+
}
|
|
1852
|
+
if (request && !requestTerminalState.submitted) {
|
|
1853
|
+
requireMeshSpotReply(record.reply(this.encodeMeshActorReply(
|
|
1854
|
+
record.parts[0],
|
|
1855
|
+
ZLinkStreamMessageKind.Response,
|
|
1856
|
+
response
|
|
1857
|
+
)));
|
|
1858
|
+
}
|
|
1859
|
+
} catch (error) {
|
|
1860
|
+
if (!request) {
|
|
1861
|
+
throw error;
|
|
1862
|
+
}
|
|
1863
|
+
if (requestTerminalState.prepared || requestTerminalState.submitted) {
|
|
1864
|
+
throw error;
|
|
1865
|
+
}
|
|
1866
|
+
requireMeshSpotReply(record.reply(this.encodeMeshActorReply(
|
|
1867
|
+
record.parts[0],
|
|
1868
|
+
ZLinkStreamMessageKind.Error,
|
|
1869
|
+
{
|
|
1870
|
+
message: error instanceof Error ? error.message : String(error),
|
|
1871
|
+
kind: error instanceof ZLinkFrameworkException
|
|
1872
|
+
? error.kind
|
|
1873
|
+
: ZLinkFrameworkErrorKind.InternalFailure
|
|
1874
|
+
}
|
|
1875
|
+
)));
|
|
1876
|
+
}
|
|
1877
|
+
}
|
|
1878
|
+
|
|
1879
|
+
async dispatchMeshActorJoin(meshName: string, owner: ReadyRecord, record: ReceiveRecord): Promise<void> {
|
|
1880
|
+
const spotId = owner.spotId as unknown as RoutingId | null;
|
|
1881
|
+
const control = record.kindData;
|
|
1882
|
+
if (control?.kind !== 'actorControl') {
|
|
1883
|
+
throw new ZLinkConfigurationException('MeshNode Actor join record is missing lifecycle identity data.');
|
|
1884
|
+
}
|
|
1885
|
+
const actorId = control.currentActor?.actorId;
|
|
1886
|
+
if (spotId === null || actorId === undefined) {
|
|
1887
|
+
throw new ZLinkConfigurationException('MeshNode Actor join record is missing its Spot or Actor owner.');
|
|
1888
|
+
}
|
|
1889
|
+
const entrySpotId = this.options.entryNodeRidProvider?.() ?? this.options.entryNodeRid;
|
|
1890
|
+
let requestContentType = record.contentType ?? 'application/json';
|
|
1891
|
+
const targetsEntrySpot = entrySpotId !== undefined
|
|
1892
|
+
&& String(spotId) === String(entrySpotId);
|
|
1893
|
+
const activation = this.activations.resolve(meshName, spotId);
|
|
1894
|
+
const transferRequest = record.parts.length === 0
|
|
1895
|
+
? undefined
|
|
1896
|
+
: decodeFormalRemoteTransferRequest(record.parts[0]!);
|
|
1897
|
+
const remoteJoinPhase = transferRequest?.phase;
|
|
1898
|
+
const isRemoteAdmission = remoteJoinPhase === REMOTE_ACTOR_JOIN_ADMISSION;
|
|
1899
|
+
const isRemoteCommit = remoteJoinPhase === REMOTE_ACTOR_JOIN_COMMIT;
|
|
1900
|
+
const isRemoteAbort = remoteJoinPhase === REMOTE_ACTOR_JOIN_ABORT;
|
|
1901
|
+
let admissionRecord = transferRequest !== undefined
|
|
1902
|
+
? this.formalRemoteActorAdmissions.get(transferRequest.transferId)
|
|
1903
|
+
: undefined;
|
|
1904
|
+
let canonicalAdmissionCreated = false;
|
|
1905
|
+
let pendingAdmission = isRemoteCommit ? admissionRecord : undefined;
|
|
1906
|
+
let commitAdmissionMissing = isRemoteCommit && admissionRecord === undefined;
|
|
1907
|
+
const applicationClaim = transferRequest === undefined
|
|
1908
|
+
? this.options.admission?.claim(meshName, 'Actor join dispatch')
|
|
1909
|
+
: undefined;
|
|
1910
|
+
let canonicalActorType: string | undefined;
|
|
1911
|
+
if (control.canonicalActorJoin !== undefined) {
|
|
1912
|
+
const resolver = this.options.canonicalActorJoinResolver;
|
|
1913
|
+
if (resolver === undefined) {
|
|
1914
|
+
throw new ZLinkConfigurationException(
|
|
1915
|
+
'Canonical Actor Join dispatch requires the Location Store admission resolver.'
|
|
1916
|
+
);
|
|
1917
|
+
}
|
|
1918
|
+
const rawActorRef = control.previousActor ?? control.currentActor;
|
|
1919
|
+
const rawRequest = record.parts[0]!;
|
|
1920
|
+
if (rawActorRef === null) {
|
|
1921
|
+
throw new ZLinkConfigurationException(
|
|
1922
|
+
`Actor '${actorId}' canonical admission is missing its ActorRef or request.`
|
|
1923
|
+
);
|
|
1924
|
+
}
|
|
1925
|
+
const actorRef = toFrameworkRemoteAdmissionActorRef(rawActorRef, meshName);
|
|
1926
|
+
const provisional = this.formalRemoteActorAdmissions.beginProvisional({
|
|
1927
|
+
actorId,
|
|
1928
|
+
actorRef,
|
|
1929
|
+
spotId,
|
|
1930
|
+
targetSpotGeneration: control.currentSpotGeneration,
|
|
1931
|
+
expectedMembershipEpoch: control.currentMembershipEpoch,
|
|
1932
|
+
requestFingerprint: rawRequest.data().toString('base64'),
|
|
1933
|
+
transferId: control.canonicalActorJoin.handoffId,
|
|
1934
|
+
sourceActorNodeRid: control.canonicalActorJoin.actorNodeRid as RoutingId
|
|
1935
|
+
});
|
|
1936
|
+
admissionRecord = provisional.record;
|
|
1937
|
+
canonicalAdmissionCreated = provisional.created;
|
|
1938
|
+
try {
|
|
1939
|
+
canonicalActorType = (await resolver({ actorId, ...control.canonicalActorJoin })).actorType;
|
|
1940
|
+
} catch (error) {
|
|
1941
|
+
this.formalRemoteActorAdmissions.fail(control.canonicalActorJoin.handoffId, error);
|
|
1942
|
+
if (error instanceof ZLinkFrameworkException && record.replyFailure !== undefined) {
|
|
1943
|
+
const terminal = internalFrameworkWireReply(error);
|
|
1944
|
+
requireMeshSpotReply(record.replyFailure(terminal.terminalResult, terminal.failureCode));
|
|
1945
|
+
return;
|
|
1946
|
+
}
|
|
1947
|
+
throw error;
|
|
1948
|
+
}
|
|
1949
|
+
}
|
|
1950
|
+
const resolvedActor = this.options.actorResolver?.(actorId);
|
|
1951
|
+
const lifecycleActor = targetsEntrySpot
|
|
1952
|
+
? this.options.actorLifecycleResolver?.(actorId)
|
|
1953
|
+
: undefined;
|
|
1954
|
+
let actor = resolvedActor;
|
|
1955
|
+
if (actor === undefined && targetsEntrySpot) {
|
|
1956
|
+
// An actor returning from a User Spot can still be marked as moving
|
|
1957
|
+
// while the source-side relocation fence is being completed. Entry Spot
|
|
1958
|
+
// admission must resolve that lifecycle object so the accepted Core
|
|
1959
|
+
// reply can commit the return transaction.
|
|
1960
|
+
actor = lifecycleActor;
|
|
1961
|
+
}
|
|
1962
|
+
if (actor === undefined && admissionRecord?.actor !== undefined) {
|
|
1963
|
+
actor = admissionRecord.actor;
|
|
1964
|
+
}
|
|
1965
|
+
let callbackRequest: Message | undefined = record.parts.length === 0
|
|
1966
|
+
? undefined
|
|
1967
|
+
: record.parts[0]!;
|
|
1968
|
+
let ownedCallbackRequest: Message | undefined;
|
|
1969
|
+
let materialized = false;
|
|
1970
|
+
let reply: Message | undefined;
|
|
1971
|
+
let deferredJoinRoot: ZLinkDeferredJoinAcceptedRoot | undefined;
|
|
1972
|
+
let preparedTransferState: Message | undefined;
|
|
1973
|
+
let admissionOutcome: ZLinkFormalRemoteActorAdmissionResult | undefined;
|
|
1974
|
+
let accepted = false;
|
|
1975
|
+
let committedAdmissionReplay = isRemoteCommit
|
|
1976
|
+
&& admissionRecord?.state === 'committed';
|
|
1977
|
+
let targetCommitPublished: boolean | undefined;
|
|
1978
|
+
const actorJoinIsCurrent = (): boolean => (
|
|
1979
|
+
(record.deadlineUnixMs === undefined || record.deadlineUnixMs > BigInt(Date.now()))
|
|
1980
|
+
&& (record.isPending?.() ?? true)
|
|
1981
|
+
);
|
|
1982
|
+
const abandonStaleAdmission = (): void => {
|
|
1983
|
+
if (isRemoteAdmission && transferRequest !== undefined) {
|
|
1984
|
+
this.formalRemoteActorAdmissions.abort(transferRequest.transferId);
|
|
1985
|
+
}
|
|
1986
|
+
};
|
|
1987
|
+
try {
|
|
1988
|
+
if (!isRemoteAbort && !actorJoinIsCurrent()) {
|
|
1989
|
+
abandonStaleAdmission();
|
|
1990
|
+
return;
|
|
1991
|
+
}
|
|
1992
|
+
if (isRemoteAbort) {
|
|
1993
|
+
if (transferRequest !== undefined) {
|
|
1994
|
+
this.formalRemoteActorAdmissions.abort(transferRequest.transferId);
|
|
1995
|
+
}
|
|
1996
|
+
requireMeshSpotReply(record.replyActorJoin(1, []));
|
|
1997
|
+
return;
|
|
1998
|
+
}
|
|
1999
|
+
if (transferRequest !== undefined) {
|
|
2000
|
+
ownedCallbackRequest = RuntimeMessage.from(
|
|
2001
|
+
Buffer.from(transferRequest.request, 'base64')
|
|
2002
|
+
);
|
|
2003
|
+
callbackRequest = ownedCallbackRequest;
|
|
2004
|
+
} else if (callbackRequest !== undefined) {
|
|
2005
|
+
ownedCallbackRequest = RuntimeMessage.from(
|
|
2006
|
+
callbackRequest.data()
|
|
2007
|
+
);
|
|
2008
|
+
callbackRequest = ownedCallbackRequest;
|
|
2009
|
+
}
|
|
2010
|
+
if (control.canonicalActorJoin !== undefined) {
|
|
2011
|
+
if (callbackRequest === undefined) {
|
|
2012
|
+
throw new ZLinkConfigurationException(
|
|
2013
|
+
`Actor '${actorId}' canonical admission could not resolve its request.`
|
|
2014
|
+
);
|
|
2015
|
+
}
|
|
2016
|
+
const actorType = canonicalActorType;
|
|
2017
|
+
if (actorType === undefined) {
|
|
2018
|
+
throw new ZLinkConfigurationException(
|
|
2019
|
+
`Actor '${actorId}' canonical admission has no Store-resolved Actor type.`
|
|
2020
|
+
);
|
|
2021
|
+
}
|
|
2022
|
+
const actorRef = toFrameworkRemoteAdmissionActorRef(
|
|
2023
|
+
control.previousActor ?? control.currentActor!,
|
|
2024
|
+
meshName
|
|
2025
|
+
);
|
|
2026
|
+
admissionRecord = this.formalRemoteActorAdmissions.finalizeProvisional(
|
|
2027
|
+
control.canonicalActorJoin.handoffId,
|
|
2028
|
+
{
|
|
2029
|
+
actorId,
|
|
2030
|
+
actorType,
|
|
2031
|
+
actorRef,
|
|
2032
|
+
spotId,
|
|
2033
|
+
targetSpotGeneration: control.currentSpotGeneration,
|
|
2034
|
+
expectedMembershipEpoch: control.currentMembershipEpoch,
|
|
2035
|
+
requestFingerprint: callbackRequest.data().toString('base64'),
|
|
2036
|
+
transferId: control.canonicalActorJoin.handoffId,
|
|
2037
|
+
sourceActorNodeRid: control.canonicalActorJoin.actorNodeRid as RoutingId
|
|
2038
|
+
}
|
|
2039
|
+
);
|
|
2040
|
+
if (canonicalAdmissionCreated) {
|
|
2041
|
+
if (targetsEntrySpot) {
|
|
2042
|
+
admissionOutcome = {
|
|
2043
|
+
accepted: this.options.dispatchEntryActorJoin !== undefined,
|
|
2044
|
+
actorRef
|
|
2045
|
+
};
|
|
2046
|
+
} else if (activation === undefined) {
|
|
2047
|
+
admissionOutcome = { accepted: false, actorRef };
|
|
2048
|
+
} else {
|
|
2049
|
+
const response: ZLinkSpotActorJoinResult = await activation.serial.execute(async () =>
|
|
2050
|
+
activation.spot.onActorJoin(
|
|
2051
|
+
actorRef.actorId,
|
|
2052
|
+
wrapFrameworkPayloadMessage(
|
|
2053
|
+
callbackRequest!,
|
|
2054
|
+
this.options.messageSerializers,
|
|
2055
|
+
requestContentType
|
|
2056
|
+
)
|
|
2057
|
+
)
|
|
2058
|
+
);
|
|
2059
|
+
let encodedReply: Message | undefined;
|
|
2060
|
+
try {
|
|
2061
|
+
encodedReply = response.reply === undefined
|
|
2062
|
+
? undefined
|
|
2063
|
+
: encodeFrameworkPayloadMessage(response.reply, this.options.messageSerializers);
|
|
2064
|
+
admissionOutcome = {
|
|
2065
|
+
accepted: response.accepted,
|
|
2066
|
+
actorRef,
|
|
2067
|
+
...(encodedReply === undefined
|
|
2068
|
+
? {}
|
|
2069
|
+
: {
|
|
2070
|
+
reply: Buffer.from(encodedReply.data()),
|
|
2071
|
+
replyContentType: frameworkPayloadContentType(encodedReply)
|
|
2072
|
+
})
|
|
2073
|
+
};
|
|
2074
|
+
} finally {
|
|
2075
|
+
encodedReply?.close();
|
|
2076
|
+
}
|
|
2077
|
+
}
|
|
2078
|
+
this.formalRemoteActorAdmissions.complete(
|
|
2079
|
+
control.canonicalActorJoin.handoffId,
|
|
2080
|
+
admissionOutcome
|
|
2081
|
+
);
|
|
2082
|
+
}
|
|
2083
|
+
admissionOutcome = admissionRecord.result ?? await admissionRecord.resultTask;
|
|
2084
|
+
if ('error' in admissionOutcome) throw admissionOutcome.error;
|
|
2085
|
+
accepted = admissionOutcome.accepted;
|
|
2086
|
+
reply = admissionOutcome.reply === undefined
|
|
2087
|
+
? undefined
|
|
2088
|
+
: RuntimeMessage.from(admissionOutcome.reply);
|
|
2089
|
+
}
|
|
2090
|
+
if (
|
|
2091
|
+
transferRequest !== undefined
|
|
2092
|
+
&& !targetsEntrySpot
|
|
2093
|
+
&& remoteJoinPhase === undefined
|
|
2094
|
+
) {
|
|
2095
|
+
// User Spot transfers must carry the private admission/commit phases.
|
|
2096
|
+
// A legacy one-phase request would otherwise read relocation state
|
|
2097
|
+
// before the target application has accepted the Actor.
|
|
2098
|
+
requireMeshSpotReply(record.replyActorJoin(1, []));
|
|
2099
|
+
return;
|
|
2100
|
+
}
|
|
2101
|
+
if (isRemoteAdmission && transferRequest !== undefined) {
|
|
2102
|
+
const rawActorRef = transferRequest.actorRef ?? control.currentActor ?? undefined;
|
|
2103
|
+
if (rawActorRef === undefined) {
|
|
2104
|
+
throw new ZLinkConfigurationException(`Actor '${actorId}' join record has no ActorRef.`);
|
|
2105
|
+
}
|
|
2106
|
+
const actorRef = toFrameworkRemoteAdmissionActorRef(rawActorRef, meshName);
|
|
2107
|
+
const admission = this.formalRemoteActorAdmissions.begin({
|
|
2108
|
+
actorId,
|
|
2109
|
+
actorType: transferRequest.actorType,
|
|
2110
|
+
actorRef,
|
|
2111
|
+
spotId,
|
|
2112
|
+
targetSpotGeneration: control.currentSpotGeneration,
|
|
2113
|
+
expectedMembershipEpoch: transferRequest.expectedMembershipEpoch,
|
|
2114
|
+
requestFingerprint: transferRequest.request,
|
|
2115
|
+
transferId: transferRequest.transferId,
|
|
2116
|
+
completionOperationId: transferRequest.completionOperationId,
|
|
2117
|
+
sourceSpotId: transferRequest.sourceSpotId
|
|
2118
|
+
});
|
|
2119
|
+
admissionRecord = admission.record;
|
|
2120
|
+
if (admission.created) {
|
|
2121
|
+
try {
|
|
2122
|
+
if (targetsEntrySpot) {
|
|
2123
|
+
if (
|
|
2124
|
+
this.options.dispatchEntryActorJoin !== undefined
|
|
2125
|
+
&& transferRequest.completionOperationId !== undefined
|
|
2126
|
+
&& this.options.actorTransferRuntime !== undefined
|
|
2127
|
+
) {
|
|
2128
|
+
deferredJoinRoot = await this.options.actorTransferRuntime
|
|
2129
|
+
.prepareDeferredJoinAccepted(
|
|
2130
|
+
actorId,
|
|
2131
|
+
transferRequest.completionOperationId,
|
|
2132
|
+
actorRef,
|
|
2133
|
+
Buffer.alloc(0)
|
|
2134
|
+
);
|
|
2135
|
+
}
|
|
2136
|
+
admissionOutcome = {
|
|
2137
|
+
accepted: this.options.dispatchEntryActorJoin !== undefined,
|
|
2138
|
+
actorRef,
|
|
2139
|
+
...(deferredJoinRoot === undefined ? {} : { deferredJoinRoot })
|
|
2140
|
+
};
|
|
2141
|
+
} else if (activation === undefined) {
|
|
2142
|
+
admissionOutcome = { accepted: false, actorRef };
|
|
2143
|
+
} else {
|
|
2144
|
+
if (!actorJoinIsCurrent()) {
|
|
2145
|
+
abandonStaleAdmission();
|
|
2146
|
+
return;
|
|
2147
|
+
}
|
|
2148
|
+
const response: ZLinkSpotActorJoinResult = await activation.serial.execute(async () =>
|
|
2149
|
+
activation.spot.onActorJoin(
|
|
2150
|
+
actorRef.actorId,
|
|
2151
|
+
wrapFrameworkPayloadMessage(
|
|
2152
|
+
ownedCallbackRequest!,
|
|
2153
|
+
this.options.messageSerializers,
|
|
2154
|
+
transferRequest.requestContentType
|
|
2155
|
+
)
|
|
2156
|
+
)
|
|
2157
|
+
);
|
|
2158
|
+
let encodedReply: Message | undefined;
|
|
2159
|
+
try {
|
|
2160
|
+
encodedReply = response.reply === undefined
|
|
2161
|
+
? undefined
|
|
2162
|
+
: encodeFrameworkPayloadMessage(response.reply, this.options.messageSerializers);
|
|
2163
|
+
if (
|
|
2164
|
+
response.accepted
|
|
2165
|
+
&& transferRequest.completionOperationId !== undefined
|
|
2166
|
+
&& this.options.actorTransferRuntime !== undefined
|
|
2167
|
+
) {
|
|
2168
|
+
deferredJoinRoot = await this.options.actorTransferRuntime
|
|
2169
|
+
.prepareDeferredJoinAccepted(
|
|
2170
|
+
actorId,
|
|
2171
|
+
transferRequest.completionOperationId,
|
|
2172
|
+
actorRef,
|
|
2173
|
+
encodedReply?.data() ?? Buffer.alloc(0),
|
|
2174
|
+
encodedReply === undefined
|
|
2175
|
+
? undefined
|
|
2176
|
+
: frameworkPayloadContentType(encodedReply)
|
|
2177
|
+
);
|
|
2178
|
+
this.options.runtimeEventPublisher?.publish({
|
|
2179
|
+
sourceName: 'zlink.framework.actor-handoff',
|
|
2180
|
+
timestamp: new Date(),
|
|
2181
|
+
marker: 'deferred_completion_staged',
|
|
2182
|
+
actorId
|
|
2183
|
+
});
|
|
2184
|
+
}
|
|
2185
|
+
admissionOutcome = {
|
|
2186
|
+
accepted: response.accepted,
|
|
2187
|
+
actorRef,
|
|
2188
|
+
...(deferredJoinRoot === undefined ? {} : { deferredJoinRoot }),
|
|
2189
|
+
...(encodedReply === undefined
|
|
2190
|
+
? {}
|
|
2191
|
+
: {
|
|
2192
|
+
reply: Buffer.from(encodedReply.data()),
|
|
2193
|
+
replyContentType: frameworkPayloadContentType(encodedReply)
|
|
2194
|
+
})
|
|
2195
|
+
};
|
|
2196
|
+
} finally {
|
|
2197
|
+
encodedReply?.close();
|
|
2198
|
+
}
|
|
2199
|
+
if (!actorJoinIsCurrent()) {
|
|
2200
|
+
abandonStaleAdmission();
|
|
2201
|
+
return;
|
|
2202
|
+
}
|
|
2203
|
+
}
|
|
2204
|
+
this.formalRemoteActorAdmissions.complete(
|
|
2205
|
+
transferRequest.transferId,
|
|
2206
|
+
admissionOutcome
|
|
2207
|
+
);
|
|
2208
|
+
} catch (error) {
|
|
2209
|
+
this.formalRemoteActorAdmissions.fail(transferRequest.transferId, error);
|
|
2210
|
+
throw error;
|
|
2211
|
+
}
|
|
2212
|
+
}
|
|
2213
|
+
admissionOutcome = await admissionRecord.resultTask;
|
|
2214
|
+
if ('error' in admissionOutcome) {
|
|
2215
|
+
throw admissionOutcome.error;
|
|
2216
|
+
}
|
|
2217
|
+
accepted = admissionOutcome.accepted;
|
|
2218
|
+
reply = admissionOutcome.reply === undefined
|
|
2219
|
+
? undefined
|
|
2220
|
+
: RuntimeMessage.from(admissionOutcome.reply);
|
|
2221
|
+
}
|
|
2222
|
+
if (isRemoteCommit && admissionRecord !== undefined) {
|
|
2223
|
+
admissionOutcome = await admissionRecord.resultTask;
|
|
2224
|
+
if ('error' in admissionOutcome) {
|
|
2225
|
+
throw admissionOutcome.error;
|
|
2226
|
+
}
|
|
2227
|
+
deferredJoinRoot = admissionOutcome.deferredJoinRoot;
|
|
2228
|
+
}
|
|
2229
|
+
if (
|
|
2230
|
+
actor === undefined
|
|
2231
|
+
&& transferRequest !== undefined
|
|
2232
|
+
&& this.options.actorTransferRuntime !== undefined
|
|
2233
|
+
&& !isRemoteAdmission
|
|
2234
|
+
&& !commitAdmissionMissing
|
|
2235
|
+
&& admissionRecord?.state !== 'committed'
|
|
2236
|
+
&& (targetsEntrySpot || activation !== undefined)
|
|
2237
|
+
) {
|
|
2238
|
+
// Relocation state travels inline with the join request. The store
|
|
2239
|
+
// reference handoff was removed with the direct-transfer contract
|
|
2240
|
+
// (spec 28 §2 — Relocation Store keeps no relocation state payloads).
|
|
2241
|
+
if (transferRequest.transferState === undefined) {
|
|
2242
|
+
throw new ZLinkConfigurationException(
|
|
2243
|
+
`Actor '${actorId}' transfer commit carries no inline relocation state.`
|
|
2244
|
+
);
|
|
2245
|
+
}
|
|
2246
|
+
preparedTransferState = RuntimeMessage.from(
|
|
2247
|
+
Buffer.from(transferRequest.transferState, 'base64')
|
|
2248
|
+
);
|
|
2249
|
+
}
|
|
2250
|
+
if (isRemoteAdmission && targetsEntrySpot) {
|
|
2251
|
+
accepted = admissionOutcome !== undefined
|
|
2252
|
+
&& !('error' in admissionOutcome)
|
|
2253
|
+
&& admissionOutcome.accepted;
|
|
2254
|
+
} else if (isRemoteCommit && pendingAdmission !== undefined) {
|
|
2255
|
+
validateRemoteAdmissionCommit(pendingAdmission, transferRequest!, actorId, control);
|
|
2256
|
+
accepted = pendingAdmission.state === 'admitted'
|
|
2257
|
+
|| pendingAdmission.state === 'committed';
|
|
2258
|
+
} else if (commitAdmissionMissing) {
|
|
2259
|
+
accepted = false;
|
|
2260
|
+
} else if (targetsEntrySpot) {
|
|
2261
|
+
// Entry Spot return joins have no application admission callback. The
|
|
2262
|
+
// actor-manager transaction is committed after the Core reply below.
|
|
2263
|
+
// A formal transfer payload materializes the existing actor state at
|
|
2264
|
+
// the Entry owner before that transaction is committed.
|
|
2265
|
+
accepted = actor !== undefined
|
|
2266
|
+
|| (transferRequest !== undefined && this.options.actorTransferRuntime !== undefined);
|
|
2267
|
+
} else if (
|
|
2268
|
+
!isRemoteAdmission
|
|
2269
|
+
&& control.canonicalActorJoin === undefined
|
|
2270
|
+
&&
|
|
2271
|
+
activation !== undefined
|
|
2272
|
+
&& callbackRequest !== undefined
|
|
2273
|
+
&& (actor !== undefined || transferRequest !== undefined)
|
|
2274
|
+
) {
|
|
2275
|
+
if (!actorJoinIsCurrent()) return;
|
|
2276
|
+
const request = callbackRequest;
|
|
2277
|
+
const rawActorRef = transferRequest?.actorRef ?? control.currentActor ?? undefined;
|
|
2278
|
+
if (rawActorRef === undefined) {
|
|
2279
|
+
throw new ZLinkConfigurationException(`Actor '${actorId}' join record has no ActorRef.`);
|
|
2280
|
+
}
|
|
2281
|
+
const actorRef: ActorRef = {
|
|
2282
|
+
actorId: rawActorRef.actorId,
|
|
2283
|
+
objectGeneration: 'objectGeneration' in rawActorRef
|
|
2284
|
+
? rawActorRef.objectGeneration
|
|
2285
|
+
: rawActorRef.generation,
|
|
2286
|
+
meshName,
|
|
2287
|
+
nodeRid: rawActorRef.nodeRid as unknown as RoutingId
|
|
2288
|
+
};
|
|
2289
|
+
const response: ZLinkSpotActorJoinResult = await activation.serial.execute(async () =>
|
|
2290
|
+
activation.spot.onActorJoin(
|
|
2291
|
+
actorRef.actorId,
|
|
2292
|
+
wrapFrameworkPayloadMessage(
|
|
2293
|
+
request,
|
|
2294
|
+
this.options.messageSerializers,
|
|
2295
|
+
transferRequest?.requestContentType ?? requestContentType
|
|
2296
|
+
)
|
|
2297
|
+
)
|
|
2298
|
+
);
|
|
2299
|
+
if (!actorJoinIsCurrent()) return;
|
|
2300
|
+
accepted = response.accepted;
|
|
2301
|
+
reply = response.reply === undefined
|
|
2302
|
+
? undefined
|
|
2303
|
+
: encodeFrameworkPayloadMessage(response.reply, this.options.messageSerializers);
|
|
2304
|
+
if (
|
|
2305
|
+
accepted
|
|
2306
|
+
&& transferRequest?.completionOperationId !== undefined
|
|
2307
|
+
&& this.options.actorTransferRuntime !== undefined
|
|
2308
|
+
) {
|
|
2309
|
+
deferredJoinRoot = await this.options.actorTransferRuntime
|
|
2310
|
+
.prepareDeferredJoinAccepted(
|
|
2311
|
+
actorId,
|
|
2312
|
+
transferRequest.completionOperationId,
|
|
2313
|
+
actorRef,
|
|
2314
|
+
reply?.data() ?? Buffer.alloc(0),
|
|
2315
|
+
reply === undefined ? undefined : frameworkPayloadContentType(reply)
|
|
2316
|
+
);
|
|
2317
|
+
this.options.runtimeEventPublisher?.publish({
|
|
2318
|
+
sourceName: 'zlink.framework.actor-handoff',
|
|
2319
|
+
timestamp: new Date(),
|
|
2320
|
+
marker: 'deferred_completion_staged',
|
|
2321
|
+
actorId
|
|
2322
|
+
});
|
|
2323
|
+
}
|
|
2324
|
+
}
|
|
2325
|
+
if (
|
|
2326
|
+
accepted
|
|
2327
|
+
&& !isRemoteAdmission
|
|
2328
|
+
&& actor === undefined
|
|
2329
|
+
&& transferRequest !== undefined
|
|
2330
|
+
&& this.options.actorTransferRuntime !== undefined
|
|
2331
|
+
) {
|
|
2332
|
+
if (!actorJoinIsCurrent()) return;
|
|
2333
|
+
const transferState = preparedTransferState;
|
|
2334
|
+
preparedTransferState = undefined;
|
|
2335
|
+
if (transferState === undefined) {
|
|
2336
|
+
throw new Error('Remote actor transfer state was not prepared before admission.');
|
|
2337
|
+
}
|
|
2338
|
+
try {
|
|
2339
|
+
const result = await this.options.actorTransferRuntime.materializeRoutedActor(
|
|
2340
|
+
actorId,
|
|
2341
|
+
transferRequest.actorType,
|
|
2342
|
+
transferRequest.transferAdapterKey,
|
|
2343
|
+
transferState,
|
|
2344
|
+
transferRequest.actorEntryNodeRid,
|
|
2345
|
+
transferRequest.remoteBoundSessionTarget
|
|
2346
|
+
);
|
|
2347
|
+
actor = result.actor;
|
|
2348
|
+
materialized = true;
|
|
2349
|
+
await this.options.actorTransferRuntime.commitRoutedActorAuthority(
|
|
2350
|
+
actor,
|
|
2351
|
+
toFrameworkRemoteAdmissionActorRef(
|
|
2352
|
+
transferRequest.actorRef ?? control.currentActor!,
|
|
2353
|
+
meshName
|
|
2354
|
+
),
|
|
2355
|
+
transferRequest.transferId,
|
|
2356
|
+
spotId,
|
|
2357
|
+
control.currentSpotGeneration,
|
|
2358
|
+
control.currentMembershipEpoch,
|
|
2359
|
+
record.deadlineUnixMs === undefined
|
|
2360
|
+
? Date.now() + 5_000
|
|
2361
|
+
: Number(record.deadlineUnixMs),
|
|
2362
|
+
undefined
|
|
2363
|
+
);
|
|
2364
|
+
} finally {
|
|
2365
|
+
transferState.close();
|
|
2366
|
+
}
|
|
2367
|
+
if (!actorJoinIsCurrent()) {
|
|
2368
|
+
await this.options.actorTransferRuntime.rollbackRoutedActor(actor);
|
|
2369
|
+
materialized = false;
|
|
2370
|
+
return;
|
|
2371
|
+
}
|
|
2372
|
+
}
|
|
2373
|
+
if (
|
|
2374
|
+
accepted
|
|
2375
|
+
&& transferRequest !== undefined
|
|
2376
|
+
&& this.options.actorTransferRuntime !== undefined
|
|
2377
|
+
&& !isRemoteAdmission
|
|
2378
|
+
) {
|
|
2379
|
+
// A lightweight Core actor-join notification can create the Actor
|
|
2380
|
+
// before the formal transfer request reaches this branch. Preserve
|
|
2381
|
+
// the full relocation fence in that race so a later Session bind
|
|
2382
|
+
// refresh cannot erase the seal or accepted journal.
|
|
2383
|
+
this.options.actorTransferRuntime.rememberRoutedActorTransferTarget(
|
|
2384
|
+
actorId,
|
|
2385
|
+
transferRequest.remoteBoundSessionTarget
|
|
2386
|
+
);
|
|
2387
|
+
}
|
|
2388
|
+
if (
|
|
2389
|
+
accepted
|
|
2390
|
+
&& actor !== undefined
|
|
2391
|
+
&& transferRequest !== undefined
|
|
2392
|
+
&& !isRemoteAdmission
|
|
2393
|
+
&& !committedAdmissionReplay
|
|
2394
|
+
) {
|
|
2395
|
+
this.formalRemoteTransfers.begin({
|
|
2396
|
+
actor,
|
|
2397
|
+
spotId,
|
|
2398
|
+
transferId: transferRequest.transferId,
|
|
2399
|
+
handoffBacklog: transferRequest.handoffBacklog,
|
|
2400
|
+
deferredJoinRoot
|
|
2401
|
+
});
|
|
2402
|
+
if (isRemoteCommit && admissionRecord !== undefined) {
|
|
2403
|
+
this.formalRemoteActorAdmissions.markCommitted(
|
|
2404
|
+
transferRequest.transferId,
|
|
2405
|
+
actor
|
|
2406
|
+
);
|
|
2407
|
+
}
|
|
2408
|
+
}
|
|
2409
|
+
const replyActorJoin = (): boolean => {
|
|
2410
|
+
if (!actorJoinIsCurrent()) return false;
|
|
2411
|
+
const joinReplyResult = record.replyActorJoin(
|
|
2412
|
+
accepted ? 0 : 1,
|
|
2413
|
+
reply === undefined ? [] : [reply.data()],
|
|
2414
|
+
undefined,
|
|
2415
|
+
admissionOutcome === undefined || 'error' in admissionOutcome
|
|
2416
|
+
? undefined
|
|
2417
|
+
: admissionOutcome.replyContentType
|
|
2418
|
+
);
|
|
2419
|
+
if (accepted && !isRemoteAdmission && joinReplyResult === SubmitResult.Ok) {
|
|
2420
|
+
// Core commits the target membership while it accepts this reply.
|
|
2421
|
+
// From this call onward a later callback/transport failure is
|
|
2422
|
+
// post-commit and must not roll the materialized Actor back.
|
|
2423
|
+
targetCommitPublished = true;
|
|
2424
|
+
}
|
|
2425
|
+
requireMeshSpotReply(joinReplyResult);
|
|
2426
|
+
return true;
|
|
2427
|
+
};
|
|
2428
|
+
if (control.canonicalActorJoin !== undefined) {
|
|
2429
|
+
replyActorJoin();
|
|
2430
|
+
return;
|
|
2431
|
+
}
|
|
2432
|
+
if (accepted && targetsEntrySpot && actor !== undefined) {
|
|
2433
|
+
const entryActor = actor;
|
|
2434
|
+
const pendingTransfer = transferRequest === undefined
|
|
2435
|
+
? undefined
|
|
2436
|
+
: this.formalRemoteTransfers.get(actorId);
|
|
2437
|
+
if (committedAdmissionReplay) {
|
|
2438
|
+
if (!replyActorJoin()) return;
|
|
2439
|
+
} else if (pendingTransfer === undefined) {
|
|
2440
|
+
if (!actorJoinIsCurrent()) return;
|
|
2441
|
+
// The Core reply commits target membership. Entry lifecycle must
|
|
2442
|
+
// therefore run after that commit, as it does on the native path.
|
|
2443
|
+
if (!replyActorJoin()) return;
|
|
2444
|
+
await this.options.dispatchEntryActorJoin?.(meshName, entryActor);
|
|
2445
|
+
} else {
|
|
2446
|
+
if (!replyActorJoin()) return;
|
|
2447
|
+
const commitEntryTransfer = async (): Promise<void> => {
|
|
2448
|
+
try {
|
|
2449
|
+
await this.options.dispatchEntryActorJoin?.(
|
|
2450
|
+
meshName,
|
|
2451
|
+
entryActor,
|
|
2452
|
+
[]
|
|
2453
|
+
);
|
|
2454
|
+
} finally {
|
|
2455
|
+
this.formalRemoteTransfers.completeTargetLifecycle(
|
|
2456
|
+
entryActor.context.actorId,
|
|
2457
|
+
pendingTransfer.transferId
|
|
2458
|
+
);
|
|
2459
|
+
}
|
|
2460
|
+
const sourceLeaveSubmitted = await pendingTransfer.sourceLeaveSubmitted;
|
|
2461
|
+
if (!sourceLeaveSubmitted) {
|
|
2462
|
+
throw new Error(
|
|
2463
|
+
`Actor '${entryActor.context.actorId}' source authority commit failed before leave submission.`
|
|
2464
|
+
);
|
|
2465
|
+
}
|
|
2466
|
+
const handoffResults = await replayActorHandoffBacklog(
|
|
2467
|
+
pendingTransfer.handoffBacklog,
|
|
2468
|
+
async (parts, returnResponse, remoteBoundSessionTarget, fallbackActorRef) => {
|
|
2469
|
+
if (this.options.dispatchEntryActorPacket === undefined) {
|
|
2470
|
+
throw new Error('Entry Spot saved handoff replay requires its Actor packet runtime.');
|
|
2471
|
+
}
|
|
2472
|
+
return await this.options.dispatchEntryActorPacket(
|
|
2473
|
+
entryActor.context.actorId,
|
|
2474
|
+
parts,
|
|
2475
|
+
returnResponse,
|
|
2476
|
+
remoteBoundSessionTarget,
|
|
2477
|
+
fallbackActorRef
|
|
2478
|
+
);
|
|
2479
|
+
},
|
|
2480
|
+
index => this.options.runtimeEventPublisher?.publish({
|
|
2481
|
+
sourceName: 'zlink.framework.actor-handoff',
|
|
2482
|
+
timestamp: new Date(),
|
|
2483
|
+
marker: 'backlog_enqueued',
|
|
2484
|
+
actorId: entryActor.context.actorId,
|
|
2485
|
+
index
|
|
2486
|
+
})
|
|
2487
|
+
);
|
|
2488
|
+
const failedHandoff = handoffResults.find(result => !result.ok);
|
|
2489
|
+
if (failedHandoff !== undefined) {
|
|
2490
|
+
throw new Error(
|
|
2491
|
+
`Actor '${entryActor.context.actorId}' saved Entry handoff packet `
|
|
2492
|
+
+ `${failedHandoff.index} failed: ${failedHandoff.error ?? 'unknown error'}.`
|
|
2493
|
+
);
|
|
2494
|
+
}
|
|
2495
|
+
this.formalRemoteTransfers.delete(entryActor.context.actorId);
|
|
2496
|
+
};
|
|
2497
|
+
this.options.detachedTaskRunner?.runDetached(
|
|
2498
|
+
`actor Entry Spot transfer ${entryActor.context.actorId}`,
|
|
2499
|
+
commitEntryTransfer
|
|
2500
|
+
);
|
|
2501
|
+
if (this.options.detachedTaskRunner === undefined) {
|
|
2502
|
+
void commitEntryTransfer().catch(() => undefined);
|
|
2503
|
+
}
|
|
2504
|
+
}
|
|
2505
|
+
} else {
|
|
2506
|
+
if (!replyActorJoin()) return;
|
|
2507
|
+
}
|
|
2508
|
+
} catch (error) {
|
|
2509
|
+
if (control.canonicalActorJoin !== undefined) {
|
|
2510
|
+
this.formalRemoteActorAdmissions.fail(
|
|
2511
|
+
control.canonicalActorJoin.handoffId,
|
|
2512
|
+
error
|
|
2513
|
+
);
|
|
2514
|
+
}
|
|
2515
|
+
if (deferredJoinRoot !== undefined && targetCommitPublished !== true) {
|
|
2516
|
+
await this.options.actorTransferRuntime?.discardDeferredJoinAccepted(
|
|
2517
|
+
deferredJoinRoot
|
|
2518
|
+
);
|
|
2519
|
+
}
|
|
2520
|
+
if (targetCommitPublished !== true) {
|
|
2521
|
+
this.formalRemoteTransfers.delete(actorId);
|
|
2522
|
+
}
|
|
2523
|
+
if (materialized && targetCommitPublished !== true) {
|
|
2524
|
+
await this.options.actorTransferRuntime?.rollbackRoutedActor(actor!);
|
|
2525
|
+
}
|
|
2526
|
+
throw error;
|
|
2527
|
+
} finally {
|
|
2528
|
+
preparedTransferState?.close();
|
|
2529
|
+
ownedCallbackRequest?.close();
|
|
2530
|
+
reply?.close();
|
|
2531
|
+
applicationClaim?.close();
|
|
2532
|
+
}
|
|
2533
|
+
}
|
|
2534
|
+
|
|
2535
|
+
async dispatchMeshSpotControl(meshName: string, owner: ReadyRecord, record: ReceiveRecord): Promise<void> {
|
|
2536
|
+
const spotId = owner.spotId as unknown as RoutingId | null;
|
|
2537
|
+
const control = record.kindData;
|
|
2538
|
+
if (control?.kind !== 'actorControl') {
|
|
2539
|
+
throw new ZLinkConfigurationException('MeshNode Spot control record is missing actor lifecycle data.');
|
|
2540
|
+
}
|
|
2541
|
+
const actorRef = control.lifecycleKind === ActorLifecycleKind.Left
|
|
2542
|
+
? control.previousActor
|
|
2543
|
+
: control.currentActor;
|
|
2544
|
+
const actorId = actorRef?.actorId;
|
|
2545
|
+
const pendingTransfer = actorId === undefined
|
|
2546
|
+
? undefined
|
|
2547
|
+
: this.formalRemoteTransfers.get(actorId);
|
|
2548
|
+
const sourceActivation = actorId === undefined || spotId === null
|
|
2549
|
+
? undefined
|
|
2550
|
+
: this.activations.resolve(meshName, spotId);
|
|
2551
|
+
const sourceJoinedActor = actorId === undefined
|
|
2552
|
+
? undefined
|
|
2553
|
+
: sourceActivation?.resolveJoinedActor(actorId);
|
|
2554
|
+
const actor = actorId === undefined
|
|
2555
|
+
? undefined
|
|
2556
|
+
: pendingTransfer?.actor
|
|
2557
|
+
?? sourceJoinedActor
|
|
2558
|
+
?? this.options.actorLifecycleResolver?.(actorId)
|
|
2559
|
+
?? this.options.actorResolver?.(actorId);
|
|
2560
|
+
const entrySpotId = this.options.entryNodeRidProvider?.() ?? this.options.entryNodeRid;
|
|
2561
|
+
if (actor === undefined) {
|
|
2562
|
+
return;
|
|
2563
|
+
}
|
|
2564
|
+
if (control.lifecycleKind === ActorLifecycleKind.Left
|
|
2565
|
+
&& (spotId === null || (entrySpotId !== undefined && String(spotId) === String(entrySpotId)))) {
|
|
2566
|
+
const callback = async () => {
|
|
2567
|
+
await this.options.entrySpotCallbacks?.onLeaveActor(
|
|
2568
|
+
actor,
|
|
2569
|
+
undefined,
|
|
2570
|
+
actorRef as unknown as ActorRef,
|
|
2571
|
+
control.previousMembershipEpoch
|
|
2572
|
+
);
|
|
2573
|
+
};
|
|
2574
|
+
if (this.options.actorTransferRuntime === undefined) {
|
|
2575
|
+
await callback();
|
|
2576
|
+
} else {
|
|
2577
|
+
await this.options.actorTransferRuntime.notifyCoreSourceLeave(actor, callback);
|
|
2578
|
+
}
|
|
2579
|
+
return;
|
|
2580
|
+
}
|
|
2581
|
+
if (spotId === null) {
|
|
2582
|
+
return;
|
|
2583
|
+
}
|
|
2584
|
+
const activation = this.activations.resolve(meshName, spotId);
|
|
2585
|
+
if (activation === undefined) {
|
|
2586
|
+
return;
|
|
2587
|
+
}
|
|
2588
|
+
await activation.serial.execute(async () => {
|
|
2589
|
+
if (control.lifecycleKind === ActorLifecycleKind.Joined) {
|
|
2590
|
+
if (control.currentActor !== null) {
|
|
2591
|
+
this.options.actorTransferRuntime?.bindRoutedActorRef(
|
|
2592
|
+
actor,
|
|
2593
|
+
control.currentActor as unknown as ActorRef
|
|
2594
|
+
);
|
|
2595
|
+
}
|
|
2596
|
+
this.options.actorTransferRuntime?.commitRoutedActor(actor, spotId, activation.spot);
|
|
2597
|
+
const completeTargetLifecycle = async (): Promise<void> => {
|
|
2598
|
+
await this.options.actorTransferRuntime?.claimRoutedActorLocation(
|
|
2599
|
+
actor,
|
|
2600
|
+
spotId,
|
|
2601
|
+
meshName,
|
|
2602
|
+
{
|
|
2603
|
+
spotGeneration: control.currentSpotGeneration,
|
|
2604
|
+
membershipEpoch: control.currentMembershipEpoch
|
|
2605
|
+
}
|
|
2606
|
+
);
|
|
2607
|
+
// Make the Actor resolvable for lifecycle and saved-work dispatch,
|
|
2608
|
+
// while formalRemoteTransfers continues to fence new ingress until
|
|
2609
|
+
// the saved backlog has completed.
|
|
2610
|
+
activation.commitActorJoin(actor);
|
|
2611
|
+
await activation.spot.onJoinedActor(actor);
|
|
2612
|
+
};
|
|
2613
|
+
const completePublicJoin = async (): Promise<void> => {
|
|
2614
|
+
const deferredJoinRoot = pendingTransfer?.deferredJoinRoot;
|
|
2615
|
+
if (deferredJoinRoot !== undefined) {
|
|
2616
|
+
const currentRef = this.options.actorTransferRuntime === undefined
|
|
2617
|
+
? null
|
|
2618
|
+
: control.currentActor as unknown as ActorRef | null;
|
|
2619
|
+
if (currentRef === null) {
|
|
2620
|
+
throw new Error(`Actor '${actor.context.actorId}' has no target ref for deferred Join completion.`);
|
|
2621
|
+
}
|
|
2622
|
+
await this.options.actorTransferRuntime?.commitAndDeliverDeferredJoinAccepted(
|
|
2623
|
+
deferredJoinRoot,
|
|
2624
|
+
actor,
|
|
2625
|
+
currentRef,
|
|
2626
|
+
operation => activation.executeActor(
|
|
2627
|
+
actor.context.actorId,
|
|
2628
|
+
async () => await operation()
|
|
2629
|
+
)
|
|
2630
|
+
);
|
|
2631
|
+
}
|
|
2632
|
+
};
|
|
2633
|
+
const completeTargetReady = async (): Promise<void> => {
|
|
2634
|
+
if (pendingTransfer !== undefined) {
|
|
2635
|
+
const handoffResults = await replayActorHandoffBacklog(
|
|
2636
|
+
pendingTransfer.handoffBacklog,
|
|
2637
|
+
(parts, returnResponse, remoteBoundSessionTarget, _fallbackActorRef) =>
|
|
2638
|
+
this.dispatchActorPacket(
|
|
2639
|
+
activation,
|
|
2640
|
+
actor.context.actorId,
|
|
2641
|
+
parts,
|
|
2642
|
+
returnResponse,
|
|
2643
|
+
remoteBoundSessionTarget,
|
|
2644
|
+
undefined
|
|
2645
|
+
),
|
|
2646
|
+
(index) => this.options.runtimeEventPublisher?.publish({
|
|
2647
|
+
sourceName: 'zlink.framework.actor-handoff',
|
|
2648
|
+
timestamp: new Date(),
|
|
2649
|
+
marker: 'backlog_enqueued',
|
|
2650
|
+
actorId: actor.context.actorId,
|
|
2651
|
+
index
|
|
2652
|
+
})
|
|
2653
|
+
);
|
|
2654
|
+
const failedHandoff = handoffResults.find(result => !result.ok);
|
|
2655
|
+
if (failedHandoff !== undefined) {
|
|
2656
|
+
throw new Error(
|
|
2657
|
+
`Actor '${actor.context.actorId}' saved handoff packet `
|
|
2658
|
+
+ `${failedHandoff.index} failed: ${failedHandoff.error ?? 'unknown error'}.`
|
|
2659
|
+
);
|
|
2660
|
+
}
|
|
2661
|
+
// Spec 15 §4.2 relocation temporary queue: arrivals parked at
|
|
2662
|
+
// this target directly (not relayed through the source's
|
|
2663
|
+
// ingress hold) migrate into the real Actor queue next, in the
|
|
2664
|
+
// order they parked — after the relayed backlog above, before
|
|
2665
|
+
// regular ingress opens.
|
|
2666
|
+
await this.migrateActorJoinPrewarm(activation, actor, pendingTransfer.transferId);
|
|
2667
|
+
// This registry owns target lifecycle and saved backlog
|
|
2668
|
+
// reconciliation only. Session route readiness is enforced by
|
|
2669
|
+
// the Session binding aggregate after this boundary.
|
|
2670
|
+
this.formalRemoteTransfers.delete(actor.context.actorId);
|
|
2671
|
+
}
|
|
2672
|
+
const updateBoundSessionRoute = async (): Promise<void> => {
|
|
2673
|
+
await this.options.actorTransferRuntime?.publishRoutedActorOwnership(actor);
|
|
2674
|
+
await this.options.actorTransferRuntime?.openRoutedActorSession(actor);
|
|
2675
|
+
};
|
|
2676
|
+
// Session routing is an independent post-Ready branch. Callback
|
|
2677
|
+
// sends are retained by the Session owner seal until this converges.
|
|
2678
|
+
if (pendingTransfer !== undefined && this.options.detachedTaskRunner !== undefined) {
|
|
2679
|
+
this.options.detachedTaskRunner.runDetached(
|
|
2680
|
+
`actor transfer Session route ${actor.context.actorId}`,
|
|
2681
|
+
updateBoundSessionRoute
|
|
2682
|
+
);
|
|
2683
|
+
} else {
|
|
2684
|
+
await updateBoundSessionRoute();
|
|
2685
|
+
}
|
|
2686
|
+
};
|
|
2687
|
+
if (pendingTransfer !== undefined) {
|
|
2688
|
+
const resume = async (): Promise<void> => {
|
|
2689
|
+
try {
|
|
2690
|
+
await activation.serial.post(completeTargetLifecycle);
|
|
2691
|
+
} finally {
|
|
2692
|
+
this.formalRemoteTransfers.completeTargetLifecycle(
|
|
2693
|
+
actor.context.actorId,
|
|
2694
|
+
pendingTransfer.transferId
|
|
2695
|
+
);
|
|
2696
|
+
}
|
|
2697
|
+
const sourceLeaveSubmitted = await pendingTransfer.sourceLeaveSubmitted;
|
|
2698
|
+
if (!sourceLeaveSubmitted) {
|
|
2699
|
+
throw new Error(
|
|
2700
|
+
`Actor '${actor.context.actorId}' source authority commit failed before leave submission.`
|
|
2701
|
+
);
|
|
2702
|
+
}
|
|
2703
|
+
await completePublicJoin();
|
|
2704
|
+
// Saved handlers enter the Spot owner on their own turns. Run
|
|
2705
|
+
// them only after the lifecycle turn above has been released.
|
|
2706
|
+
await completeTargetReady();
|
|
2707
|
+
};
|
|
2708
|
+
this.options.detachedTaskRunner?.runDetached(
|
|
2709
|
+
`actor transfer target commit ${actor.context.actorId}`,
|
|
2710
|
+
resume
|
|
2711
|
+
);
|
|
2712
|
+
if (this.options.detachedTaskRunner === undefined) {
|
|
2713
|
+
void resume().catch(() => undefined);
|
|
2714
|
+
}
|
|
2715
|
+
return;
|
|
2716
|
+
}
|
|
2717
|
+
await completeTargetLifecycle();
|
|
2718
|
+
await completePublicJoin();
|
|
2719
|
+
await completeTargetReady();
|
|
2720
|
+
return;
|
|
2721
|
+
}
|
|
2722
|
+
if (control.lifecycleKind === ActorLifecycleKind.Left) {
|
|
2723
|
+
if (this.options.actorTransferRuntime === undefined) {
|
|
2724
|
+
await activation.spot.onLeaveActor(actor);
|
|
2725
|
+
} else {
|
|
2726
|
+
// Spot.Context.leaveActor can run the source callback before the
|
|
2727
|
+
// native Entry join is submitted. In that path the membership is
|
|
2728
|
+
// already committed away, so a later Core LEFT control must not
|
|
2729
|
+
// execute the same callback twice.
|
|
2730
|
+
if (sourceJoinedActor === undefined && pendingTransfer === undefined) {
|
|
2731
|
+
return;
|
|
2732
|
+
}
|
|
2733
|
+
await this.options.actorTransferRuntime.notifyCoreSourceLeave(
|
|
2734
|
+
actor,
|
|
2735
|
+
() => activation.spot.onLeaveActor(actor)
|
|
2736
|
+
);
|
|
2737
|
+
}
|
|
2738
|
+
activation.commitActorDeparture(actor.context.actorId);
|
|
2739
|
+
return;
|
|
2740
|
+
}
|
|
2741
|
+
if (control.lifecycleKind === ActorLifecycleKind.Disconnected) {
|
|
2742
|
+
await activation.spot.onDisconnectActor?.(actor);
|
|
2743
|
+
}
|
|
2744
|
+
});
|
|
2745
|
+
}
|
|
2746
|
+
|
|
2747
|
+
async completeFormalSourceLeaveTerminal(
|
|
2748
|
+
actorId: string,
|
|
2749
|
+
transferId: string,
|
|
2750
|
+
succeeded: boolean
|
|
2751
|
+
): Promise<boolean> {
|
|
2752
|
+
return await this.formalRemoteTransfers.completeSourceLeaveTerminal(
|
|
2753
|
+
actorId,
|
|
2754
|
+
transferId,
|
|
2755
|
+
succeeded
|
|
2756
|
+
);
|
|
2757
|
+
}
|
|
2758
|
+
|
|
2759
|
+
async finalizeActorJoinRelocation(
|
|
2760
|
+
meshName: string,
|
|
2761
|
+
relocationId: string,
|
|
2762
|
+
actor: ZLinkActor,
|
|
2763
|
+
actorRef: ActorRef,
|
|
2764
|
+
submitSourceLeave: (sourceNodeRid: RoutingId) => Promise<void>,
|
|
2765
|
+
signal?: AbortSignal
|
|
2766
|
+
): Promise<boolean> {
|
|
2767
|
+
throwIfAborted(signal);
|
|
2768
|
+
const admission = this.formalRemoteActorAdmissions.get(relocationId);
|
|
2769
|
+
if (admission === undefined) return false;
|
|
2770
|
+
if (admission.admission.actorId !== actor.context.actorId) {
|
|
2771
|
+
throw new Error(`Actor Join relocation '${relocationId}' changed its admitted Actor.`);
|
|
2772
|
+
}
|
|
2773
|
+
const outcome = admission.result ?? await admission.resultTask;
|
|
2774
|
+
if ('error' in outcome) throw outcome.error;
|
|
2775
|
+
if (!outcome.accepted || admission.state !== 'admitted') {
|
|
2776
|
+
throw new Error(`Actor Join relocation '${relocationId}' has no accepted admission.`);
|
|
2777
|
+
}
|
|
2778
|
+
const entrySpotId = this.options.entryNodeRidProvider?.() ?? this.options.entryNodeRid;
|
|
2779
|
+
const targetsEntry = entrySpotId !== undefined
|
|
2780
|
+
&& String(admission.admission.spotId) === String(entrySpotId);
|
|
2781
|
+
if (targetsEntry) {
|
|
2782
|
+
await this.options.dispatchEntryActorJoin?.(meshName, actor, []);
|
|
2783
|
+
} else {
|
|
2784
|
+
const activation = this.activations.resolve(meshName, admission.admission.spotId);
|
|
2785
|
+
if (activation === undefined) {
|
|
2786
|
+
throw new Error(`Actor Join relocation '${relocationId}' target Spot is not active.`);
|
|
2787
|
+
}
|
|
2788
|
+
await activation.serial.execute(() => activation.spot.onJoinedActor(actor));
|
|
2789
|
+
}
|
|
2790
|
+
await submitSourceLeave(admission.admission.actorRef.nodeRid);
|
|
2791
|
+
if (outcome.deferredJoinRoot !== undefined && this.options.actorTransferRuntime !== undefined) {
|
|
2792
|
+
const submitMailbox = targetsEntry
|
|
2793
|
+
? <T>(operation: () => Promise<T>): Promise<T> => operation()
|
|
2794
|
+
: <T>(operation: () => Promise<T>): Promise<T> => {
|
|
2795
|
+
const activation = this.activations.resolve(meshName, admission.admission.spotId);
|
|
2796
|
+
if (activation === undefined) {
|
|
2797
|
+
throw new Error(`Actor Join relocation '${relocationId}' target mailbox is missing.`);
|
|
2798
|
+
}
|
|
2799
|
+
return activation.executeActor(actor.context.actorId, operation);
|
|
2800
|
+
};
|
|
2801
|
+
await this.options.actorTransferRuntime.commitAndDeliverDeferredJoinAccepted(
|
|
2802
|
+
outcome.deferredJoinRoot,
|
|
2803
|
+
actor,
|
|
2804
|
+
actorRef,
|
|
2805
|
+
submitMailbox,
|
|
2806
|
+
signal
|
|
2807
|
+
);
|
|
2808
|
+
}
|
|
2809
|
+
this.formalRemoteActorAdmissions.markCommitted(relocationId, actor);
|
|
2810
|
+
return true;
|
|
2811
|
+
}
|
|
2812
|
+
|
|
2813
|
+
async restoreCanonicalActorJoinRecovery(
|
|
2814
|
+
recovery: CanonicalActorJoinRecovery,
|
|
2815
|
+
signal?: AbortSignal,
|
|
2816
|
+
canonicalInventoryDigest?: string
|
|
2817
|
+
): Promise<ZLinkDeferredJoinAcceptedRoot | undefined> {
|
|
2818
|
+
throwIfAborted(signal);
|
|
2819
|
+
const admission = this.formalRemoteActorAdmissions.get(recovery.request.handoffId);
|
|
2820
|
+
if (admission === undefined) {
|
|
2821
|
+
throw new Error(
|
|
2822
|
+
`Actor Join recovery '${recovery.request.handoffId}' has no canonical command-28 admission.`
|
|
2823
|
+
);
|
|
2824
|
+
}
|
|
2825
|
+
const outcome = admission.result ?? await admission.resultTask;
|
|
2826
|
+
if ('error' in outcome || !outcome.accepted || admission.state !== 'admitted') {
|
|
2827
|
+
throw new Error(
|
|
2828
|
+
`Actor Join recovery '${recovery.request.handoffId}' has no accepted admission.`
|
|
2829
|
+
);
|
|
2830
|
+
}
|
|
2831
|
+
const admitted = admission.admission;
|
|
2832
|
+
if (admitted.sourceActorNodeRid === undefined) {
|
|
2833
|
+
throw new Error(
|
|
2834
|
+
`Actor Join recovery '${recovery.request.handoffId}' lost its command-28 source route.`
|
|
2835
|
+
);
|
|
2836
|
+
}
|
|
2837
|
+
const admittedNodeBytes = Buffer.from(
|
|
2838
|
+
encodeRoutingIdStorageHex(admitted.sourceActorNodeRid),
|
|
2839
|
+
'hex'
|
|
2840
|
+
);
|
|
2841
|
+
if (
|
|
2842
|
+
admitted.actorId !== recovery.request.actorId
|
|
2843
|
+
|| admitted.actorType !== recovery.request.actorType
|
|
2844
|
+
|| admitted.requestFingerprint !== recovery.request.request.toString('base64')
|
|
2845
|
+
|| String(admitted.spotId) !== recovery.targetSpotId
|
|
2846
|
+
|| admitted.targetSpotGeneration !== recovery.targetSpotGeneration
|
|
2847
|
+
|| admitted.actorRef.objectGeneration !== recovery.request.actorGeneration
|
|
2848
|
+
|| !admittedNodeBytes.equals(recovery.request.sourceNodeRid)
|
|
2849
|
+
) {
|
|
2850
|
+
throw new Error(
|
|
2851
|
+
`Actor Join recovery '${recovery.request.handoffId}' changed its command-28 identity.`
|
|
2852
|
+
);
|
|
2853
|
+
}
|
|
2854
|
+
const admittedReply = outcome.reply ?? Buffer.alloc(0);
|
|
2855
|
+
if (!admittedReply.equals(recovery.reply)) {
|
|
2856
|
+
throw new Error(
|
|
2857
|
+
`Actor Join recovery '${recovery.request.handoffId}' changed its admission reply.`
|
|
2858
|
+
);
|
|
2859
|
+
}
|
|
2860
|
+
if (recovery.operationId === undefined) {
|
|
2861
|
+
if (recovery.replyContentType !== undefined || recovery.reply.byteLength !== 0) {
|
|
2862
|
+
throw new Error(
|
|
2863
|
+
`Actor Join recovery '${recovery.request.handoffId}' has a reply without an OperationId.`
|
|
2864
|
+
);
|
|
2865
|
+
}
|
|
2866
|
+
return;
|
|
2867
|
+
}
|
|
2868
|
+
const outerReplyContentType = admittedReply.byteLength === 0
|
|
2869
|
+
? recovery.replyContentType
|
|
2870
|
+
: SERVICE_FRAMEWORK_MULTIPART_CONTENT_TYPE;
|
|
2871
|
+
if (recovery.replyContentType !== outerReplyContentType) {
|
|
2872
|
+
throw new Error(
|
|
2873
|
+
`Actor Join recovery '${recovery.request.handoffId}' changed its reply content type.`
|
|
2874
|
+
);
|
|
2875
|
+
}
|
|
2876
|
+
// Command 28 carries a present reply in one outer framework-multipart
|
|
2877
|
+
// part. The accepted target admission still owns the inner typed content
|
|
2878
|
+
// type, which the durable completion must retain for application decode.
|
|
2879
|
+
const admittedContentType = admittedReply.byteLength === 0
|
|
2880
|
+
? recovery.replyContentType
|
|
2881
|
+
: outcome.replyContentType;
|
|
2882
|
+
const transfer = this.options.actorTransferRuntime;
|
|
2883
|
+
if (transfer === undefined) {
|
|
2884
|
+
throw new Error('Canonical Actor Join recovery requires the Actor transfer runtime.');
|
|
2885
|
+
}
|
|
2886
|
+
const deferred = await transfer.prepareDeferredJoinAccepted(
|
|
2887
|
+
recovery.request.actorId,
|
|
2888
|
+
recovery.operationId,
|
|
2889
|
+
admitted.actorRef,
|
|
2890
|
+
recovery.reply,
|
|
2891
|
+
admittedContentType,
|
|
2892
|
+
signal,
|
|
2893
|
+
canonicalInventoryDigest
|
|
2894
|
+
);
|
|
2895
|
+
this.formalRemoteActorAdmissions.attachDeferredJoinRoot(
|
|
2896
|
+
recovery.request.handoffId,
|
|
2897
|
+
deferred
|
|
2898
|
+
);
|
|
2899
|
+
return deferred;
|
|
2900
|
+
}
|
|
2901
|
+
|
|
2902
|
+
private encodeMeshActorReply(
|
|
2903
|
+
requestHeaderPart: Message,
|
|
2904
|
+
kind: ZLinkStreamMessageKind.Response | ZLinkStreamMessageKind.Error,
|
|
2905
|
+
payload: unknown
|
|
2906
|
+
): readonly Buffer[] {
|
|
2907
|
+
// Spec 27 §4/§7: the decode gate strips the observation-only flow pair at
|
|
2908
|
+
// Off (and skips its validation); when tracing is on the reply preserves
|
|
2909
|
+
// the request's flow pair alongside its correlation.
|
|
2910
|
+
const requestHeader = decodeStreamHeader(
|
|
2911
|
+
requestHeaderPart.data(),
|
|
2912
|
+
this.options.dispatchErrors?.flow.flowCreationEnabled() ?? true
|
|
2913
|
+
);
|
|
2914
|
+
const encoded = encodeFrameworkPayload(payload, this.options.messageSerializers);
|
|
2915
|
+
try {
|
|
2916
|
+
// encodeStreamHeader returns a fresh, unaliased array; view it without
|
|
2917
|
+
// re-copying. The payload copy stays: encoded.message closes below.
|
|
2918
|
+
const replyHeader = encodeStreamHeader({
|
|
2919
|
+
kind,
|
|
2920
|
+
codec: streamCodecForContentType(encoded.contentType),
|
|
2921
|
+
flags: ZLinkStreamHeaderFlags.None,
|
|
2922
|
+
requestSeq: requestHeader.requestSeq,
|
|
2923
|
+
name: '',
|
|
2924
|
+
metadata: new Map(),
|
|
2925
|
+
correlationId: requestHeader.correlationId,
|
|
2926
|
+
flowId: requestHeader.flowId,
|
|
2927
|
+
flowOrigin: requestHeader.flowOrigin
|
|
2928
|
+
});
|
|
2929
|
+
return [
|
|
2930
|
+
Buffer.from(replyHeader.buffer, replyHeader.byteOffset, replyHeader.byteLength),
|
|
2931
|
+
Buffer.from(encoded.message.data())
|
|
2932
|
+
];
|
|
2933
|
+
} finally {
|
|
2934
|
+
encoded.message.close();
|
|
2935
|
+
}
|
|
2936
|
+
}
|
|
2937
|
+
|
|
2938
|
+
private async createActivation<TSpot extends ZLinkSpot>(
|
|
2939
|
+
meshName: string,
|
|
2940
|
+
spotType: Type<TSpot>,
|
|
2941
|
+
spotId: RoutingId,
|
|
2942
|
+
request: Message,
|
|
2943
|
+
signal?: AbortSignal,
|
|
2944
|
+
authority?: ZLinkNativeSpotAuthority
|
|
2945
|
+
): Promise<ZLinkLocalSpotCreateResult> {
|
|
2946
|
+
this.requireRegisteredFactory(spotType);
|
|
2947
|
+
return await this.activationLifecycle.create(
|
|
2948
|
+
meshName,
|
|
2949
|
+
spotType,
|
|
2950
|
+
spotId,
|
|
2951
|
+
request,
|
|
2952
|
+
signal,
|
|
2953
|
+
authority
|
|
2954
|
+
);
|
|
2955
|
+
}
|
|
2956
|
+
|
|
2957
|
+
private requireRegisteredFactory(spotType: Type<ZLinkSpot>): void {
|
|
2958
|
+
if (!this.factories.has(spotType)) {
|
|
2959
|
+
throw new ZLinkConfigurationException('Spot type is not registered as a spot factory.');
|
|
2960
|
+
}
|
|
2961
|
+
}
|
|
2962
|
+
|
|
2963
|
+
private async dispatchActorPacket(
|
|
2964
|
+
activation: ZLinkSpotActivation,
|
|
2965
|
+
actorId: string,
|
|
2966
|
+
parts: readonly Message[],
|
|
2967
|
+
returnResponse = false,
|
|
2968
|
+
remoteBoundSessionTarget?: ZLinkRemoteBoundSessionTarget,
|
|
2969
|
+
fallbackActorRef?: ActorRef,
|
|
2970
|
+
requestTerminal?: (response: unknown) => Promise<void> | void,
|
|
2971
|
+
messageFollowOrigin?: ZLinkMessageFollowOrigin
|
|
2972
|
+
): Promise<unknown> {
|
|
2973
|
+
return await this.activationLifecycle.dispatchActorPacket(
|
|
2974
|
+
activation,
|
|
2975
|
+
actorId,
|
|
2976
|
+
parts,
|
|
2977
|
+
returnResponse,
|
|
2978
|
+
remoteBoundSessionTarget,
|
|
2979
|
+
fallbackActorRef,
|
|
2980
|
+
requestTerminal,
|
|
2981
|
+
messageFollowOrigin
|
|
2982
|
+
);
|
|
2983
|
+
}
|
|
2984
|
+
|
|
2985
|
+
/**
|
|
2986
|
+
* Spec 15 §4.2 relocation temporary queue: drains every arrival parked
|
|
2987
|
+
* for this exact Actor Join admission attempt since Accepted, in order,
|
|
2988
|
+
* dispatching each one for real now that the Actor has cut over locally.
|
|
2989
|
+
* {@link ZLinkFormalRemoteActorAdmissionRegistry#completeMigration}
|
|
2990
|
+
* synchronously snapshots the parked queue and flips the attempt to
|
|
2991
|
+
* `migrated` before this method dispatches anything, so a racing arrival
|
|
2992
|
+
* either lands in the snapshot or resolves the Actor directly through
|
|
2993
|
+
* ordinary ingress — never both, never neither.
|
|
2994
|
+
*/
|
|
2995
|
+
private async migrateActorJoinPrewarm(
|
|
2996
|
+
activation: ZLinkSpotActivation,
|
|
2997
|
+
actor: ZLinkActor,
|
|
2998
|
+
transferId: string
|
|
2999
|
+
): Promise<void> {
|
|
3000
|
+
const drained = this.formalRemoteActorAdmissions.completeMigration(transferId);
|
|
3001
|
+
for (const arrival of drained) {
|
|
3002
|
+
try {
|
|
3003
|
+
const response = await this.dispatchActorPacket(
|
|
3004
|
+
activation,
|
|
3005
|
+
actor.context.actorId,
|
|
3006
|
+
[
|
|
3007
|
+
RuntimeMessage.from(arrival.header),
|
|
3008
|
+
RuntimeMessage.from(arrival.payload)
|
|
3009
|
+
],
|
|
3010
|
+
arrival.returnResponse,
|
|
3011
|
+
arrival.remoteBoundSessionTarget,
|
|
3012
|
+
arrival.fallbackActorRef,
|
|
3013
|
+
arrival.requestTerminal
|
|
3014
|
+
);
|
|
3015
|
+
arrival.resolve(response);
|
|
3016
|
+
} catch (error) {
|
|
3017
|
+
arrival.reject(error);
|
|
3018
|
+
}
|
|
3019
|
+
}
|
|
3020
|
+
}
|
|
3021
|
+
|
|
3022
|
+
private async dispatchMeshActorPacket(
|
|
3023
|
+
meshName: string,
|
|
3024
|
+
spotId: RoutingId,
|
|
3025
|
+
actorId: string,
|
|
3026
|
+
parts: readonly Message[],
|
|
3027
|
+
returnResponse: boolean,
|
|
3028
|
+
fallbackActorRef?: ActorRef,
|
|
3029
|
+
requestTerminal?: (response: unknown) => Promise<void> | void,
|
|
3030
|
+
messageFollowOrigin?: ZLinkMessageFollowOrigin
|
|
3031
|
+
): Promise<unknown> {
|
|
3032
|
+
const activation = this.activations.resolve(meshName, spotId);
|
|
3033
|
+
if (activation === undefined) {
|
|
3034
|
+
throw new ZLinkConfigurationException(
|
|
3035
|
+
`Spot '${String(spotId)}' is not active in mesh '${meshName}'.`
|
|
3036
|
+
);
|
|
3037
|
+
}
|
|
3038
|
+
return await this.dispatchActorPacket(
|
|
3039
|
+
activation,
|
|
3040
|
+
actorId,
|
|
3041
|
+
parts,
|
|
3042
|
+
returnResponse,
|
|
3043
|
+
undefined,
|
|
3044
|
+
fallbackActorRef,
|
|
3045
|
+
requestTerminal,
|
|
3046
|
+
messageFollowOrigin
|
|
3047
|
+
);
|
|
3048
|
+
}
|
|
3049
|
+
|
|
3050
|
+
}
|
|
3051
|
+
|
|
3052
|
+
function instanceDispatchErrorReason(error: unknown): ZLinkDispatchErrorReason {
|
|
3053
|
+
if (error instanceof ZLinkFrameworkException) {
|
|
3054
|
+
const kind = internalFrameworkErrorKind(error);
|
|
3055
|
+
if (
|
|
3056
|
+
kind === ZLinkFrameworkInternalErrorKind.SpotGenerationStale
|
|
3057
|
+
|| kind === ZLinkFrameworkInternalErrorKind.SpotMoving
|
|
3058
|
+
|| kind === ZLinkFrameworkInternalErrorKind.SpotRouteNotFound
|
|
3059
|
+
|| kind === ZLinkFrameworkInternalErrorKind.RequestTargetNotFound
|
|
3060
|
+
) {
|
|
3061
|
+
return ZLinkDispatchErrorReason.StaleTarget;
|
|
3062
|
+
}
|
|
3063
|
+
}
|
|
3064
|
+
return ZLinkDispatchErrorReason.HandlerException;
|
|
3065
|
+
}
|
|
3066
|
+
|
|
3067
|
+
interface ZLinkFormalRemoteTransferRequest {
|
|
3068
|
+
readonly actorType: string;
|
|
3069
|
+
readonly actorId?: string;
|
|
3070
|
+
readonly phase?: 'admission' | 'commit' | 'abort';
|
|
3071
|
+
readonly transferId: string;
|
|
3072
|
+
readonly transferAdapterKey?: string;
|
|
3073
|
+
readonly transferState?: string;
|
|
3074
|
+
readonly request: string;
|
|
3075
|
+
readonly requestContentType: string;
|
|
3076
|
+
readonly actorEntryNodeRid?: RoutingId;
|
|
3077
|
+
readonly sourceSpotId?: RoutingId;
|
|
3078
|
+
readonly actorRef?: ActorRef;
|
|
3079
|
+
readonly remoteBoundSessionTarget?: ZLinkRemoteBoundSessionTarget;
|
|
3080
|
+
readonly expectedMembershipEpoch: bigint;
|
|
3081
|
+
readonly handoffBacklog: readonly ZLinkActorHandoffPacket[];
|
|
3082
|
+
readonly completionOperationId?: {
|
|
3083
|
+
readonly high: bigint;
|
|
3084
|
+
readonly low: bigint;
|
|
3085
|
+
};
|
|
3086
|
+
}
|
|
3087
|
+
|
|
3088
|
+
function decodeFormalRemoteTransferRequest(
|
|
3089
|
+
message: Message
|
|
3090
|
+
): ZLinkFormalRemoteTransferRequest | undefined {
|
|
3091
|
+
return decodeFormalRemoteTransferRequestBytes(message.data());
|
|
3092
|
+
}
|
|
3093
|
+
|
|
3094
|
+
function decodeFormalRemoteTransferRequestBytes(
|
|
3095
|
+
bytes: Uint8Array
|
|
3096
|
+
): ZLinkFormalRemoteTransferRequest | undefined {
|
|
3097
|
+
let payload: ZLinkRemoteActorJoinWirePayload;
|
|
3098
|
+
try {
|
|
3099
|
+
payload = JSON.parse(Buffer.from(bytes).toString()) as ZLinkRemoteActorJoinWirePayload;
|
|
3100
|
+
} catch {
|
|
3101
|
+
return undefined;
|
|
3102
|
+
}
|
|
3103
|
+
if (
|
|
3104
|
+
payload.packetName !== REMOTE_ACTOR_JOIN_PACKET
|
|
3105
|
+
|| typeof payload.actorType !== 'string'
|
|
3106
|
+
|| typeof payload.transferId !== 'string'
|
|
3107
|
+
|| !(
|
|
3108
|
+
payload.phase === REMOTE_ACTOR_JOIN_ADMISSION
|
|
3109
|
+
|| payload.phase === REMOTE_ACTOR_JOIN_ABORT
|
|
3110
|
+
|| payload.phase === REMOTE_ACTOR_JOIN_COMMIT
|
|
3111
|
+
|| payload.phase === undefined
|
|
3112
|
+
)
|
|
3113
|
+
|| !(
|
|
3114
|
+
payload.phase === REMOTE_ACTOR_JOIN_ADMISSION
|
|
3115
|
+
|| payload.phase === REMOTE_ACTOR_JOIN_ABORT
|
|
3116
|
+
|| (
|
|
3117
|
+
typeof payload.transferState === 'string'
|
|
3118
|
+
)
|
|
3119
|
+
)
|
|
3120
|
+
|| typeof payload.request !== 'string'
|
|
3121
|
+
) {
|
|
3122
|
+
return undefined;
|
|
3123
|
+
}
|
|
3124
|
+
return {
|
|
3125
|
+
actorType: payload.actorType,
|
|
3126
|
+
actorId: typeof payload.actorId === 'string' ? payload.actorId : undefined,
|
|
3127
|
+
phase: payload.phase === REMOTE_ACTOR_JOIN_ADMISSION
|
|
3128
|
+
|| payload.phase === REMOTE_ACTOR_JOIN_COMMIT
|
|
3129
|
+
|| payload.phase === REMOTE_ACTOR_JOIN_ABORT
|
|
3130
|
+
? payload.phase
|
|
3131
|
+
: undefined,
|
|
3132
|
+
transferId: payload.transferId,
|
|
3133
|
+
transferAdapterKey: typeof payload.transferAdapterKey === 'string'
|
|
3134
|
+
? payload.transferAdapterKey
|
|
3135
|
+
: undefined,
|
|
3136
|
+
transferState: typeof payload.transferState === 'string'
|
|
3137
|
+
? payload.transferState
|
|
3138
|
+
: undefined,
|
|
3139
|
+
request: payload.request,
|
|
3140
|
+
requestContentType: typeof payload.requestContentType === 'string'
|
|
3141
|
+
? payload.requestContentType
|
|
3142
|
+
: 'application/json',
|
|
3143
|
+
actorEntryNodeRid: typeof payload.actorEntryNodeRid === 'string'
|
|
3144
|
+
? decodeRoutingId(payload.actorEntryNodeRid, payload.actorEntryNodeRidHex)
|
|
3145
|
+
: undefined,
|
|
3146
|
+
sourceSpotId: typeof payload.sourceSpotId === 'string'
|
|
3147
|
+
? payload.sourceSpotId as RoutingId
|
|
3148
|
+
: undefined,
|
|
3149
|
+
actorRef: decodeFormalRemoteActorRef(payload),
|
|
3150
|
+
remoteBoundSessionTarget: decodeRemoteBoundSessionTarget(
|
|
3151
|
+
payload.boundSessionRouterChannelId,
|
|
3152
|
+
payload.boundSessionTargetNodeRid,
|
|
3153
|
+
payload.boundSessionTargetNodeRidHex,
|
|
3154
|
+
payload.boundSessionSpotId,
|
|
3155
|
+
payload.boundSessionNodeRid,
|
|
3156
|
+
payload.boundSessionNodeRidHex,
|
|
3157
|
+
payload.boundSessionRid,
|
|
3158
|
+
payload.boundSessionRidHex,
|
|
3159
|
+
payload.boundSessionBindingGeneration,
|
|
3160
|
+
payload.boundSessionPreviousAuthorityOwnerGeneration,
|
|
3161
|
+
payload.boundSessionPreviousOwnerLeaseGeneration,
|
|
3162
|
+
payload.boundSessionRelocationSealId,
|
|
3163
|
+
payload.boundSessionServiceWireRelocation
|
|
3164
|
+
),
|
|
3165
|
+
expectedMembershipEpoch: typeof payload.expectedMembershipEpoch === 'string'
|
|
3166
|
+
? BigInt(payload.expectedMembershipEpoch)
|
|
3167
|
+
: 0n,
|
|
3168
|
+
handoffBacklog: decodeHandoffBacklog(payload.handoffBacklog),
|
|
3169
|
+
completionOperationId:
|
|
3170
|
+
typeof payload.completionOperationHigh === 'string'
|
|
3171
|
+
&& typeof payload.completionOperationLow === 'string'
|
|
3172
|
+
? {
|
|
3173
|
+
high: BigInt(payload.completionOperationHigh),
|
|
3174
|
+
low: BigInt(payload.completionOperationLow)
|
|
3175
|
+
}
|
|
3176
|
+
: undefined
|
|
3177
|
+
};
|
|
3178
|
+
}
|
|
3179
|
+
|
|
3180
|
+
function decodeFormalRemoteActorRef(
|
|
3181
|
+
payload: ZLinkRemoteActorJoinWirePayload
|
|
3182
|
+
): ActorRef | undefined {
|
|
3183
|
+
const backend = decodeRemoteActorRef(
|
|
3184
|
+
payload.actorNodeRid,
|
|
3185
|
+
payload.actorNodeRidHex,
|
|
3186
|
+
typeof payload.actorId === 'string' ? payload.actorId : '',
|
|
3187
|
+
payload.actorGeneration
|
|
3188
|
+
);
|
|
3189
|
+
if (backend === undefined || typeof payload.routerChannelId !== 'string') {
|
|
3190
|
+
return undefined;
|
|
3191
|
+
}
|
|
3192
|
+
return {
|
|
3193
|
+
actorId: backend.actorId,
|
|
3194
|
+
objectGeneration: backend.generation,
|
|
3195
|
+
meshName: payload.routerChannelId,
|
|
3196
|
+
nodeRid: backend.nodeRid as unknown as RoutingId
|
|
3197
|
+
};
|
|
3198
|
+
}
|
|
3199
|
+
|
|
3200
|
+
|
|
3201
|
+
function requireMeshSpotReply(result: number): void {
|
|
3202
|
+
if (result !== SubmitResult.Ok) {
|
|
3203
|
+
throw new ZLinkConfigurationException(
|
|
3204
|
+
`MeshNode reply was not accepted (submit result ${result}).`
|
|
3205
|
+
);
|
|
3206
|
+
}
|
|
3207
|
+
}
|
|
3208
|
+
|
|
3209
|
+
function toFrameworkRemoteAdmissionActorRef(
|
|
3210
|
+
rawActorRef: {
|
|
3211
|
+
readonly actorId: string;
|
|
3212
|
+
readonly nodeRid: unknown;
|
|
3213
|
+
readonly objectGeneration?: bigint;
|
|
3214
|
+
readonly generation?: bigint;
|
|
3215
|
+
},
|
|
3216
|
+
meshName: string
|
|
3217
|
+
): ActorRef {
|
|
3218
|
+
const objectGeneration = rawActorRef.objectGeneration ?? rawActorRef.generation;
|
|
3219
|
+
if (objectGeneration === undefined) {
|
|
3220
|
+
throw new ZLinkConfigurationException(
|
|
3221
|
+
`Actor '${rawActorRef.actorId}' join record has no ObjectGeneration.`
|
|
3222
|
+
);
|
|
3223
|
+
}
|
|
3224
|
+
return {
|
|
3225
|
+
actorId: rawActorRef.actorId,
|
|
3226
|
+
objectGeneration,
|
|
3227
|
+
meshName,
|
|
3228
|
+
nodeRid: rawActorRef.nodeRid as RoutingId
|
|
3229
|
+
};
|
|
3230
|
+
}
|
|
3231
|
+
|
|
3232
|
+
function validateRemoteAdmissionCommit(
|
|
3233
|
+
admission: ZLinkFormalRemoteActorAdmissionRecord,
|
|
3234
|
+
request: ZLinkFormalRemoteTransferRequest,
|
|
3235
|
+
actorId: string,
|
|
3236
|
+
control: { readonly currentSpotGeneration?: bigint }
|
|
3237
|
+
): void {
|
|
3238
|
+
const expected = admission.admission;
|
|
3239
|
+
const actorRef = request.actorRef;
|
|
3240
|
+
if (
|
|
3241
|
+
expected.actorId !== actorId
|
|
3242
|
+
|| expected.actorType !== request.actorType
|
|
3243
|
+
|| expected.expectedMembershipEpoch !== request.expectedMembershipEpoch
|
|
3244
|
+
|| expected.requestFingerprint !== request.request
|
|
3245
|
+
|| expected.targetSpotGeneration !== (control.currentSpotGeneration ?? 0n)
|
|
3246
|
+
|| actorRef === undefined
|
|
3247
|
+
|| actorRef.actorId !== expected.actorRef.actorId
|
|
3248
|
+
|| String(actorRef.nodeRid) !== String(expected.actorRef.nodeRid)
|
|
3249
|
+
|| actorRef.objectGeneration !== expected.actorRef.objectGeneration
|
|
3250
|
+
) {
|
|
3251
|
+
throw new ZLinkConfigurationException(
|
|
3252
|
+
`Remote Actor '${actorId}' commit does not match its target admission.`
|
|
3253
|
+
);
|
|
3254
|
+
}
|
|
3255
|
+
}
|
|
3256
|
+
|
|
3257
|
+
function normalizeSpotCreateArgs<TRequest>(
|
|
3258
|
+
requestOrSignal: ZLinkMessage | TRequest | AbortSignal | undefined,
|
|
3259
|
+
signal: AbortSignal | undefined
|
|
3260
|
+
): { readonly request: ZLinkMessage | TRequest | undefined; readonly signal: AbortSignal | undefined } {
|
|
3261
|
+
if (isAbortSignal(requestOrSignal)) {
|
|
3262
|
+
return { request: undefined, signal: requestOrSignal };
|
|
3263
|
+
}
|
|
3264
|
+
return { request: requestOrSignal, signal };
|
|
3265
|
+
}
|
|
3266
|
+
|
|
3267
|
+
function requireMeshName(meshName: string): void {
|
|
3268
|
+
if (meshName.length === 0) {
|
|
3269
|
+
throw new ZLinkConfigurationException('Spot operations require a mesh name.');
|
|
3270
|
+
}
|
|
3271
|
+
}
|
|
3272
|
+
|
|
3273
|
+
function instanceMaterializationPrefix(meshName: string, spotId: RoutingId): string {
|
|
3274
|
+
return `${meshName}\0${String(spotId)}`;
|
|
3275
|
+
}
|
|
3276
|
+
|
|
3277
|
+
function instanceMaterializationKey(
|
|
3278
|
+
meshName: string,
|
|
3279
|
+
spotId: RoutingId,
|
|
3280
|
+
objectGeneration: bigint
|
|
3281
|
+
): string {
|
|
3282
|
+
return `${instanceMaterializationPrefix(meshName, spotId)}\0${objectGeneration}`;
|
|
3283
|
+
}
|
|
3284
|
+
|
|
3285
|
+
function isAbortSignal(value: unknown): value is AbortSignal {
|
|
3286
|
+
return typeof value === 'object'
|
|
3287
|
+
&& value !== null
|
|
3288
|
+
&& typeof (value as { aborted?: unknown }).aborted === 'boolean'
|
|
3289
|
+
&& typeof (value as { addEventListener?: unknown }).addEventListener === 'function';
|
|
3290
|
+
}
|
|
3291
|
+
|
|
3292
|
+
function instanceActivationOutcome(error: unknown): string {
|
|
3293
|
+
if (isAbortError(error)) return 'shutdown';
|
|
3294
|
+
if (error instanceof ZLinkFrameworkException) {
|
|
3295
|
+
if (error.kind === ZLinkFrameworkErrorKind.DeadlineExceeded) return 'timed_out';
|
|
3296
|
+
if (error.kind === ZLinkFrameworkErrorKind.AlreadyExists) return 'conflict';
|
|
3297
|
+
if (
|
|
3298
|
+
error.kind === ZLinkFrameworkErrorKind.InvalidOperation
|
|
3299
|
+
|| error.kind === ZLinkFrameworkErrorKind.Unavailable
|
|
3300
|
+
) return 'fenced';
|
|
3301
|
+
}
|
|
3302
|
+
return 'failed';
|
|
3303
|
+
}
|