@zlink-systems/framework 0.21.0 → 0.22.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/dist/.tsbuildinfo +1 -1
- package/dist/contracts/Common/ZLinkMessage.js +5 -5
- package/dist/contracts/Configuration/CodecContentType.js +5 -7
- package/dist/contracts/Configuration/DiagnosticsValidation.js +1 -6
- package/dist/contracts/Configuration/EndpointNotation.js +4 -8
- package/dist/contracts/Configuration/Registration.js +14 -11
- package/dist/contracts/Configuration/RegistrationBuilders.js +32 -25
- package/dist/contracts/Configuration/RegistrationNormalizers.js +25 -26
- package/dist/contracts/Configuration/RegistrationValidators.js +36 -38
- package/dist/contracts/Configuration/SendTimeoutValidation.js +4 -4
- package/dist/contracts/Configuration/TimerRegistrationValidator.js +7 -7
- package/dist/contracts/Handlers/JsonContract.js +23 -11
- package/dist/contracts/Spots/SpotKind.js +16 -8
- package/dist/location-store-integration.js +16 -16
- package/dist/nest-integration.js +17 -11
- package/dist/runtime/abort.js +9 -5
- package/dist/runtime/actors/actor-authority-payload-codec.js +12 -16
- package/dist/runtime/actors/actor-authority-publication.js +18 -17
- package/dist/runtime/actors/actor-client.js +83 -63
- package/dist/runtime/actors/actor-context.js +24 -18
- package/dist/runtime/actors/actor-creation.js +4 -3
- package/dist/runtime/actors/actor-handoff.js +89 -92
- package/dist/runtime/actors/actor-local-native-join.js +18 -19
- package/dist/runtime/actors/actor-mailbox.js +1 -1
- package/dist/runtime/actors/actor-message-follow-context.js +24 -21
- package/dist/runtime/actors/actor-packet-relay-wire.js +1 -3
- package/dist/runtime/actors/actor-remote-joiner.js +20 -17
- package/dist/runtime/actors/actor-remote-wire.js +6 -7
- package/dist/runtime/actors/actor-runtime-state.js +87 -81
- package/dist/runtime/actors/actor-transfer-registry.js +3 -5
- package/dist/runtime/actors/bound-session-wire.js +14 -9
- package/dist/runtime/actors/deferred-join-accepted-journal.js +158 -124
- package/dist/runtime/actors/index.js +2 -5
- package/dist/runtime/actors/post-commit-actor-binder.js +3 -6
- package/dist/runtime/actors/post-commit-actor-location.js +1 -1
- package/dist/runtime/actors/spot-actor-dispatch.js +5 -5
- package/dist/runtime/actors/transferred-actor-rollback.js +4 -4
- package/dist/runtime/admission.js +2 -6
- package/dist/runtime/application-jobs/application-ingress-record-owner.js +2 -6
- package/dist/runtime/application-jobs/receive-flow-controller.js +11 -12
- package/dist/runtime/backend/mesh-completion-table.js +1 -3
- package/dist/runtime/backend/mesh-dispatch-pump.js +12 -16
- package/dist/runtime/backend/node/node-backend-adapter-factory.js +1 -3
- package/dist/runtime/backend/node/node-backend-adapter-support.js +26 -17
- package/dist/runtime/backend/node/node-mesh-backend-adapter.js +4 -3
- package/dist/runtime/backend/node/node-raw-binding-port.js +7 -6
- package/dist/runtime/backend/node/node-raw-mesh-backend.js +116 -113
- package/dist/runtime/backend/node/node-socket-backend-adapter.js +12 -13
- package/dist/runtime/backend/runtime-message.js +3 -3
- package/dist/runtime/backend/runtime-values.d.ts +2 -2
- package/dist/runtime/backend/runtime-values.js +4 -5
- package/dist/runtime/channels/channel-clients.js +27 -24
- package/dist/runtime/channels/channel-dispatch-pipeline.js +10 -18
- package/dist/runtime/channels/channel-dispatch-services.js +7 -4
- package/dist/runtime/channels/channel-dispatchers.js +9 -9
- package/dist/runtime/channels/channel-envelope-inspection.js +16 -13
- package/dist/runtime/channels/channel-envelope.js +83 -47
- package/dist/runtime/channels/channel-outbound-operations.js +8 -8
- package/dist/runtime/channels/channel-receive-loops.js +20 -22
- package/dist/runtime/channels/channel-receive-task-tracker.js +1 -1
- package/dist/runtime/channels/channel-runtime-lifecycle.js +61 -56
- package/dist/runtime/channels/channel-runtime-manager.js +18 -9
- package/dist/runtime/channels/channel-socket-registry.js +126 -123
- package/dist/runtime/channels/channel-transports.js +43 -33
- package/dist/runtime/channels/client-server-location-runtime.js +32 -40
- package/dist/runtime/channels/client-server-service-wire.js +29 -22
- package/dist/runtime/channels/dispatch-error-reporter.js +9 -7
- package/dist/runtime/channels/fanout-location-runtime.js +34 -47
- package/dist/runtime/channels/fanout-service-wire.js +3 -5
- package/dist/runtime/channels/local-spot-route-transport.js +7 -1
- package/dist/runtime/channels/route-member-snapshot.js +3 -3
- package/dist/runtime/channels/source-spot-router.js +6 -2
- package/dist/runtime/channels/spot-route-bridge-transport.js +5 -2
- package/dist/runtime/channels/spot-route-dispatch-strategy.js +2 -2
- package/dist/runtime/channels/spot-route-target-resolver.js +6 -6
- package/dist/runtime/diagnostics/index.js +38 -10
- package/dist/runtime/diagnostics/message-flow.js +47 -39
- package/dist/runtime/diagnostics/runtime-metrics.js +18 -9
- package/dist/runtime/diagnostics/runtime-observation-queue.js +8 -10
- package/dist/runtime/diagnostics/topology-runtime-projections.js +17 -10
- package/dist/runtime/execution/index.js +7 -6
- package/dist/runtime/execution/serial-execution-queue.js +12 -18
- package/dist/runtime/execution/state-lane.js +2 -2
- package/dist/runtime/foundation/actor-join-recovery-codec.js +31 -23
- package/dist/runtime/foundation/event-loop-resources.js +4 -4
- package/dist/runtime/foundation/message-follow-suppression-registry.js +4 -4
- package/dist/runtime/foundation/raw-service-mesh-runtime.js +136 -136
- package/dist/runtime/foundation/route-mesh-connection-policy.js +4 -4
- package/dist/runtime/foundation/runtime-state-projections.js +22 -11
- package/dist/runtime/foundation/service-authority-payload-codec.js +13 -15
- package/dist/runtime/foundation/service-discovery-registry.js +35 -33
- package/dist/runtime/foundation/service-instance-activation-recovery-codec.js +20 -22
- package/dist/runtime/foundation/service-liveness-registry.js +16 -12
- package/dist/runtime/foundation/service-maintenance-runtime.js +2 -4
- package/dist/runtime/foundation/service-relocation-aggregate-committer.js +24 -24
- package/dist/runtime/foundation/service-relocation-object-owner.js +6 -6
- package/dist/runtime/foundation/service-relocation-runtime.js +137 -94
- package/dist/runtime/foundation/service-runtime-contracts.js +5 -5
- package/dist/runtime/foundation/service-stateful-registry.js +24 -23
- package/dist/runtime/foundation/service-stateful-runtime.js +416 -438
- package/dist/runtime/foundation/service-stateful-wire-codec.js +95 -98
- package/dist/runtime/foundation/service-topology-registry.js +96 -95
- package/dist/runtime/foundation/service-weighted-selection.js +6 -11
- package/dist/runtime/foundation/service-wire-binary-primitives.js +5 -6
- package/dist/runtime/foundation/service-wire-m6a-codec.js +46 -35
- package/dist/runtime/framework-errors-internal.js +7 -10
- package/dist/runtime/handlers/handler-instance-scope.js +4 -5
- package/dist/runtime/handlers/index.js +3 -1
- package/dist/runtime/host/actor-packet-relay.js +74 -70
- package/dist/runtime/host/actor-placement-coordinator.js +29 -31
- package/dist/runtime/host/actor-runtime-options-factory.js +12 -14
- package/dist/runtime/host/actor-transfer-authority-runtime.js +7 -9
- package/dist/runtime/host/actor-transfer-runtime.js +176 -153
- package/dist/runtime/host/application-job-queue.js +18 -22
- package/dist/runtime/host/bound-session-relay.js +3 -1
- package/dist/runtime/host/channel-runtime-options-factory.js +31 -14
- package/dist/runtime/host/host-capacity-status.js +8 -4
- package/dist/runtime/host/index.js +244 -227
- package/dist/runtime/host/instance-activation-authority.js +93 -96
- package/dist/runtime/host/location-runtime-owner.js +16 -14
- package/dist/runtime/host/mesh-router-resolver.js +11 -13
- package/dist/runtime/host/relocation-direct-transfer.js +10 -9
- package/dist/runtime/host/remote-actor-join-receiver.js +20 -15
- package/dist/runtime/host/remote-actor-packet-target-store.js +18 -22
- package/dist/runtime/host/remote-bound-session-relay.js +97 -73
- package/dist/runtime/host/route-mesh-runtime.js +64 -69
- package/dist/runtime/host/runtime-shutdown.js +1 -2
- package/dist/runtime/host/service-relocation-host-runtime.js +586 -511
- package/dist/runtime/host/spot-address-transport.js +69 -71
- package/dist/runtime/host/spot-runtime-options-factory.js +30 -29
- package/dist/runtime/host/stateful-authority-route-runtime.js +65 -68
- package/dist/runtime/host/user-spot-creation-coordinator.js +61 -67
- package/dist/runtime/locations/actor-location-claims.js +26 -20
- package/dist/runtime/locations/aggregate-inventory-store.js +72 -75
- package/dist/runtime/locations/authority-key-codec.js +7 -7
- package/dist/runtime/locations/auto-connect-loop.js +3 -3
- package/dist/runtime/locations/auto-connect-planner.js +25 -19
- package/dist/runtime/locations/auto-connect-reconciler.js +51 -31
- package/dist/runtime/locations/in-memory-authority-store.js +128 -118
- package/dist/runtime/locations/in-memory-location-store.js +195 -168
- package/dist/runtime/locations/in-memory-provider-location-store.js +8 -10
- package/dist/runtime/locations/key-codec.js +1 -1
- package/dist/runtime/locations/lease-tracker.js +23 -21
- package/dist/runtime/locations/lifecycle.js +4 -5
- package/dist/runtime/locations/location-store-repository.js +368 -324
- package/dist/runtime/locations/opaque-record-key.js +2 -2
- package/dist/runtime/locations/resolvers.js +73 -82
- package/dist/runtime/locations/runtime.js +68 -63
- package/dist/runtime/locations/spot-location-claims.js +39 -35
- package/dist/runtime/messaging/framework-json-v1.js +7 -7
- package/dist/runtime/messaging/packet-name.js +7 -6
- package/dist/runtime/messaging/payload-codec.js +21 -18
- package/dist/runtime/protocol/service_wire_codec.generated.d.ts +30 -2
- package/dist/runtime/protocol/service_wire_codec.generated.js +1671 -234
- package/dist/runtime/routing-id.js +3 -5
- package/dist/runtime/spots/formal-remote-actor-admission-registry.js +35 -31
- package/dist/runtime/spots/formal-remote-actor-transfer-registry.js +1 -2
- package/dist/runtime/spots/index.js +208 -219
- package/dist/runtime/spots/spot-activation-registry.js +15 -14
- package/dist/runtime/spots/spot-activation-state.js +17 -15
- package/dist/runtime/spots/spot-activation.js +33 -16
- package/dist/runtime/spots/spot-actor-admission-coordinator.js +18 -15
- package/dist/runtime/spots/spot-actor-membership.js +1 -3
- package/dist/runtime/spots/spot-actor-packet-dispatch.js +23 -20
- package/dist/runtime/spots/spot-actor-packet-drain.js +12 -10
- package/dist/runtime/spots/spot-actor-packet-relay-dispatch.js +10 -6
- package/dist/runtime/spots/spot-closing.js +3 -7
- package/dist/runtime/spots/spot-context.js +2 -2
- package/dist/runtime/spots/spot-entry-activation.js +13 -14
- package/dist/runtime/spots/spot-handle.js +6 -3
- package/dist/runtime/spots/spot-handler-registry.js +12 -12
- package/dist/runtime/spots/spot-manager-public.js +5 -6
- package/dist/runtime/spots/spot-native-actor-join-admission.js +4 -3
- package/dist/runtime/spots/spot-node-autoconnect.js +15 -18
- package/dist/runtime/spots/spot-node-runtime-manager.js +74 -85
- package/dist/runtime/spots/spot-outbound.js +10 -14
- package/dist/runtime/spots/spot-remote-codec.js +22 -26
- package/dist/runtime/spots/spot-remote-route-codec.js +5 -7
- package/dist/runtime/spots/spot-route-packet-dispatch.js +16 -14
- package/dist/runtime/spots/spot-route-replies.js +4 -6
- package/dist/runtime/spots/spot-routed-actor-admission.js +9 -7
- package/dist/runtime/spots/spot-routed-bound-session-dispatch.js +1 -2
- package/dist/runtime/spots/spot-routed-frame-dispatch.js +5 -5
- package/dist/runtime/spots/spot-routed-spot-packet-dispatch.js +14 -10
- package/dist/runtime/spots/spot-serial-executor.js +5 -8
- package/dist/runtime/spots/spot-serial-turn-executor.js +4 -6
- package/dist/runtime/spots/spot-subscription-dispatch.js +5 -5
- package/dist/runtime/spots/spot-timer.js +25 -29
- package/dist/runtime/streams/actor-session-binding-registry.js +98 -107
- package/dist/runtime/streams/actor-session-lifecycle-coordinator.js +3 -1
- package/dist/runtime/streams/bound-actor-relay-sender.js +18 -16
- package/dist/runtime/streams/bound-session-service.js +8 -9
- package/dist/runtime/streams/index.js +20 -19
- package/dist/runtime/streams/managed-stream.js +32 -30
- package/dist/runtime/streams/native-fallback-bound-session.js +21 -17
- package/dist/runtime/streams/protocol.js +29 -18
- package/dist/runtime/streams/session-actor-coordinator.js +34 -37
- package/dist/runtime/streams/session-context.js +30 -28
- package/dist/runtime/streams/session-provider.js +2 -2
- package/dist/runtime/streams/session-serial-executor.js +1 -2
- package/dist/runtime/streams/stream-frame-factory.js +11 -5
- package/dist/runtime/streams/stream-session-runtime.js +70 -66
- package/dist/runtime/workers/index.js +15 -4
- package/package.json +2 -2
- package/src/contracts/Channels/RouteCalls.ts +6 -1
- package/src/contracts/Common/ZLinkMessage.ts +5 -5
- package/src/contracts/Common/ZLinkMessageMetadata.ts +4 -3
- package/src/contracts/Configuration/Builders.ts +14 -14
- package/src/contracts/Configuration/CodecContentType.ts +8 -10
- package/src/contracts/Configuration/DiagnosticsValidation.ts +1 -6
- package/src/contracts/Configuration/EndpointNotation.ts +11 -11
- package/src/contracts/Configuration/ObjectRoles.ts +1 -3
- package/src/contracts/Configuration/Registration.ts +46 -17
- package/src/contracts/Configuration/RegistrationBuilderPolicy.ts +10 -8
- package/src/contracts/Configuration/RegistrationBuilders.ts +107 -96
- package/src/contracts/Configuration/RegistrationCodecRegistry.ts +9 -3
- package/src/contracts/Configuration/RegistrationNormalizers.ts +116 -84
- package/src/contracts/Configuration/RegistrationTypes.ts +21 -25
- package/src/contracts/Configuration/RegistrationValidators.ts +122 -73
- package/src/contracts/Configuration/RouteChannelInternalState.ts +1 -4
- package/src/contracts/Configuration/RuntimeEndpointConnections.ts +4 -1
- package/src/contracts/Configuration/SendTimeoutValidation.ts +6 -4
- package/src/contracts/Configuration/TimerRegistrationValidator.ts +8 -13
- package/src/contracts/Dispatch/ZLinkDispatchOptions.ts +1 -6
- package/src/contracts/Errors/index.ts +1 -4
- package/src/contracts/Handlers/Attributes.ts +15 -9
- package/src/contracts/Handlers/IZLinkChannelHandlers.ts +24 -4
- package/src/contracts/Handlers/JsonContract.ts +53 -19
- package/src/contracts/Locations/ActorTransfer.ts +1 -5
- package/src/contracts/Locations/Authority.ts +4 -11
- package/src/contracts/Locations/Keys.ts +6 -1
- package/src/contracts/Locations/Options.ts +3 -2
- package/src/contracts/Locations/RelocationStore.ts +1 -4
- package/src/contracts/Locations/Resolvers.ts +5 -5
- package/src/contracts/Locations/RuntimeQuery.ts +6 -2
- package/src/contracts/Locations/Stores.ts +1 -2
- package/src/contracts/Locations/index.ts +2 -8
- package/src/contracts/RouteMesh/Contracts.ts +1 -7
- package/src/contracts/RouteMesh/RuntimeTopology.ts +1 -4
- package/src/contracts/Spots/Contracts.ts +2 -8
- package/src/contracts/Spots/SpotKind.ts +16 -8
- package/src/contracts/Spots/ZLinkSpot.ts +8 -11
- package/src/contracts/Streams/IZLinkSession.ts +0 -1
- package/src/contracts/Streams/IZLinkSessionActor.ts +5 -1
- package/src/contracts/Streams/IZLinkSessionPacketHandler.ts +5 -1
- package/src/internal.ts +5 -4
- package/src/location-store-integration.ts +24 -16
- package/src/nest-integration.ts +40 -25
- package/src/runtime/abort.ts +10 -4
- package/src/runtime/actors/actor-authority-payload-codec.ts +20 -29
- package/src/runtime/actors/actor-authority-publication.ts +92 -77
- package/src/runtime/actors/actor-client.ts +162 -133
- package/src/runtime/actors/actor-context.ts +138 -130
- package/src/runtime/actors/actor-creation.ts +47 -44
- package/src/runtime/actors/actor-execution-context.ts +6 -4
- package/src/runtime/actors/actor-handoff.ts +269 -293
- package/src/runtime/actors/actor-join-deferred-scope.ts +5 -4
- package/src/runtime/actors/actor-lifecycle-snapshot.ts +5 -8
- package/src/runtime/actors/actor-local-native-join.ts +131 -159
- package/src/runtime/actors/actor-mailbox.ts +16 -19
- package/src/runtime/actors/actor-message-follow-context.ts +46 -36
- package/src/runtime/actors/actor-packet-relay-wire.ts +32 -21
- package/src/runtime/actors/actor-remote-joiner.ts +50 -54
- package/src/runtime/actors/actor-remote-wire.ts +9 -13
- package/src/runtime/actors/actor-routed-join-transport.ts +10 -2
- package/src/runtime/actors/actor-runtime-contracts.ts +2 -5
- package/src/runtime/actors/actor-runtime-state.ts +127 -124
- package/src/runtime/actors/actor-transfer-registry.ts +9 -14
- package/src/runtime/actors/actor-transport-delivery-gate.ts +4 -6
- package/src/runtime/actors/bound-session-wire.ts +37 -17
- package/src/runtime/actors/deferred-join-accepted-journal.ts +351 -320
- package/src/runtime/actors/index.ts +43 -86
- package/src/runtime/actors/post-commit-actor-binder.ts +10 -10
- package/src/runtime/actors/post-commit-actor-location.ts +30 -23
- package/src/runtime/actors/spot-actor-dispatch.ts +78 -53
- package/src/runtime/actors/transferred-actor-rollback.ts +18 -13
- package/src/runtime/admission.ts +9 -9
- package/src/runtime/application-jobs/application-ingress-record-owner.ts +5 -15
- package/src/runtime/application-jobs/application-job-queue-handler-start-gate.ts +3 -2
- package/src/runtime/application-jobs/receive-flow-controller.ts +17 -14
- package/src/runtime/backend/contracts/index.ts +73 -52
- package/src/runtime/backend/mesh-actor-session-node-adapter.ts +4 -14
- package/src/runtime/backend/mesh-completion-table.ts +6 -9
- package/src/runtime/backend/mesh-dispatch-pump.ts +38 -30
- package/src/runtime/backend/node/node-backend-adapter-factory.ts +23 -21
- package/src/runtime/backend/node/node-backend-adapter-support.ts +36 -22
- package/src/runtime/backend/node/node-dealer-channel-client-transport.ts +59 -58
- package/src/runtime/backend/node/node-event-loop-poller.ts +2 -10
- package/src/runtime/backend/node/node-mesh-backend-adapter.ts +12 -5
- package/src/runtime/backend/node/node-monitor-backend-adapter.ts +4 -3
- package/src/runtime/backend/node/node-raw-binding-port.ts +29 -29
- package/src/runtime/backend/node/node-raw-mesh-backend.ts +335 -383
- package/src/runtime/backend/node/node-socket-backend-adapter.ts +101 -54
- package/src/runtime/backend/runtime-message.ts +5 -3
- package/src/runtime/backend/runtime-values.ts +10 -7
- package/src/runtime/channels/channel-autoconnect.ts +1 -4
- package/src/runtime/channels/channel-clients.ts +93 -73
- package/src/runtime/channels/channel-dispatch-pipeline.ts +40 -42
- package/src/runtime/channels/channel-dispatch-services.ts +51 -49
- package/src/runtime/channels/channel-dispatchers.ts +152 -96
- package/src/runtime/channels/channel-envelope-inspection.ts +20 -16
- package/src/runtime/channels/channel-envelope.ts +256 -150
- package/src/runtime/channels/channel-multipart.ts +13 -5
- package/src/runtime/channels/channel-outbound-operations.ts +37 -41
- package/src/runtime/channels/channel-receive-loops.ts +102 -98
- package/src/runtime/channels/channel-receive-task-tracker.ts +1 -1
- package/src/runtime/channels/channel-runtime-lifecycle.ts +248 -190
- package/src/runtime/channels/channel-runtime-manager.ts +63 -37
- package/src/runtime/channels/channel-socket-options.ts +3 -10
- package/src/runtime/channels/channel-socket-registry.ts +331 -273
- package/src/runtime/channels/channel-transports.ts +215 -197
- package/src/runtime/channels/client-server-location-runtime.ts +116 -100
- package/src/runtime/channels/client-server-service-wire.ts +37 -36
- package/src/runtime/channels/dispatch-error-reporter.ts +11 -8
- package/src/runtime/channels/fanout-location-runtime.ts +91 -94
- package/src/runtime/channels/fanout-service-wire.ts +5 -12
- package/src/runtime/channels/handler-filter-scope.ts +1 -4
- package/src/runtime/channels/index.ts +1 -4
- package/src/runtime/channels/local-spot-route-transport.ts +20 -5
- package/src/runtime/channels/route-member-snapshot.ts +11 -5
- package/src/runtime/channels/router-socket-spot-route-transport.ts +1 -7
- package/src/runtime/channels/source-spot-router.ts +26 -22
- package/src/runtime/channels/spot-direct-envelope.ts +10 -8
- package/src/runtime/channels/spot-node-route-transport.ts +13 -16
- package/src/runtime/channels/spot-route-bridge-transport.ts +26 -9
- package/src/runtime/channels/spot-route-dispatch-strategy.ts +40 -13
- package/src/runtime/channels/spot-route-target-resolver.ts +18 -9
- package/src/runtime/codecs/index.ts +3 -2
- package/src/runtime/diagnostics/flow-context.ts +12 -3
- package/src/runtime/diagnostics/index.ts +96 -61
- package/src/runtime/diagnostics/internal-event-contracts.ts +87 -33
- package/src/runtime/diagnostics/message-flow.ts +95 -76
- package/src/runtime/diagnostics/runtime-metrics.ts +46 -24
- package/src/runtime/diagnostics/runtime-observation-queue.ts +17 -28
- package/src/runtime/diagnostics/topology-runtime-projections.ts +62 -43
- package/src/runtime/execution/index.ts +18 -26
- package/src/runtime/execution/serial-execution-queue.ts +31 -40
- package/src/runtime/execution/state-lane.ts +2 -2
- package/src/runtime/foundation/actor-join-recovery-codec.ts +69 -51
- package/src/runtime/foundation/event-loop-resources.ts +8 -4
- package/src/runtime/foundation/message-follow-suppression-registry.ts +7 -14
- package/src/runtime/foundation/operation-identity.ts +1 -2
- package/src/runtime/foundation/operation-registry.ts +8 -2
- package/src/runtime/foundation/raw-service-mesh-runtime.ts +312 -385
- package/src/runtime/foundation/route-mesh-connection-policy.ts +7 -8
- package/src/runtime/foundation/runtime-state-projections.ts +24 -23
- package/src/runtime/foundation/service-authority-payload-codec.ts +54 -57
- package/src/runtime/foundation/service-discovery-registry.ts +67 -59
- package/src/runtime/foundation/service-instance-activation-recovery-codec.ts +28 -29
- package/src/runtime/foundation/service-liveness-registry.ts +18 -13
- package/src/runtime/foundation/service-mailbox.ts +14 -14
- package/src/runtime/foundation/service-maintenance-runtime.ts +22 -21
- package/src/runtime/foundation/service-metadata-codec.ts +2 -9
- package/src/runtime/foundation/service-relocation-aggregate-committer.ts +39 -36
- package/src/runtime/foundation/service-relocation-coordinator.ts +1 -4
- package/src/runtime/foundation/service-relocation-object-owner.ts +40 -58
- package/src/runtime/foundation/service-relocation-runtime.ts +292 -216
- package/src/runtime/foundation/service-runtime-contracts.ts +8 -8
- package/src/runtime/foundation/service-session-binding-ingress-port.ts +1 -4
- package/src/runtime/foundation/service-stateful-registry.ts +69 -59
- package/src/runtime/foundation/service-stateful-runtime.ts +1174 -1112
- package/src/runtime/foundation/service-stateful-wire-codec.ts +318 -270
- package/src/runtime/foundation/service-topology-registry.ts +157 -159
- package/src/runtime/foundation/service-weighted-selection.ts +9 -15
- package/src/runtime/foundation/service-wire-binary-primitives.ts +6 -12
- package/src/runtime/foundation/service-wire-m6a-codec.ts +69 -47
- package/src/runtime/framework-errors-internal.ts +31 -30
- package/src/runtime/handlers/handler-instance-scope.ts +18 -29
- package/src/runtime/handlers/index.ts +18 -8
- package/src/runtime/host/actor-packet-relay.ts +290 -261
- package/src/runtime/host/actor-placement-coordinator.ts +165 -150
- package/src/runtime/host/actor-runtime-options-factory.ts +89 -87
- package/src/runtime/host/actor-transfer-authority-runtime.ts +46 -38
- package/src/runtime/host/actor-transfer-runtime.ts +391 -395
- package/src/runtime/host/application-job-queue.ts +32 -48
- package/src/runtime/host/bound-session-relay.ts +7 -9
- package/src/runtime/host/channel-runtime-options-factory.ts +75 -35
- package/src/runtime/host/host-capacity-status.ts +10 -9
- package/src/runtime/host/index.ts +861 -789
- package/src/runtime/host/instance-activation-authority.ts +125 -143
- package/src/runtime/host/location-runtime-owner.ts +38 -26
- package/src/runtime/host/mesh-router-resolver.ts +30 -23
- package/src/runtime/host/relocation-direct-transfer.ts +15 -15
- package/src/runtime/host/relocation-integrity-fault-gate.ts +3 -2
- package/src/runtime/host/remote-actor-join-receiver.ts +43 -34
- package/src/runtime/host/remote-actor-packet-target-store.ts +54 -52
- package/src/runtime/host/remote-bound-session-relay.ts +274 -247
- package/src/runtime/host/route-mesh-runtime-options.ts +1 -3
- package/src/runtime/host/route-mesh-runtime.ts +227 -181
- package/src/runtime/host/runtime-shutdown.ts +4 -3
- package/src/runtime/host/service-relocation-control.ts +14 -5
- package/src/runtime/host/service-relocation-host-runtime.ts +1388 -1165
- package/src/runtime/host/spot-address-transport.ts +284 -237
- package/src/runtime/host/spot-node-runtime-options-factory.ts +14 -8
- package/src/runtime/host/spot-runtime-options-factory.ts +71 -62
- package/src/runtime/host/stateful-authority-route-runtime.ts +117 -116
- package/src/runtime/host/user-spot-creation-coordinator.ts +225 -220
- package/src/runtime/locations/actor-location-claims.ts +61 -49
- package/src/runtime/locations/actor-session-route-claims.ts +1 -4
- package/src/runtime/locations/aggregate-inventory-store.ts +105 -134
- package/src/runtime/locations/authority-key-codec.ts +13 -10
- package/src/runtime/locations/auto-connect-loop.ts +14 -11
- package/src/runtime/locations/auto-connect-planner.ts +42 -31
- package/src/runtime/locations/auto-connect-reconciler.ts +106 -63
- package/src/runtime/locations/canonical-codec.ts +3 -1
- package/src/runtime/locations/creation-operation-id.ts +4 -3
- package/src/runtime/locations/domain-store-contract.ts +13 -7
- package/src/runtime/locations/in-memory-authority-store.ts +232 -199
- package/src/runtime/locations/in-memory-location-store.ts +432 -250
- package/src/runtime/locations/in-memory-provider-location-store.ts +16 -17
- package/src/runtime/locations/internal-store-contracts.ts +95 -38
- package/src/runtime/locations/key-codec.ts +3 -4
- package/src/runtime/locations/lease-tracker.ts +36 -27
- package/src/runtime/locations/lifecycle-runtime.ts +15 -3
- package/src/runtime/locations/lifecycle.ts +33 -28
- package/src/runtime/locations/location-store-repository.ts +1329 -1185
- package/src/runtime/locations/opaque-record-key.ts +4 -9
- package/src/runtime/locations/resolvers.ts +201 -178
- package/src/runtime/locations/runtime.ts +251 -159
- package/src/runtime/locations/spot-location-claims.ts +110 -112
- package/src/runtime/messaging/creation-payload-codec.ts +4 -1
- package/src/runtime/messaging/framework-json-v1.ts +34 -15
- package/src/runtime/messaging/packet-name.ts +8 -6
- package/src/runtime/messaging/payload-codec.ts +70 -50
- package/src/runtime/messaging/submission-result.ts +6 -9
- package/src/runtime/protocol/service_wire_codec.generated.ts +1376 -159
- package/src/runtime/protocol/service_wire_pilot_codec.generated.ts +1 -1
- package/src/runtime/routing-id.ts +10 -7
- package/src/runtime/spots/formal-remote-actor-admission-registry.ts +56 -62
- package/src/runtime/spots/formal-remote-actor-transfer-registry.ts +23 -20
- package/src/runtime/spots/index.ts +593 -563
- package/src/runtime/spots/spot-activation-registry.ts +38 -34
- package/src/runtime/spots/spot-activation-state.ts +43 -51
- package/src/runtime/spots/spot-activation.ts +179 -116
- package/src/runtime/spots/spot-actor-admission-coordinator.ts +110 -78
- package/src/runtime/spots/spot-actor-join-dispatch.ts +57 -41
- package/src/runtime/spots/spot-actor-lifecycle-drain.ts +5 -7
- package/src/runtime/spots/spot-actor-membership.ts +25 -27
- package/src/runtime/spots/spot-actor-packet-dispatch.ts +184 -153
- package/src/runtime/spots/spot-actor-packet-drain.ts +54 -42
- package/src/runtime/spots/spot-actor-packet-relay-dispatch.ts +37 -39
- package/src/runtime/spots/spot-closing.ts +11 -12
- package/src/runtime/spots/spot-context.ts +46 -26
- package/src/runtime/spots/spot-entry-activation.ts +84 -65
- package/src/runtime/spots/spot-handle.ts +17 -15
- package/src/runtime/spots/spot-handler-registry.ts +44 -31
- package/src/runtime/spots/spot-location-claim.ts +5 -4
- package/src/runtime/spots/spot-manager-public.ts +62 -82
- package/src/runtime/spots/spot-native-actor-join-admission.ts +20 -16
- package/src/runtime/spots/spot-node-autoconnect.ts +54 -61
- package/src/runtime/spots/spot-node-runtime-manager.ts +230 -221
- package/src/runtime/spots/spot-outbound.ts +47 -59
- package/src/runtime/spots/spot-publisher-transport.ts +5 -4
- package/src/runtime/spots/spot-remote-codec.ts +66 -65
- package/src/runtime/spots/spot-remote-route-codec.ts +61 -41
- package/src/runtime/spots/spot-route-packet-dispatch.ts +128 -95
- package/src/runtime/spots/spot-route-replies.ts +23 -24
- package/src/runtime/spots/spot-route-reply-wire.ts +3 -2
- package/src/runtime/spots/spot-routed-actor-admission.ts +37 -27
- package/src/runtime/spots/spot-routed-bound-session-dispatch.ts +11 -17
- package/src/runtime/spots/spot-routed-frame-dispatch.ts +18 -15
- package/src/runtime/spots/spot-routed-spot-packet-dispatch.ts +35 -26
- package/src/runtime/spots/spot-routing-internal.ts +1 -4
- package/src/runtime/spots/spot-runtime-ports.ts +5 -5
- package/src/runtime/spots/spot-serial-executor.ts +5 -9
- package/src/runtime/spots/spot-serial-turn-executor.ts +19 -26
- package/src/runtime/spots/spot-subscription-dispatch.ts +56 -46
- package/src/runtime/spots/spot-timer.ts +98 -91
- package/src/runtime/streams/actor-session-binding-registry.ts +277 -235
- package/src/runtime/streams/actor-session-binding-runtime-owner.ts +7 -4
- package/src/runtime/streams/actor-session-lifecycle-coordinator.ts +3 -1
- package/src/runtime/streams/bound-actor-relay-sender.ts +53 -51
- package/src/runtime/streams/bound-session-response-target.ts +29 -8
- package/src/runtime/streams/bound-session-service.ts +39 -39
- package/src/runtime/streams/index.ts +176 -100
- package/src/runtime/streams/managed-stream.ts +98 -87
- package/src/runtime/streams/native-fallback-bound-session.ts +57 -52
- package/src/runtime/streams/protocol.ts +73 -43
- package/src/runtime/streams/session-actor-coordinator.ts +97 -89
- package/src/runtime/streams/session-calls.ts +2 -8
- package/src/runtime/streams/session-context.ts +66 -48
- package/src/runtime/streams/session-provider.ts +5 -7
- package/src/runtime/streams/session-serial-executor.ts +7 -6
- package/src/runtime/streams/stream-binding-runtime-ports.ts +79 -29
- package/src/runtime/streams/stream-frame-factory.ts +55 -38
- package/src/runtime/streams/stream-session-runtime.ts +268 -210
- package/src/runtime/workers/index.ts +68 -29
|
@@ -10,7 +10,7 @@ import type {
|
|
|
10
10
|
ZLinkSpot,
|
|
11
11
|
ZLinkSpotActorJoinResult,
|
|
12
12
|
ZLinkSpotInfo,
|
|
13
|
-
ZLinkSpotPublisherClient
|
|
13
|
+
ZLinkSpotPublisherClient
|
|
14
14
|
} from '../../contracts';
|
|
15
15
|
import type { ZLinkProviderResolver } from '../../contracts/Common/ZLinkProviderResolver';
|
|
16
16
|
import type {
|
|
@@ -58,19 +58,14 @@ import {
|
|
|
58
58
|
type ReceiveRecord
|
|
59
59
|
} from '../foundation/service-runtime-contracts';
|
|
60
60
|
import { zlinkMetadataByteLength, zlinkSerialWorkOptions } from '../execution/serial-work-size';
|
|
61
|
-
import {
|
|
62
|
-
ZLinkConfigurationException
|
|
63
|
-
} from '../configuration';
|
|
61
|
+
import { ZLinkConfigurationException } from '../configuration';
|
|
64
62
|
import {
|
|
65
63
|
ZLinkFrameworkInternalErrorKind,
|
|
66
64
|
createInternalFrameworkException,
|
|
67
65
|
internalFrameworkErrorKind,
|
|
68
66
|
internalFrameworkWireReply
|
|
69
67
|
} from '../framework-errors-internal';
|
|
70
|
-
import type {
|
|
71
|
-
ZLinkBackendSpot,
|
|
72
|
-
ZLinkBackendSpotNode
|
|
73
|
-
} from '../backend/contracts';
|
|
68
|
+
import type { ZLinkBackendSpot, ZLinkBackendSpotNode } from '../backend/contracts';
|
|
74
69
|
|
|
75
70
|
import { ZLinkDispatchErrorReporter } from '../channels';
|
|
76
71
|
import { ZLinkWorkerRuntime } from '../workers';
|
|
@@ -114,17 +109,12 @@ import {
|
|
|
114
109
|
decodeRemoteBoundSessionTarget
|
|
115
110
|
} from './spot-remote-codec';
|
|
116
111
|
import { decodeRoutingId, encodeRoutingIdStorageHex } from '../routing-id';
|
|
117
|
-
import type {
|
|
118
|
-
CanonicalActorJoinRecovery
|
|
119
|
-
} from '../foundation/actor-join-recovery-codec';
|
|
112
|
+
import type { CanonicalActorJoinRecovery } from '../foundation/actor-join-recovery-codec';
|
|
120
113
|
import { SERVICE_FRAMEWORK_MULTIPART_CONTENT_TYPE } from '../foundation/service-wire-constants.generated';
|
|
121
114
|
|
|
122
115
|
export { ZLinkSpotSerialTurnExecutor } from './spot-serial-turn-executor';
|
|
123
116
|
export { ZLinkSpotSerialExecutor } from './spot-serial-executor';
|
|
124
|
-
export {
|
|
125
|
-
ZLinkManagedTimer,
|
|
126
|
-
ZLinkSpotTimerRegistry
|
|
127
|
-
} from './spot-timer';
|
|
117
|
+
export { ZLinkManagedTimer, ZLinkSpotTimerRegistry } from './spot-timer';
|
|
128
118
|
export {
|
|
129
119
|
DefaultZLinkSpotOutbound,
|
|
130
120
|
type ZLinkSpotAddressCallOptions,
|
|
@@ -133,25 +123,15 @@ export {
|
|
|
133
123
|
type ZLinkSpotRoutedSendOptions,
|
|
134
124
|
type ZLinkSpotRoutedTransport
|
|
135
125
|
} from './spot-outbound';
|
|
136
|
-
import {
|
|
137
|
-
type ZLinkSpotRoutedTransport
|
|
138
|
-
} from './spot-outbound';
|
|
126
|
+
import { type ZLinkSpotRoutedTransport } from './spot-outbound';
|
|
139
127
|
export {
|
|
140
128
|
DefaultZLinkSpotHandlerRegistry,
|
|
141
129
|
type ZLinkSpotHandlerRegistration
|
|
142
130
|
} from './spot-handler-registry';
|
|
143
131
|
export { ZLinkRuntimeSpotPublisherTransport } from './spot-publisher-transport';
|
|
144
|
-
import {
|
|
145
|
-
|
|
146
|
-
} from './spot-activation
|
|
147
|
-
import {
|
|
148
|
-
ZLinkSpotCloseOccupiedError,
|
|
149
|
-
type ZLinkSpotActivation
|
|
150
|
-
} from './spot-activation-state';
|
|
151
|
-
import {
|
|
152
|
-
ZLinkSpotActivationLifecycle,
|
|
153
|
-
type ZLinkNativeSpotAuthority
|
|
154
|
-
} from './spot-activation';
|
|
132
|
+
import { ZLinkSpotActivationRegistry } from './spot-activation-registry';
|
|
133
|
+
import { ZLinkSpotCloseOccupiedError, type ZLinkSpotActivation } from './spot-activation-state';
|
|
134
|
+
import { ZLinkSpotActivationLifecycle, type ZLinkNativeSpotAuthority } from './spot-activation';
|
|
155
135
|
import { ZLinkSpotActorMembership, type ZLinkActorJoinRollback } from './spot-actor-membership';
|
|
156
136
|
import { ZLinkFormalRemoteActorTransferRegistry } from './formal-remote-actor-transfer-registry';
|
|
157
137
|
import {
|
|
@@ -177,10 +157,7 @@ export {
|
|
|
177
157
|
ZLinkSpotNodeRuntimeManager,
|
|
178
158
|
type ZLinkSpotNodeRuntimeManagerOptions
|
|
179
159
|
} from './spot-node-runtime-manager';
|
|
180
|
-
export {
|
|
181
|
-
ZLinkPublicSpotManager,
|
|
182
|
-
type ZLinkPublicSpotManagerOptions
|
|
183
|
-
} from './spot-manager-public';
|
|
160
|
+
export { ZLinkPublicSpotManager, type ZLinkPublicSpotManagerOptions } from './spot-manager-public';
|
|
184
161
|
|
|
185
162
|
export interface ZLinkSpotManagerOptions {
|
|
186
163
|
readonly spotFactories: readonly Type<ZLinkSpot>[];
|
|
@@ -329,20 +306,26 @@ export class DefaultZLinkSpotManager {
|
|
|
329
306
|
string,
|
|
330
307
|
Map<string, Promise<ZLinkSpotActivation>>
|
|
331
308
|
>();
|
|
332
|
-
private readonly instanceActivationGates = new Map<
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
309
|
+
private readonly instanceActivationGates = new Map<
|
|
310
|
+
string,
|
|
311
|
+
{
|
|
312
|
+
readonly meshName: string;
|
|
313
|
+
readonly limit: number;
|
|
314
|
+
active: number;
|
|
315
|
+
// Tombstone slots + head cursor keep abort O(1) and admit O(1) amortized
|
|
316
|
+
// instead of indexOf/splice + shift scans under a cancellation storm.
|
|
317
|
+
readonly waiters: Array<
|
|
318
|
+
| {
|
|
319
|
+
resolve: (release: () => void) => void;
|
|
320
|
+
reject: (error: unknown) => void;
|
|
321
|
+
signal?: AbortSignal;
|
|
322
|
+
abort?: () => void;
|
|
323
|
+
}
|
|
324
|
+
| undefined
|
|
325
|
+
>;
|
|
326
|
+
waiterHead: number;
|
|
327
|
+
}
|
|
328
|
+
>();
|
|
346
329
|
private readonly pendingInstanceCloses = new Map<string, Promise<boolean>>();
|
|
347
330
|
private readonly pendingInstanceTerminals = new Map<string, number>();
|
|
348
331
|
private readonly pendingInstanceTerminalGenerations = new Map<string, Map<string, number>>();
|
|
@@ -365,16 +348,18 @@ export class DefaultZLinkSpotManager {
|
|
|
365
348
|
});
|
|
366
349
|
this.routedSpotPackets = new ZLinkRoutedSpotPacketDispatch({
|
|
367
350
|
resolveActivation: (spotId) => this.activations.resolveUnique(spotId),
|
|
368
|
-
claimApplicationWork:
|
|
369
|
-
|
|
370
|
-
|
|
351
|
+
claimApplicationWork:
|
|
352
|
+
options.admission === undefined
|
|
353
|
+
? undefined
|
|
354
|
+
: (meshName) => options.admission!.claim(meshName, 'Spot route dispatch'),
|
|
371
355
|
providerResolver: options.providerResolver,
|
|
372
356
|
dispatchErrors: options.dispatchErrors
|
|
373
357
|
});
|
|
374
358
|
this.actorMembership = new ZLinkSpotActorMembership({
|
|
375
|
-
resolveActivation: (spotId, meshName) =>
|
|
376
|
-
|
|
377
|
-
|
|
359
|
+
resolveActivation: (spotId, meshName) =>
|
|
360
|
+
meshName === undefined
|
|
361
|
+
? this.activations.resolveUnique(spotId)
|
|
362
|
+
: this.activations.resolve(meshName, spotId),
|
|
378
363
|
providerResolver: options.providerResolver,
|
|
379
364
|
messageSerializers: options.messageSerializers,
|
|
380
365
|
dispatchErrors: options.dispatchErrors,
|
|
@@ -445,8 +430,10 @@ export class DefaultZLinkSpotManager {
|
|
|
445
430
|
meshName,
|
|
446
431
|
spotId
|
|
447
432
|
);
|
|
448
|
-
if (
|
|
449
|
-
|
|
433
|
+
if (
|
|
434
|
+
currentApplication !== undefined &&
|
|
435
|
+
currentApplication.objectGeneration !== activation.domain.objectGeneration
|
|
436
|
+
) {
|
|
450
437
|
// A superseded local application must not release the authority row
|
|
451
438
|
// that now belongs to the newer object generation.
|
|
452
439
|
return Promise.resolve();
|
|
@@ -470,16 +457,23 @@ export class DefaultZLinkSpotManager {
|
|
|
470
457
|
}
|
|
471
458
|
|
|
472
459
|
relocationActivations(meshName: string): readonly ZLinkSpotActivation[] {
|
|
473
|
-
return this.activations
|
|
474
|
-
|
|
475
|
-
|
|
460
|
+
return this.activations
|
|
461
|
+
.activeActivations()
|
|
462
|
+
.filter(
|
|
463
|
+
(activation) =>
|
|
464
|
+
activation.meshName === meshName &&
|
|
465
|
+
this.activations.resolve(meshName, activation.spotId) === activation
|
|
466
|
+
);
|
|
476
467
|
}
|
|
477
468
|
|
|
478
469
|
activeSpotCount(meshName: string): number {
|
|
479
470
|
return this.activations.list(meshName).length;
|
|
480
471
|
}
|
|
481
472
|
|
|
482
|
-
instanceActivationConcurrency(meshName: string): {
|
|
473
|
+
instanceActivationConcurrency(meshName: string): {
|
|
474
|
+
readonly active: number;
|
|
475
|
+
readonly limit: number;
|
|
476
|
+
} {
|
|
483
477
|
const limit = this.options.activationConcurrencyLimitProvider?.(meshName) ?? 128;
|
|
484
478
|
return { active: this.instanceActivationGates.get(meshName)?.active ?? 0, limit };
|
|
485
479
|
}
|
|
@@ -534,9 +528,7 @@ export class DefaultZLinkSpotManager {
|
|
|
534
528
|
await activation.nativeSpot?.dispose();
|
|
535
529
|
}
|
|
536
530
|
|
|
537
|
-
async completeRelocationSource(
|
|
538
|
-
activation: ZLinkSpotActivation
|
|
539
|
-
): Promise<void> {
|
|
531
|
+
async completeRelocationSource(activation: ZLinkSpotActivation): Promise<void> {
|
|
540
532
|
this.activations.detachRelocated(activation.meshName, activation.spotId);
|
|
541
533
|
await activation.nativeSpot?.dispose();
|
|
542
534
|
}
|
|
@@ -598,10 +590,7 @@ export class DefaultZLinkSpotManager {
|
|
|
598
590
|
);
|
|
599
591
|
}
|
|
600
592
|
if (current.objectGeneration === objectGeneration) return;
|
|
601
|
-
if (
|
|
602
|
-
current.objectGeneration === undefined
|
|
603
|
-
|| current.objectGeneration > objectGeneration
|
|
604
|
-
) {
|
|
593
|
+
if (current.objectGeneration === undefined || current.objectGeneration > objectGeneration) {
|
|
605
594
|
throw createInternalFrameworkException(
|
|
606
595
|
ZLinkFrameworkInternalErrorKind.SpotGenerationStale,
|
|
607
596
|
`Instance Spot '${String(spotId)}' has a newer application generation.`
|
|
@@ -616,9 +605,12 @@ export class DefaultZLinkSpotManager {
|
|
|
616
605
|
continue;
|
|
617
606
|
}
|
|
618
607
|
|
|
619
|
-
const lifecycleActivation = this.activations
|
|
620
|
-
|
|
621
|
-
|
|
608
|
+
const lifecycleActivation = this.activations
|
|
609
|
+
.activeActivations()
|
|
610
|
+
.find(
|
|
611
|
+
(activation) =>
|
|
612
|
+
activation.meshName === meshName && String(activation.spotId) === String(spotId)
|
|
613
|
+
);
|
|
622
614
|
if (lifecycleActivation?.isIdleEvicting === true) {
|
|
623
615
|
throw createInternalFrameworkException(
|
|
624
616
|
ZLinkFrameworkInternalErrorKind.SpotGenerationStale,
|
|
@@ -629,9 +621,7 @@ export class DefaultZLinkSpotManager {
|
|
|
629
621
|
let pending = this.pendingInstanceMaterializations.get(materializationKey);
|
|
630
622
|
if (pending === undefined) {
|
|
631
623
|
const siblings = this.pendingInstanceMaterializationsByPrefix.get(materializationPrefix);
|
|
632
|
-
const otherPending = siblings === undefined
|
|
633
|
-
? undefined
|
|
634
|
-
: siblings.values().next().value;
|
|
624
|
+
const otherPending = siblings === undefined ? undefined : siblings.values().next().value;
|
|
635
625
|
if (otherPending !== undefined) {
|
|
636
626
|
await awaitWithAbort(otherPending, signal);
|
|
637
627
|
continue;
|
|
@@ -639,19 +629,14 @@ export class DefaultZLinkSpotManager {
|
|
|
639
629
|
}
|
|
640
630
|
if (pending === undefined) {
|
|
641
631
|
const metric = this.options.metrics?.startInstanceSpotActivation(meshName, instanceType);
|
|
642
|
-
pending = this.activationLifecycle
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
spotId,
|
|
647
|
-
objectGeneration,
|
|
648
|
-
signal
|
|
649
|
-
).then(
|
|
650
|
-
activation => {
|
|
632
|
+
pending = this.activationLifecycle
|
|
633
|
+
.materializeInstance(meshName, instanceType, factory, spotId, objectGeneration, signal)
|
|
634
|
+
.then(
|
|
635
|
+
(activation) => {
|
|
651
636
|
metric?.complete('ready');
|
|
652
637
|
return activation;
|
|
653
638
|
},
|
|
654
|
-
error => {
|
|
639
|
+
(error) => {
|
|
655
640
|
metric?.complete(instanceActivationOutcome(error));
|
|
656
641
|
throw error;
|
|
657
642
|
}
|
|
@@ -663,18 +648,20 @@ export class DefaultZLinkSpotManager {
|
|
|
663
648
|
this.pendingInstanceMaterializationsByPrefix.set(materializationPrefix, siblings);
|
|
664
649
|
}
|
|
665
650
|
siblings.set(materializationKey, pending);
|
|
666
|
-
void pending
|
|
667
|
-
|
|
668
|
-
this.pendingInstanceMaterializations.
|
|
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);
|
|
651
|
+
void pending
|
|
652
|
+
.finally(() => {
|
|
653
|
+
if (this.pendingInstanceMaterializations.get(materializationKey) === pending) {
|
|
654
|
+
this.pendingInstanceMaterializations.delete(materializationKey);
|
|
675
655
|
}
|
|
676
|
-
|
|
677
|
-
|
|
656
|
+
const bucket = this.pendingInstanceMaterializationsByPrefix.get(materializationPrefix);
|
|
657
|
+
if (bucket !== undefined && bucket.get(materializationKey) === pending) {
|
|
658
|
+
bucket.delete(materializationKey);
|
|
659
|
+
if (bucket.size === 0) {
|
|
660
|
+
this.pendingInstanceMaterializationsByPrefix.delete(materializationPrefix);
|
|
661
|
+
}
|
|
662
|
+
}
|
|
663
|
+
})
|
|
664
|
+
.catch(() => undefined);
|
|
678
665
|
}
|
|
679
666
|
await pending;
|
|
680
667
|
return;
|
|
@@ -718,12 +705,15 @@ export class DefaultZLinkSpotManager {
|
|
|
718
705
|
readonly meshName: string;
|
|
719
706
|
readonly limit: number;
|
|
720
707
|
active: number;
|
|
721
|
-
readonly waiters: Array<
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
708
|
+
readonly waiters: Array<
|
|
709
|
+
| {
|
|
710
|
+
resolve: (release: () => void) => void;
|
|
711
|
+
reject: (error: unknown) => void;
|
|
712
|
+
signal?: AbortSignal;
|
|
713
|
+
abort?: () => void;
|
|
714
|
+
}
|
|
715
|
+
| undefined
|
|
716
|
+
>;
|
|
727
717
|
waiterHead: number;
|
|
728
718
|
}): void {
|
|
729
719
|
while (gate.waiterHead < gate.waiters.length) {
|
|
@@ -745,14 +735,12 @@ export class DefaultZLinkSpotManager {
|
|
|
745
735
|
this.options.onInstanceActivationConcurrencyChanged?.(gate.meshName);
|
|
746
736
|
}
|
|
747
737
|
|
|
748
|
-
isInstanceMaterialized(
|
|
749
|
-
meshName: string,
|
|
750
|
-
instanceType: string,
|
|
751
|
-
spotId: RoutingId
|
|
752
|
-
): boolean {
|
|
738
|
+
isInstanceMaterialized(meshName: string, instanceType: string, spotId: RoutingId): boolean {
|
|
753
739
|
const activation = this.activations.resolve(meshName, spotId);
|
|
754
|
-
return
|
|
755
|
-
|
|
740
|
+
return (
|
|
741
|
+
activation !== undefined &&
|
|
742
|
+
activation.spotType === this.requireInstanceFactory(meshName, instanceType)
|
|
743
|
+
);
|
|
756
744
|
}
|
|
757
745
|
|
|
758
746
|
isInstanceMaterializing(meshName: string, spotId: RoutingId): boolean {
|
|
@@ -762,8 +750,10 @@ export class DefaultZLinkSpotManager {
|
|
|
762
750
|
|
|
763
751
|
isInstanceClosing(meshName: string, spotId: RoutingId): boolean {
|
|
764
752
|
const key = `${meshName}\0${String(spotId)}`;
|
|
765
|
-
return
|
|
766
|
-
|
|
753
|
+
return (
|
|
754
|
+
this.pendingInstanceCloses.has(key) ||
|
|
755
|
+
this.activations.closingOperation(meshName, spotId) !== undefined
|
|
756
|
+
);
|
|
767
757
|
}
|
|
768
758
|
|
|
769
759
|
async discardInstance(meshName: string, spotId: RoutingId): Promise<void> {
|
|
@@ -780,22 +770,28 @@ export class DefaultZLinkSpotManager {
|
|
|
780
770
|
}
|
|
781
771
|
|
|
782
772
|
isInstanceSpotIdleEvicting(meshName: string, spotId: RoutingId): boolean {
|
|
783
|
-
const activation = this.activations
|
|
784
|
-
|
|
773
|
+
const activation = this.activations
|
|
774
|
+
.activeActivations()
|
|
775
|
+
.find(
|
|
776
|
+
(candidate) =>
|
|
777
|
+
candidate.meshName === meshName && String(candidate.spotId) === String(spotId)
|
|
778
|
+
);
|
|
779
|
+
return (
|
|
780
|
+
activation !== undefined && activation.domain.kind === 'instance' && activation.isIdleEvicting
|
|
785
781
|
);
|
|
786
|
-
return activation !== undefined
|
|
787
|
-
&& activation.domain.kind === 'instance'
|
|
788
|
-
&& activation.isIdleEvicting;
|
|
789
782
|
}
|
|
790
783
|
|
|
791
784
|
beginInstanceSpotIdleEviction(meshName: string, spotId: RoutingId): boolean {
|
|
792
|
-
const activation = this.activations
|
|
793
|
-
|
|
794
|
-
|
|
785
|
+
const activation = this.activations
|
|
786
|
+
.activeActivations()
|
|
787
|
+
.find(
|
|
788
|
+
(candidate) =>
|
|
789
|
+
candidate.meshName === meshName && String(candidate.spotId) === String(spotId)
|
|
790
|
+
);
|
|
795
791
|
if (
|
|
796
|
-
activation === undefined
|
|
797
|
-
|
|
798
|
-
|
|
792
|
+
activation === undefined ||
|
|
793
|
+
activation.domain.kind !== 'instance' ||
|
|
794
|
+
!activation.isIdleFor(
|
|
799
795
|
performance.now(),
|
|
800
796
|
this.options.instanceSpotIdleTimeoutMs?.get(meshName) ?? 0
|
|
801
797
|
)
|
|
@@ -826,17 +822,18 @@ export class DefaultZLinkSpotManager {
|
|
|
826
822
|
await pendingClose;
|
|
827
823
|
return true;
|
|
828
824
|
}
|
|
829
|
-
const deferredRelease =
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
&& this.activations.closingOperation(meshName, spotId) === undefined
|
|
833
|
-
) {
|
|
825
|
+
const deferredRelease =
|
|
826
|
+
this.deferredInstanceAuthorityReleases.get(key)?.has(objectGeneration) === true;
|
|
827
|
+
if (!deferredRelease && this.activations.closingOperation(meshName, spotId) === undefined) {
|
|
834
828
|
return false;
|
|
835
829
|
}
|
|
836
|
-
const currentApplication = this.options.instanceSpotApplicationTargetProvider?.(
|
|
830
|
+
const currentApplication = this.options.instanceSpotApplicationTargetProvider?.(
|
|
831
|
+
meshName,
|
|
832
|
+
spotId
|
|
833
|
+
);
|
|
837
834
|
if (
|
|
838
|
-
currentApplication !== undefined
|
|
839
|
-
|
|
835
|
+
currentApplication !== undefined &&
|
|
836
|
+
currentApplication.objectGeneration !== objectGeneration
|
|
840
837
|
) {
|
|
841
838
|
this.removeDeferredInstanceAuthorityRelease(key, objectGeneration);
|
|
842
839
|
return false;
|
|
@@ -848,11 +845,9 @@ export class DefaultZLinkSpotManager {
|
|
|
848
845
|
|
|
849
846
|
beginInstanceTerminal(meshName: string, spotId: RoutingId, objectGeneration: bigint): void {
|
|
850
847
|
const key = `${meshName}\0${String(spotId)}`;
|
|
851
|
-
this.pendingInstanceTerminals.set(
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
);
|
|
855
|
-
const generations = this.pendingInstanceTerminalGenerations.get(key) ?? new Map<string, number>();
|
|
848
|
+
this.pendingInstanceTerminals.set(key, (this.pendingInstanceTerminals.get(key) ?? 0) + 1);
|
|
849
|
+
const generations =
|
|
850
|
+
this.pendingInstanceTerminalGenerations.get(key) ?? new Map<string, number>();
|
|
856
851
|
const generationKey = objectGeneration.toString();
|
|
857
852
|
generations.set(generationKey, (generations.get(generationKey) ?? 0) + 1);
|
|
858
853
|
this.pendingInstanceTerminalGenerations.set(key, generations);
|
|
@@ -885,14 +880,13 @@ export class DefaultZLinkSpotManager {
|
|
|
885
880
|
spotId: RoutingId,
|
|
886
881
|
objectGeneration: bigint
|
|
887
882
|
): Promise<void> {
|
|
888
|
-
return
|
|
889
|
-
|
|
883
|
+
return (
|
|
884
|
+
this.options.releaseInstanceAuthority?.(meshName, spotId, objectGeneration) ??
|
|
885
|
+
Promise.resolve()
|
|
886
|
+
);
|
|
890
887
|
}
|
|
891
888
|
|
|
892
|
-
private requireInstanceFactory(
|
|
893
|
-
meshName: string,
|
|
894
|
-
instanceType: string
|
|
895
|
-
): Type<ZLinkInstanceSpot> {
|
|
889
|
+
private requireInstanceFactory(meshName: string, instanceType: string): Type<ZLinkInstanceSpot> {
|
|
896
890
|
const factory = this.options.instanceSpotFactories?.get(meshName)?.get(instanceType);
|
|
897
891
|
if (factory === undefined) {
|
|
898
892
|
throw new ZLinkConfigurationException(
|
|
@@ -905,8 +899,9 @@ export class DefaultZLinkSpotManager {
|
|
|
905
899
|
private scheduleIdleSweep(): void {
|
|
906
900
|
if (this.idleSweepTimer !== undefined) return;
|
|
907
901
|
if (!this.hasIdleSweepTarget()) return;
|
|
908
|
-
const delays = [...(this.options.instanceSpotIdleTimeoutMs?.values() ?? [])]
|
|
909
|
-
|
|
902
|
+
const delays = [...(this.options.instanceSpotIdleTimeoutMs?.values() ?? [])].filter(
|
|
903
|
+
(value) => value > 0
|
|
904
|
+
);
|
|
910
905
|
if (delays.length === 0) return;
|
|
911
906
|
const delay = Math.max(1, Math.min(...delays));
|
|
912
907
|
const timer = setTimeout(() => {
|
|
@@ -929,21 +924,19 @@ export class DefaultZLinkSpotManager {
|
|
|
929
924
|
for (const activation of this.activations.nextActiveActivationBatch()) {
|
|
930
925
|
const timeoutMs = this.options.instanceSpotIdleTimeoutMs?.get(activation.meshName) ?? 0;
|
|
931
926
|
if (
|
|
932
|
-
timeoutMs <= 0
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
927
|
+
timeoutMs <= 0 ||
|
|
928
|
+
activation.domain.kind !== 'instance' ||
|
|
929
|
+
!activation.isIdleFor(now, timeoutMs) ||
|
|
930
|
+
!activation.beginIdleEviction()
|
|
936
931
|
) {
|
|
937
932
|
continue;
|
|
938
933
|
}
|
|
939
934
|
let durableClosing: { restoreReady(): Promise<void> } | undefined;
|
|
940
935
|
try {
|
|
941
|
-
durableClosing = await (
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
) ?? Promise.resolve({ restoreReady: async () => undefined })
|
|
946
|
-
);
|
|
936
|
+
durableClosing = await (this.options.beginInstanceIdleClosingAuthority?.(
|
|
937
|
+
activation.meshName,
|
|
938
|
+
activation.spotId
|
|
939
|
+
) ?? Promise.resolve({ restoreReady: async () => undefined }));
|
|
947
940
|
} catch (error) {
|
|
948
941
|
activation.abortIdleEviction();
|
|
949
942
|
throw error;
|
|
@@ -1014,9 +1007,10 @@ export class DefaultZLinkSpotManager {
|
|
|
1014
1007
|
const args = normalizeSpotCreateArgs(requestOrSignal, signal);
|
|
1015
1008
|
this.options.admission?.requireRequest('SPOT create', meshName);
|
|
1016
1009
|
const spotId = this.activations.allocateSpotId(meshName);
|
|
1017
|
-
const ownedRequest =
|
|
1018
|
-
|
|
1019
|
-
|
|
1010
|
+
const ownedRequest =
|
|
1011
|
+
args.request === undefined
|
|
1012
|
+
? RuntimeMessage.from(Buffer.alloc(0))
|
|
1013
|
+
: encodeFrameworkPayloadMessage(args.request, this.options.messageSerializers);
|
|
1020
1014
|
try {
|
|
1021
1015
|
return await this.createActivation(meshName, spotType, spotId, ownedRequest, args.signal);
|
|
1022
1016
|
} finally {
|
|
@@ -1074,9 +1068,10 @@ export class DefaultZLinkSpotManager {
|
|
|
1074
1068
|
throwIfAborted(args.signal);
|
|
1075
1069
|
const operation = this.activations.getOrBegin(meshName, spotType, spotId, async () => {
|
|
1076
1070
|
this.options.admission?.requireRequest('SPOT create', meshName);
|
|
1077
|
-
const ownedRequest =
|
|
1078
|
-
|
|
1079
|
-
|
|
1071
|
+
const ownedRequest =
|
|
1072
|
+
args.request === undefined
|
|
1073
|
+
? RuntimeMessage.from(Buffer.alloc(0))
|
|
1074
|
+
: encodeFrameworkPayloadMessage(args.request, this.options.messageSerializers);
|
|
1080
1075
|
try {
|
|
1081
1076
|
return await this.createActivation(
|
|
1082
1077
|
meshName,
|
|
@@ -1104,25 +1099,29 @@ export class DefaultZLinkSpotManager {
|
|
|
1104
1099
|
}
|
|
1105
1100
|
|
|
1106
1101
|
async drainForShutdown(meshName: string, signal?: AbortSignal, deadline?: Date): Promise<void> {
|
|
1107
|
-
const results = await Promise.allSettled(
|
|
1108
|
-
.
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1102
|
+
const results = await Promise.allSettled(
|
|
1103
|
+
this.activations
|
|
1104
|
+
.activeActivations()
|
|
1105
|
+
.filter((activation) => activation.meshName === meshName)
|
|
1106
|
+
.map((activation) =>
|
|
1107
|
+
this.closeWithReason(
|
|
1108
|
+
meshName,
|
|
1109
|
+
activation.spotId,
|
|
1110
|
+
signal,
|
|
1111
|
+
ZLinkSpotCloseReason.HostShutdown,
|
|
1112
|
+
deadline
|
|
1113
|
+
)
|
|
1114
|
+
)
|
|
1115
|
+
);
|
|
1112
1116
|
const errors = results
|
|
1113
1117
|
.filter((result): result is PromiseRejectedResult => result.status === 'rejected')
|
|
1114
|
-
.map(result => result.reason);
|
|
1118
|
+
.map((result) => result.reason);
|
|
1115
1119
|
if (errors.length === 1) throw errors[0];
|
|
1116
1120
|
if (errors.length > 1) throw new AggregateError(errors, 'Spot shutdown cleanup failed.');
|
|
1117
1121
|
}
|
|
1118
1122
|
|
|
1119
1123
|
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
|
-
);
|
|
1124
|
+
return await this.closeWithReason(meshName, spotId, signal, ZLinkSpotCloseReason.ExplicitClose);
|
|
1126
1125
|
}
|
|
1127
1126
|
|
|
1128
1127
|
private async closeWithReason(
|
|
@@ -1166,9 +1165,10 @@ export class DefaultZLinkSpotManager {
|
|
|
1166
1165
|
};
|
|
1167
1166
|
|
|
1168
1167
|
if (isInstance) {
|
|
1169
|
-
const beginAuthorityClose =
|
|
1170
|
-
|
|
1171
|
-
|
|
1168
|
+
const beginAuthorityClose =
|
|
1169
|
+
reason === ZLinkSpotCloseReason.ExplicitClose
|
|
1170
|
+
? this.options.beginInstanceClosingAuthority
|
|
1171
|
+
: undefined;
|
|
1172
1172
|
// Register the close gate before waiting for the current application
|
|
1173
1173
|
// and activation-authority terminal completions. A close requested from
|
|
1174
1174
|
// a handler cannot publish Closing until that handler's durable inbox
|
|
@@ -1182,9 +1182,10 @@ export class DefaultZLinkSpotManager {
|
|
|
1182
1182
|
if (waitForApplication !== undefined) {
|
|
1183
1183
|
await waitForApplication;
|
|
1184
1184
|
}
|
|
1185
|
-
const closingAuthority =
|
|
1186
|
-
|
|
1187
|
-
|
|
1185
|
+
const closingAuthority =
|
|
1186
|
+
beginAuthorityClose === undefined
|
|
1187
|
+
? undefined
|
|
1188
|
+
: await beginAuthorityClose(meshName, spotId);
|
|
1188
1189
|
if (beginAuthorityClose !== undefined && closingAuthority === undefined) {
|
|
1189
1190
|
return false;
|
|
1190
1191
|
}
|
|
@@ -1209,7 +1210,9 @@ export class DefaultZLinkSpotManager {
|
|
|
1209
1210
|
// that detached close finishes.
|
|
1210
1211
|
this.options.detachedTaskRunner?.runDetached(
|
|
1211
1212
|
`instance spot close ${String(spotId)}`,
|
|
1212
|
-
async () => {
|
|
1213
|
+
async () => {
|
|
1214
|
+
await trackedClosePromise;
|
|
1215
|
+
}
|
|
1213
1216
|
);
|
|
1214
1217
|
if (this.options.detachedTaskRunner === undefined) {
|
|
1215
1218
|
void trackedClosePromise.catch(() => undefined);
|
|
@@ -1225,10 +1228,9 @@ export class DefaultZLinkSpotManager {
|
|
|
1225
1228
|
}
|
|
1226
1229
|
if (currentTurn) {
|
|
1227
1230
|
if (operation.started) {
|
|
1228
|
-
this.options.detachedTaskRunner?.runDetached(
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
);
|
|
1231
|
+
this.options.detachedTaskRunner?.runDetached(`spot close ${String(spotId)}`, async () => {
|
|
1232
|
+
await operation.ready;
|
|
1233
|
+
});
|
|
1232
1234
|
if (this.options.detachedTaskRunner === undefined) {
|
|
1233
1235
|
void operation.ready.catch(() => undefined);
|
|
1234
1236
|
}
|
|
@@ -1292,7 +1294,8 @@ export class DefaultZLinkSpotManager {
|
|
|
1292
1294
|
return undefined;
|
|
1293
1295
|
}
|
|
1294
1296
|
return {
|
|
1295
|
-
routerChannelId:
|
|
1297
|
+
routerChannelId:
|
|
1298
|
+
this.options.spotRouterChannelIdForMesh?.(activation.meshName) ?? activation.meshName,
|
|
1296
1299
|
targetNodeRid: nodeRid,
|
|
1297
1300
|
spotId: activation.spotId,
|
|
1298
1301
|
spotKind: ZLinkSpotKind.User,
|
|
@@ -1304,7 +1307,9 @@ export class DefaultZLinkSpotManager {
|
|
|
1304
1307
|
spotId: RoutingId,
|
|
1305
1308
|
actor: ZLinkActor,
|
|
1306
1309
|
request: Message,
|
|
1307
|
-
commit: (
|
|
1310
|
+
commit: (
|
|
1311
|
+
spot: ZLinkSpot
|
|
1312
|
+
) => Promise<ZLinkActorJoinRollback | void> | ZLinkActorJoinRollback | void,
|
|
1308
1313
|
signal?: AbortSignal,
|
|
1309
1314
|
leaveSource?: () => Promise<void>,
|
|
1310
1315
|
contentType = 'application/json'
|
|
@@ -1322,11 +1327,7 @@ export class DefaultZLinkSpotManager {
|
|
|
1322
1327
|
);
|
|
1323
1328
|
}
|
|
1324
1329
|
|
|
1325
|
-
async leaveActor(
|
|
1326
|
-
spotId: RoutingId,
|
|
1327
|
-
actor: ZLinkActor,
|
|
1328
|
-
signal?: AbortSignal
|
|
1329
|
-
): Promise<void> {
|
|
1330
|
+
async leaveActor(spotId: RoutingId, actor: ZLinkActor, signal?: AbortSignal): Promise<void> {
|
|
1330
1331
|
const meshName = this.activations.resolveUnique(spotId)?.meshName;
|
|
1331
1332
|
await this.actorMembership.leaveActor(spotId, actor, signal, meshName);
|
|
1332
1333
|
}
|
|
@@ -1440,11 +1441,7 @@ export class DefaultZLinkSpotManager {
|
|
|
1440
1441
|
if (activation === undefined) {
|
|
1441
1442
|
throw new ZLinkConfigurationException(`Spot '${spotId}' is not active.`);
|
|
1442
1443
|
}
|
|
1443
|
-
return this.activationLifecycle.admitActorPacketPrefix(
|
|
1444
|
-
activation,
|
|
1445
|
-
actorId,
|
|
1446
|
-
records
|
|
1447
|
-
);
|
|
1444
|
+
return this.activationLifecycle.admitActorPacketPrefix(activation, actorId, records);
|
|
1448
1445
|
}
|
|
1449
1446
|
|
|
1450
1447
|
async dispatchRoutedSpotSend(
|
|
@@ -1477,7 +1474,11 @@ export class DefaultZLinkSpotManager {
|
|
|
1477
1474
|
return await this.routedSpotPackets.request<TReply>(spotId, packetName, request, context);
|
|
1478
1475
|
}
|
|
1479
1476
|
|
|
1480
|
-
async dispatchMeshSpot(
|
|
1477
|
+
async dispatchMeshSpot(
|
|
1478
|
+
meshName: string,
|
|
1479
|
+
owner: ReadyRecord,
|
|
1480
|
+
record: ReceiveRecord
|
|
1481
|
+
): Promise<void> {
|
|
1481
1482
|
const spotId = owner.spotId as unknown as RoutingId | null;
|
|
1482
1483
|
if (spotId === null) {
|
|
1483
1484
|
throw new ZLinkConfigurationException('MeshNode Spot record is missing the owner Spot RID.');
|
|
@@ -1490,7 +1491,9 @@ export class DefaultZLinkSpotManager {
|
|
|
1490
1491
|
);
|
|
1491
1492
|
}
|
|
1492
1493
|
if (record.topic === null || record.topic.length === 0) {
|
|
1493
|
-
throw new ZLinkConfigurationException(
|
|
1494
|
+
throw new ZLinkConfigurationException(
|
|
1495
|
+
'MeshNode Spot multicast record is missing its topic.'
|
|
1496
|
+
);
|
|
1494
1497
|
}
|
|
1495
1498
|
await activation.actorDispatch.dispatchSubscriptionRecord(
|
|
1496
1499
|
record.topic,
|
|
@@ -1505,9 +1508,10 @@ export class DefaultZLinkSpotManager {
|
|
|
1505
1508
|
this.options.dispatchErrors?.flow.flowCreationEnabled() ?? true
|
|
1506
1509
|
);
|
|
1507
1510
|
const packetName = envelope.packetName;
|
|
1508
|
-
const codecs =
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
+
const codecs =
|
|
1512
|
+
this.options.messageSerializers === undefined
|
|
1513
|
+
? undefined
|
|
1514
|
+
: { serializers: this.options.messageSerializers };
|
|
1511
1515
|
const decodePayload = () => decodeChannelPayload(envelope, codecs);
|
|
1512
1516
|
const context = {
|
|
1513
1517
|
channelName: envelope.header.channelName,
|
|
@@ -1523,7 +1527,9 @@ export class DefaultZLinkSpotManager {
|
|
|
1523
1527
|
return;
|
|
1524
1528
|
}
|
|
1525
1529
|
if (record.kind !== ReceiveKind.SpotRequest) {
|
|
1526
|
-
throw new ZLinkConfigurationException(
|
|
1530
|
+
throw new ZLinkConfigurationException(
|
|
1531
|
+
`Unsupported MeshNode Spot record kind '${record.kind}'.`
|
|
1532
|
+
);
|
|
1527
1533
|
}
|
|
1528
1534
|
try {
|
|
1529
1535
|
await this.ensureInstanceApplicationActivation(meshName, spotId);
|
|
@@ -1533,12 +1539,18 @@ export class DefaultZLinkSpotManager {
|
|
|
1533
1539
|
decodePayload,
|
|
1534
1540
|
context
|
|
1535
1541
|
);
|
|
1536
|
-
requireMeshSpotReply(
|
|
1542
|
+
requireMeshSpotReply(
|
|
1543
|
+
record.reply(encodeChannelReplyParts(envelope.header, response, codecs))
|
|
1544
|
+
);
|
|
1537
1545
|
} catch (error) {
|
|
1538
|
-
requireMeshSpotReply(
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1546
|
+
requireMeshSpotReply(
|
|
1547
|
+
record.reply(
|
|
1548
|
+
encodeChannelErrorReplyParts(
|
|
1549
|
+
envelope.header,
|
|
1550
|
+
error instanceof Error ? error.message : String(error)
|
|
1551
|
+
)
|
|
1552
|
+
)
|
|
1553
|
+
);
|
|
1542
1554
|
}
|
|
1543
1555
|
}
|
|
1544
1556
|
|
|
@@ -1551,16 +1563,12 @@ export class DefaultZLinkSpotManager {
|
|
|
1551
1563
|
for (;;) {
|
|
1552
1564
|
const current = this.activations.resolve(meshName, spotId);
|
|
1553
1565
|
if (
|
|
1554
|
-
current !== undefined
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
)
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
target.stableType,
|
|
1561
|
-
spotId,
|
|
1562
|
-
target.objectGeneration
|
|
1563
|
-
);
|
|
1566
|
+
current !== undefined &&
|
|
1567
|
+
current.objectGeneration === target.objectGeneration &&
|
|
1568
|
+
current.spotType === this.requireInstanceFactory(meshName, target.stableType)
|
|
1569
|
+
)
|
|
1570
|
+
return;
|
|
1571
|
+
await this.materializeInstance(meshName, target.stableType, spotId, target.objectGeneration);
|
|
1564
1572
|
const latest = this.options.instanceSpotApplicationTargetProvider?.(meshName, spotId);
|
|
1565
1573
|
if (latest === undefined) {
|
|
1566
1574
|
throw createInternalFrameworkException(
|
|
@@ -1613,16 +1621,19 @@ export class DefaultZLinkSpotManager {
|
|
|
1613
1621
|
);
|
|
1614
1622
|
}
|
|
1615
1623
|
const target = this.options.instanceSpotApplicationTargetProvider?.(meshName, spotId);
|
|
1616
|
-
if (
|
|
1617
|
-
|
|
1624
|
+
if (
|
|
1625
|
+
target !== undefined &&
|
|
1626
|
+
activation.domain.objectGeneration !== target.objectGeneration
|
|
1627
|
+
) {
|
|
1618
1628
|
throw createInternalFrameworkException(
|
|
1619
1629
|
ZLinkFrameworkInternalErrorKind.SpotGenerationStale,
|
|
1620
1630
|
`Instance Spot target '${String(spotId)}' application generation is stale.`
|
|
1621
1631
|
);
|
|
1622
1632
|
}
|
|
1623
|
-
const codecs =
|
|
1624
|
-
|
|
1625
|
-
|
|
1633
|
+
const codecs =
|
|
1634
|
+
this.options.messageSerializers === undefined
|
|
1635
|
+
? undefined
|
|
1636
|
+
: { serializers: this.options.messageSerializers };
|
|
1626
1637
|
const decodePayload = () => decodeChannelPayload(envelope, codecs);
|
|
1627
1638
|
const context = {
|
|
1628
1639
|
channelName: envelope.header.channelName,
|
|
@@ -1630,7 +1641,8 @@ export class DefaultZLinkSpotManager {
|
|
|
1630
1641
|
awaitFirstHandlerTurn: record.kind === ReceiveKind.InstanceSpotActivation,
|
|
1631
1642
|
workOptions: zlinkSerialWorkOptions(
|
|
1632
1643
|
envelope.payload.byteLength,
|
|
1633
|
-
record.applicationMetadata?.byteLength ??
|
|
1644
|
+
record.applicationMetadata?.byteLength ??
|
|
1645
|
+
zlinkMetadataByteLength(envelope.header.metadata)
|
|
1634
1646
|
)
|
|
1635
1647
|
};
|
|
1636
1648
|
this.traceInstanceMessage(
|
|
@@ -1652,7 +1664,12 @@ export class DefaultZLinkSpotManager {
|
|
|
1652
1664
|
'ready',
|
|
1653
1665
|
target?.stableType
|
|
1654
1666
|
);
|
|
1655
|
-
await this.routedSpotPackets.sendEncoded(
|
|
1667
|
+
await this.routedSpotPackets.sendEncoded(
|
|
1668
|
+
spotId,
|
|
1669
|
+
envelope.packetName,
|
|
1670
|
+
decodePayload,
|
|
1671
|
+
context
|
|
1672
|
+
);
|
|
1656
1673
|
this.traceInstanceMessage(
|
|
1657
1674
|
ZLinkMessageFlowOutcome.Completed,
|
|
1658
1675
|
meshName,
|
|
@@ -1679,7 +1696,9 @@ export class DefaultZLinkSpotManager {
|
|
|
1679
1696
|
decodePayload,
|
|
1680
1697
|
context
|
|
1681
1698
|
);
|
|
1682
|
-
requireMeshSpotReply(
|
|
1699
|
+
requireMeshSpotReply(
|
|
1700
|
+
record.reply(encodeChannelReplyParts(envelope.header, response, codecs))
|
|
1701
|
+
);
|
|
1683
1702
|
this.traceInstanceMessage(
|
|
1684
1703
|
ZLinkMessageFlowOutcome.Replied,
|
|
1685
1704
|
meshName,
|
|
@@ -1713,7 +1732,8 @@ export class DefaultZLinkSpotManager {
|
|
|
1713
1732
|
correlationId: envelope.header.correlationId ?? undefined,
|
|
1714
1733
|
sourceRid: record.sourceNodeRid === null ? undefined : String(record.sourceNodeRid),
|
|
1715
1734
|
spotId: String(spotId),
|
|
1716
|
-
instanceSpotType: this.options.instanceSpotApplicationTargetProvider?.(meshName, spotId)
|
|
1735
|
+
instanceSpotType: this.options.instanceSpotApplicationTargetProvider?.(meshName, spotId)
|
|
1736
|
+
?.stableType,
|
|
1717
1737
|
activationState: 'closing',
|
|
1718
1738
|
flowId: envelope.header.flowId,
|
|
1719
1739
|
flowOrigin: envelope.header.flowOrigin,
|
|
@@ -1721,10 +1741,14 @@ export class DefaultZLinkSpotManager {
|
|
|
1721
1741
|
action: ZLinkDispatchErrorAction.ReplyError,
|
|
1722
1742
|
error
|
|
1723
1743
|
});
|
|
1724
|
-
requireMeshSpotReply(
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
1744
|
+
requireMeshSpotReply(
|
|
1745
|
+
record.reply(
|
|
1746
|
+
encodeChannelErrorReplyParts(
|
|
1747
|
+
envelope.header,
|
|
1748
|
+
error instanceof Error ? error.message : String(error)
|
|
1749
|
+
)
|
|
1750
|
+
)
|
|
1751
|
+
);
|
|
1728
1752
|
}
|
|
1729
1753
|
});
|
|
1730
1754
|
}
|
|
@@ -1749,9 +1773,10 @@ export class DefaultZLinkSpotManager {
|
|
|
1749
1773
|
flow.trace({
|
|
1750
1774
|
outcome,
|
|
1751
1775
|
surface: ZLinkDispatchErrorSurface.InstanceSpot,
|
|
1752
|
-
messageKind:
|
|
1753
|
-
|
|
1754
|
-
|
|
1776
|
+
messageKind:
|
|
1777
|
+
record.operationKind === OperationKind.InstanceSpotRequest
|
|
1778
|
+
? ZLinkDispatchMessageKind.Request
|
|
1779
|
+
: ZLinkDispatchMessageKind.Send,
|
|
1755
1780
|
packetName: envelope.packetName,
|
|
1756
1781
|
channelName: envelope.header.channelName,
|
|
1757
1782
|
meshName,
|
|
@@ -1766,11 +1791,15 @@ export class DefaultZLinkSpotManager {
|
|
|
1766
1791
|
});
|
|
1767
1792
|
}
|
|
1768
1793
|
|
|
1769
|
-
async dispatchMeshActor(
|
|
1794
|
+
async dispatchMeshActor(
|
|
1795
|
+
meshName: string,
|
|
1796
|
+
owner: ReadyRecord,
|
|
1797
|
+
record: ReceiveRecord
|
|
1798
|
+
): Promise<void> {
|
|
1770
1799
|
const spotId = owner.spotId as unknown as RoutingId | null;
|
|
1771
1800
|
const entrySpotId = this.options.entryNodeRidProvider?.() ?? this.options.entryNodeRid;
|
|
1772
|
-
const targetsEntrySpot =
|
|
1773
|
-
|| (entrySpotId !== undefined && spotId === entrySpotId);
|
|
1801
|
+
const targetsEntrySpot =
|
|
1802
|
+
spotId === null || (entrySpotId !== undefined && spotId === entrySpotId);
|
|
1774
1803
|
const actor = owner.actor;
|
|
1775
1804
|
if (actor === null) {
|
|
1776
1805
|
throw new ZLinkConfigurationException('MeshNode Actor record is missing its Actor owner.');
|
|
@@ -1786,24 +1815,26 @@ export class DefaultZLinkSpotManager {
|
|
|
1786
1815
|
meshName,
|
|
1787
1816
|
nodeRid: String(actor.nodeRid)
|
|
1788
1817
|
};
|
|
1789
|
-
const responseActorRef =
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
|
|
1818
|
+
const responseActorRef =
|
|
1819
|
+
record.sourceBindingGeneration > 0n
|
|
1820
|
+
? ({
|
|
1821
|
+
...resolvedActorRef,
|
|
1822
|
+
bindingGeneration: record.sourceBindingGeneration
|
|
1823
|
+
} as ActorRef)
|
|
1824
|
+
: resolvedActorRef;
|
|
1795
1825
|
const ownerActorRef = responseActorRef;
|
|
1796
1826
|
const requestTerminalState = { prepared: false, submitted: false };
|
|
1797
1827
|
const requestTerminal = request
|
|
1798
1828
|
? Object.assign(
|
|
1799
1829
|
(response: unknown, preparedReply?: unknown) => {
|
|
1800
|
-
const encoded =
|
|
1801
|
-
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
|
|
1830
|
+
const encoded =
|
|
1831
|
+
preparedReply === undefined
|
|
1832
|
+
? this.encodeMeshActorReply(
|
|
1833
|
+
record.parts[0],
|
|
1834
|
+
ZLinkStreamMessageKind.Response,
|
|
1835
|
+
response
|
|
1836
|
+
)
|
|
1837
|
+
: (preparedReply as readonly Buffer[]);
|
|
1807
1838
|
requireMeshSpotReply(record.reply(encoded));
|
|
1808
1839
|
requestTerminalState.submitted = true;
|
|
1809
1840
|
},
|
|
@@ -1822,39 +1853,39 @@ export class DefaultZLinkSpotManager {
|
|
|
1822
1853
|
: undefined;
|
|
1823
1854
|
try {
|
|
1824
1855
|
if (this.formalRemoteTransfers.has(actor.actorId)) {
|
|
1825
|
-
throw new Error(
|
|
1826
|
-
`Actor '${actor.actorId}' target transfer reconciliation is not complete.`
|
|
1827
|
-
);
|
|
1856
|
+
throw new Error(`Actor '${actor.actorId}' target transfer reconciliation is not complete.`);
|
|
1828
1857
|
}
|
|
1829
1858
|
const response = targetsEntrySpot
|
|
1830
1859
|
? await this.options.dispatchEntryActorPacket?.(
|
|
1831
|
-
|
|
1832
|
-
|
|
1833
|
-
|
|
1834
|
-
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
|
|
1860
|
+
actor.actorId,
|
|
1861
|
+
record.parts,
|
|
1862
|
+
request,
|
|
1863
|
+
undefined,
|
|
1864
|
+
ownerActorRef,
|
|
1865
|
+
requestTerminal,
|
|
1866
|
+
record.messageFollowOrigin
|
|
1867
|
+
)
|
|
1839
1868
|
: await this.dispatchMeshActorPacket(
|
|
1840
|
-
|
|
1841
|
-
|
|
1842
|
-
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
-
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
|
|
1869
|
+
meshName,
|
|
1870
|
+
spotId,
|
|
1871
|
+
actor.actorId,
|
|
1872
|
+
record.parts,
|
|
1873
|
+
request,
|
|
1874
|
+
ownerActorRef,
|
|
1875
|
+
requestTerminal,
|
|
1876
|
+
record.messageFollowOrigin
|
|
1877
|
+
);
|
|
1849
1878
|
if (targetsEntrySpot && this.options.dispatchEntryActorPacket === undefined) {
|
|
1850
|
-
throw new ZLinkConfigurationException(
|
|
1879
|
+
throw new ZLinkConfigurationException(
|
|
1880
|
+
'MeshNode Entry Spot Actor dispatch is not configured.'
|
|
1881
|
+
);
|
|
1851
1882
|
}
|
|
1852
1883
|
if (request && !requestTerminalState.submitted) {
|
|
1853
|
-
requireMeshSpotReply(
|
|
1854
|
-
record.
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
)
|
|
1884
|
+
requireMeshSpotReply(
|
|
1885
|
+
record.reply(
|
|
1886
|
+
this.encodeMeshActorReply(record.parts[0], ZLinkStreamMessageKind.Response, response)
|
|
1887
|
+
)
|
|
1888
|
+
);
|
|
1858
1889
|
}
|
|
1859
1890
|
} catch (error) {
|
|
1860
1891
|
if (!request) {
|
|
@@ -1863,50 +1894,59 @@ export class DefaultZLinkSpotManager {
|
|
|
1863
1894
|
if (requestTerminalState.prepared || requestTerminalState.submitted) {
|
|
1864
1895
|
throw error;
|
|
1865
1896
|
}
|
|
1866
|
-
requireMeshSpotReply(
|
|
1867
|
-
record.
|
|
1868
|
-
|
|
1869
|
-
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
|
|
1897
|
+
requireMeshSpotReply(
|
|
1898
|
+
record.reply(
|
|
1899
|
+
this.encodeMeshActorReply(record.parts[0], ZLinkStreamMessageKind.Error, {
|
|
1900
|
+
message: error instanceof Error ? error.message : String(error),
|
|
1901
|
+
kind:
|
|
1902
|
+
error instanceof ZLinkFrameworkException
|
|
1903
|
+
? error.kind
|
|
1904
|
+
: ZLinkFrameworkErrorKind.InternalFailure
|
|
1905
|
+
})
|
|
1906
|
+
)
|
|
1907
|
+
);
|
|
1876
1908
|
}
|
|
1877
1909
|
}
|
|
1878
1910
|
|
|
1879
|
-
async dispatchMeshActorJoin(
|
|
1911
|
+
async dispatchMeshActorJoin(
|
|
1912
|
+
meshName: string,
|
|
1913
|
+
owner: ReadyRecord,
|
|
1914
|
+
record: ReceiveRecord
|
|
1915
|
+
): Promise<void> {
|
|
1880
1916
|
const spotId = owner.spotId as unknown as RoutingId | null;
|
|
1881
1917
|
const control = record.kindData;
|
|
1882
1918
|
if (control?.kind !== 'actorControl') {
|
|
1883
|
-
throw new ZLinkConfigurationException(
|
|
1919
|
+
throw new ZLinkConfigurationException(
|
|
1920
|
+
'MeshNode Actor join record is missing lifecycle identity data.'
|
|
1921
|
+
);
|
|
1884
1922
|
}
|
|
1885
1923
|
const actorId = control.currentActor?.actorId;
|
|
1886
1924
|
if (spotId === null || actorId === undefined) {
|
|
1887
|
-
throw new ZLinkConfigurationException(
|
|
1925
|
+
throw new ZLinkConfigurationException(
|
|
1926
|
+
'MeshNode Actor join record is missing its Spot or Actor owner.'
|
|
1927
|
+
);
|
|
1888
1928
|
}
|
|
1889
1929
|
const entrySpotId = this.options.entryNodeRidProvider?.() ?? this.options.entryNodeRid;
|
|
1890
1930
|
let requestContentType = record.contentType ?? 'application/json';
|
|
1891
|
-
const targetsEntrySpot = entrySpotId !== undefined
|
|
1892
|
-
&& String(spotId) === String(entrySpotId);
|
|
1931
|
+
const targetsEntrySpot = entrySpotId !== undefined && String(spotId) === String(entrySpotId);
|
|
1893
1932
|
const activation = this.activations.resolve(meshName, spotId);
|
|
1894
|
-
const transferRequest =
|
|
1895
|
-
? undefined
|
|
1896
|
-
: decodeFormalRemoteTransferRequest(record.parts[0]!);
|
|
1933
|
+
const transferRequest =
|
|
1934
|
+
record.parts.length === 0 ? undefined : decodeFormalRemoteTransferRequest(record.parts[0]!);
|
|
1897
1935
|
const remoteJoinPhase = transferRequest?.phase;
|
|
1898
1936
|
const isRemoteAdmission = remoteJoinPhase === REMOTE_ACTOR_JOIN_ADMISSION;
|
|
1899
1937
|
const isRemoteCommit = remoteJoinPhase === REMOTE_ACTOR_JOIN_COMMIT;
|
|
1900
1938
|
const isRemoteAbort = remoteJoinPhase === REMOTE_ACTOR_JOIN_ABORT;
|
|
1901
|
-
let admissionRecord =
|
|
1902
|
-
|
|
1903
|
-
|
|
1939
|
+
let admissionRecord =
|
|
1940
|
+
transferRequest !== undefined
|
|
1941
|
+
? this.formalRemoteActorAdmissions.get(transferRequest.transferId)
|
|
1942
|
+
: undefined;
|
|
1904
1943
|
let canonicalAdmissionCreated = false;
|
|
1905
1944
|
let pendingAdmission = isRemoteCommit ? admissionRecord : undefined;
|
|
1906
1945
|
let commitAdmissionMissing = isRemoteCommit && admissionRecord === undefined;
|
|
1907
|
-
const applicationClaim =
|
|
1908
|
-
|
|
1909
|
-
|
|
1946
|
+
const applicationClaim =
|
|
1947
|
+
transferRequest === undefined
|
|
1948
|
+
? this.options.admission?.claim(meshName, 'Actor join dispatch')
|
|
1949
|
+
: undefined;
|
|
1910
1950
|
let canonicalActorType: string | undefined;
|
|
1911
1951
|
if (control.canonicalActorJoin !== undefined) {
|
|
1912
1952
|
const resolver = this.options.canonicalActorJoinResolver;
|
|
@@ -1962,9 +2002,8 @@ export class DefaultZLinkSpotManager {
|
|
|
1962
2002
|
if (actor === undefined && admissionRecord?.actor !== undefined) {
|
|
1963
2003
|
actor = admissionRecord.actor;
|
|
1964
2004
|
}
|
|
1965
|
-
let callbackRequest: Message | undefined =
|
|
1966
|
-
? undefined
|
|
1967
|
-
: record.parts[0]!;
|
|
2005
|
+
let callbackRequest: Message | undefined =
|
|
2006
|
+
record.parts.length === 0 ? undefined : record.parts[0]!;
|
|
1968
2007
|
let ownedCallbackRequest: Message | undefined;
|
|
1969
2008
|
let materialized = false;
|
|
1970
2009
|
let reply: Message | undefined;
|
|
@@ -1972,13 +2011,11 @@ export class DefaultZLinkSpotManager {
|
|
|
1972
2011
|
let preparedTransferState: Message | undefined;
|
|
1973
2012
|
let admissionOutcome: ZLinkFormalRemoteActorAdmissionResult | undefined;
|
|
1974
2013
|
let accepted = false;
|
|
1975
|
-
let committedAdmissionReplay = isRemoteCommit
|
|
1976
|
-
&& admissionRecord?.state === 'committed';
|
|
2014
|
+
let committedAdmissionReplay = isRemoteCommit && admissionRecord?.state === 'committed';
|
|
1977
2015
|
let targetCommitPublished: boolean | undefined;
|
|
1978
|
-
const actorJoinIsCurrent = (): boolean =>
|
|
1979
|
-
(record.deadlineUnixMs === undefined || record.deadlineUnixMs > BigInt(Date.now()))
|
|
1980
|
-
|
|
1981
|
-
);
|
|
2016
|
+
const actorJoinIsCurrent = (): boolean =>
|
|
2017
|
+
(record.deadlineUnixMs === undefined || record.deadlineUnixMs > BigInt(Date.now())) &&
|
|
2018
|
+
(record.isPending?.() ?? true);
|
|
1982
2019
|
const abandonStaleAdmission = (): void => {
|
|
1983
2020
|
if (isRemoteAdmission && transferRequest !== undefined) {
|
|
1984
2021
|
this.formalRemoteActorAdmissions.abort(transferRequest.transferId);
|
|
@@ -1997,14 +2034,10 @@ export class DefaultZLinkSpotManager {
|
|
|
1997
2034
|
return;
|
|
1998
2035
|
}
|
|
1999
2036
|
if (transferRequest !== undefined) {
|
|
2000
|
-
ownedCallbackRequest = RuntimeMessage.from(
|
|
2001
|
-
Buffer.from(transferRequest.request, 'base64')
|
|
2002
|
-
);
|
|
2037
|
+
ownedCallbackRequest = RuntimeMessage.from(Buffer.from(transferRequest.request, 'base64'));
|
|
2003
2038
|
callbackRequest = ownedCallbackRequest;
|
|
2004
2039
|
} else if (callbackRequest !== undefined) {
|
|
2005
|
-
ownedCallbackRequest = RuntimeMessage.from(
|
|
2006
|
-
callbackRequest.data()
|
|
2007
|
-
);
|
|
2040
|
+
ownedCallbackRequest = RuntimeMessage.from(callbackRequest.data());
|
|
2008
2041
|
callbackRequest = ownedCallbackRequest;
|
|
2009
2042
|
}
|
|
2010
2043
|
if (control.canonicalActorJoin !== undefined) {
|
|
@@ -2026,15 +2059,15 @@ export class DefaultZLinkSpotManager {
|
|
|
2026
2059
|
admissionRecord = this.formalRemoteActorAdmissions.finalizeProvisional(
|
|
2027
2060
|
control.canonicalActorJoin.handoffId,
|
|
2028
2061
|
{
|
|
2029
|
-
|
|
2030
|
-
|
|
2031
|
-
|
|
2032
|
-
|
|
2033
|
-
|
|
2034
|
-
|
|
2035
|
-
|
|
2036
|
-
|
|
2037
|
-
|
|
2062
|
+
actorId,
|
|
2063
|
+
actorType,
|
|
2064
|
+
actorRef,
|
|
2065
|
+
spotId,
|
|
2066
|
+
targetSpotGeneration: control.currentSpotGeneration,
|
|
2067
|
+
expectedMembershipEpoch: control.currentMembershipEpoch,
|
|
2068
|
+
requestFingerprint: callbackRequest.data().toString('base64'),
|
|
2069
|
+
transferId: control.canonicalActorJoin.handoffId,
|
|
2070
|
+
sourceActorNodeRid: control.canonicalActorJoin.actorNodeRid as RoutingId
|
|
2038
2071
|
}
|
|
2039
2072
|
);
|
|
2040
2073
|
if (canonicalAdmissionCreated) {
|
|
@@ -2058,9 +2091,10 @@ export class DefaultZLinkSpotManager {
|
|
|
2058
2091
|
);
|
|
2059
2092
|
let encodedReply: Message | undefined;
|
|
2060
2093
|
try {
|
|
2061
|
-
encodedReply =
|
|
2062
|
-
|
|
2063
|
-
|
|
2094
|
+
encodedReply =
|
|
2095
|
+
response.reply === undefined
|
|
2096
|
+
? undefined
|
|
2097
|
+
: encodeFrameworkPayloadMessage(response.reply, this.options.messageSerializers);
|
|
2064
2098
|
admissionOutcome = {
|
|
2065
2099
|
accepted: response.accepted,
|
|
2066
2100
|
actorRef,
|
|
@@ -2080,18 +2114,15 @@ export class DefaultZLinkSpotManager {
|
|
|
2080
2114
|
admissionOutcome
|
|
2081
2115
|
);
|
|
2082
2116
|
}
|
|
2083
|
-
admissionOutcome = admissionRecord.result ?? await admissionRecord.resultTask;
|
|
2117
|
+
admissionOutcome = admissionRecord.result ?? (await admissionRecord.resultTask);
|
|
2084
2118
|
if ('error' in admissionOutcome) throw admissionOutcome.error;
|
|
2085
2119
|
accepted = admissionOutcome.accepted;
|
|
2086
|
-
reply =
|
|
2087
|
-
|
|
2088
|
-
|
|
2120
|
+
reply =
|
|
2121
|
+
admissionOutcome.reply === undefined
|
|
2122
|
+
? undefined
|
|
2123
|
+
: RuntimeMessage.from(admissionOutcome.reply);
|
|
2089
2124
|
}
|
|
2090
|
-
if (
|
|
2091
|
-
transferRequest !== undefined
|
|
2092
|
-
&& !targetsEntrySpot
|
|
2093
|
-
&& remoteJoinPhase === undefined
|
|
2094
|
-
) {
|
|
2125
|
+
if (transferRequest !== undefined && !targetsEntrySpot && remoteJoinPhase === undefined) {
|
|
2095
2126
|
// User Spot transfers must carry the private admission/commit phases.
|
|
2096
2127
|
// A legacy one-phase request would otherwise read relocation state
|
|
2097
2128
|
// before the target application has accepted the Actor.
|
|
@@ -2121,12 +2152,12 @@ export class DefaultZLinkSpotManager {
|
|
|
2121
2152
|
try {
|
|
2122
2153
|
if (targetsEntrySpot) {
|
|
2123
2154
|
if (
|
|
2124
|
-
this.options.dispatchEntryActorJoin !== undefined
|
|
2125
|
-
|
|
2126
|
-
|
|
2155
|
+
this.options.dispatchEntryActorJoin !== undefined &&
|
|
2156
|
+
transferRequest.completionOperationId !== undefined &&
|
|
2157
|
+
this.options.actorTransferRuntime !== undefined
|
|
2127
2158
|
) {
|
|
2128
|
-
deferredJoinRoot =
|
|
2129
|
-
.prepareDeferredJoinAccepted(
|
|
2159
|
+
deferredJoinRoot =
|
|
2160
|
+
await this.options.actorTransferRuntime.prepareDeferredJoinAccepted(
|
|
2130
2161
|
actorId,
|
|
2131
2162
|
transferRequest.completionOperationId,
|
|
2132
2163
|
actorRef,
|
|
@@ -2157,16 +2188,20 @@ export class DefaultZLinkSpotManager {
|
|
|
2157
2188
|
);
|
|
2158
2189
|
let encodedReply: Message | undefined;
|
|
2159
2190
|
try {
|
|
2160
|
-
encodedReply =
|
|
2161
|
-
|
|
2162
|
-
|
|
2191
|
+
encodedReply =
|
|
2192
|
+
response.reply === undefined
|
|
2193
|
+
? undefined
|
|
2194
|
+
: encodeFrameworkPayloadMessage(
|
|
2195
|
+
response.reply,
|
|
2196
|
+
this.options.messageSerializers
|
|
2197
|
+
);
|
|
2163
2198
|
if (
|
|
2164
|
-
response.accepted
|
|
2165
|
-
|
|
2166
|
-
|
|
2199
|
+
response.accepted &&
|
|
2200
|
+
transferRequest.completionOperationId !== undefined &&
|
|
2201
|
+
this.options.actorTransferRuntime !== undefined
|
|
2167
2202
|
) {
|
|
2168
|
-
deferredJoinRoot =
|
|
2169
|
-
.prepareDeferredJoinAccepted(
|
|
2203
|
+
deferredJoinRoot =
|
|
2204
|
+
await this.options.actorTransferRuntime.prepareDeferredJoinAccepted(
|
|
2170
2205
|
actorId,
|
|
2171
2206
|
transferRequest.completionOperationId,
|
|
2172
2207
|
actorRef,
|
|
@@ -2201,10 +2236,7 @@ export class DefaultZLinkSpotManager {
|
|
|
2201
2236
|
return;
|
|
2202
2237
|
}
|
|
2203
2238
|
}
|
|
2204
|
-
this.formalRemoteActorAdmissions.complete(
|
|
2205
|
-
transferRequest.transferId,
|
|
2206
|
-
admissionOutcome
|
|
2207
|
-
);
|
|
2239
|
+
this.formalRemoteActorAdmissions.complete(transferRequest.transferId, admissionOutcome);
|
|
2208
2240
|
} catch (error) {
|
|
2209
2241
|
this.formalRemoteActorAdmissions.fail(transferRequest.transferId, error);
|
|
2210
2242
|
throw error;
|
|
@@ -2215,9 +2247,10 @@ export class DefaultZLinkSpotManager {
|
|
|
2215
2247
|
throw admissionOutcome.error;
|
|
2216
2248
|
}
|
|
2217
2249
|
accepted = admissionOutcome.accepted;
|
|
2218
|
-
reply =
|
|
2219
|
-
|
|
2220
|
-
|
|
2250
|
+
reply =
|
|
2251
|
+
admissionOutcome.reply === undefined
|
|
2252
|
+
? undefined
|
|
2253
|
+
: RuntimeMessage.from(admissionOutcome.reply);
|
|
2221
2254
|
}
|
|
2222
2255
|
if (isRemoteCommit && admissionRecord !== undefined) {
|
|
2223
2256
|
admissionOutcome = await admissionRecord.resultTask;
|
|
@@ -2227,13 +2260,13 @@ export class DefaultZLinkSpotManager {
|
|
|
2227
2260
|
deferredJoinRoot = admissionOutcome.deferredJoinRoot;
|
|
2228
2261
|
}
|
|
2229
2262
|
if (
|
|
2230
|
-
actor === undefined
|
|
2231
|
-
|
|
2232
|
-
|
|
2233
|
-
|
|
2234
|
-
|
|
2235
|
-
|
|
2236
|
-
|
|
2263
|
+
actor === undefined &&
|
|
2264
|
+
transferRequest !== undefined &&
|
|
2265
|
+
this.options.actorTransferRuntime !== undefined &&
|
|
2266
|
+
!isRemoteAdmission &&
|
|
2267
|
+
!commitAdmissionMissing &&
|
|
2268
|
+
admissionRecord?.state !== 'committed' &&
|
|
2269
|
+
(targetsEntrySpot || activation !== undefined)
|
|
2237
2270
|
) {
|
|
2238
2271
|
// Relocation state travels inline with the join request. The store
|
|
2239
2272
|
// reference handoff was removed with the direct-transfer contract
|
|
@@ -2248,13 +2281,13 @@ export class DefaultZLinkSpotManager {
|
|
|
2248
2281
|
);
|
|
2249
2282
|
}
|
|
2250
2283
|
if (isRemoteAdmission && targetsEntrySpot) {
|
|
2251
|
-
accepted =
|
|
2252
|
-
|
|
2253
|
-
|
|
2284
|
+
accepted =
|
|
2285
|
+
admissionOutcome !== undefined &&
|
|
2286
|
+
!('error' in admissionOutcome) &&
|
|
2287
|
+
admissionOutcome.accepted;
|
|
2254
2288
|
} else if (isRemoteCommit && pendingAdmission !== undefined) {
|
|
2255
2289
|
validateRemoteAdmissionCommit(pendingAdmission, transferRequest!, actorId, control);
|
|
2256
|
-
accepted = pendingAdmission.state === 'admitted'
|
|
2257
|
-
|| pendingAdmission.state === 'committed';
|
|
2290
|
+
accepted = pendingAdmission.state === 'admitted' || pendingAdmission.state === 'committed';
|
|
2258
2291
|
} else if (commitAdmissionMissing) {
|
|
2259
2292
|
accepted = false;
|
|
2260
2293
|
} else if (targetsEntrySpot) {
|
|
@@ -2262,15 +2295,15 @@ export class DefaultZLinkSpotManager {
|
|
|
2262
2295
|
// actor-manager transaction is committed after the Core reply below.
|
|
2263
2296
|
// A formal transfer payload materializes the existing actor state at
|
|
2264
2297
|
// the Entry owner before that transaction is committed.
|
|
2265
|
-
accepted =
|
|
2266
|
-
|
|
2298
|
+
accepted =
|
|
2299
|
+
actor !== undefined ||
|
|
2300
|
+
(transferRequest !== undefined && this.options.actorTransferRuntime !== undefined);
|
|
2267
2301
|
} else if (
|
|
2268
|
-
!isRemoteAdmission
|
|
2269
|
-
|
|
2270
|
-
&&
|
|
2271
|
-
|
|
2272
|
-
|
|
2273
|
-
&& (actor !== undefined || transferRequest !== undefined)
|
|
2302
|
+
!isRemoteAdmission &&
|
|
2303
|
+
control.canonicalActorJoin === undefined &&
|
|
2304
|
+
activation !== undefined &&
|
|
2305
|
+
callbackRequest !== undefined &&
|
|
2306
|
+
(actor !== undefined || transferRequest !== undefined)
|
|
2274
2307
|
) {
|
|
2275
2308
|
if (!actorJoinIsCurrent()) return;
|
|
2276
2309
|
const request = callbackRequest;
|
|
@@ -2280,9 +2313,10 @@ export class DefaultZLinkSpotManager {
|
|
|
2280
2313
|
}
|
|
2281
2314
|
const actorRef: ActorRef = {
|
|
2282
2315
|
actorId: rawActorRef.actorId,
|
|
2283
|
-
objectGeneration:
|
|
2284
|
-
|
|
2285
|
-
|
|
2316
|
+
objectGeneration:
|
|
2317
|
+
'objectGeneration' in rawActorRef
|
|
2318
|
+
? rawActorRef.objectGeneration
|
|
2319
|
+
: rawActorRef.generation,
|
|
2286
2320
|
meshName,
|
|
2287
2321
|
nodeRid: rawActorRef.nodeRid as unknown as RoutingId
|
|
2288
2322
|
};
|
|
@@ -2298,22 +2332,22 @@ export class DefaultZLinkSpotManager {
|
|
|
2298
2332
|
);
|
|
2299
2333
|
if (!actorJoinIsCurrent()) return;
|
|
2300
2334
|
accepted = response.accepted;
|
|
2301
|
-
reply =
|
|
2302
|
-
|
|
2303
|
-
|
|
2335
|
+
reply =
|
|
2336
|
+
response.reply === undefined
|
|
2337
|
+
? undefined
|
|
2338
|
+
: encodeFrameworkPayloadMessage(response.reply, this.options.messageSerializers);
|
|
2304
2339
|
if (
|
|
2305
|
-
accepted
|
|
2306
|
-
|
|
2307
|
-
|
|
2340
|
+
accepted &&
|
|
2341
|
+
transferRequest?.completionOperationId !== undefined &&
|
|
2342
|
+
this.options.actorTransferRuntime !== undefined
|
|
2308
2343
|
) {
|
|
2309
|
-
deferredJoinRoot = await this.options.actorTransferRuntime
|
|
2310
|
-
|
|
2311
|
-
|
|
2312
|
-
|
|
2313
|
-
|
|
2314
|
-
|
|
2315
|
-
|
|
2316
|
-
);
|
|
2344
|
+
deferredJoinRoot = await this.options.actorTransferRuntime.prepareDeferredJoinAccepted(
|
|
2345
|
+
actorId,
|
|
2346
|
+
transferRequest.completionOperationId,
|
|
2347
|
+
actorRef,
|
|
2348
|
+
reply?.data() ?? Buffer.alloc(0),
|
|
2349
|
+
reply === undefined ? undefined : frameworkPayloadContentType(reply)
|
|
2350
|
+
);
|
|
2317
2351
|
this.options.runtimeEventPublisher?.publish({
|
|
2318
2352
|
sourceName: 'zlink.framework.actor-handoff',
|
|
2319
2353
|
timestamp: new Date(),
|
|
@@ -2323,11 +2357,11 @@ export class DefaultZLinkSpotManager {
|
|
|
2323
2357
|
}
|
|
2324
2358
|
}
|
|
2325
2359
|
if (
|
|
2326
|
-
accepted
|
|
2327
|
-
|
|
2328
|
-
|
|
2329
|
-
|
|
2330
|
-
|
|
2360
|
+
accepted &&
|
|
2361
|
+
!isRemoteAdmission &&
|
|
2362
|
+
actor === undefined &&
|
|
2363
|
+
transferRequest !== undefined &&
|
|
2364
|
+
this.options.actorTransferRuntime !== undefined
|
|
2331
2365
|
) {
|
|
2332
2366
|
if (!actorJoinIsCurrent()) return;
|
|
2333
2367
|
const transferState = preparedTransferState;
|
|
@@ -2371,10 +2405,10 @@ export class DefaultZLinkSpotManager {
|
|
|
2371
2405
|
}
|
|
2372
2406
|
}
|
|
2373
2407
|
if (
|
|
2374
|
-
accepted
|
|
2375
|
-
|
|
2376
|
-
|
|
2377
|
-
|
|
2408
|
+
accepted &&
|
|
2409
|
+
transferRequest !== undefined &&
|
|
2410
|
+
this.options.actorTransferRuntime !== undefined &&
|
|
2411
|
+
!isRemoteAdmission
|
|
2378
2412
|
) {
|
|
2379
2413
|
// A lightweight Core actor-join notification can create the Actor
|
|
2380
2414
|
// before the formal transfer request reaches this branch. Preserve
|
|
@@ -2386,11 +2420,11 @@ export class DefaultZLinkSpotManager {
|
|
|
2386
2420
|
);
|
|
2387
2421
|
}
|
|
2388
2422
|
if (
|
|
2389
|
-
accepted
|
|
2390
|
-
|
|
2391
|
-
|
|
2392
|
-
|
|
2393
|
-
|
|
2423
|
+
accepted &&
|
|
2424
|
+
actor !== undefined &&
|
|
2425
|
+
transferRequest !== undefined &&
|
|
2426
|
+
!isRemoteAdmission &&
|
|
2427
|
+
!committedAdmissionReplay
|
|
2394
2428
|
) {
|
|
2395
2429
|
this.formalRemoteTransfers.begin({
|
|
2396
2430
|
actor,
|
|
@@ -2400,10 +2434,7 @@ export class DefaultZLinkSpotManager {
|
|
|
2400
2434
|
deferredJoinRoot
|
|
2401
2435
|
});
|
|
2402
2436
|
if (isRemoteCommit && admissionRecord !== undefined) {
|
|
2403
|
-
this.formalRemoteActorAdmissions.markCommitted(
|
|
2404
|
-
transferRequest.transferId,
|
|
2405
|
-
actor
|
|
2406
|
-
);
|
|
2437
|
+
this.formalRemoteActorAdmissions.markCommitted(transferRequest.transferId, actor);
|
|
2407
2438
|
}
|
|
2408
2439
|
}
|
|
2409
2440
|
const replyActorJoin = (): boolean => {
|
|
@@ -2431,9 +2462,8 @@ export class DefaultZLinkSpotManager {
|
|
|
2431
2462
|
}
|
|
2432
2463
|
if (accepted && targetsEntrySpot && actor !== undefined) {
|
|
2433
2464
|
const entryActor = actor;
|
|
2434
|
-
const pendingTransfer =
|
|
2435
|
-
? undefined
|
|
2436
|
-
: this.formalRemoteTransfers.get(actorId);
|
|
2465
|
+
const pendingTransfer =
|
|
2466
|
+
transferRequest === undefined ? undefined : this.formalRemoteTransfers.get(actorId);
|
|
2437
2467
|
if (committedAdmissionReplay) {
|
|
2438
2468
|
if (!replyActorJoin()) return;
|
|
2439
2469
|
} else if (pendingTransfer === undefined) {
|
|
@@ -2446,11 +2476,7 @@ export class DefaultZLinkSpotManager {
|
|
|
2446
2476
|
if (!replyActorJoin()) return;
|
|
2447
2477
|
const commitEntryTransfer = async (): Promise<void> => {
|
|
2448
2478
|
try {
|
|
2449
|
-
await this.options.dispatchEntryActorJoin?.(
|
|
2450
|
-
meshName,
|
|
2451
|
-
entryActor,
|
|
2452
|
-
[]
|
|
2453
|
-
);
|
|
2479
|
+
await this.options.dispatchEntryActorJoin?.(meshName, entryActor, []);
|
|
2454
2480
|
} finally {
|
|
2455
2481
|
this.formalRemoteTransfers.completeTargetLifecycle(
|
|
2456
2482
|
entryActor.context.actorId,
|
|
@@ -2467,7 +2493,9 @@ export class DefaultZLinkSpotManager {
|
|
|
2467
2493
|
pendingTransfer.handoffBacklog,
|
|
2468
2494
|
async (parts, returnResponse, remoteBoundSessionTarget, fallbackActorRef) => {
|
|
2469
2495
|
if (this.options.dispatchEntryActorPacket === undefined) {
|
|
2470
|
-
throw new Error(
|
|
2496
|
+
throw new Error(
|
|
2497
|
+
'Entry Spot saved handoff replay requires its Actor packet runtime.'
|
|
2498
|
+
);
|
|
2471
2499
|
}
|
|
2472
2500
|
return await this.options.dispatchEntryActorPacket(
|
|
2473
2501
|
entryActor.context.actorId,
|
|
@@ -2477,19 +2505,20 @@ export class DefaultZLinkSpotManager {
|
|
|
2477
2505
|
fallbackActorRef
|
|
2478
2506
|
);
|
|
2479
2507
|
},
|
|
2480
|
-
index =>
|
|
2481
|
-
|
|
2482
|
-
|
|
2483
|
-
|
|
2484
|
-
|
|
2485
|
-
|
|
2486
|
-
|
|
2508
|
+
(index) =>
|
|
2509
|
+
this.options.runtimeEventPublisher?.publish({
|
|
2510
|
+
sourceName: 'zlink.framework.actor-handoff',
|
|
2511
|
+
timestamp: new Date(),
|
|
2512
|
+
marker: 'backlog_enqueued',
|
|
2513
|
+
actorId: entryActor.context.actorId,
|
|
2514
|
+
index
|
|
2515
|
+
})
|
|
2487
2516
|
);
|
|
2488
|
-
const failedHandoff = handoffResults.find(result => !result.ok);
|
|
2517
|
+
const failedHandoff = handoffResults.find((result) => !result.ok);
|
|
2489
2518
|
if (failedHandoff !== undefined) {
|
|
2490
2519
|
throw new Error(
|
|
2491
|
-
`Actor '${entryActor.context.actorId}' saved Entry handoff packet `
|
|
2492
|
-
|
|
2520
|
+
`Actor '${entryActor.context.actorId}' saved Entry handoff packet ` +
|
|
2521
|
+
`${failedHandoff.index} failed: ${failedHandoff.error ?? 'unknown error'}.`
|
|
2493
2522
|
);
|
|
2494
2523
|
}
|
|
2495
2524
|
this.formalRemoteTransfers.delete(entryActor.context.actorId);
|
|
@@ -2507,15 +2536,10 @@ export class DefaultZLinkSpotManager {
|
|
|
2507
2536
|
}
|
|
2508
2537
|
} catch (error) {
|
|
2509
2538
|
if (control.canonicalActorJoin !== undefined) {
|
|
2510
|
-
this.formalRemoteActorAdmissions.fail(
|
|
2511
|
-
control.canonicalActorJoin.handoffId,
|
|
2512
|
-
error
|
|
2513
|
-
);
|
|
2539
|
+
this.formalRemoteActorAdmissions.fail(control.canonicalActorJoin.handoffId, error);
|
|
2514
2540
|
}
|
|
2515
2541
|
if (deferredJoinRoot !== undefined && targetCommitPublished !== true) {
|
|
2516
|
-
await this.options.actorTransferRuntime?.discardDeferredJoinAccepted(
|
|
2517
|
-
deferredJoinRoot
|
|
2518
|
-
);
|
|
2542
|
+
await this.options.actorTransferRuntime?.discardDeferredJoinAccepted(deferredJoinRoot);
|
|
2519
2543
|
}
|
|
2520
2544
|
if (targetCommitPublished !== true) {
|
|
2521
2545
|
this.formalRemoteTransfers.delete(actorId);
|
|
@@ -2532,37 +2556,46 @@ export class DefaultZLinkSpotManager {
|
|
|
2532
2556
|
}
|
|
2533
2557
|
}
|
|
2534
2558
|
|
|
2535
|
-
async dispatchMeshSpotControl(
|
|
2559
|
+
async dispatchMeshSpotControl(
|
|
2560
|
+
meshName: string,
|
|
2561
|
+
owner: ReadyRecord,
|
|
2562
|
+
record: ReceiveRecord
|
|
2563
|
+
): Promise<void> {
|
|
2536
2564
|
const spotId = owner.spotId as unknown as RoutingId | null;
|
|
2537
2565
|
const control = record.kindData;
|
|
2538
2566
|
if (control?.kind !== 'actorControl') {
|
|
2539
|
-
throw new ZLinkConfigurationException(
|
|
2567
|
+
throw new ZLinkConfigurationException(
|
|
2568
|
+
'MeshNode Spot control record is missing actor lifecycle data.'
|
|
2569
|
+
);
|
|
2540
2570
|
}
|
|
2541
|
-
const actorRef =
|
|
2542
|
-
|
|
2543
|
-
|
|
2571
|
+
const actorRef =
|
|
2572
|
+
control.lifecycleKind === ActorLifecycleKind.Left
|
|
2573
|
+
? control.previousActor
|
|
2574
|
+
: control.currentActor;
|
|
2544
2575
|
const actorId = actorRef?.actorId;
|
|
2545
|
-
const pendingTransfer =
|
|
2546
|
-
? undefined
|
|
2547
|
-
|
|
2548
|
-
|
|
2549
|
-
|
|
2550
|
-
|
|
2551
|
-
const sourceJoinedActor =
|
|
2552
|
-
? undefined
|
|
2553
|
-
|
|
2554
|
-
|
|
2555
|
-
|
|
2556
|
-
|
|
2557
|
-
|
|
2558
|
-
|
|
2559
|
-
|
|
2576
|
+
const pendingTransfer =
|
|
2577
|
+
actorId === undefined ? undefined : this.formalRemoteTransfers.get(actorId);
|
|
2578
|
+
const sourceActivation =
|
|
2579
|
+
actorId === undefined || spotId === null
|
|
2580
|
+
? undefined
|
|
2581
|
+
: this.activations.resolve(meshName, spotId);
|
|
2582
|
+
const sourceJoinedActor =
|
|
2583
|
+
actorId === undefined ? undefined : sourceActivation?.resolveJoinedActor(actorId);
|
|
2584
|
+
const actor =
|
|
2585
|
+
actorId === undefined
|
|
2586
|
+
? undefined
|
|
2587
|
+
: (pendingTransfer?.actor ??
|
|
2588
|
+
sourceJoinedActor ??
|
|
2589
|
+
this.options.actorLifecycleResolver?.(actorId) ??
|
|
2590
|
+
this.options.actorResolver?.(actorId));
|
|
2560
2591
|
const entrySpotId = this.options.entryNodeRidProvider?.() ?? this.options.entryNodeRid;
|
|
2561
2592
|
if (actor === undefined) {
|
|
2562
2593
|
return;
|
|
2563
2594
|
}
|
|
2564
|
-
if (
|
|
2565
|
-
|
|
2595
|
+
if (
|
|
2596
|
+
control.lifecycleKind === ActorLifecycleKind.Left &&
|
|
2597
|
+
(spotId === null || (entrySpotId !== undefined && String(spotId) === String(entrySpotId)))
|
|
2598
|
+
) {
|
|
2566
2599
|
const callback = async () => {
|
|
2567
2600
|
await this.options.entrySpotCallbacks?.onLeaveActor(
|
|
2568
2601
|
actor,
|
|
@@ -2613,20 +2646,21 @@ export class DefaultZLinkSpotManager {
|
|
|
2613
2646
|
const completePublicJoin = async (): Promise<void> => {
|
|
2614
2647
|
const deferredJoinRoot = pendingTransfer?.deferredJoinRoot;
|
|
2615
2648
|
if (deferredJoinRoot !== undefined) {
|
|
2616
|
-
const currentRef =
|
|
2617
|
-
|
|
2618
|
-
|
|
2649
|
+
const currentRef =
|
|
2650
|
+
this.options.actorTransferRuntime === undefined
|
|
2651
|
+
? null
|
|
2652
|
+
: (control.currentActor as unknown as ActorRef | null);
|
|
2619
2653
|
if (currentRef === null) {
|
|
2620
|
-
throw new Error(
|
|
2654
|
+
throw new Error(
|
|
2655
|
+
`Actor '${actor.context.actorId}' has no target ref for deferred Join completion.`
|
|
2656
|
+
);
|
|
2621
2657
|
}
|
|
2622
2658
|
await this.options.actorTransferRuntime?.commitAndDeliverDeferredJoinAccepted(
|
|
2623
2659
|
deferredJoinRoot,
|
|
2624
2660
|
actor,
|
|
2625
2661
|
currentRef,
|
|
2626
|
-
operation =>
|
|
2627
|
-
actor.context.actorId,
|
|
2628
|
-
async () => await operation()
|
|
2629
|
-
)
|
|
2662
|
+
(operation) =>
|
|
2663
|
+
activation.executeActor(actor.context.actorId, async () => await operation())
|
|
2630
2664
|
);
|
|
2631
2665
|
}
|
|
2632
2666
|
};
|
|
@@ -2643,19 +2677,20 @@ export class DefaultZLinkSpotManager {
|
|
|
2643
2677
|
remoteBoundSessionTarget,
|
|
2644
2678
|
undefined
|
|
2645
2679
|
),
|
|
2646
|
-
(index) =>
|
|
2647
|
-
|
|
2648
|
-
|
|
2649
|
-
|
|
2650
|
-
|
|
2651
|
-
|
|
2652
|
-
|
|
2680
|
+
(index) =>
|
|
2681
|
+
this.options.runtimeEventPublisher?.publish({
|
|
2682
|
+
sourceName: 'zlink.framework.actor-handoff',
|
|
2683
|
+
timestamp: new Date(),
|
|
2684
|
+
marker: 'backlog_enqueued',
|
|
2685
|
+
actorId: actor.context.actorId,
|
|
2686
|
+
index
|
|
2687
|
+
})
|
|
2653
2688
|
);
|
|
2654
|
-
const failedHandoff = handoffResults.find(result => !result.ok);
|
|
2689
|
+
const failedHandoff = handoffResults.find((result) => !result.ok);
|
|
2655
2690
|
if (failedHandoff !== undefined) {
|
|
2656
2691
|
throw new Error(
|
|
2657
|
-
`Actor '${actor.context.actorId}' saved handoff packet `
|
|
2658
|
-
|
|
2692
|
+
`Actor '${actor.context.actorId}' saved handoff packet ` +
|
|
2693
|
+
`${failedHandoff.index} failed: ${failedHandoff.error ?? 'unknown error'}.`
|
|
2659
2694
|
);
|
|
2660
2695
|
}
|
|
2661
2696
|
// Spec 15 §4.2 relocation temporary queue: arrivals parked at
|
|
@@ -2730,9 +2765,8 @@ export class DefaultZLinkSpotManager {
|
|
|
2730
2765
|
if (sourceJoinedActor === undefined && pendingTransfer === undefined) {
|
|
2731
2766
|
return;
|
|
2732
2767
|
}
|
|
2733
|
-
await this.options.actorTransferRuntime.notifyCoreSourceLeave(
|
|
2734
|
-
actor
|
|
2735
|
-
() => activation.spot.onLeaveActor(actor)
|
|
2768
|
+
await this.options.actorTransferRuntime.notifyCoreSourceLeave(actor, () =>
|
|
2769
|
+
activation.spot.onLeaveActor(actor)
|
|
2736
2770
|
);
|
|
2737
2771
|
}
|
|
2738
2772
|
activation.commitActorDeparture(actor.context.actorId);
|
|
@@ -2770,14 +2804,14 @@ export class DefaultZLinkSpotManager {
|
|
|
2770
2804
|
if (admission.admission.actorId !== actor.context.actorId) {
|
|
2771
2805
|
throw new Error(`Actor Join relocation '${relocationId}' changed its admitted Actor.`);
|
|
2772
2806
|
}
|
|
2773
|
-
const outcome = admission.result ?? await admission.resultTask;
|
|
2807
|
+
const outcome = admission.result ?? (await admission.resultTask);
|
|
2774
2808
|
if ('error' in outcome) throw outcome.error;
|
|
2775
2809
|
if (!outcome.accepted || admission.state !== 'admitted') {
|
|
2776
2810
|
throw new Error(`Actor Join relocation '${relocationId}' has no accepted admission.`);
|
|
2777
2811
|
}
|
|
2778
2812
|
const entrySpotId = this.options.entryNodeRidProvider?.() ?? this.options.entryNodeRid;
|
|
2779
|
-
const targetsEntry =
|
|
2780
|
-
&& String(admission.admission.spotId) === String(entrySpotId);
|
|
2813
|
+
const targetsEntry =
|
|
2814
|
+
entrySpotId !== undefined && String(admission.admission.spotId) === String(entrySpotId);
|
|
2781
2815
|
if (targetsEntry) {
|
|
2782
2816
|
await this.options.dispatchEntryActorJoin?.(meshName, actor, []);
|
|
2783
2817
|
} else {
|
|
@@ -2822,7 +2856,7 @@ export class DefaultZLinkSpotManager {
|
|
|
2822
2856
|
`Actor Join recovery '${recovery.request.handoffId}' has no canonical command-28 admission.`
|
|
2823
2857
|
);
|
|
2824
2858
|
}
|
|
2825
|
-
const outcome = admission.result ?? await admission.resultTask;
|
|
2859
|
+
const outcome = admission.result ?? (await admission.resultTask);
|
|
2826
2860
|
if ('error' in outcome || !outcome.accepted || admission.state !== 'admitted') {
|
|
2827
2861
|
throw new Error(
|
|
2828
2862
|
`Actor Join recovery '${recovery.request.handoffId}' has no accepted admission.`
|
|
@@ -2839,13 +2873,13 @@ export class DefaultZLinkSpotManager {
|
|
|
2839
2873
|
'hex'
|
|
2840
2874
|
);
|
|
2841
2875
|
if (
|
|
2842
|
-
admitted.actorId !== recovery.request.actorId
|
|
2843
|
-
|
|
2844
|
-
|
|
2845
|
-
|
|
2846
|
-
|
|
2847
|
-
|
|
2848
|
-
|
|
2876
|
+
admitted.actorId !== recovery.request.actorId ||
|
|
2877
|
+
admitted.actorType !== recovery.request.actorType ||
|
|
2878
|
+
admitted.requestFingerprint !== recovery.request.request.toString('base64') ||
|
|
2879
|
+
String(admitted.spotId) !== recovery.targetSpotId ||
|
|
2880
|
+
admitted.targetSpotGeneration !== recovery.targetSpotGeneration ||
|
|
2881
|
+
admitted.actorRef.objectGeneration !== recovery.request.actorGeneration ||
|
|
2882
|
+
!admittedNodeBytes.equals(recovery.request.sourceNodeRid)
|
|
2849
2883
|
) {
|
|
2850
2884
|
throw new Error(
|
|
2851
2885
|
`Actor Join recovery '${recovery.request.handoffId}' changed its command-28 identity.`
|
|
@@ -2865,9 +2899,10 @@ export class DefaultZLinkSpotManager {
|
|
|
2865
2899
|
}
|
|
2866
2900
|
return;
|
|
2867
2901
|
}
|
|
2868
|
-
const outerReplyContentType =
|
|
2869
|
-
|
|
2870
|
-
|
|
2902
|
+
const outerReplyContentType =
|
|
2903
|
+
admittedReply.byteLength === 0
|
|
2904
|
+
? recovery.replyContentType
|
|
2905
|
+
: SERVICE_FRAMEWORK_MULTIPART_CONTENT_TYPE;
|
|
2871
2906
|
if (recovery.replyContentType !== outerReplyContentType) {
|
|
2872
2907
|
throw new Error(
|
|
2873
2908
|
`Actor Join recovery '${recovery.request.handoffId}' changed its reply content type.`
|
|
@@ -2876,9 +2911,8 @@ export class DefaultZLinkSpotManager {
|
|
|
2876
2911
|
// Command 28 carries a present reply in one outer framework-multipart
|
|
2877
2912
|
// part. The accepted target admission still owns the inner typed content
|
|
2878
2913
|
// type, which the durable completion must retain for application decode.
|
|
2879
|
-
const admittedContentType =
|
|
2880
|
-
? recovery.replyContentType
|
|
2881
|
-
: outcome.replyContentType;
|
|
2914
|
+
const admittedContentType =
|
|
2915
|
+
admittedReply.byteLength === 0 ? recovery.replyContentType : outcome.replyContentType;
|
|
2882
2916
|
const transfer = this.options.actorTransferRuntime;
|
|
2883
2917
|
if (transfer === undefined) {
|
|
2884
2918
|
throw new Error('Canonical Actor Join recovery requires the Actor transfer runtime.');
|
|
@@ -2892,10 +2926,7 @@ export class DefaultZLinkSpotManager {
|
|
|
2892
2926
|
signal,
|
|
2893
2927
|
canonicalInventoryDigest
|
|
2894
2928
|
);
|
|
2895
|
-
this.formalRemoteActorAdmissions.attachDeferredJoinRoot(
|
|
2896
|
-
recovery.request.handoffId,
|
|
2897
|
-
deferred
|
|
2898
|
-
);
|
|
2929
|
+
this.formalRemoteActorAdmissions.attachDeferredJoinRoot(recovery.request.handoffId, deferred);
|
|
2899
2930
|
return deferred;
|
|
2900
2931
|
}
|
|
2901
2932
|
|
|
@@ -3003,10 +3034,7 @@ export class DefaultZLinkSpotManager {
|
|
|
3003
3034
|
const response = await this.dispatchActorPacket(
|
|
3004
3035
|
activation,
|
|
3005
3036
|
actor.context.actorId,
|
|
3006
|
-
[
|
|
3007
|
-
RuntimeMessage.from(arrival.header),
|
|
3008
|
-
RuntimeMessage.from(arrival.payload)
|
|
3009
|
-
],
|
|
3037
|
+
[RuntimeMessage.from(arrival.header), RuntimeMessage.from(arrival.payload)],
|
|
3010
3038
|
arrival.returnResponse,
|
|
3011
3039
|
arrival.remoteBoundSessionTarget,
|
|
3012
3040
|
arrival.fallbackActorRef,
|
|
@@ -3046,17 +3074,16 @@ export class DefaultZLinkSpotManager {
|
|
|
3046
3074
|
messageFollowOrigin
|
|
3047
3075
|
);
|
|
3048
3076
|
}
|
|
3049
|
-
|
|
3050
3077
|
}
|
|
3051
3078
|
|
|
3052
3079
|
function instanceDispatchErrorReason(error: unknown): ZLinkDispatchErrorReason {
|
|
3053
3080
|
if (error instanceof ZLinkFrameworkException) {
|
|
3054
3081
|
const kind = internalFrameworkErrorKind(error);
|
|
3055
3082
|
if (
|
|
3056
|
-
kind === ZLinkFrameworkInternalErrorKind.SpotGenerationStale
|
|
3057
|
-
|
|
3058
|
-
|
|
3059
|
-
|
|
3083
|
+
kind === ZLinkFrameworkInternalErrorKind.SpotGenerationStale ||
|
|
3084
|
+
kind === ZLinkFrameworkInternalErrorKind.SpotMoving ||
|
|
3085
|
+
kind === ZLinkFrameworkInternalErrorKind.SpotRouteNotFound ||
|
|
3086
|
+
kind === ZLinkFrameworkInternalErrorKind.RequestTargetNotFound
|
|
3060
3087
|
) {
|
|
3061
3088
|
return ZLinkDispatchErrorReason.StaleTarget;
|
|
3062
3089
|
}
|
|
@@ -3101,51 +3128,48 @@ function decodeFormalRemoteTransferRequestBytes(
|
|
|
3101
3128
|
return undefined;
|
|
3102
3129
|
}
|
|
3103
3130
|
if (
|
|
3104
|
-
payload.packetName !== REMOTE_ACTOR_JOIN_PACKET
|
|
3105
|
-
|
|
3106
|
-
|
|
3107
|
-
|
|
3108
|
-
payload.phase === REMOTE_ACTOR_JOIN_ADMISSION
|
|
3109
|
-
|
|
3110
|
-
|
|
3111
|
-
|
|
3112
|
-
)
|
|
3113
|
-
|
|
3114
|
-
payload.phase === REMOTE_ACTOR_JOIN_ADMISSION
|
|
3115
|
-
|
|
3116
|
-
|| (
|
|
3131
|
+
payload.packetName !== REMOTE_ACTOR_JOIN_PACKET ||
|
|
3132
|
+
typeof payload.actorType !== 'string' ||
|
|
3133
|
+
typeof payload.transferId !== 'string' ||
|
|
3134
|
+
!(
|
|
3135
|
+
payload.phase === REMOTE_ACTOR_JOIN_ADMISSION ||
|
|
3136
|
+
payload.phase === REMOTE_ACTOR_JOIN_ABORT ||
|
|
3137
|
+
payload.phase === REMOTE_ACTOR_JOIN_COMMIT ||
|
|
3138
|
+
payload.phase === undefined
|
|
3139
|
+
) ||
|
|
3140
|
+
!(
|
|
3141
|
+
payload.phase === REMOTE_ACTOR_JOIN_ADMISSION ||
|
|
3142
|
+
payload.phase === REMOTE_ACTOR_JOIN_ABORT ||
|
|
3117
3143
|
typeof payload.transferState === 'string'
|
|
3118
|
-
|
|
3119
|
-
|
|
3120
|
-
|| typeof payload.request !== 'string'
|
|
3144
|
+
) ||
|
|
3145
|
+
typeof payload.request !== 'string'
|
|
3121
3146
|
) {
|
|
3122
3147
|
return undefined;
|
|
3123
3148
|
}
|
|
3124
3149
|
return {
|
|
3125
3150
|
actorType: payload.actorType,
|
|
3126
3151
|
actorId: typeof payload.actorId === 'string' ? payload.actorId : undefined,
|
|
3127
|
-
phase:
|
|
3128
|
-
|
|
3129
|
-
|
|
3130
|
-
|
|
3131
|
-
|
|
3152
|
+
phase:
|
|
3153
|
+
payload.phase === REMOTE_ACTOR_JOIN_ADMISSION ||
|
|
3154
|
+
payload.phase === REMOTE_ACTOR_JOIN_COMMIT ||
|
|
3155
|
+
payload.phase === REMOTE_ACTOR_JOIN_ABORT
|
|
3156
|
+
? payload.phase
|
|
3157
|
+
: undefined,
|
|
3132
3158
|
transferId: payload.transferId,
|
|
3133
|
-
transferAdapterKey:
|
|
3134
|
-
? payload.transferAdapterKey
|
|
3135
|
-
|
|
3136
|
-
transferState: typeof payload.transferState === 'string'
|
|
3137
|
-
? payload.transferState
|
|
3138
|
-
: undefined,
|
|
3159
|
+
transferAdapterKey:
|
|
3160
|
+
typeof payload.transferAdapterKey === 'string' ? payload.transferAdapterKey : undefined,
|
|
3161
|
+
transferState: typeof payload.transferState === 'string' ? payload.transferState : undefined,
|
|
3139
3162
|
request: payload.request,
|
|
3140
|
-
requestContentType:
|
|
3141
|
-
|
|
3142
|
-
|
|
3143
|
-
|
|
3144
|
-
|
|
3145
|
-
|
|
3146
|
-
|
|
3147
|
-
|
|
3148
|
-
|
|
3163
|
+
requestContentType:
|
|
3164
|
+
typeof payload.requestContentType === 'string'
|
|
3165
|
+
? payload.requestContentType
|
|
3166
|
+
: 'application/json',
|
|
3167
|
+
actorEntryNodeRid:
|
|
3168
|
+
typeof payload.actorEntryNodeRid === 'string'
|
|
3169
|
+
? decodeRoutingId(payload.actorEntryNodeRid, payload.actorEntryNodeRidHex)
|
|
3170
|
+
: undefined,
|
|
3171
|
+
sourceSpotId:
|
|
3172
|
+
typeof payload.sourceSpotId === 'string' ? (payload.sourceSpotId as RoutingId) : undefined,
|
|
3149
3173
|
actorRef: decodeFormalRemoteActorRef(payload),
|
|
3150
3174
|
remoteBoundSessionTarget: decodeRemoteBoundSessionTarget(
|
|
3151
3175
|
payload.boundSessionRouterChannelId,
|
|
@@ -3162,13 +3186,14 @@ function decodeFormalRemoteTransferRequestBytes(
|
|
|
3162
3186
|
payload.boundSessionRelocationSealId,
|
|
3163
3187
|
payload.boundSessionServiceWireRelocation
|
|
3164
3188
|
),
|
|
3165
|
-
expectedMembershipEpoch:
|
|
3166
|
-
|
|
3167
|
-
|
|
3189
|
+
expectedMembershipEpoch:
|
|
3190
|
+
typeof payload.expectedMembershipEpoch === 'string'
|
|
3191
|
+
? BigInt(payload.expectedMembershipEpoch)
|
|
3192
|
+
: 0n,
|
|
3168
3193
|
handoffBacklog: decodeHandoffBacklog(payload.handoffBacklog),
|
|
3169
3194
|
completionOperationId:
|
|
3170
|
-
typeof payload.completionOperationHigh === 'string'
|
|
3171
|
-
|
|
3195
|
+
typeof payload.completionOperationHigh === 'string' &&
|
|
3196
|
+
typeof payload.completionOperationLow === 'string'
|
|
3172
3197
|
? {
|
|
3173
3198
|
high: BigInt(payload.completionOperationHigh),
|
|
3174
3199
|
low: BigInt(payload.completionOperationLow)
|
|
@@ -3197,7 +3222,6 @@ function decodeFormalRemoteActorRef(
|
|
|
3197
3222
|
};
|
|
3198
3223
|
}
|
|
3199
3224
|
|
|
3200
|
-
|
|
3201
3225
|
function requireMeshSpotReply(result: number): void {
|
|
3202
3226
|
if (result !== SubmitResult.Ok) {
|
|
3203
3227
|
throw new ZLinkConfigurationException(
|
|
@@ -3238,15 +3262,15 @@ function validateRemoteAdmissionCommit(
|
|
|
3238
3262
|
const expected = admission.admission;
|
|
3239
3263
|
const actorRef = request.actorRef;
|
|
3240
3264
|
if (
|
|
3241
|
-
expected.actorId !== actorId
|
|
3242
|
-
|
|
3243
|
-
|
|
3244
|
-
|
|
3245
|
-
|
|
3246
|
-
|
|
3247
|
-
|
|
3248
|
-
|
|
3249
|
-
|
|
3265
|
+
expected.actorId !== actorId ||
|
|
3266
|
+
expected.actorType !== request.actorType ||
|
|
3267
|
+
expected.expectedMembershipEpoch !== request.expectedMembershipEpoch ||
|
|
3268
|
+
expected.requestFingerprint !== request.request ||
|
|
3269
|
+
expected.targetSpotGeneration !== (control.currentSpotGeneration ?? 0n) ||
|
|
3270
|
+
actorRef === undefined ||
|
|
3271
|
+
actorRef.actorId !== expected.actorRef.actorId ||
|
|
3272
|
+
String(actorRef.nodeRid) !== String(expected.actorRef.nodeRid) ||
|
|
3273
|
+
actorRef.objectGeneration !== expected.actorRef.objectGeneration
|
|
3250
3274
|
) {
|
|
3251
3275
|
throw new ZLinkConfigurationException(
|
|
3252
3276
|
`Remote Actor '${actorId}' commit does not match its target admission.`
|
|
@@ -3257,7 +3281,10 @@ function validateRemoteAdmissionCommit(
|
|
|
3257
3281
|
function normalizeSpotCreateArgs<TRequest>(
|
|
3258
3282
|
requestOrSignal: ZLinkMessage | TRequest | AbortSignal | undefined,
|
|
3259
3283
|
signal: AbortSignal | undefined
|
|
3260
|
-
): {
|
|
3284
|
+
): {
|
|
3285
|
+
readonly request: ZLinkMessage | TRequest | undefined;
|
|
3286
|
+
readonly signal: AbortSignal | undefined;
|
|
3287
|
+
} {
|
|
3261
3288
|
if (isAbortSignal(requestOrSignal)) {
|
|
3262
3289
|
return { request: undefined, signal: requestOrSignal };
|
|
3263
3290
|
}
|
|
@@ -3283,10 +3310,12 @@ function instanceMaterializationKey(
|
|
|
3283
3310
|
}
|
|
3284
3311
|
|
|
3285
3312
|
function isAbortSignal(value: unknown): value is AbortSignal {
|
|
3286
|
-
return
|
|
3287
|
-
|
|
3288
|
-
|
|
3289
|
-
|
|
3313
|
+
return (
|
|
3314
|
+
typeof value === 'object' &&
|
|
3315
|
+
value !== null &&
|
|
3316
|
+
typeof (value as { aborted?: unknown }).aborted === 'boolean' &&
|
|
3317
|
+
typeof (value as { addEventListener?: unknown }).addEventListener === 'function'
|
|
3318
|
+
);
|
|
3290
3319
|
}
|
|
3291
3320
|
|
|
3292
3321
|
function instanceActivationOutcome(error: unknown): string {
|
|
@@ -3295,9 +3324,10 @@ function instanceActivationOutcome(error: unknown): string {
|
|
|
3295
3324
|
if (error.kind === ZLinkFrameworkErrorKind.DeadlineExceeded) return 'timed_out';
|
|
3296
3325
|
if (error.kind === ZLinkFrameworkErrorKind.AlreadyExists) return 'conflict';
|
|
3297
3326
|
if (
|
|
3298
|
-
error.kind === ZLinkFrameworkErrorKind.InvalidOperation
|
|
3299
|
-
|
|
3300
|
-
)
|
|
3327
|
+
error.kind === ZLinkFrameworkErrorKind.InvalidOperation ||
|
|
3328
|
+
error.kind === ZLinkFrameworkErrorKind.Unavailable
|
|
3329
|
+
)
|
|
3330
|
+
return 'fenced';
|
|
3301
3331
|
}
|
|
3302
3332
|
return 'failed';
|
|
3303
3333
|
}
|