@zlink-systems/framework 0.21.0 → 0.23.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/.tsbuildinfo +1 -1
- package/dist/contracts/Common/ZLinkMessage.js +5 -5
- package/dist/contracts/Configuration/CodecContentType.js +5 -7
- package/dist/contracts/Configuration/DiagnosticsValidation.js +1 -6
- package/dist/contracts/Configuration/EndpointNotation.js +4 -8
- package/dist/contracts/Configuration/Registration.js +14 -11
- package/dist/contracts/Configuration/RegistrationBuilders.js +32 -25
- package/dist/contracts/Configuration/RegistrationNormalizers.js +25 -26
- package/dist/contracts/Configuration/RegistrationValidators.js +36 -38
- package/dist/contracts/Configuration/SendTimeoutValidation.js +4 -4
- package/dist/contracts/Configuration/TimerRegistrationValidator.js +7 -7
- package/dist/contracts/Dispatch/ZLinkDispatchOptions.d.ts +1 -0
- package/dist/contracts/Handlers/JsonContract.js +23 -11
- package/dist/contracts/Spots/SpotKind.js +16 -8
- package/dist/contracts/Streams/IZLinkSession.d.ts +2 -1
- package/dist/location-store-integration.js +16 -16
- package/dist/nest-integration.js +17 -11
- package/dist/runtime/abort.js +9 -5
- package/dist/runtime/actors/actor-authority-payload-codec.js +12 -16
- package/dist/runtime/actors/actor-authority-publication.js +18 -17
- package/dist/runtime/actors/actor-client.js +83 -63
- package/dist/runtime/actors/actor-context.js +28 -22
- package/dist/runtime/actors/actor-creation.js +4 -3
- package/dist/runtime/actors/actor-handoff.js +89 -92
- package/dist/runtime/actors/actor-join-deferred-scope.d.ts +0 -1
- package/dist/runtime/actors/actor-join-deferred-scope.js +0 -18
- package/dist/runtime/actors/actor-local-native-join.js +18 -19
- package/dist/runtime/actors/actor-mailbox.js +1 -1
- package/dist/runtime/actors/actor-message-follow-context.js +24 -21
- package/dist/runtime/actors/actor-packet-relay-wire.js +1 -3
- package/dist/runtime/actors/actor-remote-joiner.js +20 -17
- package/dist/runtime/actors/actor-remote-wire.js +6 -7
- package/dist/runtime/actors/actor-runtime-state.js +87 -81
- package/dist/runtime/actors/actor-transfer-registry.js +3 -5
- package/dist/runtime/actors/bound-session-wire.js +14 -9
- package/dist/runtime/actors/deferred-join-accepted-journal.js +160 -130
- package/dist/runtime/actors/index.js +2 -5
- package/dist/runtime/actors/post-commit-actor-binder.js +3 -6
- package/dist/runtime/actors/post-commit-actor-location.js +1 -1
- package/dist/runtime/actors/spot-actor-dispatch.js +5 -5
- package/dist/runtime/actors/transferred-actor-rollback.js +4 -4
- package/dist/runtime/admission.js +2 -6
- package/dist/runtime/application-jobs/application-ingress-record-owner.js +2 -6
- package/dist/runtime/application-jobs/receive-flow-controller.js +11 -12
- package/dist/runtime/backend/contracts/index.d.ts +1 -0
- package/dist/runtime/backend/mesh-completion-table.js +1 -3
- package/dist/runtime/backend/mesh-dispatch-pump.js +12 -16
- package/dist/runtime/backend/node/node-backend-adapter-factory.js +1 -3
- package/dist/runtime/backend/node/node-backend-adapter-support.js +26 -17
- package/dist/runtime/backend/node/node-mesh-backend-adapter.js +4 -3
- package/dist/runtime/backend/node/node-raw-binding-port.js +7 -6
- package/dist/runtime/backend/node/node-raw-mesh-backend.d.ts +3 -0
- package/dist/runtime/backend/node/node-raw-mesh-backend.js +134 -118
- package/dist/runtime/backend/node/node-socket-backend-adapter.js +12 -13
- package/dist/runtime/backend/runtime-message.js +3 -3
- package/dist/runtime/backend/runtime-values.d.ts +2 -2
- package/dist/runtime/backend/runtime-values.js +4 -5
- package/dist/runtime/channels/channel-clients.js +27 -24
- package/dist/runtime/channels/channel-dispatch-pipeline.js +12 -20
- package/dist/runtime/channels/channel-dispatch-services.js +7 -4
- package/dist/runtime/channels/channel-dispatchers.js +9 -9
- package/dist/runtime/channels/channel-envelope-inspection.js +16 -13
- package/dist/runtime/channels/channel-envelope.js +83 -47
- package/dist/runtime/channels/channel-outbound-operations.js +8 -8
- package/dist/runtime/channels/channel-receive-loops.js +20 -22
- package/dist/runtime/channels/channel-receive-task-tracker.js +1 -1
- package/dist/runtime/channels/channel-runtime-lifecycle.js +61 -56
- package/dist/runtime/channels/channel-runtime-manager.js +18 -9
- package/dist/runtime/channels/channel-socket-registry.js +126 -123
- package/dist/runtime/channels/channel-transports.js +46 -42
- package/dist/runtime/channels/client-server-location-runtime.js +32 -40
- package/dist/runtime/channels/client-server-service-wire.js +29 -22
- package/dist/runtime/channels/dispatch-error-reporter.d.ts +1 -0
- package/dist/runtime/channels/dispatch-error-reporter.js +9 -39
- package/dist/runtime/channels/fanout-location-runtime.js +34 -47
- package/dist/runtime/channels/fanout-service-wire.js +3 -5
- package/dist/runtime/channels/local-spot-route-transport.js +7 -1
- package/dist/runtime/channels/route-member-snapshot.js +3 -3
- package/dist/runtime/channels/source-spot-router.js +6 -2
- package/dist/runtime/channels/spot-route-bridge-transport.js +5 -2
- package/dist/runtime/channels/spot-route-dispatch-strategy.js +2 -2
- package/dist/runtime/channels/spot-route-target-resolver.js +6 -6
- package/dist/runtime/diagnostics/dispatch-error-details.d.ts +6 -0
- package/dist/runtime/diagnostics/dispatch-error-details.js +55 -0
- package/dist/runtime/diagnostics/flow-context.d.ts +2 -1
- package/dist/runtime/diagnostics/flow-context.js +2 -2
- package/dist/runtime/diagnostics/index.js +38 -10
- package/dist/runtime/diagnostics/message-flow.js +58 -42
- package/dist/runtime/diagnostics/runtime-metrics.js +18 -9
- package/dist/runtime/diagnostics/runtime-observation-queue.js +8 -10
- package/dist/runtime/diagnostics/topology-runtime-projections.js +17 -10
- package/dist/runtime/execution/index.js +7 -6
- package/dist/runtime/execution/serial-execution-queue.js +12 -18
- package/dist/runtime/execution/state-lane.js +2 -2
- package/dist/runtime/foundation/actor-join-recovery-codec.js +31 -27
- package/dist/runtime/foundation/event-loop-resources.js +4 -4
- package/dist/runtime/foundation/message-follow-suppression-registry.js +4 -4
- package/dist/runtime/foundation/raw-service-mesh-runtime.d.ts +4 -2
- package/dist/runtime/foundation/raw-service-mesh-runtime.js +169 -144
- package/dist/runtime/foundation/route-mesh-connection-policy.js +4 -4
- package/dist/runtime/foundation/runtime-state-projections.js +22 -11
- package/dist/runtime/foundation/service-authority-payload-codec.js +13 -15
- package/dist/runtime/foundation/service-discovery-registry.js +35 -33
- package/dist/runtime/foundation/service-instance-activation-recovery-codec.js +20 -22
- package/dist/runtime/foundation/service-liveness-registry.js +16 -12
- package/dist/runtime/foundation/service-maintenance-runtime.js +2 -4
- package/dist/runtime/foundation/service-relocation-aggregate-committer.js +24 -24
- package/dist/runtime/foundation/service-relocation-object-owner.js +6 -6
- package/dist/runtime/foundation/service-relocation-runtime.js +137 -94
- package/dist/runtime/foundation/service-runtime-contracts.js +5 -5
- package/dist/runtime/foundation/service-session-binding-ingress-port.d.ts +1 -0
- package/dist/runtime/foundation/service-stateful-registry.js +24 -23
- package/dist/runtime/foundation/service-stateful-runtime.d.ts +4 -0
- package/dist/runtime/foundation/service-stateful-runtime.js +461 -439
- package/dist/runtime/foundation/service-stateful-wire-codec.js +95 -98
- package/dist/runtime/foundation/service-topology-registry.d.ts +1 -0
- package/dist/runtime/foundation/service-topology-registry.js +105 -96
- package/dist/runtime/foundation/service-weighted-selection.js +6 -11
- package/dist/runtime/foundation/service-wire-binary-primitives.js +5 -6
- package/dist/runtime/foundation/service-wire-m6a-codec.js +46 -35
- package/dist/runtime/framework-errors-internal.js +7 -10
- package/dist/runtime/handlers/handler-instance-scope.js +4 -5
- package/dist/runtime/handlers/index.js +3 -1
- package/dist/runtime/host/actor-packet-relay.js +74 -70
- package/dist/runtime/host/actor-placement-coordinator.js +29 -31
- package/dist/runtime/host/actor-runtime-options-factory.js +12 -14
- package/dist/runtime/host/actor-transfer-authority-runtime.js +7 -9
- package/dist/runtime/host/actor-transfer-runtime.js +176 -153
- package/dist/runtime/host/application-job-queue.js +18 -22
- package/dist/runtime/host/bound-session-relay.js +3 -1
- package/dist/runtime/host/channel-runtime-options-factory.js +31 -14
- package/dist/runtime/host/host-capacity-status.js +8 -4
- package/dist/runtime/host/index.js +245 -228
- package/dist/runtime/host/instance-activation-authority.js +93 -96
- package/dist/runtime/host/location-runtime-owner.js +16 -14
- package/dist/runtime/host/mesh-router-resolver.js +11 -13
- package/dist/runtime/host/relocation-direct-transfer.js +10 -9
- package/dist/runtime/host/remote-actor-join-receiver.js +20 -15
- package/dist/runtime/host/remote-actor-packet-target-store.js +18 -22
- package/dist/runtime/host/remote-bound-session-relay.js +97 -73
- package/dist/runtime/host/route-mesh-runtime.js +64 -69
- package/dist/runtime/host/runtime-shutdown.js +1 -2
- package/dist/runtime/host/service-relocation-host-runtime.js +586 -511
- package/dist/runtime/host/spot-address-transport.js +69 -71
- package/dist/runtime/host/spot-runtime-options-factory.js +30 -29
- package/dist/runtime/host/stateful-authority-route-runtime.js +65 -68
- package/dist/runtime/host/user-spot-creation-coordinator.js +61 -67
- package/dist/runtime/locations/actor-location-claims.js +26 -20
- package/dist/runtime/locations/aggregate-inventory-store.js +72 -75
- package/dist/runtime/locations/authority-key-codec.js +7 -7
- package/dist/runtime/locations/auto-connect-loop.js +3 -3
- package/dist/runtime/locations/auto-connect-planner.js +25 -19
- package/dist/runtime/locations/auto-connect-reconciler.js +51 -31
- package/dist/runtime/locations/in-memory-authority-store.js +128 -118
- package/dist/runtime/locations/in-memory-location-store.js +195 -168
- package/dist/runtime/locations/in-memory-provider-location-store.js +8 -10
- package/dist/runtime/locations/key-codec.js +1 -1
- package/dist/runtime/locations/lease-tracker.js +23 -21
- package/dist/runtime/locations/lifecycle.js +4 -5
- package/dist/runtime/locations/location-store-repository.js +368 -324
- package/dist/runtime/locations/opaque-record-key.js +2 -2
- package/dist/runtime/locations/resolvers.js +73 -82
- package/dist/runtime/locations/runtime.js +68 -63
- package/dist/runtime/locations/spot-location-claims.js +39 -35
- package/dist/runtime/messaging/framework-json-v1.js +7 -7
- package/dist/runtime/messaging/packet-name.js +7 -6
- package/dist/runtime/messaging/payload-codec.js +21 -18
- package/dist/runtime/protocol/service_wire_codec.generated.d.ts +30 -2
- package/dist/runtime/protocol/service_wire_codec.generated.js +1671 -234
- package/dist/runtime/protocol/service_wire_pilot_codec.generated.js +20 -18
- package/dist/runtime/routing-id.js +3 -5
- package/dist/runtime/spots/formal-remote-actor-admission-registry.js +35 -31
- package/dist/runtime/spots/formal-remote-actor-transfer-registry.js +1 -2
- package/dist/runtime/spots/index.js +209 -220
- package/dist/runtime/spots/spot-activation-registry.js +15 -14
- package/dist/runtime/spots/spot-activation-state.js +17 -15
- package/dist/runtime/spots/spot-activation.js +33 -16
- package/dist/runtime/spots/spot-actor-admission-coordinator.js +18 -15
- package/dist/runtime/spots/spot-actor-membership.js +1 -3
- package/dist/runtime/spots/spot-actor-packet-dispatch.d.ts +2 -1
- package/dist/runtime/spots/spot-actor-packet-dispatch.js +29 -21
- package/dist/runtime/spots/spot-actor-packet-drain.js +14 -10
- package/dist/runtime/spots/spot-actor-packet-relay-dispatch.js +10 -6
- package/dist/runtime/spots/spot-closing.js +3 -7
- package/dist/runtime/spots/spot-context.js +2 -2
- package/dist/runtime/spots/spot-entry-activation.js +13 -14
- package/dist/runtime/spots/spot-handle.js +6 -3
- package/dist/runtime/spots/spot-handler-registry.js +12 -12
- package/dist/runtime/spots/spot-manager-public.js +5 -6
- package/dist/runtime/spots/spot-native-actor-join-admission.js +4 -3
- package/dist/runtime/spots/spot-node-autoconnect.js +15 -18
- package/dist/runtime/spots/spot-node-runtime-manager.js +79 -86
- package/dist/runtime/spots/spot-outbound.js +10 -14
- package/dist/runtime/spots/spot-remote-codec.js +22 -26
- package/dist/runtime/spots/spot-remote-route-codec.js +5 -7
- package/dist/runtime/spots/spot-route-packet-dispatch.js +17 -15
- package/dist/runtime/spots/spot-route-replies.js +4 -6
- package/dist/runtime/spots/spot-routed-actor-admission.js +9 -7
- package/dist/runtime/spots/spot-routed-bound-session-dispatch.js +2 -3
- package/dist/runtime/spots/spot-routed-frame-dispatch.js +5 -5
- package/dist/runtime/spots/spot-routed-spot-packet-dispatch.js +14 -10
- package/dist/runtime/spots/spot-serial-executor.js +5 -8
- package/dist/runtime/spots/spot-serial-turn-executor.js +4 -6
- package/dist/runtime/spots/spot-subscription-dispatch.js +6 -6
- package/dist/runtime/spots/spot-timer.js +26 -30
- package/dist/runtime/streams/actor-session-binding-registry.d.ts +21 -8
- package/dist/runtime/streams/actor-session-binding-registry.js +168 -148
- package/dist/runtime/streams/actor-session-binding-runtime-owner.d.ts +1 -0
- package/dist/runtime/streams/actor-session-lifecycle-coordinator.js +3 -1
- package/dist/runtime/streams/bound-actor-relay-sender.js +20 -17
- package/dist/runtime/streams/bound-session-response-target.js +8 -1
- package/dist/runtime/streams/bound-session-service.d.ts +1 -0
- package/dist/runtime/streams/bound-session-service.js +14 -12
- package/dist/runtime/streams/index.js +28 -20
- package/dist/runtime/streams/managed-stream.d.ts +3 -0
- package/dist/runtime/streams/managed-stream.js +52 -31
- package/dist/runtime/streams/native-fallback-bound-session.js +21 -17
- package/dist/runtime/streams/protocol.d.ts +5 -1
- package/dist/runtime/streams/protocol.js +68 -20
- package/dist/runtime/streams/session-actor-coordinator.js +37 -41
- package/dist/runtime/streams/session-context.d.ts +9 -2
- package/dist/runtime/streams/session-context.js +50 -32
- package/dist/runtime/streams/session-local-actors.d.ts +3 -1
- package/dist/runtime/streams/session-local-actors.js +17 -2
- package/dist/runtime/streams/session-provider.js +2 -2
- package/dist/runtime/streams/session-serial-executor.js +1 -2
- package/dist/runtime/streams/stream-frame-factory.d.ts +1 -1
- package/dist/runtime/streams/stream-frame-factory.js +14 -7
- package/dist/runtime/streams/stream-session-runtime.js +112 -78
- package/dist/runtime/workers/index.js +15 -4
- package/package.json +3 -3
- package/src/contracts/Channels/RouteCalls.ts +6 -1
- package/src/contracts/Common/ZLinkMessage.ts +5 -5
- package/src/contracts/Common/ZLinkMessageMetadata.ts +4 -3
- package/src/contracts/Configuration/Builders.ts +14 -14
- package/src/contracts/Configuration/CodecContentType.ts +8 -10
- package/src/contracts/Configuration/DiagnosticsValidation.ts +1 -6
- package/src/contracts/Configuration/EndpointNotation.ts +11 -11
- package/src/contracts/Configuration/ObjectRoles.ts +1 -3
- package/src/contracts/Configuration/Registration.ts +46 -17
- package/src/contracts/Configuration/RegistrationBuilderPolicy.ts +10 -8
- package/src/contracts/Configuration/RegistrationBuilders.ts +107 -96
- package/src/contracts/Configuration/RegistrationCodecRegistry.ts +9 -3
- package/src/contracts/Configuration/RegistrationNormalizers.ts +116 -84
- package/src/contracts/Configuration/RegistrationTypes.ts +21 -25
- package/src/contracts/Configuration/RegistrationValidators.ts +122 -73
- package/src/contracts/Configuration/RouteChannelInternalState.ts +1 -4
- package/src/contracts/Configuration/RuntimeEndpointConnections.ts +4 -1
- package/src/contracts/Configuration/SendTimeoutValidation.ts +6 -4
- package/src/contracts/Configuration/TimerRegistrationValidator.ts +8 -13
- package/src/contracts/Dispatch/ZLinkDispatchOptions.ts +2 -6
- package/src/contracts/Errors/index.ts +1 -4
- package/src/contracts/Handlers/Attributes.ts +15 -9
- package/src/contracts/Handlers/IZLinkChannelHandlers.ts +24 -4
- package/src/contracts/Handlers/JsonContract.ts +53 -19
- package/src/contracts/Locations/ActorTransfer.ts +1 -5
- package/src/contracts/Locations/Authority.ts +4 -11
- package/src/contracts/Locations/Keys.ts +6 -1
- package/src/contracts/Locations/Options.ts +3 -2
- package/src/contracts/Locations/RelocationStore.ts +1 -4
- package/src/contracts/Locations/Resolvers.ts +5 -5
- package/src/contracts/Locations/RuntimeQuery.ts +6 -2
- package/src/contracts/Locations/Stores.ts +1 -2
- package/src/contracts/Locations/index.ts +2 -8
- package/src/contracts/RouteMesh/Contracts.ts +1 -7
- package/src/contracts/RouteMesh/RuntimeTopology.ts +1 -4
- package/src/contracts/Spots/Contracts.ts +2 -8
- package/src/contracts/Spots/SpotKind.ts +16 -8
- package/src/contracts/Spots/ZLinkSpot.ts +8 -11
- package/src/contracts/Streams/IZLinkSession.ts +2 -2
- package/src/contracts/Streams/IZLinkSessionActor.ts +5 -1
- package/src/contracts/Streams/IZLinkSessionPacketHandler.ts +5 -1
- package/src/internal.ts +5 -4
- package/src/location-store-integration.ts +24 -16
- package/src/nest-integration.ts +40 -25
- package/src/runtime/abort.ts +10 -4
- package/src/runtime/actors/actor-authority-payload-codec.ts +20 -29
- package/src/runtime/actors/actor-authority-publication.ts +92 -77
- package/src/runtime/actors/actor-client.ts +162 -133
- package/src/runtime/actors/actor-context.ts +142 -134
- package/src/runtime/actors/actor-creation.ts +47 -44
- package/src/runtime/actors/actor-execution-context.ts +6 -4
- package/src/runtime/actors/actor-handoff.ts +269 -293
- package/src/runtime/actors/actor-join-deferred-scope.ts +1 -32
- package/src/runtime/actors/actor-lifecycle-snapshot.ts +5 -8
- package/src/runtime/actors/actor-local-native-join.ts +131 -159
- package/src/runtime/actors/actor-mailbox.ts +16 -19
- package/src/runtime/actors/actor-message-follow-context.ts +46 -36
- package/src/runtime/actors/actor-packet-relay-wire.ts +32 -21
- package/src/runtime/actors/actor-remote-joiner.ts +50 -54
- package/src/runtime/actors/actor-remote-wire.ts +9 -13
- package/src/runtime/actors/actor-routed-join-transport.ts +10 -2
- package/src/runtime/actors/actor-runtime-contracts.ts +2 -5
- package/src/runtime/actors/actor-runtime-state.ts +127 -124
- package/src/runtime/actors/actor-transfer-registry.ts +9 -14
- package/src/runtime/actors/actor-transport-delivery-gate.ts +4 -6
- package/src/runtime/actors/bound-session-wire.ts +37 -17
- package/src/runtime/actors/deferred-join-accepted-journal.ts +353 -326
- package/src/runtime/actors/index.ts +43 -86
- package/src/runtime/actors/post-commit-actor-binder.ts +10 -10
- package/src/runtime/actors/post-commit-actor-location.ts +30 -23
- package/src/runtime/actors/spot-actor-dispatch.ts +78 -53
- package/src/runtime/actors/transferred-actor-rollback.ts +18 -13
- package/src/runtime/admission.ts +9 -9
- package/src/runtime/application-jobs/application-ingress-record-owner.ts +5 -15
- package/src/runtime/application-jobs/application-job-queue-handler-start-gate.ts +3 -2
- package/src/runtime/application-jobs/receive-flow-controller.ts +17 -14
- package/src/runtime/backend/contracts/index.ts +77 -52
- package/src/runtime/backend/mesh-actor-session-node-adapter.ts +4 -14
- package/src/runtime/backend/mesh-completion-table.ts +6 -9
- package/src/runtime/backend/mesh-dispatch-pump.ts +38 -30
- package/src/runtime/backend/node/node-backend-adapter-factory.ts +23 -21
- package/src/runtime/backend/node/node-backend-adapter-support.ts +36 -22
- package/src/runtime/backend/node/node-dealer-channel-client-transport.ts +59 -58
- package/src/runtime/backend/node/node-event-loop-poller.ts +2 -10
- package/src/runtime/backend/node/node-mesh-backend-adapter.ts +12 -5
- package/src/runtime/backend/node/node-monitor-backend-adapter.ts +4 -3
- package/src/runtime/backend/node/node-raw-binding-port.ts +29 -29
- package/src/runtime/backend/node/node-raw-mesh-backend.ts +370 -390
- package/src/runtime/backend/node/node-socket-backend-adapter.ts +101 -54
- package/src/runtime/backend/runtime-message.ts +5 -3
- package/src/runtime/backend/runtime-values.ts +10 -7
- package/src/runtime/channels/channel-autoconnect.ts +1 -4
- package/src/runtime/channels/channel-clients.ts +93 -73
- package/src/runtime/channels/channel-dispatch-pipeline.ts +44 -44
- package/src/runtime/channels/channel-dispatch-services.ts +51 -49
- package/src/runtime/channels/channel-dispatchers.ts +152 -96
- package/src/runtime/channels/channel-envelope-inspection.ts +20 -16
- package/src/runtime/channels/channel-envelope.ts +256 -150
- package/src/runtime/channels/channel-multipart.ts +13 -5
- package/src/runtime/channels/channel-outbound-operations.ts +37 -41
- package/src/runtime/channels/channel-receive-loops.ts +102 -98
- package/src/runtime/channels/channel-receive-task-tracker.ts +1 -1
- package/src/runtime/channels/channel-runtime-lifecycle.ts +248 -190
- package/src/runtime/channels/channel-runtime-manager.ts +63 -37
- package/src/runtime/channels/channel-socket-options.ts +3 -10
- package/src/runtime/channels/channel-socket-registry.ts +331 -273
- package/src/runtime/channels/channel-transports.ts +218 -206
- package/src/runtime/channels/client-server-location-runtime.ts +116 -100
- package/src/runtime/channels/client-server-service-wire.ts +37 -36
- package/src/runtime/channels/dispatch-error-reporter.ts +12 -47
- package/src/runtime/channels/fanout-location-runtime.ts +91 -94
- package/src/runtime/channels/fanout-service-wire.ts +5 -12
- package/src/runtime/channels/handler-filter-scope.ts +1 -4
- package/src/runtime/channels/index.ts +1 -4
- package/src/runtime/channels/local-spot-route-transport.ts +20 -5
- package/src/runtime/channels/route-member-snapshot.ts +11 -5
- package/src/runtime/channels/router-socket-spot-route-transport.ts +1 -7
- package/src/runtime/channels/source-spot-router.ts +26 -22
- package/src/runtime/channels/spot-direct-envelope.ts +10 -8
- package/src/runtime/channels/spot-node-route-transport.ts +13 -16
- package/src/runtime/channels/spot-route-bridge-transport.ts +26 -9
- package/src/runtime/channels/spot-route-dispatch-strategy.ts +40 -13
- package/src/runtime/channels/spot-route-target-resolver.ts +18 -9
- package/src/runtime/codecs/index.ts +3 -2
- package/src/runtime/diagnostics/dispatch-error-details.ts +62 -0
- package/src/runtime/diagnostics/flow-context.ts +18 -7
- package/src/runtime/diagnostics/index.ts +96 -61
- package/src/runtime/diagnostics/internal-event-contracts.ts +87 -33
- package/src/runtime/diagnostics/message-flow.ts +107 -79
- package/src/runtime/diagnostics/runtime-metrics.ts +46 -24
- package/src/runtime/diagnostics/runtime-observation-queue.ts +17 -28
- package/src/runtime/diagnostics/topology-runtime-projections.ts +62 -43
- package/src/runtime/execution/index.ts +18 -26
- package/src/runtime/execution/serial-execution-queue.ts +31 -40
- package/src/runtime/execution/state-lane.ts +2 -2
- package/src/runtime/foundation/actor-join-recovery-codec.ts +69 -55
- package/src/runtime/foundation/event-loop-resources.ts +8 -4
- package/src/runtime/foundation/message-follow-suppression-registry.ts +7 -14
- package/src/runtime/foundation/operation-identity.ts +1 -2
- package/src/runtime/foundation/operation-registry.ts +8 -2
- package/src/runtime/foundation/raw-service-mesh-runtime.ts +364 -396
- package/src/runtime/foundation/route-mesh-connection-policy.ts +7 -8
- package/src/runtime/foundation/runtime-state-projections.ts +24 -23
- package/src/runtime/foundation/service-authority-payload-codec.ts +54 -57
- package/src/runtime/foundation/service-discovery-registry.ts +67 -59
- package/src/runtime/foundation/service-instance-activation-recovery-codec.ts +28 -29
- package/src/runtime/foundation/service-liveness-registry.ts +18 -13
- package/src/runtime/foundation/service-mailbox.ts +14 -14
- package/src/runtime/foundation/service-maintenance-runtime.ts +22 -21
- package/src/runtime/foundation/service-metadata-codec.ts +2 -9
- package/src/runtime/foundation/service-relocation-aggregate-committer.ts +39 -36
- package/src/runtime/foundation/service-relocation-coordinator.ts +1 -4
- package/src/runtime/foundation/service-relocation-object-owner.ts +40 -58
- package/src/runtime/foundation/service-relocation-runtime.ts +292 -216
- package/src/runtime/foundation/service-runtime-contracts.ts +8 -8
- package/src/runtime/foundation/service-session-binding-ingress-port.ts +2 -4
- package/src/runtime/foundation/service-stateful-registry.ts +69 -59
- package/src/runtime/foundation/service-stateful-runtime.ts +1233 -1112
- package/src/runtime/foundation/service-stateful-wire-codec.ts +318 -270
- package/src/runtime/foundation/service-topology-registry.ts +170 -159
- package/src/runtime/foundation/service-weighted-selection.ts +9 -15
- package/src/runtime/foundation/service-wire-binary-primitives.ts +6 -12
- package/src/runtime/foundation/service-wire-m6a-codec.ts +69 -47
- package/src/runtime/framework-errors-internal.ts +31 -30
- package/src/runtime/handlers/handler-instance-scope.ts +18 -29
- package/src/runtime/handlers/index.ts +18 -8
- package/src/runtime/host/actor-packet-relay.ts +290 -261
- package/src/runtime/host/actor-placement-coordinator.ts +165 -150
- package/src/runtime/host/actor-runtime-options-factory.ts +89 -87
- package/src/runtime/host/actor-transfer-authority-runtime.ts +46 -38
- package/src/runtime/host/actor-transfer-runtime.ts +391 -395
- package/src/runtime/host/application-job-queue.ts +32 -48
- package/src/runtime/host/bound-session-relay.ts +7 -9
- package/src/runtime/host/channel-runtime-options-factory.ts +75 -35
- package/src/runtime/host/host-capacity-status.ts +10 -9
- package/src/runtime/host/index.ts +861 -789
- package/src/runtime/host/instance-activation-authority.ts +125 -143
- package/src/runtime/host/location-runtime-owner.ts +38 -26
- package/src/runtime/host/mesh-router-resolver.ts +30 -23
- package/src/runtime/host/relocation-direct-transfer.ts +15 -15
- package/src/runtime/host/relocation-integrity-fault-gate.ts +3 -2
- package/src/runtime/host/remote-actor-join-receiver.ts +43 -34
- package/src/runtime/host/remote-actor-packet-target-store.ts +54 -52
- package/src/runtime/host/remote-bound-session-relay.ts +274 -247
- package/src/runtime/host/route-mesh-runtime-options.ts +1 -3
- package/src/runtime/host/route-mesh-runtime.ts +227 -181
- package/src/runtime/host/runtime-shutdown.ts +4 -3
- package/src/runtime/host/service-relocation-control.ts +14 -5
- package/src/runtime/host/service-relocation-host-runtime.ts +1388 -1165
- package/src/runtime/host/spot-address-transport.ts +284 -237
- package/src/runtime/host/spot-node-runtime-options-factory.ts +14 -8
- package/src/runtime/host/spot-runtime-options-factory.ts +71 -62
- package/src/runtime/host/stateful-authority-route-runtime.ts +117 -116
- package/src/runtime/host/user-spot-creation-coordinator.ts +225 -220
- package/src/runtime/locations/actor-location-claims.ts +61 -49
- package/src/runtime/locations/actor-session-route-claims.ts +1 -4
- package/src/runtime/locations/aggregate-inventory-store.ts +105 -134
- package/src/runtime/locations/authority-key-codec.ts +13 -10
- package/src/runtime/locations/auto-connect-loop.ts +14 -11
- package/src/runtime/locations/auto-connect-planner.ts +42 -31
- package/src/runtime/locations/auto-connect-reconciler.ts +106 -63
- package/src/runtime/locations/canonical-codec.ts +3 -1
- package/src/runtime/locations/creation-operation-id.ts +4 -3
- package/src/runtime/locations/domain-store-contract.ts +13 -7
- package/src/runtime/locations/in-memory-authority-store.ts +232 -199
- package/src/runtime/locations/in-memory-location-store.ts +432 -250
- package/src/runtime/locations/in-memory-provider-location-store.ts +16 -17
- package/src/runtime/locations/internal-store-contracts.ts +95 -38
- package/src/runtime/locations/key-codec.ts +3 -4
- package/src/runtime/locations/lease-tracker.ts +36 -27
- package/src/runtime/locations/lifecycle-runtime.ts +15 -3
- package/src/runtime/locations/lifecycle.ts +33 -28
- package/src/runtime/locations/location-store-repository.ts +1329 -1185
- package/src/runtime/locations/opaque-record-key.ts +4 -9
- package/src/runtime/locations/resolvers.ts +201 -178
- package/src/runtime/locations/runtime.ts +251 -159
- package/src/runtime/locations/spot-location-claims.ts +110 -112
- package/src/runtime/messaging/creation-payload-codec.ts +4 -1
- package/src/runtime/messaging/framework-json-v1.ts +34 -15
- package/src/runtime/messaging/packet-name.ts +8 -6
- package/src/runtime/messaging/payload-codec.ts +70 -50
- package/src/runtime/messaging/submission-result.ts +6 -9
- package/src/runtime/protocol/service_wire_codec.generated.ts +1376 -159
- package/src/runtime/protocol/service_wire_pilot_codec.generated.ts +19 -18
- package/src/runtime/routing-id.ts +10 -7
- package/src/runtime/spots/formal-remote-actor-admission-registry.ts +56 -62
- package/src/runtime/spots/formal-remote-actor-transfer-registry.ts +23 -20
- package/src/runtime/spots/index.ts +595 -564
- package/src/runtime/spots/spot-activation-registry.ts +38 -34
- package/src/runtime/spots/spot-activation-state.ts +43 -51
- package/src/runtime/spots/spot-activation.ts +179 -116
- package/src/runtime/spots/spot-actor-admission-coordinator.ts +110 -78
- package/src/runtime/spots/spot-actor-join-dispatch.ts +57 -41
- package/src/runtime/spots/spot-actor-lifecycle-drain.ts +5 -7
- package/src/runtime/spots/spot-actor-membership.ts +25 -27
- package/src/runtime/spots/spot-actor-packet-dispatch.ts +196 -148
- package/src/runtime/spots/spot-actor-packet-drain.ts +56 -42
- package/src/runtime/spots/spot-actor-packet-relay-dispatch.ts +37 -39
- package/src/runtime/spots/spot-closing.ts +11 -12
- package/src/runtime/spots/spot-context.ts +46 -26
- package/src/runtime/spots/spot-entry-activation.ts +84 -65
- package/src/runtime/spots/spot-handle.ts +17 -15
- package/src/runtime/spots/spot-handler-registry.ts +44 -31
- package/src/runtime/spots/spot-location-claim.ts +5 -4
- package/src/runtime/spots/spot-manager-public.ts +62 -82
- package/src/runtime/spots/spot-native-actor-join-admission.ts +20 -16
- package/src/runtime/spots/spot-node-autoconnect.ts +54 -61
- package/src/runtime/spots/spot-node-runtime-manager.ts +235 -222
- package/src/runtime/spots/spot-outbound.ts +47 -59
- package/src/runtime/spots/spot-publisher-transport.ts +5 -4
- package/src/runtime/spots/spot-remote-codec.ts +66 -65
- package/src/runtime/spots/spot-remote-route-codec.ts +61 -41
- package/src/runtime/spots/spot-route-packet-dispatch.ts +129 -95
- package/src/runtime/spots/spot-route-replies.ts +23 -24
- package/src/runtime/spots/spot-route-reply-wire.ts +3 -2
- package/src/runtime/spots/spot-routed-actor-admission.ts +37 -27
- package/src/runtime/spots/spot-routed-bound-session-dispatch.ts +13 -18
- package/src/runtime/spots/spot-routed-frame-dispatch.ts +18 -15
- package/src/runtime/spots/spot-routed-spot-packet-dispatch.ts +35 -26
- package/src/runtime/spots/spot-routing-internal.ts +1 -4
- package/src/runtime/spots/spot-runtime-ports.ts +5 -5
- package/src/runtime/spots/spot-serial-executor.ts +5 -9
- package/src/runtime/spots/spot-serial-turn-executor.ts +19 -26
- package/src/runtime/spots/spot-subscription-dispatch.ts +58 -47
- package/src/runtime/spots/spot-timer.ts +103 -91
- package/src/runtime/streams/actor-session-binding-registry.ts +421 -292
- package/src/runtime/streams/actor-session-binding-runtime-owner.ts +8 -4
- package/src/runtime/streams/actor-session-lifecycle-coordinator.ts +3 -1
- package/src/runtime/streams/bound-actor-relay-sender.ts +60 -50
- package/src/runtime/streams/bound-session-response-target.ts +39 -9
- package/src/runtime/streams/bound-session-service.ts +52 -42
- package/src/runtime/streams/index.ts +183 -100
- package/src/runtime/streams/managed-stream.ts +123 -90
- package/src/runtime/streams/native-fallback-bound-session.ts +57 -52
- package/src/runtime/streams/protocol.ts +115 -46
- package/src/runtime/streams/session-actor-coordinator.ts +109 -93
- package/src/runtime/streams/session-calls.ts +2 -8
- package/src/runtime/streams/session-context.ts +96 -51
- package/src/runtime/streams/session-local-actors.ts +19 -3
- package/src/runtime/streams/session-provider.ts +5 -7
- package/src/runtime/streams/session-serial-executor.ts +7 -6
- package/src/runtime/streams/stream-binding-runtime-ports.ts +79 -29
- package/src/runtime/streams/stream-frame-factory.ts +59 -40
- package/src/runtime/streams/stream-session-runtime.ts +317 -214
- package/src/runtime/workers/index.ts +68 -29
|
@@ -7,6 +7,7 @@ const abort_1 = require("../abort");
|
|
|
7
7
|
const execution_1 = require("../execution");
|
|
8
8
|
const framework_errors_internal_1 = require("../framework-errors-internal");
|
|
9
9
|
const runtime_values_1 = require("../backend/runtime-values");
|
|
10
|
+
const ZLinkDispatchOptions_1 = require("../../contracts/Dispatch/ZLinkDispatchOptions");
|
|
10
11
|
const service_runtime_contracts_1 = require("./service-runtime-contracts");
|
|
11
12
|
const message_follow_suppression_registry_1 = require("./message-follow-suppression-registry");
|
|
12
13
|
const service_stateful_registry_1 = require("./service-stateful-registry");
|
|
@@ -81,6 +82,8 @@ class ServiceStatefulRuntime {
|
|
|
81
82
|
userSpotOperationHandler;
|
|
82
83
|
messageFollowHandler;
|
|
83
84
|
mailboxDropHandler;
|
|
85
|
+
dispatchErrors;
|
|
86
|
+
dispatchErrorMeshName;
|
|
84
87
|
admittedUserSpotOperations = new Map();
|
|
85
88
|
pendingInstanceActivations = new Map();
|
|
86
89
|
closed = false;
|
|
@@ -90,11 +93,15 @@ class ServiceStatefulRuntime {
|
|
|
90
93
|
this.nodeGeneration = nodeGeneration;
|
|
91
94
|
this.registry = new service_stateful_registry_1.ServiceStatefulRegistry(nodeRid, nodeGeneration);
|
|
92
95
|
this.registry.createEntrySpot(nodeRid);
|
|
93
|
-
raw.setServiceIngress(record => this.ingress(record));
|
|
96
|
+
raw.setServiceIngress((record) => this.ingress(record));
|
|
94
97
|
}
|
|
95
98
|
setMailboxDropHandler(handler) {
|
|
96
99
|
this.mailboxDropHandler = handler;
|
|
97
100
|
}
|
|
101
|
+
setDispatchErrorReporter(reporter, meshName) {
|
|
102
|
+
this.dispatchErrors = reporter;
|
|
103
|
+
this.dispatchErrorMeshName = meshName;
|
|
104
|
+
}
|
|
98
105
|
createSpot(routingId, kind = 'user', stableType = kind) {
|
|
99
106
|
this.requireOpen();
|
|
100
107
|
return this.registry.createSpot(routingId ?? `spot-${this.nodeRid}-${this.nextSpotId++}`, kind, stableType);
|
|
@@ -125,15 +132,15 @@ class ServiceStatefulRuntime {
|
|
|
125
132
|
restoreActorSessionBinding(actorRef, sessionNodeRid, sessionRid, bindingGeneration) {
|
|
126
133
|
this.requireOpen();
|
|
127
134
|
const actor = this.registry.actor(actorRef.actorId);
|
|
128
|
-
if (actor === undefined
|
|
129
|
-
|
|
130
|
-
|
|
135
|
+
if (actor === undefined ||
|
|
136
|
+
actor.ref.generation !== actorRef.generation ||
|
|
137
|
+
actor.ref.nodeRid !== actorRef.nodeRid) {
|
|
131
138
|
throw new service_stateful_registry_1.ServiceStaleGenerationError('actor', actorRef.actorId);
|
|
132
139
|
}
|
|
133
140
|
const current = this.registry.binding(actor.ref);
|
|
134
|
-
if (current?.bindingGeneration === bindingGeneration
|
|
135
|
-
|
|
136
|
-
|
|
141
|
+
if (current?.bindingGeneration === bindingGeneration &&
|
|
142
|
+
current.sessionOwnerNodeRid === sessionNodeRid &&
|
|
143
|
+
current.sessionRid === sessionRid) {
|
|
137
144
|
return;
|
|
138
145
|
}
|
|
139
146
|
this.registry.installSessionBinding({
|
|
@@ -172,7 +179,8 @@ class ServiceStatefulRuntime {
|
|
|
172
179
|
};
|
|
173
180
|
}
|
|
174
181
|
registerInstanceIntent(instanceType, route, expectedCurrentRoute) {
|
|
175
|
-
if (route.targetNodeRid !== this.nodeRid ||
|
|
182
|
+
if (route.targetNodeRid !== this.nodeRid ||
|
|
183
|
+
route.targetNodeGeneration !== this.nodeGeneration) {
|
|
176
184
|
throw new service_stateful_registry_1.ServiceStaleGenerationError('spot', route.targetSpotId);
|
|
177
185
|
}
|
|
178
186
|
const current = this.instanceIntents.get(route.targetSpotId);
|
|
@@ -209,10 +217,10 @@ class ServiceStatefulRuntime {
|
|
|
209
217
|
instanceSpotApplicationTarget(spotId) {
|
|
210
218
|
const intent = this.instanceIntents.get(spotId);
|
|
211
219
|
const spot = this.registry.spot(spotId);
|
|
212
|
-
if (intent === undefined
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
220
|
+
if (intent === undefined ||
|
|
221
|
+
spot?.kind !== 'instance' ||
|
|
222
|
+
spot.state !== 'ready' ||
|
|
223
|
+
spot.ref.generation !== intent.route.objectGeneration) {
|
|
216
224
|
return undefined;
|
|
217
225
|
}
|
|
218
226
|
return {
|
|
@@ -222,25 +230,24 @@ class ServiceStatefulRuntime {
|
|
|
222
230
|
}
|
|
223
231
|
forgetInstanceIntent(spotId, objectGeneration, authorityOwnerGeneration, storeVersion) {
|
|
224
232
|
const current = this.instanceIntents.get(spotId);
|
|
225
|
-
if (current?.route.objectGeneration === objectGeneration
|
|
226
|
-
|
|
227
|
-
|
|
233
|
+
if (current?.route.objectGeneration === objectGeneration &&
|
|
234
|
+
current.route.authorityOwnerGeneration === authorityOwnerGeneration &&
|
|
235
|
+
(storeVersion === undefined || current.route.storeVersion === storeVersion)) {
|
|
228
236
|
this.instanceIntents.delete(spotId);
|
|
229
237
|
}
|
|
230
238
|
}
|
|
231
239
|
registerInstanceActivationAuthority(authority) {
|
|
232
240
|
this.requireOpen();
|
|
233
|
-
if (this.asyncInstanceAuthority !== undefined
|
|
234
|
-
|
|
241
|
+
if (this.asyncInstanceAuthority !== undefined ||
|
|
242
|
+
(this.instanceAuthority !== undefined && this.instanceAuthority !== authority)) {
|
|
235
243
|
throw new Error('Instance activation authority is already registered.');
|
|
236
244
|
}
|
|
237
245
|
this.instanceAuthority = authority;
|
|
238
246
|
}
|
|
239
247
|
registerAsyncInstanceActivationAuthority(authority) {
|
|
240
248
|
this.requireOpen();
|
|
241
|
-
if (this.instanceAuthority !== undefined
|
|
242
|
-
|
|
243
|
-
&& this.asyncInstanceAuthority !== authority) {
|
|
249
|
+
if (this.instanceAuthority !== undefined ||
|
|
250
|
+
(this.asyncInstanceAuthority !== undefined && this.asyncInstanceAuthority !== authority)) {
|
|
244
251
|
throw new Error('Instance activation authority is already registered.');
|
|
245
252
|
}
|
|
246
253
|
this.asyncInstanceAuthority = authority;
|
|
@@ -253,8 +260,7 @@ class ServiceStatefulRuntime {
|
|
|
253
260
|
}
|
|
254
261
|
registerUserSpotOperationHandler(handler) {
|
|
255
262
|
this.requireOpen();
|
|
256
|
-
if (this.userSpotOperationHandler !== undefined
|
|
257
|
-
&& this.userSpotOperationHandler !== handler) {
|
|
263
|
+
if (this.userSpotOperationHandler !== undefined && this.userSpotOperationHandler !== handler) {
|
|
258
264
|
throw new Error('User Spot operation handler is already registered.');
|
|
259
265
|
}
|
|
260
266
|
this.userSpotOperationHandler = handler;
|
|
@@ -301,11 +307,11 @@ class ServiceStatefulRuntime {
|
|
|
301
307
|
const target = envelope.target;
|
|
302
308
|
if (!matchesExpectedInstanceRoute(this.instanceIntents.get(target.targetSpotId)?.route, expectedCurrentRoute))
|
|
303
309
|
return false;
|
|
304
|
-
if (target.targetNodeRid !== this.nodeRid
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
310
|
+
if (target.targetNodeRid !== this.nodeRid ||
|
|
311
|
+
target.targetNodeGeneration !== this.nodeGeneration ||
|
|
312
|
+
target.targetSpotId !== route.targetSpotId ||
|
|
313
|
+
route.targetNodeRid !== this.nodeRid ||
|
|
314
|
+
route.targetNodeGeneration !== this.nodeGeneration) {
|
|
309
315
|
throw new service_stateful_registry_1.ServiceStaleGenerationError('spot', target.targetSpotId);
|
|
310
316
|
}
|
|
311
317
|
const authority = this.asyncInstanceAuthority;
|
|
@@ -317,15 +323,15 @@ class ServiceStatefulRuntime {
|
|
|
317
323
|
}
|
|
318
324
|
async finishRecoveredInstanceActivation(envelope, route, expectedCurrentRoute) {
|
|
319
325
|
const target = envelope.target;
|
|
320
|
-
const spot = this.registry.spot(target.targetSpotId)
|
|
321
|
-
|
|
326
|
+
const spot = this.registry.spot(target.targetSpotId) ??
|
|
327
|
+
this.registry.restoreSpot({
|
|
322
328
|
spotId: target.targetSpotId,
|
|
323
329
|
generation: route.objectGeneration
|
|
324
330
|
}, 'instance', target.stableType, route.authorityOwnerGeneration);
|
|
325
|
-
if (spot.kind !== 'instance'
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
331
|
+
if (spot.kind !== 'instance' ||
|
|
332
|
+
spot.stableType !== target.stableType ||
|
|
333
|
+
spot.ref.generation !== route.objectGeneration ||
|
|
334
|
+
spot.authorityOwnerGeneration !== route.authorityOwnerGeneration) {
|
|
329
335
|
throw new service_stateful_registry_1.ServiceStaleGenerationError('spot', target.targetSpotId);
|
|
330
336
|
}
|
|
331
337
|
if (!matchesExpectedInstanceRoute(this.instanceIntents.get(target.targetSpotId)?.route, expectedCurrentRoute))
|
|
@@ -337,9 +343,7 @@ class ServiceStatefulRuntime {
|
|
|
337
343
|
target,
|
|
338
344
|
sourceNodeGeneration: envelope.sourceNodeGeneration,
|
|
339
345
|
sourceNodeRid: envelope.sourceNodeRid,
|
|
340
|
-
...(envelope.sourceSpotId === undefined
|
|
341
|
-
? {}
|
|
342
|
-
: { sourceSpotId: envelope.sourceSpotId }),
|
|
346
|
+
...(envelope.sourceSpotId === undefined ? {} : { sourceSpotId: envelope.sourceSpotId }),
|
|
343
347
|
operationKind: envelope.operationKind,
|
|
344
348
|
operation: envelope.operation,
|
|
345
349
|
deadlineUnixMs: envelope.deadlineUnixMs,
|
|
@@ -371,11 +375,11 @@ class ServiceStatefulRuntime {
|
|
|
371
375
|
const target = envelope.target;
|
|
372
376
|
if (!matchesExpectedInstanceRoute(this.instanceIntents.get(target.targetSpotId)?.route, expectedCurrentRoute))
|
|
373
377
|
return false;
|
|
374
|
-
if (target.targetNodeRid !== this.nodeRid
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
378
|
+
if (target.targetNodeRid !== this.nodeRid ||
|
|
379
|
+
target.targetNodeGeneration !== this.nodeGeneration ||
|
|
380
|
+
pending.nodeRid !== this.nodeRid ||
|
|
381
|
+
pending.nodeGeneration !== this.nodeGeneration ||
|
|
382
|
+
pending.meshName !== envelope.targetMeshName) {
|
|
379
383
|
throw new service_stateful_registry_1.ServiceStaleGenerationError('spot', target.targetSpotId);
|
|
380
384
|
}
|
|
381
385
|
const authority = this.asyncInstanceAuthority;
|
|
@@ -408,12 +412,11 @@ class ServiceStatefulRuntime {
|
|
|
408
412
|
return undefined;
|
|
409
413
|
if (currentRoute !== undefined && !sameInstanceRoute(currentRoute, route))
|
|
410
414
|
return undefined;
|
|
411
|
-
const authorityReleased = await this.instanceApplicationLifecycle?.completeTerminal({
|
|
415
|
+
const authorityReleased = (await this.instanceApplicationLifecycle?.completeTerminal({
|
|
412
416
|
targetSpotId: target.targetSpotId,
|
|
413
417
|
stableType: target.stableType,
|
|
414
418
|
objectGeneration: route.objectGeneration
|
|
415
|
-
})
|
|
416
|
-
?? false;
|
|
419
|
+
})) ?? false;
|
|
417
420
|
if (!authorityReleased) {
|
|
418
421
|
if (currentRoute === undefined) {
|
|
419
422
|
this.publishCommittedInstanceRoute(target.stableType, released, null);
|
|
@@ -429,8 +432,8 @@ class ServiceStatefulRuntime {
|
|
|
429
432
|
}
|
|
430
433
|
waitForInstanceApplicationQuiescence(spotId, signal) {
|
|
431
434
|
const key = String(spotId);
|
|
432
|
-
if ((this.pendingInstanceTerminals.get(key) ?? 0) === 0
|
|
433
|
-
|
|
435
|
+
if ((this.pendingInstanceTerminals.get(key) ?? 0) === 0 &&
|
|
436
|
+
(this.pendingInstanceAuthorityTerminals.get(key) ?? 0) === 0) {
|
|
434
437
|
return Promise.resolve();
|
|
435
438
|
}
|
|
436
439
|
if (signal?.aborted === true) {
|
|
@@ -475,8 +478,8 @@ class ServiceStatefulRuntime {
|
|
|
475
478
|
this.spotRoutes.set(spotKey(route.spot), current);
|
|
476
479
|
return;
|
|
477
480
|
}
|
|
478
|
-
if (expectedCurrentRoute !== undefined
|
|
479
|
-
|
|
481
|
+
if (expectedCurrentRoute !== undefined &&
|
|
482
|
+
!matchesExpectedDirectSpotRoute(current, expectedCurrentRoute))
|
|
480
483
|
return;
|
|
481
484
|
if (current !== undefined) {
|
|
482
485
|
if (current.spot.generation < route.spot.generation) {
|
|
@@ -519,8 +522,8 @@ class ServiceStatefulRuntime {
|
|
|
519
522
|
}
|
|
520
523
|
sealSpotMessageFollowIngress(source) {
|
|
521
524
|
this.requireOpen();
|
|
522
|
-
if (source.targetNodeRid !== this.nodeRid
|
|
523
|
-
|
|
525
|
+
if (source.targetNodeRid !== this.nodeRid ||
|
|
526
|
+
source.targetNodeGeneration !== this.nodeGeneration) {
|
|
524
527
|
return undefined;
|
|
525
528
|
}
|
|
526
529
|
const key = spotKey(source.spot);
|
|
@@ -569,18 +572,16 @@ class ServiceStatefulRuntime {
|
|
|
569
572
|
if (!Number.isSafeInteger(durationMs) || durationMs < 0) {
|
|
570
573
|
throw new RangeError('Message Follow duration must be a non-negative safe integer.');
|
|
571
574
|
}
|
|
572
|
-
if (target.spot.spotId !== state.source.spot.spotId
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
575
|
+
if (target.spot.spotId !== state.source.spot.spotId ||
|
|
576
|
+
target.spot.generation !== state.source.spot.generation ||
|
|
577
|
+
target.authorityOwnerGeneration <= state.source.authorityOwnerGeneration ||
|
|
578
|
+
target.targetNodeRid === this.nodeRid) {
|
|
576
579
|
throw new service_stateful_registry_1.ServiceStaleGenerationError('spot', state.source.spot.spotId);
|
|
577
580
|
}
|
|
578
581
|
state.target = freezeDirectSpotRoute(target);
|
|
579
582
|
state.suppressionFence = spotMessageFollowSuppressionFence(state.objectKind, state.source, state.target);
|
|
580
583
|
this.spotMessageFollowSuppression.retainRoute(state.suppressionFence);
|
|
581
|
-
state.expiresAtMs = durationMs === 0
|
|
582
|
-
? Number.MAX_SAFE_INTEGER
|
|
583
|
-
: performance.now() + durationMs;
|
|
584
|
+
state.expiresAtMs = durationMs === 0 ? Number.MAX_SAFE_INTEGER : performance.now() + durationMs;
|
|
584
585
|
await this.drainSpotMessageFollow(state);
|
|
585
586
|
if (durationMs === 0)
|
|
586
587
|
this.removeSpotMessageFollow(state);
|
|
@@ -590,14 +591,14 @@ class ServiceStatefulRuntime {
|
|
|
590
591
|
const exactKey = spotKey(spot);
|
|
591
592
|
const exact = this.spotRoutes.get(exactKey);
|
|
592
593
|
const current = this.directSpotRoutes.get(directSpotKey(spot.spotId));
|
|
593
|
-
if (exact?.authorityOwnerGeneration === authorityOwnerGeneration
|
|
594
|
-
|
|
594
|
+
if (exact?.authorityOwnerGeneration === authorityOwnerGeneration &&
|
|
595
|
+
(storeVersion === undefined || exact.storeVersion === storeVersion)) {
|
|
595
596
|
this.spotRoutes.delete(exactKey);
|
|
596
597
|
}
|
|
597
598
|
const key = directSpotKey(spot.spotId);
|
|
598
|
-
if (current?.authorityOwnerGeneration === authorityOwnerGeneration
|
|
599
|
-
|
|
600
|
-
|
|
599
|
+
if (current?.authorityOwnerGeneration === authorityOwnerGeneration &&
|
|
600
|
+
current.spot.generation === spot.generation &&
|
|
601
|
+
(storeVersion === undefined || current.storeVersion === storeVersion)) {
|
|
601
602
|
this.directSpotRoutes.delete(key);
|
|
602
603
|
}
|
|
603
604
|
}
|
|
@@ -627,14 +628,34 @@ class ServiceStatefulRuntime {
|
|
|
627
628
|
}
|
|
628
629
|
async publishLogicalMulticast(channelName, topic, payload, sourceSpotId = this.nodeRid) {
|
|
629
630
|
await this.enqueueLogicalMulticast(channelName, topic, sourceSpotId, payload);
|
|
630
|
-
const targets = this.raw.topology
|
|
631
|
-
.
|
|
631
|
+
const targets = this.raw.topology
|
|
632
|
+
.peers()
|
|
633
|
+
.filter((peer) => peer.descriptor.channels.some((channel) => channel.name === channelName && channel.weight > 0) && this.raw.isPeerRouteReady(peer.descriptor.nodeRoutingId));
|
|
632
634
|
const header = (0, service_stateful_wire_codec_1.encodeLogicalMulticastHeader)(channelName, topic, sourceSpotId);
|
|
633
635
|
const payloadFrame = (0, service_wire_m6a_codec_1.encodeApplicationPayload)(payload);
|
|
636
|
+
const reporter = this.dispatchErrors;
|
|
637
|
+
const captureFailures = reporter?.captureEnabled() === true;
|
|
634
638
|
for (const target of targets) {
|
|
635
639
|
// Remote admission ends at the source outbound transport queue. The
|
|
636
640
|
// receiver's Spot queue and handler completion are not publish results.
|
|
637
|
-
await this.raw.sendService(target.descriptor.nodeRoutingId, [
|
|
641
|
+
const accepted = await this.raw.sendService(target.descriptor.nodeRoutingId, [
|
|
642
|
+
header,
|
|
643
|
+
payloadFrame
|
|
644
|
+
]);
|
|
645
|
+
if (!accepted) {
|
|
646
|
+
if (captureFailures) {
|
|
647
|
+
reporter.report({
|
|
648
|
+
surface: ZLinkDispatchOptions_1.ZLinkDispatchErrorSurface.SpotRoute,
|
|
649
|
+
messageKind: ZLinkDispatchOptions_1.ZLinkDispatchMessageKind.Send,
|
|
650
|
+
reason: serviceSpotPublishFailureReason(undefined, this.raw.isPeerRouteReady(target.descriptor.nodeRoutingId), this.closed),
|
|
651
|
+
action: ZLinkDispatchOptions_1.ZLinkRuntimeDispatchErrorAction.Drop,
|
|
652
|
+
meshName: this.dispatchErrorMeshName,
|
|
653
|
+
channelName,
|
|
654
|
+
topic,
|
|
655
|
+
targetRid: target.descriptor.nodeRoutingId
|
|
656
|
+
});
|
|
657
|
+
}
|
|
658
|
+
}
|
|
638
659
|
}
|
|
639
660
|
}
|
|
640
661
|
async sendToSpot(sourceSpotId, requested, payload) {
|
|
@@ -769,7 +790,11 @@ class ServiceStatefulRuntime {
|
|
|
769
790
|
...targetSpot,
|
|
770
791
|
generation: targetSpotGeneration
|
|
771
792
|
});
|
|
772
|
-
this.submitActorJoin(pending, actor, targetNodeRid, target, request, deadlineMs, {
|
|
793
|
+
this.submitActorJoin(pending, actor, targetNodeRid, target, request, deadlineMs, {
|
|
794
|
+
request,
|
|
795
|
+
actorFence,
|
|
796
|
+
local
|
|
797
|
+
});
|
|
773
798
|
return pending;
|
|
774
799
|
}
|
|
775
800
|
joinActorEntrySpot(actor, targetNodeRid, payload, timeoutMs) {
|
|
@@ -837,7 +862,8 @@ class ServiceStatefulRuntime {
|
|
|
837
862
|
const previous = this.registry.binding(actor);
|
|
838
863
|
if (previous !== undefined && sameSessionIdentity(previous, localBinding)) {
|
|
839
864
|
const currentDelivery = this.sessionDeliveries.get(deliveryKey);
|
|
840
|
-
if (currentDelivery !== undefined &&
|
|
865
|
+
if (currentDelivery !== undefined &&
|
|
866
|
+
sameSessionBinding(currentDelivery.binding, previous)) {
|
|
841
867
|
this.sessionDeliveries.set(deliveryKey, {
|
|
842
868
|
...delivery,
|
|
843
869
|
binding: previous
|
|
@@ -868,14 +894,14 @@ class ServiceStatefulRuntime {
|
|
|
868
894
|
this.sendBoundSessionReplacement(previous, actorAuthorityFromRoute(this.tryActorFence(actor) ?? {
|
|
869
895
|
actor,
|
|
870
896
|
targetNodeGeneration: this.nodeGeneration,
|
|
871
|
-
authorityOwnerGeneration: this.registry.actor(actor.actorId)?.authorityOwnerGeneration
|
|
872
|
-
?? actor.generation,
|
|
897
|
+
authorityOwnerGeneration: this.registry.actor(actor.actorId)?.authorityOwnerGeneration ?? actor.generation,
|
|
873
898
|
ownerLeaseGeneration: this.nodeGeneration
|
|
874
899
|
}));
|
|
875
900
|
}
|
|
876
901
|
}
|
|
877
902
|
catch (error) {
|
|
878
|
-
if (installedDelivery !== undefined &&
|
|
903
|
+
if (installedDelivery !== undefined &&
|
|
904
|
+
this.sessionDeliveries.get(deliveryKey) === installedDelivery) {
|
|
879
905
|
this.sessionDeliveries.delete(deliveryKey);
|
|
880
906
|
}
|
|
881
907
|
this.operations.reply(pending.id, failure(error));
|
|
@@ -886,19 +912,21 @@ class ServiceStatefulRuntime {
|
|
|
886
912
|
let bindingActorFence;
|
|
887
913
|
let header;
|
|
888
914
|
try {
|
|
889
|
-
bindingActorFence =
|
|
890
|
-
? this.actorFence(actor)
|
|
891
|
-
|
|
892
|
-
|
|
915
|
+
bindingActorFence =
|
|
916
|
+
actorAuthority === undefined ? this.actorFence(actor) : { actor, ...actorAuthority };
|
|
917
|
+
header = (0, service_stateful_wire_codec_1.encodeBoundSessionBindHeader)(pending.id, bindingActorFence, sessionRid, {
|
|
918
|
+
state: 'active',
|
|
919
|
+
generation
|
|
920
|
+
});
|
|
893
921
|
}
|
|
894
922
|
catch (error) {
|
|
895
923
|
this.operations.fail(pending.id, error);
|
|
896
924
|
return pending;
|
|
897
925
|
}
|
|
898
|
-
void this.requestDurableOperation(actor.nodeRid, [header], pending.id, 'streamBind', deadlineMs).then(reply => this.completeRemoteReply(pending, actor.nodeRid, 'streamBind', undefined, reply), error => this.operations.fail(pending.id, error));
|
|
926
|
+
void this.requestDurableOperation(actor.nodeRid, [header], pending.id, 'streamBind', deadlineMs).then((reply) => this.completeRemoteReply(pending, actor.nodeRid, 'streamBind', undefined, reply), (error) => this.operations.fail(pending.id, error));
|
|
899
927
|
return {
|
|
900
928
|
id: pending.id,
|
|
901
|
-
promise: pending.promise.then(result => {
|
|
929
|
+
promise: pending.promise.then((result) => {
|
|
902
930
|
if (result.terminalResult === runtime_values_1.RequestResult.Ok && result.streamBinding !== undefined) {
|
|
903
931
|
const committed = {
|
|
904
932
|
...delivery,
|
|
@@ -908,10 +936,10 @@ class ServiceStatefulRuntime {
|
|
|
908
936
|
}
|
|
909
937
|
};
|
|
910
938
|
const current = this.sessionDeliveries.get(deliveryKey);
|
|
911
|
-
if (current === previousDelivery
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
939
|
+
if (current === previousDelivery ||
|
|
940
|
+
current === undefined ||
|
|
941
|
+
(sameSessionOwnerIdentity(current.binding, committed.binding) &&
|
|
942
|
+
current.binding.bindingGeneration < committed.binding.bindingGeneration)) {
|
|
915
943
|
if (current !== undefined && !sameSessionBinding(current.binding, committed.binding)) {
|
|
916
944
|
this.retiredSessionDeliveries.set(sessionDeliveryKey(current.binding), current);
|
|
917
945
|
}
|
|
@@ -929,9 +957,9 @@ class ServiceStatefulRuntime {
|
|
|
929
957
|
unbindSession(sessionRid, actor, expectedBindingGeneration, timeoutMs) {
|
|
930
958
|
const pending = this.operations.register(timeoutMs);
|
|
931
959
|
const delivery = this.sessionDeliveries.get(actorKey(actor));
|
|
932
|
-
if (delivery === undefined
|
|
933
|
-
|
|
934
|
-
|
|
960
|
+
if (delivery === undefined ||
|
|
961
|
+
delivery.binding.sessionRid !== sessionRid ||
|
|
962
|
+
delivery.binding.bindingGeneration !== expectedBindingGeneration) {
|
|
935
963
|
this.operations.reply(pending.id, {
|
|
936
964
|
terminalResult: runtime_values_1.RequestResult.NotFound,
|
|
937
965
|
failureCode: ACTOR_ROUTE_STALE
|
|
@@ -949,17 +977,20 @@ class ServiceStatefulRuntime {
|
|
|
949
977
|
}
|
|
950
978
|
return pending;
|
|
951
979
|
}
|
|
952
|
-
const header = (0, service_stateful_wire_codec_1.encodeBoundSessionBindHeader)(pending.id, this.actorFence(actor), sessionRid, {
|
|
980
|
+
const header = (0, service_stateful_wire_codec_1.encodeBoundSessionBindHeader)(pending.id, this.actorFence(actor), sessionRid, {
|
|
981
|
+
state: 'tombstone',
|
|
982
|
+
retiredGeneration: expectedBindingGeneration
|
|
983
|
+
});
|
|
953
984
|
this.submitRequest(pending, actor.nodeRid, [header], timeoutMs, 'streamUnbind');
|
|
954
985
|
return pending;
|
|
955
986
|
}
|
|
956
987
|
sessionBindings(sessionRid) {
|
|
957
988
|
return [...this.sessionDeliveries.values()]
|
|
958
|
-
.map(value => value.binding)
|
|
959
|
-
.filter(binding => binding.sessionRid === sessionRid);
|
|
989
|
+
.map((value) => value.binding)
|
|
990
|
+
.filter((binding) => binding.sessionRid === sessionRid);
|
|
960
991
|
}
|
|
961
992
|
allSessionBindings() {
|
|
962
|
-
return [...this.sessionDeliveries.values()].map(value => value.binding);
|
|
993
|
+
return [...this.sessionDeliveries.values()].map((value) => value.binding);
|
|
963
994
|
}
|
|
964
995
|
async sendSessionToActor(sessionRid, actor, payload) {
|
|
965
996
|
const delivery = this.sessionDeliveries.get(actorKey(actor));
|
|
@@ -983,7 +1014,10 @@ class ServiceStatefulRuntime {
|
|
|
983
1014
|
if (actorFence === undefined)
|
|
984
1015
|
return runtime_values_1.SubmitResult.InvalidState;
|
|
985
1016
|
const header = (0, service_stateful_wire_codec_1.encodeBoundSessionSendHeader)(actorFence, expectedBindingGeneration);
|
|
986
|
-
return this.submitOneWay(binding.sessionOwnerNodeRid, [
|
|
1017
|
+
return this.submitOneWay(binding.sessionOwnerNodeRid, [
|
|
1018
|
+
header,
|
|
1019
|
+
(0, service_wire_m6a_codec_1.encodeApplicationPayload)(payload)
|
|
1020
|
+
]);
|
|
987
1021
|
}
|
|
988
1022
|
close() {
|
|
989
1023
|
if (this.closed)
|
|
@@ -1026,19 +1060,19 @@ class ServiceStatefulRuntime {
|
|
|
1026
1060
|
// number range (30-34). They are bare infrastructure records and must
|
|
1027
1061
|
// fall through to RawServiceMeshRuntime's relocation ingress instead of
|
|
1028
1062
|
// being decoded as stateful actor/spot work.
|
|
1029
|
-
if (record.command === service_stateful_wire_codec_1.M6bServiceWireCommand.relocationReady
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1063
|
+
if (record.command === service_stateful_wire_codec_1.M6bServiceWireCommand.relocationReady ||
|
|
1064
|
+
record.command === service_stateful_wire_codec_1.M6bServiceWireCommand.relocationData ||
|
|
1065
|
+
record.command === service_stateful_wire_codec_1.M6bServiceWireCommand.replyRelay ||
|
|
1066
|
+
record.command === service_stateful_wire_codec_1.M6bServiceWireCommand.relocationCutover) {
|
|
1033
1067
|
return undefined;
|
|
1034
1068
|
}
|
|
1035
|
-
if (record.command < service_stateful_wire_codec_1.M6bServiceWireCommand.spotSend
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1069
|
+
if (record.command < service_stateful_wire_codec_1.M6bServiceWireCommand.spotSend ||
|
|
1070
|
+
(record.command > service_stateful_wire_codec_1.M6bServiceWireCommand.instanceSpot &&
|
|
1071
|
+
record.command !== service_stateful_wire_codec_1.M6bServiceWireCommand.userSpotCreate &&
|
|
1072
|
+
record.command !== service_stateful_wire_codec_1.M6bServiceWireCommand.userSpotClose &&
|
|
1073
|
+
record.command !== service_stateful_wire_codec_1.M6bServiceWireCommand.actorCreate &&
|
|
1074
|
+
record.command !== service_stateful_wire_codec_1.M6bServiceWireCommand.messageFollow &&
|
|
1075
|
+
record.command !== service_stateful_wire_codec_1.M6bServiceWireCommand.boundSessionReplaced)) {
|
|
1042
1076
|
return undefined;
|
|
1043
1077
|
}
|
|
1044
1078
|
let decoded;
|
|
@@ -1065,19 +1099,17 @@ class ServiceStatefulRuntime {
|
|
|
1065
1099
|
'actorJoin',
|
|
1066
1100
|
'boundSessionSend'
|
|
1067
1101
|
].includes(decoded.kind);
|
|
1068
|
-
const instanceMetadata = decoded.kind === 'instanceSpot'
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
&& record.parts.length !== (instanceMetadata ? 3 : 2))
|
|
1080
|
-
|| (userSpotInfrastructure && record.parts.length !== 1)) {
|
|
1102
|
+
const instanceMetadata = decoded.kind === 'instanceSpot' && (record.flags & service_stateful_wire_codec_1.M6bServiceWireFlag.metadata) !== 0;
|
|
1103
|
+
const userSpotInfrastructure = decoded.kind === 'userSpotCreate' ||
|
|
1104
|
+
decoded.kind === 'userSpotClose' ||
|
|
1105
|
+
decoded.kind === 'actorCreate' ||
|
|
1106
|
+
decoded.kind === 'messageFollow' ||
|
|
1107
|
+
decoded.kind === 'boundSessionReplaced';
|
|
1108
|
+
if (record.parts.length < 1 ||
|
|
1109
|
+
record.parts.length > (instanceMetadata ? 3 : 2) ||
|
|
1110
|
+
(hasPayload && decoded.kind !== 'actorJoin' && record.parts.length !== 2) ||
|
|
1111
|
+
(decoded.kind === 'instanceSpot' && record.parts.length !== (instanceMetadata ? 3 : 2)) ||
|
|
1112
|
+
(userSpotInfrastructure && record.parts.length !== 1)) {
|
|
1081
1113
|
return 'protocolError';
|
|
1082
1114
|
}
|
|
1083
1115
|
const metadataFrame = instanceMetadata
|
|
@@ -1091,7 +1123,9 @@ class ServiceStatefulRuntime {
|
|
|
1091
1123
|
payload: Buffer.from(canonicalActorJoin.payload.payload)
|
|
1092
1124
|
};
|
|
1093
1125
|
const payloadFrame = canonicalPayload === undefined
|
|
1094
|
-
?
|
|
1126
|
+
? record.parts.length >= 2
|
|
1127
|
+
? record.parts[record.parts.length - 1]
|
|
1128
|
+
: undefined
|
|
1095
1129
|
: (0, service_wire_m6a_codec_1.encodeApplicationPayload)(canonicalPayload);
|
|
1096
1130
|
try {
|
|
1097
1131
|
return await this.handleIngress(record, decoded, payloadFrame, metadataFrame, canonicalActorJoin, canonicalPayload);
|
|
@@ -1107,9 +1141,9 @@ class ServiceStatefulRuntime {
|
|
|
1107
1141
|
return 'protocolError';
|
|
1108
1142
|
if (error instanceof contracts_1.ZLinkFrameworkException) {
|
|
1109
1143
|
const kind = (0, framework_errors_internal_1.internalFrameworkErrorKind)(error);
|
|
1110
|
-
if (kind === framework_errors_internal_1.ZLinkFrameworkInternalErrorKind.RequestTargetNotFound
|
|
1111
|
-
|
|
1112
|
-
|
|
1144
|
+
if (kind === framework_errors_internal_1.ZLinkFrameworkInternalErrorKind.RequestTargetNotFound ||
|
|
1145
|
+
kind === framework_errors_internal_1.ZLinkFrameworkInternalErrorKind.SpotMoving ||
|
|
1146
|
+
kind === framework_errors_internal_1.ZLinkFrameworkInternalErrorKind.SpotGenerationStale) {
|
|
1113
1147
|
return 'protocolError';
|
|
1114
1148
|
}
|
|
1115
1149
|
}
|
|
@@ -1125,9 +1159,8 @@ class ServiceStatefulRuntime {
|
|
|
1125
1159
|
async handleIngress(ingress, record, payloadFrame, metadataFrame, canonicalActorJoin, canonicalActorJoinPayload) {
|
|
1126
1160
|
switch (record.kind) {
|
|
1127
1161
|
case 'messageFollow': {
|
|
1128
|
-
if (record.source.kind !== record.target.kind
|
|
1129
|
-
|
|
1130
|
-
<= record.source.authorityOwnerGeneration) {
|
|
1162
|
+
if (record.source.kind !== record.target.kind ||
|
|
1163
|
+
record.target.authorityOwnerGeneration <= record.source.authorityOwnerGeneration) {
|
|
1131
1164
|
throw new service_wire_m6a_codec_1.ServiceWireProtocolError('Message Follow target owner generation must increase at every hop.');
|
|
1132
1165
|
}
|
|
1133
1166
|
if (record.source.targetNodeRid !== ingress.sourceRoutingId) {
|
|
@@ -1139,8 +1172,7 @@ class ServiceStatefulRuntime {
|
|
|
1139
1172
|
}
|
|
1140
1173
|
const targetGeneration = record.target.targetNodeRid === this.nodeRid
|
|
1141
1174
|
? this.nodeGeneration
|
|
1142
|
-
: this.raw.topology.peer(record.target.targetNodeRid)?.descriptor
|
|
1143
|
-
.lifecycleGeneration;
|
|
1175
|
+
: this.raw.topology.peer(record.target.targetNodeRid)?.descriptor.lifecycleGeneration;
|
|
1144
1176
|
if (targetGeneration !== record.target.targetNodeGeneration) {
|
|
1145
1177
|
throw new service_wire_m6a_codec_1.ServiceWireProtocolError('Message Follow target route is not the current topology target.');
|
|
1146
1178
|
}
|
|
@@ -1150,8 +1182,7 @@ class ServiceStatefulRuntime {
|
|
|
1150
1182
|
else {
|
|
1151
1183
|
const directKey = directSpotKey(record.source.spot.spotId);
|
|
1152
1184
|
const current = this.directSpotRoutes.get(directKey);
|
|
1153
|
-
if (current !== undefined
|
|
1154
|
-
&& sameMessageFollowSpotSource(current, record.source)) {
|
|
1185
|
+
if (current !== undefined && sameMessageFollowSpotSource(current, record.source)) {
|
|
1155
1186
|
this.directSpotRoutes.delete(directKey);
|
|
1156
1187
|
const exactKey = spotKey(record.source.spot);
|
|
1157
1188
|
const exact = this.spotRoutes.get(exactKey);
|
|
@@ -1186,8 +1217,8 @@ class ServiceStatefulRuntime {
|
|
|
1186
1217
|
: this.validateActorFence(record.target);
|
|
1187
1218
|
if (record.boundSession !== undefined) {
|
|
1188
1219
|
const binding = this.registry.validateBoundSession(record.target.actor, record.boundSession.bindingGeneration);
|
|
1189
|
-
if (binding.sessionRid !== record.boundSession.sessionRid
|
|
1190
|
-
|
|
1220
|
+
if (binding.sessionRid !== record.boundSession.sessionRid ||
|
|
1221
|
+
binding.sessionOwnerNodeRid !== ingress.sourceRoutingId) {
|
|
1191
1222
|
throw new service_stateful_registry_1.ServiceStaleGenerationError('binding', record.target.actor.actorId);
|
|
1192
1223
|
}
|
|
1193
1224
|
}
|
|
@@ -1251,8 +1282,8 @@ class ServiceStatefulRuntime {
|
|
|
1251
1282
|
void this.continueMissingInstanceActivation(ownedIngress, record, payloadFrame, undefined, metadataFrame).finally(() => ownedIngress.applicationJobOwner?.close());
|
|
1252
1283
|
return 'infrastructure';
|
|
1253
1284
|
}
|
|
1254
|
-
if (record.activation === 'ready'
|
|
1255
|
-
|
|
1285
|
+
if (record.activation === 'ready' &&
|
|
1286
|
+
this.needsInstanceApplicationMaterialization(ingress, record)) {
|
|
1256
1287
|
const ownedIngress = shareIngressOwnership(ingress);
|
|
1257
1288
|
void this.continueReadyInstanceMaterialization(ownedIngress, record, payloadFrame, metadataFrame).finally(() => ownedIngress.applicationJobOwner?.close());
|
|
1258
1289
|
return 'infrastructure';
|
|
@@ -1303,10 +1334,10 @@ class ServiceStatefulRuntime {
|
|
|
1303
1334
|
return 'application';
|
|
1304
1335
|
}
|
|
1305
1336
|
const directReply = record.operationKind === 'request'
|
|
1306
|
-
? localReply ?? this.replyPort(ingress, record.replyRouteId, 'instanceSpotRequest')
|
|
1337
|
+
? (localReply ?? this.replyPort(ingress, record.replyRouteId, 'instanceSpotRequest'))
|
|
1307
1338
|
: undefined;
|
|
1308
|
-
const applicationTarget = applicationTargetOverride
|
|
1309
|
-
|
|
1339
|
+
const applicationTarget = applicationTargetOverride ??
|
|
1340
|
+
(record.activation === 'missing'
|
|
1310
1341
|
? {
|
|
1311
1342
|
targetSpotId: record.target.targetSpotId,
|
|
1312
1343
|
stableType: record.target.stableType,
|
|
@@ -1342,10 +1373,10 @@ class ServiceStatefulRuntime {
|
|
|
1342
1373
|
? {
|
|
1343
1374
|
reply: onTerminalCompletion === undefined
|
|
1344
1375
|
? directReply
|
|
1345
|
-
: (
|
|
1376
|
+
: (...reply) => {
|
|
1346
1377
|
deferredReply = reply;
|
|
1347
1378
|
return true;
|
|
1348
|
-
}
|
|
1379
|
+
}
|
|
1349
1380
|
}
|
|
1350
1381
|
: {})
|
|
1351
1382
|
});
|
|
@@ -1413,8 +1444,7 @@ class ServiceStatefulRuntime {
|
|
|
1413
1444
|
if (this.closed)
|
|
1414
1445
|
return;
|
|
1415
1446
|
const latestRoute = this.instanceIntents.get(record.route.targetSpotId)?.route;
|
|
1416
|
-
const refreshedRecord = latestRoute !== undefined
|
|
1417
|
-
&& sameInstanceApplicationOwner(latestRoute, record.route)
|
|
1447
|
+
const refreshedRecord = latestRoute !== undefined && sameInstanceApplicationOwner(latestRoute, record.route)
|
|
1418
1448
|
? { ...record, route: latestRoute }
|
|
1419
1449
|
: record;
|
|
1420
1450
|
const spot = this.requireInstanceActivation(ingress, refreshedRecord);
|
|
@@ -1437,15 +1467,15 @@ class ServiceStatefulRuntime {
|
|
|
1437
1467
|
stableType: target.stableType,
|
|
1438
1468
|
objectGeneration: route.objectGeneration
|
|
1439
1469
|
};
|
|
1440
|
-
return () => completion ??= (async () => {
|
|
1470
|
+
return () => (completion ??= (async () => {
|
|
1441
1471
|
let authorityCompletionSignaled = false;
|
|
1442
1472
|
try {
|
|
1443
1473
|
const released = await this.asyncInstanceAuthority?.complete(target, route);
|
|
1444
1474
|
this.completeInstanceAuthorityOperation(target.targetSpotId);
|
|
1445
1475
|
authorityCompletionSignaled = true;
|
|
1446
1476
|
if (released !== undefined) {
|
|
1447
|
-
const authorityReleased = await this.instanceApplicationLifecycle?.completeTerminal(applicationTarget)
|
|
1448
|
-
|
|
1477
|
+
const authorityReleased = (await this.instanceApplicationLifecycle?.completeTerminal(applicationTarget)) ??
|
|
1478
|
+
false;
|
|
1449
1479
|
if (!authorityReleased) {
|
|
1450
1480
|
this.replaceCommittedInstanceRoute(target.stableType, route, released);
|
|
1451
1481
|
}
|
|
@@ -1459,17 +1489,16 @@ class ServiceStatefulRuntime {
|
|
|
1459
1489
|
this.completeInstanceAuthorityOperation(target.targetSpotId);
|
|
1460
1490
|
}
|
|
1461
1491
|
}
|
|
1462
|
-
})();
|
|
1492
|
+
})());
|
|
1463
1493
|
}
|
|
1464
1494
|
instanceApplicationTerminalCompletion(target) {
|
|
1465
1495
|
return async () => {
|
|
1466
|
-
const authorityReleased = await this.instanceApplicationLifecycle?.completeTerminal(target)
|
|
1467
|
-
?? false;
|
|
1496
|
+
const authorityReleased = (await this.instanceApplicationLifecycle?.completeTerminal(target)) ?? false;
|
|
1468
1497
|
if (!authorityReleased)
|
|
1469
1498
|
return;
|
|
1470
1499
|
const current = this.instanceIntents.get(target.targetSpotId);
|
|
1471
|
-
if (current?.instanceType === target.stableType
|
|
1472
|
-
|
|
1500
|
+
if (current?.instanceType === target.stableType &&
|
|
1501
|
+
current.route.objectGeneration === target.objectGeneration) {
|
|
1473
1502
|
this.forgetClosedInstanceRoute(current.route);
|
|
1474
1503
|
}
|
|
1475
1504
|
};
|
|
@@ -1524,8 +1553,8 @@ class ServiceStatefulRuntime {
|
|
|
1524
1553
|
this.pendingInstanceAuthorityTerminals.set(key, pending - 1);
|
|
1525
1554
|
}
|
|
1526
1555
|
completeInstanceApplicationWaitersIfQuiescent(key) {
|
|
1527
|
-
if ((this.pendingInstanceTerminals.get(key) ?? 0) !== 0
|
|
1528
|
-
|
|
1556
|
+
if ((this.pendingInstanceTerminals.get(key) ?? 0) !== 0 ||
|
|
1557
|
+
(this.pendingInstanceAuthorityTerminals.get(key) ?? 0) !== 0)
|
|
1529
1558
|
return;
|
|
1530
1559
|
const waiters = this.instanceApplicationWaiters.get(key);
|
|
1531
1560
|
if (waiters === undefined)
|
|
@@ -1571,8 +1600,8 @@ class ServiceStatefulRuntime {
|
|
|
1571
1600
|
}
|
|
1572
1601
|
requireInstanceActivation(ingress, record) {
|
|
1573
1602
|
const readyRoute = record.activation === 'ready' ? record.route : undefined;
|
|
1574
|
-
const spotId = readyRoute?.targetSpotId
|
|
1575
|
-
|
|
1603
|
+
const spotId = readyRoute?.targetSpotId ??
|
|
1604
|
+
(record.activation === 'missing' ? record.target.targetSpotId : undefined);
|
|
1576
1605
|
if (spotId === undefined)
|
|
1577
1606
|
throw new service_stateful_registry_1.ServiceStaleGenerationError('spot', 'unknown');
|
|
1578
1607
|
this.validateInstanceIngress(ingress, record);
|
|
@@ -1580,16 +1609,16 @@ class ServiceStatefulRuntime {
|
|
|
1580
1609
|
return this.activateMissingInstance(record);
|
|
1581
1610
|
}
|
|
1582
1611
|
const { intent, route } = this.requireReadyInstanceApplicationRoute(ingress, record);
|
|
1583
|
-
const spot = this.registry.spot(route.targetSpotId)
|
|
1584
|
-
|
|
1612
|
+
const spot = this.registry.spot(route.targetSpotId) ??
|
|
1613
|
+
this.registry.restoreSpot({
|
|
1585
1614
|
spotId: route.targetSpotId,
|
|
1586
1615
|
generation: route.objectGeneration
|
|
1587
1616
|
}, 'instance', intent.instanceType, route.authorityOwnerGeneration);
|
|
1588
|
-
if (spot.state !== 'ready'
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1617
|
+
if (spot.state !== 'ready' ||
|
|
1618
|
+
spot.kind !== 'instance' ||
|
|
1619
|
+
spot.stableType !== intent.instanceType ||
|
|
1620
|
+
spot.ref.generation !== route.objectGeneration ||
|
|
1621
|
+
spot.authorityOwnerGeneration !== route.authorityOwnerGeneration) {
|
|
1593
1622
|
throw (0, framework_errors_internal_1.createInternalFrameworkException)(framework_errors_internal_1.ZLinkFrameworkInternalErrorKind.SpotMoving, `Instance Spot '${route.targetSpotId}' is not projected from its current Ready authority.`);
|
|
1594
1623
|
}
|
|
1595
1624
|
return spot;
|
|
@@ -1605,9 +1634,9 @@ class ServiceStatefulRuntime {
|
|
|
1605
1634
|
// instead of exposing a transient NotFound result to a following
|
|
1606
1635
|
// request. A mismatched or absent local projection remains NotFound.
|
|
1607
1636
|
const local = this.registry.spot(record.route.targetSpotId);
|
|
1608
|
-
if (local?.kind === 'instance'
|
|
1609
|
-
|
|
1610
|
-
|
|
1637
|
+
if (local?.kind === 'instance' &&
|
|
1638
|
+
local.state === 'ready' &&
|
|
1639
|
+
routeMatchesLocal(record.route, local, this.nodeRid, this.nodeGeneration)) {
|
|
1611
1640
|
this.publishCommittedInstanceRoute(local.stableType, record.route);
|
|
1612
1641
|
intent = this.instanceIntents.get(record.route.targetSpotId);
|
|
1613
1642
|
}
|
|
@@ -1622,16 +1651,16 @@ class ServiceStatefulRuntime {
|
|
|
1622
1651
|
if (!sameInstanceApplicationOwner(current, record.route)) {
|
|
1623
1652
|
throw (0, framework_errors_internal_1.createInternalFrameworkException)(framework_errors_internal_1.ZLinkFrameworkInternalErrorKind.SpotMoving, `Instance Spot '${record.route.targetSpotId}' is owned by a different current route.`);
|
|
1624
1653
|
}
|
|
1625
|
-
if (current.objectGeneration === record.route.objectGeneration
|
|
1626
|
-
|
|
1654
|
+
if (current.objectGeneration === record.route.objectGeneration &&
|
|
1655
|
+
current.authorityOwnerGeneration !== record.route.authorityOwnerGeneration) {
|
|
1627
1656
|
throw (0, framework_errors_internal_1.createInternalFrameworkException)(framework_errors_internal_1.ZLinkFrameworkInternalErrorKind.SpotMoving, `Instance Spot '${record.route.targetSpotId}' has a different authority owner fence.`);
|
|
1628
1657
|
}
|
|
1629
1658
|
return { intent, route: current };
|
|
1630
1659
|
}
|
|
1631
1660
|
validateInstanceIngress(ingress, record) {
|
|
1632
1661
|
const expectedSourceGeneration = this.peerGeneration(record.sourceNodeRid);
|
|
1633
|
-
if (record.sourceNodeRid !== ingress.sourceRoutingId
|
|
1634
|
-
|
|
1662
|
+
if (record.sourceNodeRid !== ingress.sourceRoutingId ||
|
|
1663
|
+
record.sourceNodeGeneration !== expectedSourceGeneration) {
|
|
1635
1664
|
if (record.activation === 'ready') {
|
|
1636
1665
|
throw (0, framework_errors_internal_1.createInternalFrameworkException)(framework_errors_internal_1.ZLinkFrameworkInternalErrorKind.SpotMoving, `Instance Spot '${record.route.targetSpotId}' received a stale source lifecycle fence.`);
|
|
1637
1666
|
}
|
|
@@ -1640,9 +1669,9 @@ class ServiceStatefulRuntime {
|
|
|
1640
1669
|
}
|
|
1641
1670
|
activateMissingInstance(record) {
|
|
1642
1671
|
const target = record.target;
|
|
1643
|
-
if (target.targetNodeRid !== this.nodeRid
|
|
1644
|
-
|
|
1645
|
-
|
|
1672
|
+
if (target.targetNodeRid !== this.nodeRid ||
|
|
1673
|
+
target.targetNodeGeneration !== this.nodeGeneration ||
|
|
1674
|
+
record.deadlineUnixMs < BigInt(Date.now())) {
|
|
1646
1675
|
throw new service_stateful_registry_1.ServiceStaleGenerationError('spot', target.targetSpotId);
|
|
1647
1676
|
}
|
|
1648
1677
|
if (this.instanceApplicationLifecycle?.isIdleEvicting?.(target) === true) {
|
|
@@ -1655,10 +1684,10 @@ class ServiceStatefulRuntime {
|
|
|
1655
1684
|
const local = this.registry.spot(target.targetSpotId);
|
|
1656
1685
|
const current = authority.read(target);
|
|
1657
1686
|
if (local !== undefined) {
|
|
1658
|
-
if (local.kind !== 'instance'
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
|
|
1687
|
+
if (local.kind !== 'instance' ||
|
|
1688
|
+
local.stableType !== target.stableType ||
|
|
1689
|
+
current.kind !== 'ready' ||
|
|
1690
|
+
!routeMatchesLocal(current.route, local, this.nodeRid, this.nodeGeneration)) {
|
|
1662
1691
|
throw new service_stateful_registry_1.ServiceStaleGenerationError('spot', target.targetSpotId);
|
|
1663
1692
|
}
|
|
1664
1693
|
return local;
|
|
@@ -1708,9 +1737,9 @@ class ServiceStatefulRuntime {
|
|
|
1708
1737
|
}
|
|
1709
1738
|
async runMissingInstanceActivation(record, payloadFrame, metadataFrame) {
|
|
1710
1739
|
const target = record.target;
|
|
1711
|
-
if (target.targetNodeRid !== this.nodeRid
|
|
1712
|
-
|
|
1713
|
-
|
|
1740
|
+
if (target.targetNodeRid !== this.nodeRid ||
|
|
1741
|
+
target.targetNodeGeneration !== this.nodeGeneration ||
|
|
1742
|
+
record.deadlineUnixMs < BigInt(Date.now())) {
|
|
1714
1743
|
throw new service_stateful_registry_1.ServiceStaleGenerationError('spot', target.targetSpotId);
|
|
1715
1744
|
}
|
|
1716
1745
|
const authority = this.asyncInstanceAuthority;
|
|
@@ -1734,13 +1763,12 @@ class ServiceStatefulRuntime {
|
|
|
1734
1763
|
if (current.route.targetNodeGeneration !== this.nodeGeneration) {
|
|
1735
1764
|
throw new service_stateful_registry_1.ServiceStaleGenerationError('spot', target.targetSpotId);
|
|
1736
1765
|
}
|
|
1737
|
-
if (local !== undefined
|
|
1738
|
-
|
|
1739
|
-
|| local.stableType !== target.stableType)) {
|
|
1766
|
+
if (local !== undefined &&
|
|
1767
|
+
(local.kind !== 'instance' || local.stableType !== target.stableType)) {
|
|
1740
1768
|
throw new service_stateful_registry_1.ServiceStaleGenerationError('spot', target.targetSpotId);
|
|
1741
1769
|
}
|
|
1742
|
-
if (local !== undefined
|
|
1743
|
-
|
|
1770
|
+
if (local !== undefined &&
|
|
1771
|
+
routeMatchesLocal(current.route, local, this.nodeRid, this.nodeGeneration)) {
|
|
1744
1772
|
return { spot: local, route: current.route };
|
|
1745
1773
|
}
|
|
1746
1774
|
return await this.reconcileReadyInstanceProjection(target, current.route, authority);
|
|
@@ -1748,23 +1776,20 @@ class ServiceStatefulRuntime {
|
|
|
1748
1776
|
if (local !== undefined) {
|
|
1749
1777
|
const lifecycle = this.instanceApplicationLifecycle;
|
|
1750
1778
|
const closing = lifecycle?.isClosing?.(target) === true;
|
|
1751
|
-
let materialized = lifecycle === undefined
|
|
1752
|
-
? undefined
|
|
1753
|
-
: lifecycle.isMaterialized(target);
|
|
1779
|
+
let materialized = lifecycle === undefined ? undefined : lifecycle.isMaterialized(target);
|
|
1754
1780
|
const materializing = lifecycle?.isMaterializing?.(target) === true;
|
|
1755
|
-
if (local.kind !== 'instance'
|
|
1756
|
-
|| local.stableType !== target.stableType) {
|
|
1781
|
+
if (local.kind !== 'instance' || local.stableType !== target.stableType) {
|
|
1757
1782
|
throw new service_stateful_registry_1.ServiceStaleGenerationError('spot', target.targetSpotId);
|
|
1758
1783
|
}
|
|
1759
|
-
const joinsCreating = current.kind === 'creating'
|
|
1760
|
-
|
|
1761
|
-
|
|
1784
|
+
const joinsCreating = current.kind === 'creating' &&
|
|
1785
|
+
local.ref.generation === current.objectGeneration &&
|
|
1786
|
+
local.authorityOwnerGeneration === current.authorityOwnerGeneration;
|
|
1762
1787
|
const replacesClosingProjection = current.kind === 'creating' && closing;
|
|
1763
|
-
if (current.kind === 'missing'
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
1788
|
+
if (current.kind === 'missing' &&
|
|
1789
|
+
!closing &&
|
|
1790
|
+
!materializing &&
|
|
1791
|
+
materialized === true &&
|
|
1792
|
+
lifecycle !== undefined) {
|
|
1768
1793
|
// The durable authority is the ownership source of truth. Its removal
|
|
1769
1794
|
// can become visible before the route reconciler has discarded the
|
|
1770
1795
|
// previous application projection. Converge that orphan here before
|
|
@@ -1783,8 +1808,8 @@ class ServiceStatefulRuntime {
|
|
|
1783
1808
|
// failure.
|
|
1784
1809
|
// If disposal did not remove an orphaned materialization, keep fencing
|
|
1785
1810
|
// it instead of admitting work into two application generations.
|
|
1786
|
-
if ((!joinsCreating && !replacesClosingProjection && current.kind !== 'missing')
|
|
1787
|
-
|
|
1811
|
+
if ((!joinsCreating && !replacesClosingProjection && current.kind !== 'missing') ||
|
|
1812
|
+
(!joinsCreating && !closing && materialized !== false && !materializing)) {
|
|
1788
1813
|
throw new service_stateful_registry_1.ServiceStaleGenerationError('spot', target.targetSpotId);
|
|
1789
1814
|
}
|
|
1790
1815
|
}
|
|
@@ -1845,8 +1870,7 @@ class ServiceStatefulRuntime {
|
|
|
1845
1870
|
acceptsLocalMissingInstancePlacement() {
|
|
1846
1871
|
const topology = this.raw.topology;
|
|
1847
1872
|
const descriptor = topology.localDescriptor?.();
|
|
1848
|
-
return descriptor === undefined
|
|
1849
|
-
|| (descriptor.state === 'serving' && descriptor.placementWeight > 0);
|
|
1873
|
+
return (descriptor === undefined || (descriptor.state === 'serving' && descriptor.placementWeight > 0));
|
|
1850
1874
|
}
|
|
1851
1875
|
async reconcileReadyInstanceProjection(target, route, authority) {
|
|
1852
1876
|
await this.instanceApplicationLifecycle?.materialize(target, route.objectGeneration);
|
|
@@ -1859,15 +1883,14 @@ class ServiceStatefulRuntime {
|
|
|
1859
1883
|
this.publishCommittedInstanceRoute(target.stableType, route);
|
|
1860
1884
|
const confirmed = await authority.read(target);
|
|
1861
1885
|
if (confirmed.kind !== 'ready' || !sameInstanceRoute(confirmed.route, route)) {
|
|
1862
|
-
if (confirmed.kind === 'ready'
|
|
1863
|
-
&& confirmed.route.targetNodeRid !== this.nodeRid) {
|
|
1886
|
+
if (confirmed.kind === 'ready' && confirmed.route.targetNodeRid !== this.nodeRid) {
|
|
1864
1887
|
throw new ServiceInstanceActivationRedirectError(confirmed.route);
|
|
1865
1888
|
}
|
|
1866
1889
|
throw new service_stateful_registry_1.ServiceStaleGenerationError('spot', target.targetSpotId);
|
|
1867
1890
|
}
|
|
1868
1891
|
const current = this.registry.spot(target.targetSpotId);
|
|
1869
|
-
if (current === undefined
|
|
1870
|
-
|
|
1892
|
+
if (current === undefined ||
|
|
1893
|
+
!routeMatchesLocal(confirmed.route, current, this.nodeRid, this.nodeGeneration)) {
|
|
1871
1894
|
throw new service_stateful_registry_1.ServiceStaleGenerationError('spot', target.targetSpotId);
|
|
1872
1895
|
}
|
|
1873
1896
|
return { spot: current, route: confirmed.route };
|
|
@@ -1901,9 +1924,9 @@ class ServiceStatefulRuntime {
|
|
|
1901
1924
|
}
|
|
1902
1925
|
forgetClosedInstanceRoute(route) {
|
|
1903
1926
|
const local = this.registry.spot(route.targetSpotId);
|
|
1904
|
-
if (local?.kind === 'instance'
|
|
1905
|
-
|
|
1906
|
-
|
|
1927
|
+
if (local?.kind === 'instance' &&
|
|
1928
|
+
local.ref.generation === route.objectGeneration &&
|
|
1929
|
+
local.authorityOwnerGeneration === route.authorityOwnerGeneration) {
|
|
1907
1930
|
this.registry.closeSpot(local.ref);
|
|
1908
1931
|
}
|
|
1909
1932
|
this.forgetSpotRoute({ spotId: route.targetSpotId, generation: route.objectGeneration }, route.authorityOwnerGeneration, route.storeVersion);
|
|
@@ -1994,8 +2017,7 @@ class ServiceStatefulRuntime {
|
|
|
1994
2017
|
if (record.binding.state === 'active') {
|
|
1995
2018
|
const actor = this.validateActorFence(record.actor);
|
|
1996
2019
|
const previous = this.registry.binding(actor.ref);
|
|
1997
|
-
const sourceGeneration = ingress.sourceNodeGeneration
|
|
1998
|
-
?? this.peerGeneration(ingress.sourceRoutingId);
|
|
2020
|
+
const sourceGeneration = ingress.sourceNodeGeneration ?? this.peerGeneration(ingress.sourceRoutingId);
|
|
1999
2021
|
const binding = (0, service_stateful_wire_codec_1.sessionBindingFromWire)(actor.ref, record.sessionRid, ingress.sourceRoutingId, record.binding.generation, actor.membershipEpoch, sourceGeneration, ingress.sourceRoutingId, sourceGeneration);
|
|
2000
2022
|
if (previous !== undefined && sameSessionIdentity(previous, binding)) {
|
|
2001
2023
|
// Registry publication is the last step of the first binding owner
|
|
@@ -2032,9 +2054,9 @@ class ServiceStatefulRuntime {
|
|
|
2032
2054
|
authorityOwnerGeneration: actor.authorityOwnerGeneration
|
|
2033
2055
|
}
|
|
2034
2056
|
: undefined);
|
|
2035
|
-
if (terminalResult === runtime_values_1.RequestResult.Ok
|
|
2036
|
-
|
|
2037
|
-
|
|
2057
|
+
if (terminalResult === runtime_values_1.RequestResult.Ok &&
|
|
2058
|
+
replacedBinding !== undefined &&
|
|
2059
|
+
!sameSessionBinding(replacedBinding, completedBinding)) {
|
|
2038
2060
|
this.sendBoundSessionReplacement(replacedBinding, actorAuthorityFromRoute({
|
|
2039
2061
|
...record.actor,
|
|
2040
2062
|
ownerLeaseGeneration: record.actor.ownerLeaseGeneration
|
|
@@ -2068,8 +2090,7 @@ class ServiceStatefulRuntime {
|
|
|
2068
2090
|
if (authority.actor.nodeRid !== ingress.sourceRoutingId) {
|
|
2069
2091
|
return 'protocolError';
|
|
2070
2092
|
}
|
|
2071
|
-
const sourceGeneration = ingress.sourceNodeGeneration
|
|
2072
|
-
?? this.tryPeerGeneration(ingress.sourceRoutingId);
|
|
2093
|
+
const sourceGeneration = ingress.sourceNodeGeneration ?? this.tryPeerGeneration(ingress.sourceRoutingId);
|
|
2073
2094
|
if (sourceGeneration === undefined)
|
|
2074
2095
|
return 'infrastructure';
|
|
2075
2096
|
if (sourceGeneration !== authority.targetNodeGeneration) {
|
|
@@ -2077,10 +2098,10 @@ class ServiceStatefulRuntime {
|
|
|
2077
2098
|
// session that belongs to the new lifecycle.
|
|
2078
2099
|
return 'infrastructure';
|
|
2079
2100
|
}
|
|
2080
|
-
if (record.retiredSession.sessionOwnerNodeRid !== this.nodeRid
|
|
2081
|
-
|
|
2082
|
-
|
|
2083
|
-
|
|
2101
|
+
if (record.retiredSession.sessionOwnerNodeRid !== this.nodeRid ||
|
|
2102
|
+
record.retiredSession.sessionOwnerNodeGeneration !== this.nodeGeneration ||
|
|
2103
|
+
record.retiredSession.sessionOwnerId !== this.nodeRid ||
|
|
2104
|
+
record.retiredSession.sessionOwnerLeaseGeneration !== this.nodeGeneration) {
|
|
2084
2105
|
return 'infrastructure';
|
|
2085
2106
|
}
|
|
2086
2107
|
const actor = authority.actor;
|
|
@@ -2096,13 +2117,11 @@ class ServiceStatefulRuntime {
|
|
|
2096
2117
|
sessionOwnerNodeGeneration: record.retiredSession.sessionOwnerNodeGeneration,
|
|
2097
2118
|
sessionOwnerId: record.retiredSession.sessionOwnerId,
|
|
2098
2119
|
sessionOwnerLeaseGeneration: record.retiredSession.sessionOwnerLeaseGeneration,
|
|
2099
|
-
bindingGeneration: record.retiredSession.retiredBindingGeneration
|
|
2120
|
+
bindingGeneration: record.retiredSession.retiredBindingGeneration
|
|
2100
2121
|
}));
|
|
2101
|
-
const delivery = current !== undefined
|
|
2102
|
-
&& exactRetiredDelivery(current.binding, record.retiredSession)
|
|
2122
|
+
const delivery = current !== undefined && exactRetiredDelivery(current.binding, record.retiredSession)
|
|
2103
2123
|
? current
|
|
2104
|
-
: retired !== undefined
|
|
2105
|
-
&& exactRetiredDelivery(retired.binding, record.retiredSession)
|
|
2124
|
+
: retired !== undefined && exactRetiredDelivery(retired.binding, record.retiredSession)
|
|
2106
2125
|
? retired
|
|
2107
2126
|
: undefined;
|
|
2108
2127
|
if (delivery === undefined)
|
|
@@ -2115,8 +2134,7 @@ class ServiceStatefulRuntime {
|
|
|
2115
2134
|
return 'infrastructure';
|
|
2116
2135
|
}
|
|
2117
2136
|
sendBoundSessionReplacement(previous, actorAuthority) {
|
|
2118
|
-
const ownerGeneration = previous.sessionOwnerNodeGeneration
|
|
2119
|
-
?? this.tryPeerGeneration(previous.sessionOwnerNodeRid);
|
|
2137
|
+
const ownerGeneration = previous.sessionOwnerNodeGeneration ?? this.tryPeerGeneration(previous.sessionOwnerNodeRid);
|
|
2120
2138
|
if (ownerGeneration === undefined)
|
|
2121
2139
|
return;
|
|
2122
2140
|
const header = (0, service_stateful_wire_codec_1.encodeBoundSessionReplacedHeader)(actorAuthority, {
|
|
@@ -2137,22 +2155,20 @@ class ServiceStatefulRuntime {
|
|
|
2137
2155
|
return;
|
|
2138
2156
|
const actor = record.actor.actor;
|
|
2139
2157
|
const current = this.registry.binding(actor);
|
|
2140
|
-
const sourceGeneration = ingress.sourceNodeGeneration
|
|
2141
|
-
|
|
2142
|
-
|
|
2143
|
-
|
|
2144
|
-
|
|
2145
|
-
|
|
2146
|
-
|
|
2147
|
-
|
|
2148
|
-
|
|
2149
|
-
|| current.sessionOwnerLeaseGeneration !== sourceGeneration) {
|
|
2158
|
+
const sourceGeneration = ingress.sourceNodeGeneration ?? this.tryPeerGeneration(ingress.sourceRoutingId);
|
|
2159
|
+
if (current === undefined ||
|
|
2160
|
+
sourceGeneration === undefined ||
|
|
2161
|
+
current.bindingGeneration !== record.binding.retiredGeneration ||
|
|
2162
|
+
current.sessionRid !== record.sessionRid ||
|
|
2163
|
+
current.sessionOwnerNodeRid !== ingress.sourceRoutingId ||
|
|
2164
|
+
current.sessionOwnerNodeGeneration !== sourceGeneration ||
|
|
2165
|
+
current.sessionOwnerId !== ingress.sourceRoutingId ||
|
|
2166
|
+
current.sessionOwnerLeaseGeneration !== sourceGeneration) {
|
|
2150
2167
|
this.replyWire(ingress, record.correlation, runtime_values_1.RequestResult.Ok, 0);
|
|
2151
2168
|
return;
|
|
2152
2169
|
}
|
|
2153
2170
|
const delivery = this.sessionDeliveries.get(actorKey(actor));
|
|
2154
|
-
const currentDelivery = delivery !== undefined
|
|
2155
|
-
&& sameSessionBinding(delivery.binding, current)
|
|
2171
|
+
const currentDelivery = delivery !== undefined && sameSessionBinding(delivery.binding, current)
|
|
2156
2172
|
? delivery
|
|
2157
2173
|
: undefined;
|
|
2158
2174
|
const accepted = this.enqueueSessionBindingRetirement(ingress, current, record.actor, (terminalResult, failureCode) => {
|
|
@@ -2161,8 +2177,8 @@ class ServiceStatefulRuntime {
|
|
|
2161
2177
|
if (turnCurrent !== undefined && sameSessionBinding(turnCurrent, current)) {
|
|
2162
2178
|
this.registry.unbindSession(actor, current.bindingGeneration, current.sessionRid, current.sessionOwnerNodeRid);
|
|
2163
2179
|
}
|
|
2164
|
-
if (currentDelivery !== undefined
|
|
2165
|
-
|
|
2180
|
+
if (currentDelivery !== undefined &&
|
|
2181
|
+
this.sessionDeliveries.get(actorKey(actor)) === currentDelivery) {
|
|
2166
2182
|
this.sessionDeliveries.delete(actorKey(actor));
|
|
2167
2183
|
}
|
|
2168
2184
|
}
|
|
@@ -2211,12 +2227,12 @@ class ServiceStatefulRuntime {
|
|
|
2211
2227
|
}
|
|
2212
2228
|
async deliverBoundSession(ingress, record, payloadFrame) {
|
|
2213
2229
|
const delivery = this.sessionDeliveries.get(actorKey(record.actor.actor));
|
|
2214
|
-
if (delivery === undefined
|
|
2215
|
-
|
|
2216
|
-
|
|
2217
|
-
|
|
2218
|
-
|
|
2219
|
-
|
|
2230
|
+
if (delivery === undefined ||
|
|
2231
|
+
delivery.binding.bindingGeneration !== record.expectedBindingGeneration ||
|
|
2232
|
+
payloadFrame === undefined ||
|
|
2233
|
+
ingress.sourceNodeGeneration === undefined ||
|
|
2234
|
+
!(0, routing_id_1.routingIdsEqual)(ingress.sourceRoutingId, record.actor.actor.nodeRid) ||
|
|
2235
|
+
ingress.sourceNodeGeneration !== record.actor.targetNodeGeneration) {
|
|
2220
2236
|
return 'protocolError';
|
|
2221
2237
|
}
|
|
2222
2238
|
const sessionRid = delivery.binding.sessionRid;
|
|
@@ -2270,9 +2286,9 @@ class ServiceStatefulRuntime {
|
|
|
2270
2286
|
// Remote command 36 is one-way: its source transport admission has
|
|
2271
2287
|
// already completed, so a later client delivery terminal is local to
|
|
2272
2288
|
// this session owner. Local fast paths still preserve the typed result.
|
|
2273
|
-
if (ingress.sourceRoutingId !== this.nodeRid
|
|
2274
|
-
|
|
2275
|
-
|
|
2289
|
+
if (ingress.sourceRoutingId !== this.nodeRid &&
|
|
2290
|
+
(0, runtime_values_1.isZLinkBackendResultError)(error) &&
|
|
2291
|
+
error.operation === 'submit') {
|
|
2276
2292
|
return 'application';
|
|
2277
2293
|
}
|
|
2278
2294
|
throw error;
|
|
@@ -2294,7 +2310,9 @@ class ServiceStatefulRuntime {
|
|
|
2294
2310
|
sourceRoutingId: ingress.sourceRoutingId,
|
|
2295
2311
|
sourceRoute: ingress.sourceRoute,
|
|
2296
2312
|
...(ingress.reply === undefined ? {} : { reply: ingress.reply }),
|
|
2297
|
-
...(ingress.requestSequence === undefined
|
|
2313
|
+
...(ingress.requestSequence === undefined
|
|
2314
|
+
? {}
|
|
2315
|
+
: { requestSequence: ingress.requestSequence }),
|
|
2298
2316
|
...(stateful.correlation === undefined ? {} : { correlation: stateful.correlation }),
|
|
2299
2317
|
stateful,
|
|
2300
2318
|
applicationJob
|
|
@@ -2320,10 +2338,10 @@ class ServiceStatefulRuntime {
|
|
|
2320
2338
|
}
|
|
2321
2339
|
async enqueueLogicalMulticastFrame(channelName, topic, sourceSpotId, payloadFrame, sourceNodeRid, applicationJobOwner) {
|
|
2322
2340
|
const targets = [...this.subscriptions.entries()]
|
|
2323
|
-
.filter(([, values]) => [...values].some(value => {
|
|
2341
|
+
.filter(([, values]) => [...values].some((value) => {
|
|
2324
2342
|
const separator = value.indexOf('\0');
|
|
2325
|
-
return value.slice(0, separator) === channelName
|
|
2326
|
-
|
|
2343
|
+
return (value.slice(0, separator) === channelName &&
|
|
2344
|
+
topicMatches(value.slice(separator + 1), topic));
|
|
2327
2345
|
}))
|
|
2328
2346
|
.map(([spotId]) => spotId)
|
|
2329
2347
|
.sort();
|
|
@@ -2335,10 +2353,7 @@ class ServiceStatefulRuntime {
|
|
|
2335
2353
|
const accepted = this.raw.mailbox.tryEnqueue({
|
|
2336
2354
|
owner: `spot:${spotId}`,
|
|
2337
2355
|
domain: 'application',
|
|
2338
|
-
parts: [
|
|
2339
|
-
(0, service_stateful_wire_codec_1.encodeLogicalMulticastHeader)(channelName, topic, sourceSpotId),
|
|
2340
|
-
payloadFrame
|
|
2341
|
-
],
|
|
2356
|
+
parts: [(0, service_stateful_wire_codec_1.encodeLogicalMulticastHeader)(channelName, topic, sourceSpotId), payloadFrame],
|
|
2342
2357
|
sourceRoutingId: sourceNodeRid,
|
|
2343
2358
|
stateful: {
|
|
2344
2359
|
receiveKind: service_runtime_contracts_1.ReceiveKind.SpotMulticast,
|
|
@@ -2451,17 +2466,17 @@ class ServiceStatefulRuntime {
|
|
|
2451
2466
|
]);
|
|
2452
2467
|
}
|
|
2453
2468
|
handleUserSpotOperation(ingress, record) {
|
|
2454
|
-
if (ingress.requestSequence === undefined
|
|
2455
|
-
|
|
2456
|
-
|
|
2457
|
-
|
|
2469
|
+
if (ingress.requestSequence === undefined ||
|
|
2470
|
+
record.sourceNodeRid !== ingress.sourceRoutingId ||
|
|
2471
|
+
record.sourceNodeGeneration !== this.peerGeneration(ingress.sourceRoutingId) ||
|
|
2472
|
+
(record.kind === 'actorCreate' && record.reservation.pendingCapacityDelta !== 1)) {
|
|
2458
2473
|
return 'protocolError';
|
|
2459
2474
|
}
|
|
2460
2475
|
const target = record.kind === 'userSpotCreate' || record.kind === 'actorCreate'
|
|
2461
2476
|
? record.reservation
|
|
2462
2477
|
: record.target;
|
|
2463
|
-
if (target.targetNodeRid !== this.nodeRid
|
|
2464
|
-
|
|
2478
|
+
if (target.targetNodeRid !== this.nodeRid ||
|
|
2479
|
+
target.targetNodeGeneration !== this.nodeGeneration) {
|
|
2465
2480
|
this.replyWire(ingress, record.correlation, runtime_values_1.RequestResult.Conflict, SPOT_MOVING);
|
|
2466
2481
|
return 'infrastructure';
|
|
2467
2482
|
}
|
|
@@ -2473,8 +2488,7 @@ class ServiceStatefulRuntime {
|
|
|
2473
2488
|
].join('\0');
|
|
2474
2489
|
const encodedRequest = userSpotOperationFingerprint(record);
|
|
2475
2490
|
let admitted = this.admittedUserSpotOperations.get(operationKey);
|
|
2476
|
-
if (admitted?.settled === true
|
|
2477
|
-
&& operationReplayExpired(admitted.replayExpiresAtMs)) {
|
|
2491
|
+
if (admitted?.settled === true && operationReplayExpired(admitted.replayExpiresAtMs)) {
|
|
2478
2492
|
this.admittedUserSpotOperations.delete(operationKey);
|
|
2479
2493
|
admitted = undefined;
|
|
2480
2494
|
}
|
|
@@ -2493,9 +2507,9 @@ class ServiceStatefulRuntime {
|
|
|
2493
2507
|
this.replyWire(ingress, record.correlation, runtime_values_1.RequestResult.Busy, 0);
|
|
2494
2508
|
return 'infrastructure';
|
|
2495
2509
|
}
|
|
2496
|
-
const replayExpiresAtMs = performance.now()
|
|
2497
|
-
|
|
2498
|
-
|
|
2510
|
+
const replayExpiresAtMs = performance.now() +
|
|
2511
|
+
Number(record.deadlineUnixMs - BigInt(Date.now())) +
|
|
2512
|
+
USER_SPOT_OPERATION_REPLAY_RETENTION_MS;
|
|
2499
2513
|
const handler = this.userSpotOperationHandler;
|
|
2500
2514
|
const result = handler === undefined
|
|
2501
2515
|
? Promise.resolve({
|
|
@@ -2510,22 +2524,22 @@ class ServiceStatefulRuntime {
|
|
|
2510
2524
|
settled: false
|
|
2511
2525
|
};
|
|
2512
2526
|
this.admittedUserSpotOperations.set(operationKey, admitted);
|
|
2513
|
-
void result
|
|
2527
|
+
void result
|
|
2528
|
+
.finally(() => {
|
|
2514
2529
|
const current = this.admittedUserSpotOperations.get(operationKey);
|
|
2515
2530
|
if (current?.result === result)
|
|
2516
2531
|
current.settled = true;
|
|
2517
|
-
})
|
|
2532
|
+
})
|
|
2533
|
+
.catch(() => undefined);
|
|
2518
2534
|
}
|
|
2519
|
-
void admitted.result.then(result => {
|
|
2535
|
+
void admitted.result.then((result) => {
|
|
2520
2536
|
if (this.closed)
|
|
2521
2537
|
return;
|
|
2522
2538
|
this.raw.replyService(ingress, [
|
|
2523
2539
|
(0, service_stateful_wire_codec_1.encodeStatefulReply)(record.correlation, result.terminalResult, result.failureCode, result.tail),
|
|
2524
|
-
...(result.payload === undefined
|
|
2525
|
-
? []
|
|
2526
|
-
: [(0, service_wire_m6a_codec_1.encodeApplicationPayload)(result.payload)])
|
|
2540
|
+
...(result.payload === undefined ? [] : [(0, service_wire_m6a_codec_1.encodeApplicationPayload)(result.payload)])
|
|
2527
2541
|
]);
|
|
2528
|
-
}, error => {
|
|
2542
|
+
}, (error) => {
|
|
2529
2543
|
if (this.closed)
|
|
2530
2544
|
return;
|
|
2531
2545
|
const failed = failure(error);
|
|
@@ -2553,9 +2567,8 @@ class ServiceStatefulRuntime {
|
|
|
2553
2567
|
failureCode: 0
|
|
2554
2568
|
}
|
|
2555
2569
|
: await handler.createActor(record, deadline.signal);
|
|
2556
|
-
if (result.terminalResult === runtime_values_1.RequestResult.Ok
|
|
2557
|
-
|
|
2558
|
-
|| result.tail.kind !== record.kind)) {
|
|
2570
|
+
if (result.terminalResult === runtime_values_1.RequestResult.Ok &&
|
|
2571
|
+
(result.tail === undefined || result.tail.kind !== record.kind)) {
|
|
2559
2572
|
throw new service_wire_m6a_codec_1.ServiceWireProtocolError('User Spot success result omits its operation tail.');
|
|
2560
2573
|
}
|
|
2561
2574
|
return result;
|
|
@@ -2576,21 +2589,17 @@ class ServiceStatefulRuntime {
|
|
|
2576
2589
|
throw new service_wire_m6a_codec_1.ServiceWireProtocolError('Invalid creation operation reply parts.');
|
|
2577
2590
|
}
|
|
2578
2591
|
const decoded = (0, service_stateful_wire_codec_1.decodeStatefulReply)(parts[0], correlation, operationKind, parts.length >= 2);
|
|
2579
|
-
if (decoded.terminalResult !== runtime_values_1.RequestResult.Ok
|
|
2580
|
-
&& parts.length !== 1) {
|
|
2592
|
+
if (decoded.terminalResult !== runtime_values_1.RequestResult.Ok && parts.length !== 1) {
|
|
2581
2593
|
throw new service_wire_m6a_codec_1.ServiceWireProtocolError('Failed creation operation reply carries a payload.');
|
|
2582
2594
|
}
|
|
2583
|
-
if (operationKind === 'userSpotClose'
|
|
2584
|
-
&& parts.length !== 1) {
|
|
2595
|
+
if (operationKind === 'userSpotClose' && parts.length !== 1) {
|
|
2585
2596
|
throw new service_wire_m6a_codec_1.ServiceWireProtocolError('User Spot close reply carries a payload.');
|
|
2586
2597
|
}
|
|
2587
2598
|
return {
|
|
2588
2599
|
terminalResult: decoded.terminalResult,
|
|
2589
2600
|
failureCode: decoded.failureCode,
|
|
2590
2601
|
...(decoded.tail === undefined ? {} : { tail: decoded.tail }),
|
|
2591
|
-
...(parts.length === 2
|
|
2592
|
-
? { payload: (0, service_wire_m6a_codec_1.decodeApplicationPayload)(parts[1]) }
|
|
2593
|
-
: {})
|
|
2602
|
+
...(parts.length === 2 ? { payload: (0, service_wire_m6a_codec_1.decodeApplicationPayload)(parts[1]) } : {})
|
|
2594
2603
|
};
|
|
2595
2604
|
}
|
|
2596
2605
|
catch (error) {
|
|
@@ -2599,7 +2608,7 @@ class ServiceStatefulRuntime {
|
|
|
2599
2608
|
}
|
|
2600
2609
|
async requestDurableOperation(targetNodeRid, parts, correlation, operationKind, deadlineMs) {
|
|
2601
2610
|
const stop = new AbortController();
|
|
2602
|
-
const unobserve = this.raw.observePeerConnectionIntentRemoved(nodeRoutingId => {
|
|
2611
|
+
const unobserve = this.raw.observePeerConnectionIntentRemoved((nodeRoutingId) => {
|
|
2603
2612
|
if (nodeRoutingId === targetNodeRid) {
|
|
2604
2613
|
stop.abort((0, framework_errors_internal_1.createInternalFrameworkException)(framework_errors_internal_1.ZLinkFrameworkInternalErrorKind.RouteNotConnected, `${operationKind} target node lifecycle ended.`, true));
|
|
2605
2614
|
}
|
|
@@ -2631,7 +2640,7 @@ class ServiceStatefulRuntime {
|
|
|
2631
2640
|
}
|
|
2632
2641
|
let timer;
|
|
2633
2642
|
try {
|
|
2634
|
-
await (0, abort_1.awaitWithAbort)(new Promise(resolve => {
|
|
2643
|
+
await (0, abort_1.awaitWithAbort)(new Promise((resolve) => {
|
|
2635
2644
|
timer = setTimeout(resolve, retryDelayMs);
|
|
2636
2645
|
}), stop.signal);
|
|
2637
2646
|
}
|
|
@@ -2668,7 +2677,7 @@ class ServiceStatefulRuntime {
|
|
|
2668
2677
|
return;
|
|
2669
2678
|
settled = true;
|
|
2670
2679
|
clearTimeout(timer);
|
|
2671
|
-
resolve(parts.map(part => Buffer.from(part)));
|
|
2680
|
+
resolve(parts.map((part) => Buffer.from(part)));
|
|
2672
2681
|
};
|
|
2673
2682
|
void (async () => {
|
|
2674
2683
|
const applicationJobOwner = await this.raw.reserveLocalIngress();
|
|
@@ -2750,7 +2759,7 @@ class ServiceStatefulRuntime {
|
|
|
2750
2759
|
applicationJobOwner.close();
|
|
2751
2760
|
}
|
|
2752
2761
|
}
|
|
2753
|
-
return await this.raw.sendService(targetNodeRid, parts)
|
|
2762
|
+
return (await this.raw.sendService(targetNodeRid, parts))
|
|
2754
2763
|
? runtime_values_1.SubmitResult.Ok
|
|
2755
2764
|
: runtime_values_1.SubmitResult.NotConnected;
|
|
2756
2765
|
}
|
|
@@ -2776,10 +2785,10 @@ class ServiceStatefulRuntime {
|
|
|
2776
2785
|
finally {
|
|
2777
2786
|
applicationJobOwner.close();
|
|
2778
2787
|
}
|
|
2779
|
-
})().catch(error => this.operations.reply(pending.id, failure(error)));
|
|
2788
|
+
})().catch((error) => this.operations.reply(pending.id, failure(error)));
|
|
2780
2789
|
return;
|
|
2781
2790
|
}
|
|
2782
|
-
void this.raw.requestService(targetNodeRid, parts, timeoutMs).then(reply => this.completeRemoteReply(pending, targetNodeRid, operationKind, actor, reply), error => this.operations.fail(pending.id, error));
|
|
2791
|
+
void this.raw.requestService(targetNodeRid, parts, timeoutMs).then((reply) => this.completeRemoteReply(pending, targetNodeRid, operationKind, actor, reply), (error) => this.operations.fail(pending.id, error));
|
|
2783
2792
|
}
|
|
2784
2793
|
submitActorJoin(pending, actor, targetNodeRid, target, payload, deadlineMs, canonical) {
|
|
2785
2794
|
const actorRoute = canonical === undefined
|
|
@@ -2823,7 +2832,7 @@ class ServiceStatefulRuntime {
|
|
|
2823
2832
|
expectedOwnerLeaseGeneration: target.ownerLeaseGeneration
|
|
2824
2833
|
},
|
|
2825
2834
|
...(payload === undefined ? {} : { payload })
|
|
2826
|
-
}).map(frame => Buffer.from(frame));
|
|
2835
|
+
}).map((frame) => Buffer.from(frame));
|
|
2827
2836
|
}
|
|
2828
2837
|
catch (error) {
|
|
2829
2838
|
this.canonicalActorJoinHandoffs.delete(pending.id);
|
|
@@ -2834,20 +2843,20 @@ class ServiceStatefulRuntime {
|
|
|
2834
2843
|
this.submitRequest(pending, targetNodeRid, parts, Math.max(0, Math.ceil(deadlineMs - performance.now())), 'actorJoin', actor);
|
|
2835
2844
|
return;
|
|
2836
2845
|
}
|
|
2837
|
-
void this.requestDurableOperation(targetNodeRid, parts, pending.id, 'actorJoin', deadlineMs).then(reply => this.completeRemoteReply(pending, targetNodeRid, 'actorJoin', actor, reply), error => {
|
|
2846
|
+
void this.requestDurableOperation(targetNodeRid, parts, pending.id, 'actorJoin', deadlineMs).then((reply) => this.completeRemoteReply(pending, targetNodeRid, 'actorJoin', actor, reply), (error) => {
|
|
2838
2847
|
this.canonicalActorJoinHandoffs.delete(pending.id);
|
|
2839
2848
|
this.operations.fail(pending.id, error);
|
|
2840
2849
|
});
|
|
2841
2850
|
}
|
|
2842
2851
|
submitLocalRequest(ingress, pending, operationKind, actor, deadlineUnixMs) {
|
|
2843
|
-
const canonicalActorJoin = operationKind === 'actorJoin'
|
|
2844
|
-
? (0, service_wire_pilot_codec_generated_1.decodeActorJoin28)(ingress.parts)
|
|
2845
|
-
: undefined;
|
|
2852
|
+
const canonicalActorJoin = operationKind === 'actorJoin' ? (0, service_wire_pilot_codec_generated_1.decodeActorJoin28)(ingress.parts) : undefined;
|
|
2846
2853
|
const decoded = canonicalActorJoin === undefined
|
|
2847
2854
|
? (0, service_stateful_wire_codec_1.decodeStatefulHeader)(ingress.parts[0])
|
|
2848
2855
|
: statefulActorJoinFromCanonical(canonicalActorJoin);
|
|
2849
2856
|
const payloadFrame = canonicalActorJoin?.payload === undefined
|
|
2850
|
-
?
|
|
2857
|
+
? ingress.parts.length < 2
|
|
2858
|
+
? undefined
|
|
2859
|
+
: ingress.parts[1]
|
|
2851
2860
|
: (0, service_wire_m6a_codec_1.encodeApplicationPayload)({
|
|
2852
2861
|
packetName: canonicalActorJoin.payload.packetName,
|
|
2853
2862
|
contentType: canonicalActorJoin.payload.contentType,
|
|
@@ -2945,9 +2954,9 @@ class ServiceStatefulRuntime {
|
|
|
2945
2954
|
reply: (terminalResult, failureCode, replyPayload, tail) => {
|
|
2946
2955
|
if (actorJoinReplyAccepted)
|
|
2947
2956
|
return false;
|
|
2948
|
-
const acceptedJoin = terminalResult === runtime_values_1.RequestResult.Ok
|
|
2949
|
-
|
|
2950
|
-
|
|
2957
|
+
const acceptedJoin = terminalResult === runtime_values_1.RequestResult.Ok &&
|
|
2958
|
+
tail?.kind === 'actorJoin' &&
|
|
2959
|
+
tail.joinResult === 0;
|
|
2951
2960
|
if (acceptedJoin && this.operations.isPending(pending.id)) {
|
|
2952
2961
|
// Commit membership now, but keep the source operation behind
|
|
2953
2962
|
// target OnJoinedActor. Entry finishes on this record; User
|
|
@@ -3021,9 +3030,7 @@ class ServiceStatefulRuntime {
|
|
|
3021
3030
|
void operationKind;
|
|
3022
3031
|
}
|
|
3023
3032
|
completeRemoteReply(pending, targetNodeRid, operationKind, actor, reply) {
|
|
3024
|
-
const canonicalActorJoinHandoffId = operationKind === 'actorJoin'
|
|
3025
|
-
? this.canonicalActorJoinHandoffs.get(pending.id)
|
|
3026
|
-
: undefined;
|
|
3033
|
+
const canonicalActorJoinHandoffId = operationKind === 'actorJoin' ? this.canonicalActorJoinHandoffs.get(pending.id) : undefined;
|
|
3027
3034
|
try {
|
|
3028
3035
|
if (reply.length < 1 || reply.length > 2)
|
|
3029
3036
|
throw new service_wire_m6a_codec_1.ServiceWireProtocolError('Invalid M6B reply parts.');
|
|
@@ -3101,7 +3108,8 @@ class ServiceStatefulRuntime {
|
|
|
3101
3108
|
};
|
|
3102
3109
|
}
|
|
3103
3110
|
validateActorFence(fence) {
|
|
3104
|
-
if (fence.actor.nodeRid !== this.nodeRid ||
|
|
3111
|
+
if (fence.actor.nodeRid !== this.nodeRid ||
|
|
3112
|
+
fence.targetNodeGeneration !== this.nodeGeneration) {
|
|
3105
3113
|
throw new service_stateful_registry_1.ServiceStaleGenerationError('actor', fence.actor.actorId);
|
|
3106
3114
|
}
|
|
3107
3115
|
const actor = this.registry.requireActor(fence.actor);
|
|
@@ -3111,7 +3119,8 @@ class ServiceStatefulRuntime {
|
|
|
3111
3119
|
return actor;
|
|
3112
3120
|
}
|
|
3113
3121
|
validateActorMessageFence(fence) {
|
|
3114
|
-
if (fence.actor.nodeRid !== this.nodeRid ||
|
|
3122
|
+
if (fence.actor.nodeRid !== this.nodeRid ||
|
|
3123
|
+
fence.targetNodeGeneration !== this.nodeGeneration) {
|
|
3115
3124
|
throw new service_stateful_registry_1.ServiceStaleGenerationError('actor', fence.actor.actorId);
|
|
3116
3125
|
}
|
|
3117
3126
|
const actor = this.registry.actor(fence.actor.actorId);
|
|
@@ -3121,7 +3130,8 @@ class ServiceStatefulRuntime {
|
|
|
3121
3130
|
return actor;
|
|
3122
3131
|
}
|
|
3123
3132
|
validateSpotFence(fence) {
|
|
3124
|
-
if (fence.targetNodeRid !== this.nodeRid ||
|
|
3133
|
+
if (fence.targetNodeRid !== this.nodeRid ||
|
|
3134
|
+
fence.targetNodeGeneration !== this.nodeGeneration) {
|
|
3125
3135
|
throw new service_stateful_registry_1.ServiceStaleGenerationError('spot', fence.spot.spotId);
|
|
3126
3136
|
}
|
|
3127
3137
|
const spot = this.registry.requireSpot(fence.spot);
|
|
@@ -3138,7 +3148,8 @@ class ServiceStatefulRuntime {
|
|
|
3138
3148
|
if (spot.state !== 'ready') {
|
|
3139
3149
|
throw (0, framework_errors_internal_1.createInternalFrameworkException)(framework_errors_internal_1.ZLinkFrameworkInternalErrorKind.SpotMoving, `Spot '${fence.spot.spotId}' is not Ready.`);
|
|
3140
3150
|
}
|
|
3141
|
-
if (fence.targetNodeRid !== this.nodeRid ||
|
|
3151
|
+
if (fence.targetNodeRid !== this.nodeRid ||
|
|
3152
|
+
fence.targetNodeGeneration !== this.nodeGeneration) {
|
|
3142
3153
|
throw (0, framework_errors_internal_1.createInternalFrameworkException)(framework_errors_internal_1.ZLinkFrameworkInternalErrorKind.SpotMoving, `Spot '${fence.spot.spotId}' targets an unavailable owner route.`);
|
|
3143
3154
|
}
|
|
3144
3155
|
if (spot.kind === 'entry') {
|
|
@@ -3151,11 +3162,11 @@ class ServiceStatefulRuntime {
|
|
|
3151
3162
|
if (current === undefined) {
|
|
3152
3163
|
throw (0, framework_errors_internal_1.createInternalFrameworkException)(framework_errors_internal_1.ZLinkFrameworkInternalErrorKind.SpotMoving, `Spot '${fence.spot.spotId}' has no current owner route.`);
|
|
3153
3164
|
}
|
|
3154
|
-
if (current.targetNodeRid !== this.nodeRid
|
|
3155
|
-
|
|
3156
|
-
|
|
3157
|
-
|
|
3158
|
-
|
|
3165
|
+
if (current.targetNodeRid !== this.nodeRid ||
|
|
3166
|
+
current.targetNodeGeneration !== this.nodeGeneration ||
|
|
3167
|
+
current.ownerLeaseGeneration !== fence.ownerLeaseGeneration ||
|
|
3168
|
+
(current.spot.generation === fence.spot.generation &&
|
|
3169
|
+
current.authorityOwnerGeneration !== fence.authorityOwnerGeneration)) {
|
|
3159
3170
|
throw (0, framework_errors_internal_1.createInternalFrameworkException)(framework_errors_internal_1.ZLinkFrameworkInternalErrorKind.SpotMoving, `Spot '${fence.spot.spotId}' has a stale owner fence.`);
|
|
3160
3171
|
}
|
|
3161
3172
|
return spot;
|
|
@@ -3212,7 +3223,7 @@ class ServiceStatefulRuntime {
|
|
|
3212
3223
|
current.ingress.parts[1]
|
|
3213
3224
|
];
|
|
3214
3225
|
if (current.wire.kind === 'spotSend') {
|
|
3215
|
-
if (!await this.raw.sendService(state.target.targetNodeRid, parts))
|
|
3226
|
+
if (!(await this.raw.sendService(state.target.targetNodeRid, parts)))
|
|
3216
3227
|
continue;
|
|
3217
3228
|
}
|
|
3218
3229
|
else {
|
|
@@ -3248,11 +3259,11 @@ class ServiceStatefulRuntime {
|
|
|
3248
3259
|
const claim = this.spotMessageFollowSuppression.begin(suppressionFence);
|
|
3249
3260
|
if (claim === undefined)
|
|
3250
3261
|
return;
|
|
3251
|
-
const operationLow = current.ingress.requestSequence !== undefined
|
|
3252
|
-
&& current.ingress.requestSequence !== 0n
|
|
3262
|
+
const operationLow = current.ingress.requestSequence !== undefined && current.ingress.requestSequence !== 0n
|
|
3253
3263
|
? current.ingress.requestSequence
|
|
3254
3264
|
: this.nextMessageFollowOperation++;
|
|
3255
|
-
const accepted = await this.raw.sendService(current.ingress.sourceRoutingId, [
|
|
3265
|
+
const accepted = await this.raw.sendService(current.ingress.sourceRoutingId, [
|
|
3266
|
+
(0, service_stateful_wire_codec_1.encodeMessageFollowHeader)({
|
|
3256
3267
|
source: messageFollowSpotRoute(state.source),
|
|
3257
3268
|
target: messageFollowSpotRoute(target),
|
|
3258
3269
|
hopCount: 1,
|
|
@@ -3263,7 +3274,8 @@ class ServiceStatefulRuntime {
|
|
|
3263
3274
|
low: operationLow
|
|
3264
3275
|
},
|
|
3265
3276
|
originalReplyRouteId: current.ingress.requestSequence ?? 0n
|
|
3266
|
-
})
|
|
3277
|
+
})
|
|
3278
|
+
]);
|
|
3267
3279
|
if (accepted) {
|
|
3268
3280
|
this.spotMessageFollowSuppression.markSent(claim);
|
|
3269
3281
|
}
|
|
@@ -3324,16 +3336,16 @@ class ServiceStatefulRuntime {
|
|
|
3324
3336
|
return route;
|
|
3325
3337
|
}
|
|
3326
3338
|
tryBoundSessionSendFence(actor, senderFence) {
|
|
3327
|
-
if (senderFence === undefined
|
|
3328
|
-
|
|
3329
|
-
|
|
3330
|
-
|
|
3339
|
+
if (senderFence === undefined ||
|
|
3340
|
+
senderFence.targetNodeGeneration !== this.nodeGeneration ||
|
|
3341
|
+
senderFence.authorityOwnerGeneration <= 0n ||
|
|
3342
|
+
senderFence.ownerLeaseGeneration <= 0n) {
|
|
3331
3343
|
return undefined;
|
|
3332
3344
|
}
|
|
3333
3345
|
const local = actor.nodeRid === this.nodeRid ? this.registry.actor(actor.actorId) : undefined;
|
|
3334
|
-
if (local === undefined
|
|
3335
|
-
|
|
3336
|
-
|
|
3346
|
+
if (local === undefined ||
|
|
3347
|
+
!sameActorRef(local.ref, actor) ||
|
|
3348
|
+
local.authorityOwnerGeneration !== senderFence.authorityOwnerGeneration) {
|
|
3337
3349
|
return undefined;
|
|
3338
3350
|
}
|
|
3339
3351
|
return {
|
|
@@ -3364,10 +3376,10 @@ class ServiceStatefulRuntime {
|
|
|
3364
3376
|
// application admission (spec 15 section 4.2 / spec 51 section 9).
|
|
3365
3377
|
// Object/authority/lease are bounded counters. Node lifecycle is a
|
|
3366
3378
|
// full-range opaque token, where only zero represents absence.
|
|
3367
|
-
if (actor.generation <= 0n
|
|
3368
|
-
|
|
3369
|
-
|
|
3370
|
-
|
|
3379
|
+
if (actor.generation <= 0n ||
|
|
3380
|
+
fence.targetNodeGeneration === 0n ||
|
|
3381
|
+
fence.authorityOwnerGeneration <= 0n ||
|
|
3382
|
+
fence.ownerLeaseGeneration <= 0n) {
|
|
3371
3383
|
return undefined;
|
|
3372
3384
|
}
|
|
3373
3385
|
return {
|
|
@@ -3389,9 +3401,9 @@ class ServiceStatefulRuntime {
|
|
|
3389
3401
|
};
|
|
3390
3402
|
}
|
|
3391
3403
|
const route = this.spotRoutes.get(spotKey(spot));
|
|
3392
|
-
return route !== undefined
|
|
3393
|
-
|
|
3394
|
-
|
|
3404
|
+
return route !== undefined &&
|
|
3405
|
+
route.targetNodeRid === targetNodeRid &&
|
|
3406
|
+
sameSpotRef(route.spot, spot)
|
|
3395
3407
|
? route
|
|
3396
3408
|
: undefined;
|
|
3397
3409
|
}
|
|
@@ -3417,23 +3429,23 @@ class ServiceStatefulRuntime {
|
|
|
3417
3429
|
const { targetNodeRid, spot, targetNodeGeneration } = requested;
|
|
3418
3430
|
if (targetNodeRid === this.nodeRid) {
|
|
3419
3431
|
const local = this.registry.spot(spot.spotId);
|
|
3420
|
-
if (local?.kind === 'entry'
|
|
3421
|
-
|
|
3422
|
-
|
|
3423
|
-
|
|
3424
|
-
|
|
3432
|
+
if (local?.kind === 'entry' &&
|
|
3433
|
+
sameSpotRef(local.ref, spot) &&
|
|
3434
|
+
targetNodeGeneration === this.nodeGeneration &&
|
|
3435
|
+
requested.authorityOwnerGeneration === local.authorityOwnerGeneration &&
|
|
3436
|
+
isEntrySpotFence(requested)) {
|
|
3425
3437
|
return requested;
|
|
3426
3438
|
}
|
|
3427
3439
|
const current = this.directSpotRoutes.get(directSpotKey(spot.spotId));
|
|
3428
|
-
return local !== undefined
|
|
3429
|
-
|
|
3430
|
-
|
|
3431
|
-
|
|
3432
|
-
|
|
3433
|
-
|
|
3434
|
-
|
|
3435
|
-
|
|
3436
|
-
|
|
3440
|
+
return local !== undefined &&
|
|
3441
|
+
local.state === 'ready' &&
|
|
3442
|
+
targetNodeGeneration === this.nodeGeneration &&
|
|
3443
|
+
current !== undefined &&
|
|
3444
|
+
current.targetNodeRid === this.nodeRid &&
|
|
3445
|
+
current.targetNodeGeneration === this.nodeGeneration &&
|
|
3446
|
+
current.ownerLeaseGeneration === requested.ownerLeaseGeneration &&
|
|
3447
|
+
(current.spot.generation !== requested.spot.generation ||
|
|
3448
|
+
current.authorityOwnerGeneration === requested.authorityOwnerGeneration)
|
|
3437
3449
|
? current
|
|
3438
3450
|
: undefined;
|
|
3439
3451
|
}
|
|
@@ -3460,9 +3472,7 @@ class ServiceStatefulRuntime {
|
|
|
3460
3472
|
const current = this.registry.actor(actor.actorId);
|
|
3461
3473
|
const previousActor = current?.ref ?? actor;
|
|
3462
3474
|
const previousSpot = current?.spot;
|
|
3463
|
-
const previousSpotState = previousSpot === undefined
|
|
3464
|
-
? undefined
|
|
3465
|
-
: this.registry.spot(previousSpot.spotId);
|
|
3475
|
+
const previousSpotState = previousSpot === undefined ? undefined : this.registry.spot(previousSpot.spotId);
|
|
3466
3476
|
const previousMembershipEpoch = current?.membershipEpoch ?? membershipEpoch - 1n;
|
|
3467
3477
|
if (current === undefined) {
|
|
3468
3478
|
this.registry.restoreActor({ ...actor, nodeRid: this.nodeRid }, 'actor', spot, membershipEpoch);
|
|
@@ -3490,11 +3500,11 @@ class ServiceStatefulRuntime {
|
|
|
3490
3500
|
resultCode: 0
|
|
3491
3501
|
}, onTargetLifecycleCompleted);
|
|
3492
3502
|
}
|
|
3493
|
-
if (actor.nodeRid === this.nodeRid
|
|
3494
|
-
|
|
3495
|
-
|
|
3496
|
-
|
|
3497
|
-
|
|
3503
|
+
if (actor.nodeRid === this.nodeRid &&
|
|
3504
|
+
previousSpot !== undefined &&
|
|
3505
|
+
previousSpot.spotId !== spot.spotId &&
|
|
3506
|
+
previousSpotState?.ref.generation === previousSpot.generation &&
|
|
3507
|
+
(previousSpotState.kind === 'entry' || previousSpotState.kind === 'user')) {
|
|
3498
3508
|
// A same-node Core join commits the target membership and publishes
|
|
3499
3509
|
// the source LEFT control separately. Remote joins use the formal
|
|
3500
3510
|
// transfer source terminal instead; the wire ActorRef still identifies
|
|
@@ -3520,12 +3530,30 @@ class ServiceStatefulRuntime {
|
|
|
3520
3530
|
}
|
|
3521
3531
|
}
|
|
3522
3532
|
exports.ServiceStatefulRuntime = ServiceStatefulRuntime;
|
|
3533
|
+
function serviceSpotPublishFailureReason(result, routeReady, closed) {
|
|
3534
|
+
if (closed || result === runtime_values_1.SubmitResult.Terminated)
|
|
3535
|
+
return 'shutdown';
|
|
3536
|
+
switch (result) {
|
|
3537
|
+
case runtime_values_1.SubmitResult.Backpressured:
|
|
3538
|
+
return 'backpressure';
|
|
3539
|
+
case runtime_values_1.SubmitResult.NotAdmitted:
|
|
3540
|
+
case runtime_values_1.SubmitResult.NotConnected:
|
|
3541
|
+
case runtime_values_1.SubmitResult.NotFound:
|
|
3542
|
+
case runtime_values_1.SubmitResult.InvalidHandle:
|
|
3543
|
+
return 'stale_target';
|
|
3544
|
+
default:
|
|
3545
|
+
// RawServiceMeshRuntime exposes failed Core submissions as false. A
|
|
3546
|
+
// ready route therefore identifies queue admission failure; a route
|
|
3547
|
+
// that became unready after selection is a stale target.
|
|
3548
|
+
return routeReady ? 'backpressure' : 'stale_target';
|
|
3549
|
+
}
|
|
3550
|
+
}
|
|
3523
3551
|
function isEntrySpotFence(fence) {
|
|
3524
|
-
return fence.spot.spotId === fence.targetNodeRid
|
|
3525
|
-
|
|
3526
|
-
|
|
3527
|
-
|
|
3528
|
-
|
|
3552
|
+
return (fence.spot.spotId === fence.targetNodeRid &&
|
|
3553
|
+
fence.spot.generation === fence.targetNodeGeneration &&
|
|
3554
|
+
fence.authorityOwnerGeneration === fence.targetNodeGeneration &&
|
|
3555
|
+
fence.ownerLeaseGeneration === fence.targetNodeGeneration &&
|
|
3556
|
+
fence.storeVersion === `entry:${fence.targetNodeGeneration}`);
|
|
3529
3557
|
}
|
|
3530
3558
|
function userSpotDeadline(deadlineUnixMs) {
|
|
3531
3559
|
const controller = new AbortController();
|
|
@@ -3554,10 +3582,10 @@ function durableRequestCanReplay(error) {
|
|
|
3554
3582
|
return false;
|
|
3555
3583
|
return error.operation === 'request'
|
|
3556
3584
|
? error.result === runtime_values_1.RequestResult.NotConnected || error.result === runtime_values_1.RequestResult.TimedOut
|
|
3557
|
-
: error.result === runtime_values_1.SubmitResult.NotConnected
|
|
3558
|
-
|
|
3559
|
-
|
|
3560
|
-
|
|
3585
|
+
: error.result === runtime_values_1.SubmitResult.NotConnected ||
|
|
3586
|
+
error.result === runtime_values_1.SubmitResult.NotFound ||
|
|
3587
|
+
error.result === runtime_values_1.SubmitResult.NotAdmitted ||
|
|
3588
|
+
error.result === runtime_values_1.SubmitResult.Backpressured;
|
|
3561
3589
|
}
|
|
3562
3590
|
function remainingDeadlineMs(deadlineUnixMs) {
|
|
3563
3591
|
const remainingMs = deadlineUnixMs - BigInt(Date.now());
|
|
@@ -3597,26 +3625,26 @@ function actorKey(actor) {
|
|
|
3597
3625
|
return `${actor.actorId}\0${actor.generation}`;
|
|
3598
3626
|
}
|
|
3599
3627
|
function sameSessionBinding(left, right) {
|
|
3600
|
-
return sameActorRef(left.actor, right.actor)
|
|
3601
|
-
|
|
3602
|
-
|
|
3603
|
-
|
|
3628
|
+
return (sameActorRef(left.actor, right.actor) &&
|
|
3629
|
+
left.sessionRid === right.sessionRid &&
|
|
3630
|
+
sameSessionOwnerIdentity(left, right) &&
|
|
3631
|
+
left.bindingGeneration === right.bindingGeneration);
|
|
3604
3632
|
}
|
|
3605
3633
|
function sameSessionIdentity(left, right) {
|
|
3606
|
-
return sameActorRef(left.actor, right.actor)
|
|
3607
|
-
|
|
3608
|
-
|
|
3634
|
+
return (sameActorRef(left.actor, right.actor) &&
|
|
3635
|
+
left.sessionRid === right.sessionRid &&
|
|
3636
|
+
sameSessionOwnerIdentity(left, right));
|
|
3609
3637
|
}
|
|
3610
3638
|
function sameSessionOwnerIdentity(left, right) {
|
|
3611
|
-
return left.sessionOwnerNodeRid === right.sessionOwnerNodeRid
|
|
3612
|
-
|
|
3613
|
-
|
|
3614
|
-
|
|
3639
|
+
return (left.sessionOwnerNodeRid === right.sessionOwnerNodeRid &&
|
|
3640
|
+
left.sessionOwnerNodeGeneration === right.sessionOwnerNodeGeneration &&
|
|
3641
|
+
left.sessionOwnerId === right.sessionOwnerId &&
|
|
3642
|
+
left.sessionOwnerLeaseGeneration === right.sessionOwnerLeaseGeneration);
|
|
3615
3643
|
}
|
|
3616
3644
|
function requireSessionOwnerIdentity(binding) {
|
|
3617
|
-
if (binding.sessionOwnerNodeGeneration === undefined
|
|
3618
|
-
|
|
3619
|
-
|
|
3645
|
+
if (binding.sessionOwnerNodeGeneration === undefined ||
|
|
3646
|
+
binding.sessionOwnerId === undefined ||
|
|
3647
|
+
binding.sessionOwnerLeaseGeneration === undefined) {
|
|
3620
3648
|
throw new service_wire_m6a_codec_1.ServiceWireProtocolError(`Session binding '${binding.sessionRid}' omits its owner lifecycle identity.`);
|
|
3621
3649
|
}
|
|
3622
3650
|
return {
|
|
@@ -3626,30 +3654,30 @@ function requireSessionOwnerIdentity(binding) {
|
|
|
3626
3654
|
};
|
|
3627
3655
|
}
|
|
3628
3656
|
function sessionDeliveryKey(binding) {
|
|
3629
|
-
return `${actorKey(binding.actor)}\0${binding.sessionOwnerNodeRid}\0${binding.sessionRid}`
|
|
3630
|
-
|
|
3631
|
-
|
|
3632
|
-
|
|
3633
|
-
|
|
3657
|
+
return (`${actorKey(binding.actor)}\0${binding.sessionOwnerNodeRid}\0${binding.sessionRid}` +
|
|
3658
|
+
`\0${binding.sessionOwnerNodeGeneration ?? ''}` +
|
|
3659
|
+
`\0${binding.sessionOwnerId ?? ''}` +
|
|
3660
|
+
`\0${binding.sessionOwnerLeaseGeneration ?? ''}` +
|
|
3661
|
+
`\0${binding.bindingGeneration}`);
|
|
3634
3662
|
}
|
|
3635
3663
|
function exactRetiredDelivery(binding, retired) {
|
|
3636
|
-
return binding.sessionRid === retired.sessionRid
|
|
3637
|
-
|
|
3638
|
-
|
|
3639
|
-
|
|
3640
|
-
|
|
3641
|
-
|
|
3664
|
+
return (binding.sessionRid === retired.sessionRid &&
|
|
3665
|
+
binding.sessionOwnerNodeRid === retired.sessionOwnerNodeRid &&
|
|
3666
|
+
binding.sessionOwnerNodeGeneration === retired.sessionOwnerNodeGeneration &&
|
|
3667
|
+
binding.sessionOwnerId === retired.sessionOwnerId &&
|
|
3668
|
+
binding.sessionOwnerLeaseGeneration === retired.sessionOwnerLeaseGeneration &&
|
|
3669
|
+
binding.bindingGeneration === retired.retiredBindingGeneration);
|
|
3642
3670
|
}
|
|
3643
3671
|
function replacementNoticeKey(record) {
|
|
3644
|
-
return `${actorKey(record.actorAuthority.actor)}\0${record.retiredSession.sessionOwnerNodeRid}`
|
|
3645
|
-
|
|
3646
|
-
|
|
3647
|
-
|
|
3648
|
-
|
|
3649
|
-
|
|
3650
|
-
|
|
3651
|
-
|
|
3652
|
-
|
|
3672
|
+
return (`${actorKey(record.actorAuthority.actor)}\0${record.retiredSession.sessionOwnerNodeRid}` +
|
|
3673
|
+
`\0${record.actorAuthority.targetNodeGeneration}` +
|
|
3674
|
+
`\0${record.actorAuthority.authorityOwnerGeneration}` +
|
|
3675
|
+
`\0${record.actorAuthority.ownerLeaseGeneration}` +
|
|
3676
|
+
`\0${record.retiredSession.sessionOwnerNodeGeneration}` +
|
|
3677
|
+
`\0${record.retiredSession.sessionOwnerId}` +
|
|
3678
|
+
`\0${record.retiredSession.sessionOwnerLeaseGeneration}` +
|
|
3679
|
+
`\0${record.retiredSession.sessionRid}` +
|
|
3680
|
+
`\0${record.retiredSession.retiredBindingGeneration}`);
|
|
3653
3681
|
}
|
|
3654
3682
|
function actorAuthorityFromRoute(route) {
|
|
3655
3683
|
return {
|
|
@@ -3666,9 +3694,9 @@ function directSpotKey(spotId) {
|
|
|
3666
3694
|
return spotId;
|
|
3667
3695
|
}
|
|
3668
3696
|
function sameActorRef(left, right) {
|
|
3669
|
-
return left.nodeRid === right.nodeRid
|
|
3670
|
-
|
|
3671
|
-
|
|
3697
|
+
return (left.nodeRid === right.nodeRid &&
|
|
3698
|
+
left.actorId === right.actorId &&
|
|
3699
|
+
left.generation === right.generation);
|
|
3672
3700
|
}
|
|
3673
3701
|
function sameSpotRef(left, right) {
|
|
3674
3702
|
return left.spotId === right.spotId && left.generation === right.generation;
|
|
@@ -3716,30 +3744,30 @@ function matchesExpectedInstanceRoute(current, expected) {
|
|
|
3716
3744
|
: current !== undefined && sameInstanceRoute(current, expected);
|
|
3717
3745
|
}
|
|
3718
3746
|
function sameInstanceRoute(left, right) {
|
|
3719
|
-
return left.targetNodeRid === right.targetNodeRid
|
|
3720
|
-
|
|
3721
|
-
|
|
3722
|
-
|
|
3723
|
-
|
|
3724
|
-
|
|
3725
|
-
|
|
3726
|
-
|
|
3747
|
+
return (left.targetNodeRid === right.targetNodeRid &&
|
|
3748
|
+
left.targetNodeGeneration === right.targetNodeGeneration &&
|
|
3749
|
+
left.targetSpotId === right.targetSpotId &&
|
|
3750
|
+
left.objectGeneration === right.objectGeneration &&
|
|
3751
|
+
left.ownerId === right.ownerId &&
|
|
3752
|
+
left.authorityOwnerGeneration === right.authorityOwnerGeneration &&
|
|
3753
|
+
left.leaseGeneration === right.leaseGeneration &&
|
|
3754
|
+
left.storeVersion === right.storeVersion);
|
|
3727
3755
|
}
|
|
3728
3756
|
function sameInstanceOwnerIdentity(left, right) {
|
|
3729
|
-
return left.targetNodeRid === right.targetNodeRid
|
|
3730
|
-
|
|
3731
|
-
|
|
3732
|
-
|
|
3733
|
-
|
|
3734
|
-
|
|
3735
|
-
|
|
3757
|
+
return (left.targetNodeRid === right.targetNodeRid &&
|
|
3758
|
+
left.targetNodeGeneration === right.targetNodeGeneration &&
|
|
3759
|
+
left.targetSpotId === right.targetSpotId &&
|
|
3760
|
+
left.objectGeneration === right.objectGeneration &&
|
|
3761
|
+
left.ownerId === right.ownerId &&
|
|
3762
|
+
left.authorityOwnerGeneration === right.authorityOwnerGeneration &&
|
|
3763
|
+
left.leaseGeneration === right.leaseGeneration);
|
|
3736
3764
|
}
|
|
3737
3765
|
function sameInstanceApplicationOwner(left, right) {
|
|
3738
|
-
return left.targetNodeRid === right.targetNodeRid
|
|
3739
|
-
|
|
3740
|
-
|
|
3741
|
-
|
|
3742
|
-
|
|
3766
|
+
return (left.targetNodeRid === right.targetNodeRid &&
|
|
3767
|
+
left.targetNodeGeneration === right.targetNodeGeneration &&
|
|
3768
|
+
left.targetSpotId === right.targetSpotId &&
|
|
3769
|
+
left.ownerId === right.ownerId &&
|
|
3770
|
+
left.leaseGeneration === right.leaseGeneration);
|
|
3743
3771
|
}
|
|
3744
3772
|
function matchesExpectedDirectSpotRoute(current, expected) {
|
|
3745
3773
|
return expected === null
|
|
@@ -3760,8 +3788,7 @@ function instanceRouteAsDirectRoute(route) {
|
|
|
3760
3788
|
};
|
|
3761
3789
|
}
|
|
3762
3790
|
function sameDirectSpotRoute(left, right) {
|
|
3763
|
-
return sameDirectSpotRouteIdentity(left, right)
|
|
3764
|
-
&& left.storeVersion === right.storeVersion;
|
|
3791
|
+
return sameDirectSpotRouteIdentity(left, right) && left.storeVersion === right.storeVersion;
|
|
3765
3792
|
}
|
|
3766
3793
|
function messageFollowSpotRoute(route) {
|
|
3767
3794
|
return {
|
|
@@ -3789,38 +3816,37 @@ function spotMessageFollowSuppressionFence(objectKind, source, target) {
|
|
|
3789
3816
|
});
|
|
3790
3817
|
}
|
|
3791
3818
|
function sameMessageFollowSpotSource(current, source) {
|
|
3792
|
-
return current.spot.spotId === source.spot.spotId
|
|
3793
|
-
|
|
3794
|
-
|
|
3795
|
-
|
|
3796
|
-
|
|
3797
|
-
|
|
3819
|
+
return (current.spot.spotId === source.spot.spotId &&
|
|
3820
|
+
current.spot.generation === source.spot.generation &&
|
|
3821
|
+
current.targetNodeRid === source.targetNodeRid &&
|
|
3822
|
+
current.targetNodeGeneration === source.targetNodeGeneration &&
|
|
3823
|
+
current.authorityOwnerGeneration === source.authorityOwnerGeneration &&
|
|
3824
|
+
current.ownerLeaseGeneration === source.ownerLeaseGeneration);
|
|
3798
3825
|
}
|
|
3799
3826
|
function sameDirectSpotRouteIdentity(left, right) {
|
|
3800
|
-
return sameDirectSpotOwnerIdentity(left, right)
|
|
3801
|
-
&& left.spot.generation === right.spot.generation;
|
|
3827
|
+
return sameDirectSpotOwnerIdentity(left, right) && left.spot.generation === right.spot.generation;
|
|
3802
3828
|
}
|
|
3803
3829
|
function sameDirectSpotOwnerIdentity(left, right) {
|
|
3804
|
-
return left.spot.spotId === right.spot.spotId
|
|
3805
|
-
|
|
3806
|
-
|
|
3807
|
-
|
|
3808
|
-
|
|
3830
|
+
return (left.spot.spotId === right.spot.spotId &&
|
|
3831
|
+
left.targetNodeRid === right.targetNodeRid &&
|
|
3832
|
+
left.targetNodeGeneration === right.targetNodeGeneration &&
|
|
3833
|
+
left.authorityOwnerGeneration === right.authorityOwnerGeneration &&
|
|
3834
|
+
left.ownerLeaseGeneration === right.ownerLeaseGeneration);
|
|
3809
3835
|
}
|
|
3810
3836
|
function routeMatchesLocal(route, spot, nodeRid, nodeGeneration) {
|
|
3811
|
-
return route.targetNodeRid === nodeRid
|
|
3812
|
-
|
|
3813
|
-
|
|
3814
|
-
|
|
3815
|
-
|
|
3837
|
+
return (route.targetNodeRid === nodeRid &&
|
|
3838
|
+
route.targetNodeGeneration === nodeGeneration &&
|
|
3839
|
+
route.targetSpotId === spot.ref.spotId &&
|
|
3840
|
+
route.objectGeneration === spot.ref.generation &&
|
|
3841
|
+
route.authorityOwnerGeneration === spot.authorityOwnerGeneration);
|
|
3816
3842
|
}
|
|
3817
3843
|
function instanceOperationKey(record) {
|
|
3818
|
-
return `${record.sourceNodeRid}\0${record.sourceNodeGeneration}\0`
|
|
3819
|
-
|
|
3844
|
+
return (`${record.sourceNodeRid}\0${record.sourceNodeGeneration}\0` +
|
|
3845
|
+
`${record.operation.high}\0${record.operation.low}`);
|
|
3820
3846
|
}
|
|
3821
3847
|
function instanceActivationKey(record) {
|
|
3822
|
-
return `${record.target.targetNodeRid}\0${record.target.targetNodeGeneration}\0`
|
|
3823
|
-
|
|
3848
|
+
return (`${record.target.targetNodeRid}\0${record.target.targetNodeGeneration}\0` +
|
|
3849
|
+
`${record.target.targetSpotId}\0${record.target.stableType}`);
|
|
3824
3850
|
}
|
|
3825
3851
|
function subscriptionKey(channelName, topicFilter) {
|
|
3826
3852
|
if (channelName.length === 0 || topicFilter.length === 0) {
|
|
@@ -3883,11 +3909,7 @@ function instanceOperationParts(headerAndPayload, metadataFrame) {
|
|
|
3883
3909
|
}
|
|
3884
3910
|
if (metadataFrame === undefined)
|
|
3885
3911
|
return headerAndPayload;
|
|
3886
|
-
return [
|
|
3887
|
-
headerAndPayload[0],
|
|
3888
|
-
(0, service_metadata_codec_1.validateServiceMetadataFrame)(metadataFrame),
|
|
3889
|
-
headerAndPayload[1]
|
|
3890
|
-
];
|
|
3912
|
+
return [headerAndPayload[0], (0, service_metadata_codec_1.validateServiceMetadataFrame)(metadataFrame), headerAndPayload[1]];
|
|
3891
3913
|
}
|
|
3892
3914
|
function statefulMailboxData(record) {
|
|
3893
3915
|
return record.stateful;
|