@zlink-systems/framework 0.21.0 → 0.22.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/.tsbuildinfo +1 -1
- package/dist/contracts/Common/ZLinkMessage.js +5 -5
- package/dist/contracts/Configuration/CodecContentType.js +5 -7
- package/dist/contracts/Configuration/DiagnosticsValidation.js +1 -6
- package/dist/contracts/Configuration/EndpointNotation.js +4 -8
- package/dist/contracts/Configuration/Registration.js +14 -11
- package/dist/contracts/Configuration/RegistrationBuilders.js +32 -25
- package/dist/contracts/Configuration/RegistrationNormalizers.js +25 -26
- package/dist/contracts/Configuration/RegistrationValidators.js +36 -38
- package/dist/contracts/Configuration/SendTimeoutValidation.js +4 -4
- package/dist/contracts/Configuration/TimerRegistrationValidator.js +7 -7
- package/dist/contracts/Handlers/JsonContract.js +23 -11
- package/dist/contracts/Spots/SpotKind.js +16 -8
- package/dist/location-store-integration.js +16 -16
- package/dist/nest-integration.js +17 -11
- package/dist/runtime/abort.js +9 -5
- package/dist/runtime/actors/actor-authority-payload-codec.js +12 -16
- package/dist/runtime/actors/actor-authority-publication.js +18 -17
- package/dist/runtime/actors/actor-client.js +83 -63
- package/dist/runtime/actors/actor-context.js +24 -18
- package/dist/runtime/actors/actor-creation.js +4 -3
- package/dist/runtime/actors/actor-handoff.js +89 -92
- package/dist/runtime/actors/actor-local-native-join.js +18 -19
- package/dist/runtime/actors/actor-mailbox.js +1 -1
- package/dist/runtime/actors/actor-message-follow-context.js +24 -21
- package/dist/runtime/actors/actor-packet-relay-wire.js +1 -3
- package/dist/runtime/actors/actor-remote-joiner.js +20 -17
- package/dist/runtime/actors/actor-remote-wire.js +6 -7
- package/dist/runtime/actors/actor-runtime-state.js +87 -81
- package/dist/runtime/actors/actor-transfer-registry.js +3 -5
- package/dist/runtime/actors/bound-session-wire.js +14 -9
- package/dist/runtime/actors/deferred-join-accepted-journal.js +158 -124
- package/dist/runtime/actors/index.js +2 -5
- package/dist/runtime/actors/post-commit-actor-binder.js +3 -6
- package/dist/runtime/actors/post-commit-actor-location.js +1 -1
- package/dist/runtime/actors/spot-actor-dispatch.js +5 -5
- package/dist/runtime/actors/transferred-actor-rollback.js +4 -4
- package/dist/runtime/admission.js +2 -6
- package/dist/runtime/application-jobs/application-ingress-record-owner.js +2 -6
- package/dist/runtime/application-jobs/receive-flow-controller.js +11 -12
- package/dist/runtime/backend/mesh-completion-table.js +1 -3
- package/dist/runtime/backend/mesh-dispatch-pump.js +12 -16
- package/dist/runtime/backend/node/node-backend-adapter-factory.js +1 -3
- package/dist/runtime/backend/node/node-backend-adapter-support.js +26 -17
- package/dist/runtime/backend/node/node-mesh-backend-adapter.js +4 -3
- package/dist/runtime/backend/node/node-raw-binding-port.js +7 -6
- package/dist/runtime/backend/node/node-raw-mesh-backend.js +116 -113
- package/dist/runtime/backend/node/node-socket-backend-adapter.js +12 -13
- package/dist/runtime/backend/runtime-message.js +3 -3
- package/dist/runtime/backend/runtime-values.d.ts +2 -2
- package/dist/runtime/backend/runtime-values.js +4 -5
- package/dist/runtime/channels/channel-clients.js +27 -24
- package/dist/runtime/channels/channel-dispatch-pipeline.js +10 -18
- package/dist/runtime/channels/channel-dispatch-services.js +7 -4
- package/dist/runtime/channels/channel-dispatchers.js +9 -9
- package/dist/runtime/channels/channel-envelope-inspection.js +16 -13
- package/dist/runtime/channels/channel-envelope.js +83 -47
- package/dist/runtime/channels/channel-outbound-operations.js +8 -8
- package/dist/runtime/channels/channel-receive-loops.js +20 -22
- package/dist/runtime/channels/channel-receive-task-tracker.js +1 -1
- package/dist/runtime/channels/channel-runtime-lifecycle.js +61 -56
- package/dist/runtime/channels/channel-runtime-manager.js +18 -9
- package/dist/runtime/channels/channel-socket-registry.js +126 -123
- package/dist/runtime/channels/channel-transports.js +43 -33
- package/dist/runtime/channels/client-server-location-runtime.js +32 -40
- package/dist/runtime/channels/client-server-service-wire.js +29 -22
- package/dist/runtime/channels/dispatch-error-reporter.js +9 -7
- package/dist/runtime/channels/fanout-location-runtime.js +34 -47
- package/dist/runtime/channels/fanout-service-wire.js +3 -5
- package/dist/runtime/channels/local-spot-route-transport.js +7 -1
- package/dist/runtime/channels/route-member-snapshot.js +3 -3
- package/dist/runtime/channels/source-spot-router.js +6 -2
- package/dist/runtime/channels/spot-route-bridge-transport.js +5 -2
- package/dist/runtime/channels/spot-route-dispatch-strategy.js +2 -2
- package/dist/runtime/channels/spot-route-target-resolver.js +6 -6
- package/dist/runtime/diagnostics/index.js +38 -10
- package/dist/runtime/diagnostics/message-flow.js +47 -39
- package/dist/runtime/diagnostics/runtime-metrics.js +18 -9
- package/dist/runtime/diagnostics/runtime-observation-queue.js +8 -10
- package/dist/runtime/diagnostics/topology-runtime-projections.js +17 -10
- package/dist/runtime/execution/index.js +7 -6
- package/dist/runtime/execution/serial-execution-queue.js +12 -18
- package/dist/runtime/execution/state-lane.js +2 -2
- package/dist/runtime/foundation/actor-join-recovery-codec.js +31 -23
- package/dist/runtime/foundation/event-loop-resources.js +4 -4
- package/dist/runtime/foundation/message-follow-suppression-registry.js +4 -4
- package/dist/runtime/foundation/raw-service-mesh-runtime.js +136 -136
- package/dist/runtime/foundation/route-mesh-connection-policy.js +4 -4
- package/dist/runtime/foundation/runtime-state-projections.js +22 -11
- package/dist/runtime/foundation/service-authority-payload-codec.js +13 -15
- package/dist/runtime/foundation/service-discovery-registry.js +35 -33
- package/dist/runtime/foundation/service-instance-activation-recovery-codec.js +20 -22
- package/dist/runtime/foundation/service-liveness-registry.js +16 -12
- package/dist/runtime/foundation/service-maintenance-runtime.js +2 -4
- package/dist/runtime/foundation/service-relocation-aggregate-committer.js +24 -24
- package/dist/runtime/foundation/service-relocation-object-owner.js +6 -6
- package/dist/runtime/foundation/service-relocation-runtime.js +137 -94
- package/dist/runtime/foundation/service-runtime-contracts.js +5 -5
- package/dist/runtime/foundation/service-stateful-registry.js +24 -23
- package/dist/runtime/foundation/service-stateful-runtime.js +416 -438
- package/dist/runtime/foundation/service-stateful-wire-codec.js +95 -98
- package/dist/runtime/foundation/service-topology-registry.js +96 -95
- package/dist/runtime/foundation/service-weighted-selection.js +6 -11
- package/dist/runtime/foundation/service-wire-binary-primitives.js +5 -6
- package/dist/runtime/foundation/service-wire-m6a-codec.js +46 -35
- package/dist/runtime/framework-errors-internal.js +7 -10
- package/dist/runtime/handlers/handler-instance-scope.js +4 -5
- package/dist/runtime/handlers/index.js +3 -1
- package/dist/runtime/host/actor-packet-relay.js +74 -70
- package/dist/runtime/host/actor-placement-coordinator.js +29 -31
- package/dist/runtime/host/actor-runtime-options-factory.js +12 -14
- package/dist/runtime/host/actor-transfer-authority-runtime.js +7 -9
- package/dist/runtime/host/actor-transfer-runtime.js +176 -153
- package/dist/runtime/host/application-job-queue.js +18 -22
- package/dist/runtime/host/bound-session-relay.js +3 -1
- package/dist/runtime/host/channel-runtime-options-factory.js +31 -14
- package/dist/runtime/host/host-capacity-status.js +8 -4
- package/dist/runtime/host/index.js +244 -227
- package/dist/runtime/host/instance-activation-authority.js +93 -96
- package/dist/runtime/host/location-runtime-owner.js +16 -14
- package/dist/runtime/host/mesh-router-resolver.js +11 -13
- package/dist/runtime/host/relocation-direct-transfer.js +10 -9
- package/dist/runtime/host/remote-actor-join-receiver.js +20 -15
- package/dist/runtime/host/remote-actor-packet-target-store.js +18 -22
- package/dist/runtime/host/remote-bound-session-relay.js +97 -73
- package/dist/runtime/host/route-mesh-runtime.js +64 -69
- package/dist/runtime/host/runtime-shutdown.js +1 -2
- package/dist/runtime/host/service-relocation-host-runtime.js +586 -511
- package/dist/runtime/host/spot-address-transport.js +69 -71
- package/dist/runtime/host/spot-runtime-options-factory.js +30 -29
- package/dist/runtime/host/stateful-authority-route-runtime.js +65 -68
- package/dist/runtime/host/user-spot-creation-coordinator.js +61 -67
- package/dist/runtime/locations/actor-location-claims.js +26 -20
- package/dist/runtime/locations/aggregate-inventory-store.js +72 -75
- package/dist/runtime/locations/authority-key-codec.js +7 -7
- package/dist/runtime/locations/auto-connect-loop.js +3 -3
- package/dist/runtime/locations/auto-connect-planner.js +25 -19
- package/dist/runtime/locations/auto-connect-reconciler.js +51 -31
- package/dist/runtime/locations/in-memory-authority-store.js +128 -118
- package/dist/runtime/locations/in-memory-location-store.js +195 -168
- package/dist/runtime/locations/in-memory-provider-location-store.js +8 -10
- package/dist/runtime/locations/key-codec.js +1 -1
- package/dist/runtime/locations/lease-tracker.js +23 -21
- package/dist/runtime/locations/lifecycle.js +4 -5
- package/dist/runtime/locations/location-store-repository.js +368 -324
- package/dist/runtime/locations/opaque-record-key.js +2 -2
- package/dist/runtime/locations/resolvers.js +73 -82
- package/dist/runtime/locations/runtime.js +68 -63
- package/dist/runtime/locations/spot-location-claims.js +39 -35
- package/dist/runtime/messaging/framework-json-v1.js +7 -7
- package/dist/runtime/messaging/packet-name.js +7 -6
- package/dist/runtime/messaging/payload-codec.js +21 -18
- package/dist/runtime/protocol/service_wire_codec.generated.d.ts +30 -2
- package/dist/runtime/protocol/service_wire_codec.generated.js +1671 -234
- package/dist/runtime/routing-id.js +3 -5
- package/dist/runtime/spots/formal-remote-actor-admission-registry.js +35 -31
- package/dist/runtime/spots/formal-remote-actor-transfer-registry.js +1 -2
- package/dist/runtime/spots/index.js +208 -219
- package/dist/runtime/spots/spot-activation-registry.js +15 -14
- package/dist/runtime/spots/spot-activation-state.js +17 -15
- package/dist/runtime/spots/spot-activation.js +33 -16
- package/dist/runtime/spots/spot-actor-admission-coordinator.js +18 -15
- package/dist/runtime/spots/spot-actor-membership.js +1 -3
- package/dist/runtime/spots/spot-actor-packet-dispatch.js +23 -20
- package/dist/runtime/spots/spot-actor-packet-drain.js +12 -10
- package/dist/runtime/spots/spot-actor-packet-relay-dispatch.js +10 -6
- package/dist/runtime/spots/spot-closing.js +3 -7
- package/dist/runtime/spots/spot-context.js +2 -2
- package/dist/runtime/spots/spot-entry-activation.js +13 -14
- package/dist/runtime/spots/spot-handle.js +6 -3
- package/dist/runtime/spots/spot-handler-registry.js +12 -12
- package/dist/runtime/spots/spot-manager-public.js +5 -6
- package/dist/runtime/spots/spot-native-actor-join-admission.js +4 -3
- package/dist/runtime/spots/spot-node-autoconnect.js +15 -18
- package/dist/runtime/spots/spot-node-runtime-manager.js +74 -85
- package/dist/runtime/spots/spot-outbound.js +10 -14
- package/dist/runtime/spots/spot-remote-codec.js +22 -26
- package/dist/runtime/spots/spot-remote-route-codec.js +5 -7
- package/dist/runtime/spots/spot-route-packet-dispatch.js +16 -14
- package/dist/runtime/spots/spot-route-replies.js +4 -6
- package/dist/runtime/spots/spot-routed-actor-admission.js +9 -7
- package/dist/runtime/spots/spot-routed-bound-session-dispatch.js +1 -2
- package/dist/runtime/spots/spot-routed-frame-dispatch.js +5 -5
- package/dist/runtime/spots/spot-routed-spot-packet-dispatch.js +14 -10
- package/dist/runtime/spots/spot-serial-executor.js +5 -8
- package/dist/runtime/spots/spot-serial-turn-executor.js +4 -6
- package/dist/runtime/spots/spot-subscription-dispatch.js +5 -5
- package/dist/runtime/spots/spot-timer.js +25 -29
- package/dist/runtime/streams/actor-session-binding-registry.js +98 -107
- package/dist/runtime/streams/actor-session-lifecycle-coordinator.js +3 -1
- package/dist/runtime/streams/bound-actor-relay-sender.js +18 -16
- package/dist/runtime/streams/bound-session-service.js +8 -9
- package/dist/runtime/streams/index.js +20 -19
- package/dist/runtime/streams/managed-stream.js +32 -30
- package/dist/runtime/streams/native-fallback-bound-session.js +21 -17
- package/dist/runtime/streams/protocol.js +29 -18
- package/dist/runtime/streams/session-actor-coordinator.js +34 -37
- package/dist/runtime/streams/session-context.js +30 -28
- package/dist/runtime/streams/session-provider.js +2 -2
- package/dist/runtime/streams/session-serial-executor.js +1 -2
- package/dist/runtime/streams/stream-frame-factory.js +11 -5
- package/dist/runtime/streams/stream-session-runtime.js +70 -66
- package/dist/runtime/workers/index.js +15 -4
- package/package.json +2 -2
- package/src/contracts/Channels/RouteCalls.ts +6 -1
- package/src/contracts/Common/ZLinkMessage.ts +5 -5
- package/src/contracts/Common/ZLinkMessageMetadata.ts +4 -3
- package/src/contracts/Configuration/Builders.ts +14 -14
- package/src/contracts/Configuration/CodecContentType.ts +8 -10
- package/src/contracts/Configuration/DiagnosticsValidation.ts +1 -6
- package/src/contracts/Configuration/EndpointNotation.ts +11 -11
- package/src/contracts/Configuration/ObjectRoles.ts +1 -3
- package/src/contracts/Configuration/Registration.ts +46 -17
- package/src/contracts/Configuration/RegistrationBuilderPolicy.ts +10 -8
- package/src/contracts/Configuration/RegistrationBuilders.ts +107 -96
- package/src/contracts/Configuration/RegistrationCodecRegistry.ts +9 -3
- package/src/contracts/Configuration/RegistrationNormalizers.ts +116 -84
- package/src/contracts/Configuration/RegistrationTypes.ts +21 -25
- package/src/contracts/Configuration/RegistrationValidators.ts +122 -73
- package/src/contracts/Configuration/RouteChannelInternalState.ts +1 -4
- package/src/contracts/Configuration/RuntimeEndpointConnections.ts +4 -1
- package/src/contracts/Configuration/SendTimeoutValidation.ts +6 -4
- package/src/contracts/Configuration/TimerRegistrationValidator.ts +8 -13
- package/src/contracts/Dispatch/ZLinkDispatchOptions.ts +1 -6
- package/src/contracts/Errors/index.ts +1 -4
- package/src/contracts/Handlers/Attributes.ts +15 -9
- package/src/contracts/Handlers/IZLinkChannelHandlers.ts +24 -4
- package/src/contracts/Handlers/JsonContract.ts +53 -19
- package/src/contracts/Locations/ActorTransfer.ts +1 -5
- package/src/contracts/Locations/Authority.ts +4 -11
- package/src/contracts/Locations/Keys.ts +6 -1
- package/src/contracts/Locations/Options.ts +3 -2
- package/src/contracts/Locations/RelocationStore.ts +1 -4
- package/src/contracts/Locations/Resolvers.ts +5 -5
- package/src/contracts/Locations/RuntimeQuery.ts +6 -2
- package/src/contracts/Locations/Stores.ts +1 -2
- package/src/contracts/Locations/index.ts +2 -8
- package/src/contracts/RouteMesh/Contracts.ts +1 -7
- package/src/contracts/RouteMesh/RuntimeTopology.ts +1 -4
- package/src/contracts/Spots/Contracts.ts +2 -8
- package/src/contracts/Spots/SpotKind.ts +16 -8
- package/src/contracts/Spots/ZLinkSpot.ts +8 -11
- package/src/contracts/Streams/IZLinkSession.ts +0 -1
- package/src/contracts/Streams/IZLinkSessionActor.ts +5 -1
- package/src/contracts/Streams/IZLinkSessionPacketHandler.ts +5 -1
- package/src/internal.ts +5 -4
- package/src/location-store-integration.ts +24 -16
- package/src/nest-integration.ts +40 -25
- package/src/runtime/abort.ts +10 -4
- package/src/runtime/actors/actor-authority-payload-codec.ts +20 -29
- package/src/runtime/actors/actor-authority-publication.ts +92 -77
- package/src/runtime/actors/actor-client.ts +162 -133
- package/src/runtime/actors/actor-context.ts +138 -130
- package/src/runtime/actors/actor-creation.ts +47 -44
- package/src/runtime/actors/actor-execution-context.ts +6 -4
- package/src/runtime/actors/actor-handoff.ts +269 -293
- package/src/runtime/actors/actor-join-deferred-scope.ts +5 -4
- package/src/runtime/actors/actor-lifecycle-snapshot.ts +5 -8
- package/src/runtime/actors/actor-local-native-join.ts +131 -159
- package/src/runtime/actors/actor-mailbox.ts +16 -19
- package/src/runtime/actors/actor-message-follow-context.ts +46 -36
- package/src/runtime/actors/actor-packet-relay-wire.ts +32 -21
- package/src/runtime/actors/actor-remote-joiner.ts +50 -54
- package/src/runtime/actors/actor-remote-wire.ts +9 -13
- package/src/runtime/actors/actor-routed-join-transport.ts +10 -2
- package/src/runtime/actors/actor-runtime-contracts.ts +2 -5
- package/src/runtime/actors/actor-runtime-state.ts +127 -124
- package/src/runtime/actors/actor-transfer-registry.ts +9 -14
- package/src/runtime/actors/actor-transport-delivery-gate.ts +4 -6
- package/src/runtime/actors/bound-session-wire.ts +37 -17
- package/src/runtime/actors/deferred-join-accepted-journal.ts +351 -320
- package/src/runtime/actors/index.ts +43 -86
- package/src/runtime/actors/post-commit-actor-binder.ts +10 -10
- package/src/runtime/actors/post-commit-actor-location.ts +30 -23
- package/src/runtime/actors/spot-actor-dispatch.ts +78 -53
- package/src/runtime/actors/transferred-actor-rollback.ts +18 -13
- package/src/runtime/admission.ts +9 -9
- package/src/runtime/application-jobs/application-ingress-record-owner.ts +5 -15
- package/src/runtime/application-jobs/application-job-queue-handler-start-gate.ts +3 -2
- package/src/runtime/application-jobs/receive-flow-controller.ts +17 -14
- package/src/runtime/backend/contracts/index.ts +73 -52
- package/src/runtime/backend/mesh-actor-session-node-adapter.ts +4 -14
- package/src/runtime/backend/mesh-completion-table.ts +6 -9
- package/src/runtime/backend/mesh-dispatch-pump.ts +38 -30
- package/src/runtime/backend/node/node-backend-adapter-factory.ts +23 -21
- package/src/runtime/backend/node/node-backend-adapter-support.ts +36 -22
- package/src/runtime/backend/node/node-dealer-channel-client-transport.ts +59 -58
- package/src/runtime/backend/node/node-event-loop-poller.ts +2 -10
- package/src/runtime/backend/node/node-mesh-backend-adapter.ts +12 -5
- package/src/runtime/backend/node/node-monitor-backend-adapter.ts +4 -3
- package/src/runtime/backend/node/node-raw-binding-port.ts +29 -29
- package/src/runtime/backend/node/node-raw-mesh-backend.ts +335 -383
- package/src/runtime/backend/node/node-socket-backend-adapter.ts +101 -54
- package/src/runtime/backend/runtime-message.ts +5 -3
- package/src/runtime/backend/runtime-values.ts +10 -7
- package/src/runtime/channels/channel-autoconnect.ts +1 -4
- package/src/runtime/channels/channel-clients.ts +93 -73
- package/src/runtime/channels/channel-dispatch-pipeline.ts +40 -42
- package/src/runtime/channels/channel-dispatch-services.ts +51 -49
- package/src/runtime/channels/channel-dispatchers.ts +152 -96
- package/src/runtime/channels/channel-envelope-inspection.ts +20 -16
- package/src/runtime/channels/channel-envelope.ts +256 -150
- package/src/runtime/channels/channel-multipart.ts +13 -5
- package/src/runtime/channels/channel-outbound-operations.ts +37 -41
- package/src/runtime/channels/channel-receive-loops.ts +102 -98
- package/src/runtime/channels/channel-receive-task-tracker.ts +1 -1
- package/src/runtime/channels/channel-runtime-lifecycle.ts +248 -190
- package/src/runtime/channels/channel-runtime-manager.ts +63 -37
- package/src/runtime/channels/channel-socket-options.ts +3 -10
- package/src/runtime/channels/channel-socket-registry.ts +331 -273
- package/src/runtime/channels/channel-transports.ts +215 -197
- package/src/runtime/channels/client-server-location-runtime.ts +116 -100
- package/src/runtime/channels/client-server-service-wire.ts +37 -36
- package/src/runtime/channels/dispatch-error-reporter.ts +11 -8
- package/src/runtime/channels/fanout-location-runtime.ts +91 -94
- package/src/runtime/channels/fanout-service-wire.ts +5 -12
- package/src/runtime/channels/handler-filter-scope.ts +1 -4
- package/src/runtime/channels/index.ts +1 -4
- package/src/runtime/channels/local-spot-route-transport.ts +20 -5
- package/src/runtime/channels/route-member-snapshot.ts +11 -5
- package/src/runtime/channels/router-socket-spot-route-transport.ts +1 -7
- package/src/runtime/channels/source-spot-router.ts +26 -22
- package/src/runtime/channels/spot-direct-envelope.ts +10 -8
- package/src/runtime/channels/spot-node-route-transport.ts +13 -16
- package/src/runtime/channels/spot-route-bridge-transport.ts +26 -9
- package/src/runtime/channels/spot-route-dispatch-strategy.ts +40 -13
- package/src/runtime/channels/spot-route-target-resolver.ts +18 -9
- package/src/runtime/codecs/index.ts +3 -2
- package/src/runtime/diagnostics/flow-context.ts +12 -3
- package/src/runtime/diagnostics/index.ts +96 -61
- package/src/runtime/diagnostics/internal-event-contracts.ts +87 -33
- package/src/runtime/diagnostics/message-flow.ts +95 -76
- package/src/runtime/diagnostics/runtime-metrics.ts +46 -24
- package/src/runtime/diagnostics/runtime-observation-queue.ts +17 -28
- package/src/runtime/diagnostics/topology-runtime-projections.ts +62 -43
- package/src/runtime/execution/index.ts +18 -26
- package/src/runtime/execution/serial-execution-queue.ts +31 -40
- package/src/runtime/execution/state-lane.ts +2 -2
- package/src/runtime/foundation/actor-join-recovery-codec.ts +69 -51
- package/src/runtime/foundation/event-loop-resources.ts +8 -4
- package/src/runtime/foundation/message-follow-suppression-registry.ts +7 -14
- package/src/runtime/foundation/operation-identity.ts +1 -2
- package/src/runtime/foundation/operation-registry.ts +8 -2
- package/src/runtime/foundation/raw-service-mesh-runtime.ts +312 -385
- package/src/runtime/foundation/route-mesh-connection-policy.ts +7 -8
- package/src/runtime/foundation/runtime-state-projections.ts +24 -23
- package/src/runtime/foundation/service-authority-payload-codec.ts +54 -57
- package/src/runtime/foundation/service-discovery-registry.ts +67 -59
- package/src/runtime/foundation/service-instance-activation-recovery-codec.ts +28 -29
- package/src/runtime/foundation/service-liveness-registry.ts +18 -13
- package/src/runtime/foundation/service-mailbox.ts +14 -14
- package/src/runtime/foundation/service-maintenance-runtime.ts +22 -21
- package/src/runtime/foundation/service-metadata-codec.ts +2 -9
- package/src/runtime/foundation/service-relocation-aggregate-committer.ts +39 -36
- package/src/runtime/foundation/service-relocation-coordinator.ts +1 -4
- package/src/runtime/foundation/service-relocation-object-owner.ts +40 -58
- package/src/runtime/foundation/service-relocation-runtime.ts +292 -216
- package/src/runtime/foundation/service-runtime-contracts.ts +8 -8
- package/src/runtime/foundation/service-session-binding-ingress-port.ts +1 -4
- package/src/runtime/foundation/service-stateful-registry.ts +69 -59
- package/src/runtime/foundation/service-stateful-runtime.ts +1174 -1112
- package/src/runtime/foundation/service-stateful-wire-codec.ts +318 -270
- package/src/runtime/foundation/service-topology-registry.ts +157 -159
- package/src/runtime/foundation/service-weighted-selection.ts +9 -15
- package/src/runtime/foundation/service-wire-binary-primitives.ts +6 -12
- package/src/runtime/foundation/service-wire-m6a-codec.ts +69 -47
- package/src/runtime/framework-errors-internal.ts +31 -30
- package/src/runtime/handlers/handler-instance-scope.ts +18 -29
- package/src/runtime/handlers/index.ts +18 -8
- package/src/runtime/host/actor-packet-relay.ts +290 -261
- package/src/runtime/host/actor-placement-coordinator.ts +165 -150
- package/src/runtime/host/actor-runtime-options-factory.ts +89 -87
- package/src/runtime/host/actor-transfer-authority-runtime.ts +46 -38
- package/src/runtime/host/actor-transfer-runtime.ts +391 -395
- package/src/runtime/host/application-job-queue.ts +32 -48
- package/src/runtime/host/bound-session-relay.ts +7 -9
- package/src/runtime/host/channel-runtime-options-factory.ts +75 -35
- package/src/runtime/host/host-capacity-status.ts +10 -9
- package/src/runtime/host/index.ts +861 -789
- package/src/runtime/host/instance-activation-authority.ts +125 -143
- package/src/runtime/host/location-runtime-owner.ts +38 -26
- package/src/runtime/host/mesh-router-resolver.ts +30 -23
- package/src/runtime/host/relocation-direct-transfer.ts +15 -15
- package/src/runtime/host/relocation-integrity-fault-gate.ts +3 -2
- package/src/runtime/host/remote-actor-join-receiver.ts +43 -34
- package/src/runtime/host/remote-actor-packet-target-store.ts +54 -52
- package/src/runtime/host/remote-bound-session-relay.ts +274 -247
- package/src/runtime/host/route-mesh-runtime-options.ts +1 -3
- package/src/runtime/host/route-mesh-runtime.ts +227 -181
- package/src/runtime/host/runtime-shutdown.ts +4 -3
- package/src/runtime/host/service-relocation-control.ts +14 -5
- package/src/runtime/host/service-relocation-host-runtime.ts +1388 -1165
- package/src/runtime/host/spot-address-transport.ts +284 -237
- package/src/runtime/host/spot-node-runtime-options-factory.ts +14 -8
- package/src/runtime/host/spot-runtime-options-factory.ts +71 -62
- package/src/runtime/host/stateful-authority-route-runtime.ts +117 -116
- package/src/runtime/host/user-spot-creation-coordinator.ts +225 -220
- package/src/runtime/locations/actor-location-claims.ts +61 -49
- package/src/runtime/locations/actor-session-route-claims.ts +1 -4
- package/src/runtime/locations/aggregate-inventory-store.ts +105 -134
- package/src/runtime/locations/authority-key-codec.ts +13 -10
- package/src/runtime/locations/auto-connect-loop.ts +14 -11
- package/src/runtime/locations/auto-connect-planner.ts +42 -31
- package/src/runtime/locations/auto-connect-reconciler.ts +106 -63
- package/src/runtime/locations/canonical-codec.ts +3 -1
- package/src/runtime/locations/creation-operation-id.ts +4 -3
- package/src/runtime/locations/domain-store-contract.ts +13 -7
- package/src/runtime/locations/in-memory-authority-store.ts +232 -199
- package/src/runtime/locations/in-memory-location-store.ts +432 -250
- package/src/runtime/locations/in-memory-provider-location-store.ts +16 -17
- package/src/runtime/locations/internal-store-contracts.ts +95 -38
- package/src/runtime/locations/key-codec.ts +3 -4
- package/src/runtime/locations/lease-tracker.ts +36 -27
- package/src/runtime/locations/lifecycle-runtime.ts +15 -3
- package/src/runtime/locations/lifecycle.ts +33 -28
- package/src/runtime/locations/location-store-repository.ts +1329 -1185
- package/src/runtime/locations/opaque-record-key.ts +4 -9
- package/src/runtime/locations/resolvers.ts +201 -178
- package/src/runtime/locations/runtime.ts +251 -159
- package/src/runtime/locations/spot-location-claims.ts +110 -112
- package/src/runtime/messaging/creation-payload-codec.ts +4 -1
- package/src/runtime/messaging/framework-json-v1.ts +34 -15
- package/src/runtime/messaging/packet-name.ts +8 -6
- package/src/runtime/messaging/payload-codec.ts +70 -50
- package/src/runtime/messaging/submission-result.ts +6 -9
- package/src/runtime/protocol/service_wire_codec.generated.ts +1376 -159
- package/src/runtime/protocol/service_wire_pilot_codec.generated.ts +1 -1
- package/src/runtime/routing-id.ts +10 -7
- package/src/runtime/spots/formal-remote-actor-admission-registry.ts +56 -62
- package/src/runtime/spots/formal-remote-actor-transfer-registry.ts +23 -20
- package/src/runtime/spots/index.ts +593 -563
- package/src/runtime/spots/spot-activation-registry.ts +38 -34
- package/src/runtime/spots/spot-activation-state.ts +43 -51
- package/src/runtime/spots/spot-activation.ts +179 -116
- package/src/runtime/spots/spot-actor-admission-coordinator.ts +110 -78
- package/src/runtime/spots/spot-actor-join-dispatch.ts +57 -41
- package/src/runtime/spots/spot-actor-lifecycle-drain.ts +5 -7
- package/src/runtime/spots/spot-actor-membership.ts +25 -27
- package/src/runtime/spots/spot-actor-packet-dispatch.ts +184 -153
- package/src/runtime/spots/spot-actor-packet-drain.ts +54 -42
- package/src/runtime/spots/spot-actor-packet-relay-dispatch.ts +37 -39
- package/src/runtime/spots/spot-closing.ts +11 -12
- package/src/runtime/spots/spot-context.ts +46 -26
- package/src/runtime/spots/spot-entry-activation.ts +84 -65
- package/src/runtime/spots/spot-handle.ts +17 -15
- package/src/runtime/spots/spot-handler-registry.ts +44 -31
- package/src/runtime/spots/spot-location-claim.ts +5 -4
- package/src/runtime/spots/spot-manager-public.ts +62 -82
- package/src/runtime/spots/spot-native-actor-join-admission.ts +20 -16
- package/src/runtime/spots/spot-node-autoconnect.ts +54 -61
- package/src/runtime/spots/spot-node-runtime-manager.ts +230 -221
- package/src/runtime/spots/spot-outbound.ts +47 -59
- package/src/runtime/spots/spot-publisher-transport.ts +5 -4
- package/src/runtime/spots/spot-remote-codec.ts +66 -65
- package/src/runtime/spots/spot-remote-route-codec.ts +61 -41
- package/src/runtime/spots/spot-route-packet-dispatch.ts +128 -95
- package/src/runtime/spots/spot-route-replies.ts +23 -24
- package/src/runtime/spots/spot-route-reply-wire.ts +3 -2
- package/src/runtime/spots/spot-routed-actor-admission.ts +37 -27
- package/src/runtime/spots/spot-routed-bound-session-dispatch.ts +11 -17
- package/src/runtime/spots/spot-routed-frame-dispatch.ts +18 -15
- package/src/runtime/spots/spot-routed-spot-packet-dispatch.ts +35 -26
- package/src/runtime/spots/spot-routing-internal.ts +1 -4
- package/src/runtime/spots/spot-runtime-ports.ts +5 -5
- package/src/runtime/spots/spot-serial-executor.ts +5 -9
- package/src/runtime/spots/spot-serial-turn-executor.ts +19 -26
- package/src/runtime/spots/spot-subscription-dispatch.ts +56 -46
- package/src/runtime/spots/spot-timer.ts +98 -91
- package/src/runtime/streams/actor-session-binding-registry.ts +277 -235
- package/src/runtime/streams/actor-session-binding-runtime-owner.ts +7 -4
- package/src/runtime/streams/actor-session-lifecycle-coordinator.ts +3 -1
- package/src/runtime/streams/bound-actor-relay-sender.ts +53 -51
- package/src/runtime/streams/bound-session-response-target.ts +29 -8
- package/src/runtime/streams/bound-session-service.ts +39 -39
- package/src/runtime/streams/index.ts +176 -100
- package/src/runtime/streams/managed-stream.ts +98 -87
- package/src/runtime/streams/native-fallback-bound-session.ts +57 -52
- package/src/runtime/streams/protocol.ts +73 -43
- package/src/runtime/streams/session-actor-coordinator.ts +97 -89
- package/src/runtime/streams/session-calls.ts +2 -8
- package/src/runtime/streams/session-context.ts +66 -48
- package/src/runtime/streams/session-provider.ts +5 -7
- package/src/runtime/streams/session-serial-executor.ts +7 -6
- package/src/runtime/streams/stream-binding-runtime-ports.ts +79 -29
- package/src/runtime/streams/stream-frame-factory.ts +55 -38
- package/src/runtime/streams/stream-session-runtime.ts +268 -210
- package/src/runtime/workers/index.ts +68 -29
|
@@ -90,7 +90,7 @@ class ServiceStatefulRuntime {
|
|
|
90
90
|
this.nodeGeneration = nodeGeneration;
|
|
91
91
|
this.registry = new service_stateful_registry_1.ServiceStatefulRegistry(nodeRid, nodeGeneration);
|
|
92
92
|
this.registry.createEntrySpot(nodeRid);
|
|
93
|
-
raw.setServiceIngress(record => this.ingress(record));
|
|
93
|
+
raw.setServiceIngress((record) => this.ingress(record));
|
|
94
94
|
}
|
|
95
95
|
setMailboxDropHandler(handler) {
|
|
96
96
|
this.mailboxDropHandler = handler;
|
|
@@ -125,15 +125,15 @@ class ServiceStatefulRuntime {
|
|
|
125
125
|
restoreActorSessionBinding(actorRef, sessionNodeRid, sessionRid, bindingGeneration) {
|
|
126
126
|
this.requireOpen();
|
|
127
127
|
const actor = this.registry.actor(actorRef.actorId);
|
|
128
|
-
if (actor === undefined
|
|
129
|
-
|
|
130
|
-
|
|
128
|
+
if (actor === undefined ||
|
|
129
|
+
actor.ref.generation !== actorRef.generation ||
|
|
130
|
+
actor.ref.nodeRid !== actorRef.nodeRid) {
|
|
131
131
|
throw new service_stateful_registry_1.ServiceStaleGenerationError('actor', actorRef.actorId);
|
|
132
132
|
}
|
|
133
133
|
const current = this.registry.binding(actor.ref);
|
|
134
|
-
if (current?.bindingGeneration === bindingGeneration
|
|
135
|
-
|
|
136
|
-
|
|
134
|
+
if (current?.bindingGeneration === bindingGeneration &&
|
|
135
|
+
current.sessionOwnerNodeRid === sessionNodeRid &&
|
|
136
|
+
current.sessionRid === sessionRid) {
|
|
137
137
|
return;
|
|
138
138
|
}
|
|
139
139
|
this.registry.installSessionBinding({
|
|
@@ -172,7 +172,8 @@ class ServiceStatefulRuntime {
|
|
|
172
172
|
};
|
|
173
173
|
}
|
|
174
174
|
registerInstanceIntent(instanceType, route, expectedCurrentRoute) {
|
|
175
|
-
if (route.targetNodeRid !== this.nodeRid ||
|
|
175
|
+
if (route.targetNodeRid !== this.nodeRid ||
|
|
176
|
+
route.targetNodeGeneration !== this.nodeGeneration) {
|
|
176
177
|
throw new service_stateful_registry_1.ServiceStaleGenerationError('spot', route.targetSpotId);
|
|
177
178
|
}
|
|
178
179
|
const current = this.instanceIntents.get(route.targetSpotId);
|
|
@@ -209,10 +210,10 @@ class ServiceStatefulRuntime {
|
|
|
209
210
|
instanceSpotApplicationTarget(spotId) {
|
|
210
211
|
const intent = this.instanceIntents.get(spotId);
|
|
211
212
|
const spot = this.registry.spot(spotId);
|
|
212
|
-
if (intent === undefined
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
213
|
+
if (intent === undefined ||
|
|
214
|
+
spot?.kind !== 'instance' ||
|
|
215
|
+
spot.state !== 'ready' ||
|
|
216
|
+
spot.ref.generation !== intent.route.objectGeneration) {
|
|
216
217
|
return undefined;
|
|
217
218
|
}
|
|
218
219
|
return {
|
|
@@ -222,25 +223,24 @@ class ServiceStatefulRuntime {
|
|
|
222
223
|
}
|
|
223
224
|
forgetInstanceIntent(spotId, objectGeneration, authorityOwnerGeneration, storeVersion) {
|
|
224
225
|
const current = this.instanceIntents.get(spotId);
|
|
225
|
-
if (current?.route.objectGeneration === objectGeneration
|
|
226
|
-
|
|
227
|
-
|
|
226
|
+
if (current?.route.objectGeneration === objectGeneration &&
|
|
227
|
+
current.route.authorityOwnerGeneration === authorityOwnerGeneration &&
|
|
228
|
+
(storeVersion === undefined || current.route.storeVersion === storeVersion)) {
|
|
228
229
|
this.instanceIntents.delete(spotId);
|
|
229
230
|
}
|
|
230
231
|
}
|
|
231
232
|
registerInstanceActivationAuthority(authority) {
|
|
232
233
|
this.requireOpen();
|
|
233
|
-
if (this.asyncInstanceAuthority !== undefined
|
|
234
|
-
|
|
234
|
+
if (this.asyncInstanceAuthority !== undefined ||
|
|
235
|
+
(this.instanceAuthority !== undefined && this.instanceAuthority !== authority)) {
|
|
235
236
|
throw new Error('Instance activation authority is already registered.');
|
|
236
237
|
}
|
|
237
238
|
this.instanceAuthority = authority;
|
|
238
239
|
}
|
|
239
240
|
registerAsyncInstanceActivationAuthority(authority) {
|
|
240
241
|
this.requireOpen();
|
|
241
|
-
if (this.instanceAuthority !== undefined
|
|
242
|
-
|
|
243
|
-
&& this.asyncInstanceAuthority !== authority) {
|
|
242
|
+
if (this.instanceAuthority !== undefined ||
|
|
243
|
+
(this.asyncInstanceAuthority !== undefined && this.asyncInstanceAuthority !== authority)) {
|
|
244
244
|
throw new Error('Instance activation authority is already registered.');
|
|
245
245
|
}
|
|
246
246
|
this.asyncInstanceAuthority = authority;
|
|
@@ -253,8 +253,7 @@ class ServiceStatefulRuntime {
|
|
|
253
253
|
}
|
|
254
254
|
registerUserSpotOperationHandler(handler) {
|
|
255
255
|
this.requireOpen();
|
|
256
|
-
if (this.userSpotOperationHandler !== undefined
|
|
257
|
-
&& this.userSpotOperationHandler !== handler) {
|
|
256
|
+
if (this.userSpotOperationHandler !== undefined && this.userSpotOperationHandler !== handler) {
|
|
258
257
|
throw new Error('User Spot operation handler is already registered.');
|
|
259
258
|
}
|
|
260
259
|
this.userSpotOperationHandler = handler;
|
|
@@ -301,11 +300,11 @@ class ServiceStatefulRuntime {
|
|
|
301
300
|
const target = envelope.target;
|
|
302
301
|
if (!matchesExpectedInstanceRoute(this.instanceIntents.get(target.targetSpotId)?.route, expectedCurrentRoute))
|
|
303
302
|
return false;
|
|
304
|
-
if (target.targetNodeRid !== this.nodeRid
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
303
|
+
if (target.targetNodeRid !== this.nodeRid ||
|
|
304
|
+
target.targetNodeGeneration !== this.nodeGeneration ||
|
|
305
|
+
target.targetSpotId !== route.targetSpotId ||
|
|
306
|
+
route.targetNodeRid !== this.nodeRid ||
|
|
307
|
+
route.targetNodeGeneration !== this.nodeGeneration) {
|
|
309
308
|
throw new service_stateful_registry_1.ServiceStaleGenerationError('spot', target.targetSpotId);
|
|
310
309
|
}
|
|
311
310
|
const authority = this.asyncInstanceAuthority;
|
|
@@ -317,15 +316,15 @@ class ServiceStatefulRuntime {
|
|
|
317
316
|
}
|
|
318
317
|
async finishRecoveredInstanceActivation(envelope, route, expectedCurrentRoute) {
|
|
319
318
|
const target = envelope.target;
|
|
320
|
-
const spot = this.registry.spot(target.targetSpotId)
|
|
321
|
-
|
|
319
|
+
const spot = this.registry.spot(target.targetSpotId) ??
|
|
320
|
+
this.registry.restoreSpot({
|
|
322
321
|
spotId: target.targetSpotId,
|
|
323
322
|
generation: route.objectGeneration
|
|
324
323
|
}, 'instance', target.stableType, route.authorityOwnerGeneration);
|
|
325
|
-
if (spot.kind !== 'instance'
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
324
|
+
if (spot.kind !== 'instance' ||
|
|
325
|
+
spot.stableType !== target.stableType ||
|
|
326
|
+
spot.ref.generation !== route.objectGeneration ||
|
|
327
|
+
spot.authorityOwnerGeneration !== route.authorityOwnerGeneration) {
|
|
329
328
|
throw new service_stateful_registry_1.ServiceStaleGenerationError('spot', target.targetSpotId);
|
|
330
329
|
}
|
|
331
330
|
if (!matchesExpectedInstanceRoute(this.instanceIntents.get(target.targetSpotId)?.route, expectedCurrentRoute))
|
|
@@ -337,9 +336,7 @@ class ServiceStatefulRuntime {
|
|
|
337
336
|
target,
|
|
338
337
|
sourceNodeGeneration: envelope.sourceNodeGeneration,
|
|
339
338
|
sourceNodeRid: envelope.sourceNodeRid,
|
|
340
|
-
...(envelope.sourceSpotId === undefined
|
|
341
|
-
? {}
|
|
342
|
-
: { sourceSpotId: envelope.sourceSpotId }),
|
|
339
|
+
...(envelope.sourceSpotId === undefined ? {} : { sourceSpotId: envelope.sourceSpotId }),
|
|
343
340
|
operationKind: envelope.operationKind,
|
|
344
341
|
operation: envelope.operation,
|
|
345
342
|
deadlineUnixMs: envelope.deadlineUnixMs,
|
|
@@ -371,11 +368,11 @@ class ServiceStatefulRuntime {
|
|
|
371
368
|
const target = envelope.target;
|
|
372
369
|
if (!matchesExpectedInstanceRoute(this.instanceIntents.get(target.targetSpotId)?.route, expectedCurrentRoute))
|
|
373
370
|
return false;
|
|
374
|
-
if (target.targetNodeRid !== this.nodeRid
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
371
|
+
if (target.targetNodeRid !== this.nodeRid ||
|
|
372
|
+
target.targetNodeGeneration !== this.nodeGeneration ||
|
|
373
|
+
pending.nodeRid !== this.nodeRid ||
|
|
374
|
+
pending.nodeGeneration !== this.nodeGeneration ||
|
|
375
|
+
pending.meshName !== envelope.targetMeshName) {
|
|
379
376
|
throw new service_stateful_registry_1.ServiceStaleGenerationError('spot', target.targetSpotId);
|
|
380
377
|
}
|
|
381
378
|
const authority = this.asyncInstanceAuthority;
|
|
@@ -408,12 +405,11 @@ class ServiceStatefulRuntime {
|
|
|
408
405
|
return undefined;
|
|
409
406
|
if (currentRoute !== undefined && !sameInstanceRoute(currentRoute, route))
|
|
410
407
|
return undefined;
|
|
411
|
-
const authorityReleased = await this.instanceApplicationLifecycle?.completeTerminal({
|
|
408
|
+
const authorityReleased = (await this.instanceApplicationLifecycle?.completeTerminal({
|
|
412
409
|
targetSpotId: target.targetSpotId,
|
|
413
410
|
stableType: target.stableType,
|
|
414
411
|
objectGeneration: route.objectGeneration
|
|
415
|
-
})
|
|
416
|
-
?? false;
|
|
412
|
+
})) ?? false;
|
|
417
413
|
if (!authorityReleased) {
|
|
418
414
|
if (currentRoute === undefined) {
|
|
419
415
|
this.publishCommittedInstanceRoute(target.stableType, released, null);
|
|
@@ -429,8 +425,8 @@ class ServiceStatefulRuntime {
|
|
|
429
425
|
}
|
|
430
426
|
waitForInstanceApplicationQuiescence(spotId, signal) {
|
|
431
427
|
const key = String(spotId);
|
|
432
|
-
if ((this.pendingInstanceTerminals.get(key) ?? 0) === 0
|
|
433
|
-
|
|
428
|
+
if ((this.pendingInstanceTerminals.get(key) ?? 0) === 0 &&
|
|
429
|
+
(this.pendingInstanceAuthorityTerminals.get(key) ?? 0) === 0) {
|
|
434
430
|
return Promise.resolve();
|
|
435
431
|
}
|
|
436
432
|
if (signal?.aborted === true) {
|
|
@@ -475,8 +471,8 @@ class ServiceStatefulRuntime {
|
|
|
475
471
|
this.spotRoutes.set(spotKey(route.spot), current);
|
|
476
472
|
return;
|
|
477
473
|
}
|
|
478
|
-
if (expectedCurrentRoute !== undefined
|
|
479
|
-
|
|
474
|
+
if (expectedCurrentRoute !== undefined &&
|
|
475
|
+
!matchesExpectedDirectSpotRoute(current, expectedCurrentRoute))
|
|
480
476
|
return;
|
|
481
477
|
if (current !== undefined) {
|
|
482
478
|
if (current.spot.generation < route.spot.generation) {
|
|
@@ -519,8 +515,8 @@ class ServiceStatefulRuntime {
|
|
|
519
515
|
}
|
|
520
516
|
sealSpotMessageFollowIngress(source) {
|
|
521
517
|
this.requireOpen();
|
|
522
|
-
if (source.targetNodeRid !== this.nodeRid
|
|
523
|
-
|
|
518
|
+
if (source.targetNodeRid !== this.nodeRid ||
|
|
519
|
+
source.targetNodeGeneration !== this.nodeGeneration) {
|
|
524
520
|
return undefined;
|
|
525
521
|
}
|
|
526
522
|
const key = spotKey(source.spot);
|
|
@@ -569,18 +565,16 @@ class ServiceStatefulRuntime {
|
|
|
569
565
|
if (!Number.isSafeInteger(durationMs) || durationMs < 0) {
|
|
570
566
|
throw new RangeError('Message Follow duration must be a non-negative safe integer.');
|
|
571
567
|
}
|
|
572
|
-
if (target.spot.spotId !== state.source.spot.spotId
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
568
|
+
if (target.spot.spotId !== state.source.spot.spotId ||
|
|
569
|
+
target.spot.generation !== state.source.spot.generation ||
|
|
570
|
+
target.authorityOwnerGeneration <= state.source.authorityOwnerGeneration ||
|
|
571
|
+
target.targetNodeRid === this.nodeRid) {
|
|
576
572
|
throw new service_stateful_registry_1.ServiceStaleGenerationError('spot', state.source.spot.spotId);
|
|
577
573
|
}
|
|
578
574
|
state.target = freezeDirectSpotRoute(target);
|
|
579
575
|
state.suppressionFence = spotMessageFollowSuppressionFence(state.objectKind, state.source, state.target);
|
|
580
576
|
this.spotMessageFollowSuppression.retainRoute(state.suppressionFence);
|
|
581
|
-
state.expiresAtMs = durationMs === 0
|
|
582
|
-
? Number.MAX_SAFE_INTEGER
|
|
583
|
-
: performance.now() + durationMs;
|
|
577
|
+
state.expiresAtMs = durationMs === 0 ? Number.MAX_SAFE_INTEGER : performance.now() + durationMs;
|
|
584
578
|
await this.drainSpotMessageFollow(state);
|
|
585
579
|
if (durationMs === 0)
|
|
586
580
|
this.removeSpotMessageFollow(state);
|
|
@@ -590,14 +584,14 @@ class ServiceStatefulRuntime {
|
|
|
590
584
|
const exactKey = spotKey(spot);
|
|
591
585
|
const exact = this.spotRoutes.get(exactKey);
|
|
592
586
|
const current = this.directSpotRoutes.get(directSpotKey(spot.spotId));
|
|
593
|
-
if (exact?.authorityOwnerGeneration === authorityOwnerGeneration
|
|
594
|
-
|
|
587
|
+
if (exact?.authorityOwnerGeneration === authorityOwnerGeneration &&
|
|
588
|
+
(storeVersion === undefined || exact.storeVersion === storeVersion)) {
|
|
595
589
|
this.spotRoutes.delete(exactKey);
|
|
596
590
|
}
|
|
597
591
|
const key = directSpotKey(spot.spotId);
|
|
598
|
-
if (current?.authorityOwnerGeneration === authorityOwnerGeneration
|
|
599
|
-
|
|
600
|
-
|
|
592
|
+
if (current?.authorityOwnerGeneration === authorityOwnerGeneration &&
|
|
593
|
+
current.spot.generation === spot.generation &&
|
|
594
|
+
(storeVersion === undefined || current.storeVersion === storeVersion)) {
|
|
601
595
|
this.directSpotRoutes.delete(key);
|
|
602
596
|
}
|
|
603
597
|
}
|
|
@@ -627,8 +621,9 @@ class ServiceStatefulRuntime {
|
|
|
627
621
|
}
|
|
628
622
|
async publishLogicalMulticast(channelName, topic, payload, sourceSpotId = this.nodeRid) {
|
|
629
623
|
await this.enqueueLogicalMulticast(channelName, topic, sourceSpotId, payload);
|
|
630
|
-
const targets = this.raw.topology
|
|
631
|
-
.
|
|
624
|
+
const targets = this.raw.topology
|
|
625
|
+
.peers()
|
|
626
|
+
.filter((peer) => peer.descriptor.channels.some((channel) => channel.name === channelName && channel.weight > 0));
|
|
632
627
|
const header = (0, service_stateful_wire_codec_1.encodeLogicalMulticastHeader)(channelName, topic, sourceSpotId);
|
|
633
628
|
const payloadFrame = (0, service_wire_m6a_codec_1.encodeApplicationPayload)(payload);
|
|
634
629
|
for (const target of targets) {
|
|
@@ -769,7 +764,11 @@ class ServiceStatefulRuntime {
|
|
|
769
764
|
...targetSpot,
|
|
770
765
|
generation: targetSpotGeneration
|
|
771
766
|
});
|
|
772
|
-
this.submitActorJoin(pending, actor, targetNodeRid, target, request, deadlineMs, {
|
|
767
|
+
this.submitActorJoin(pending, actor, targetNodeRid, target, request, deadlineMs, {
|
|
768
|
+
request,
|
|
769
|
+
actorFence,
|
|
770
|
+
local
|
|
771
|
+
});
|
|
773
772
|
return pending;
|
|
774
773
|
}
|
|
775
774
|
joinActorEntrySpot(actor, targetNodeRid, payload, timeoutMs) {
|
|
@@ -837,7 +836,8 @@ class ServiceStatefulRuntime {
|
|
|
837
836
|
const previous = this.registry.binding(actor);
|
|
838
837
|
if (previous !== undefined && sameSessionIdentity(previous, localBinding)) {
|
|
839
838
|
const currentDelivery = this.sessionDeliveries.get(deliveryKey);
|
|
840
|
-
if (currentDelivery !== undefined &&
|
|
839
|
+
if (currentDelivery !== undefined &&
|
|
840
|
+
sameSessionBinding(currentDelivery.binding, previous)) {
|
|
841
841
|
this.sessionDeliveries.set(deliveryKey, {
|
|
842
842
|
...delivery,
|
|
843
843
|
binding: previous
|
|
@@ -868,14 +868,14 @@ class ServiceStatefulRuntime {
|
|
|
868
868
|
this.sendBoundSessionReplacement(previous, actorAuthorityFromRoute(this.tryActorFence(actor) ?? {
|
|
869
869
|
actor,
|
|
870
870
|
targetNodeGeneration: this.nodeGeneration,
|
|
871
|
-
authorityOwnerGeneration: this.registry.actor(actor.actorId)?.authorityOwnerGeneration
|
|
872
|
-
?? actor.generation,
|
|
871
|
+
authorityOwnerGeneration: this.registry.actor(actor.actorId)?.authorityOwnerGeneration ?? actor.generation,
|
|
873
872
|
ownerLeaseGeneration: this.nodeGeneration
|
|
874
873
|
}));
|
|
875
874
|
}
|
|
876
875
|
}
|
|
877
876
|
catch (error) {
|
|
878
|
-
if (installedDelivery !== undefined &&
|
|
877
|
+
if (installedDelivery !== undefined &&
|
|
878
|
+
this.sessionDeliveries.get(deliveryKey) === installedDelivery) {
|
|
879
879
|
this.sessionDeliveries.delete(deliveryKey);
|
|
880
880
|
}
|
|
881
881
|
this.operations.reply(pending.id, failure(error));
|
|
@@ -886,19 +886,21 @@ class ServiceStatefulRuntime {
|
|
|
886
886
|
let bindingActorFence;
|
|
887
887
|
let header;
|
|
888
888
|
try {
|
|
889
|
-
bindingActorFence =
|
|
890
|
-
? this.actorFence(actor)
|
|
891
|
-
|
|
892
|
-
|
|
889
|
+
bindingActorFence =
|
|
890
|
+
actorAuthority === undefined ? this.actorFence(actor) : { actor, ...actorAuthority };
|
|
891
|
+
header = (0, service_stateful_wire_codec_1.encodeBoundSessionBindHeader)(pending.id, bindingActorFence, sessionRid, {
|
|
892
|
+
state: 'active',
|
|
893
|
+
generation
|
|
894
|
+
});
|
|
893
895
|
}
|
|
894
896
|
catch (error) {
|
|
895
897
|
this.operations.fail(pending.id, error);
|
|
896
898
|
return pending;
|
|
897
899
|
}
|
|
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));
|
|
900
|
+
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
901
|
return {
|
|
900
902
|
id: pending.id,
|
|
901
|
-
promise: pending.promise.then(result => {
|
|
903
|
+
promise: pending.promise.then((result) => {
|
|
902
904
|
if (result.terminalResult === runtime_values_1.RequestResult.Ok && result.streamBinding !== undefined) {
|
|
903
905
|
const committed = {
|
|
904
906
|
...delivery,
|
|
@@ -908,10 +910,10 @@ class ServiceStatefulRuntime {
|
|
|
908
910
|
}
|
|
909
911
|
};
|
|
910
912
|
const current = this.sessionDeliveries.get(deliveryKey);
|
|
911
|
-
if (current === previousDelivery
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
913
|
+
if (current === previousDelivery ||
|
|
914
|
+
current === undefined ||
|
|
915
|
+
(sameSessionOwnerIdentity(current.binding, committed.binding) &&
|
|
916
|
+
current.binding.bindingGeneration < committed.binding.bindingGeneration)) {
|
|
915
917
|
if (current !== undefined && !sameSessionBinding(current.binding, committed.binding)) {
|
|
916
918
|
this.retiredSessionDeliveries.set(sessionDeliveryKey(current.binding), current);
|
|
917
919
|
}
|
|
@@ -929,9 +931,9 @@ class ServiceStatefulRuntime {
|
|
|
929
931
|
unbindSession(sessionRid, actor, expectedBindingGeneration, timeoutMs) {
|
|
930
932
|
const pending = this.operations.register(timeoutMs);
|
|
931
933
|
const delivery = this.sessionDeliveries.get(actorKey(actor));
|
|
932
|
-
if (delivery === undefined
|
|
933
|
-
|
|
934
|
-
|
|
934
|
+
if (delivery === undefined ||
|
|
935
|
+
delivery.binding.sessionRid !== sessionRid ||
|
|
936
|
+
delivery.binding.bindingGeneration !== expectedBindingGeneration) {
|
|
935
937
|
this.operations.reply(pending.id, {
|
|
936
938
|
terminalResult: runtime_values_1.RequestResult.NotFound,
|
|
937
939
|
failureCode: ACTOR_ROUTE_STALE
|
|
@@ -949,17 +951,20 @@ class ServiceStatefulRuntime {
|
|
|
949
951
|
}
|
|
950
952
|
return pending;
|
|
951
953
|
}
|
|
952
|
-
const header = (0, service_stateful_wire_codec_1.encodeBoundSessionBindHeader)(pending.id, this.actorFence(actor), sessionRid, {
|
|
954
|
+
const header = (0, service_stateful_wire_codec_1.encodeBoundSessionBindHeader)(pending.id, this.actorFence(actor), sessionRid, {
|
|
955
|
+
state: 'tombstone',
|
|
956
|
+
retiredGeneration: expectedBindingGeneration
|
|
957
|
+
});
|
|
953
958
|
this.submitRequest(pending, actor.nodeRid, [header], timeoutMs, 'streamUnbind');
|
|
954
959
|
return pending;
|
|
955
960
|
}
|
|
956
961
|
sessionBindings(sessionRid) {
|
|
957
962
|
return [...this.sessionDeliveries.values()]
|
|
958
|
-
.map(value => value.binding)
|
|
959
|
-
.filter(binding => binding.sessionRid === sessionRid);
|
|
963
|
+
.map((value) => value.binding)
|
|
964
|
+
.filter((binding) => binding.sessionRid === sessionRid);
|
|
960
965
|
}
|
|
961
966
|
allSessionBindings() {
|
|
962
|
-
return [...this.sessionDeliveries.values()].map(value => value.binding);
|
|
967
|
+
return [...this.sessionDeliveries.values()].map((value) => value.binding);
|
|
963
968
|
}
|
|
964
969
|
async sendSessionToActor(sessionRid, actor, payload) {
|
|
965
970
|
const delivery = this.sessionDeliveries.get(actorKey(actor));
|
|
@@ -983,7 +988,10 @@ class ServiceStatefulRuntime {
|
|
|
983
988
|
if (actorFence === undefined)
|
|
984
989
|
return runtime_values_1.SubmitResult.InvalidState;
|
|
985
990
|
const header = (0, service_stateful_wire_codec_1.encodeBoundSessionSendHeader)(actorFence, expectedBindingGeneration);
|
|
986
|
-
return this.submitOneWay(binding.sessionOwnerNodeRid, [
|
|
991
|
+
return this.submitOneWay(binding.sessionOwnerNodeRid, [
|
|
992
|
+
header,
|
|
993
|
+
(0, service_wire_m6a_codec_1.encodeApplicationPayload)(payload)
|
|
994
|
+
]);
|
|
987
995
|
}
|
|
988
996
|
close() {
|
|
989
997
|
if (this.closed)
|
|
@@ -1026,19 +1034,19 @@ class ServiceStatefulRuntime {
|
|
|
1026
1034
|
// number range (30-34). They are bare infrastructure records and must
|
|
1027
1035
|
// fall through to RawServiceMeshRuntime's relocation ingress instead of
|
|
1028
1036
|
// being decoded as stateful actor/spot work.
|
|
1029
|
-
if (record.command === service_stateful_wire_codec_1.M6bServiceWireCommand.relocationReady
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1037
|
+
if (record.command === service_stateful_wire_codec_1.M6bServiceWireCommand.relocationReady ||
|
|
1038
|
+
record.command === service_stateful_wire_codec_1.M6bServiceWireCommand.relocationData ||
|
|
1039
|
+
record.command === service_stateful_wire_codec_1.M6bServiceWireCommand.replyRelay ||
|
|
1040
|
+
record.command === service_stateful_wire_codec_1.M6bServiceWireCommand.relocationCutover) {
|
|
1033
1041
|
return undefined;
|
|
1034
1042
|
}
|
|
1035
|
-
if (record.command < service_stateful_wire_codec_1.M6bServiceWireCommand.spotSend
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1043
|
+
if (record.command < service_stateful_wire_codec_1.M6bServiceWireCommand.spotSend ||
|
|
1044
|
+
(record.command > service_stateful_wire_codec_1.M6bServiceWireCommand.instanceSpot &&
|
|
1045
|
+
record.command !== service_stateful_wire_codec_1.M6bServiceWireCommand.userSpotCreate &&
|
|
1046
|
+
record.command !== service_stateful_wire_codec_1.M6bServiceWireCommand.userSpotClose &&
|
|
1047
|
+
record.command !== service_stateful_wire_codec_1.M6bServiceWireCommand.actorCreate &&
|
|
1048
|
+
record.command !== service_stateful_wire_codec_1.M6bServiceWireCommand.messageFollow &&
|
|
1049
|
+
record.command !== service_stateful_wire_codec_1.M6bServiceWireCommand.boundSessionReplaced)) {
|
|
1042
1050
|
return undefined;
|
|
1043
1051
|
}
|
|
1044
1052
|
let decoded;
|
|
@@ -1065,19 +1073,17 @@ class ServiceStatefulRuntime {
|
|
|
1065
1073
|
'actorJoin',
|
|
1066
1074
|
'boundSessionSend'
|
|
1067
1075
|
].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)) {
|
|
1076
|
+
const instanceMetadata = decoded.kind === 'instanceSpot' && (record.flags & service_stateful_wire_codec_1.M6bServiceWireFlag.metadata) !== 0;
|
|
1077
|
+
const userSpotInfrastructure = decoded.kind === 'userSpotCreate' ||
|
|
1078
|
+
decoded.kind === 'userSpotClose' ||
|
|
1079
|
+
decoded.kind === 'actorCreate' ||
|
|
1080
|
+
decoded.kind === 'messageFollow' ||
|
|
1081
|
+
decoded.kind === 'boundSessionReplaced';
|
|
1082
|
+
if (record.parts.length < 1 ||
|
|
1083
|
+
record.parts.length > (instanceMetadata ? 3 : 2) ||
|
|
1084
|
+
(hasPayload && decoded.kind !== 'actorJoin' && record.parts.length !== 2) ||
|
|
1085
|
+
(decoded.kind === 'instanceSpot' && record.parts.length !== (instanceMetadata ? 3 : 2)) ||
|
|
1086
|
+
(userSpotInfrastructure && record.parts.length !== 1)) {
|
|
1081
1087
|
return 'protocolError';
|
|
1082
1088
|
}
|
|
1083
1089
|
const metadataFrame = instanceMetadata
|
|
@@ -1091,7 +1097,9 @@ class ServiceStatefulRuntime {
|
|
|
1091
1097
|
payload: Buffer.from(canonicalActorJoin.payload.payload)
|
|
1092
1098
|
};
|
|
1093
1099
|
const payloadFrame = canonicalPayload === undefined
|
|
1094
|
-
?
|
|
1100
|
+
? record.parts.length >= 2
|
|
1101
|
+
? record.parts[record.parts.length - 1]
|
|
1102
|
+
: undefined
|
|
1095
1103
|
: (0, service_wire_m6a_codec_1.encodeApplicationPayload)(canonicalPayload);
|
|
1096
1104
|
try {
|
|
1097
1105
|
return await this.handleIngress(record, decoded, payloadFrame, metadataFrame, canonicalActorJoin, canonicalPayload);
|
|
@@ -1107,9 +1115,9 @@ class ServiceStatefulRuntime {
|
|
|
1107
1115
|
return 'protocolError';
|
|
1108
1116
|
if (error instanceof contracts_1.ZLinkFrameworkException) {
|
|
1109
1117
|
const kind = (0, framework_errors_internal_1.internalFrameworkErrorKind)(error);
|
|
1110
|
-
if (kind === framework_errors_internal_1.ZLinkFrameworkInternalErrorKind.RequestTargetNotFound
|
|
1111
|
-
|
|
1112
|
-
|
|
1118
|
+
if (kind === framework_errors_internal_1.ZLinkFrameworkInternalErrorKind.RequestTargetNotFound ||
|
|
1119
|
+
kind === framework_errors_internal_1.ZLinkFrameworkInternalErrorKind.SpotMoving ||
|
|
1120
|
+
kind === framework_errors_internal_1.ZLinkFrameworkInternalErrorKind.SpotGenerationStale) {
|
|
1113
1121
|
return 'protocolError';
|
|
1114
1122
|
}
|
|
1115
1123
|
}
|
|
@@ -1125,9 +1133,8 @@ class ServiceStatefulRuntime {
|
|
|
1125
1133
|
async handleIngress(ingress, record, payloadFrame, metadataFrame, canonicalActorJoin, canonicalActorJoinPayload) {
|
|
1126
1134
|
switch (record.kind) {
|
|
1127
1135
|
case 'messageFollow': {
|
|
1128
|
-
if (record.source.kind !== record.target.kind
|
|
1129
|
-
|
|
1130
|
-
<= record.source.authorityOwnerGeneration) {
|
|
1136
|
+
if (record.source.kind !== record.target.kind ||
|
|
1137
|
+
record.target.authorityOwnerGeneration <= record.source.authorityOwnerGeneration) {
|
|
1131
1138
|
throw new service_wire_m6a_codec_1.ServiceWireProtocolError('Message Follow target owner generation must increase at every hop.');
|
|
1132
1139
|
}
|
|
1133
1140
|
if (record.source.targetNodeRid !== ingress.sourceRoutingId) {
|
|
@@ -1139,8 +1146,7 @@ class ServiceStatefulRuntime {
|
|
|
1139
1146
|
}
|
|
1140
1147
|
const targetGeneration = record.target.targetNodeRid === this.nodeRid
|
|
1141
1148
|
? this.nodeGeneration
|
|
1142
|
-
: this.raw.topology.peer(record.target.targetNodeRid)?.descriptor
|
|
1143
|
-
.lifecycleGeneration;
|
|
1149
|
+
: this.raw.topology.peer(record.target.targetNodeRid)?.descriptor.lifecycleGeneration;
|
|
1144
1150
|
if (targetGeneration !== record.target.targetNodeGeneration) {
|
|
1145
1151
|
throw new service_wire_m6a_codec_1.ServiceWireProtocolError('Message Follow target route is not the current topology target.');
|
|
1146
1152
|
}
|
|
@@ -1150,8 +1156,7 @@ class ServiceStatefulRuntime {
|
|
|
1150
1156
|
else {
|
|
1151
1157
|
const directKey = directSpotKey(record.source.spot.spotId);
|
|
1152
1158
|
const current = this.directSpotRoutes.get(directKey);
|
|
1153
|
-
if (current !== undefined
|
|
1154
|
-
&& sameMessageFollowSpotSource(current, record.source)) {
|
|
1159
|
+
if (current !== undefined && sameMessageFollowSpotSource(current, record.source)) {
|
|
1155
1160
|
this.directSpotRoutes.delete(directKey);
|
|
1156
1161
|
const exactKey = spotKey(record.source.spot);
|
|
1157
1162
|
const exact = this.spotRoutes.get(exactKey);
|
|
@@ -1186,8 +1191,8 @@ class ServiceStatefulRuntime {
|
|
|
1186
1191
|
: this.validateActorFence(record.target);
|
|
1187
1192
|
if (record.boundSession !== undefined) {
|
|
1188
1193
|
const binding = this.registry.validateBoundSession(record.target.actor, record.boundSession.bindingGeneration);
|
|
1189
|
-
if (binding.sessionRid !== record.boundSession.sessionRid
|
|
1190
|
-
|
|
1194
|
+
if (binding.sessionRid !== record.boundSession.sessionRid ||
|
|
1195
|
+
binding.sessionOwnerNodeRid !== ingress.sourceRoutingId) {
|
|
1191
1196
|
throw new service_stateful_registry_1.ServiceStaleGenerationError('binding', record.target.actor.actorId);
|
|
1192
1197
|
}
|
|
1193
1198
|
}
|
|
@@ -1251,8 +1256,8 @@ class ServiceStatefulRuntime {
|
|
|
1251
1256
|
void this.continueMissingInstanceActivation(ownedIngress, record, payloadFrame, undefined, metadataFrame).finally(() => ownedIngress.applicationJobOwner?.close());
|
|
1252
1257
|
return 'infrastructure';
|
|
1253
1258
|
}
|
|
1254
|
-
if (record.activation === 'ready'
|
|
1255
|
-
|
|
1259
|
+
if (record.activation === 'ready' &&
|
|
1260
|
+
this.needsInstanceApplicationMaterialization(ingress, record)) {
|
|
1256
1261
|
const ownedIngress = shareIngressOwnership(ingress);
|
|
1257
1262
|
void this.continueReadyInstanceMaterialization(ownedIngress, record, payloadFrame, metadataFrame).finally(() => ownedIngress.applicationJobOwner?.close());
|
|
1258
1263
|
return 'infrastructure';
|
|
@@ -1303,10 +1308,10 @@ class ServiceStatefulRuntime {
|
|
|
1303
1308
|
return 'application';
|
|
1304
1309
|
}
|
|
1305
1310
|
const directReply = record.operationKind === 'request'
|
|
1306
|
-
? localReply ?? this.replyPort(ingress, record.replyRouteId, 'instanceSpotRequest')
|
|
1311
|
+
? (localReply ?? this.replyPort(ingress, record.replyRouteId, 'instanceSpotRequest'))
|
|
1307
1312
|
: undefined;
|
|
1308
|
-
const applicationTarget = applicationTargetOverride
|
|
1309
|
-
|
|
1313
|
+
const applicationTarget = applicationTargetOverride ??
|
|
1314
|
+
(record.activation === 'missing'
|
|
1310
1315
|
? {
|
|
1311
1316
|
targetSpotId: record.target.targetSpotId,
|
|
1312
1317
|
stableType: record.target.stableType,
|
|
@@ -1342,10 +1347,10 @@ class ServiceStatefulRuntime {
|
|
|
1342
1347
|
? {
|
|
1343
1348
|
reply: onTerminalCompletion === undefined
|
|
1344
1349
|
? directReply
|
|
1345
|
-
: (
|
|
1350
|
+
: (...reply) => {
|
|
1346
1351
|
deferredReply = reply;
|
|
1347
1352
|
return true;
|
|
1348
|
-
}
|
|
1353
|
+
}
|
|
1349
1354
|
}
|
|
1350
1355
|
: {})
|
|
1351
1356
|
});
|
|
@@ -1413,8 +1418,7 @@ class ServiceStatefulRuntime {
|
|
|
1413
1418
|
if (this.closed)
|
|
1414
1419
|
return;
|
|
1415
1420
|
const latestRoute = this.instanceIntents.get(record.route.targetSpotId)?.route;
|
|
1416
|
-
const refreshedRecord = latestRoute !== undefined
|
|
1417
|
-
&& sameInstanceApplicationOwner(latestRoute, record.route)
|
|
1421
|
+
const refreshedRecord = latestRoute !== undefined && sameInstanceApplicationOwner(latestRoute, record.route)
|
|
1418
1422
|
? { ...record, route: latestRoute }
|
|
1419
1423
|
: record;
|
|
1420
1424
|
const spot = this.requireInstanceActivation(ingress, refreshedRecord);
|
|
@@ -1437,15 +1441,15 @@ class ServiceStatefulRuntime {
|
|
|
1437
1441
|
stableType: target.stableType,
|
|
1438
1442
|
objectGeneration: route.objectGeneration
|
|
1439
1443
|
};
|
|
1440
|
-
return () => completion ??= (async () => {
|
|
1444
|
+
return () => (completion ??= (async () => {
|
|
1441
1445
|
let authorityCompletionSignaled = false;
|
|
1442
1446
|
try {
|
|
1443
1447
|
const released = await this.asyncInstanceAuthority?.complete(target, route);
|
|
1444
1448
|
this.completeInstanceAuthorityOperation(target.targetSpotId);
|
|
1445
1449
|
authorityCompletionSignaled = true;
|
|
1446
1450
|
if (released !== undefined) {
|
|
1447
|
-
const authorityReleased = await this.instanceApplicationLifecycle?.completeTerminal(applicationTarget)
|
|
1448
|
-
|
|
1451
|
+
const authorityReleased = (await this.instanceApplicationLifecycle?.completeTerminal(applicationTarget)) ??
|
|
1452
|
+
false;
|
|
1449
1453
|
if (!authorityReleased) {
|
|
1450
1454
|
this.replaceCommittedInstanceRoute(target.stableType, route, released);
|
|
1451
1455
|
}
|
|
@@ -1459,17 +1463,16 @@ class ServiceStatefulRuntime {
|
|
|
1459
1463
|
this.completeInstanceAuthorityOperation(target.targetSpotId);
|
|
1460
1464
|
}
|
|
1461
1465
|
}
|
|
1462
|
-
})();
|
|
1466
|
+
})());
|
|
1463
1467
|
}
|
|
1464
1468
|
instanceApplicationTerminalCompletion(target) {
|
|
1465
1469
|
return async () => {
|
|
1466
|
-
const authorityReleased = await this.instanceApplicationLifecycle?.completeTerminal(target)
|
|
1467
|
-
?? false;
|
|
1470
|
+
const authorityReleased = (await this.instanceApplicationLifecycle?.completeTerminal(target)) ?? false;
|
|
1468
1471
|
if (!authorityReleased)
|
|
1469
1472
|
return;
|
|
1470
1473
|
const current = this.instanceIntents.get(target.targetSpotId);
|
|
1471
|
-
if (current?.instanceType === target.stableType
|
|
1472
|
-
|
|
1474
|
+
if (current?.instanceType === target.stableType &&
|
|
1475
|
+
current.route.objectGeneration === target.objectGeneration) {
|
|
1473
1476
|
this.forgetClosedInstanceRoute(current.route);
|
|
1474
1477
|
}
|
|
1475
1478
|
};
|
|
@@ -1524,8 +1527,8 @@ class ServiceStatefulRuntime {
|
|
|
1524
1527
|
this.pendingInstanceAuthorityTerminals.set(key, pending - 1);
|
|
1525
1528
|
}
|
|
1526
1529
|
completeInstanceApplicationWaitersIfQuiescent(key) {
|
|
1527
|
-
if ((this.pendingInstanceTerminals.get(key) ?? 0) !== 0
|
|
1528
|
-
|
|
1530
|
+
if ((this.pendingInstanceTerminals.get(key) ?? 0) !== 0 ||
|
|
1531
|
+
(this.pendingInstanceAuthorityTerminals.get(key) ?? 0) !== 0)
|
|
1529
1532
|
return;
|
|
1530
1533
|
const waiters = this.instanceApplicationWaiters.get(key);
|
|
1531
1534
|
if (waiters === undefined)
|
|
@@ -1571,8 +1574,8 @@ class ServiceStatefulRuntime {
|
|
|
1571
1574
|
}
|
|
1572
1575
|
requireInstanceActivation(ingress, record) {
|
|
1573
1576
|
const readyRoute = record.activation === 'ready' ? record.route : undefined;
|
|
1574
|
-
const spotId = readyRoute?.targetSpotId
|
|
1575
|
-
|
|
1577
|
+
const spotId = readyRoute?.targetSpotId ??
|
|
1578
|
+
(record.activation === 'missing' ? record.target.targetSpotId : undefined);
|
|
1576
1579
|
if (spotId === undefined)
|
|
1577
1580
|
throw new service_stateful_registry_1.ServiceStaleGenerationError('spot', 'unknown');
|
|
1578
1581
|
this.validateInstanceIngress(ingress, record);
|
|
@@ -1580,16 +1583,16 @@ class ServiceStatefulRuntime {
|
|
|
1580
1583
|
return this.activateMissingInstance(record);
|
|
1581
1584
|
}
|
|
1582
1585
|
const { intent, route } = this.requireReadyInstanceApplicationRoute(ingress, record);
|
|
1583
|
-
const spot = this.registry.spot(route.targetSpotId)
|
|
1584
|
-
|
|
1586
|
+
const spot = this.registry.spot(route.targetSpotId) ??
|
|
1587
|
+
this.registry.restoreSpot({
|
|
1585
1588
|
spotId: route.targetSpotId,
|
|
1586
1589
|
generation: route.objectGeneration
|
|
1587
1590
|
}, 'instance', intent.instanceType, route.authorityOwnerGeneration);
|
|
1588
|
-
if (spot.state !== 'ready'
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1591
|
+
if (spot.state !== 'ready' ||
|
|
1592
|
+
spot.kind !== 'instance' ||
|
|
1593
|
+
spot.stableType !== intent.instanceType ||
|
|
1594
|
+
spot.ref.generation !== route.objectGeneration ||
|
|
1595
|
+
spot.authorityOwnerGeneration !== route.authorityOwnerGeneration) {
|
|
1593
1596
|
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
1597
|
}
|
|
1595
1598
|
return spot;
|
|
@@ -1605,9 +1608,9 @@ class ServiceStatefulRuntime {
|
|
|
1605
1608
|
// instead of exposing a transient NotFound result to a following
|
|
1606
1609
|
// request. A mismatched or absent local projection remains NotFound.
|
|
1607
1610
|
const local = this.registry.spot(record.route.targetSpotId);
|
|
1608
|
-
if (local?.kind === 'instance'
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
+
if (local?.kind === 'instance' &&
|
|
1612
|
+
local.state === 'ready' &&
|
|
1613
|
+
routeMatchesLocal(record.route, local, this.nodeRid, this.nodeGeneration)) {
|
|
1611
1614
|
this.publishCommittedInstanceRoute(local.stableType, record.route);
|
|
1612
1615
|
intent = this.instanceIntents.get(record.route.targetSpotId);
|
|
1613
1616
|
}
|
|
@@ -1622,16 +1625,16 @@ class ServiceStatefulRuntime {
|
|
|
1622
1625
|
if (!sameInstanceApplicationOwner(current, record.route)) {
|
|
1623
1626
|
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
1627
|
}
|
|
1625
|
-
if (current.objectGeneration === record.route.objectGeneration
|
|
1626
|
-
|
|
1628
|
+
if (current.objectGeneration === record.route.objectGeneration &&
|
|
1629
|
+
current.authorityOwnerGeneration !== record.route.authorityOwnerGeneration) {
|
|
1627
1630
|
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
1631
|
}
|
|
1629
1632
|
return { intent, route: current };
|
|
1630
1633
|
}
|
|
1631
1634
|
validateInstanceIngress(ingress, record) {
|
|
1632
1635
|
const expectedSourceGeneration = this.peerGeneration(record.sourceNodeRid);
|
|
1633
|
-
if (record.sourceNodeRid !== ingress.sourceRoutingId
|
|
1634
|
-
|
|
1636
|
+
if (record.sourceNodeRid !== ingress.sourceRoutingId ||
|
|
1637
|
+
record.sourceNodeGeneration !== expectedSourceGeneration) {
|
|
1635
1638
|
if (record.activation === 'ready') {
|
|
1636
1639
|
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
1640
|
}
|
|
@@ -1640,9 +1643,9 @@ class ServiceStatefulRuntime {
|
|
|
1640
1643
|
}
|
|
1641
1644
|
activateMissingInstance(record) {
|
|
1642
1645
|
const target = record.target;
|
|
1643
|
-
if (target.targetNodeRid !== this.nodeRid
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
+
if (target.targetNodeRid !== this.nodeRid ||
|
|
1647
|
+
target.targetNodeGeneration !== this.nodeGeneration ||
|
|
1648
|
+
record.deadlineUnixMs < BigInt(Date.now())) {
|
|
1646
1649
|
throw new service_stateful_registry_1.ServiceStaleGenerationError('spot', target.targetSpotId);
|
|
1647
1650
|
}
|
|
1648
1651
|
if (this.instanceApplicationLifecycle?.isIdleEvicting?.(target) === true) {
|
|
@@ -1655,10 +1658,10 @@ class ServiceStatefulRuntime {
|
|
|
1655
1658
|
const local = this.registry.spot(target.targetSpotId);
|
|
1656
1659
|
const current = authority.read(target);
|
|
1657
1660
|
if (local !== undefined) {
|
|
1658
|
-
if (local.kind !== 'instance'
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
|
|
1661
|
+
if (local.kind !== 'instance' ||
|
|
1662
|
+
local.stableType !== target.stableType ||
|
|
1663
|
+
current.kind !== 'ready' ||
|
|
1664
|
+
!routeMatchesLocal(current.route, local, this.nodeRid, this.nodeGeneration)) {
|
|
1662
1665
|
throw new service_stateful_registry_1.ServiceStaleGenerationError('spot', target.targetSpotId);
|
|
1663
1666
|
}
|
|
1664
1667
|
return local;
|
|
@@ -1708,9 +1711,9 @@ class ServiceStatefulRuntime {
|
|
|
1708
1711
|
}
|
|
1709
1712
|
async runMissingInstanceActivation(record, payloadFrame, metadataFrame) {
|
|
1710
1713
|
const target = record.target;
|
|
1711
|
-
if (target.targetNodeRid !== this.nodeRid
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
+
if (target.targetNodeRid !== this.nodeRid ||
|
|
1715
|
+
target.targetNodeGeneration !== this.nodeGeneration ||
|
|
1716
|
+
record.deadlineUnixMs < BigInt(Date.now())) {
|
|
1714
1717
|
throw new service_stateful_registry_1.ServiceStaleGenerationError('spot', target.targetSpotId);
|
|
1715
1718
|
}
|
|
1716
1719
|
const authority = this.asyncInstanceAuthority;
|
|
@@ -1734,13 +1737,12 @@ class ServiceStatefulRuntime {
|
|
|
1734
1737
|
if (current.route.targetNodeGeneration !== this.nodeGeneration) {
|
|
1735
1738
|
throw new service_stateful_registry_1.ServiceStaleGenerationError('spot', target.targetSpotId);
|
|
1736
1739
|
}
|
|
1737
|
-
if (local !== undefined
|
|
1738
|
-
|
|
1739
|
-
|| local.stableType !== target.stableType)) {
|
|
1740
|
+
if (local !== undefined &&
|
|
1741
|
+
(local.kind !== 'instance' || local.stableType !== target.stableType)) {
|
|
1740
1742
|
throw new service_stateful_registry_1.ServiceStaleGenerationError('spot', target.targetSpotId);
|
|
1741
1743
|
}
|
|
1742
|
-
if (local !== undefined
|
|
1743
|
-
|
|
1744
|
+
if (local !== undefined &&
|
|
1745
|
+
routeMatchesLocal(current.route, local, this.nodeRid, this.nodeGeneration)) {
|
|
1744
1746
|
return { spot: local, route: current.route };
|
|
1745
1747
|
}
|
|
1746
1748
|
return await this.reconcileReadyInstanceProjection(target, current.route, authority);
|
|
@@ -1748,23 +1750,20 @@ class ServiceStatefulRuntime {
|
|
|
1748
1750
|
if (local !== undefined) {
|
|
1749
1751
|
const lifecycle = this.instanceApplicationLifecycle;
|
|
1750
1752
|
const closing = lifecycle?.isClosing?.(target) === true;
|
|
1751
|
-
let materialized = lifecycle === undefined
|
|
1752
|
-
? undefined
|
|
1753
|
-
: lifecycle.isMaterialized(target);
|
|
1753
|
+
let materialized = lifecycle === undefined ? undefined : lifecycle.isMaterialized(target);
|
|
1754
1754
|
const materializing = lifecycle?.isMaterializing?.(target) === true;
|
|
1755
|
-
if (local.kind !== 'instance'
|
|
1756
|
-
|| local.stableType !== target.stableType) {
|
|
1755
|
+
if (local.kind !== 'instance' || local.stableType !== target.stableType) {
|
|
1757
1756
|
throw new service_stateful_registry_1.ServiceStaleGenerationError('spot', target.targetSpotId);
|
|
1758
1757
|
}
|
|
1759
|
-
const joinsCreating = current.kind === 'creating'
|
|
1760
|
-
|
|
1761
|
-
|
|
1758
|
+
const joinsCreating = current.kind === 'creating' &&
|
|
1759
|
+
local.ref.generation === current.objectGeneration &&
|
|
1760
|
+
local.authorityOwnerGeneration === current.authorityOwnerGeneration;
|
|
1762
1761
|
const replacesClosingProjection = current.kind === 'creating' && closing;
|
|
1763
|
-
if (current.kind === 'missing'
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
1762
|
+
if (current.kind === 'missing' &&
|
|
1763
|
+
!closing &&
|
|
1764
|
+
!materializing &&
|
|
1765
|
+
materialized === true &&
|
|
1766
|
+
lifecycle !== undefined) {
|
|
1768
1767
|
// The durable authority is the ownership source of truth. Its removal
|
|
1769
1768
|
// can become visible before the route reconciler has discarded the
|
|
1770
1769
|
// previous application projection. Converge that orphan here before
|
|
@@ -1783,8 +1782,8 @@ class ServiceStatefulRuntime {
|
|
|
1783
1782
|
// failure.
|
|
1784
1783
|
// If disposal did not remove an orphaned materialization, keep fencing
|
|
1785
1784
|
// it instead of admitting work into two application generations.
|
|
1786
|
-
if ((!joinsCreating && !replacesClosingProjection && current.kind !== 'missing')
|
|
1787
|
-
|
|
1785
|
+
if ((!joinsCreating && !replacesClosingProjection && current.kind !== 'missing') ||
|
|
1786
|
+
(!joinsCreating && !closing && materialized !== false && !materializing)) {
|
|
1788
1787
|
throw new service_stateful_registry_1.ServiceStaleGenerationError('spot', target.targetSpotId);
|
|
1789
1788
|
}
|
|
1790
1789
|
}
|
|
@@ -1845,8 +1844,7 @@ class ServiceStatefulRuntime {
|
|
|
1845
1844
|
acceptsLocalMissingInstancePlacement() {
|
|
1846
1845
|
const topology = this.raw.topology;
|
|
1847
1846
|
const descriptor = topology.localDescriptor?.();
|
|
1848
|
-
return descriptor === undefined
|
|
1849
|
-
|| (descriptor.state === 'serving' && descriptor.placementWeight > 0);
|
|
1847
|
+
return (descriptor === undefined || (descriptor.state === 'serving' && descriptor.placementWeight > 0));
|
|
1850
1848
|
}
|
|
1851
1849
|
async reconcileReadyInstanceProjection(target, route, authority) {
|
|
1852
1850
|
await this.instanceApplicationLifecycle?.materialize(target, route.objectGeneration);
|
|
@@ -1859,15 +1857,14 @@ class ServiceStatefulRuntime {
|
|
|
1859
1857
|
this.publishCommittedInstanceRoute(target.stableType, route);
|
|
1860
1858
|
const confirmed = await authority.read(target);
|
|
1861
1859
|
if (confirmed.kind !== 'ready' || !sameInstanceRoute(confirmed.route, route)) {
|
|
1862
|
-
if (confirmed.kind === 'ready'
|
|
1863
|
-
&& confirmed.route.targetNodeRid !== this.nodeRid) {
|
|
1860
|
+
if (confirmed.kind === 'ready' && confirmed.route.targetNodeRid !== this.nodeRid) {
|
|
1864
1861
|
throw new ServiceInstanceActivationRedirectError(confirmed.route);
|
|
1865
1862
|
}
|
|
1866
1863
|
throw new service_stateful_registry_1.ServiceStaleGenerationError('spot', target.targetSpotId);
|
|
1867
1864
|
}
|
|
1868
1865
|
const current = this.registry.spot(target.targetSpotId);
|
|
1869
|
-
if (current === undefined
|
|
1870
|
-
|
|
1866
|
+
if (current === undefined ||
|
|
1867
|
+
!routeMatchesLocal(confirmed.route, current, this.nodeRid, this.nodeGeneration)) {
|
|
1871
1868
|
throw new service_stateful_registry_1.ServiceStaleGenerationError('spot', target.targetSpotId);
|
|
1872
1869
|
}
|
|
1873
1870
|
return { spot: current, route: confirmed.route };
|
|
@@ -1901,9 +1898,9 @@ class ServiceStatefulRuntime {
|
|
|
1901
1898
|
}
|
|
1902
1899
|
forgetClosedInstanceRoute(route) {
|
|
1903
1900
|
const local = this.registry.spot(route.targetSpotId);
|
|
1904
|
-
if (local?.kind === 'instance'
|
|
1905
|
-
|
|
1906
|
-
|
|
1901
|
+
if (local?.kind === 'instance' &&
|
|
1902
|
+
local.ref.generation === route.objectGeneration &&
|
|
1903
|
+
local.authorityOwnerGeneration === route.authorityOwnerGeneration) {
|
|
1907
1904
|
this.registry.closeSpot(local.ref);
|
|
1908
1905
|
}
|
|
1909
1906
|
this.forgetSpotRoute({ spotId: route.targetSpotId, generation: route.objectGeneration }, route.authorityOwnerGeneration, route.storeVersion);
|
|
@@ -1994,8 +1991,7 @@ class ServiceStatefulRuntime {
|
|
|
1994
1991
|
if (record.binding.state === 'active') {
|
|
1995
1992
|
const actor = this.validateActorFence(record.actor);
|
|
1996
1993
|
const previous = this.registry.binding(actor.ref);
|
|
1997
|
-
const sourceGeneration = ingress.sourceNodeGeneration
|
|
1998
|
-
?? this.peerGeneration(ingress.sourceRoutingId);
|
|
1994
|
+
const sourceGeneration = ingress.sourceNodeGeneration ?? this.peerGeneration(ingress.sourceRoutingId);
|
|
1999
1995
|
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
1996
|
if (previous !== undefined && sameSessionIdentity(previous, binding)) {
|
|
2001
1997
|
// Registry publication is the last step of the first binding owner
|
|
@@ -2032,9 +2028,9 @@ class ServiceStatefulRuntime {
|
|
|
2032
2028
|
authorityOwnerGeneration: actor.authorityOwnerGeneration
|
|
2033
2029
|
}
|
|
2034
2030
|
: undefined);
|
|
2035
|
-
if (terminalResult === runtime_values_1.RequestResult.Ok
|
|
2036
|
-
|
|
2037
|
-
|
|
2031
|
+
if (terminalResult === runtime_values_1.RequestResult.Ok &&
|
|
2032
|
+
replacedBinding !== undefined &&
|
|
2033
|
+
!sameSessionBinding(replacedBinding, completedBinding)) {
|
|
2038
2034
|
this.sendBoundSessionReplacement(replacedBinding, actorAuthorityFromRoute({
|
|
2039
2035
|
...record.actor,
|
|
2040
2036
|
ownerLeaseGeneration: record.actor.ownerLeaseGeneration
|
|
@@ -2068,8 +2064,7 @@ class ServiceStatefulRuntime {
|
|
|
2068
2064
|
if (authority.actor.nodeRid !== ingress.sourceRoutingId) {
|
|
2069
2065
|
return 'protocolError';
|
|
2070
2066
|
}
|
|
2071
|
-
const sourceGeneration = ingress.sourceNodeGeneration
|
|
2072
|
-
?? this.tryPeerGeneration(ingress.sourceRoutingId);
|
|
2067
|
+
const sourceGeneration = ingress.sourceNodeGeneration ?? this.tryPeerGeneration(ingress.sourceRoutingId);
|
|
2073
2068
|
if (sourceGeneration === undefined)
|
|
2074
2069
|
return 'infrastructure';
|
|
2075
2070
|
if (sourceGeneration !== authority.targetNodeGeneration) {
|
|
@@ -2077,10 +2072,10 @@ class ServiceStatefulRuntime {
|
|
|
2077
2072
|
// session that belongs to the new lifecycle.
|
|
2078
2073
|
return 'infrastructure';
|
|
2079
2074
|
}
|
|
2080
|
-
if (record.retiredSession.sessionOwnerNodeRid !== this.nodeRid
|
|
2081
|
-
|
|
2082
|
-
|
|
2083
|
-
|
|
2075
|
+
if (record.retiredSession.sessionOwnerNodeRid !== this.nodeRid ||
|
|
2076
|
+
record.retiredSession.sessionOwnerNodeGeneration !== this.nodeGeneration ||
|
|
2077
|
+
record.retiredSession.sessionOwnerId !== this.nodeRid ||
|
|
2078
|
+
record.retiredSession.sessionOwnerLeaseGeneration !== this.nodeGeneration) {
|
|
2084
2079
|
return 'infrastructure';
|
|
2085
2080
|
}
|
|
2086
2081
|
const actor = authority.actor;
|
|
@@ -2096,13 +2091,11 @@ class ServiceStatefulRuntime {
|
|
|
2096
2091
|
sessionOwnerNodeGeneration: record.retiredSession.sessionOwnerNodeGeneration,
|
|
2097
2092
|
sessionOwnerId: record.retiredSession.sessionOwnerId,
|
|
2098
2093
|
sessionOwnerLeaseGeneration: record.retiredSession.sessionOwnerLeaseGeneration,
|
|
2099
|
-
bindingGeneration: record.retiredSession.retiredBindingGeneration
|
|
2094
|
+
bindingGeneration: record.retiredSession.retiredBindingGeneration
|
|
2100
2095
|
}));
|
|
2101
|
-
const delivery = current !== undefined
|
|
2102
|
-
&& exactRetiredDelivery(current.binding, record.retiredSession)
|
|
2096
|
+
const delivery = current !== undefined && exactRetiredDelivery(current.binding, record.retiredSession)
|
|
2103
2097
|
? current
|
|
2104
|
-
: retired !== undefined
|
|
2105
|
-
&& exactRetiredDelivery(retired.binding, record.retiredSession)
|
|
2098
|
+
: retired !== undefined && exactRetiredDelivery(retired.binding, record.retiredSession)
|
|
2106
2099
|
? retired
|
|
2107
2100
|
: undefined;
|
|
2108
2101
|
if (delivery === undefined)
|
|
@@ -2115,8 +2108,7 @@ class ServiceStatefulRuntime {
|
|
|
2115
2108
|
return 'infrastructure';
|
|
2116
2109
|
}
|
|
2117
2110
|
sendBoundSessionReplacement(previous, actorAuthority) {
|
|
2118
|
-
const ownerGeneration = previous.sessionOwnerNodeGeneration
|
|
2119
|
-
?? this.tryPeerGeneration(previous.sessionOwnerNodeRid);
|
|
2111
|
+
const ownerGeneration = previous.sessionOwnerNodeGeneration ?? this.tryPeerGeneration(previous.sessionOwnerNodeRid);
|
|
2120
2112
|
if (ownerGeneration === undefined)
|
|
2121
2113
|
return;
|
|
2122
2114
|
const header = (0, service_stateful_wire_codec_1.encodeBoundSessionReplacedHeader)(actorAuthority, {
|
|
@@ -2137,22 +2129,20 @@ class ServiceStatefulRuntime {
|
|
|
2137
2129
|
return;
|
|
2138
2130
|
const actor = record.actor.actor;
|
|
2139
2131
|
const current = this.registry.binding(actor);
|
|
2140
|
-
const sourceGeneration = ingress.sourceNodeGeneration
|
|
2141
|
-
|
|
2142
|
-
|
|
2143
|
-
|
|
2144
|
-
|
|
2145
|
-
|
|
2146
|
-
|
|
2147
|
-
|
|
2148
|
-
|
|
2149
|
-
|| current.sessionOwnerLeaseGeneration !== sourceGeneration) {
|
|
2132
|
+
const sourceGeneration = ingress.sourceNodeGeneration ?? this.tryPeerGeneration(ingress.sourceRoutingId);
|
|
2133
|
+
if (current === undefined ||
|
|
2134
|
+
sourceGeneration === undefined ||
|
|
2135
|
+
current.bindingGeneration !== record.binding.retiredGeneration ||
|
|
2136
|
+
current.sessionRid !== record.sessionRid ||
|
|
2137
|
+
current.sessionOwnerNodeRid !== ingress.sourceRoutingId ||
|
|
2138
|
+
current.sessionOwnerNodeGeneration !== sourceGeneration ||
|
|
2139
|
+
current.sessionOwnerId !== ingress.sourceRoutingId ||
|
|
2140
|
+
current.sessionOwnerLeaseGeneration !== sourceGeneration) {
|
|
2150
2141
|
this.replyWire(ingress, record.correlation, runtime_values_1.RequestResult.Ok, 0);
|
|
2151
2142
|
return;
|
|
2152
2143
|
}
|
|
2153
2144
|
const delivery = this.sessionDeliveries.get(actorKey(actor));
|
|
2154
|
-
const currentDelivery = delivery !== undefined
|
|
2155
|
-
&& sameSessionBinding(delivery.binding, current)
|
|
2145
|
+
const currentDelivery = delivery !== undefined && sameSessionBinding(delivery.binding, current)
|
|
2156
2146
|
? delivery
|
|
2157
2147
|
: undefined;
|
|
2158
2148
|
const accepted = this.enqueueSessionBindingRetirement(ingress, current, record.actor, (terminalResult, failureCode) => {
|
|
@@ -2161,8 +2151,8 @@ class ServiceStatefulRuntime {
|
|
|
2161
2151
|
if (turnCurrent !== undefined && sameSessionBinding(turnCurrent, current)) {
|
|
2162
2152
|
this.registry.unbindSession(actor, current.bindingGeneration, current.sessionRid, current.sessionOwnerNodeRid);
|
|
2163
2153
|
}
|
|
2164
|
-
if (currentDelivery !== undefined
|
|
2165
|
-
|
|
2154
|
+
if (currentDelivery !== undefined &&
|
|
2155
|
+
this.sessionDeliveries.get(actorKey(actor)) === currentDelivery) {
|
|
2166
2156
|
this.sessionDeliveries.delete(actorKey(actor));
|
|
2167
2157
|
}
|
|
2168
2158
|
}
|
|
@@ -2211,12 +2201,12 @@ class ServiceStatefulRuntime {
|
|
|
2211
2201
|
}
|
|
2212
2202
|
async deliverBoundSession(ingress, record, payloadFrame) {
|
|
2213
2203
|
const delivery = this.sessionDeliveries.get(actorKey(record.actor.actor));
|
|
2214
|
-
if (delivery === undefined
|
|
2215
|
-
|
|
2216
|
-
|
|
2217
|
-
|
|
2218
|
-
|
|
2219
|
-
|
|
2204
|
+
if (delivery === undefined ||
|
|
2205
|
+
delivery.binding.bindingGeneration !== record.expectedBindingGeneration ||
|
|
2206
|
+
payloadFrame === undefined ||
|
|
2207
|
+
ingress.sourceNodeGeneration === undefined ||
|
|
2208
|
+
!(0, routing_id_1.routingIdsEqual)(ingress.sourceRoutingId, record.actor.actor.nodeRid) ||
|
|
2209
|
+
ingress.sourceNodeGeneration !== record.actor.targetNodeGeneration) {
|
|
2220
2210
|
return 'protocolError';
|
|
2221
2211
|
}
|
|
2222
2212
|
const sessionRid = delivery.binding.sessionRid;
|
|
@@ -2270,9 +2260,9 @@ class ServiceStatefulRuntime {
|
|
|
2270
2260
|
// Remote command 36 is one-way: its source transport admission has
|
|
2271
2261
|
// already completed, so a later client delivery terminal is local to
|
|
2272
2262
|
// this session owner. Local fast paths still preserve the typed result.
|
|
2273
|
-
if (ingress.sourceRoutingId !== this.nodeRid
|
|
2274
|
-
|
|
2275
|
-
|
|
2263
|
+
if (ingress.sourceRoutingId !== this.nodeRid &&
|
|
2264
|
+
(0, runtime_values_1.isZLinkBackendResultError)(error) &&
|
|
2265
|
+
error.operation === 'submit') {
|
|
2276
2266
|
return 'application';
|
|
2277
2267
|
}
|
|
2278
2268
|
throw error;
|
|
@@ -2294,7 +2284,9 @@ class ServiceStatefulRuntime {
|
|
|
2294
2284
|
sourceRoutingId: ingress.sourceRoutingId,
|
|
2295
2285
|
sourceRoute: ingress.sourceRoute,
|
|
2296
2286
|
...(ingress.reply === undefined ? {} : { reply: ingress.reply }),
|
|
2297
|
-
...(ingress.requestSequence === undefined
|
|
2287
|
+
...(ingress.requestSequence === undefined
|
|
2288
|
+
? {}
|
|
2289
|
+
: { requestSequence: ingress.requestSequence }),
|
|
2298
2290
|
...(stateful.correlation === undefined ? {} : { correlation: stateful.correlation }),
|
|
2299
2291
|
stateful,
|
|
2300
2292
|
applicationJob
|
|
@@ -2320,10 +2312,10 @@ class ServiceStatefulRuntime {
|
|
|
2320
2312
|
}
|
|
2321
2313
|
async enqueueLogicalMulticastFrame(channelName, topic, sourceSpotId, payloadFrame, sourceNodeRid, applicationJobOwner) {
|
|
2322
2314
|
const targets = [...this.subscriptions.entries()]
|
|
2323
|
-
.filter(([, values]) => [...values].some(value => {
|
|
2315
|
+
.filter(([, values]) => [...values].some((value) => {
|
|
2324
2316
|
const separator = value.indexOf('\0');
|
|
2325
|
-
return value.slice(0, separator) === channelName
|
|
2326
|
-
|
|
2317
|
+
return (value.slice(0, separator) === channelName &&
|
|
2318
|
+
topicMatches(value.slice(separator + 1), topic));
|
|
2327
2319
|
}))
|
|
2328
2320
|
.map(([spotId]) => spotId)
|
|
2329
2321
|
.sort();
|
|
@@ -2335,10 +2327,7 @@ class ServiceStatefulRuntime {
|
|
|
2335
2327
|
const accepted = this.raw.mailbox.tryEnqueue({
|
|
2336
2328
|
owner: `spot:${spotId}`,
|
|
2337
2329
|
domain: 'application',
|
|
2338
|
-
parts: [
|
|
2339
|
-
(0, service_stateful_wire_codec_1.encodeLogicalMulticastHeader)(channelName, topic, sourceSpotId),
|
|
2340
|
-
payloadFrame
|
|
2341
|
-
],
|
|
2330
|
+
parts: [(0, service_stateful_wire_codec_1.encodeLogicalMulticastHeader)(channelName, topic, sourceSpotId), payloadFrame],
|
|
2342
2331
|
sourceRoutingId: sourceNodeRid,
|
|
2343
2332
|
stateful: {
|
|
2344
2333
|
receiveKind: service_runtime_contracts_1.ReceiveKind.SpotMulticast,
|
|
@@ -2451,17 +2440,17 @@ class ServiceStatefulRuntime {
|
|
|
2451
2440
|
]);
|
|
2452
2441
|
}
|
|
2453
2442
|
handleUserSpotOperation(ingress, record) {
|
|
2454
|
-
if (ingress.requestSequence === undefined
|
|
2455
|
-
|
|
2456
|
-
|
|
2457
|
-
|
|
2443
|
+
if (ingress.requestSequence === undefined ||
|
|
2444
|
+
record.sourceNodeRid !== ingress.sourceRoutingId ||
|
|
2445
|
+
record.sourceNodeGeneration !== this.peerGeneration(ingress.sourceRoutingId) ||
|
|
2446
|
+
(record.kind === 'actorCreate' && record.reservation.pendingCapacityDelta !== 1)) {
|
|
2458
2447
|
return 'protocolError';
|
|
2459
2448
|
}
|
|
2460
2449
|
const target = record.kind === 'userSpotCreate' || record.kind === 'actorCreate'
|
|
2461
2450
|
? record.reservation
|
|
2462
2451
|
: record.target;
|
|
2463
|
-
if (target.targetNodeRid !== this.nodeRid
|
|
2464
|
-
|
|
2452
|
+
if (target.targetNodeRid !== this.nodeRid ||
|
|
2453
|
+
target.targetNodeGeneration !== this.nodeGeneration) {
|
|
2465
2454
|
this.replyWire(ingress, record.correlation, runtime_values_1.RequestResult.Conflict, SPOT_MOVING);
|
|
2466
2455
|
return 'infrastructure';
|
|
2467
2456
|
}
|
|
@@ -2473,8 +2462,7 @@ class ServiceStatefulRuntime {
|
|
|
2473
2462
|
].join('\0');
|
|
2474
2463
|
const encodedRequest = userSpotOperationFingerprint(record);
|
|
2475
2464
|
let admitted = this.admittedUserSpotOperations.get(operationKey);
|
|
2476
|
-
if (admitted?.settled === true
|
|
2477
|
-
&& operationReplayExpired(admitted.replayExpiresAtMs)) {
|
|
2465
|
+
if (admitted?.settled === true && operationReplayExpired(admitted.replayExpiresAtMs)) {
|
|
2478
2466
|
this.admittedUserSpotOperations.delete(operationKey);
|
|
2479
2467
|
admitted = undefined;
|
|
2480
2468
|
}
|
|
@@ -2493,9 +2481,9 @@ class ServiceStatefulRuntime {
|
|
|
2493
2481
|
this.replyWire(ingress, record.correlation, runtime_values_1.RequestResult.Busy, 0);
|
|
2494
2482
|
return 'infrastructure';
|
|
2495
2483
|
}
|
|
2496
|
-
const replayExpiresAtMs = performance.now()
|
|
2497
|
-
|
|
2498
|
-
|
|
2484
|
+
const replayExpiresAtMs = performance.now() +
|
|
2485
|
+
Number(record.deadlineUnixMs - BigInt(Date.now())) +
|
|
2486
|
+
USER_SPOT_OPERATION_REPLAY_RETENTION_MS;
|
|
2499
2487
|
const handler = this.userSpotOperationHandler;
|
|
2500
2488
|
const result = handler === undefined
|
|
2501
2489
|
? Promise.resolve({
|
|
@@ -2510,22 +2498,22 @@ class ServiceStatefulRuntime {
|
|
|
2510
2498
|
settled: false
|
|
2511
2499
|
};
|
|
2512
2500
|
this.admittedUserSpotOperations.set(operationKey, admitted);
|
|
2513
|
-
void result
|
|
2501
|
+
void result
|
|
2502
|
+
.finally(() => {
|
|
2514
2503
|
const current = this.admittedUserSpotOperations.get(operationKey);
|
|
2515
2504
|
if (current?.result === result)
|
|
2516
2505
|
current.settled = true;
|
|
2517
|
-
})
|
|
2506
|
+
})
|
|
2507
|
+
.catch(() => undefined);
|
|
2518
2508
|
}
|
|
2519
|
-
void admitted.result.then(result => {
|
|
2509
|
+
void admitted.result.then((result) => {
|
|
2520
2510
|
if (this.closed)
|
|
2521
2511
|
return;
|
|
2522
2512
|
this.raw.replyService(ingress, [
|
|
2523
2513
|
(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)])
|
|
2514
|
+
...(result.payload === undefined ? [] : [(0, service_wire_m6a_codec_1.encodeApplicationPayload)(result.payload)])
|
|
2527
2515
|
]);
|
|
2528
|
-
}, error => {
|
|
2516
|
+
}, (error) => {
|
|
2529
2517
|
if (this.closed)
|
|
2530
2518
|
return;
|
|
2531
2519
|
const failed = failure(error);
|
|
@@ -2553,9 +2541,8 @@ class ServiceStatefulRuntime {
|
|
|
2553
2541
|
failureCode: 0
|
|
2554
2542
|
}
|
|
2555
2543
|
: await handler.createActor(record, deadline.signal);
|
|
2556
|
-
if (result.terminalResult === runtime_values_1.RequestResult.Ok
|
|
2557
|
-
|
|
2558
|
-
|| result.tail.kind !== record.kind)) {
|
|
2544
|
+
if (result.terminalResult === runtime_values_1.RequestResult.Ok &&
|
|
2545
|
+
(result.tail === undefined || result.tail.kind !== record.kind)) {
|
|
2559
2546
|
throw new service_wire_m6a_codec_1.ServiceWireProtocolError('User Spot success result omits its operation tail.');
|
|
2560
2547
|
}
|
|
2561
2548
|
return result;
|
|
@@ -2576,21 +2563,17 @@ class ServiceStatefulRuntime {
|
|
|
2576
2563
|
throw new service_wire_m6a_codec_1.ServiceWireProtocolError('Invalid creation operation reply parts.');
|
|
2577
2564
|
}
|
|
2578
2565
|
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) {
|
|
2566
|
+
if (decoded.terminalResult !== runtime_values_1.RequestResult.Ok && parts.length !== 1) {
|
|
2581
2567
|
throw new service_wire_m6a_codec_1.ServiceWireProtocolError('Failed creation operation reply carries a payload.');
|
|
2582
2568
|
}
|
|
2583
|
-
if (operationKind === 'userSpotClose'
|
|
2584
|
-
&& parts.length !== 1) {
|
|
2569
|
+
if (operationKind === 'userSpotClose' && parts.length !== 1) {
|
|
2585
2570
|
throw new service_wire_m6a_codec_1.ServiceWireProtocolError('User Spot close reply carries a payload.');
|
|
2586
2571
|
}
|
|
2587
2572
|
return {
|
|
2588
2573
|
terminalResult: decoded.terminalResult,
|
|
2589
2574
|
failureCode: decoded.failureCode,
|
|
2590
2575
|
...(decoded.tail === undefined ? {} : { tail: decoded.tail }),
|
|
2591
|
-
...(parts.length === 2
|
|
2592
|
-
? { payload: (0, service_wire_m6a_codec_1.decodeApplicationPayload)(parts[1]) }
|
|
2593
|
-
: {})
|
|
2576
|
+
...(parts.length === 2 ? { payload: (0, service_wire_m6a_codec_1.decodeApplicationPayload)(parts[1]) } : {})
|
|
2594
2577
|
};
|
|
2595
2578
|
}
|
|
2596
2579
|
catch (error) {
|
|
@@ -2599,7 +2582,7 @@ class ServiceStatefulRuntime {
|
|
|
2599
2582
|
}
|
|
2600
2583
|
async requestDurableOperation(targetNodeRid, parts, correlation, operationKind, deadlineMs) {
|
|
2601
2584
|
const stop = new AbortController();
|
|
2602
|
-
const unobserve = this.raw.observePeerConnectionIntentRemoved(nodeRoutingId => {
|
|
2585
|
+
const unobserve = this.raw.observePeerConnectionIntentRemoved((nodeRoutingId) => {
|
|
2603
2586
|
if (nodeRoutingId === targetNodeRid) {
|
|
2604
2587
|
stop.abort((0, framework_errors_internal_1.createInternalFrameworkException)(framework_errors_internal_1.ZLinkFrameworkInternalErrorKind.RouteNotConnected, `${operationKind} target node lifecycle ended.`, true));
|
|
2605
2588
|
}
|
|
@@ -2631,7 +2614,7 @@ class ServiceStatefulRuntime {
|
|
|
2631
2614
|
}
|
|
2632
2615
|
let timer;
|
|
2633
2616
|
try {
|
|
2634
|
-
await (0, abort_1.awaitWithAbort)(new Promise(resolve => {
|
|
2617
|
+
await (0, abort_1.awaitWithAbort)(new Promise((resolve) => {
|
|
2635
2618
|
timer = setTimeout(resolve, retryDelayMs);
|
|
2636
2619
|
}), stop.signal);
|
|
2637
2620
|
}
|
|
@@ -2668,7 +2651,7 @@ class ServiceStatefulRuntime {
|
|
|
2668
2651
|
return;
|
|
2669
2652
|
settled = true;
|
|
2670
2653
|
clearTimeout(timer);
|
|
2671
|
-
resolve(parts.map(part => Buffer.from(part)));
|
|
2654
|
+
resolve(parts.map((part) => Buffer.from(part)));
|
|
2672
2655
|
};
|
|
2673
2656
|
void (async () => {
|
|
2674
2657
|
const applicationJobOwner = await this.raw.reserveLocalIngress();
|
|
@@ -2750,7 +2733,7 @@ class ServiceStatefulRuntime {
|
|
|
2750
2733
|
applicationJobOwner.close();
|
|
2751
2734
|
}
|
|
2752
2735
|
}
|
|
2753
|
-
return await this.raw.sendService(targetNodeRid, parts)
|
|
2736
|
+
return (await this.raw.sendService(targetNodeRid, parts))
|
|
2754
2737
|
? runtime_values_1.SubmitResult.Ok
|
|
2755
2738
|
: runtime_values_1.SubmitResult.NotConnected;
|
|
2756
2739
|
}
|
|
@@ -2776,10 +2759,10 @@ class ServiceStatefulRuntime {
|
|
|
2776
2759
|
finally {
|
|
2777
2760
|
applicationJobOwner.close();
|
|
2778
2761
|
}
|
|
2779
|
-
})().catch(error => this.operations.reply(pending.id, failure(error)));
|
|
2762
|
+
})().catch((error) => this.operations.reply(pending.id, failure(error)));
|
|
2780
2763
|
return;
|
|
2781
2764
|
}
|
|
2782
|
-
void this.raw.requestService(targetNodeRid, parts, timeoutMs).then(reply => this.completeRemoteReply(pending, targetNodeRid, operationKind, actor, reply), error => this.operations.fail(pending.id, error));
|
|
2765
|
+
void this.raw.requestService(targetNodeRid, parts, timeoutMs).then((reply) => this.completeRemoteReply(pending, targetNodeRid, operationKind, actor, reply), (error) => this.operations.fail(pending.id, error));
|
|
2783
2766
|
}
|
|
2784
2767
|
submitActorJoin(pending, actor, targetNodeRid, target, payload, deadlineMs, canonical) {
|
|
2785
2768
|
const actorRoute = canonical === undefined
|
|
@@ -2823,7 +2806,7 @@ class ServiceStatefulRuntime {
|
|
|
2823
2806
|
expectedOwnerLeaseGeneration: target.ownerLeaseGeneration
|
|
2824
2807
|
},
|
|
2825
2808
|
...(payload === undefined ? {} : { payload })
|
|
2826
|
-
}).map(frame => Buffer.from(frame));
|
|
2809
|
+
}).map((frame) => Buffer.from(frame));
|
|
2827
2810
|
}
|
|
2828
2811
|
catch (error) {
|
|
2829
2812
|
this.canonicalActorJoinHandoffs.delete(pending.id);
|
|
@@ -2834,20 +2817,20 @@ class ServiceStatefulRuntime {
|
|
|
2834
2817
|
this.submitRequest(pending, targetNodeRid, parts, Math.max(0, Math.ceil(deadlineMs - performance.now())), 'actorJoin', actor);
|
|
2835
2818
|
return;
|
|
2836
2819
|
}
|
|
2837
|
-
void this.requestDurableOperation(targetNodeRid, parts, pending.id, 'actorJoin', deadlineMs).then(reply => this.completeRemoteReply(pending, targetNodeRid, 'actorJoin', actor, reply), error => {
|
|
2820
|
+
void this.requestDurableOperation(targetNodeRid, parts, pending.id, 'actorJoin', deadlineMs).then((reply) => this.completeRemoteReply(pending, targetNodeRid, 'actorJoin', actor, reply), (error) => {
|
|
2838
2821
|
this.canonicalActorJoinHandoffs.delete(pending.id);
|
|
2839
2822
|
this.operations.fail(pending.id, error);
|
|
2840
2823
|
});
|
|
2841
2824
|
}
|
|
2842
2825
|
submitLocalRequest(ingress, pending, operationKind, actor, deadlineUnixMs) {
|
|
2843
|
-
const canonicalActorJoin = operationKind === 'actorJoin'
|
|
2844
|
-
? (0, service_wire_pilot_codec_generated_1.decodeActorJoin28)(ingress.parts)
|
|
2845
|
-
: undefined;
|
|
2826
|
+
const canonicalActorJoin = operationKind === 'actorJoin' ? (0, service_wire_pilot_codec_generated_1.decodeActorJoin28)(ingress.parts) : undefined;
|
|
2846
2827
|
const decoded = canonicalActorJoin === undefined
|
|
2847
2828
|
? (0, service_stateful_wire_codec_1.decodeStatefulHeader)(ingress.parts[0])
|
|
2848
2829
|
: statefulActorJoinFromCanonical(canonicalActorJoin);
|
|
2849
2830
|
const payloadFrame = canonicalActorJoin?.payload === undefined
|
|
2850
|
-
?
|
|
2831
|
+
? ingress.parts.length < 2
|
|
2832
|
+
? undefined
|
|
2833
|
+
: ingress.parts[1]
|
|
2851
2834
|
: (0, service_wire_m6a_codec_1.encodeApplicationPayload)({
|
|
2852
2835
|
packetName: canonicalActorJoin.payload.packetName,
|
|
2853
2836
|
contentType: canonicalActorJoin.payload.contentType,
|
|
@@ -2945,9 +2928,9 @@ class ServiceStatefulRuntime {
|
|
|
2945
2928
|
reply: (terminalResult, failureCode, replyPayload, tail) => {
|
|
2946
2929
|
if (actorJoinReplyAccepted)
|
|
2947
2930
|
return false;
|
|
2948
|
-
const acceptedJoin = terminalResult === runtime_values_1.RequestResult.Ok
|
|
2949
|
-
|
|
2950
|
-
|
|
2931
|
+
const acceptedJoin = terminalResult === runtime_values_1.RequestResult.Ok &&
|
|
2932
|
+
tail?.kind === 'actorJoin' &&
|
|
2933
|
+
tail.joinResult === 0;
|
|
2951
2934
|
if (acceptedJoin && this.operations.isPending(pending.id)) {
|
|
2952
2935
|
// Commit membership now, but keep the source operation behind
|
|
2953
2936
|
// target OnJoinedActor. Entry finishes on this record; User
|
|
@@ -3021,9 +3004,7 @@ class ServiceStatefulRuntime {
|
|
|
3021
3004
|
void operationKind;
|
|
3022
3005
|
}
|
|
3023
3006
|
completeRemoteReply(pending, targetNodeRid, operationKind, actor, reply) {
|
|
3024
|
-
const canonicalActorJoinHandoffId = operationKind === 'actorJoin'
|
|
3025
|
-
? this.canonicalActorJoinHandoffs.get(pending.id)
|
|
3026
|
-
: undefined;
|
|
3007
|
+
const canonicalActorJoinHandoffId = operationKind === 'actorJoin' ? this.canonicalActorJoinHandoffs.get(pending.id) : undefined;
|
|
3027
3008
|
try {
|
|
3028
3009
|
if (reply.length < 1 || reply.length > 2)
|
|
3029
3010
|
throw new service_wire_m6a_codec_1.ServiceWireProtocolError('Invalid M6B reply parts.');
|
|
@@ -3101,7 +3082,8 @@ class ServiceStatefulRuntime {
|
|
|
3101
3082
|
};
|
|
3102
3083
|
}
|
|
3103
3084
|
validateActorFence(fence) {
|
|
3104
|
-
if (fence.actor.nodeRid !== this.nodeRid ||
|
|
3085
|
+
if (fence.actor.nodeRid !== this.nodeRid ||
|
|
3086
|
+
fence.targetNodeGeneration !== this.nodeGeneration) {
|
|
3105
3087
|
throw new service_stateful_registry_1.ServiceStaleGenerationError('actor', fence.actor.actorId);
|
|
3106
3088
|
}
|
|
3107
3089
|
const actor = this.registry.requireActor(fence.actor);
|
|
@@ -3111,7 +3093,8 @@ class ServiceStatefulRuntime {
|
|
|
3111
3093
|
return actor;
|
|
3112
3094
|
}
|
|
3113
3095
|
validateActorMessageFence(fence) {
|
|
3114
|
-
if (fence.actor.nodeRid !== this.nodeRid ||
|
|
3096
|
+
if (fence.actor.nodeRid !== this.nodeRid ||
|
|
3097
|
+
fence.targetNodeGeneration !== this.nodeGeneration) {
|
|
3115
3098
|
throw new service_stateful_registry_1.ServiceStaleGenerationError('actor', fence.actor.actorId);
|
|
3116
3099
|
}
|
|
3117
3100
|
const actor = this.registry.actor(fence.actor.actorId);
|
|
@@ -3121,7 +3104,8 @@ class ServiceStatefulRuntime {
|
|
|
3121
3104
|
return actor;
|
|
3122
3105
|
}
|
|
3123
3106
|
validateSpotFence(fence) {
|
|
3124
|
-
if (fence.targetNodeRid !== this.nodeRid ||
|
|
3107
|
+
if (fence.targetNodeRid !== this.nodeRid ||
|
|
3108
|
+
fence.targetNodeGeneration !== this.nodeGeneration) {
|
|
3125
3109
|
throw new service_stateful_registry_1.ServiceStaleGenerationError('spot', fence.spot.spotId);
|
|
3126
3110
|
}
|
|
3127
3111
|
const spot = this.registry.requireSpot(fence.spot);
|
|
@@ -3138,7 +3122,8 @@ class ServiceStatefulRuntime {
|
|
|
3138
3122
|
if (spot.state !== 'ready') {
|
|
3139
3123
|
throw (0, framework_errors_internal_1.createInternalFrameworkException)(framework_errors_internal_1.ZLinkFrameworkInternalErrorKind.SpotMoving, `Spot '${fence.spot.spotId}' is not Ready.`);
|
|
3140
3124
|
}
|
|
3141
|
-
if (fence.targetNodeRid !== this.nodeRid ||
|
|
3125
|
+
if (fence.targetNodeRid !== this.nodeRid ||
|
|
3126
|
+
fence.targetNodeGeneration !== this.nodeGeneration) {
|
|
3142
3127
|
throw (0, framework_errors_internal_1.createInternalFrameworkException)(framework_errors_internal_1.ZLinkFrameworkInternalErrorKind.SpotMoving, `Spot '${fence.spot.spotId}' targets an unavailable owner route.`);
|
|
3143
3128
|
}
|
|
3144
3129
|
if (spot.kind === 'entry') {
|
|
@@ -3151,11 +3136,11 @@ class ServiceStatefulRuntime {
|
|
|
3151
3136
|
if (current === undefined) {
|
|
3152
3137
|
throw (0, framework_errors_internal_1.createInternalFrameworkException)(framework_errors_internal_1.ZLinkFrameworkInternalErrorKind.SpotMoving, `Spot '${fence.spot.spotId}' has no current owner route.`);
|
|
3153
3138
|
}
|
|
3154
|
-
if (current.targetNodeRid !== this.nodeRid
|
|
3155
|
-
|
|
3156
|
-
|
|
3157
|
-
|
|
3158
|
-
|
|
3139
|
+
if (current.targetNodeRid !== this.nodeRid ||
|
|
3140
|
+
current.targetNodeGeneration !== this.nodeGeneration ||
|
|
3141
|
+
current.ownerLeaseGeneration !== fence.ownerLeaseGeneration ||
|
|
3142
|
+
(current.spot.generation === fence.spot.generation &&
|
|
3143
|
+
current.authorityOwnerGeneration !== fence.authorityOwnerGeneration)) {
|
|
3159
3144
|
throw (0, framework_errors_internal_1.createInternalFrameworkException)(framework_errors_internal_1.ZLinkFrameworkInternalErrorKind.SpotMoving, `Spot '${fence.spot.spotId}' has a stale owner fence.`);
|
|
3160
3145
|
}
|
|
3161
3146
|
return spot;
|
|
@@ -3212,7 +3197,7 @@ class ServiceStatefulRuntime {
|
|
|
3212
3197
|
current.ingress.parts[1]
|
|
3213
3198
|
];
|
|
3214
3199
|
if (current.wire.kind === 'spotSend') {
|
|
3215
|
-
if (!await this.raw.sendService(state.target.targetNodeRid, parts))
|
|
3200
|
+
if (!(await this.raw.sendService(state.target.targetNodeRid, parts)))
|
|
3216
3201
|
continue;
|
|
3217
3202
|
}
|
|
3218
3203
|
else {
|
|
@@ -3248,11 +3233,11 @@ class ServiceStatefulRuntime {
|
|
|
3248
3233
|
const claim = this.spotMessageFollowSuppression.begin(suppressionFence);
|
|
3249
3234
|
if (claim === undefined)
|
|
3250
3235
|
return;
|
|
3251
|
-
const operationLow = current.ingress.requestSequence !== undefined
|
|
3252
|
-
&& current.ingress.requestSequence !== 0n
|
|
3236
|
+
const operationLow = current.ingress.requestSequence !== undefined && current.ingress.requestSequence !== 0n
|
|
3253
3237
|
? current.ingress.requestSequence
|
|
3254
3238
|
: this.nextMessageFollowOperation++;
|
|
3255
|
-
const accepted = await this.raw.sendService(current.ingress.sourceRoutingId, [
|
|
3239
|
+
const accepted = await this.raw.sendService(current.ingress.sourceRoutingId, [
|
|
3240
|
+
(0, service_stateful_wire_codec_1.encodeMessageFollowHeader)({
|
|
3256
3241
|
source: messageFollowSpotRoute(state.source),
|
|
3257
3242
|
target: messageFollowSpotRoute(target),
|
|
3258
3243
|
hopCount: 1,
|
|
@@ -3263,7 +3248,8 @@ class ServiceStatefulRuntime {
|
|
|
3263
3248
|
low: operationLow
|
|
3264
3249
|
},
|
|
3265
3250
|
originalReplyRouteId: current.ingress.requestSequence ?? 0n
|
|
3266
|
-
})
|
|
3251
|
+
})
|
|
3252
|
+
]);
|
|
3267
3253
|
if (accepted) {
|
|
3268
3254
|
this.spotMessageFollowSuppression.markSent(claim);
|
|
3269
3255
|
}
|
|
@@ -3324,16 +3310,16 @@ class ServiceStatefulRuntime {
|
|
|
3324
3310
|
return route;
|
|
3325
3311
|
}
|
|
3326
3312
|
tryBoundSessionSendFence(actor, senderFence) {
|
|
3327
|
-
if (senderFence === undefined
|
|
3328
|
-
|
|
3329
|
-
|
|
3330
|
-
|
|
3313
|
+
if (senderFence === undefined ||
|
|
3314
|
+
senderFence.targetNodeGeneration !== this.nodeGeneration ||
|
|
3315
|
+
senderFence.authorityOwnerGeneration <= 0n ||
|
|
3316
|
+
senderFence.ownerLeaseGeneration <= 0n) {
|
|
3331
3317
|
return undefined;
|
|
3332
3318
|
}
|
|
3333
3319
|
const local = actor.nodeRid === this.nodeRid ? this.registry.actor(actor.actorId) : undefined;
|
|
3334
|
-
if (local === undefined
|
|
3335
|
-
|
|
3336
|
-
|
|
3320
|
+
if (local === undefined ||
|
|
3321
|
+
!sameActorRef(local.ref, actor) ||
|
|
3322
|
+
local.authorityOwnerGeneration !== senderFence.authorityOwnerGeneration) {
|
|
3337
3323
|
return undefined;
|
|
3338
3324
|
}
|
|
3339
3325
|
return {
|
|
@@ -3364,10 +3350,10 @@ class ServiceStatefulRuntime {
|
|
|
3364
3350
|
// application admission (spec 15 section 4.2 / spec 51 section 9).
|
|
3365
3351
|
// Object/authority/lease are bounded counters. Node lifecycle is a
|
|
3366
3352
|
// full-range opaque token, where only zero represents absence.
|
|
3367
|
-
if (actor.generation <= 0n
|
|
3368
|
-
|
|
3369
|
-
|
|
3370
|
-
|
|
3353
|
+
if (actor.generation <= 0n ||
|
|
3354
|
+
fence.targetNodeGeneration === 0n ||
|
|
3355
|
+
fence.authorityOwnerGeneration <= 0n ||
|
|
3356
|
+
fence.ownerLeaseGeneration <= 0n) {
|
|
3371
3357
|
return undefined;
|
|
3372
3358
|
}
|
|
3373
3359
|
return {
|
|
@@ -3389,9 +3375,9 @@ class ServiceStatefulRuntime {
|
|
|
3389
3375
|
};
|
|
3390
3376
|
}
|
|
3391
3377
|
const route = this.spotRoutes.get(spotKey(spot));
|
|
3392
|
-
return route !== undefined
|
|
3393
|
-
|
|
3394
|
-
|
|
3378
|
+
return route !== undefined &&
|
|
3379
|
+
route.targetNodeRid === targetNodeRid &&
|
|
3380
|
+
sameSpotRef(route.spot, spot)
|
|
3395
3381
|
? route
|
|
3396
3382
|
: undefined;
|
|
3397
3383
|
}
|
|
@@ -3417,23 +3403,23 @@ class ServiceStatefulRuntime {
|
|
|
3417
3403
|
const { targetNodeRid, spot, targetNodeGeneration } = requested;
|
|
3418
3404
|
if (targetNodeRid === this.nodeRid) {
|
|
3419
3405
|
const local = this.registry.spot(spot.spotId);
|
|
3420
|
-
if (local?.kind === 'entry'
|
|
3421
|
-
|
|
3422
|
-
|
|
3423
|
-
|
|
3424
|
-
|
|
3406
|
+
if (local?.kind === 'entry' &&
|
|
3407
|
+
sameSpotRef(local.ref, spot) &&
|
|
3408
|
+
targetNodeGeneration === this.nodeGeneration &&
|
|
3409
|
+
requested.authorityOwnerGeneration === local.authorityOwnerGeneration &&
|
|
3410
|
+
isEntrySpotFence(requested)) {
|
|
3425
3411
|
return requested;
|
|
3426
3412
|
}
|
|
3427
3413
|
const current = this.directSpotRoutes.get(directSpotKey(spot.spotId));
|
|
3428
|
-
return local !== undefined
|
|
3429
|
-
|
|
3430
|
-
|
|
3431
|
-
|
|
3432
|
-
|
|
3433
|
-
|
|
3434
|
-
|
|
3435
|
-
|
|
3436
|
-
|
|
3414
|
+
return local !== undefined &&
|
|
3415
|
+
local.state === 'ready' &&
|
|
3416
|
+
targetNodeGeneration === this.nodeGeneration &&
|
|
3417
|
+
current !== undefined &&
|
|
3418
|
+
current.targetNodeRid === this.nodeRid &&
|
|
3419
|
+
current.targetNodeGeneration === this.nodeGeneration &&
|
|
3420
|
+
current.ownerLeaseGeneration === requested.ownerLeaseGeneration &&
|
|
3421
|
+
(current.spot.generation !== requested.spot.generation ||
|
|
3422
|
+
current.authorityOwnerGeneration === requested.authorityOwnerGeneration)
|
|
3437
3423
|
? current
|
|
3438
3424
|
: undefined;
|
|
3439
3425
|
}
|
|
@@ -3460,9 +3446,7 @@ class ServiceStatefulRuntime {
|
|
|
3460
3446
|
const current = this.registry.actor(actor.actorId);
|
|
3461
3447
|
const previousActor = current?.ref ?? actor;
|
|
3462
3448
|
const previousSpot = current?.spot;
|
|
3463
|
-
const previousSpotState = previousSpot === undefined
|
|
3464
|
-
? undefined
|
|
3465
|
-
: this.registry.spot(previousSpot.spotId);
|
|
3449
|
+
const previousSpotState = previousSpot === undefined ? undefined : this.registry.spot(previousSpot.spotId);
|
|
3466
3450
|
const previousMembershipEpoch = current?.membershipEpoch ?? membershipEpoch - 1n;
|
|
3467
3451
|
if (current === undefined) {
|
|
3468
3452
|
this.registry.restoreActor({ ...actor, nodeRid: this.nodeRid }, 'actor', spot, membershipEpoch);
|
|
@@ -3490,11 +3474,11 @@ class ServiceStatefulRuntime {
|
|
|
3490
3474
|
resultCode: 0
|
|
3491
3475
|
}, onTargetLifecycleCompleted);
|
|
3492
3476
|
}
|
|
3493
|
-
if (actor.nodeRid === this.nodeRid
|
|
3494
|
-
|
|
3495
|
-
|
|
3496
|
-
|
|
3497
|
-
|
|
3477
|
+
if (actor.nodeRid === this.nodeRid &&
|
|
3478
|
+
previousSpot !== undefined &&
|
|
3479
|
+
previousSpot.spotId !== spot.spotId &&
|
|
3480
|
+
previousSpotState?.ref.generation === previousSpot.generation &&
|
|
3481
|
+
(previousSpotState.kind === 'entry' || previousSpotState.kind === 'user')) {
|
|
3498
3482
|
// A same-node Core join commits the target membership and publishes
|
|
3499
3483
|
// the source LEFT control separately. Remote joins use the formal
|
|
3500
3484
|
// transfer source terminal instead; the wire ActorRef still identifies
|
|
@@ -3521,11 +3505,11 @@ class ServiceStatefulRuntime {
|
|
|
3521
3505
|
}
|
|
3522
3506
|
exports.ServiceStatefulRuntime = ServiceStatefulRuntime;
|
|
3523
3507
|
function isEntrySpotFence(fence) {
|
|
3524
|
-
return fence.spot.spotId === fence.targetNodeRid
|
|
3525
|
-
|
|
3526
|
-
|
|
3527
|
-
|
|
3528
|
-
|
|
3508
|
+
return (fence.spot.spotId === fence.targetNodeRid &&
|
|
3509
|
+
fence.spot.generation === fence.targetNodeGeneration &&
|
|
3510
|
+
fence.authorityOwnerGeneration === fence.targetNodeGeneration &&
|
|
3511
|
+
fence.ownerLeaseGeneration === fence.targetNodeGeneration &&
|
|
3512
|
+
fence.storeVersion === `entry:${fence.targetNodeGeneration}`);
|
|
3529
3513
|
}
|
|
3530
3514
|
function userSpotDeadline(deadlineUnixMs) {
|
|
3531
3515
|
const controller = new AbortController();
|
|
@@ -3554,10 +3538,10 @@ function durableRequestCanReplay(error) {
|
|
|
3554
3538
|
return false;
|
|
3555
3539
|
return error.operation === 'request'
|
|
3556
3540
|
? 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
|
-
|
|
3541
|
+
: error.result === runtime_values_1.SubmitResult.NotConnected ||
|
|
3542
|
+
error.result === runtime_values_1.SubmitResult.NotFound ||
|
|
3543
|
+
error.result === runtime_values_1.SubmitResult.NotAdmitted ||
|
|
3544
|
+
error.result === runtime_values_1.SubmitResult.Backpressured;
|
|
3561
3545
|
}
|
|
3562
3546
|
function remainingDeadlineMs(deadlineUnixMs) {
|
|
3563
3547
|
const remainingMs = deadlineUnixMs - BigInt(Date.now());
|
|
@@ -3597,26 +3581,26 @@ function actorKey(actor) {
|
|
|
3597
3581
|
return `${actor.actorId}\0${actor.generation}`;
|
|
3598
3582
|
}
|
|
3599
3583
|
function sameSessionBinding(left, right) {
|
|
3600
|
-
return sameActorRef(left.actor, right.actor)
|
|
3601
|
-
|
|
3602
|
-
|
|
3603
|
-
|
|
3584
|
+
return (sameActorRef(left.actor, right.actor) &&
|
|
3585
|
+
left.sessionRid === right.sessionRid &&
|
|
3586
|
+
sameSessionOwnerIdentity(left, right) &&
|
|
3587
|
+
left.bindingGeneration === right.bindingGeneration);
|
|
3604
3588
|
}
|
|
3605
3589
|
function sameSessionIdentity(left, right) {
|
|
3606
|
-
return sameActorRef(left.actor, right.actor)
|
|
3607
|
-
|
|
3608
|
-
|
|
3590
|
+
return (sameActorRef(left.actor, right.actor) &&
|
|
3591
|
+
left.sessionRid === right.sessionRid &&
|
|
3592
|
+
sameSessionOwnerIdentity(left, right));
|
|
3609
3593
|
}
|
|
3610
3594
|
function sameSessionOwnerIdentity(left, right) {
|
|
3611
|
-
return left.sessionOwnerNodeRid === right.sessionOwnerNodeRid
|
|
3612
|
-
|
|
3613
|
-
|
|
3614
|
-
|
|
3595
|
+
return (left.sessionOwnerNodeRid === right.sessionOwnerNodeRid &&
|
|
3596
|
+
left.sessionOwnerNodeGeneration === right.sessionOwnerNodeGeneration &&
|
|
3597
|
+
left.sessionOwnerId === right.sessionOwnerId &&
|
|
3598
|
+
left.sessionOwnerLeaseGeneration === right.sessionOwnerLeaseGeneration);
|
|
3615
3599
|
}
|
|
3616
3600
|
function requireSessionOwnerIdentity(binding) {
|
|
3617
|
-
if (binding.sessionOwnerNodeGeneration === undefined
|
|
3618
|
-
|
|
3619
|
-
|
|
3601
|
+
if (binding.sessionOwnerNodeGeneration === undefined ||
|
|
3602
|
+
binding.sessionOwnerId === undefined ||
|
|
3603
|
+
binding.sessionOwnerLeaseGeneration === undefined) {
|
|
3620
3604
|
throw new service_wire_m6a_codec_1.ServiceWireProtocolError(`Session binding '${binding.sessionRid}' omits its owner lifecycle identity.`);
|
|
3621
3605
|
}
|
|
3622
3606
|
return {
|
|
@@ -3626,30 +3610,30 @@ function requireSessionOwnerIdentity(binding) {
|
|
|
3626
3610
|
};
|
|
3627
3611
|
}
|
|
3628
3612
|
function sessionDeliveryKey(binding) {
|
|
3629
|
-
return `${actorKey(binding.actor)}\0${binding.sessionOwnerNodeRid}\0${binding.sessionRid}`
|
|
3630
|
-
|
|
3631
|
-
|
|
3632
|
-
|
|
3633
|
-
|
|
3613
|
+
return (`${actorKey(binding.actor)}\0${binding.sessionOwnerNodeRid}\0${binding.sessionRid}` +
|
|
3614
|
+
`\0${binding.sessionOwnerNodeGeneration ?? ''}` +
|
|
3615
|
+
`\0${binding.sessionOwnerId ?? ''}` +
|
|
3616
|
+
`\0${binding.sessionOwnerLeaseGeneration ?? ''}` +
|
|
3617
|
+
`\0${binding.bindingGeneration}`);
|
|
3634
3618
|
}
|
|
3635
3619
|
function exactRetiredDelivery(binding, retired) {
|
|
3636
|
-
return binding.sessionRid === retired.sessionRid
|
|
3637
|
-
|
|
3638
|
-
|
|
3639
|
-
|
|
3640
|
-
|
|
3641
|
-
|
|
3620
|
+
return (binding.sessionRid === retired.sessionRid &&
|
|
3621
|
+
binding.sessionOwnerNodeRid === retired.sessionOwnerNodeRid &&
|
|
3622
|
+
binding.sessionOwnerNodeGeneration === retired.sessionOwnerNodeGeneration &&
|
|
3623
|
+
binding.sessionOwnerId === retired.sessionOwnerId &&
|
|
3624
|
+
binding.sessionOwnerLeaseGeneration === retired.sessionOwnerLeaseGeneration &&
|
|
3625
|
+
binding.bindingGeneration === retired.retiredBindingGeneration);
|
|
3642
3626
|
}
|
|
3643
3627
|
function replacementNoticeKey(record) {
|
|
3644
|
-
return `${actorKey(record.actorAuthority.actor)}\0${record.retiredSession.sessionOwnerNodeRid}`
|
|
3645
|
-
|
|
3646
|
-
|
|
3647
|
-
|
|
3648
|
-
|
|
3649
|
-
|
|
3650
|
-
|
|
3651
|
-
|
|
3652
|
-
|
|
3628
|
+
return (`${actorKey(record.actorAuthority.actor)}\0${record.retiredSession.sessionOwnerNodeRid}` +
|
|
3629
|
+
`\0${record.actorAuthority.targetNodeGeneration}` +
|
|
3630
|
+
`\0${record.actorAuthority.authorityOwnerGeneration}` +
|
|
3631
|
+
`\0${record.actorAuthority.ownerLeaseGeneration}` +
|
|
3632
|
+
`\0${record.retiredSession.sessionOwnerNodeGeneration}` +
|
|
3633
|
+
`\0${record.retiredSession.sessionOwnerId}` +
|
|
3634
|
+
`\0${record.retiredSession.sessionOwnerLeaseGeneration}` +
|
|
3635
|
+
`\0${record.retiredSession.sessionRid}` +
|
|
3636
|
+
`\0${record.retiredSession.retiredBindingGeneration}`);
|
|
3653
3637
|
}
|
|
3654
3638
|
function actorAuthorityFromRoute(route) {
|
|
3655
3639
|
return {
|
|
@@ -3666,9 +3650,9 @@ function directSpotKey(spotId) {
|
|
|
3666
3650
|
return spotId;
|
|
3667
3651
|
}
|
|
3668
3652
|
function sameActorRef(left, right) {
|
|
3669
|
-
return left.nodeRid === right.nodeRid
|
|
3670
|
-
|
|
3671
|
-
|
|
3653
|
+
return (left.nodeRid === right.nodeRid &&
|
|
3654
|
+
left.actorId === right.actorId &&
|
|
3655
|
+
left.generation === right.generation);
|
|
3672
3656
|
}
|
|
3673
3657
|
function sameSpotRef(left, right) {
|
|
3674
3658
|
return left.spotId === right.spotId && left.generation === right.generation;
|
|
@@ -3716,30 +3700,30 @@ function matchesExpectedInstanceRoute(current, expected) {
|
|
|
3716
3700
|
: current !== undefined && sameInstanceRoute(current, expected);
|
|
3717
3701
|
}
|
|
3718
3702
|
function sameInstanceRoute(left, right) {
|
|
3719
|
-
return left.targetNodeRid === right.targetNodeRid
|
|
3720
|
-
|
|
3721
|
-
|
|
3722
|
-
|
|
3723
|
-
|
|
3724
|
-
|
|
3725
|
-
|
|
3726
|
-
|
|
3703
|
+
return (left.targetNodeRid === right.targetNodeRid &&
|
|
3704
|
+
left.targetNodeGeneration === right.targetNodeGeneration &&
|
|
3705
|
+
left.targetSpotId === right.targetSpotId &&
|
|
3706
|
+
left.objectGeneration === right.objectGeneration &&
|
|
3707
|
+
left.ownerId === right.ownerId &&
|
|
3708
|
+
left.authorityOwnerGeneration === right.authorityOwnerGeneration &&
|
|
3709
|
+
left.leaseGeneration === right.leaseGeneration &&
|
|
3710
|
+
left.storeVersion === right.storeVersion);
|
|
3727
3711
|
}
|
|
3728
3712
|
function sameInstanceOwnerIdentity(left, right) {
|
|
3729
|
-
return left.targetNodeRid === right.targetNodeRid
|
|
3730
|
-
|
|
3731
|
-
|
|
3732
|
-
|
|
3733
|
-
|
|
3734
|
-
|
|
3735
|
-
|
|
3713
|
+
return (left.targetNodeRid === right.targetNodeRid &&
|
|
3714
|
+
left.targetNodeGeneration === right.targetNodeGeneration &&
|
|
3715
|
+
left.targetSpotId === right.targetSpotId &&
|
|
3716
|
+
left.objectGeneration === right.objectGeneration &&
|
|
3717
|
+
left.ownerId === right.ownerId &&
|
|
3718
|
+
left.authorityOwnerGeneration === right.authorityOwnerGeneration &&
|
|
3719
|
+
left.leaseGeneration === right.leaseGeneration);
|
|
3736
3720
|
}
|
|
3737
3721
|
function sameInstanceApplicationOwner(left, right) {
|
|
3738
|
-
return left.targetNodeRid === right.targetNodeRid
|
|
3739
|
-
|
|
3740
|
-
|
|
3741
|
-
|
|
3742
|
-
|
|
3722
|
+
return (left.targetNodeRid === right.targetNodeRid &&
|
|
3723
|
+
left.targetNodeGeneration === right.targetNodeGeneration &&
|
|
3724
|
+
left.targetSpotId === right.targetSpotId &&
|
|
3725
|
+
left.ownerId === right.ownerId &&
|
|
3726
|
+
left.leaseGeneration === right.leaseGeneration);
|
|
3743
3727
|
}
|
|
3744
3728
|
function matchesExpectedDirectSpotRoute(current, expected) {
|
|
3745
3729
|
return expected === null
|
|
@@ -3760,8 +3744,7 @@ function instanceRouteAsDirectRoute(route) {
|
|
|
3760
3744
|
};
|
|
3761
3745
|
}
|
|
3762
3746
|
function sameDirectSpotRoute(left, right) {
|
|
3763
|
-
return sameDirectSpotRouteIdentity(left, right)
|
|
3764
|
-
&& left.storeVersion === right.storeVersion;
|
|
3747
|
+
return sameDirectSpotRouteIdentity(left, right) && left.storeVersion === right.storeVersion;
|
|
3765
3748
|
}
|
|
3766
3749
|
function messageFollowSpotRoute(route) {
|
|
3767
3750
|
return {
|
|
@@ -3789,38 +3772,37 @@ function spotMessageFollowSuppressionFence(objectKind, source, target) {
|
|
|
3789
3772
|
});
|
|
3790
3773
|
}
|
|
3791
3774
|
function sameMessageFollowSpotSource(current, source) {
|
|
3792
|
-
return current.spot.spotId === source.spot.spotId
|
|
3793
|
-
|
|
3794
|
-
|
|
3795
|
-
|
|
3796
|
-
|
|
3797
|
-
|
|
3775
|
+
return (current.spot.spotId === source.spot.spotId &&
|
|
3776
|
+
current.spot.generation === source.spot.generation &&
|
|
3777
|
+
current.targetNodeRid === source.targetNodeRid &&
|
|
3778
|
+
current.targetNodeGeneration === source.targetNodeGeneration &&
|
|
3779
|
+
current.authorityOwnerGeneration === source.authorityOwnerGeneration &&
|
|
3780
|
+
current.ownerLeaseGeneration === source.ownerLeaseGeneration);
|
|
3798
3781
|
}
|
|
3799
3782
|
function sameDirectSpotRouteIdentity(left, right) {
|
|
3800
|
-
return sameDirectSpotOwnerIdentity(left, right)
|
|
3801
|
-
&& left.spot.generation === right.spot.generation;
|
|
3783
|
+
return sameDirectSpotOwnerIdentity(left, right) && left.spot.generation === right.spot.generation;
|
|
3802
3784
|
}
|
|
3803
3785
|
function sameDirectSpotOwnerIdentity(left, right) {
|
|
3804
|
-
return left.spot.spotId === right.spot.spotId
|
|
3805
|
-
|
|
3806
|
-
|
|
3807
|
-
|
|
3808
|
-
|
|
3786
|
+
return (left.spot.spotId === right.spot.spotId &&
|
|
3787
|
+
left.targetNodeRid === right.targetNodeRid &&
|
|
3788
|
+
left.targetNodeGeneration === right.targetNodeGeneration &&
|
|
3789
|
+
left.authorityOwnerGeneration === right.authorityOwnerGeneration &&
|
|
3790
|
+
left.ownerLeaseGeneration === right.ownerLeaseGeneration);
|
|
3809
3791
|
}
|
|
3810
3792
|
function routeMatchesLocal(route, spot, nodeRid, nodeGeneration) {
|
|
3811
|
-
return route.targetNodeRid === nodeRid
|
|
3812
|
-
|
|
3813
|
-
|
|
3814
|
-
|
|
3815
|
-
|
|
3793
|
+
return (route.targetNodeRid === nodeRid &&
|
|
3794
|
+
route.targetNodeGeneration === nodeGeneration &&
|
|
3795
|
+
route.targetSpotId === spot.ref.spotId &&
|
|
3796
|
+
route.objectGeneration === spot.ref.generation &&
|
|
3797
|
+
route.authorityOwnerGeneration === spot.authorityOwnerGeneration);
|
|
3816
3798
|
}
|
|
3817
3799
|
function instanceOperationKey(record) {
|
|
3818
|
-
return `${record.sourceNodeRid}\0${record.sourceNodeGeneration}\0`
|
|
3819
|
-
|
|
3800
|
+
return (`${record.sourceNodeRid}\0${record.sourceNodeGeneration}\0` +
|
|
3801
|
+
`${record.operation.high}\0${record.operation.low}`);
|
|
3820
3802
|
}
|
|
3821
3803
|
function instanceActivationKey(record) {
|
|
3822
|
-
return `${record.target.targetNodeRid}\0${record.target.targetNodeGeneration}\0`
|
|
3823
|
-
|
|
3804
|
+
return (`${record.target.targetNodeRid}\0${record.target.targetNodeGeneration}\0` +
|
|
3805
|
+
`${record.target.targetSpotId}\0${record.target.stableType}`);
|
|
3824
3806
|
}
|
|
3825
3807
|
function subscriptionKey(channelName, topicFilter) {
|
|
3826
3808
|
if (channelName.length === 0 || topicFilter.length === 0) {
|
|
@@ -3883,11 +3865,7 @@ function instanceOperationParts(headerAndPayload, metadataFrame) {
|
|
|
3883
3865
|
}
|
|
3884
3866
|
if (metadataFrame === undefined)
|
|
3885
3867
|
return headerAndPayload;
|
|
3886
|
-
return [
|
|
3887
|
-
headerAndPayload[0],
|
|
3888
|
-
(0, service_metadata_codec_1.validateServiceMetadataFrame)(metadataFrame),
|
|
3889
|
-
headerAndPayload[1]
|
|
3890
|
-
];
|
|
3868
|
+
return [headerAndPayload[0], (0, service_metadata_codec_1.validateServiceMetadataFrame)(metadataFrame), headerAndPayload[1]];
|
|
3891
3869
|
}
|
|
3892
3870
|
function statefulMailboxData(record) {
|
|
3893
3871
|
return record.stateful;
|