@zlink-systems/framework 0.26.0 → 0.27.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/CoreTypes.d.ts +6 -0
- package/dist/contracts/Common/CoreTypes.js +7 -0
- package/dist/contracts/Common/index.d.ts +1 -1
- package/dist/contracts/Common/index.js +0 -1
- package/dist/contracts/Configuration/InternalDefaults.d.ts +8 -0
- package/dist/contracts/Configuration/InternalDefaults.js +9 -1
- package/dist/contracts/Configuration/Registration.d.ts +13 -2
- package/dist/contracts/Configuration/Registration.js +58 -36
- package/dist/contracts/Configuration/RegistrationBuilderPolicy.d.ts +13 -1
- package/dist/contracts/Configuration/RegistrationBuilderPolicy.js +38 -1
- package/dist/contracts/Configuration/RegistrationBuilders.d.ts +2 -3
- package/dist/contracts/Configuration/RegistrationBuilders.js +27 -32
- package/dist/contracts/Configuration/RegistrationTypes.d.ts +1 -0
- package/dist/contracts/Configuration/RegistrationValidators.js +15 -12
- package/dist/contracts/Configuration/TimerRegistrationValidator.js +3 -2
- package/dist/contracts/Dispatch/ZLinkDispatchOptions.d.ts +1 -1
- package/dist/contracts/Handlers/JsonContract.js +10 -4
- package/dist/contracts/Locations/Authority.d.ts +1 -1
- package/dist/contracts/Locations/Authority.js +3 -2
- package/dist/contracts/Locations/Options.js +1 -1
- package/dist/contracts/Locations/Stores.d.ts +12 -0
- package/dist/contracts/Locations/Stores.js +9 -0
- package/dist/contracts/Spots/Contracts.d.ts +1 -1
- package/dist/internal.d.ts +4 -0
- package/dist/internal.js +15 -1
- package/dist/nest-integration.d.ts +4 -2
- package/dist/nest-integration.js +14 -4
- package/dist/runtime/abort.d.ts +1 -0
- package/dist/runtime/abort.js +8 -5
- package/dist/runtime/activation-admission.d.ts +1 -2
- package/dist/runtime/activation-admission.js +2 -6
- package/dist/runtime/actors/actor-authority-payload-codec.d.ts +1 -2
- package/dist/runtime/actors/actor-authority-payload-codec.js +34 -18
- package/dist/runtime/actors/actor-client.d.ts +2 -2
- package/dist/runtime/actors/actor-client.js +42 -143
- package/dist/runtime/actors/actor-context.d.ts +3 -5
- package/dist/runtime/actors/actor-context.js +13 -11
- package/dist/runtime/actors/actor-handoff.d.ts +4 -4
- package/dist/runtime/actors/actor-handoff.js +8 -8
- package/dist/runtime/actors/actor-lifecycle-snapshot.js +2 -1
- package/dist/runtime/actors/actor-local-native-join.d.ts +11 -6
- package/dist/runtime/actors/actor-local-native-join.js +83 -105
- package/dist/runtime/actors/actor-native-lookup.js +2 -8
- package/dist/runtime/actors/actor-packet-relay-wire.d.ts +3 -3
- package/dist/runtime/actors/actor-packet-relay-wire.js +5 -3
- package/dist/runtime/actors/actor-remote-joiner.d.ts +1 -1
- package/dist/runtime/actors/actor-remote-joiner.js +5 -9
- package/dist/runtime/actors/actor-remote-wire.js +5 -3
- package/dist/runtime/actors/actor-request-deadline.d.ts +3 -0
- package/dist/runtime/actors/actor-request-deadline.js +31 -0
- package/dist/runtime/actors/actor-retry-delay.js +2 -1
- package/dist/runtime/actors/actor-runtime-state.d.ts +9 -21
- package/dist/runtime/actors/actor-runtime-state.js +70 -187
- package/dist/runtime/actors/bound-session-wire.js +2 -7
- package/dist/runtime/actors/deferred-join-completion.d.ts +11 -6
- package/dist/runtime/actors/deferred-join-completion.js +1 -0
- package/dist/runtime/actors/index.d.ts +9 -7
- package/dist/runtime/actors/index.js +87 -69
- package/dist/runtime/actors/spot-actor-dispatch.d.ts +3 -3
- package/dist/runtime/actors/spot-actor-dispatch.js +25 -10
- package/dist/runtime/actors/transferred-actor-rollback.d.ts +3 -5
- package/dist/runtime/actors/transferred-actor-rollback.js +9 -42
- package/dist/runtime/admission.d.ts +2 -0
- package/dist/runtime/admission.js +7 -1
- package/dist/runtime/application-jobs/application-job-queue-scope.d.ts +1 -1
- package/dist/runtime/application-jobs/application-job-queue-scope.js +1 -1
- package/dist/runtime/backend/contracts/index.d.ts +6 -23
- package/dist/runtime/backend/mesh-actor-session-node-adapter.js +1 -17
- package/dist/runtime/backend/mesh-dispatch-pump.d.ts +1 -2
- package/dist/runtime/backend/mesh-dispatch-pump.js +95 -107
- package/dist/runtime/backend/node/node-backend-adapter-support.d.ts +1 -1
- package/dist/runtime/backend/node/node-backend-adapter-support.js +16 -6
- package/dist/runtime/backend/node/node-event-loop-poller.d.ts +2 -2
- package/dist/runtime/backend/node/node-event-loop-poller.js +6 -7
- package/dist/runtime/backend/node/node-monitor-backend-adapter.js +1 -0
- package/dist/runtime/backend/node/node-raw-binding-port.js +40 -16
- package/dist/runtime/backend/node/node-raw-mesh-backend.d.ts +14 -15
- package/dist/runtime/backend/node/node-raw-mesh-backend.js +146 -118
- package/dist/runtime/backend/node/node-socket-backend-adapter.js +3 -2
- package/dist/runtime/backend/raw-binding-port.d.ts +1 -1
- package/dist/runtime/backend/runtime-values.d.ts +4 -1
- package/dist/runtime/backend/runtime-values.js +2 -0
- package/dist/runtime/channels/channel-clients.d.ts +20 -8
- package/dist/runtime/channels/channel-clients.js +68 -52
- package/dist/runtime/channels/channel-envelope-inspection.js +2 -1
- package/dist/runtime/channels/channel-envelope.js +47 -29
- package/dist/runtime/channels/channel-outbound-operations.d.ts +3 -0
- package/dist/runtime/channels/channel-outbound-operations.js +9 -10
- package/dist/runtime/channels/channel-receive-loops.d.ts +8 -3
- package/dist/runtime/channels/channel-receive-loops.js +27 -6
- package/dist/runtime/channels/channel-runtime-lifecycle.d.ts +12 -1
- package/dist/runtime/channels/channel-runtime-lifecycle.js +48 -28
- package/dist/runtime/channels/channel-runtime-manager.js +5 -2
- package/dist/runtime/channels/channel-socket-options.js +3 -2
- package/dist/runtime/channels/channel-socket-registry.d.ts +14 -29
- package/dist/runtime/channels/channel-socket-registry.js +248 -174
- package/dist/runtime/channels/channel-transports.d.ts +11 -17
- package/dist/runtime/channels/channel-transports.js +68 -47
- package/dist/runtime/channels/client-server-location-runtime.d.ts +1 -1
- package/dist/runtime/channels/client-server-location-runtime.js +10 -11
- package/dist/runtime/channels/client-server-service-wire.d.ts +7 -2
- package/dist/runtime/channels/client-server-service-wire.js +32 -11
- package/dist/runtime/channels/dispatch-error-reporter.d.ts +1 -2
- package/dist/runtime/channels/dispatch-error-reporter.js +2 -1
- package/dist/runtime/channels/fanout-location-runtime.d.ts +16 -3
- package/dist/runtime/channels/fanout-location-runtime.js +130 -72
- package/dist/runtime/channels/spot-direct-envelope.d.ts +1 -0
- package/dist/runtime/channels/spot-direct-envelope.js +4 -3
- package/dist/runtime/channels/spot-node-route-transport.js +3 -2
- package/dist/runtime/diagnostics/diagnostic-text.d.ts +2 -0
- package/dist/runtime/diagnostics/diagnostic-text.js +7 -0
- package/dist/runtime/diagnostics/dispatch-error-details.d.ts +3 -0
- package/dist/runtime/diagnostics/dispatch-error-details.js +30 -2
- package/dist/runtime/diagnostics/flow-context.d.ts +6 -0
- package/dist/runtime/diagnostics/flow-context.js +16 -2
- package/dist/runtime/diagnostics/index.d.ts +4 -2
- package/dist/runtime/diagnostics/index.js +14 -4
- package/dist/runtime/diagnostics/message-flow.d.ts +1 -1
- package/dist/runtime/diagnostics/message-flow.js +10 -19
- package/dist/runtime/diagnostics/runtime-metrics.d.ts +94 -31
- package/dist/runtime/diagnostics/runtime-metrics.js +168 -105
- package/dist/runtime/diagnostics/runtime-observation-queue.js +3 -2
- package/dist/runtime/diagnostics/topology-runtime-projections.d.ts +2 -4
- package/dist/runtime/diagnostics/topology-runtime-projections.js +135 -154
- package/dist/runtime/disposal.d.ts +5 -0
- package/dist/runtime/disposal.js +22 -0
- package/dist/runtime/execution/index.d.ts +12 -9
- package/dist/runtime/execution/index.js +58 -14
- package/dist/runtime/execution/serial-execution-queue.d.ts +8 -2
- package/dist/runtime/execution/serial-execution-queue.js +54 -15
- package/dist/runtime/execution/state-lane.d.ts +8 -1
- package/dist/runtime/execution/state-lane.js +118 -3
- package/dist/runtime/foundation/actor-join-recovery-codec.d.ts +3 -0
- package/dist/runtime/foundation/actor-join-recovery-codec.js +15 -11
- package/dist/runtime/foundation/event-loop-resources.d.ts +2 -24
- package/dist/runtime/foundation/event-loop-resources.js +6 -119
- package/dist/runtime/foundation/operation-identity.d.ts +2 -0
- package/dist/runtime/foundation/operation-identity.js +9 -5
- package/dist/runtime/foundation/operation-registry.d.ts +5 -7
- package/dist/runtime/foundation/operation-registry.js +34 -44
- package/dist/runtime/foundation/raw-service-mesh-runtime.d.ts +8 -5
- package/dist/runtime/foundation/raw-service-mesh-runtime.js +62 -83
- package/dist/runtime/foundation/runtime-state-projections.d.ts +3 -1
- package/dist/runtime/foundation/runtime-state-projections.js +8 -0
- package/dist/runtime/foundation/service-authority-payload-codec.js +22 -12
- package/dist/runtime/foundation/service-discovery-registry.d.ts +4 -0
- package/dist/runtime/foundation/service-discovery-registry.js +22 -3
- package/dist/runtime/foundation/service-instance-activation-recovery-codec.js +8 -4
- package/dist/runtime/foundation/service-liveness-registry.js +2 -1
- package/dist/runtime/foundation/service-maintenance-runtime.d.ts +0 -1
- package/dist/runtime/foundation/service-maintenance-runtime.js +0 -6
- package/dist/runtime/foundation/service-metadata-codec.js +3 -3
- package/dist/runtime/foundation/service-relocation-aggregate-committer.d.ts +2 -5
- package/dist/runtime/foundation/service-relocation-aggregate-committer.js +1 -48
- package/dist/runtime/foundation/service-relocation-object-owner.js +3 -2
- package/dist/runtime/foundation/service-relocation-runtime.js +43 -32
- package/dist/runtime/foundation/service-runtime-contracts.d.ts +40 -8
- package/dist/runtime/foundation/service-runtime-contracts.js +25 -1
- package/dist/runtime/foundation/service-session-binding-ingress-port.d.ts +0 -12
- package/dist/runtime/foundation/service-stateful-registry.d.ts +2 -0
- package/dist/runtime/foundation/service-stateful-registry.js +10 -2
- package/dist/runtime/foundation/service-stateful-runtime.d.ts +26 -25
- package/dist/runtime/foundation/service-stateful-runtime.js +217 -204
- package/dist/runtime/foundation/service-stateful-wire-codec.d.ts +3 -3
- package/dist/runtime/foundation/service-stateful-wire-codec.js +89 -55
- package/dist/runtime/foundation/service-topology-registry.d.ts +0 -1
- package/dist/runtime/foundation/service-topology-registry.js +17 -32
- package/dist/runtime/foundation/service-wire-binary-primitives.d.ts +5 -0
- package/dist/runtime/foundation/service-wire-binary-primitives.js +6 -0
- package/dist/runtime/foundation/service-wire-codec.js +10 -8
- package/dist/runtime/foundation/service-wire-constants.generated.d.ts +1 -0
- package/dist/runtime/foundation/service-wire-constants.generated.js +2 -1
- package/dist/runtime/foundation/service-wire-m6a-codec.d.ts +2 -0
- package/dist/runtime/foundation/service-wire-m6a-codec.js +23 -13
- package/dist/runtime/framework-errors-internal.d.ts +2 -1
- package/dist/runtime/framework-errors-internal.js +343 -122
- package/dist/runtime/handlers/handler-instance-scope.d.ts +3 -1
- package/dist/runtime/handlers/handler-instance-scope.js +61 -74
- package/dist/runtime/host/actor-packet-relay.d.ts +9 -6
- package/dist/runtime/host/actor-packet-relay.js +48 -91
- package/dist/runtime/host/actor-placement-coordinator.js +7 -5
- package/dist/runtime/host/actor-runtime-options-factory.d.ts +2 -0
- package/dist/runtime/host/actor-runtime-options-factory.js +17 -4
- package/dist/runtime/host/actor-transfer-runtime.d.ts +16 -18
- package/dist/runtime/host/actor-transfer-runtime.js +143 -176
- package/dist/runtime/host/application-job-queue.js +16 -33
- package/dist/runtime/host/bound-session-relay.js +1 -1
- package/dist/runtime/host/channel-runtime-options-factory.js +1 -1
- package/dist/runtime/host/index.d.ts +14 -13
- package/dist/runtime/host/index.js +190 -157
- package/dist/runtime/host/instance-activation-authority.d.ts +2 -3
- package/dist/runtime/host/instance-activation-authority.js +17 -45
- package/dist/runtime/host/location-runtime-owner.d.ts +1 -1
- package/dist/runtime/host/location-runtime-owner.js +2 -2
- package/dist/runtime/host/remote-actor-join-receiver.d.ts +2 -2
- package/dist/runtime/host/remote-actor-join-receiver.js +1 -14
- package/dist/runtime/host/remote-actor-packet-target-store.d.ts +3 -2
- package/dist/runtime/host/remote-actor-packet-target-store.js +8 -47
- package/dist/runtime/host/remote-bound-session-relay.d.ts +2 -3
- package/dist/runtime/host/remote-bound-session-relay.js +7 -20
- package/dist/runtime/host/route-mesh-runtime.d.ts +13 -11
- package/dist/runtime/host/route-mesh-runtime.js +171 -252
- package/dist/runtime/host/runtime-shutdown.d.ts +2 -0
- package/dist/runtime/host/runtime-shutdown.js +18 -21
- package/dist/runtime/host/service-relocation-control.js +6 -1
- package/dist/runtime/host/service-relocation-host-runtime.d.ts +21 -30
- package/dist/runtime/host/service-relocation-host-runtime.js +508 -416
- package/dist/runtime/host/spot-address-transport.d.ts +2 -3
- package/dist/runtime/host/spot-address-transport.js +34 -136
- package/dist/runtime/host/spot-node-runtime-options-factory.d.ts +1 -1
- package/dist/runtime/host/spot-node-runtime-options-factory.js +3 -2
- package/dist/runtime/host/spot-runtime-options-factory.d.ts +4 -10
- package/dist/runtime/host/spot-runtime-options-factory.js +50 -14
- package/dist/runtime/host/user-spot-creation-coordinator.d.ts +3 -3
- package/dist/runtime/host/user-spot-creation-coordinator.js +11 -8
- package/dist/runtime/locations/aggregate-inventory-store.js +13 -10
- package/dist/runtime/locations/authority-key-codec.js +4 -3
- package/dist/runtime/locations/auto-connect-reconciler.d.ts +4 -0
- package/dist/runtime/locations/auto-connect-reconciler.js +37 -25
- package/dist/runtime/locations/creation-operation-id.js +6 -4
- package/dist/runtime/locations/domain-store-contract.d.ts +3 -3
- package/dist/runtime/locations/in-memory-authority-store.js +31 -15
- package/dist/runtime/locations/in-memory-location-store.d.ts +2 -2
- package/dist/runtime/locations/in-memory-location-store.js +17 -14
- package/dist/runtime/locations/in-memory-provider-location-store.d.ts +1 -0
- package/dist/runtime/locations/in-memory-provider-location-store.js +72 -22
- package/dist/runtime/locations/key-codec.js +3 -2
- package/dist/runtime/locations/lease-tracker.d.ts +3 -5
- package/dist/runtime/locations/lease-tracker.js +7 -11
- package/dist/runtime/locations/lifecycle.d.ts +4 -9
- package/dist/runtime/locations/lifecycle.js +2 -31
- package/dist/runtime/locations/location-store-failure.d.ts +2 -0
- package/dist/runtime/locations/location-store-failure.js +7 -0
- package/dist/runtime/locations/location-store-pages.d.ts +3 -0
- package/dist/runtime/locations/location-store-pages.js +13 -0
- package/dist/runtime/locations/location-store-repository.d.ts +5 -7
- package/dist/runtime/locations/location-store-repository.js +303 -332
- package/dist/runtime/locations/relocation-blob.js +18 -5
- package/dist/runtime/locations/resolvers.d.ts +5 -5
- package/dist/runtime/locations/resolvers.js +37 -28
- package/dist/runtime/locations/runtime.d.ts +5 -4
- package/dist/runtime/locations/runtime.js +123 -92
- package/dist/runtime/locations/spot-location-claims.d.ts +6 -0
- package/dist/runtime/locations/spot-location-claims.js +42 -1
- package/dist/runtime/messaging/payload-codec.js +26 -20
- package/dist/runtime/messaging/submission-result.d.ts +3 -0
- package/dist/runtime/messaging/submission-result.js +48 -0
- package/dist/runtime/protocol/service_wire_codec.generated.d.ts +1 -0
- package/dist/runtime/protocol/service_wire_codec.generated.js +12 -7
- package/dist/runtime/spots/formal-remote-actor-transfer-registry.d.ts +4 -1
- package/dist/runtime/spots/index.d.ts +14 -20
- package/dist/runtime/spots/index.js +302 -176
- package/dist/runtime/spots/spot-activation-registry.d.ts +3 -5
- package/dist/runtime/spots/spot-activation-registry.js +14 -50
- package/dist/runtime/spots/spot-activation-state.d.ts +1 -1
- package/dist/runtime/spots/spot-activation-state.js +2 -2
- package/dist/runtime/spots/spot-activation.d.ts +3 -4
- package/dist/runtime/spots/spot-activation.js +49 -32
- package/dist/runtime/spots/spot-actor-admission-coordinator.d.ts +1 -2
- package/dist/runtime/spots/spot-actor-admission-coordinator.js +3 -40
- package/dist/runtime/spots/spot-actor-join-dispatch.d.ts +10 -18
- package/dist/runtime/spots/spot-actor-join-dispatch.js +4 -52
- package/dist/runtime/spots/spot-actor-membership.d.ts +4 -6
- package/dist/runtime/spots/spot-actor-membership.js +22 -45
- package/dist/runtime/spots/spot-actor-packet-dispatch.d.ts +0 -1
- package/dist/runtime/spots/spot-actor-packet-dispatch.js +0 -9
- package/dist/runtime/spots/spot-actor-packet-relay-dispatch.d.ts +2 -2
- package/dist/runtime/spots/spot-actor-packet-relay-dispatch.js +1 -7
- package/dist/runtime/spots/spot-context.d.ts +2 -2
- package/dist/runtime/spots/spot-entry-activation.d.ts +2 -2
- package/dist/runtime/spots/spot-entry-activation.js +9 -20
- package/dist/runtime/spots/spot-lifecycle-metrics.js +3 -2
- package/dist/runtime/spots/spot-manager-public.d.ts +5 -6
- package/dist/runtime/spots/spot-manager-public.js +5 -4
- package/dist/runtime/spots/spot-node-autoconnect.js +22 -31
- package/dist/runtime/spots/spot-node-runtime-manager.d.ts +19 -18
- package/dist/runtime/spots/spot-node-runtime-manager.js +67 -72
- package/dist/runtime/spots/spot-outbound.d.ts +4 -3
- package/dist/runtime/spots/spot-outbound.js +9 -8
- package/dist/runtime/spots/spot-remote-codec.js +5 -3
- package/dist/runtime/spots/spot-route-packet-dispatch.d.ts +2 -2
- package/dist/runtime/spots/spot-route-packet-dispatch.js +8 -8
- package/dist/runtime/spots/spot-route-replies.d.ts +2 -2
- package/dist/runtime/spots/spot-route-replies.js +3 -1
- package/dist/runtime/spots/spot-routed-actor-admission.d.ts +3 -3
- package/dist/runtime/spots/spot-routed-actor-admission.js +3 -12
- package/dist/runtime/spots/spot-routed-frame-dispatch.d.ts +1 -2
- package/dist/runtime/spots/spot-routed-frame-dispatch.js +0 -1
- package/dist/runtime/spots/spot-routed-spot-packet-dispatch.d.ts +4 -0
- package/dist/runtime/spots/spot-routed-spot-packet-dispatch.js +65 -15
- package/dist/runtime/spots/spot-runtime-ports.d.ts +2 -16
- package/dist/runtime/spots/spot-serial-executor.js +2 -2
- package/dist/runtime/spots/spot-serial-turn-executor.d.ts +27 -7
- package/dist/runtime/spots/spot-serial-turn-executor.js +83 -11
- package/dist/runtime/spots/spot-timer.d.ts +3 -2
- package/dist/runtime/streams/actor-session-binding-registry.d.ts +16 -29
- package/dist/runtime/streams/actor-session-binding-registry.js +142 -212
- package/dist/runtime/streams/actor-session-binding-runtime-owner.d.ts +1 -4
- package/dist/runtime/streams/bound-actor-relay-sender.d.ts +6 -2
- package/dist/runtime/streams/bound-actor-relay-sender.js +57 -33
- package/dist/runtime/streams/bound-session-service.d.ts +7 -0
- package/dist/runtime/streams/bound-session-service.js +11 -1
- package/dist/runtime/streams/index.d.ts +14 -15
- package/dist/runtime/streams/index.js +20 -21
- package/dist/runtime/streams/managed-stream.d.ts +3 -0
- package/dist/runtime/streams/managed-stream.js +17 -8
- package/dist/runtime/streams/native-fallback-bound-session.js +1 -3
- package/dist/runtime/streams/protocol.d.ts +6 -33
- package/dist/runtime/streams/protocol.js +38 -110
- package/dist/runtime/streams/session-actor-coordinator.d.ts +2 -3
- package/dist/runtime/streams/session-actor-coordinator.js +12 -4
- package/dist/runtime/streams/session-calls.d.ts +1 -1
- package/dist/runtime/streams/session-calls.js +5 -4
- package/dist/runtime/streams/session-context.d.ts +6 -6
- package/dist/runtime/streams/session-context.js +22 -4
- package/dist/runtime/streams/session-requests.js +2 -1
- package/dist/runtime/streams/stream-binding-runtime-ports.d.ts +16 -1
- package/dist/runtime/streams/stream-frame-factory.js +2 -2
- package/dist/runtime/streams/stream-session-runtime.d.ts +10 -11
- package/dist/runtime/streams/stream-session-runtime.js +25 -33
- package/dist/runtime/workers/index.d.ts +2 -2
- package/dist/runtime/workers/index.js +5 -4
- package/package.json +3 -3
- package/src/contracts/Common/CoreTypes.ts +7 -0
- package/src/contracts/Common/index.ts +1 -1
- package/src/contracts/Configuration/InternalDefaults.ts +12 -0
- package/src/contracts/Configuration/Registration.ts +92 -48
- package/src/contracts/Configuration/RegistrationBuilderPolicy.ts +44 -2
- package/src/contracts/Configuration/RegistrationBuilders.ts +77 -68
- package/src/contracts/Configuration/RegistrationTypes.ts +1 -0
- package/src/contracts/Configuration/RegistrationValidators.ts +19 -13
- package/src/contracts/Configuration/TimerRegistrationValidator.ts +4 -2
- package/src/contracts/Dispatch/ZLinkDispatchOptions.ts +1 -0
- package/src/contracts/Handlers/JsonContract.ts +14 -4
- package/src/contracts/Locations/Authority.ts +7 -3
- package/src/contracts/Locations/Options.ts +1 -1
- package/src/contracts/Locations/Stores.ts +14 -0
- package/src/contracts/Spots/Contracts.ts +1 -1
- package/src/internal.ts +14 -0
- package/src/nest-integration.ts +28 -10
- package/src/runtime/abort.ts +6 -5
- package/src/runtime/activation-admission.ts +2 -8
- package/src/runtime/actors/actor-authority-payload-codec.ts +58 -20
- package/src/runtime/actors/actor-client.ts +77 -204
- package/src/runtime/actors/actor-context.ts +39 -33
- package/src/runtime/actors/actor-handoff.ts +24 -22
- package/src/runtime/actors/actor-lifecycle-snapshot.ts +2 -1
- package/src/runtime/actors/actor-local-native-join.ts +172 -174
- package/src/runtime/actors/actor-native-lookup.ts +2 -9
- package/src/runtime/actors/actor-packet-relay-wire.ts +18 -12
- package/src/runtime/actors/actor-remote-joiner.ts +9 -11
- package/src/runtime/actors/actor-remote-wire.ts +5 -3
- package/src/runtime/actors/actor-request-deadline.ts +49 -0
- package/src/runtime/actors/actor-retry-delay.ts +2 -1
- package/src/runtime/actors/actor-runtime-state.ts +85 -247
- package/src/runtime/actors/bound-session-wire.ts +2 -8
- package/src/runtime/actors/deferred-join-completion.ts +10 -6
- package/src/runtime/actors/index.ts +100 -79
- package/src/runtime/actors/spot-actor-dispatch.ts +60 -29
- package/src/runtime/actors/transferred-actor-rollback.ts +11 -62
- package/src/runtime/admission.ts +8 -1
- package/src/runtime/application-jobs/application-job-queue-scope.ts +4 -4
- package/src/runtime/backend/contracts/index.ts +13 -29
- package/src/runtime/backend/mesh-actor-session-node-adapter.ts +2 -18
- package/src/runtime/backend/mesh-dispatch-pump.ts +111 -117
- package/src/runtime/backend/node/node-backend-adapter-support.ts +23 -6
- package/src/runtime/backend/node/node-event-loop-poller.ts +8 -12
- package/src/runtime/backend/node/node-monitor-backend-adapter.ts +1 -0
- package/src/runtime/backend/node/node-raw-binding-port.ts +41 -20
- package/src/runtime/backend/node/node-raw-mesh-backend.ts +227 -170
- package/src/runtime/backend/node/node-socket-backend-adapter.ts +3 -2
- package/src/runtime/backend/raw-binding-port.ts +1 -1
- package/src/runtime/backend/runtime-values.ts +4 -1
- package/src/runtime/channels/channel-clients.ts +132 -85
- package/src/runtime/channels/channel-envelope-inspection.ts +2 -1
- package/src/runtime/channels/channel-envelope.ts +58 -29
- package/src/runtime/channels/channel-outbound-operations.ts +10 -23
- package/src/runtime/channels/channel-receive-loops.ts +39 -7
- package/src/runtime/channels/channel-runtime-lifecycle.ts +60 -27
- package/src/runtime/channels/channel-runtime-manager.ts +6 -2
- package/src/runtime/channels/channel-socket-options.ts +8 -2
- package/src/runtime/channels/channel-socket-registry.ts +301 -192
- package/src/runtime/channels/channel-transports.ts +161 -112
- package/src/runtime/channels/client-server-location-runtime.ts +17 -17
- package/src/runtime/channels/client-server-service-wire.ts +40 -12
- package/src/runtime/channels/dispatch-error-reporter.ts +7 -5
- package/src/runtime/channels/fanout-location-runtime.ts +172 -91
- package/src/runtime/channels/spot-direct-envelope.ts +1 -1
- package/src/runtime/channels/spot-node-route-transport.ts +5 -2
- package/src/runtime/diagnostics/diagnostic-text.ts +4 -0
- package/src/runtime/diagnostics/dispatch-error-details.ts +36 -1
- package/src/runtime/diagnostics/flow-context.ts +16 -2
- package/src/runtime/diagnostics/index.ts +27 -17
- package/src/runtime/diagnostics/message-flow.ts +15 -25
- package/src/runtime/diagnostics/runtime-metrics.ts +181 -113
- package/src/runtime/diagnostics/runtime-observation-queue.ts +3 -2
- package/src/runtime/diagnostics/topology-runtime-projections.ts +194 -162
- package/src/runtime/disposal.ts +19 -0
- package/src/runtime/execution/index.ts +60 -20
- package/src/runtime/execution/serial-execution-queue.ts +131 -18
- package/src/runtime/execution/state-lane.ts +142 -4
- package/src/runtime/foundation/actor-join-recovery-codec.ts +13 -8
- package/src/runtime/foundation/event-loop-resources.ts +5 -122
- package/src/runtime/foundation/operation-identity.ts +11 -5
- package/src/runtime/foundation/operation-registry.ts +33 -50
- package/src/runtime/foundation/raw-service-mesh-runtime.ts +110 -111
- package/src/runtime/foundation/runtime-state-projections.ts +9 -1
- package/src/runtime/foundation/service-authority-payload-codec.ts +31 -13
- package/src/runtime/foundation/service-discovery-registry.ts +32 -3
- package/src/runtime/foundation/service-instance-activation-recovery-codec.ts +12 -4
- package/src/runtime/foundation/service-liveness-registry.ts +2 -1
- package/src/runtime/foundation/service-maintenance-runtime.ts +0 -10
- package/src/runtime/foundation/service-metadata-codec.ts +2 -2
- package/src/runtime/foundation/service-relocation-aggregate-committer.ts +3 -66
- package/src/runtime/foundation/service-relocation-object-owner.ts +5 -2
- package/src/runtime/foundation/service-relocation-runtime.ts +57 -35
- package/src/runtime/foundation/service-runtime-contracts.ts +46 -10
- package/src/runtime/foundation/service-session-binding-ingress-port.ts +0 -17
- package/src/runtime/foundation/service-stateful-registry.ts +14 -2
- package/src/runtime/foundation/service-stateful-runtime.ts +322 -276
- package/src/runtime/foundation/service-stateful-wire-codec.ts +128 -80
- package/src/runtime/foundation/service-topology-registry.ts +23 -32
- package/src/runtime/foundation/service-wire-binary-primitives.ts +6 -0
- package/src/runtime/foundation/service-wire-codec.ts +15 -8
- package/src/runtime/foundation/service-wire-constants.generated.ts +1 -0
- package/src/runtime/foundation/service-wire-m6a-codec.ts +29 -15
- package/src/runtime/framework-errors-internal.ts +380 -134
- package/src/runtime/handlers/handler-instance-scope.ts +68 -95
- package/src/runtime/host/actor-packet-relay.ts +57 -147
- package/src/runtime/host/actor-placement-coordinator.ts +8 -5
- package/src/runtime/host/actor-runtime-options-factory.ts +27 -8
- package/src/runtime/host/actor-transfer-runtime.ts +180 -260
- package/src/runtime/host/application-job-queue.ts +28 -34
- package/src/runtime/host/bound-session-relay.ts +1 -2
- package/src/runtime/host/channel-runtime-options-factory.ts +1 -2
- package/src/runtime/host/index.ts +327 -296
- package/src/runtime/host/instance-activation-authority.ts +89 -109
- package/src/runtime/host/location-runtime-owner.ts +4 -2
- package/src/runtime/host/remote-actor-join-receiver.ts +3 -31
- package/src/runtime/host/remote-actor-packet-target-store.ts +17 -58
- package/src/runtime/host/remote-bound-session-relay.ts +8 -41
- package/src/runtime/host/route-mesh-runtime.ts +228 -271
- package/src/runtime/host/runtime-shutdown.ts +17 -21
- package/src/runtime/host/service-relocation-control.ts +14 -1
- package/src/runtime/host/service-relocation-host-runtime.ts +699 -561
- package/src/runtime/host/spot-address-transport.ts +73 -195
- package/src/runtime/host/spot-node-runtime-options-factory.ts +6 -3
- package/src/runtime/host/spot-runtime-options-factory.ts +73 -22
- package/src/runtime/host/user-spot-creation-coordinator.ts +36 -22
- package/src/runtime/locations/aggregate-inventory-store.ts +16 -13
- package/src/runtime/locations/authority-key-codec.ts +7 -3
- package/src/runtime/locations/auto-connect-reconciler.ts +39 -26
- package/src/runtime/locations/creation-operation-id.ts +6 -3
- package/src/runtime/locations/domain-store-contract.ts +12 -3
- package/src/runtime/locations/in-memory-authority-store.ts +44 -15
- package/src/runtime/locations/in-memory-location-store.ts +50 -39
- package/src/runtime/locations/in-memory-provider-location-store.ts +100 -25
- package/src/runtime/locations/key-codec.ts +3 -2
- package/src/runtime/locations/lease-tracker.ts +8 -14
- package/src/runtime/locations/lifecycle.ts +13 -43
- package/src/runtime/locations/location-store-failure.ts +4 -0
- package/src/runtime/locations/location-store-pages.ts +18 -0
- package/src/runtime/locations/location-store-repository.ts +450 -478
- package/src/runtime/locations/relocation-blob.ts +17 -6
- package/src/runtime/locations/resolvers.ts +75 -49
- package/src/runtime/locations/runtime.ts +220 -110
- package/src/runtime/locations/spot-location-claims.ts +58 -1
- package/src/runtime/messaging/payload-codec.ts +35 -24
- package/src/runtime/messaging/submission-result.ts +57 -1
- package/src/runtime/protocol/service_wire_codec.generated.ts +18 -8
- package/src/runtime/protocol/service_wire_pilot_codec.generated.ts +1 -1
- package/src/runtime/spots/formal-remote-actor-transfer-registry.ts +4 -1
- package/src/runtime/spots/index.ts +433 -229
- package/src/runtime/spots/spot-activation-registry.ts +30 -69
- package/src/runtime/spots/spot-activation-state.ts +2 -2
- package/src/runtime/spots/spot-activation.ts +67 -37
- package/src/runtime/spots/spot-actor-admission-coordinator.ts +5 -57
- package/src/runtime/spots/spot-actor-join-dispatch.ts +24 -77
- package/src/runtime/spots/spot-actor-membership.ts +40 -72
- package/src/runtime/spots/spot-actor-packet-dispatch.ts +0 -16
- package/src/runtime/spots/spot-actor-packet-relay-dispatch.ts +3 -15
- package/src/runtime/spots/spot-context.ts +3 -3
- package/src/runtime/spots/spot-entry-activation.ts +13 -30
- package/src/runtime/spots/spot-lifecycle-metrics.ts +3 -2
- package/src/runtime/spots/spot-manager-public.ts +21 -17
- package/src/runtime/spots/spot-node-autoconnect.ts +20 -26
- package/src/runtime/spots/spot-node-runtime-manager.ts +136 -125
- package/src/runtime/spots/spot-outbound.ts +45 -23
- package/src/runtime/spots/spot-remote-codec.ts +7 -3
- package/src/runtime/spots/spot-route-packet-dispatch.ts +25 -24
- package/src/runtime/spots/spot-route-replies.ts +6 -4
- package/src/runtime/spots/spot-routed-actor-admission.ts +13 -26
- package/src/runtime/spots/spot-routed-frame-dispatch.ts +2 -3
- package/src/runtime/spots/spot-routed-spot-packet-dispatch.ts +95 -22
- package/src/runtime/spots/spot-runtime-ports.ts +5 -27
- package/src/runtime/spots/spot-serial-executor.ts +2 -2
- package/src/runtime/spots/spot-serial-turn-executor.ts +112 -11
- package/src/runtime/spots/spot-timer.ts +3 -2
- package/src/runtime/streams/actor-session-binding-registry.ts +179 -269
- package/src/runtime/streams/actor-session-binding-runtime-owner.ts +0 -8
- package/src/runtime/streams/bound-actor-relay-sender.ts +89 -43
- package/src/runtime/streams/bound-session-service.ts +21 -1
- package/src/runtime/streams/index.ts +76 -64
- package/src/runtime/streams/managed-stream.ts +29 -10
- package/src/runtime/streams/native-fallback-bound-session.ts +1 -3
- package/src/runtime/streams/protocol.ts +34 -88
- package/src/runtime/streams/session-actor-coordinator.ts +17 -5
- package/src/runtime/streams/session-calls.ts +6 -5
- package/src/runtime/streams/session-context.ts +54 -10
- package/src/runtime/streams/session-requests.ts +2 -1
- package/src/runtime/streams/stream-binding-runtime-ports.ts +22 -1
- package/src/runtime/streams/stream-frame-factory.ts +2 -3
- package/src/runtime/streams/stream-session-runtime.ts +57 -59
- package/src/runtime/workers/index.ts +13 -12
- package/dist/runtime/actors/post-commit-actor-location.d.ts +0 -19
- package/dist/runtime/actors/post-commit-actor-location.js +0 -72
- package/dist/runtime/spots/spot-native-actor-join-admission.d.ts +0 -26
- package/dist/runtime/spots/spot-native-actor-join-admission.js +0 -106
- package/src/runtime/actors/post-commit-actor-location.ts +0 -121
- package/src/runtime/spots/spot-native-actor-join-admission.ts +0 -155
|
@@ -1,83 +1,79 @@
|
|
|
1
|
+
import { UINT64_MAX, ZlinkStreamContentType } from '@zlink-systems/stream-wire';
|
|
1
2
|
import { randomBytes } from 'node:crypto';
|
|
2
|
-
import { SubmitResult } from '../backend/runtime-values';
|
|
3
|
-
import type {
|
|
4
|
-
RoutingId,
|
|
5
|
-
Type,
|
|
6
|
-
ZLinkActor,
|
|
7
|
-
ZLinkActorRelocationAdapter,
|
|
8
|
-
ZLinkMeshNodeDescriptor,
|
|
9
|
-
ZLinkSpot,
|
|
10
|
-
ZLinkSpotRelocationAdapter,
|
|
11
|
-
ZLinkInstanceSpot
|
|
12
|
-
} from '../../contracts';
|
|
13
|
-
import type {
|
|
14
|
-
ZLinkAuthorityKey,
|
|
15
|
-
ZLinkAuthorityScanCursor,
|
|
16
|
-
ZLinkAuthoritySnapshot,
|
|
17
|
-
ZLinkCapacityVector,
|
|
18
|
-
ZLinkLocationOwnerToken
|
|
19
|
-
} from '../locations/internal-location-contracts';
|
|
20
3
|
import {
|
|
4
|
+
type RoutingId,
|
|
5
|
+
type Type,
|
|
6
|
+
type ZLinkActor,
|
|
7
|
+
type ZLinkActorRelocationAdapter,
|
|
8
|
+
type ZLinkInstanceSpot,
|
|
9
|
+
type ZLinkMeshNodeDescriptor,
|
|
10
|
+
type ZLinkSpot,
|
|
11
|
+
type ZLinkSpotRelocationAdapter,
|
|
21
12
|
ZLinkFrameworkErrorKind,
|
|
22
13
|
ZLinkFrameworkException,
|
|
23
14
|
ZLinkFrameworkRuntimeState,
|
|
24
15
|
ZLinkObjectRole,
|
|
16
|
+
ZLinkSpotKind,
|
|
25
17
|
ZLinkSpotRelocationCoordinationMode,
|
|
26
18
|
ZLinkSpotRelocationReadyOutcome,
|
|
27
|
-
ZLinkSpotKind,
|
|
28
19
|
ZLinkUserSpotExecutionMode
|
|
29
20
|
} from '../../contracts';
|
|
30
|
-
|
|
31
|
-
import {
|
|
32
|
-
ZLinkFrameworkInternalErrorKind,
|
|
33
|
-
createInternalFrameworkException
|
|
34
|
-
} from '../framework-errors-internal';
|
|
35
|
-
import type { ZLinkDomainLocationStore as ZLinkLocationStore } from '../locations/domain-store-contract';
|
|
36
|
-
import type { ZLinkTrackedInstanceAuthority } from '../locations/spot-location-claims';
|
|
21
|
+
|
|
37
22
|
import type { ZLinkProviderResolver } from '../../contracts/Common/ZLinkProviderResolver';
|
|
38
|
-
import
|
|
23
|
+
import { zlinkRuntimeDefaultLocationOptions } from '../../contracts/Locations/Options';
|
|
24
|
+
import { ZLINK_PROVIDER_MAX_PAGE_SIZE } from '../../contracts/Locations/Stores';
|
|
39
25
|
import type { ZLinkActivationAdmission } from '../activation-admission';
|
|
40
|
-
import type {
|
|
26
|
+
import type { DefaultZLinkActorManager } from '../actors';
|
|
27
|
+
import {
|
|
28
|
+
decodeRelocatingActorAuthorityIdentity,
|
|
29
|
+
rewriteActorAuthorityRoute
|
|
30
|
+
} from '../actors/actor-authority-publication';
|
|
31
|
+
import {
|
|
32
|
+
replayActorHandoffBacklog,
|
|
33
|
+
type ZLinkActorHandoffPacket,
|
|
34
|
+
type ZLinkActorHandoffResult
|
|
35
|
+
} from '../actors/actor-handoff';
|
|
36
|
+
import type { ZLinkActorJoinRelocation } from '../actors/actor-join-relocation';
|
|
37
|
+
import {
|
|
38
|
+
ZLINK_REMOTE_ACTOR_SOURCE_LEAVE_TERMINAL,
|
|
39
|
+
decodeRemoteActorSourceLeaveTerminal
|
|
40
|
+
} from '../actors/actor-remote-wire';
|
|
41
|
+
import {
|
|
42
|
+
toFrameworkActorRef,
|
|
43
|
+
type ZLinkActorRuntimeState,
|
|
44
|
+
type ZLinkRemoteBoundSessionTarget
|
|
45
|
+
} from '../actors/actor-runtime-state';
|
|
41
46
|
import type { ZLinkBackendMeshNode, ZLinkMeshCompletionTable } from '../backend';
|
|
42
|
-
import {
|
|
43
|
-
import {
|
|
44
|
-
import { ServiceWireProtocolError } from '../foundation/service-wire-m6a-codec';
|
|
45
|
-
import type { ServiceSpotMessageFollowSeal } from '../foundation/service-stateful-runtime';
|
|
47
|
+
import { RequestResult, SubmitResult } from '../backend/runtime-values';
|
|
48
|
+
import type { ZLinkFrameworkRegistration } from '../configuration';
|
|
46
49
|
import {
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
serviceRelocationAuthoritySlotIdentity,
|
|
56
|
-
type ServiceRelocationEnvelope,
|
|
57
|
-
type ServiceRelocationMembership,
|
|
58
|
-
type ServiceRelocationParticipant,
|
|
59
|
-
type ServiceRelocationPublication,
|
|
60
|
-
type ServiceRelocationQueuedMessage,
|
|
61
|
-
type ServiceRelocationTimer
|
|
62
|
-
} from '../foundation/service-relocation-runtime';
|
|
50
|
+
type ZLinkRuntimeEventPublisher,
|
|
51
|
+
type ZLinkRuntimeMetrics,
|
|
52
|
+
isRelocationDebugEnabled,
|
|
53
|
+
relocationDebug
|
|
54
|
+
} from '../diagnostics';
|
|
55
|
+
|
|
56
|
+
import { METRIC_NAMES, MILLISECONDS_PER_SECOND } from '../diagnostics/runtime-metrics';
|
|
57
|
+
import { isStructuralGuardEnabled, trackDiagnosticCompletion } from '../execution/state-lane';
|
|
63
58
|
import {
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
} from '
|
|
59
|
+
RECREATE_RELOCATION_CONTENT_TYPE,
|
|
60
|
+
SNAPSHOT_RELOCATION_CONTENT_TYPE,
|
|
61
|
+
decodeCanonicalActorJoinRecoverySavedWork,
|
|
62
|
+
encodeCanonicalActorJoinRecoverySavedWork,
|
|
63
|
+
type CanonicalActorJoinRecovery
|
|
64
|
+
} from '../foundation/actor-join-recovery-codec';
|
|
65
|
+
import { OPERATION_IDENTITY_BYTES } from '../foundation/operation-identity';
|
|
66
|
+
import { rewriteServiceAuthorityRoute } from '../foundation/service-authority-payload-codec';
|
|
67
|
+
import { ServiceMaintenanceRuntime } from '../foundation/service-maintenance-runtime';
|
|
71
68
|
import {
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
type
|
|
75
|
-
} from '
|
|
69
|
+
ServiceRelocationAggregateCommitter,
|
|
70
|
+
type ServicePreparedRelocationAggregate,
|
|
71
|
+
type ServiceRelocationAggregatePlan
|
|
72
|
+
} from '../foundation/service-relocation-aggregate-committer';
|
|
76
73
|
import {
|
|
77
74
|
ServiceRelocationAuthorityError,
|
|
78
75
|
ServiceRelocationPostCommitError
|
|
79
76
|
} from '../foundation/service-relocation-coordinator';
|
|
80
|
-
import { ServiceMaintenanceRuntime } from '../foundation/service-maintenance-runtime';
|
|
81
77
|
import {
|
|
82
78
|
ServiceRelocationObjectCaptureOwner,
|
|
83
79
|
ServiceRelocationObjectRestoreOwner,
|
|
@@ -88,89 +84,125 @@ import {
|
|
|
88
84
|
type ServiceRelocationTargetObjectPort
|
|
89
85
|
} from '../foundation/service-relocation-object-owner';
|
|
90
86
|
import {
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
type
|
|
102
|
-
type
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
type ZLinkActorHandoffResult
|
|
108
|
-
} from '../actors/actor-handoff';
|
|
109
|
-
import { decodeHandoffBacklog } from '../spots/spot-remote-codec';
|
|
110
|
-
import {
|
|
111
|
-
decodeRelocatingActorAuthorityIdentity,
|
|
112
|
-
rewriteActorAuthorityRoute
|
|
113
|
-
} from '../actors/actor-authority-publication';
|
|
114
|
-
import { rewriteServiceAuthorityRoute } from '../foundation/service-authority-payload-codec';
|
|
115
|
-
import { committedActorOwnerFence, type ZLinkActorTransferRuntime } from './actor-transfer-runtime';
|
|
116
|
-
import { decodeAuthorityKey, encodeAuthorityKey } from '../locations/authority-key-codec';
|
|
87
|
+
ServiceRelocationAuthorityPayloadCodec,
|
|
88
|
+
crc32c,
|
|
89
|
+
decodeServiceRelocationEnvelope,
|
|
90
|
+
encodeServiceRelocationEnvelope,
|
|
91
|
+
inventoryDigest,
|
|
92
|
+
projectServiceRelocationAuthorityTargetReady,
|
|
93
|
+
replaceServiceRelocationAuthorityApplicationPayload,
|
|
94
|
+
serviceRelocationAuthorityApplicationPayload,
|
|
95
|
+
serviceRelocationAuthoritySlotIdentity,
|
|
96
|
+
type ServiceRelocationEnvelope,
|
|
97
|
+
type ServiceRelocationMembership,
|
|
98
|
+
type ServiceRelocationParticipant,
|
|
99
|
+
type ServiceRelocationPublication,
|
|
100
|
+
type ServiceRelocationQueuedMessage,
|
|
101
|
+
type ServiceRelocationTimer
|
|
102
|
+
} from '../foundation/service-relocation-runtime';
|
|
117
103
|
import {
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
type ZLinkServiceRelocationControlResponse
|
|
124
|
-
} from './service-relocation-control';
|
|
104
|
+
MeshPeerRuntimeState,
|
|
105
|
+
ReceiveKind,
|
|
106
|
+
type ReceiveRecord
|
|
107
|
+
} from '../foundation/service-runtime-contracts';
|
|
108
|
+
import type { ServiceSpotMessageFollowSeal } from '../foundation/service-stateful-runtime';
|
|
125
109
|
import {
|
|
110
|
+
M6bServiceWireCommand,
|
|
126
111
|
decodeMaintenanceReplyRelay,
|
|
127
112
|
decodeMaintenanceReplyRelayAck,
|
|
113
|
+
decodeServiceWireFrozenRecord,
|
|
128
114
|
decodeSessionRelocationRoute,
|
|
129
115
|
decodeSessionRelocationSeal,
|
|
130
116
|
decodeSessionRelocationSealed,
|
|
131
117
|
encodeMaintenanceReplyRelay,
|
|
132
118
|
encodeMaintenanceReplyRelayAck,
|
|
119
|
+
encodeServiceWireFrozenActorApplicationRecord,
|
|
133
120
|
encodeSessionRelocationRoute,
|
|
134
121
|
encodeSessionRelocationSeal,
|
|
135
122
|
encodeSessionRelocationSealed,
|
|
136
123
|
serviceSessionRelocationIdentityKey,
|
|
137
|
-
decodeServiceWireFrozenRecord,
|
|
138
|
-
encodeServiceWireFrozenActorApplicationRecord,
|
|
139
|
-
M6bServiceWireCommand,
|
|
140
|
-
type ServiceMaintenanceReplyRelay,
|
|
141
|
-
type ServiceMaintenanceReplyRelayAck,
|
|
142
124
|
type ServiceMaintenanceRelocationControl,
|
|
143
125
|
type ServiceMaintenanceRelocationCutover,
|
|
144
126
|
type ServiceMaintenanceRelocationData,
|
|
145
127
|
type ServiceMaintenanceRelocationFailed,
|
|
146
|
-
type ServiceMaintenanceRelocationReady,
|
|
147
128
|
type ServiceMaintenanceRelocationPrepare,
|
|
129
|
+
type ServiceMaintenanceRelocationReady,
|
|
148
130
|
type ServiceMaintenanceRelocationState,
|
|
131
|
+
type ServiceMaintenanceReplyRelay,
|
|
132
|
+
type ServiceMaintenanceReplyRelayAck,
|
|
149
133
|
type ServiceSessionRelocationRoute,
|
|
150
134
|
type ServiceSessionRelocationSeal,
|
|
151
135
|
type ServiceSessionRelocationSealed,
|
|
152
136
|
type ServiceWireOperationId,
|
|
153
|
-
type ServiceWireRequestSourceFence,
|
|
154
|
-
type ServiceWireRelocationTarget,
|
|
155
137
|
type ServiceWireRelocationCoordinatorFence,
|
|
156
|
-
type ServiceWireRelocationObject
|
|
138
|
+
type ServiceWireRelocationObject,
|
|
139
|
+
type ServiceWireRelocationTarget,
|
|
140
|
+
type ServiceWireRequestSourceFence
|
|
157
141
|
} from '../foundation/service-stateful-wire-codec';
|
|
158
142
|
import { ServiceWireFrameworkErrorCode } from '../foundation/service-wire-constants.generated';
|
|
143
|
+
import { ServiceWireProtocolError } from '../foundation/service-wire-m6a-codec';
|
|
144
|
+
import {
|
|
145
|
+
ZLinkFrameworkInternalErrorKind,
|
|
146
|
+
createInternalFrameworkException,
|
|
147
|
+
frameworkRelocationFailureCode,
|
|
148
|
+
internalFrameworkErrorKindFromWireFailureCode
|
|
149
|
+
} from '../framework-errors-internal';
|
|
150
|
+
import { decodeAuthorityKey, encodeAuthorityKey } from '../locations/authority-key-codec';
|
|
151
|
+
import { isIndeterminateLocationStoreFailure } from '../locations/location-store-failure';
|
|
152
|
+
import type { ZLinkDomainLocationStore as ZLinkLocationStore } from '../locations/domain-store-contract';
|
|
153
|
+
import type {
|
|
154
|
+
ZLinkAuthorityKey,
|
|
155
|
+
ZLinkAuthorityScanCursor,
|
|
156
|
+
ZLinkAuthoritySnapshot,
|
|
157
|
+
ZLinkCapacityVector,
|
|
158
|
+
ZLinkLocationOwnerToken
|
|
159
|
+
} from '../locations/internal-location-contracts';
|
|
160
|
+
import type { ZLinkTrackedInstanceAuthority } from '../locations/spot-location-claims';
|
|
161
|
+
import { decodeRoutingId, encodeRoutingIdStorageHex, routingIdsEqual } from '../routing-id';
|
|
162
|
+
import type { DefaultZLinkSpotManager, ZLinkSpotNodeRuntimeManager } from '../spots';
|
|
163
|
+
import type { ZLinkSpotActivation } from '../spots/spot-activation-state';
|
|
164
|
+
import { createProviderInstance } from '../spots/spot-provider';
|
|
165
|
+
import { decodeHandoffBacklog } from '../spots/spot-remote-codec';
|
|
166
|
+
import { committedActorOwnerFence, type ZLinkActorTransferRuntime } from './actor-transfer-runtime';
|
|
159
167
|
import { BoundedReplayMap } from './bounded-replay-map';
|
|
160
|
-
import
|
|
168
|
+
import {
|
|
169
|
+
ZLinkRelocationInFlightBudget,
|
|
170
|
+
ZLinkRelocationPayloadAssembly,
|
|
171
|
+
effectiveActorJoinChunkLimitBytes,
|
|
172
|
+
effectiveRelocationBudgetBytes,
|
|
173
|
+
planRelocationChunks,
|
|
174
|
+
relocationChunkAt
|
|
175
|
+
} from './relocation-direct-transfer';
|
|
161
176
|
import {
|
|
162
177
|
ZLINK_INTERNAL_RELOCATION_INTEGRITY_FAULT_GATE,
|
|
163
178
|
type ZLinkInternalRelocationIntegrityFaultGate
|
|
164
179
|
} from './relocation-integrity-fault-gate';
|
|
165
180
|
import {
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
181
|
+
captureRelocationAdapterState,
|
|
182
|
+
restoreRelocationAdapterState,
|
|
183
|
+
type ZLinkRelocationStateAdapterLike
|
|
184
|
+
} from './relocation-state-adapter';
|
|
169
185
|
import {
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
186
|
+
decodeServiceRelocationControlRequest,
|
|
187
|
+
decodeServiceRelocationControlResponse,
|
|
188
|
+
encodeServiceRelocationControlRequest,
|
|
189
|
+
encodeServiceRelocationControlResponse,
|
|
190
|
+
type ZLinkServiceRelocationControlRequest,
|
|
191
|
+
type ZLinkServiceRelocationControlResponse
|
|
192
|
+
} from './service-relocation-control';
|
|
193
|
+
const RELOCATION_ATTEMPT_TIMEOUT_MS = 250;
|
|
194
|
+
|
|
195
|
+
const RELOCATION_AUTHORITY_RETRY_DELAY_MS = 25;
|
|
196
|
+
|
|
197
|
+
const RELOCATION_MAX_SEND_ATTEMPTS = 120;
|
|
198
|
+
|
|
199
|
+
const RELOCATION_AUTHORITY_POLL_INTERVAL_MS = 10;
|
|
200
|
+
|
|
201
|
+
const RELOCATION_RESEND_DELAY_MS = 250;
|
|
202
|
+
|
|
203
|
+
const RELOCATION_ABORTABLE_OPERATION_TIMEOUT_MS = 24 * 60 * 60 * 1000;
|
|
204
|
+
|
|
205
|
+
const RELOCATION_OPERATION_TIMEOUT_MS = 30_000;
|
|
174
206
|
|
|
175
207
|
export class ZLinkRelocationStateIncompatibleError extends Error {
|
|
176
208
|
constructor(message: string) {
|
|
@@ -189,6 +221,7 @@ interface ZLinkHostRelocationOptions {
|
|
|
189
221
|
readonly providerResolver?: ZLinkProviderResolver;
|
|
190
222
|
readonly locationStore: () => ZLinkLocationStore | undefined;
|
|
191
223
|
readonly currentOwner: () => ZLinkLocationOwnerToken | undefined;
|
|
224
|
+
readonly targetAdmissionSealed?: () => boolean;
|
|
192
225
|
readonly liveDescriptors: (
|
|
193
226
|
meshName: string,
|
|
194
227
|
signal?: AbortSignal
|
|
@@ -307,7 +340,7 @@ interface SourceActorJoinProfile {
|
|
|
307
340
|
Parameters<ZLinkActorJoinRelocation['relocateActorJoin']>[0]['canonicalRecovery']
|
|
308
341
|
>;
|
|
309
342
|
readonly ready: Promise<void>;
|
|
310
|
-
readonly resolveReady: () => void;
|
|
343
|
+
readonly resolveReady: (failure?: ServiceRelocationPostCommitError) => void;
|
|
311
344
|
}
|
|
312
345
|
|
|
313
346
|
interface PendingRelocationReplyRelay {
|
|
@@ -366,8 +399,7 @@ export class ZLinkHostServiceRelocationRuntime implements ZLinkActorJoinRelocati
|
|
|
366
399
|
* Terminal restore failures (assembly/checksum/factory/restore error): the
|
|
367
400
|
* target already sent relocationFailed (command 53) once. An exact-identity
|
|
368
401
|
* Prepare resend replays the stored response rather than retrying the
|
|
369
|
-
* restore
|
|
370
|
-
* key supersedes the stale entry (spec 28 §3, §9).
|
|
402
|
+
* restore. A different exact identity never changes this entry (spec 28 §4.3).
|
|
371
403
|
*/
|
|
372
404
|
private readonly targetReadyFailures = new Map<
|
|
373
405
|
string,
|
|
@@ -424,9 +456,12 @@ export class ZLinkHostServiceRelocationRuntime implements ZLinkActorJoinRelocati
|
|
|
424
456
|
);
|
|
425
457
|
}
|
|
426
458
|
this.reserveExactRelocationId(input.relocationId);
|
|
427
|
-
let resolveReady!: () => void;
|
|
428
|
-
const ready = new Promise<void>((resolve) => {
|
|
429
|
-
resolveReady =
|
|
459
|
+
let resolveReady!: (failure?: ServiceRelocationPostCommitError) => void;
|
|
460
|
+
const ready = new Promise<void>((resolve, reject) => {
|
|
461
|
+
resolveReady = (failure) => {
|
|
462
|
+
if (failure === undefined) resolve();
|
|
463
|
+
else reject(failure.cause);
|
|
464
|
+
};
|
|
430
465
|
});
|
|
431
466
|
this.sourceActorJoinProfiles.set(input.relocationId, {
|
|
432
467
|
actor: input.actor,
|
|
@@ -438,8 +473,8 @@ export class ZLinkHostServiceRelocationRuntime implements ZLinkActorJoinRelocati
|
|
|
438
473
|
relocationContentType:
|
|
439
474
|
this.actorRegistration(input.state.meshName ?? input.meshName, input.state.actorType ?? '')
|
|
440
475
|
.relocation.kind === 'snapshot'
|
|
441
|
-
?
|
|
442
|
-
:
|
|
476
|
+
? SNAPSHOT_RELOCATION_CONTENT_TYPE
|
|
477
|
+
: RECREATE_RELOCATION_CONTENT_TYPE,
|
|
443
478
|
completionOperationId: input.completionOperationId,
|
|
444
479
|
canonicalRecovery: input.canonicalRecovery,
|
|
445
480
|
ready,
|
|
@@ -469,8 +504,13 @@ export class ZLinkHostServiceRelocationRuntime implements ZLinkActorJoinRelocati
|
|
|
469
504
|
);
|
|
470
505
|
resolveReady();
|
|
471
506
|
} catch (error) {
|
|
472
|
-
|
|
473
|
-
|
|
507
|
+
if (error instanceof ServiceRelocationPostCommitError) {
|
|
508
|
+
resolveReady(error);
|
|
509
|
+
this.completeActorJoinSourceCleanup(input.state.actorId);
|
|
510
|
+
} else {
|
|
511
|
+
this.sourceActorJoinProfiles.delete(input.relocationId);
|
|
512
|
+
throw error;
|
|
513
|
+
}
|
|
474
514
|
}
|
|
475
515
|
return {
|
|
476
516
|
actorRef: {
|
|
@@ -486,17 +526,10 @@ export class ZLinkHostServiceRelocationRuntime implements ZLinkActorJoinRelocati
|
|
|
486
526
|
async dispose(): Promise<void> {
|
|
487
527
|
this.disposed = true;
|
|
488
528
|
const errors: unknown[] = [];
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
await stage.finalize;
|
|
494
|
-
} else if (stage.phase === 'ready') {
|
|
495
|
-
await this.abortTargetStage(stage);
|
|
496
|
-
}
|
|
497
|
-
} catch (error) {
|
|
498
|
-
errors.push(error);
|
|
499
|
-
}
|
|
529
|
+
try {
|
|
530
|
+
await this.drainTargetAttempts();
|
|
531
|
+
} catch (error) {
|
|
532
|
+
errors.push(error);
|
|
500
533
|
}
|
|
501
534
|
this.targetStages.clear();
|
|
502
535
|
this.terminalTargets.clear();
|
|
@@ -534,24 +567,78 @@ export class ZLinkHostServiceRelocationRuntime implements ZLinkActorJoinRelocati
|
|
|
534
567
|
if (errors.length > 1) throw new AggregateError(errors, 'Relocation runtime stop failed.');
|
|
535
568
|
}
|
|
536
569
|
|
|
570
|
+
/** Host shutdown waits for the existing attempt terminal before releasing its lease. */
|
|
571
|
+
async drainTargetAttempts(): Promise<void> {
|
|
572
|
+
const results = await Promise.allSettled(
|
|
573
|
+
[...this.targetStages.entries()].map(([stagingId, stage]) => {
|
|
574
|
+
if (stage.fallback !== undefined) clearTimeout(stage.fallback);
|
|
575
|
+
return stage.lane.finally(() => {
|
|
576
|
+
if (stage.phase === 'failed') return stage.finalize;
|
|
577
|
+
if (this.targetStageSealed(stage)) {
|
|
578
|
+
const terminal = this.discardTargetStage(stagingId, stage);
|
|
579
|
+
stage.finalize = terminal;
|
|
580
|
+
return terminal;
|
|
581
|
+
}
|
|
582
|
+
return this.beginTargetFinalize(
|
|
583
|
+
stage.offer.reservation.prepared.plan.targetDescriptor.meshName,
|
|
584
|
+
stagingId,
|
|
585
|
+
stage
|
|
586
|
+
);
|
|
587
|
+
});
|
|
588
|
+
})
|
|
589
|
+
);
|
|
590
|
+
const errors = results.flatMap((result) =>
|
|
591
|
+
result.status === 'rejected' ? [result.reason as unknown] : []
|
|
592
|
+
);
|
|
593
|
+
if (errors.length === 1) throw errors[0];
|
|
594
|
+
if (errors.length > 1) throw new AggregateError(errors, 'Relocation target drain failed.');
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
/** Spec 28 §4.4: the target owner alone orders shutdown seal and verified cutover. */
|
|
598
|
+
private targetStageSealed(stage: LocalStage): boolean {
|
|
599
|
+
return (
|
|
600
|
+
!stage.cutoverReceived && (this.disposed || this.options.targetAdmissionSealed?.() === true)
|
|
601
|
+
);
|
|
602
|
+
}
|
|
603
|
+
|
|
537
604
|
completeActorJoinSourceCleanup(actorId: string): void {
|
|
538
605
|
for (const [relocationId, profile] of this.sourceActorJoinProfiles) {
|
|
539
606
|
if (profile.state.actorId !== actorId) continue;
|
|
540
607
|
this.sourceActorJoinProfiles.delete(relocationId);
|
|
541
608
|
this.terminalActorJoinSourceLeaves.remember(relocationId, actorId);
|
|
542
|
-
void profile
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
609
|
+
void this.finalizeActorJoinSource(profile);
|
|
610
|
+
}
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
private async finalizeActorJoinSource(profile: SourceActorJoinProfile): Promise<void> {
|
|
614
|
+
const failures: unknown[] = [];
|
|
615
|
+
try {
|
|
616
|
+
await profile.ready;
|
|
617
|
+
} catch (error) {
|
|
618
|
+
failures.push(error);
|
|
619
|
+
}
|
|
620
|
+
try {
|
|
621
|
+
await this.options.actorTransfer.completeRelocationSourceLeave(
|
|
622
|
+
profile.actor,
|
|
623
|
+
profile.sourceSpotId
|
|
624
|
+
);
|
|
625
|
+
} catch (error) {
|
|
626
|
+
failures.push(error);
|
|
627
|
+
}
|
|
628
|
+
try {
|
|
629
|
+
await this.options
|
|
630
|
+
.actorManager()
|
|
631
|
+
?.completeRelocationSource(profile.state.actorId, profile.sourceActorRef);
|
|
632
|
+
} catch (error) {
|
|
633
|
+
failures.push(error);
|
|
634
|
+
}
|
|
635
|
+
if (failures.length > 0) {
|
|
636
|
+
console.error(
|
|
637
|
+
'[zlink.runtime.relocation.source_cleanup_failed]',
|
|
638
|
+
failures.length === 1
|
|
639
|
+
? failures[0]
|
|
640
|
+
: new AggregateError(failures, 'Actor source retirement failed.')
|
|
641
|
+
);
|
|
555
642
|
}
|
|
556
643
|
}
|
|
557
644
|
|
|
@@ -671,13 +758,19 @@ export class ZLinkHostServiceRelocationRuntime implements ZLinkActorJoinRelocati
|
|
|
671
758
|
ready: () => true,
|
|
672
759
|
relocate: (relocationSignal) => {
|
|
673
760
|
const run = unit.relocate(relocationSignal);
|
|
761
|
+
if (isStructuralGuardEnabled()) {
|
|
762
|
+
trackDiagnosticCompletion(run, `relocation ${unit.id}`);
|
|
763
|
+
}
|
|
674
764
|
started.push(run);
|
|
675
765
|
return run;
|
|
676
766
|
}
|
|
677
767
|
});
|
|
678
768
|
}
|
|
679
769
|
const operationSignal = signal ?? new AbortController().signal;
|
|
680
|
-
const deadlineMs =
|
|
770
|
+
const deadlineMs =
|
|
771
|
+
signal === undefined
|
|
772
|
+
? RELOCATION_OPERATION_TIMEOUT_MS
|
|
773
|
+
: RELOCATION_ABORTABLE_OPERATION_TIMEOUT_MS;
|
|
681
774
|
let failure: unknown;
|
|
682
775
|
try {
|
|
683
776
|
const result = await raceAbort(
|
|
@@ -798,47 +891,57 @@ export class ZLinkHostServiceRelocationRuntime implements ZLinkActorJoinRelocati
|
|
|
798
891
|
}
|
|
799
892
|
const operationKey = relocationStagingId(request);
|
|
800
893
|
const fingerprint = stringifyWire(request);
|
|
894
|
+
const readyFailure = this.targetReadyFailures.get(operationKey);
|
|
895
|
+
const readyPending = this.targetReadyResponses.get(operationKey);
|
|
896
|
+
let operation = this.targetPrepareOperations.get(operationKey);
|
|
897
|
+
const acceptedFingerprint =
|
|
898
|
+
readyFailure?.fingerprint ??
|
|
899
|
+
readyPending?.fingerprint ??
|
|
900
|
+
operation?.fingerprint ??
|
|
901
|
+
this.targetAssemblies.get(operationKey)?.fingerprint ??
|
|
902
|
+
this.targetStages.get(operationKey)?.offer.prepareFingerprint ??
|
|
903
|
+
this.terminalTargets.get(operationKey);
|
|
904
|
+
if (request.sourceNodeRid !== String(record.sourceNodeRid)) return true;
|
|
905
|
+
if (acceptedFingerprint !== undefined && acceptedFingerprint !== fingerprint) {
|
|
906
|
+
if (!samePrepareIdentity(acceptedFingerprint, request)) return true;
|
|
907
|
+
this.replyPrepare(
|
|
908
|
+
record,
|
|
909
|
+
relocationFailed(request, ServiceWireFrameworkErrorCode.relocationDataLost)
|
|
910
|
+
);
|
|
911
|
+
return true;
|
|
912
|
+
}
|
|
801
913
|
// A restore that failed outright is terminal: the source observes the
|
|
802
914
|
// same explicit relocationFailed on every identical Prepare resend
|
|
803
|
-
// rather than a silent stall.
|
|
804
|
-
// same RelocationId+attempt key supersedes the stale failure — the
|
|
805
|
-
// newer attempt wins (spec 28 §3).
|
|
806
|
-
const readyFailure = this.targetReadyFailures.get(operationKey);
|
|
915
|
+
// rather than a silent stall.
|
|
807
916
|
if (readyFailure !== undefined) {
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
return true;
|
|
811
|
-
}
|
|
812
|
-
this.targetReadyFailures.delete(operationKey);
|
|
917
|
+
this.replyPrepare(record, readyFailure.response);
|
|
918
|
+
return true;
|
|
813
919
|
}
|
|
814
920
|
// Spec 28: an exact-identity Restore resend against staging that
|
|
815
921
|
// already restored successfully reuses that staging — it re-submits
|
|
816
922
|
// READY rather than restarting the restore.
|
|
817
|
-
const readyPending = this.targetReadyResponses.get(operationKey);
|
|
818
923
|
if (readyPending !== undefined) {
|
|
819
|
-
if (readyPending.fingerprint !== fingerprint) {
|
|
820
|
-
throw new Error(`Relocation '${operationKey}' repeated Prepare with different bytes.`);
|
|
821
|
-
}
|
|
822
924
|
this.submitTargetReady(meshName, operationKey, record, readyPending.response);
|
|
823
925
|
return true;
|
|
824
926
|
}
|
|
825
|
-
let operation = this.targetPrepareOperations.get(operationKey);
|
|
826
|
-
if (operation !== undefined && operation.fingerprint !== fingerprint) {
|
|
827
|
-
throw new Error(`Relocation '${operationKey}' repeated Prepare with different bytes.`);
|
|
828
|
-
}
|
|
829
927
|
if (operation === undefined) {
|
|
830
928
|
// The prepare turn must not block the ordered dispatch lane: the
|
|
831
929
|
// payload chunks that complete this operation arrive as later records
|
|
832
930
|
// on the same connection. Register the assembly synchronously, then
|
|
833
931
|
// finish the restore and the Ready reply asynchronously.
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
932
|
+
let promise: Promise<ServiceMaintenanceRelocationReady>;
|
|
933
|
+
try {
|
|
934
|
+
this.registerTargetAssembly(operationKey, request, String(record.sourceNodeRid));
|
|
935
|
+
promise = this.handlePrepareControl(
|
|
936
|
+
meshName,
|
|
937
|
+
operationKey,
|
|
938
|
+
request,
|
|
939
|
+
record.sourceNodeRid,
|
|
940
|
+
signal
|
|
941
|
+
);
|
|
942
|
+
} catch (error) {
|
|
943
|
+
promise = Promise.reject(error);
|
|
944
|
+
}
|
|
842
945
|
operation = { fingerprint, promise };
|
|
843
946
|
this.targetPrepareOperations.set(operationKey, operation);
|
|
844
947
|
void promise
|
|
@@ -872,10 +975,7 @@ export class ZLinkHostServiceRelocationRuntime implements ZLinkActorJoinRelocati
|
|
|
872
975
|
// restore or staging): this is terminal. Send relocationFailed
|
|
873
976
|
// (command 53) once and remember it so an identical Prepare resend
|
|
874
977
|
// replays the same response instead of retrying the restore.
|
|
875
|
-
const failed = relocationFailed(
|
|
876
|
-
request,
|
|
877
|
-
relocationFailedFailureCode(error, request.object.kind)
|
|
878
|
-
);
|
|
978
|
+
const failed = relocationFailed(request, relocationFailedFailureCode(error));
|
|
879
979
|
this.targetReadyFailures.set(operationKey, {
|
|
880
980
|
fingerprint: stringifyWire(request),
|
|
881
981
|
response: failed
|
|
@@ -969,7 +1069,7 @@ export class ZLinkHostServiceRelocationRuntime implements ZLinkActorJoinRelocati
|
|
|
969
1069
|
String(sourceNodeRid) !== pending.authenticatedSourceNodeRid ||
|
|
970
1070
|
request.senderRole !== 'source' ||
|
|
971
1071
|
!sameCoordinator(request.coordinator, pending.prepare.coordinator) ||
|
|
972
|
-
|
|
1072
|
+
!sameRelocationObject(request.object, pending.prepare.object)
|
|
973
1073
|
) {
|
|
974
1074
|
// Spec 28 §4.3 — a chunk with a different exact identity is never
|
|
975
1075
|
// attached to an in-progress assembly; it is discarded.
|
|
@@ -993,14 +1093,6 @@ export class ZLinkHostServiceRelocationRuntime implements ZLinkActorJoinRelocati
|
|
|
993
1093
|
): TargetPayloadAssembly {
|
|
994
1094
|
const existing = this.targetAssemblies.get(operationKey);
|
|
995
1095
|
if (existing !== undefined) {
|
|
996
|
-
if (existing.fingerprint !== stringifyWire(request)) {
|
|
997
|
-
// Same exact identity with a different declared length or checksum is
|
|
998
|
-
// an explicit conflict failure; the existing assembly is neither
|
|
999
|
-
// reused nor overwritten (spec 28 §4.3).
|
|
1000
|
-
throw existing.assembly.fail(
|
|
1001
|
-
`Relocation '${operationKey}' repeated Prepare with a conflicting manifest.`
|
|
1002
|
-
);
|
|
1003
|
-
}
|
|
1004
1096
|
return existing;
|
|
1005
1097
|
}
|
|
1006
1098
|
const pending: TargetPayloadAssembly = {
|
|
@@ -1015,15 +1107,10 @@ export class ZLinkHostServiceRelocationRuntime implements ZLinkActorJoinRelocati
|
|
|
1015
1107
|
};
|
|
1016
1108
|
this.targetAssemblies.set(operationKey, pending);
|
|
1017
1109
|
if (this.relocationIntegrityFaultGate()?.consumeIdentityConflict() === true) {
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
{
|
|
1023
|
-
...request,
|
|
1024
|
-
payloadChecksumCrc32c: request.payloadChecksumCrc32c ^ 1
|
|
1025
|
-
},
|
|
1026
|
-
authenticatedSourceNodeRid
|
|
1110
|
+
throw new ServiceRelocationDataLostError(
|
|
1111
|
+
pending.assembly.fail(
|
|
1112
|
+
`Relocation '${operationKey}' repeated Prepare with a conflicting manifest.`
|
|
1113
|
+
).message
|
|
1027
1114
|
);
|
|
1028
1115
|
}
|
|
1029
1116
|
return pending;
|
|
@@ -1201,7 +1288,7 @@ export class ZLinkHostServiceRelocationRuntime implements ZLinkActorJoinRelocati
|
|
|
1201
1288
|
return;
|
|
1202
1289
|
}
|
|
1203
1290
|
if (this.pendingSessionRelocations.get(key) === pending) {
|
|
1204
|
-
pending.retryTimer = setTimeout(() => void send(),
|
|
1291
|
+
pending.retryTimer = setTimeout(() => void send(), RELOCATION_RESEND_DELAY_MS);
|
|
1205
1292
|
}
|
|
1206
1293
|
} catch (error) {
|
|
1207
1294
|
pending.reject(
|
|
@@ -1420,7 +1507,7 @@ export class ZLinkHostServiceRelocationRuntime implements ZLinkActorJoinRelocati
|
|
|
1420
1507
|
targetApplicationVersion: bigint | undefined,
|
|
1421
1508
|
signal?: AbortSignal
|
|
1422
1509
|
): Promise<void> {
|
|
1423
|
-
await activation.serial.
|
|
1510
|
+
await activation.serial.executeControlLifecycleOperation(() =>
|
|
1424
1511
|
this.relocateSpotAggregateCore(
|
|
1425
1512
|
meshName,
|
|
1426
1513
|
activation,
|
|
@@ -1537,47 +1624,72 @@ export class ZLinkHostServiceRelocationRuntime implements ZLinkActorJoinRelocati
|
|
|
1537
1624
|
captureApplicationState: (captureSignal) =>
|
|
1538
1625
|
this.captureApplication(spotRegistration.relocation, activation.spot, captureSignal),
|
|
1539
1626
|
commitSeal: async () => {
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1627
|
+
const failures: unknown[] = [];
|
|
1628
|
+
try {
|
|
1629
|
+
if (!spotSealCommitted) {
|
|
1630
|
+
if (spotCapture === undefined || !(await activation.commitRelocation(spotCapture))) {
|
|
1631
|
+
throw new Error(`Spot '${String(activation.spotId)}' relocation seal became stale.`);
|
|
1632
|
+
}
|
|
1633
|
+
spotSealCommitted = true;
|
|
1543
1634
|
}
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1635
|
+
if (spotMessageFollowSeal !== undefined) {
|
|
1636
|
+
await this.commitSpotMessageFollow(
|
|
1637
|
+
meshName,
|
|
1638
|
+
spotMessageFollowSeal,
|
|
1639
|
+
spotKey,
|
|
1640
|
+
activation,
|
|
1641
|
+
target
|
|
1642
|
+
);
|
|
1643
|
+
}
|
|
1644
|
+
} catch (error) {
|
|
1645
|
+
failures.push(error);
|
|
1554
1646
|
}
|
|
1555
1647
|
for (const session of sessions) {
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1648
|
+
try {
|
|
1649
|
+
const committedAuthority = await requireAuthority(
|
|
1650
|
+
this.requireLocationStore(),
|
|
1651
|
+
encodeAuthorityKey('actor', session.state.actorId)
|
|
1652
|
+
);
|
|
1653
|
+
const targetActorRef = {
|
|
1654
|
+
actorId: session.state.actorId,
|
|
1655
|
+
objectGeneration: actorAuthorities.get(session.state.actorId)!.objectGeneration,
|
|
1656
|
+
meshName,
|
|
1657
|
+
nodeRid: target.rid
|
|
1658
|
+
};
|
|
1659
|
+
await session.prepared.commit(
|
|
1660
|
+
{
|
|
1661
|
+
routerChannelId: meshName,
|
|
1662
|
+
targetNodeRid: target.rid,
|
|
1663
|
+
spotId: activation.spotId,
|
|
1664
|
+
spotKind: kind === 'user_spot' ? ZLinkSpotKind.User : ZLinkSpotKind.Instance,
|
|
1665
|
+
authorityOwnerGeneration: committedAuthority.authorityOwnerGeneration
|
|
1666
|
+
} as never,
|
|
1667
|
+
targetActorRef,
|
|
1668
|
+
committedActorOwnerFence(session.state.actorId, targetActorRef, committedAuthority)
|
|
1669
|
+
);
|
|
1670
|
+
} catch (error) {
|
|
1671
|
+
failures.push(error);
|
|
1672
|
+
}
|
|
1673
|
+
try {
|
|
1674
|
+
activation.commitActorDeparture(session.state.actorId);
|
|
1675
|
+
} catch (error) {
|
|
1676
|
+
failures.push(error);
|
|
1677
|
+
}
|
|
1678
|
+
try {
|
|
1679
|
+
await this.requireActorManager().completeRelocationSource(session.state.actorId);
|
|
1680
|
+
} catch (error) {
|
|
1681
|
+
failures.push(error);
|
|
1682
|
+
}
|
|
1579
1683
|
}
|
|
1580
|
-
|
|
1684
|
+
try {
|
|
1685
|
+
await this.requireSpotManager().completeRelocationSource(activation);
|
|
1686
|
+
} catch (error) {
|
|
1687
|
+
failures.push(error);
|
|
1688
|
+
}
|
|
1689
|
+
if (failures.length > 0)
|
|
1690
|
+
throw failures.length === 1
|
|
1691
|
+
? failures[0]
|
|
1692
|
+
: new AggregateError(failures, 'Spot source retirement failed.');
|
|
1581
1693
|
},
|
|
1582
1694
|
abortSeal: async () => {
|
|
1583
1695
|
const failures: unknown[] = [];
|
|
@@ -1723,7 +1835,9 @@ export class ZLinkHostServiceRelocationRuntime implements ZLinkActorJoinRelocati
|
|
|
1723
1835
|
/** Target's advertised relocation state chunk cap (Actor Join only; spec 15 §4.2). */
|
|
1724
1836
|
advertisedReceiveChunkLimitBytes?: number
|
|
1725
1837
|
): Promise<void> {
|
|
1726
|
-
|
|
1838
|
+
if (isRelocationDebugEnabled()) {
|
|
1839
|
+
relocationDebug('standalone_actor.begin', { actorId: state.actorId });
|
|
1840
|
+
}
|
|
1727
1841
|
const authority = await requireAuthority(
|
|
1728
1842
|
this.requireLocationStore(),
|
|
1729
1843
|
encodeAuthorityKey('actor', state.actorId),
|
|
@@ -1780,12 +1894,16 @@ export class ZLinkHostServiceRelocationRuntime implements ZLinkActorJoinRelocati
|
|
|
1780
1894
|
};
|
|
1781
1895
|
let outcome = 'completed';
|
|
1782
1896
|
try {
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
|
|
1786
|
-
|
|
1897
|
+
if (isRelocationDebugEnabled()) {
|
|
1898
|
+
relocationDebug('standalone_actor.wait_budget', {
|
|
1899
|
+
actorId: state.actorId,
|
|
1900
|
+
targetRid: String(target.rid)
|
|
1901
|
+
});
|
|
1902
|
+
}
|
|
1787
1903
|
await this.waitForRelocationBudgetHeadroom(String(target.rid), signal);
|
|
1788
|
-
|
|
1904
|
+
if (isRelocationDebugEnabled()) {
|
|
1905
|
+
relocationDebug('standalone_actor.capture_begin', { actorId: state.actorId });
|
|
1906
|
+
}
|
|
1789
1907
|
const captured = await new ServiceRelocationObjectCaptureOwner().captureStandaloneActor(
|
|
1790
1908
|
aggregateId,
|
|
1791
1909
|
1n,
|
|
@@ -1793,7 +1911,9 @@ export class ZLinkHostServiceRelocationRuntime implements ZLinkActorJoinRelocati
|
|
|
1793
1911
|
membership,
|
|
1794
1912
|
signal
|
|
1795
1913
|
);
|
|
1796
|
-
|
|
1914
|
+
if (isRelocationDebugEnabled()) {
|
|
1915
|
+
relocationDebug('standalone_actor.capture_complete', { actorId: state.actorId });
|
|
1916
|
+
}
|
|
1797
1917
|
await this.runCoordinator(
|
|
1798
1918
|
meshName,
|
|
1799
1919
|
target,
|
|
@@ -1828,7 +1948,7 @@ export class ZLinkHostServiceRelocationRuntime implements ZLinkActorJoinRelocati
|
|
|
1828
1948
|
targetApplicationVersion: bigint | undefined,
|
|
1829
1949
|
signal?: AbortSignal
|
|
1830
1950
|
): Promise<void> {
|
|
1831
|
-
await activation.serial.
|
|
1951
|
+
await activation.serial.executeControlLifecycleOperation(() =>
|
|
1832
1952
|
this.relocatePerActorSpotShellCore(
|
|
1833
1953
|
meshName,
|
|
1834
1954
|
activation,
|
|
@@ -2026,32 +2146,45 @@ export class ZLinkHostServiceRelocationRuntime implements ZLinkActorJoinRelocati
|
|
|
2026
2146
|
meshName === undefined
|
|
2027
2147
|
)
|
|
2028
2148
|
return;
|
|
2029
|
-
const
|
|
2030
|
-
|
|
2031
|
-
|
|
2032
|
-
|
|
2033
|
-
|
|
2034
|
-
|
|
2035
|
-
|
|
2036
|
-
|
|
2037
|
-
|
|
2038
|
-
|
|
2039
|
-
|
|
2040
|
-
|
|
2041
|
-
|
|
2042
|
-
|
|
2043
|
-
|
|
2044
|
-
|
|
2045
|
-
|
|
2046
|
-
|
|
2047
|
-
|
|
2048
|
-
|
|
2049
|
-
|
|
2050
|
-
|
|
2051
|
-
|
|
2149
|
+
const failures: unknown[] = [];
|
|
2150
|
+
try {
|
|
2151
|
+
const membershipSpotId =
|
|
2152
|
+
targetMembership?.spotId ?? ((target.entrySpotId ?? String(target.rid)) as RoutingId);
|
|
2153
|
+
const committedAuthority = await requireAuthority(
|
|
2154
|
+
this.requireLocationStore(),
|
|
2155
|
+
encodeAuthorityKey('actor', state.actorId)
|
|
2156
|
+
);
|
|
2157
|
+
const targetActorRef = {
|
|
2158
|
+
actorId: state.actorId,
|
|
2159
|
+
objectGeneration: authority.objectGeneration,
|
|
2160
|
+
meshName,
|
|
2161
|
+
nodeRid: target.rid
|
|
2162
|
+
};
|
|
2163
|
+
await ownSession.prepared.commit(
|
|
2164
|
+
{
|
|
2165
|
+
routerChannelId: meshName,
|
|
2166
|
+
targetNodeRid: target.rid,
|
|
2167
|
+
spotId: membershipSpotId,
|
|
2168
|
+
spotKind: targetMembership?.spotKind ?? ZLinkSpotKind.Entry,
|
|
2169
|
+
authorityOwnerGeneration: committedAuthority.authorityOwnerGeneration
|
|
2170
|
+
} as never,
|
|
2171
|
+
targetActorRef,
|
|
2172
|
+
committedActorOwnerFence(state.actorId, targetActorRef, committedAuthority)
|
|
2173
|
+
);
|
|
2174
|
+
} catch (error) {
|
|
2175
|
+
failures.push(error);
|
|
2176
|
+
}
|
|
2052
2177
|
if (!retainSourceForActorJoin) {
|
|
2053
|
-
|
|
2178
|
+
try {
|
|
2179
|
+
await this.requireActorManager().completeRelocationSource(state.actorId);
|
|
2180
|
+
} catch (error) {
|
|
2181
|
+
failures.push(error);
|
|
2182
|
+
}
|
|
2054
2183
|
}
|
|
2184
|
+
if (failures.length > 0)
|
|
2185
|
+
throw failures.length === 1
|
|
2186
|
+
? failures[0]
|
|
2187
|
+
: new AggregateError(failures, 'Actor source retirement failed.');
|
|
2055
2188
|
},
|
|
2056
2189
|
abortSeal: async () => {
|
|
2057
2190
|
if (standalone && ownSession !== undefined) await ownSession.prepared.rollback();
|
|
@@ -2098,13 +2231,17 @@ export class ZLinkHostServiceRelocationRuntime implements ZLinkActorJoinRelocati
|
|
|
2098
2231
|
/** Target's advertised relocation state chunk cap (Actor Join only; spec 15 §4.2). */
|
|
2099
2232
|
advertisedReceiveChunkLimitBytes?: number
|
|
2100
2233
|
): Promise<void> {
|
|
2101
|
-
|
|
2102
|
-
|
|
2103
|
-
|
|
2104
|
-
|
|
2234
|
+
if (isRelocationDebugEnabled()) {
|
|
2235
|
+
relocationDebug('coordinator.begin', {
|
|
2236
|
+
aggregateId: captured.envelope.aggregateId,
|
|
2237
|
+
targetRid: String(target.rid)
|
|
2238
|
+
});
|
|
2239
|
+
}
|
|
2105
2240
|
const localStatus = this.requireMeshNode(meshName).status();
|
|
2106
2241
|
const controlDeadlineAtMs =
|
|
2107
|
-
signal === undefined
|
|
2242
|
+
signal === undefined
|
|
2243
|
+
? performance.now() + RELOCATION_OPERATION_TIMEOUT_MS
|
|
2244
|
+
: Number.MAX_SAFE_INTEGER;
|
|
2108
2245
|
const coordinator = {
|
|
2109
2246
|
ownerId: primary.ownerId,
|
|
2110
2247
|
leaseGeneration: primary.ownerLeaseGeneration,
|
|
@@ -2169,7 +2306,6 @@ export class ZLinkHostServiceRelocationRuntime implements ZLinkActorJoinRelocati
|
|
|
2169
2306
|
signal?.aborted === true || performance.now() >= controlDeadlineAtMs;
|
|
2170
2307
|
let readyReceived = false;
|
|
2171
2308
|
let settlement: 'target' | 'source' | 'lost' | undefined;
|
|
2172
|
-
let sourceCommitted = false;
|
|
2173
2309
|
try {
|
|
2174
2310
|
const prepare = {
|
|
2175
2311
|
kind: 'prepare',
|
|
@@ -2199,17 +2335,25 @@ export class ZLinkHostServiceRelocationRuntime implements ZLinkActorJoinRelocati
|
|
|
2199
2335
|
encodePrepareSideband(captured.envelope)
|
|
2200
2336
|
);
|
|
2201
2337
|
try {
|
|
2202
|
-
|
|
2203
|
-
|
|
2204
|
-
|
|
2338
|
+
if (isRelocationDebugEnabled()) {
|
|
2339
|
+
relocationDebug('coordinator.state_transfer_begin', {
|
|
2340
|
+
aggregateId: captured.envelope.aggregateId
|
|
2341
|
+
});
|
|
2342
|
+
}
|
|
2205
2343
|
await this.sendRelocationStateChunks(meshName, target, prepare, encoded, plan, signal);
|
|
2206
2344
|
} catch (chunkError) {
|
|
2207
2345
|
readyOperation.catch(() => undefined);
|
|
2208
2346
|
throw chunkError;
|
|
2209
2347
|
}
|
|
2210
|
-
|
|
2348
|
+
if (isRelocationDebugEnabled()) {
|
|
2349
|
+
relocationDebug('coordinator.await_ready', { aggregateId: captured.envelope.aggregateId });
|
|
2350
|
+
}
|
|
2211
2351
|
const ready = await readyOperation;
|
|
2212
|
-
|
|
2352
|
+
if (isRelocationDebugEnabled()) {
|
|
2353
|
+
relocationDebug('coordinator.ready_received', {
|
|
2354
|
+
aggregateId: captured.envelope.aggregateId
|
|
2355
|
+
});
|
|
2356
|
+
}
|
|
2213
2357
|
validateControlResponse(prepare, ready);
|
|
2214
2358
|
// Ready arms the target's cutover-wait fallback. From this point
|
|
2215
2359
|
// forward the source can no longer reopen dispatch without risking two
|
|
@@ -2298,10 +2442,12 @@ export class ZLinkHostServiceRelocationRuntime implements ZLinkActorJoinRelocati
|
|
|
2298
2442
|
} finally {
|
|
2299
2443
|
this.closeSourceCutoverWindow(relayAuthorityId, window);
|
|
2300
2444
|
}
|
|
2301
|
-
|
|
2302
|
-
|
|
2303
|
-
|
|
2304
|
-
|
|
2445
|
+
if (isRelocationDebugEnabled()) {
|
|
2446
|
+
relocationDebug('coordinator.authority_settled', {
|
|
2447
|
+
aggregateId: captured.envelope.aggregateId,
|
|
2448
|
+
settlement
|
|
2449
|
+
});
|
|
2450
|
+
}
|
|
2305
2451
|
if (settlement === 'source') {
|
|
2306
2452
|
// Preserve won: the captured queue, timers and held records return to
|
|
2307
2453
|
// the source queue in their accepted order, and dispatch reopens.
|
|
@@ -2323,17 +2469,11 @@ export class ZLinkHostServiceRelocationRuntime implements ZLinkActorJoinRelocati
|
|
|
2323
2469
|
}
|
|
2324
2470
|
for (const session of sessions) session.prepared.setReplayResults([]);
|
|
2325
2471
|
await captured.commitSource();
|
|
2326
|
-
sourceCommitted = true;
|
|
2327
2472
|
await this.options.reconcileStatefulAuthorityRoutes?.(signal);
|
|
2328
2473
|
} catch (error) {
|
|
2329
2474
|
if (settlement !== 'target') throw error;
|
|
2330
2475
|
// Target commit is confirmed; later source cleanup failures cannot move
|
|
2331
|
-
// the authority back (spec 28 §
|
|
2332
|
-
if (!sourceCommitted) {
|
|
2333
|
-
for (const session of sessions) session.prepared.setReplayResults([]);
|
|
2334
|
-
await captured.commitSource().catch(() => undefined);
|
|
2335
|
-
}
|
|
2336
|
-
await this.options.reconcileStatefulAuthorityRoutes?.().catch(() => undefined);
|
|
2476
|
+
// the authority back (spec 28 §10).
|
|
2337
2477
|
const authority = await requireAuthority(
|
|
2338
2478
|
this.requireLocationStore(),
|
|
2339
2479
|
{ value: primaryKey(captured.envelope) } as ZLinkAuthorityKey,
|
|
@@ -2476,8 +2616,8 @@ export class ZLinkHostServiceRelocationRuntime implements ZLinkActorJoinRelocati
|
|
|
2476
2616
|
// S1→S4 route convergence: the span the source must keep its Message
|
|
2477
2617
|
// Follow route (spec 30 §7.1).
|
|
2478
2618
|
this.options.metrics?.duration(
|
|
2479
|
-
|
|
2480
|
-
Math.max(0, performance.now() - submittedAt) /
|
|
2619
|
+
METRIC_NAMES.RelocationRouteConvergence,
|
|
2620
|
+
Math.max(0, performance.now() - submittedAt) / MILLISECONDS_PER_SECOND,
|
|
2481
2621
|
{ mesh_name: meshName }
|
|
2482
2622
|
);
|
|
2483
2623
|
this.releaseSourceCutoverWindow(relocationKey, window);
|
|
@@ -2516,8 +2656,7 @@ export class ZLinkHostServiceRelocationRuntime implements ZLinkActorJoinRelocati
|
|
|
2516
2656
|
(value) =>
|
|
2517
2657
|
value.routingId !== null && String(value.routingId) === String(window.targetNodeRid)
|
|
2518
2658
|
);
|
|
2519
|
-
|
|
2520
|
-
if (peer !== undefined && peer.state !== 3) {
|
|
2659
|
+
if (peer !== undefined && peer.state !== MeshPeerRuntimeState.Serving) {
|
|
2521
2660
|
window.resendPending = true;
|
|
2522
2661
|
return;
|
|
2523
2662
|
}
|
|
@@ -2561,13 +2700,22 @@ export class ZLinkHostServiceRelocationRuntime implements ZLinkActorJoinRelocati
|
|
|
2561
2700
|
if (this.disposed) throw new Error('Relocation runtime stopped.');
|
|
2562
2701
|
await this.resendSourceCutover(window);
|
|
2563
2702
|
const observed = await this.readSourceSettlement(envelope, primary, target).catch(
|
|
2564
|
-
() =>
|
|
2703
|
+
(error: unknown) => {
|
|
2704
|
+
if (!isIndeterminateLocationStoreFailure(error)) throw error;
|
|
2705
|
+
return undefined;
|
|
2706
|
+
}
|
|
2565
2707
|
);
|
|
2566
2708
|
if (observed?.kind === 'target') return 'target';
|
|
2567
2709
|
if (observed?.kind === 'other') return 'lost';
|
|
2568
2710
|
if (restoreDeadlineReached() && observed?.kind === 'source') {
|
|
2569
2711
|
// An unreadable lease is an uncertain result, not an expiry.
|
|
2570
|
-
if (
|
|
2712
|
+
if (
|
|
2713
|
+
await this.exactSourceLeaseExpired(owner).catch((error: unknown) => {
|
|
2714
|
+
if (!isIndeterminateLocationStoreFailure(error)) throw error;
|
|
2715
|
+
return false;
|
|
2716
|
+
})
|
|
2717
|
+
)
|
|
2718
|
+
return 'lost';
|
|
2571
2719
|
const publication = this.codec.read(observed.current.payload);
|
|
2572
2720
|
const preserved = await store
|
|
2573
2721
|
.compareExchangeAuthority(
|
|
@@ -2582,11 +2730,16 @@ export class ZLinkHostServiceRelocationRuntime implements ZLinkActorJoinRelocati
|
|
|
2582
2730
|
: this.codec.clear(observed.current.payload, publication.reference)
|
|
2583
2731
|
}
|
|
2584
2732
|
)
|
|
2585
|
-
.catch(() =>
|
|
2733
|
+
.catch((error: unknown) => {
|
|
2734
|
+
if (!isIndeterminateLocationStoreFailure(error)) throw error;
|
|
2735
|
+
return undefined;
|
|
2736
|
+
});
|
|
2586
2737
|
if (preserved?.kind === 'stored') return 'source';
|
|
2587
2738
|
}
|
|
2588
2739
|
// The caller awaits this settlement, so the retry timer keeps the loop alive.
|
|
2589
|
-
await new Promise<void>((resolve) =>
|
|
2740
|
+
await new Promise<void>((resolve) =>
|
|
2741
|
+
setTimeout(resolve, RELOCATION_AUTHORITY_POLL_INTERVAL_MS)
|
|
2742
|
+
);
|
|
2590
2743
|
}
|
|
2591
2744
|
}
|
|
2592
2745
|
|
|
@@ -2667,14 +2820,9 @@ export class ZLinkHostServiceRelocationRuntime implements ZLinkActorJoinRelocati
|
|
|
2667
2820
|
meshName: string,
|
|
2668
2821
|
stagingId: string,
|
|
2669
2822
|
request: ServiceMaintenanceRelocationPrepare,
|
|
2670
|
-
sourceNodeRid: RoutingId
|
|
2823
|
+
sourceNodeRid: RoutingId,
|
|
2671
2824
|
signal?: AbortSignal
|
|
2672
2825
|
): Promise<ServiceMaintenanceRelocationReady> {
|
|
2673
|
-
if (sourceNodeRid === null || String(sourceNodeRid) !== request.sourceNodeRid) {
|
|
2674
|
-
throw new Error(
|
|
2675
|
-
'Relocation prepare source node fence does not match the authenticated peer.'
|
|
2676
|
-
);
|
|
2677
|
-
}
|
|
2678
2826
|
const targetStatus = this.requireMeshNode(meshName).status();
|
|
2679
2827
|
const targetOwner = this.options.currentOwner();
|
|
2680
2828
|
const targetDescriptor = this.options.localDescriptor?.(meshName);
|
|
@@ -2692,24 +2840,15 @@ export class ZLinkHostServiceRelocationRuntime implements ZLinkActorJoinRelocati
|
|
|
2692
2840
|
const fingerprint = stringifyWire(request);
|
|
2693
2841
|
const existing = this.targetStages.get(stagingId);
|
|
2694
2842
|
if (existing !== undefined) {
|
|
2695
|
-
if (
|
|
2696
|
-
existing.offer.authenticatedSourceNodeRid !== String(sourceNodeRid) ||
|
|
2697
|
-
existing.offer.prepareFingerprint !== fingerprint
|
|
2698
|
-
) {
|
|
2699
|
-
throw new Error('Relocation prepare retry source node changed.');
|
|
2700
|
-
}
|
|
2701
2843
|
return relocationReady(request);
|
|
2702
2844
|
}
|
|
2703
2845
|
const terminal = this.terminalTargets.get(stagingId);
|
|
2704
2846
|
if (terminal !== undefined) {
|
|
2705
|
-
if (terminal !== fingerprint) {
|
|
2706
|
-
throw new Error(`Relocation '${stagingId}' repeated Prepare with different bytes.`);
|
|
2707
|
-
}
|
|
2708
2847
|
this.terminalTargets.touch(stagingId);
|
|
2709
2848
|
return relocationReady(request);
|
|
2710
2849
|
}
|
|
2711
2850
|
const pendingAssembly = this.targetAssemblies.get(stagingId);
|
|
2712
|
-
if (pendingAssembly === undefined
|
|
2851
|
+
if (pendingAssembly === undefined) {
|
|
2713
2852
|
throw new Error(`Relocation '${stagingId}' has no matching payload assembly.`);
|
|
2714
2853
|
}
|
|
2715
2854
|
// The directly transferred payload replaces the shared durable root: the
|
|
@@ -2798,7 +2937,7 @@ export class ZLinkHostServiceRelocationRuntime implements ZLinkActorJoinRelocati
|
|
|
2798
2937
|
stage.fallback = setTimeout(() => {
|
|
2799
2938
|
if (stage.finalize !== undefined) return;
|
|
2800
2939
|
console.warn('[zlink.runtime.relocation.cutover_timeout]', stagingId);
|
|
2801
|
-
this.options.metrics?.count(
|
|
2940
|
+
this.options.metrics?.count(METRIC_NAMES.RelocationCutoverTimeout, 1, {
|
|
2802
2941
|
mesh_name: meshName
|
|
2803
2942
|
});
|
|
2804
2943
|
void this.beginTargetFinalize(meshName, stagingId, stage).catch((error) =>
|
|
@@ -2820,7 +2959,7 @@ export class ZLinkHostServiceRelocationRuntime implements ZLinkActorJoinRelocati
|
|
|
2820
2959
|
const stagingId = relocationStagingId(request);
|
|
2821
2960
|
const stage = this.targetStages.get(stagingId);
|
|
2822
2961
|
if (stage === undefined) {
|
|
2823
|
-
if (this.terminalTargets.get(stagingId) !== undefined) {
|
|
2962
|
+
if (this.disposed || this.terminalTargets.get(stagingId) !== undefined) {
|
|
2824
2963
|
if (request.kind === 'cutover') {
|
|
2825
2964
|
console.warn('[zlink.runtime.relocation.late_cutover]', stagingId);
|
|
2826
2965
|
}
|
|
@@ -2829,21 +2968,24 @@ export class ZLinkHostServiceRelocationRuntime implements ZLinkActorJoinRelocati
|
|
|
2829
2968
|
throw new Error(`Relocation staging '${stagingId}' is missing.`);
|
|
2830
2969
|
}
|
|
2831
2970
|
validateTargetOneWayControl(stage, request, sourceNodeRid);
|
|
2832
|
-
|
|
2833
|
-
|
|
2834
|
-
|
|
2835
|
-
if (
|
|
2836
|
-
|
|
2971
|
+
stage.lane = stage.lane.then(() => {
|
|
2972
|
+
// A verified cutover closes the boundary batch. A later record or cutover
|
|
2973
|
+
// is a duplicate retransmission and never changes the staged batch.
|
|
2974
|
+
if (stage.cutoverReceived || (stage.phase !== 'ready' && stage.phase !== 'finalizing')) {
|
|
2975
|
+
if (request.kind === 'cutover') {
|
|
2976
|
+
console.warn('[zlink.runtime.relocation.late_cutover]', stagingId);
|
|
2977
|
+
}
|
|
2978
|
+
return;
|
|
2837
2979
|
}
|
|
2838
|
-
|
|
2839
|
-
|
|
2840
|
-
|
|
2841
|
-
|
|
2842
|
-
|
|
2843
|
-
|
|
2844
|
-
}
|
|
2845
|
-
|
|
2846
|
-
|
|
2980
|
+
if (request.kind === 'data') {
|
|
2981
|
+
return this.stageBoundaryRelay(stage, request);
|
|
2982
|
+
}
|
|
2983
|
+
if (this.targetStageSealed(stage)) return;
|
|
2984
|
+
this.reconcileBoundaryRelay(stage, request, stagingId);
|
|
2985
|
+
stage.cutoverReceived = true;
|
|
2986
|
+
});
|
|
2987
|
+
await stage.lane;
|
|
2988
|
+
if (request.kind === 'data') return;
|
|
2847
2989
|
// A settlement started by the cutover wait Warning is still reading the
|
|
2848
2990
|
// Store; it submits the CAS on its next round now that cutover verified.
|
|
2849
2991
|
if (stage.finalize !== undefined) return;
|
|
@@ -2928,10 +3070,9 @@ export class ZLinkHostServiceRelocationRuntime implements ZLinkActorJoinRelocati
|
|
|
2928
3070
|
try {
|
|
2929
3071
|
authority = await this.commitTargetReservation(stage, stage.offer.reservation, signal);
|
|
2930
3072
|
if (authority === undefined) {
|
|
2931
|
-
//
|
|
2932
|
-
|
|
2933
|
-
|
|
2934
|
-
throw new Error(`Relocation '${stagingId}' target staging lost the authority settlement.`);
|
|
3073
|
+
// The seal owner may have ended staging while a Store read was pending.
|
|
3074
|
+
if ((stage as LocalStage).phase === 'failed') return;
|
|
3075
|
+
return this.discardTargetStage(stagingId, stage, signal);
|
|
2935
3076
|
}
|
|
2936
3077
|
authorityCommitted = true;
|
|
2937
3078
|
stage.releaseActivation();
|
|
@@ -2964,8 +3105,8 @@ export class ZLinkHostServiceRelocationRuntime implements ZLinkActorJoinRelocati
|
|
|
2964
3105
|
await stage.owner.openAdmission(stage.staging, signal);
|
|
2965
3106
|
// S2→S3: owner confirmation to application dispatch opening.
|
|
2966
3107
|
this.options.metrics?.duration(
|
|
2967
|
-
|
|
2968
|
-
Math.max(0, performance.now() - resumeStartedAt) /
|
|
3108
|
+
METRIC_NAMES.RelocationTargetResume,
|
|
3109
|
+
Math.max(0, performance.now() - resumeStartedAt) / MILLISECONDS_PER_SECOND,
|
|
2969
3110
|
{ mesh_name: meshName }
|
|
2970
3111
|
);
|
|
2971
3112
|
await this.publishSessionRoutes(stage.staging);
|
|
@@ -2980,14 +3121,15 @@ export class ZLinkHostServiceRelocationRuntime implements ZLinkActorJoinRelocati
|
|
|
2980
3121
|
this.targetStages.delete(stagingId);
|
|
2981
3122
|
this.targetAssemblies.delete(stagingId);
|
|
2982
3123
|
} catch (error) {
|
|
2983
|
-
stage.phase = 'failed';
|
|
2984
3124
|
this.terminalTargets.remember(stagingId, stage.offer.prepareFingerprint);
|
|
2985
3125
|
this.targetStages.delete(stagingId);
|
|
2986
3126
|
this.targetAssemblies.delete(stagingId);
|
|
2987
3127
|
if (!authorityCommitted) {
|
|
2988
|
-
|
|
3128
|
+
// abortTargetStage may already have assigned failed before throwing.
|
|
3129
|
+
if ((stage as LocalStage).phase !== 'failed') await this.abortTargetStage(stage);
|
|
2989
3130
|
throw error;
|
|
2990
3131
|
}
|
|
3132
|
+
stage.phase = 'failed';
|
|
2991
3133
|
if (authority !== undefined) {
|
|
2992
3134
|
throw new ServiceRelocationPostCommitError(authority, stage.staging, error);
|
|
2993
3135
|
}
|
|
@@ -3123,19 +3265,7 @@ export class ZLinkHostServiceRelocationRuntime implements ZLinkActorJoinRelocati
|
|
|
3123
3265
|
}
|
|
3124
3266
|
this.sourceActorJoinProfiles.delete(input.transferId);
|
|
3125
3267
|
this.terminalActorJoinSourceLeaves.remember(input.transferId, input.actorId);
|
|
3126
|
-
void profile
|
|
3127
|
-
.then(async () => {
|
|
3128
|
-
await this.options.actorTransfer.completeRelocationSourceLeave(
|
|
3129
|
-
profile.actor,
|
|
3130
|
-
profile.sourceSpotId
|
|
3131
|
-
);
|
|
3132
|
-
await this.options
|
|
3133
|
-
.actorManager()
|
|
3134
|
-
?.completeRelocationSource(input.actorId, profile.sourceActorRef);
|
|
3135
|
-
})
|
|
3136
|
-
.catch((error) => {
|
|
3137
|
-
console.error('[zlink.runtime.relocation.source_leave_failed]', error);
|
|
3138
|
-
});
|
|
3268
|
+
void this.finalizeActorJoinSource(profile);
|
|
3139
3269
|
return true;
|
|
3140
3270
|
}
|
|
3141
3271
|
|
|
@@ -3309,7 +3439,7 @@ export class ZLinkHostServiceRelocationRuntime implements ZLinkActorJoinRelocati
|
|
|
3309
3439
|
pending.resolve('sourceLeaseExpired');
|
|
3310
3440
|
return;
|
|
3311
3441
|
}
|
|
3312
|
-
if (++attempts >
|
|
3442
|
+
if (++attempts > RELOCATION_MAX_SEND_ATTEMPTS) {
|
|
3313
3443
|
pending.reject(new Error(`Relocation reply relay ACK '${key}' timed out.`));
|
|
3314
3444
|
return;
|
|
3315
3445
|
}
|
|
@@ -3319,7 +3449,7 @@ export class ZLinkHostServiceRelocationRuntime implements ZLinkActorJoinRelocati
|
|
|
3319
3449
|
encodeMaintenanceReplyRelay(request)
|
|
3320
3450
|
);
|
|
3321
3451
|
if (this.pendingReplyRelays.get(key) === pending) {
|
|
3322
|
-
pending.timer = setTimeout(() => void send(),
|
|
3452
|
+
pending.timer = setTimeout(() => void send(), RELOCATION_RESEND_DELAY_MS);
|
|
3323
3453
|
}
|
|
3324
3454
|
} catch (error) {
|
|
3325
3455
|
pending.reject(error);
|
|
@@ -3464,10 +3594,14 @@ export class ZLinkHostServiceRelocationRuntime implements ZLinkActorJoinRelocati
|
|
|
3464
3594
|
private async publishSessionRoutes(
|
|
3465
3595
|
staging: ServiceObjectRelocationStaging<LocalHidden>
|
|
3466
3596
|
): Promise<void> {
|
|
3467
|
-
for (const hidden of staging.hidden
|
|
3468
|
-
if (hidden.actor
|
|
3469
|
-
|
|
3470
|
-
|
|
3597
|
+
for (const [key, hidden] of staging.hidden) {
|
|
3598
|
+
if (hidden.actor === undefined) continue;
|
|
3599
|
+
// The Session seal travels with the relocation envelope, not the Actor.
|
|
3600
|
+
const carried = staging.envelope.participants.find((value) => value.key === key);
|
|
3601
|
+
await this.options.actorTransfer.publishRoutedActorOwnership(
|
|
3602
|
+
hidden.actor,
|
|
3603
|
+
carried === undefined ? undefined : decodeActorSession(carried.boundSessionState)
|
|
3604
|
+
);
|
|
3471
3605
|
}
|
|
3472
3606
|
}
|
|
3473
3607
|
|
|
@@ -3476,7 +3610,7 @@ export class ZLinkHostServiceRelocationRuntime implements ZLinkActorJoinRelocati
|
|
|
3476
3610
|
targetNodeRid: RoutingId,
|
|
3477
3611
|
request: ZLinkServiceRelocationControlRequest,
|
|
3478
3612
|
signal?: AbortSignal,
|
|
3479
|
-
deadlineAtMs = performance.now() +
|
|
3613
|
+
deadlineAtMs: number = performance.now() + RELOCATION_OPERATION_TIMEOUT_MS,
|
|
3480
3614
|
sideband: readonly Uint8Array[] = []
|
|
3481
3615
|
): Promise<ReturnType<typeof decodeServiceRelocationControlResponse>> {
|
|
3482
3616
|
const key = controlAckKey(request);
|
|
@@ -3496,7 +3630,10 @@ export class ZLinkHostServiceRelocationRuntime implements ZLinkActorJoinRelocati
|
|
|
3496
3630
|
lastRequestError
|
|
3497
3631
|
);
|
|
3498
3632
|
}
|
|
3499
|
-
const attemptTimeoutMs = Math.max(
|
|
3633
|
+
const attemptTimeoutMs = Math.max(
|
|
3634
|
+
1,
|
|
3635
|
+
Math.min(RELOCATION_ATTEMPT_TIMEOUT_MS, Math.ceil(remainingMs))
|
|
3636
|
+
);
|
|
3500
3637
|
const startedAtMs = performance.now();
|
|
3501
3638
|
try {
|
|
3502
3639
|
const replyFrames = await this.requestInfrastructureControl(
|
|
@@ -3522,11 +3659,13 @@ export class ZLinkHostServiceRelocationRuntime implements ZLinkActorJoinRelocati
|
|
|
3522
3659
|
throw error;
|
|
3523
3660
|
}
|
|
3524
3661
|
lastRequestError = error;
|
|
3525
|
-
|
|
3526
|
-
|
|
3527
|
-
|
|
3528
|
-
|
|
3529
|
-
|
|
3662
|
+
if (isRelocationDebugEnabled()) {
|
|
3663
|
+
relocationDebug('control.request_retry', {
|
|
3664
|
+
key,
|
|
3665
|
+
kind: request.kind,
|
|
3666
|
+
targetRid: String(targetNodeRid)
|
|
3667
|
+
});
|
|
3668
|
+
}
|
|
3530
3669
|
const retryDelayMs = Math.min(
|
|
3531
3670
|
Math.max(0, attemptTimeoutMs - (performance.now() - startedAtMs)),
|
|
3532
3671
|
Math.max(0, deadlineAtMs - performance.now())
|
|
@@ -3566,7 +3705,7 @@ export class ZLinkHostServiceRelocationRuntime implements ZLinkActorJoinRelocati
|
|
|
3566
3705
|
peer.routingId !== null &&
|
|
3567
3706
|
String(peer.routingId) === String(descriptor.rid) &&
|
|
3568
3707
|
peer.lifecycleGeneration === descriptor.lifecycleGeneration &&
|
|
3569
|
-
peer.state ===
|
|
3708
|
+
peer.state === MeshPeerRuntimeState.Serving
|
|
3570
3709
|
) &&
|
|
3571
3710
|
relocationTargetSupports(descriptor, requirements)
|
|
3572
3711
|
)
|
|
@@ -3801,6 +3940,22 @@ export class ZLinkHostServiceRelocationRuntime implements ZLinkActorJoinRelocati
|
|
|
3801
3940
|
}
|
|
3802
3941
|
}
|
|
3803
3942
|
|
|
3943
|
+
private async discardTargetStage(
|
|
3944
|
+
stagingId: string,
|
|
3945
|
+
stage: LocalStage,
|
|
3946
|
+
signal?: AbortSignal
|
|
3947
|
+
): Promise<void> {
|
|
3948
|
+
stage.phase = 'failed';
|
|
3949
|
+
console.warn('[zlink.runtime.relocation.target_staging_discarded]', stagingId);
|
|
3950
|
+
try {
|
|
3951
|
+
await this.abortTargetStage(stage, signal);
|
|
3952
|
+
} finally {
|
|
3953
|
+
this.terminalTargets.remember(stagingId, stage.offer.prepareFingerprint);
|
|
3954
|
+
this.targetStages.delete(stagingId);
|
|
3955
|
+
this.targetAssemblies.delete(stagingId);
|
|
3956
|
+
}
|
|
3957
|
+
}
|
|
3958
|
+
|
|
3804
3959
|
private async commitTargetReservation(
|
|
3805
3960
|
stage: LocalStage,
|
|
3806
3961
|
reservation: TargetRelocationReservation,
|
|
@@ -3827,8 +3982,9 @@ export class ZLinkHostServiceRelocationRuntime implements ZLinkActorJoinRelocati
|
|
|
3827
3982
|
): Promise<ZLinkAuthoritySnapshot | undefined> {
|
|
3828
3983
|
const target = stage.offer.prepare.target;
|
|
3829
3984
|
for (;;) {
|
|
3985
|
+
if (stage.phase === 'failed') return undefined;
|
|
3830
3986
|
signal?.throwIfAborted();
|
|
3831
|
-
if (this.
|
|
3987
|
+
if (this.targetStageSealed(stage)) return undefined;
|
|
3832
3988
|
let conflict = false;
|
|
3833
3989
|
if (stage.cutoverReceived) {
|
|
3834
3990
|
// The boundary relay span is applied to the temporary queue before
|
|
@@ -3840,13 +3996,17 @@ export class ZLinkHostServiceRelocationRuntime implements ZLinkActorJoinRelocati
|
|
|
3840
3996
|
// A thrown provider call has an unknown result; the read below decides.
|
|
3841
3997
|
const result = await this.requireLocationStore()
|
|
3842
3998
|
.commitAggregate(prepared.fence, signal)
|
|
3843
|
-
.catch(() =>
|
|
3999
|
+
.catch((error: unknown) => {
|
|
4000
|
+
if (!isIndeterminateLocationStoreFailure(error, signal)) throw error;
|
|
4001
|
+
return undefined;
|
|
4002
|
+
});
|
|
3844
4003
|
if (result?.kind === 'generationExhausted') {
|
|
3845
4004
|
throw new Error('location_update_failed: relocation aggregate commit exhausted.');
|
|
3846
4005
|
}
|
|
3847
4006
|
conflict = result?.kind === 'stale';
|
|
3848
4007
|
}
|
|
3849
4008
|
const observed = await this.readAggregateForCommitRetry(prepared, signal);
|
|
4009
|
+
if ((stage as LocalStage).phase === 'failed') return undefined;
|
|
3850
4010
|
if (observed.kind === 'committed') {
|
|
3851
4011
|
const primary = observed.authorities.get(stage.staging.primaryAuthorityKey.value);
|
|
3852
4012
|
if (primary === undefined) {
|
|
@@ -3860,11 +4020,14 @@ export class ZLinkHostServiceRelocationRuntime implements ZLinkActorJoinRelocati
|
|
|
3860
4020
|
await this.exactSourceLeaseExpired(
|
|
3861
4021
|
{ ownerId: target.ownerId, leaseGeneration: target.ownerLeaseGeneration },
|
|
3862
4022
|
signal
|
|
3863
|
-
).catch(() =>
|
|
4023
|
+
).catch((error: unknown) => {
|
|
4024
|
+
if (!isIndeterminateLocationStoreFailure(error, signal)) throw error;
|
|
4025
|
+
return false;
|
|
4026
|
+
})
|
|
3864
4027
|
) {
|
|
3865
4028
|
return undefined;
|
|
3866
4029
|
}
|
|
3867
|
-
await waitForRelocationRetry(
|
|
4030
|
+
await waitForRelocationRetry(RELOCATION_AUTHORITY_RETRY_DELAY_MS, signal);
|
|
3868
4031
|
}
|
|
3869
4032
|
}
|
|
3870
4033
|
|
|
@@ -3906,7 +4069,8 @@ export class ZLinkHostServiceRelocationRuntime implements ZLinkActorJoinRelocati
|
|
|
3906
4069
|
return { kind: 'stale' };
|
|
3907
4070
|
}
|
|
3908
4071
|
}
|
|
3909
|
-
} catch {
|
|
4072
|
+
} catch (error) {
|
|
4073
|
+
if (!isIndeterminateLocationStoreFailure(error, signal)) throw error;
|
|
3910
4074
|
return { kind: 'unknown' };
|
|
3911
4075
|
}
|
|
3912
4076
|
if (committed === prepared.plan.participants.length) {
|
|
@@ -3958,7 +4122,7 @@ export class ZLinkHostServiceRelocationRuntime implements ZLinkActorJoinRelocati
|
|
|
3958
4122
|
if (request.object.kind === 'userSpot' || request.object.kind === 'instanceSpot') {
|
|
3959
4123
|
let cursor: ZLinkAuthorityScanCursor | undefined;
|
|
3960
4124
|
for (;;) {
|
|
3961
|
-
const page = await store.listAuthorities('', cursor,
|
|
4125
|
+
const page = await store.listAuthorities('', cursor, ZLINK_PROVIDER_MAX_PAGE_SIZE, signal);
|
|
3962
4126
|
if (page.kind === 'scanExpired') {
|
|
3963
4127
|
throw new Error('Location Store authority scan expired during relocation.');
|
|
3964
4128
|
}
|
|
@@ -4103,7 +4267,7 @@ export class ZLinkHostServiceRelocationRuntime implements ZLinkActorJoinRelocati
|
|
|
4103
4267
|
);
|
|
4104
4268
|
if (captured.byteLength > RELOCATION_PARTICIPANT_STATE_LIMIT_BYTES) {
|
|
4105
4269
|
throw new ZLinkRelocationStateIncompatibleError(
|
|
4106
|
-
|
|
4270
|
+
`Relocation application state exceeds the ${RELOCATION_PARTICIPANT_STATE_LIMIT_BYTES / (1024 * 1024)} MiB participant limit.`
|
|
4107
4271
|
);
|
|
4108
4272
|
}
|
|
4109
4273
|
return captured;
|
|
@@ -4124,13 +4288,13 @@ export class ZLinkHostServiceRelocationRuntime implements ZLinkActorJoinRelocati
|
|
|
4124
4288
|
startedAt: number,
|
|
4125
4289
|
outcome: string
|
|
4126
4290
|
): void {
|
|
4127
|
-
const seconds = Math.max(0, performance.now() - startedAt) /
|
|
4291
|
+
const seconds = Math.max(0, performance.now() - startedAt) / MILLISECONDS_PER_SECOND;
|
|
4128
4292
|
const attributes = {
|
|
4129
4293
|
unit_kind: unitKind,
|
|
4130
4294
|
...(executionMode === undefined ? {} : { execution_mode: executionMode })
|
|
4131
4295
|
};
|
|
4132
|
-
this.options.metrics?.duration(
|
|
4133
|
-
this.options.metrics?.count(
|
|
4296
|
+
this.options.metrics?.duration(METRIC_NAMES.RelocationInterruption, seconds, attributes);
|
|
4297
|
+
this.options.metrics?.count(METRIC_NAMES.RelocationCompleted, 1, {
|
|
4134
4298
|
mesh_name: meshName,
|
|
4135
4299
|
object_kind: unitKind,
|
|
4136
4300
|
policy: unitKind === 'user_spot' && executionMode === 'per_actor' ? 'recreate' : 'configured',
|
|
@@ -4388,11 +4552,6 @@ function actorJoinTargetMembership(
|
|
|
4388
4552
|
];
|
|
4389
4553
|
}
|
|
4390
4554
|
|
|
4391
|
-
function relocationDebug(marker: string, detail: Record<string, unknown>): void {
|
|
4392
|
-
if (process.env.ZLINK_DEBUG_FRAMEWORK_RELOCATION !== '1') return;
|
|
4393
|
-
console.error('[zlink.runtime.relocation]', marker, detail);
|
|
4394
|
-
}
|
|
4395
|
-
|
|
4396
4555
|
class LocalTargetPort implements ServiceRelocationTargetObjectPort<LocalHidden> {
|
|
4397
4556
|
constructor(
|
|
4398
4557
|
private readonly options: ZLinkHostRelocationOptions,
|
|
@@ -4421,8 +4580,8 @@ class LocalTargetPort implements ServiceRelocationTargetObjectPort<LocalHidden>
|
|
|
4421
4580
|
participant.stableType,
|
|
4422
4581
|
participant.objectGeneration,
|
|
4423
4582
|
participant.authorityOwnerGeneration + 1n,
|
|
4424
|
-
|
|
4425
|
-
|
|
4583
|
+
nativeEntrySpot ? undefined : (spotIdentity as RoutingId),
|
|
4584
|
+
membership.spotObjectGeneration,
|
|
4426
4585
|
membership.membershipEpoch,
|
|
4427
4586
|
signal
|
|
4428
4587
|
);
|
|
@@ -4562,11 +4721,22 @@ class LocalTargetPort implements ServiceRelocationTargetObjectPort<LocalHidden>
|
|
|
4562
4721
|
hidden.participant.objectKind === 'user_spot' &&
|
|
4563
4722
|
registration.options?.relocationCoordinationMode ===
|
|
4564
4723
|
ZLinkSpotRelocationCoordinationMode.ApplicationSignaled;
|
|
4724
|
+
// createHidden could only predict the owner generation; the native Spot
|
|
4725
|
+
// takes the committed authority, as the Actor branch does above.
|
|
4726
|
+
const node = this.options.meshNode(this.meshName);
|
|
4727
|
+
node?.restoreSpotAuthority?.(
|
|
4728
|
+
String(hidden.activation.spotId),
|
|
4729
|
+
// createHidden stages an activation only for a Spot participant.
|
|
4730
|
+
hidden.participant.objectKind as 'user_spot' | 'instance_spot',
|
|
4731
|
+
hidden.participant.stableType,
|
|
4732
|
+
authority.objectGeneration,
|
|
4733
|
+
authority.authorityOwnerGeneration
|
|
4734
|
+
);
|
|
4565
4735
|
await this.requireSpotManager().publishRelocationSpot(
|
|
4566
4736
|
hidden.activation,
|
|
4567
4737
|
applicationSignaled ? () => hidden.activation!.notifyRelocatedBoundary() : undefined
|
|
4568
4738
|
);
|
|
4569
|
-
|
|
4739
|
+
node?.rememberSpotRoute?.({
|
|
4570
4740
|
spot: {
|
|
4571
4741
|
spotId: String(hidden.activation.spotId),
|
|
4572
4742
|
generation: authority.objectGeneration
|
|
@@ -4597,14 +4767,13 @@ class LocalTargetPort implements ServiceRelocationTargetObjectPort<LocalHidden>
|
|
|
4597
4767
|
}
|
|
4598
4768
|
|
|
4599
4769
|
async restoreBoundSession(hidden: LocalHidden, payload: Uint8Array): Promise<void> {
|
|
4600
|
-
|
|
4601
|
-
|
|
4602
|
-
|
|
4603
|
-
|
|
4604
|
-
|
|
4605
|
-
|
|
4606
|
-
|
|
4607
|
-
}
|
|
4770
|
+
const carried = decodeActorSession(payload);
|
|
4771
|
+
if (hidden.actor === undefined || carried === undefined) return;
|
|
4772
|
+
// The relocation delivers the binding it carried; the target installs it
|
|
4773
|
+
// through the one install rule (Session–Actor binding §6, §8).
|
|
4774
|
+
this.requireActorManager()
|
|
4775
|
+
.getState(hidden.actor.context.actorId)!
|
|
4776
|
+
.installBoundSessionBinding(carried);
|
|
4608
4777
|
}
|
|
4609
4778
|
|
|
4610
4779
|
async replayQueuedMessage(
|
|
@@ -5060,9 +5229,11 @@ export function createServiceRelocationId(
|
|
|
5060
5229
|
entropy: (size: number) => Uint8Array = randomBytes
|
|
5061
5230
|
): string {
|
|
5062
5231
|
for (;;) {
|
|
5063
|
-
const bytes = entropy(
|
|
5064
|
-
if (bytes.byteLength !==
|
|
5065
|
-
throw new Error(
|
|
5232
|
+
const bytes = entropy(OPERATION_IDENTITY_BYTES);
|
|
5233
|
+
if (bytes.byteLength !== OPERATION_IDENTITY_BYTES) {
|
|
5234
|
+
throw new Error(
|
|
5235
|
+
`Relocation identity entropy must return exactly ${OPERATION_IDENTITY_BYTES} bytes.`
|
|
5236
|
+
);
|
|
5066
5237
|
}
|
|
5067
5238
|
let nonZero = false;
|
|
5068
5239
|
for (const byte of bytes) {
|
|
@@ -5103,13 +5274,52 @@ function sameCoordinator(
|
|
|
5103
5274
|
): boolean {
|
|
5104
5275
|
return (
|
|
5105
5276
|
left.ownerId === right.ownerId &&
|
|
5106
|
-
left.leaseGeneration === right.leaseGeneration &&
|
|
5277
|
+
BigInt(left.leaseGeneration) === right.leaseGeneration &&
|
|
5107
5278
|
left.nodeRid === right.nodeRid &&
|
|
5108
|
-
left.nodeGeneration === right.nodeGeneration &&
|
|
5279
|
+
BigInt(left.nodeGeneration) === right.nodeGeneration &&
|
|
5109
5280
|
left.expectedAuthorityStoreVersion === right.expectedAuthorityStoreVersion
|
|
5110
5281
|
);
|
|
5111
5282
|
}
|
|
5112
5283
|
|
|
5284
|
+
function sameRelocationTarget(
|
|
5285
|
+
left: ServiceWireRelocationTarget,
|
|
5286
|
+
right: ServiceWireRelocationTarget
|
|
5287
|
+
): boolean {
|
|
5288
|
+
return (
|
|
5289
|
+
left.nodeRid === right.nodeRid &&
|
|
5290
|
+
BigInt(left.nodeGeneration) === right.nodeGeneration &&
|
|
5291
|
+
left.ownerId === right.ownerId &&
|
|
5292
|
+
BigInt(left.ownerLeaseGeneration) === right.ownerLeaseGeneration
|
|
5293
|
+
);
|
|
5294
|
+
}
|
|
5295
|
+
|
|
5296
|
+
function sameRelocationObject(
|
|
5297
|
+
left: ServiceWireRelocationObject,
|
|
5298
|
+
right: ServiceWireRelocationObject
|
|
5299
|
+
): boolean {
|
|
5300
|
+
if (left.kind !== right.kind || BigInt(left.objectGeneration) !== right.objectGeneration) {
|
|
5301
|
+
return false;
|
|
5302
|
+
}
|
|
5303
|
+
if (left.kind === 'actor' && right.kind === 'actor') {
|
|
5304
|
+
return (
|
|
5305
|
+
left.actorId === right.actorId &&
|
|
5306
|
+
BigInt(left.expectedAuthorityOwnerGeneration) === right.expectedAuthorityOwnerGeneration
|
|
5307
|
+
);
|
|
5308
|
+
}
|
|
5309
|
+
if (left.kind === 'userSpot' && right.kind === 'userSpot') {
|
|
5310
|
+
return (
|
|
5311
|
+
left.spotId === right.spotId &&
|
|
5312
|
+
BigInt(left.expectedAuthorityOwnerGeneration) === right.expectedAuthorityOwnerGeneration
|
|
5313
|
+
);
|
|
5314
|
+
}
|
|
5315
|
+
return (
|
|
5316
|
+
left.kind === 'instanceSpot' &&
|
|
5317
|
+
right.kind === 'instanceSpot' &&
|
|
5318
|
+
left.spotId === right.spotId &&
|
|
5319
|
+
left.stableType === right.stableType
|
|
5320
|
+
);
|
|
5321
|
+
}
|
|
5322
|
+
|
|
5113
5323
|
function isExactSourceAuthority(
|
|
5114
5324
|
current: ZLinkAuthoritySnapshot,
|
|
5115
5325
|
expected: ZLinkAuthoritySnapshot
|
|
@@ -5206,14 +5416,16 @@ function maintenanceReplyRelay(
|
|
|
5206
5416
|
replyRouteId: BigInt(completion.source.replyRouteId),
|
|
5207
5417
|
participantId,
|
|
5208
5418
|
sequence: BigInt(completion.index + 1),
|
|
5209
|
-
terminalResult: completion.result.ok ?
|
|
5210
|
-
failureCode: completion.result.ok
|
|
5419
|
+
terminalResult: completion.result.ok ? RequestResult.Ok : RequestResult.InternalError,
|
|
5420
|
+
failureCode: completion.result.ok
|
|
5421
|
+
? ServiceWireFrameworkErrorCode.none
|
|
5422
|
+
: ServiceWireFrameworkErrorCode.requestFailed,
|
|
5211
5423
|
...(value === undefined
|
|
5212
5424
|
? {}
|
|
5213
5425
|
: {
|
|
5214
5426
|
payload: {
|
|
5215
|
-
packetName:
|
|
5216
|
-
contentType:
|
|
5427
|
+
packetName: SERVICE_RELOCATION_REPLY_PACKET_NAME,
|
|
5428
|
+
contentType: ZlinkStreamContentType.Json,
|
|
5217
5429
|
bytes: Buffer.from(JSON.stringify(value), 'utf8')
|
|
5218
5430
|
}
|
|
5219
5431
|
})
|
|
@@ -5227,16 +5439,16 @@ function handoffResultFromRelay(relay: ServiceMaintenanceReplyRelay): ZLinkActor
|
|
|
5227
5439
|
let value: unknown;
|
|
5228
5440
|
if (relay.payload !== undefined) {
|
|
5229
5441
|
if (
|
|
5230
|
-
relay.terminalResult !==
|
|
5231
|
-
relay.payload.packetName !==
|
|
5232
|
-
relay.payload.contentType !==
|
|
5442
|
+
relay.terminalResult !== RequestResult.Ok ||
|
|
5443
|
+
relay.payload.packetName !== SERVICE_RELOCATION_REPLY_PACKET_NAME ||
|
|
5444
|
+
relay.payload.contentType !== ZlinkStreamContentType.Json
|
|
5233
5445
|
) {
|
|
5234
5446
|
throw new TypeError('Relocation terminal payload boundary is invalid.');
|
|
5235
5447
|
}
|
|
5236
5448
|
value = JSON.parse(Buffer.from(relay.payload.bytes).toString('utf8')) as unknown;
|
|
5237
5449
|
}
|
|
5238
5450
|
const index = Number(relay.sequence - 1n);
|
|
5239
|
-
return relay.terminalResult ===
|
|
5451
|
+
return relay.terminalResult === RequestResult.Ok
|
|
5240
5452
|
? { index, ok: true, ...(value === undefined ? {} : { response: value }) }
|
|
5241
5453
|
: { index, ok: false, error: `Actor handoff failed with framework code ${relay.failureCode}.` };
|
|
5242
5454
|
}
|
|
@@ -5252,76 +5464,15 @@ function wireIdText(value: { readonly high: bigint; readonly low: bigint }): str
|
|
|
5252
5464
|
*/
|
|
5253
5465
|
export class ServiceRelocationDataLostError extends Error {}
|
|
5254
5466
|
|
|
5255
|
-
/**
|
|
5256
|
-
|
|
5257
|
-
* framework-error code the generated schema
|
|
5258
|
-
* ({@link ServiceWireFrameworkErrorCode}) defines — mirrors the java
|
|
5259
|
-
* reference mapping (commit 97fc074058) and the dotnet/cpp ports. The wire
|
|
5260
|
-
* vocabulary predates the framework's typed error kinds and has no
|
|
5261
|
-
* one-to-one code for every kind, so several kinds share the nearest fit
|
|
5262
|
-
* (documented per case below); unresolvable vocabulary gaps belong at the
|
|
5263
|
-
* schema level, not invented here. {@link ServiceRelocationDataLostError}
|
|
5264
|
-
* is this runtime's dedicated tag for a verified checksum/assembly/digest
|
|
5265
|
-
* integrity failure — the case that keeps relocationDataLost(35). An
|
|
5266
|
-
* unclassified error carries no evidence of integrity loss and takes the
|
|
5267
|
-
* generic opaque requestFailed(17). `objectKind` (the Prepare's
|
|
5268
|
-
* ObjectFence.kind, spec 28 §4.2) picks between an Actor- and
|
|
5269
|
-
* Spot-specific code where the schema splits by object kind.
|
|
5270
|
-
*/
|
|
5271
|
-
export function relocationFailedFailureCode(
|
|
5272
|
-
error: unknown,
|
|
5273
|
-
objectKind: ServiceWireRelocationObject['kind']
|
|
5274
|
-
): number {
|
|
5467
|
+
/** Classifies relocation failure with the error model §2.1 mapping. */
|
|
5468
|
+
export function relocationFailedFailureCode(error: unknown): number {
|
|
5275
5469
|
if (error instanceof ServiceRelocationDataLostError) {
|
|
5276
|
-
return
|
|
5470
|
+
return frameworkRelocationFailureCode(ZLinkFrameworkErrorKind.DataLost);
|
|
5277
5471
|
}
|
|
5278
5472
|
if (!(error instanceof ZLinkFrameworkException)) {
|
|
5279
|
-
return
|
|
5280
|
-
}
|
|
5281
|
-
switch (error.kind) {
|
|
5282
|
-
case ZLinkFrameworkErrorKind.DataLost:
|
|
5283
|
-
return ServiceWireFrameworkErrorCode.relocationDataLost;
|
|
5284
|
-
case ZLinkFrameworkErrorKind.Rejected:
|
|
5285
|
-
return ServiceWireFrameworkErrorCode.requestRejected;
|
|
5286
|
-
case ZLinkFrameworkErrorKind.ProtocolError:
|
|
5287
|
-
return ServiceWireFrameworkErrorCode.requestProtocolError;
|
|
5288
|
-
// No dedicated "deadline exceeded" wire code exists; a worker timeout
|
|
5289
|
-
// is the closest timeout-shaped signal.
|
|
5290
|
-
case ZLinkFrameworkErrorKind.DeadlineExceeded:
|
|
5291
|
-
return ServiceWireFrameworkErrorCode.workerTimedOut;
|
|
5292
|
-
// A stale generation/fence is the concrete cause of InvalidOperation
|
|
5293
|
-
// along this path (spec 15 failure table); pick the
|
|
5294
|
-
// object-kind-specific stale code.
|
|
5295
|
-
case ZLinkFrameworkErrorKind.InvalidOperation:
|
|
5296
|
-
return objectKind === 'actor'
|
|
5297
|
-
? ServiceWireFrameworkErrorCode.actorLocationStale
|
|
5298
|
-
: ServiceWireFrameworkErrorCode.spotGenerationStale;
|
|
5299
|
-
// No dedicated generic "unavailable" wire code exists; a disconnected
|
|
5300
|
-
// route is the closest "cannot reach/use the target" signal.
|
|
5301
|
-
case ZLinkFrameworkErrorKind.Unavailable:
|
|
5302
|
-
return ServiceWireFrameworkErrorCode.routeNotConnected;
|
|
5303
|
-
case ZLinkFrameworkErrorKind.NotFound:
|
|
5304
|
-
return ServiceWireFrameworkErrorCode.requestTargetNotFound;
|
|
5305
|
-
// The only "already exists" wire code is Actor-specific; not expected
|
|
5306
|
-
// along this target-failure path, mapped for completeness.
|
|
5307
|
-
case ZLinkFrameworkErrorKind.AlreadyExists:
|
|
5308
|
-
return ServiceWireFrameworkErrorCode.actorAlreadyExists;
|
|
5309
|
-
case ZLinkFrameworkErrorKind.TypeMismatch:
|
|
5310
|
-
return objectKind === 'actor'
|
|
5311
|
-
? ServiceWireFrameworkErrorCode.actorTypeMismatch
|
|
5312
|
-
: ServiceWireFrameworkErrorCode.spotTypeMismatch;
|
|
5313
|
-
// No dedicated "not configured" wire code exists; a missing configured
|
|
5314
|
-
// handler is the closest analog.
|
|
5315
|
-
case ZLinkFrameworkErrorKind.NotConfigured:
|
|
5316
|
-
return ServiceWireFrameworkErrorCode.handlerNotFound;
|
|
5317
|
-
// No dedicated generic "internal failure" or "shutting down" wire code
|
|
5318
|
-
// exists; the generic opaque request-failure code is the closest fit
|
|
5319
|
-
// for both (ShuttingDown included — re-judged 2026-08-19, C-10).
|
|
5320
|
-
case ZLinkFrameworkErrorKind.ShuttingDown:
|
|
5321
|
-
case ZLinkFrameworkErrorKind.InternalFailure:
|
|
5322
|
-
default:
|
|
5323
|
-
return ServiceWireFrameworkErrorCode.requestFailed;
|
|
5473
|
+
return frameworkRelocationFailureCode(ZLinkFrameworkErrorKind.InternalFailure);
|
|
5324
5474
|
}
|
|
5475
|
+
return frameworkRelocationFailureCode(error);
|
|
5325
5476
|
}
|
|
5326
5477
|
|
|
5327
5478
|
function relocationStagingId(value: {
|
|
@@ -5434,7 +5585,7 @@ function validatePrepareEnvelope(
|
|
|
5434
5585
|
if (
|
|
5435
5586
|
!sameWireId(request.relocation, relocationWireId(envelope.aggregateId)) ||
|
|
5436
5587
|
request.applicationVersion !== envelope.applicationVersion ||
|
|
5437
|
-
|
|
5588
|
+
!sameRelocationObject(request.object, relocationObject(envelope))
|
|
5438
5589
|
) {
|
|
5439
5590
|
throw new Error('Relocation Prepare does not match its immutable root identity.');
|
|
5440
5591
|
}
|
|
@@ -5451,17 +5602,10 @@ function validateTargetOneWayControl(
|
|
|
5451
5602
|
!sameWireId(request.relocation, prepare.relocation) ||
|
|
5452
5603
|
request.targetAttemptGeneration !== prepare.targetAttemptGeneration ||
|
|
5453
5604
|
!sameCoordinator(request.coordinator, prepare.coordinator) ||
|
|
5454
|
-
|
|
5455
|
-
stringifyWire(request.kind === 'data' ? request.object : prepare.object)
|
|
5605
|
+
(request.kind === 'cutover' && !sameRelocationObject(request.object, prepare.object))
|
|
5456
5606
|
) {
|
|
5457
5607
|
throw new Error('Relocation one-way control changed its exact Prepare fence.');
|
|
5458
5608
|
}
|
|
5459
|
-
if (
|
|
5460
|
-
request.kind === 'cutover' &&
|
|
5461
|
-
stringifyWire(request.object) !== stringifyWire(prepare.object)
|
|
5462
|
-
) {
|
|
5463
|
-
throw new Error('Relocation Cutover changed its prepared object.');
|
|
5464
|
-
}
|
|
5465
5609
|
}
|
|
5466
5610
|
|
|
5467
5611
|
function relocationPublication(
|
|
@@ -5566,7 +5710,7 @@ function canonicalQueuedFrozenRecord(
|
|
|
5566
5710
|
...(packet.returnResponse ? { replyRouteId: BigInt(packet.source!.replyRouteId) } : {}),
|
|
5567
5711
|
payload: {
|
|
5568
5712
|
packetName: '__zlink.actor.handoff.accepted',
|
|
5569
|
-
contentType:
|
|
5713
|
+
contentType: ZlinkStreamContentType.Json,
|
|
5570
5714
|
bytes: message.payload
|
|
5571
5715
|
}
|
|
5572
5716
|
});
|
|
@@ -5590,6 +5734,20 @@ function stringifyWire(value: unknown): string {
|
|
|
5590
5734
|
return JSON.stringify(value, (_key, item) => (typeof item === 'bigint' ? item.toString() : item));
|
|
5591
5735
|
}
|
|
5592
5736
|
|
|
5737
|
+
function samePrepareIdentity(
|
|
5738
|
+
acceptedFingerprint: string,
|
|
5739
|
+
incoming: ServiceMaintenanceRelocationPrepare
|
|
5740
|
+
): boolean {
|
|
5741
|
+
const accepted = JSON.parse(acceptedFingerprint) as ServiceMaintenanceRelocationPrepare;
|
|
5742
|
+
return (
|
|
5743
|
+
accepted.sourceNodeRid === incoming.sourceNodeRid &&
|
|
5744
|
+
BigInt(accepted.sourceNodeGeneration) === incoming.sourceNodeGeneration &&
|
|
5745
|
+
sameCoordinator(accepted.coordinator, incoming.coordinator) &&
|
|
5746
|
+
sameRelocationTarget(accepted.target, incoming.target) &&
|
|
5747
|
+
sameRelocationObject(accepted.object, incoming.object)
|
|
5748
|
+
);
|
|
5749
|
+
}
|
|
5750
|
+
|
|
5593
5751
|
function validateControlResponse(
|
|
5594
5752
|
request: ZLinkServiceRelocationControlRequest,
|
|
5595
5753
|
response: ZLinkServiceRelocationControlResponse
|
|
@@ -5600,8 +5758,8 @@ function validateControlResponse(
|
|
|
5600
5758
|
!sameWireId(response.relocation, request.relocation) ||
|
|
5601
5759
|
response.targetAttemptGeneration !== request.targetAttemptGeneration ||
|
|
5602
5760
|
!sameCoordinator(response.coordinator, request.coordinator) ||
|
|
5603
|
-
|
|
5604
|
-
|
|
5761
|
+
!sameRelocationTarget(response.target, request.target) ||
|
|
5762
|
+
!sameRelocationObject(response.object, request.object) ||
|
|
5605
5763
|
response.senderRole !== 'target'
|
|
5606
5764
|
) {
|
|
5607
5765
|
throw new Error('Relocation control response does not match the request fence.');
|
|
@@ -5624,82 +5782,19 @@ function validateControlFailureResponse(
|
|
|
5624
5782
|
!sameWireId(response.relocation, request.relocation) ||
|
|
5625
5783
|
response.targetAttemptGeneration !== request.targetAttemptGeneration ||
|
|
5626
5784
|
!sameCoordinator(response.coordinator, request.coordinator) ||
|
|
5627
|
-
|
|
5628
|
-
|
|
5785
|
+
!sameRelocationTarget(response.target, request.target) ||
|
|
5786
|
+
!sameRelocationObject(response.object, request.object) ||
|
|
5629
5787
|
response.senderRole !== 'target'
|
|
5630
5788
|
) {
|
|
5631
5789
|
throw new Error('Relocation control response does not match the request fence.');
|
|
5632
5790
|
}
|
|
5633
5791
|
}
|
|
5634
5792
|
|
|
5635
|
-
/**
|
|
5636
|
-
* Maps a relocationFailed(53) wire failureCode (the generated
|
|
5637
|
-
* ServiceWireFrameworkErrorCode vocabulary) to its internal error kind, so a
|
|
5638
|
-
* source-side reject carries the same classification the target chose
|
|
5639
|
-
* instead of a generic Error. Direct 1:1 correspondence with the generated
|
|
5640
|
-
* names; an unrecognised or absent code falls back to RequestFailed
|
|
5641
|
-
* (InternalFailure) — the closest existing kind (spec 15 §"Failed.Kind").
|
|
5642
|
-
*/
|
|
5643
|
-
function relocationFailureCodeKind(failureCode: number): ZLinkFrameworkInternalErrorKind {
|
|
5644
|
-
switch (failureCode) {
|
|
5645
|
-
case 1:
|
|
5646
|
-
return ZLinkFrameworkInternalErrorKind.ActorRouteNotFound;
|
|
5647
|
-
case 2:
|
|
5648
|
-
return ZLinkFrameworkInternalErrorKind.ActorCreateFailed;
|
|
5649
|
-
case 3:
|
|
5650
|
-
return ZLinkFrameworkInternalErrorKind.ActorAlreadyExists;
|
|
5651
|
-
case 4:
|
|
5652
|
-
return ZLinkFrameworkInternalErrorKind.ActorTypeMismatch;
|
|
5653
|
-
case 5:
|
|
5654
|
-
return ZLinkFrameworkInternalErrorKind.SpotCreateFailed;
|
|
5655
|
-
case 6:
|
|
5656
|
-
return ZLinkFrameworkInternalErrorKind.SpotRouteNotFound;
|
|
5657
|
-
case 7:
|
|
5658
|
-
return ZLinkFrameworkInternalErrorKind.SpotTypeMismatch;
|
|
5659
|
-
case 8:
|
|
5660
|
-
return ZLinkFrameworkInternalErrorKind.ActorSessionNotBound;
|
|
5661
|
-
case 9:
|
|
5662
|
-
return ZLinkFrameworkInternalErrorKind.HandlerNotFound;
|
|
5663
|
-
case 10:
|
|
5664
|
-
return ZLinkFrameworkInternalErrorKind.RouteHandlerNotFound;
|
|
5665
|
-
case 11:
|
|
5666
|
-
return ZLinkFrameworkInternalErrorKind.ActorDispatchHandlerNotFound;
|
|
5667
|
-
case 12:
|
|
5668
|
-
return ZLinkFrameworkInternalErrorKind.PayloadDecodeFailed;
|
|
5669
|
-
case 13:
|
|
5670
|
-
return ZLinkFrameworkInternalErrorKind.RouteNotConnected;
|
|
5671
|
-
case 14:
|
|
5672
|
-
return ZLinkFrameworkInternalErrorKind.RequestTargetNotFound;
|
|
5673
|
-
case 15:
|
|
5674
|
-
return ZLinkFrameworkInternalErrorKind.RequestRejected;
|
|
5675
|
-
case 16:
|
|
5676
|
-
return ZLinkFrameworkInternalErrorKind.RequestProtocolError;
|
|
5677
|
-
case 18:
|
|
5678
|
-
return ZLinkFrameworkInternalErrorKind.WorkerQueueFull;
|
|
5679
|
-
case 19:
|
|
5680
|
-
return ZLinkFrameworkInternalErrorKind.WorkerTimedOut;
|
|
5681
|
-
case 20:
|
|
5682
|
-
return ZLinkFrameworkInternalErrorKind.WorkerFailed;
|
|
5683
|
-
case 21:
|
|
5684
|
-
return ZLinkFrameworkInternalErrorKind.ActorLocationStale;
|
|
5685
|
-
case 22:
|
|
5686
|
-
return ZLinkFrameworkInternalErrorKind.ActorCreateRejected;
|
|
5687
|
-
case 33:
|
|
5688
|
-
return ZLinkFrameworkInternalErrorKind.SpotGenerationStale;
|
|
5689
|
-
case 34:
|
|
5690
|
-
return ZLinkFrameworkInternalErrorKind.SpotMoving;
|
|
5691
|
-
case 35:
|
|
5692
|
-
return ZLinkFrameworkInternalErrorKind.RelocationDataLost;
|
|
5693
|
-
case 17:
|
|
5694
|
-
default:
|
|
5695
|
-
return ZLinkFrameworkInternalErrorKind.RequestFailed;
|
|
5696
|
-
}
|
|
5697
|
-
}
|
|
5698
|
-
|
|
5699
5793
|
/** Builds the typed exception a Prepare waiter rejects with on an explicit Failed(53). */
|
|
5700
5794
|
function relocationFailureException(response: ServiceMaintenanceRelocationFailed) {
|
|
5701
5795
|
return createInternalFrameworkException(
|
|
5702
|
-
|
|
5796
|
+
internalFrameworkErrorKindFromWireFailureCode(response.failureCode) ??
|
|
5797
|
+
ZLinkFrameworkInternalErrorKind.RequestFailed,
|
|
5703
5798
|
`Relocation '${response.relocation.high}:${response.relocation.low}:` +
|
|
5704
5799
|
`${response.targetAttemptGeneration}' failed with wire failureCode ${response.failureCode}.`,
|
|
5705
5800
|
true
|
|
@@ -5879,7 +5974,7 @@ function queuedMessageU64(value: unknown, field: string): bigint {
|
|
|
5879
5974
|
throw new TypeError(`Relocation Actor Message Follow ${field} is invalid.`);
|
|
5880
5975
|
}
|
|
5881
5976
|
const result = BigInt(value);
|
|
5882
|
-
if (result >
|
|
5977
|
+
if (result > UINT64_MAX) {
|
|
5883
5978
|
throw new TypeError(`Relocation Actor Message Follow ${field} is outside u64.`);
|
|
5884
5979
|
}
|
|
5885
5980
|
return result;
|
|
@@ -5903,6 +5998,15 @@ function toServiceTimer(
|
|
|
5903
5998
|
};
|
|
5904
5999
|
}
|
|
5905
6000
|
|
|
6001
|
+
const PREPARE_SIDEBAND_MAGIC = 'ZLNI';
|
|
6002
|
+
const PREPARE_SIDEBAND_VERSION = 1;
|
|
6003
|
+
const PREPARE_SIDEBAND_HEADER_BYTES = 11;
|
|
6004
|
+
const PREPARE_SIDEBAND_VERSION_OFFSET = 4;
|
|
6005
|
+
const PREPARE_SIDEBAND_KEY_LENGTH_OFFSET = 5;
|
|
6006
|
+
const PREPARE_SIDEBAND_PAYLOAD_LENGTH_OFFSET = 7;
|
|
6007
|
+
const ACTOR_SESSION_JOURNAL_VERSION = 1;
|
|
6008
|
+
const SERVICE_RELOCATION_REPLY_PACKET_NAME = 'zlink.relocation.reply';
|
|
6009
|
+
|
|
5906
6010
|
/**
|
|
5907
6011
|
* NODE-INTERNAL Prepare sideband. Frame zero remains the exact canonical
|
|
5908
6012
|
* command-40 schema record; each following ZLNI frame carries one sealed
|
|
@@ -5918,11 +6022,11 @@ function encodePrepareSideband(envelope: ServiceRelocationEnvelope): readonly Bu
|
|
|
5918
6022
|
if (key.byteLength === 0 || key.byteLength > 0xffff || payload.byteLength > 0xffff_ffff) {
|
|
5919
6023
|
throw new TypeError('Bound-session relocation sideband is out of bounds.');
|
|
5920
6024
|
}
|
|
5921
|
-
const header = Buffer.allocUnsafe(
|
|
5922
|
-
header.write(
|
|
5923
|
-
header[
|
|
5924
|
-
header.writeUInt16BE(key.byteLength,
|
|
5925
|
-
header.writeUInt32BE(payload.byteLength,
|
|
6025
|
+
const header = Buffer.allocUnsafe(PREPARE_SIDEBAND_HEADER_BYTES);
|
|
6026
|
+
header.write(PREPARE_SIDEBAND_MAGIC, 0, 'ascii');
|
|
6027
|
+
header[PREPARE_SIDEBAND_VERSION_OFFSET] = PREPARE_SIDEBAND_VERSION;
|
|
6028
|
+
header.writeUInt16BE(key.byteLength, PREPARE_SIDEBAND_KEY_LENGTH_OFFSET);
|
|
6029
|
+
header.writeUInt32BE(payload.byteLength, PREPARE_SIDEBAND_PAYLOAD_LENGTH_OFFSET);
|
|
5926
6030
|
return Buffer.concat([header, key, payload]);
|
|
5927
6031
|
});
|
|
5928
6032
|
}
|
|
@@ -5938,19 +6042,29 @@ function decodePrepareSideband(frames: readonly Uint8Array[]):
|
|
|
5938
6042
|
for (const frame of frames) {
|
|
5939
6043
|
const bytes = Buffer.from(frame);
|
|
5940
6044
|
if (
|
|
5941
|
-
bytes.byteLength <
|
|
5942
|
-
bytes.subarray(0,
|
|
5943
|
-
|
|
6045
|
+
bytes.byteLength < PREPARE_SIDEBAND_HEADER_BYTES ||
|
|
6046
|
+
bytes.subarray(0, PREPARE_SIDEBAND_VERSION_OFFSET).toString('ascii') !==
|
|
6047
|
+
PREPARE_SIDEBAND_MAGIC ||
|
|
6048
|
+
bytes[PREPARE_SIDEBAND_VERSION_OFFSET] !== PREPARE_SIDEBAND_VERSION
|
|
5944
6049
|
) {
|
|
5945
6050
|
return undefined;
|
|
5946
6051
|
}
|
|
5947
|
-
const keyLength = bytes.readUInt16BE(
|
|
5948
|
-
const payloadLength = bytes.readUInt32BE(
|
|
5949
|
-
if (
|
|
5950
|
-
|
|
6052
|
+
const keyLength = bytes.readUInt16BE(PREPARE_SIDEBAND_KEY_LENGTH_OFFSET);
|
|
6053
|
+
const payloadLength = bytes.readUInt32BE(PREPARE_SIDEBAND_PAYLOAD_LENGTH_OFFSET);
|
|
6054
|
+
if (
|
|
6055
|
+
PREPARE_SIDEBAND_HEADER_BYTES + keyLength + payloadLength !== bytes.byteLength ||
|
|
6056
|
+
keyLength === 0
|
|
6057
|
+
)
|
|
6058
|
+
return undefined;
|
|
6059
|
+
const participantKey = bytes
|
|
6060
|
+
.subarray(PREPARE_SIDEBAND_HEADER_BYTES, PREPARE_SIDEBAND_HEADER_BYTES + keyLength)
|
|
6061
|
+
.toString('utf8');
|
|
5951
6062
|
if (keys.has(participantKey)) return undefined;
|
|
5952
6063
|
keys.add(participantKey);
|
|
5953
|
-
result.push({
|
|
6064
|
+
result.push({
|
|
6065
|
+
participantKey,
|
|
6066
|
+
payload: Buffer.from(bytes.subarray(PREPARE_SIDEBAND_HEADER_BYTES + keyLength))
|
|
6067
|
+
});
|
|
5954
6068
|
}
|
|
5955
6069
|
return result;
|
|
5956
6070
|
}
|
|
@@ -5981,13 +6095,16 @@ function encodeActorSession(target: ZLinkRemoteBoundSessionTarget | undefined):
|
|
|
5981
6095
|
if (target === undefined) return Buffer.alloc(0);
|
|
5982
6096
|
return Buffer.from(
|
|
5983
6097
|
JSON.stringify({
|
|
5984
|
-
version:
|
|
6098
|
+
version: ACTOR_SESSION_JOURNAL_VERSION,
|
|
5985
6099
|
routerChannelId: target.routerChannelId,
|
|
5986
6100
|
targetNodeRid: String(target.targetNodeRid),
|
|
5987
6101
|
spotId: String(target.spotId),
|
|
5988
6102
|
sessionNodeRid:
|
|
5989
6103
|
target.sessionNodeRid === undefined ? undefined : String(target.sessionNodeRid),
|
|
5990
6104
|
sessionRid: target.sessionRid === undefined ? undefined : String(target.sessionRid),
|
|
6105
|
+
sessionOwnerNodeGeneration: target.sessionOwnerNodeGeneration?.toString(),
|
|
6106
|
+
sessionOwnerId: target.sessionOwnerId,
|
|
6107
|
+
sessionOwnerLeaseGeneration: target.sessionOwnerLeaseGeneration?.toString(),
|
|
5991
6108
|
bindingGeneration: target.bindingGeneration?.toString(),
|
|
5992
6109
|
previousAuthorityOwnerGeneration: target.previousAuthorityOwnerGeneration?.toString(),
|
|
5993
6110
|
previousOwnerLeaseGeneration: target.previousOwnerLeaseGeneration?.toString(),
|
|
@@ -6020,12 +6137,13 @@ function encodeActorSession(target: ZLinkRemoteBoundSessionTarget | undefined):
|
|
|
6020
6137
|
);
|
|
6021
6138
|
}
|
|
6022
6139
|
|
|
6023
|
-
function decodeActorSession(payload: Uint8Array): ZLinkRemoteBoundSessionTarget {
|
|
6140
|
+
function decodeActorSession(payload: Uint8Array): ZLinkRemoteBoundSessionTarget | undefined {
|
|
6141
|
+
if (payload.byteLength === 0) return undefined;
|
|
6024
6142
|
const value = JSON.parse(Buffer.from(payload).toString('utf8')) as Record<string, unknown>;
|
|
6025
6143
|
const optionalBigInt = (field: string) =>
|
|
6026
6144
|
typeof value[field] === 'string' ? BigInt(value[field] as string) : undefined;
|
|
6027
6145
|
if (
|
|
6028
|
-
value.version !==
|
|
6146
|
+
value.version !== ACTOR_SESSION_JOURNAL_VERSION ||
|
|
6029
6147
|
typeof value.routerChannelId !== 'string' ||
|
|
6030
6148
|
typeof value.targetNodeRid !== 'string' ||
|
|
6031
6149
|
typeof value.spotId !== 'string'
|
|
@@ -6041,6 +6159,13 @@ function decodeActorSession(payload: Uint8Array): ZLinkRemoteBoundSessionTarget
|
|
|
6041
6159
|
? { sessionNodeRid: value.sessionNodeRid as RoutingId }
|
|
6042
6160
|
: {}),
|
|
6043
6161
|
...(typeof value.sessionRid === 'string' ? { sessionRid: value.sessionRid as RoutingId } : {}),
|
|
6162
|
+
...(optionalBigInt('sessionOwnerNodeGeneration') === undefined
|
|
6163
|
+
? {}
|
|
6164
|
+
: { sessionOwnerNodeGeneration: optionalBigInt('sessionOwnerNodeGeneration') }),
|
|
6165
|
+
...(typeof value.sessionOwnerId === 'string' ? { sessionOwnerId: value.sessionOwnerId } : {}),
|
|
6166
|
+
...(optionalBigInt('sessionOwnerLeaseGeneration') === undefined
|
|
6167
|
+
? {}
|
|
6168
|
+
: { sessionOwnerLeaseGeneration: optionalBigInt('sessionOwnerLeaseGeneration') }),
|
|
6044
6169
|
...(optionalBigInt('bindingGeneration') === undefined
|
|
6045
6170
|
? {}
|
|
6046
6171
|
: { bindingGeneration: optionalBigInt('bindingGeneration') }),
|
|
@@ -6153,3 +6278,16 @@ function addCapacity(left: ZLinkCapacityVector, right: ZLinkCapacityVector): ZLi
|
|
|
6153
6278
|
})
|
|
6154
6279
|
};
|
|
6155
6280
|
}
|
|
6281
|
+
|
|
6282
|
+
if (isStructuralGuardEnabled()) {
|
|
6283
|
+
const relocateActorJoin = ZLinkHostServiceRelocationRuntime.prototype.relocateActorJoin;
|
|
6284
|
+
ZLinkHostServiceRelocationRuntime.prototype.relocateActorJoin = function (
|
|
6285
|
+
this: ZLinkHostServiceRelocationRuntime,
|
|
6286
|
+
input: Parameters<ZLinkActorJoinRelocation['relocateActorJoin']>[0]
|
|
6287
|
+
): ReturnType<ZLinkActorJoinRelocation['relocateActorJoin']> {
|
|
6288
|
+
return trackDiagnosticCompletion(
|
|
6289
|
+
relocateActorJoin.call(this, input),
|
|
6290
|
+
`relocation join actor:${input.state.actorId}`
|
|
6291
|
+
);
|
|
6292
|
+
};
|
|
6293
|
+
}
|