@zlink-systems/framework 0.25.0 → 0.27.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/.tsbuildinfo +1 -1
- package/dist/contracts/Channels/IZLinkFanoutClient.d.ts +0 -6
- package/dist/contracts/Common/CoreTypes.d.ts +6 -0
- package/dist/contracts/Common/CoreTypes.js +7 -0
- package/dist/contracts/Common/index.d.ts +1 -1
- package/dist/contracts/Common/index.js +0 -1
- package/dist/contracts/Configuration/InternalDefaults.d.ts +8 -0
- package/dist/contracts/Configuration/InternalDefaults.js +9 -1
- package/dist/contracts/Configuration/Registration.d.ts +13 -2
- package/dist/contracts/Configuration/Registration.js +58 -36
- package/dist/contracts/Configuration/RegistrationBuilderPolicy.d.ts +13 -1
- package/dist/contracts/Configuration/RegistrationBuilderPolicy.js +38 -1
- package/dist/contracts/Configuration/RegistrationBuilders.d.ts +2 -3
- package/dist/contracts/Configuration/RegistrationBuilders.js +27 -32
- package/dist/contracts/Configuration/RegistrationTypes.d.ts +1 -0
- package/dist/contracts/Configuration/RegistrationValidators.js +15 -12
- package/dist/contracts/Configuration/TimerRegistrationValidator.js +3 -2
- package/dist/contracts/Dispatch/ZLinkDispatchOptions.d.ts +1 -1
- package/dist/contracts/Handlers/JsonContract.js +10 -4
- package/dist/contracts/Locations/Authority.d.ts +1 -1
- package/dist/contracts/Locations/Authority.js +3 -2
- package/dist/contracts/Locations/Options.js +1 -1
- package/dist/contracts/Locations/Stores.d.ts +12 -0
- package/dist/contracts/Locations/Stores.js +9 -0
- package/dist/contracts/RouteMesh/RuntimeTopology.d.ts +8 -0
- package/dist/contracts/Spots/Contracts.d.ts +1 -1
- package/dist/internal.d.ts +5 -0
- package/dist/internal.js +16 -1
- package/dist/nest-integration.d.ts +4 -2
- package/dist/nest-integration.js +14 -4
- package/dist/runtime/abort.d.ts +1 -0
- package/dist/runtime/abort.js +8 -5
- package/dist/runtime/activation-admission.d.ts +28 -0
- package/dist/runtime/activation-admission.js +57 -0
- package/dist/runtime/actors/actor-authority-payload-codec.d.ts +1 -2
- package/dist/runtime/actors/actor-authority-payload-codec.js +34 -18
- package/dist/runtime/actors/actor-client.d.ts +2 -2
- package/dist/runtime/actors/actor-client.js +42 -143
- package/dist/runtime/actors/actor-context.d.ts +3 -5
- package/dist/runtime/actors/actor-context.js +19 -17
- package/dist/runtime/actors/actor-handoff.d.ts +13 -7
- package/dist/runtime/actors/actor-handoff.js +36 -25
- package/dist/runtime/actors/actor-lifecycle-snapshot.js +2 -1
- package/dist/runtime/actors/actor-local-native-join.d.ts +11 -6
- package/dist/runtime/actors/actor-local-native-join.js +85 -123
- package/dist/runtime/actors/actor-native-lookup.js +2 -8
- package/dist/runtime/actors/actor-packet-relay-wire.d.ts +3 -3
- package/dist/runtime/actors/actor-packet-relay-wire.js +5 -3
- package/dist/runtime/actors/actor-remote-joiner.d.ts +3 -3
- package/dist/runtime/actors/actor-remote-joiner.js +11 -17
- package/dist/runtime/actors/actor-remote-wire.js +5 -3
- package/dist/runtime/actors/actor-request-deadline.d.ts +3 -0
- package/dist/runtime/actors/actor-request-deadline.js +31 -0
- package/dist/runtime/actors/actor-retry-delay.js +2 -1
- package/dist/runtime/actors/actor-runtime-contracts.d.ts +4 -2
- package/dist/runtime/actors/actor-runtime-state.d.ts +9 -21
- package/dist/runtime/actors/actor-runtime-state.js +70 -187
- package/dist/runtime/actors/actor-source-transfer.d.ts +5 -5
- package/dist/runtime/actors/bound-session-wire.js +2 -7
- package/dist/runtime/actors/deferred-join-completion.d.ts +19 -0
- package/dist/runtime/actors/deferred-join-completion.js +21 -0
- package/dist/runtime/actors/index.d.ts +10 -8
- package/dist/runtime/actors/index.js +101 -73
- package/dist/runtime/actors/spot-actor-dispatch.d.ts +3 -3
- package/dist/runtime/actors/spot-actor-dispatch.js +25 -10
- package/dist/runtime/actors/transferred-actor-rollback.d.ts +3 -5
- package/dist/runtime/actors/transferred-actor-rollback.js +9 -42
- package/dist/runtime/admission.d.ts +7 -1
- package/dist/runtime/admission.js +11 -1
- package/dist/runtime/application-jobs/application-job-queue-scope.d.ts +1 -1
- package/dist/runtime/application-jobs/application-job-queue-scope.js +1 -1
- package/dist/runtime/backend/contracts/index.d.ts +8 -33
- package/dist/runtime/backend/mesh-actor-session-node-adapter.js +3 -26
- package/dist/runtime/backend/mesh-dispatch-pump.d.ts +1 -2
- package/dist/runtime/backend/mesh-dispatch-pump.js +95 -107
- package/dist/runtime/backend/node/node-backend-adapter-factory.d.ts +1 -2
- package/dist/runtime/backend/node/node-backend-adapter-factory.js +4 -18
- package/dist/runtime/backend/node/node-backend-adapter-support.d.ts +7 -4
- package/dist/runtime/backend/node/node-backend-adapter-support.js +28 -34
- package/dist/runtime/backend/node/node-event-loop-poller.d.ts +2 -2
- package/dist/runtime/backend/node/node-event-loop-poller.js +11 -6
- package/dist/runtime/backend/node/node-monitor-backend-adapter.js +1 -0
- package/dist/runtime/backend/node/node-raw-binding-port.d.ts +1 -1
- package/dist/runtime/backend/node/node-raw-binding-port.js +51 -19
- package/dist/runtime/backend/node/node-raw-mesh-backend.d.ts +21 -19
- package/dist/runtime/backend/node/node-raw-mesh-backend.js +171 -111
- package/dist/runtime/backend/node/node-socket-backend-adapter.js +4 -3
- package/dist/runtime/backend/raw-binding-port.d.ts +13 -1
- package/dist/runtime/backend/runtime-values.d.ts +4 -1
- package/dist/runtime/backend/runtime-values.js +2 -0
- package/dist/runtime/channels/channel-clients.d.ts +20 -9
- package/dist/runtime/channels/channel-clients.js +68 -60
- package/dist/runtime/channels/channel-envelope-inspection.js +2 -1
- package/dist/runtime/channels/channel-envelope.js +47 -29
- package/dist/runtime/channels/channel-outbound-operations.d.ts +3 -0
- package/dist/runtime/channels/channel-outbound-operations.js +9 -18
- package/dist/runtime/channels/channel-receive-loops.d.ts +8 -3
- package/dist/runtime/channels/channel-receive-loops.js +27 -6
- package/dist/runtime/channels/channel-runtime-lifecycle.d.ts +12 -1
- package/dist/runtime/channels/channel-runtime-lifecycle.js +48 -28
- package/dist/runtime/channels/channel-runtime-manager.d.ts +2 -5
- package/dist/runtime/channels/channel-runtime-manager.js +4 -12
- package/dist/runtime/channels/channel-socket-options.js +3 -2
- package/dist/runtime/channels/channel-socket-registry.d.ts +30 -32
- package/dist/runtime/channels/channel-socket-registry.js +296 -235
- package/dist/runtime/channels/channel-transports.d.ts +11 -20
- package/dist/runtime/channels/channel-transports.js +68 -47
- package/dist/runtime/channels/client-server-location-runtime.d.ts +1 -1
- package/dist/runtime/channels/client-server-location-runtime.js +10 -11
- package/dist/runtime/channels/client-server-service-wire.d.ts +7 -2
- package/dist/runtime/channels/client-server-service-wire.js +32 -11
- package/dist/runtime/channels/dispatch-error-reporter.d.ts +1 -2
- package/dist/runtime/channels/dispatch-error-reporter.js +2 -1
- package/dist/runtime/channels/fanout-location-runtime.d.ts +16 -3
- package/dist/runtime/channels/fanout-location-runtime.js +133 -81
- package/dist/runtime/channels/spot-direct-envelope.d.ts +1 -0
- package/dist/runtime/channels/spot-direct-envelope.js +4 -3
- package/dist/runtime/channels/spot-node-route-transport.js +3 -2
- package/dist/runtime/diagnostics/diagnostic-text.d.ts +2 -0
- package/dist/runtime/diagnostics/diagnostic-text.js +7 -0
- package/dist/runtime/diagnostics/dispatch-error-details.d.ts +3 -0
- package/dist/runtime/diagnostics/dispatch-error-details.js +30 -2
- package/dist/runtime/diagnostics/flow-context.d.ts +6 -0
- package/dist/runtime/diagnostics/flow-context.js +16 -2
- package/dist/runtime/diagnostics/index.d.ts +4 -2
- package/dist/runtime/diagnostics/index.js +14 -4
- package/dist/runtime/diagnostics/message-flow.d.ts +1 -1
- package/dist/runtime/diagnostics/message-flow.js +10 -19
- package/dist/runtime/diagnostics/runtime-metrics.d.ts +94 -31
- package/dist/runtime/diagnostics/runtime-metrics.js +168 -105
- package/dist/runtime/diagnostics/runtime-observation-queue.js +3 -2
- package/dist/runtime/diagnostics/topology-runtime-projections.d.ts +2 -4
- package/dist/runtime/diagnostics/topology-runtime-projections.js +135 -154
- package/dist/runtime/disposal.d.ts +5 -0
- package/dist/runtime/disposal.js +22 -0
- package/dist/runtime/execution/index.d.ts +22 -9
- package/dist/runtime/execution/index.js +107 -37
- package/dist/runtime/execution/serial-execution-queue.d.ts +12 -7
- package/dist/runtime/execution/serial-execution-queue.js +99 -26
- package/dist/runtime/execution/state-lane.d.ts +8 -1
- package/dist/runtime/execution/state-lane.js +118 -3
- package/dist/runtime/foundation/actor-join-recovery-codec.d.ts +3 -0
- package/dist/runtime/foundation/actor-join-recovery-codec.js +15 -11
- package/dist/runtime/foundation/event-loop-resources.d.ts +2 -24
- package/dist/runtime/foundation/event-loop-resources.js +6 -119
- package/dist/runtime/foundation/listener-records.d.ts +11 -0
- package/dist/runtime/foundation/listener-records.js +20 -0
- package/dist/runtime/foundation/operation-identity.d.ts +2 -0
- package/dist/runtime/foundation/operation-identity.js +9 -5
- package/dist/runtime/foundation/operation-registry.d.ts +5 -7
- package/dist/runtime/foundation/operation-registry.js +34 -44
- package/dist/runtime/foundation/raw-service-mesh-runtime.d.ts +18 -26
- package/dist/runtime/foundation/raw-service-mesh-runtime.js +122 -469
- package/dist/runtime/foundation/runtime-state-projections.d.ts +3 -1
- package/dist/runtime/foundation/runtime-state-projections.js +8 -0
- package/dist/runtime/foundation/service-authority-payload-codec.d.ts +1 -0
- package/dist/runtime/foundation/service-authority-payload-codec.js +30 -12
- package/dist/runtime/foundation/service-discovery-registry.d.ts +4 -0
- package/dist/runtime/foundation/service-discovery-registry.js +22 -3
- package/dist/runtime/foundation/service-instance-activation-recovery-codec.js +8 -4
- package/dist/runtime/foundation/service-liveness-registry.js +2 -1
- package/dist/runtime/foundation/service-maintenance-runtime.d.ts +0 -1
- package/dist/runtime/foundation/service-maintenance-runtime.js +23 -8
- package/dist/runtime/foundation/service-metadata-codec.js +3 -3
- package/dist/runtime/foundation/service-relocation-aggregate-committer.d.ts +2 -5
- package/dist/runtime/foundation/service-relocation-aggregate-committer.js +1 -48
- package/dist/runtime/foundation/service-relocation-coordinator.d.ts +9 -0
- package/dist/runtime/foundation/service-relocation-coordinator.js +14 -1
- package/dist/runtime/foundation/service-relocation-object-owner.d.ts +8 -0
- package/dist/runtime/foundation/service-relocation-object-owner.js +19 -6
- package/dist/runtime/foundation/service-relocation-runtime.js +43 -32
- package/dist/runtime/foundation/service-runtime-contracts.d.ts +40 -8
- package/dist/runtime/foundation/service-runtime-contracts.js +25 -1
- package/dist/runtime/foundation/service-session-binding-ingress-port.d.ts +0 -19
- package/dist/runtime/foundation/service-stateful-registry.d.ts +2 -0
- package/dist/runtime/foundation/service-stateful-registry.js +10 -2
- package/dist/runtime/foundation/service-stateful-runtime.d.ts +28 -24
- package/dist/runtime/foundation/service-stateful-runtime.js +297 -244
- package/dist/runtime/foundation/service-stateful-wire-codec.d.ts +12 -7
- package/dist/runtime/foundation/service-stateful-wire-codec.js +240 -143
- package/dist/runtime/foundation/service-topology-registry.d.ts +1 -3
- package/dist/runtime/foundation/service-topology-registry.js +22 -61
- package/dist/runtime/foundation/service-wire-binary-primitives.d.ts +5 -0
- package/dist/runtime/foundation/service-wire-binary-primitives.js +6 -0
- package/dist/runtime/foundation/service-wire-codec.js +10 -8
- package/dist/runtime/foundation/service-wire-constants.generated.d.ts +1 -0
- package/dist/runtime/foundation/service-wire-constants.generated.js +2 -1
- package/dist/runtime/foundation/service-wire-m6a-codec.d.ts +2 -0
- package/dist/runtime/foundation/service-wire-m6a-codec.js +23 -13
- package/dist/runtime/framework-errors-internal.d.ts +2 -1
- package/dist/runtime/framework-errors-internal.js +343 -122
- package/dist/runtime/handlers/handler-instance-scope.d.ts +3 -1
- package/dist/runtime/handlers/handler-instance-scope.js +61 -74
- package/dist/runtime/host/actor-packet-relay.d.ts +9 -6
- package/dist/runtime/host/actor-packet-relay.js +48 -91
- package/dist/runtime/host/actor-placement-coordinator.js +7 -5
- package/dist/runtime/host/actor-runtime-options-factory.d.ts +2 -0
- package/dist/runtime/host/actor-runtime-options-factory.js +17 -4
- package/dist/runtime/host/actor-transfer-runtime.d.ts +28 -28
- package/dist/runtime/host/actor-transfer-runtime.js +210 -256
- package/dist/runtime/host/application-job-queue.js +16 -33
- package/dist/runtime/host/bound-session-relay.js +1 -1
- package/dist/runtime/host/channel-runtime-options-factory.js +1 -1
- package/dist/runtime/host/index.d.ts +19 -14
- package/dist/runtime/host/index.js +234 -175
- package/dist/runtime/host/instance-activation-authority.d.ts +2 -3
- package/dist/runtime/host/instance-activation-authority.js +17 -45
- package/dist/runtime/host/location-runtime-owner.d.ts +1 -1
- package/dist/runtime/host/location-runtime-owner.js +2 -2
- package/dist/runtime/host/remote-actor-join-receiver.d.ts +2 -2
- package/dist/runtime/host/remote-actor-join-receiver.js +1 -14
- package/dist/runtime/host/remote-actor-packet-target-store.d.ts +3 -2
- package/dist/runtime/host/remote-actor-packet-target-store.js +8 -47
- package/dist/runtime/host/remote-bound-session-relay.d.ts +2 -3
- package/dist/runtime/host/remote-bound-session-relay.js +11 -23
- package/dist/runtime/host/route-mesh-runtime.d.ts +14 -10
- package/dist/runtime/host/route-mesh-runtime.js +178 -257
- package/dist/runtime/host/runtime-shutdown.d.ts +2 -0
- package/dist/runtime/host/runtime-shutdown.js +18 -21
- package/dist/runtime/host/service-relocation-control.js +6 -1
- package/dist/runtime/host/service-relocation-host-runtime.d.ts +71 -38
- package/dist/runtime/host/service-relocation-host-runtime.js +816 -651
- package/dist/runtime/host/spot-address-transport.d.ts +2 -3
- package/dist/runtime/host/spot-address-transport.js +34 -136
- package/dist/runtime/host/spot-node-runtime-options-factory.d.ts +1 -1
- package/dist/runtime/host/spot-node-runtime-options-factory.js +3 -2
- package/dist/runtime/host/spot-runtime-options-factory.d.ts +4 -7
- package/dist/runtime/host/spot-runtime-options-factory.js +53 -21
- package/dist/runtime/host/stateful-authority-route-runtime.js +6 -2
- package/dist/runtime/host/user-spot-creation-coordinator.d.ts +14 -6
- package/dist/runtime/host/user-spot-creation-coordinator.js +96 -95
- package/dist/runtime/locations/aggregate-inventory-store.js +13 -10
- package/dist/runtime/locations/authority-key-codec.js +4 -3
- package/dist/runtime/locations/auto-connect-reconciler.d.ts +4 -0
- package/dist/runtime/locations/auto-connect-reconciler.js +37 -25
- package/dist/runtime/locations/creation-operation-id.js +6 -4
- package/dist/runtime/locations/domain-store-contract.d.ts +3 -3
- package/dist/runtime/locations/in-memory-authority-store.js +31 -15
- package/dist/runtime/locations/in-memory-location-store.d.ts +2 -2
- package/dist/runtime/locations/in-memory-location-store.js +17 -14
- package/dist/runtime/locations/in-memory-provider-location-store.d.ts +1 -0
- package/dist/runtime/locations/in-memory-provider-location-store.js +79 -27
- package/dist/runtime/locations/key-codec.js +3 -2
- package/dist/runtime/locations/lease-tracker.d.ts +3 -5
- package/dist/runtime/locations/lease-tracker.js +7 -11
- package/dist/runtime/locations/lifecycle.d.ts +5 -10
- package/dist/runtime/locations/lifecycle.js +4 -33
- package/dist/runtime/locations/location-store-failure.d.ts +2 -0
- package/dist/runtime/locations/location-store-failure.js +7 -0
- package/dist/runtime/locations/location-store-pages.d.ts +3 -0
- package/dist/runtime/locations/location-store-pages.js +13 -0
- package/dist/runtime/locations/location-store-repository.d.ts +5 -7
- package/dist/runtime/locations/location-store-repository.js +303 -332
- package/dist/runtime/locations/relocation-blob.js +18 -5
- package/dist/runtime/locations/resolvers.d.ts +5 -5
- package/dist/runtime/locations/resolvers.js +44 -30
- package/dist/runtime/locations/runtime.d.ts +5 -4
- package/dist/runtime/locations/runtime.js +123 -92
- package/dist/runtime/locations/spot-location-claims.d.ts +8 -2
- package/dist/runtime/locations/spot-location-claims.js +40 -23
- package/dist/runtime/messaging/payload-codec.js +26 -20
- package/dist/runtime/messaging/submission-result.d.ts +3 -0
- package/dist/runtime/messaging/submission-result.js +48 -0
- package/dist/runtime/protocol/service_wire_codec.generated.d.ts +2 -0
- package/dist/runtime/protocol/service_wire_codec.generated.js +17 -8
- package/dist/runtime/protocol/service_wire_pilot_codec.generated.d.ts +1 -0
- package/dist/runtime/protocol/service_wire_pilot_codec.generated.js +3 -2
- package/dist/runtime/spots/formal-remote-actor-admission-registry.d.ts +3 -3
- package/dist/runtime/spots/formal-remote-actor-admission-registry.js +4 -4
- package/dist/runtime/spots/formal-remote-actor-transfer-registry.d.ts +6 -3
- package/dist/runtime/spots/index.d.ts +29 -29
- package/dist/runtime/spots/index.js +441 -313
- package/dist/runtime/spots/spot-activation-registry.d.ts +4 -4
- package/dist/runtime/spots/spot-activation-registry.js +27 -60
- package/dist/runtime/spots/spot-activation-state.d.ts +2 -11
- package/dist/runtime/spots/spot-activation-state.js +4 -17
- package/dist/runtime/spots/spot-activation.d.ts +10 -9
- package/dist/runtime/spots/spot-activation.js +103 -81
- package/dist/runtime/spots/spot-actor-admission-coordinator.d.ts +1 -2
- package/dist/runtime/spots/spot-actor-admission-coordinator.js +3 -40
- package/dist/runtime/spots/spot-actor-join-dispatch.d.ts +10 -18
- package/dist/runtime/spots/spot-actor-join-dispatch.js +5 -55
- package/dist/runtime/spots/spot-actor-lifecycle-drain.js +2 -2
- package/dist/runtime/spots/spot-actor-membership.d.ts +7 -5
- package/dist/runtime/spots/spot-actor-membership.js +44 -53
- package/dist/runtime/spots/spot-actor-packet-dispatch.d.ts +0 -1
- package/dist/runtime/spots/spot-actor-packet-dispatch.js +0 -9
- package/dist/runtime/spots/spot-actor-packet-relay-dispatch.d.ts +2 -2
- package/dist/runtime/spots/spot-actor-packet-relay-dispatch.js +1 -7
- package/dist/runtime/spots/spot-context.d.ts +2 -2
- package/dist/runtime/spots/spot-entry-activation.d.ts +3 -4
- package/dist/runtime/spots/spot-entry-activation.js +9 -21
- package/dist/runtime/spots/spot-lifecycle-metrics.js +3 -2
- package/dist/runtime/spots/spot-manager-public.d.ts +5 -6
- package/dist/runtime/spots/spot-manager-public.js +6 -5
- package/dist/runtime/spots/spot-node-autoconnect.js +22 -31
- package/dist/runtime/spots/spot-node-runtime-manager.d.ts +22 -21
- package/dist/runtime/spots/spot-node-runtime-manager.js +73 -82
- package/dist/runtime/spots/spot-outbound.d.ts +4 -3
- package/dist/runtime/spots/spot-outbound.js +10 -37
- package/dist/runtime/spots/spot-remote-codec.js +5 -3
- package/dist/runtime/spots/spot-route-packet-dispatch.d.ts +2 -2
- package/dist/runtime/spots/spot-route-packet-dispatch.js +8 -8
- package/dist/runtime/spots/spot-route-replies.d.ts +2 -2
- package/dist/runtime/spots/spot-route-replies.js +3 -1
- package/dist/runtime/spots/spot-routed-actor-admission.d.ts +3 -2
- package/dist/runtime/spots/spot-routed-actor-admission.js +3 -2
- package/dist/runtime/spots/spot-routed-frame-dispatch.d.ts +2 -7
- package/dist/runtime/spots/spot-routed-frame-dispatch.js +1 -70
- package/dist/runtime/spots/spot-routed-spot-packet-dispatch.d.ts +4 -0
- package/dist/runtime/spots/spot-routed-spot-packet-dispatch.js +65 -15
- package/dist/runtime/spots/spot-runtime-ports.d.ts +4 -20
- package/dist/runtime/spots/spot-serial-executor.d.ts +5 -0
- package/dist/runtime/spots/spot-serial-executor.js +9 -2
- package/dist/runtime/spots/spot-serial-turn-executor.d.ts +29 -6
- package/dist/runtime/spots/spot-serial-turn-executor.js +89 -13
- package/dist/runtime/spots/spot-timer.d.ts +3 -2
- package/dist/runtime/streams/actor-session-binding-registry.d.ts +17 -32
- package/dist/runtime/streams/actor-session-binding-registry.js +145 -367
- package/dist/runtime/streams/actor-session-binding-runtime-owner.d.ts +2 -6
- package/dist/runtime/streams/bound-actor-relay-sender.d.ts +6 -2
- package/dist/runtime/streams/bound-actor-relay-sender.js +57 -33
- package/dist/runtime/streams/bound-session-service.d.ts +7 -0
- package/dist/runtime/streams/bound-session-service.js +12 -19
- package/dist/runtime/streams/index.d.ts +15 -14
- package/dist/runtime/streams/index.js +38 -39
- package/dist/runtime/streams/managed-stream.d.ts +3 -0
- package/dist/runtime/streams/managed-stream.js +17 -8
- package/dist/runtime/streams/native-fallback-bound-session.js +1 -3
- package/dist/runtime/streams/protocol.d.ts +6 -33
- package/dist/runtime/streams/protocol.js +38 -110
- package/dist/runtime/streams/session-actor-coordinator.d.ts +2 -3
- package/dist/runtime/streams/session-actor-coordinator.js +12 -4
- package/dist/runtime/streams/session-calls.d.ts +1 -1
- package/dist/runtime/streams/session-calls.js +5 -4
- package/dist/runtime/streams/session-context.d.ts +6 -6
- package/dist/runtime/streams/session-context.js +22 -4
- package/dist/runtime/streams/session-requests.js +2 -1
- package/dist/runtime/streams/session-serial-executor.js +2 -2
- package/dist/runtime/streams/stream-binding-runtime-ports.d.ts +16 -1
- package/dist/runtime/streams/stream-frame-factory.js +2 -2
- package/dist/runtime/streams/stream-session-runtime.d.ts +10 -11
- package/dist/runtime/streams/stream-session-runtime.js +25 -33
- package/dist/runtime/workers/index.d.ts +2 -2
- package/dist/runtime/workers/index.js +5 -4
- package/package.json +3 -3
- package/src/contracts/Channels/IZLinkFanoutClient.ts +0 -7
- package/src/contracts/Common/CoreTypes.ts +7 -0
- package/src/contracts/Common/index.ts +1 -1
- package/src/contracts/Configuration/InternalDefaults.ts +12 -0
- package/src/contracts/Configuration/Registration.ts +92 -48
- package/src/contracts/Configuration/RegistrationBuilderPolicy.ts +44 -2
- package/src/contracts/Configuration/RegistrationBuilders.ts +77 -68
- package/src/contracts/Configuration/RegistrationTypes.ts +1 -0
- package/src/contracts/Configuration/RegistrationValidators.ts +19 -13
- package/src/contracts/Configuration/TimerRegistrationValidator.ts +4 -2
- package/src/contracts/Dispatch/ZLinkDispatchOptions.ts +1 -0
- package/src/contracts/Handlers/JsonContract.ts +14 -4
- package/src/contracts/Locations/Authority.ts +7 -3
- package/src/contracts/Locations/Options.ts +1 -1
- package/src/contracts/Locations/Stores.ts +14 -0
- package/src/contracts/RouteMesh/RuntimeTopology.ts +10 -0
- package/src/contracts/Spots/Contracts.ts +1 -1
- package/src/internal.ts +15 -0
- package/src/nest-integration.ts +28 -10
- package/src/runtime/abort.ts +6 -5
- package/src/runtime/activation-admission.ts +72 -0
- package/src/runtime/actors/actor-authority-payload-codec.ts +58 -20
- package/src/runtime/actors/actor-client.ts +77 -204
- package/src/runtime/actors/actor-context.ts +45 -39
- package/src/runtime/actors/actor-handoff.ts +55 -45
- package/src/runtime/actors/actor-lifecycle-snapshot.ts +2 -1
- package/src/runtime/actors/actor-local-native-join.ts +174 -215
- package/src/runtime/actors/actor-native-lookup.ts +2 -9
- package/src/runtime/actors/actor-packet-relay-wire.ts +18 -12
- package/src/runtime/actors/actor-remote-joiner.ts +15 -36
- package/src/runtime/actors/actor-remote-wire.ts +5 -3
- package/src/runtime/actors/actor-request-deadline.ts +49 -0
- package/src/runtime/actors/actor-retry-delay.ts +2 -1
- package/src/runtime/actors/actor-runtime-contracts.ts +4 -10
- package/src/runtime/actors/actor-runtime-state.ts +85 -247
- package/src/runtime/actors/actor-source-transfer.ts +5 -18
- package/src/runtime/actors/bound-session-wire.ts +2 -8
- package/src/runtime/actors/deferred-join-completion.ts +44 -0
- package/src/runtime/actors/index.ts +122 -88
- package/src/runtime/actors/spot-actor-dispatch.ts +60 -29
- package/src/runtime/actors/transferred-actor-rollback.ts +11 -62
- package/src/runtime/admission.ts +13 -2
- package/src/runtime/application-jobs/application-job-queue-scope.ts +4 -4
- package/src/runtime/backend/contracts/index.ts +15 -42
- package/src/runtime/backend/mesh-actor-session-node-adapter.ts +4 -28
- package/src/runtime/backend/mesh-dispatch-pump.ts +111 -117
- package/src/runtime/backend/node/node-backend-adapter-factory.ts +5 -25
- package/src/runtime/backend/node/node-backend-adapter-support.ts +32 -35
- package/src/runtime/backend/node/node-event-loop-poller.ts +16 -8
- package/src/runtime/backend/node/node-monitor-backend-adapter.ts +1 -0
- package/src/runtime/backend/node/node-raw-binding-port.ts +58 -23
- package/src/runtime/backend/node/node-raw-mesh-backend.ts +252 -162
- package/src/runtime/backend/node/node-socket-backend-adapter.ts +5 -4
- package/src/runtime/backend/raw-binding-port.ts +14 -1
- package/src/runtime/backend/runtime-values.ts +4 -1
- package/src/runtime/channels/channel-clients.ts +132 -96
- package/src/runtime/channels/channel-envelope-inspection.ts +2 -1
- package/src/runtime/channels/channel-envelope.ts +58 -29
- package/src/runtime/channels/channel-outbound-operations.ts +10 -31
- package/src/runtime/channels/channel-receive-loops.ts +39 -7
- package/src/runtime/channels/channel-runtime-lifecycle.ts +60 -27
- package/src/runtime/channels/channel-runtime-manager.ts +8 -15
- package/src/runtime/channels/channel-socket-options.ts +8 -2
- package/src/runtime/channels/channel-socket-registry.ts +369 -262
- package/src/runtime/channels/channel-transports.ts +161 -115
- package/src/runtime/channels/client-server-location-runtime.ts +17 -17
- package/src/runtime/channels/client-server-service-wire.ts +40 -12
- package/src/runtime/channels/dispatch-error-reporter.ts +7 -5
- package/src/runtime/channels/fanout-location-runtime.ts +175 -106
- package/src/runtime/channels/spot-direct-envelope.ts +1 -1
- package/src/runtime/channels/spot-node-route-transport.ts +5 -2
- package/src/runtime/diagnostics/diagnostic-text.ts +4 -0
- package/src/runtime/diagnostics/dispatch-error-details.ts +36 -1
- package/src/runtime/diagnostics/flow-context.ts +16 -2
- package/src/runtime/diagnostics/index.ts +27 -17
- package/src/runtime/diagnostics/message-flow.ts +15 -25
- package/src/runtime/diagnostics/runtime-metrics.ts +181 -113
- package/src/runtime/diagnostics/runtime-observation-queue.ts +3 -2
- package/src/runtime/diagnostics/topology-runtime-projections.ts +194 -162
- package/src/runtime/disposal.ts +19 -0
- package/src/runtime/execution/index.ts +116 -38
- package/src/runtime/execution/serial-execution-queue.ts +179 -34
- package/src/runtime/execution/state-lane.ts +142 -4
- package/src/runtime/foundation/actor-join-recovery-codec.ts +13 -8
- package/src/runtime/foundation/event-loop-resources.ts +5 -122
- package/src/runtime/foundation/listener-records.ts +21 -0
- package/src/runtime/foundation/operation-identity.ts +11 -5
- package/src/runtime/foundation/operation-registry.ts +33 -50
- package/src/runtime/foundation/raw-service-mesh-runtime.ts +170 -571
- package/src/runtime/foundation/runtime-state-projections.ts +9 -1
- package/src/runtime/foundation/service-authority-payload-codec.ts +41 -13
- package/src/runtime/foundation/service-discovery-registry.ts +32 -3
- package/src/runtime/foundation/service-instance-activation-recovery-codec.ts +12 -4
- package/src/runtime/foundation/service-liveness-registry.ts +2 -1
- package/src/runtime/foundation/service-maintenance-runtime.ts +30 -19
- package/src/runtime/foundation/service-metadata-codec.ts +2 -2
- package/src/runtime/foundation/service-relocation-aggregate-committer.ts +3 -66
- package/src/runtime/foundation/service-relocation-coordinator.ts +13 -0
- package/src/runtime/foundation/service-relocation-object-owner.ts +23 -7
- package/src/runtime/foundation/service-relocation-runtime.ts +57 -35
- package/src/runtime/foundation/service-runtime-contracts.ts +46 -10
- package/src/runtime/foundation/service-session-binding-ingress-port.ts +0 -25
- package/src/runtime/foundation/service-stateful-registry.ts +14 -2
- package/src/runtime/foundation/service-stateful-runtime.ts +435 -327
- package/src/runtime/foundation/service-stateful-wire-codec.ts +329 -199
- package/src/runtime/foundation/service-topology-registry.ts +30 -79
- package/src/runtime/foundation/service-wire-binary-primitives.ts +6 -0
- package/src/runtime/foundation/service-wire-codec.ts +15 -8
- package/src/runtime/foundation/service-wire-constants.generated.ts +1 -0
- package/src/runtime/foundation/service-wire-m6a-codec.ts +29 -15
- package/src/runtime/framework-errors-internal.ts +380 -134
- package/src/runtime/handlers/handler-instance-scope.ts +68 -95
- package/src/runtime/host/actor-packet-relay.ts +57 -147
- package/src/runtime/host/actor-placement-coordinator.ts +8 -5
- package/src/runtime/host/actor-runtime-options-factory.ts +27 -8
- package/src/runtime/host/actor-transfer-runtime.ts +266 -418
- package/src/runtime/host/application-job-queue.ts +28 -34
- package/src/runtime/host/bound-session-relay.ts +1 -2
- package/src/runtime/host/channel-runtime-options-factory.ts +1 -2
- package/src/runtime/host/index.ts +408 -312
- package/src/runtime/host/instance-activation-authority.ts +89 -109
- package/src/runtime/host/location-runtime-owner.ts +4 -2
- package/src/runtime/host/remote-actor-join-receiver.ts +3 -31
- package/src/runtime/host/remote-actor-packet-target-store.ts +17 -58
- package/src/runtime/host/remote-bound-session-relay.ts +12 -44
- package/src/runtime/host/route-mesh-runtime.ts +236 -275
- package/src/runtime/host/runtime-shutdown.ts +17 -21
- package/src/runtime/host/service-relocation-control.ts +14 -1
- package/src/runtime/host/service-relocation-host-runtime.ts +1161 -904
- package/src/runtime/host/spot-address-transport.ts +73 -195
- package/src/runtime/host/spot-node-runtime-options-factory.ts +6 -3
- package/src/runtime/host/spot-runtime-options-factory.ts +92 -30
- package/src/runtime/host/stateful-authority-route-runtime.ts +8 -4
- package/src/runtime/host/user-spot-creation-coordinator.ts +182 -163
- package/src/runtime/locations/aggregate-inventory-store.ts +16 -13
- package/src/runtime/locations/authority-key-codec.ts +7 -3
- package/src/runtime/locations/auto-connect-reconciler.ts +39 -26
- package/src/runtime/locations/creation-operation-id.ts +6 -3
- package/src/runtime/locations/domain-store-contract.ts +12 -3
- package/src/runtime/locations/in-memory-authority-store.ts +44 -15
- package/src/runtime/locations/in-memory-location-store.ts +50 -39
- package/src/runtime/locations/in-memory-provider-location-store.ts +110 -31
- package/src/runtime/locations/key-codec.ts +3 -2
- package/src/runtime/locations/lease-tracker.ts +8 -14
- package/src/runtime/locations/lifecycle.ts +16 -45
- package/src/runtime/locations/location-store-failure.ts +4 -0
- package/src/runtime/locations/location-store-pages.ts +18 -0
- package/src/runtime/locations/location-store-repository.ts +450 -478
- package/src/runtime/locations/relocation-blob.ts +17 -6
- package/src/runtime/locations/resolvers.ts +90 -58
- package/src/runtime/locations/runtime.ts +220 -110
- package/src/runtime/locations/spot-location-claims.ts +54 -26
- package/src/runtime/messaging/payload-codec.ts +35 -24
- package/src/runtime/messaging/submission-result.ts +57 -1
- package/src/runtime/protocol/service_wire_codec.generated.ts +27 -10
- package/src/runtime/protocol/service_wire_pilot_codec.generated.ts +4 -4
- package/src/runtime/spots/formal-remote-actor-admission-registry.ts +6 -6
- package/src/runtime/spots/formal-remote-actor-transfer-registry.ts +6 -3
- package/src/runtime/spots/index.ts +687 -437
- package/src/runtime/spots/spot-activation-registry.ts +42 -71
- package/src/runtime/spots/spot-activation-state.ts +4 -16
- package/src/runtime/spots/spot-activation.ts +167 -115
- package/src/runtime/spots/spot-actor-admission-coordinator.ts +5 -57
- package/src/runtime/spots/spot-actor-join-dispatch.ts +25 -79
- package/src/runtime/spots/spot-actor-lifecycle-drain.ts +20 -18
- package/src/runtime/spots/spot-actor-membership.ts +107 -75
- package/src/runtime/spots/spot-actor-packet-dispatch.ts +0 -16
- package/src/runtime/spots/spot-actor-packet-relay-dispatch.ts +3 -15
- package/src/runtime/spots/spot-context.ts +3 -3
- package/src/runtime/spots/spot-entry-activation.ts +13 -33
- package/src/runtime/spots/spot-lifecycle-metrics.ts +3 -2
- package/src/runtime/spots/spot-manager-public.ts +29 -21
- package/src/runtime/spots/spot-node-autoconnect.ts +20 -26
- package/src/runtime/spots/spot-node-runtime-manager.ts +145 -140
- package/src/runtime/spots/spot-outbound.ts +47 -68
- package/src/runtime/spots/spot-remote-codec.ts +7 -3
- package/src/runtime/spots/spot-route-packet-dispatch.ts +25 -24
- package/src/runtime/spots/spot-route-replies.ts +6 -4
- package/src/runtime/spots/spot-routed-actor-admission.ts +13 -6
- package/src/runtime/spots/spot-routed-frame-dispatch.ts +6 -77
- package/src/runtime/spots/spot-routed-spot-packet-dispatch.ts +95 -22
- package/src/runtime/spots/spot-runtime-ports.ts +10 -43
- package/src/runtime/spots/spot-serial-executor.ts +10 -2
- package/src/runtime/spots/spot-serial-turn-executor.ts +120 -13
- package/src/runtime/spots/spot-timer.ts +3 -2
- package/src/runtime/streams/actor-session-binding-registry.ts +182 -560
- package/src/runtime/streams/actor-session-binding-runtime-owner.ts +1 -19
- package/src/runtime/streams/bound-actor-relay-sender.ts +89 -43
- package/src/runtime/streams/bound-session-service.ts +23 -37
- package/src/runtime/streams/index.ts +102 -88
- package/src/runtime/streams/managed-stream.ts +29 -10
- package/src/runtime/streams/native-fallback-bound-session.ts +1 -3
- package/src/runtime/streams/protocol.ts +34 -88
- package/src/runtime/streams/session-actor-coordinator.ts +17 -5
- package/src/runtime/streams/session-calls.ts +6 -5
- package/src/runtime/streams/session-context.ts +54 -10
- package/src/runtime/streams/session-requests.ts +2 -1
- package/src/runtime/streams/session-serial-executor.ts +2 -2
- package/src/runtime/streams/stream-binding-runtime-ports.ts +22 -1
- package/src/runtime/streams/stream-frame-factory.ts +2 -3
- package/src/runtime/streams/stream-session-runtime.ts +57 -59
- package/src/runtime/workers/index.ts +13 -12
- package/dist/runtime/actors/deferred-join-accepted-journal.d.ts +0 -47
- package/dist/runtime/actors/deferred-join-accepted-journal.js +0 -992
- package/dist/runtime/actors/post-commit-actor-location.d.ts +0 -19
- package/dist/runtime/actors/post-commit-actor-location.js +0 -72
- package/dist/runtime/spots/spot-native-actor-join-admission.d.ts +0 -26
- package/dist/runtime/spots/spot-native-actor-join-admission.js +0 -106
- package/src/runtime/actors/deferred-join-accepted-journal.ts +0 -1346
- package/src/runtime/actors/post-commit-actor-location.ts +0 -121
- package/src/runtime/spots/spot-native-actor-join-admission.ts +0 -155
|
@@ -1,5 +1,20 @@
|
|
|
1
|
+
import { ZlinkStreamContentType } from '@zlink-systems/stream-wire';
|
|
1
2
|
import { AsyncLocalStorage } from 'node:async_hooks';
|
|
3
|
+
import { ZLinkFrameworkException } from '../../contracts';
|
|
4
|
+
import type { ZLinkAuthoritySnapshot } from '../locations/internal-location-contracts';
|
|
5
|
+
import { decodeServiceClosingSpotAuthority } from './service-authority-payload-codec';
|
|
6
|
+
import {
|
|
7
|
+
ZLinkRuntimeDispatchErrorAction as ZLinkDispatchErrorAction,
|
|
8
|
+
ZLinkRuntimeDispatchErrorReason as ZLinkDispatchErrorReason,
|
|
9
|
+
ZLinkDispatchErrorSurface,
|
|
10
|
+
ZLinkDispatchMessageKind,
|
|
11
|
+
ZLinkRuntimeMessageFlowOutcome as ZLinkMessageFlowOutcome
|
|
12
|
+
} from '../../contracts/Dispatch/ZLinkDispatchOptions';
|
|
2
13
|
import { awaitWithAbort } from '../abort';
|
|
14
|
+
import { shouldCompactBackingArray } from '../admission';
|
|
15
|
+
import { RequestResult, SubmitResult, isZLinkBackendResultError } from '../backend/runtime-values';
|
|
16
|
+
import type { ZLinkDispatchErrorReporter } from '../channels/dispatch-error-reporter';
|
|
17
|
+
import { flowIfEnabled } from '../diagnostics/message-flow';
|
|
3
18
|
import { captureZLinkExecutionTurn } from '../execution';
|
|
4
19
|
import {
|
|
5
20
|
ZLinkFrameworkInternalErrorKind,
|
|
@@ -8,18 +23,26 @@ import {
|
|
|
8
23
|
internalFrameworkWireReply,
|
|
9
24
|
translateWireReplyDecodeError
|
|
10
25
|
} from '../framework-errors-internal';
|
|
11
|
-
import { RequestResult, SubmitResult, isZLinkBackendResultError } from '../backend/runtime-values';
|
|
12
|
-
import type { ZLinkDispatchErrorReporter } from '../channels/dispatch-error-reporter';
|
|
13
26
|
import {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
} from '
|
|
27
|
+
decodeActorJoin28,
|
|
28
|
+
encodeActorJoin28,
|
|
29
|
+
type ActorJoin28
|
|
30
|
+
} from '../protocol/service_wire_pilot_codec.generated';
|
|
31
|
+
import { canonicalActorJoinHandoffId, routingIdBytes } from './actor-join-recovery-codec';
|
|
32
|
+
import { OperationRegistry } from './operation-registry';
|
|
33
|
+
import {
|
|
34
|
+
MessageFollowSuppressionRegistry,
|
|
35
|
+
type MessageFollowSuppressionFence
|
|
36
|
+
} from './message-follow-suppression-registry';
|
|
37
|
+
import { ZLINK_NATIVE_CORRELATION_OPERATION_NAMESPACE } from './operation-identity';
|
|
18
38
|
import type {
|
|
19
39
|
RawServiceIngressRecord,
|
|
20
40
|
RawServiceMeshRuntime,
|
|
21
41
|
RawServicePumpResult
|
|
22
42
|
} from './raw-service-mesh-runtime';
|
|
43
|
+
import type { ServiceInstanceActivationRecoveryEnvelope } from './service-instance-activation-recovery-codec';
|
|
44
|
+
import type { ServiceMailboxRecord } from './service-mailbox';
|
|
45
|
+
import { validateServiceMetadataFrame } from './service-metadata-codec';
|
|
23
46
|
import {
|
|
24
47
|
ActorLifecycleKind,
|
|
25
48
|
OperationKind,
|
|
@@ -28,13 +51,9 @@ import {
|
|
|
28
51
|
type ActorJoinCompletionPayload,
|
|
29
52
|
type ActorLocation,
|
|
30
53
|
type ReceiveKindData,
|
|
54
|
+
type ServiceStreamSessionBinding,
|
|
31
55
|
type StreamSessionActorAuthorityFence
|
|
32
56
|
} from './service-runtime-contracts';
|
|
33
|
-
import type { ServiceMailboxRecord } from './service-mailbox';
|
|
34
|
-
import {
|
|
35
|
-
MessageFollowSuppressionRegistry,
|
|
36
|
-
type MessageFollowSuppressionFence
|
|
37
|
-
} from './message-follow-suppression-registry';
|
|
38
57
|
import {
|
|
39
58
|
ServiceStaleGenerationError,
|
|
40
59
|
ServiceStatefulRegistry,
|
|
@@ -46,6 +65,8 @@ import {
|
|
|
46
65
|
type ServiceSpotState
|
|
47
66
|
} from './service-stateful-registry';
|
|
48
67
|
import {
|
|
68
|
+
M6bServiceWireCommand,
|
|
69
|
+
M6bServiceWireFlag,
|
|
49
70
|
decodeStatefulHeader,
|
|
50
71
|
decodeStatefulReply,
|
|
51
72
|
encodeActorCreateHeader,
|
|
@@ -63,43 +84,37 @@ import {
|
|
|
63
84
|
encodeStatefulReply,
|
|
64
85
|
encodeUserSpotCloseHeader,
|
|
65
86
|
encodeUserSpotCreateHeader,
|
|
66
|
-
M6bServiceWireCommand,
|
|
67
|
-
M6bServiceWireFlag,
|
|
68
87
|
sessionBindingFromWire,
|
|
88
|
+
type ServiceActorCreateRecord,
|
|
69
89
|
type ServiceActorRouteFence,
|
|
70
90
|
type ServiceBoundSessionActorAuthority,
|
|
71
|
-
type
|
|
72
|
-
type ServiceActorCreateRecord,
|
|
91
|
+
type ServiceDirectSpotRouteFence,
|
|
73
92
|
type ServiceInstanceActivationTarget,
|
|
74
93
|
type ServiceInstanceRouteFence,
|
|
75
94
|
type ServiceMessageFollowRoute,
|
|
76
|
-
type
|
|
95
|
+
type ServiceRetiredBoundSessionRouteFence,
|
|
77
96
|
type ServiceSpotRouteFence,
|
|
78
97
|
type ServiceStatefulReplyTail,
|
|
79
98
|
type ServiceStatefulWireRecord,
|
|
80
99
|
type ServiceUserSpotCloseRecord,
|
|
81
100
|
type ServiceUserSpotCreateRecord
|
|
82
101
|
} from './service-stateful-wire-codec';
|
|
83
|
-
import { routingIdsEqual } from '../routing-id';
|
|
84
102
|
import {
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
} from '
|
|
89
|
-
import { canonicalActorJoinHandoffId, routingIdBytes } from './actor-join-recovery-codec';
|
|
90
|
-
|
|
103
|
+
SERVICE_WIRE_COMMAND_OFFSET,
|
|
104
|
+
SERVICE_WIRE_FLAGS_OFFSET
|
|
105
|
+
} from './service-wire-binary-primitives';
|
|
106
|
+
import { SERVICE_WIRE_MAGIC, SERVICE_WIRE_MAJOR } from './service-wire-constants.generated';
|
|
91
107
|
import {
|
|
108
|
+
ServiceWireProtocolError,
|
|
92
109
|
decodeApplicationPayload,
|
|
110
|
+
decodeApplicationPayloadView,
|
|
93
111
|
encodeApplicationPayload,
|
|
94
|
-
type ServiceApplicationPayload
|
|
95
|
-
ServiceWireProtocolError
|
|
112
|
+
type ServiceApplicationPayload
|
|
96
113
|
} from './service-wire-m6a-codec';
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
import { ZLinkFrameworkException } from '../../contracts';
|
|
114
|
+
const STATEFUL_OPERATION_RETRY_TICK_MS = 20;
|
|
115
|
+
|
|
116
|
+
const MAX_NODE_TIMER_DELAY_MS = 2_147_483_647;
|
|
101
117
|
|
|
102
|
-
const ACTOR_ROUTE_STALE = 21;
|
|
103
118
|
const SPOT_MOVING = 34;
|
|
104
119
|
const USER_SPOT_OPERATION_CAPACITY = 65_536;
|
|
105
120
|
const USER_SPOT_OPERATION_REPLAY_RETENTION_MS = 5 * 60_000;
|
|
@@ -110,12 +125,6 @@ export interface ServiceSpotMessageFollowSeal {
|
|
|
110
125
|
readonly serial: bigint;
|
|
111
126
|
}
|
|
112
127
|
|
|
113
|
-
export interface ServiceBoundSessionSendFence {
|
|
114
|
-
readonly targetNodeGeneration: bigint;
|
|
115
|
-
readonly authorityOwnerGeneration: bigint;
|
|
116
|
-
readonly ownerLeaseGeneration: bigint;
|
|
117
|
-
}
|
|
118
|
-
|
|
119
128
|
interface ServiceSpotMessageFollowRecord {
|
|
120
129
|
readonly ingress: RawServiceIngressRecord;
|
|
121
130
|
readonly wire: Extract<ServiceStatefulWireRecord, { readonly kind: 'spotSend' | 'spotRequest' }>;
|
|
@@ -172,7 +181,9 @@ export interface ServiceStatefulMailboxData {
|
|
|
172
181
|
readonly isPending?: () => boolean;
|
|
173
182
|
/** Carries the local operation deadline into the lifecycle dispatch lane. */
|
|
174
183
|
readonly deadlineUnixMs?: bigint;
|
|
184
|
+
readonly activationRecord?: Extract<ServiceStatefulWireRecord, { readonly kind: 'instanceSpot' }>;
|
|
175
185
|
readonly onTerminalCompletion?: () => void | Promise<void>;
|
|
186
|
+
readonly onHandlerTurnStarted?: () => void;
|
|
176
187
|
/** Decoded only by the canonical command-28 generator path. */
|
|
177
188
|
readonly canonicalApplicationPayload?: ServiceApplicationPayload;
|
|
178
189
|
readonly reply?: (
|
|
@@ -196,9 +207,8 @@ export interface ServiceCanonicalActorJoinCandidate {
|
|
|
196
207
|
|
|
197
208
|
export interface ServiceSessionDelivery {
|
|
198
209
|
readonly binding: ServiceSessionBinding;
|
|
199
|
-
readonly bindingIngress?: ServiceSessionBindingIngressPort;
|
|
200
210
|
/**
|
|
201
|
-
* Delivers the
|
|
211
|
+
* Delivers the M6A application frame after the binding fence has
|
|
202
212
|
* been validated. The stream adapter owns multipart decoding at that point.
|
|
203
213
|
*/
|
|
204
214
|
readonly deliver: (sessionRid: string, payloadFrame: Uint8Array) => Promise<boolean>;
|
|
@@ -233,7 +243,6 @@ export type ServiceInstanceApplicationTarget = ServiceInstanceApplicationIdentit
|
|
|
233
243
|
export interface ServiceInstanceApplicationLifecycle {
|
|
234
244
|
isMaterialized(target: ServiceInstanceApplicationIdentity): boolean;
|
|
235
245
|
isMaterializing?(target: ServiceInstanceApplicationIdentity): boolean;
|
|
236
|
-
isClosing?(target: ServiceInstanceApplicationIdentity): boolean;
|
|
237
246
|
isIdleEvicting?(target: ServiceInstanceApplicationIdentity): boolean;
|
|
238
247
|
beginIdleEviction?(target: ServiceInstanceApplicationIdentity): boolean;
|
|
239
248
|
materialize(target: ServiceInstanceApplicationIdentity, objectGeneration: bigint): Promise<void>;
|
|
@@ -263,8 +272,13 @@ export type ServiceInstanceAuthorityRead =
|
|
|
263
272
|
readonly kind: 'creating';
|
|
264
273
|
readonly objectGeneration: bigint;
|
|
265
274
|
readonly authorityOwnerGeneration: bigint;
|
|
275
|
+
readonly authority?: ZLinkAuthoritySnapshot;
|
|
266
276
|
}
|
|
267
|
-
| {
|
|
277
|
+
| {
|
|
278
|
+
readonly kind: 'ready';
|
|
279
|
+
readonly route: ServiceInstanceRouteFence;
|
|
280
|
+
readonly authority?: ZLinkAuthoritySnapshot;
|
|
281
|
+
};
|
|
268
282
|
|
|
269
283
|
export type ServiceInstanceAuthorityReserve =
|
|
270
284
|
| { readonly kind: 'reserved'; readonly reservation: ServiceInstanceActivationReservation }
|
|
@@ -300,7 +314,8 @@ export interface ServiceInstanceActivationAuthority {
|
|
|
300
314
|
export interface ServiceAsyncInstanceActivationAuthority {
|
|
301
315
|
read(target: ServiceInstanceActivationTarget): Promise<ServiceInstanceAuthorityRead>;
|
|
302
316
|
reserve(
|
|
303
|
-
activation: Omit<ServiceInstanceActivationRecoveryEnvelope, 'targetMeshName'
|
|
317
|
+
activation: Omit<ServiceInstanceActivationRecoveryEnvelope, 'targetMeshName'>,
|
|
318
|
+
signal?: AbortSignal
|
|
304
319
|
): Promise<ServiceInstanceAuthorityReserve>;
|
|
305
320
|
resume(
|
|
306
321
|
target: ServiceInstanceActivationTarget,
|
|
@@ -309,7 +324,8 @@ export interface ServiceAsyncInstanceActivationAuthority {
|
|
|
309
324
|
commit(
|
|
310
325
|
target: ServiceInstanceActivationTarget,
|
|
311
326
|
reservation: ServiceInstanceActivationReservation,
|
|
312
|
-
spot: ServiceSpotState
|
|
327
|
+
spot: ServiceSpotState,
|
|
328
|
+
deadlineUnixMs?: bigint
|
|
313
329
|
): Promise<{ readonly kind: 'committed' | 'lost'; readonly route: ServiceInstanceRouteFence }>;
|
|
314
330
|
complete(
|
|
315
331
|
target: ServiceInstanceActivationTarget,
|
|
@@ -366,7 +382,7 @@ export class ServiceStatefulRuntime {
|
|
|
366
382
|
|
|
367
383
|
readonly registry: ServiceStatefulRegistry;
|
|
368
384
|
|
|
369
|
-
private readonly operations
|
|
385
|
+
private readonly operations: ServiceTerminalOperationRegistry<ServiceStatefulResult>;
|
|
370
386
|
private readonly sessionDeliveries = new Map<string, ServiceSessionDelivery>();
|
|
371
387
|
/**
|
|
372
388
|
* A local Actor owner can replace its own session binding before the
|
|
@@ -378,7 +394,6 @@ export class ServiceStatefulRuntime {
|
|
|
378
394
|
private readonly subscriptions = new Map<string, Set<string>>();
|
|
379
395
|
private readonly instanceIntents = new Map<string, ServiceInstanceIntent>();
|
|
380
396
|
private readonly admittedInstanceOperations = new Map<string, bigint>();
|
|
381
|
-
private readonly pendingInstanceTerminals = new Map<string, number>();
|
|
382
397
|
private readonly pendingInstanceAuthorityTerminals = new Map<string, number>();
|
|
383
398
|
private readonly instanceApplicationWaiters = new Map<string, Set<() => void>>();
|
|
384
399
|
private readonly canonicalActorJoinHandoffs = new Map<bigint, string>();
|
|
@@ -421,7 +436,7 @@ export class ServiceStatefulRuntime {
|
|
|
421
436
|
private readonly pendingInstanceActivations = new Map<
|
|
422
437
|
string,
|
|
423
438
|
Promise<{
|
|
424
|
-
readonly spot: ServiceSpotState
|
|
439
|
+
readonly spot: Pick<ServiceSpotState, 'ref'>;
|
|
425
440
|
readonly route: ServiceInstanceRouteFence;
|
|
426
441
|
}>
|
|
427
442
|
>();
|
|
@@ -430,8 +445,12 @@ export class ServiceStatefulRuntime {
|
|
|
430
445
|
constructor(
|
|
431
446
|
private readonly raw: RawServiceMeshRuntime,
|
|
432
447
|
readonly nodeRid: string,
|
|
433
|
-
readonly nodeGeneration: bigint
|
|
448
|
+
readonly nodeGeneration: bigint,
|
|
449
|
+
onPendingOperationsChanged?: () => void
|
|
434
450
|
) {
|
|
451
|
+
this.operations = new ServiceTerminalOperationRegistry(
|
|
452
|
+
new OperationRegistry(undefined, onPendingOperationsChanged)
|
|
453
|
+
);
|
|
435
454
|
this.registry = new ServiceStatefulRegistry(nodeRid, nodeGeneration);
|
|
436
455
|
this.registry.createEntrySpot(nodeRid);
|
|
437
456
|
raw.setServiceIngress((record) => this.ingress(record));
|
|
@@ -879,6 +898,7 @@ export class ServiceStatefulRuntime {
|
|
|
879
898
|
...(envelope.replyRouteId === undefined ? {} : { replyRouteId: envelope.replyRouteId })
|
|
880
899
|
};
|
|
881
900
|
const applicationJobOwner = await this.raw.reserveLocalIngress();
|
|
901
|
+
const terminal = this.activationTerminalCompletion(target, route);
|
|
882
902
|
try {
|
|
883
903
|
const admitted = this.enqueueActivatedInstanceSpot(
|
|
884
904
|
{
|
|
@@ -904,11 +924,11 @@ export class ServiceStatefulRuntime {
|
|
|
904
924
|
Buffer.from(envelope.applicationPayloadFrame),
|
|
905
925
|
spot,
|
|
906
926
|
undefined,
|
|
907
|
-
|
|
927
|
+
terminal.onTerminalCompletion,
|
|
908
928
|
envelope.metadataFrame === undefined
|
|
909
929
|
? undefined
|
|
910
930
|
: validateServiceMetadataFrame(envelope.metadataFrame),
|
|
911
|
-
|
|
931
|
+
terminal.onHandlerTurnStarted,
|
|
912
932
|
this.instanceApplicationTarget(record, route.objectGeneration)
|
|
913
933
|
);
|
|
914
934
|
if (admitted !== 'application') {
|
|
@@ -1003,12 +1023,10 @@ export class ServiceStatefulRuntime {
|
|
|
1003
1023
|
return released;
|
|
1004
1024
|
}
|
|
1005
1025
|
|
|
1026
|
+
/** Resolves once every first terminal record of an activated Instance message is durable. */
|
|
1006
1027
|
waitForInstanceApplicationQuiescence(spotId: string, signal?: AbortSignal): Promise<void> {
|
|
1007
1028
|
const key = String(spotId);
|
|
1008
|
-
if (
|
|
1009
|
-
(this.pendingInstanceTerminals.get(key) ?? 0) === 0 &&
|
|
1010
|
-
(this.pendingInstanceAuthorityTerminals.get(key) ?? 0) === 0
|
|
1011
|
-
) {
|
|
1029
|
+
if ((this.pendingInstanceAuthorityTerminals.get(key) ?? 0) === 0) {
|
|
1012
1030
|
return Promise.resolve();
|
|
1013
1031
|
}
|
|
1014
1032
|
if (signal?.aborted === true) {
|
|
@@ -1271,11 +1289,11 @@ export class ServiceStatefulRuntime {
|
|
|
1271
1289
|
reporter.report({
|
|
1272
1290
|
surface: ZLinkDispatchErrorSurface.SpotRoute,
|
|
1273
1291
|
messageKind: ZLinkDispatchMessageKind.Send,
|
|
1274
|
-
reason:
|
|
1275
|
-
|
|
1276
|
-
this.raw.isPeerRouteReady(target.descriptor.nodeRoutingId)
|
|
1277
|
-
|
|
1278
|
-
|
|
1292
|
+
reason: this.closed
|
|
1293
|
+
? ZLinkDispatchErrorReason.Shutdown
|
|
1294
|
+
: this.raw.isPeerRouteReady(target.descriptor.nodeRoutingId)
|
|
1295
|
+
? ZLinkDispatchErrorReason.Backpressure
|
|
1296
|
+
: ZLinkDispatchErrorReason.StaleTarget,
|
|
1279
1297
|
action: ZLinkDispatchErrorAction.Drop,
|
|
1280
1298
|
meshName: this.dispatchErrorMeshName,
|
|
1281
1299
|
channelName,
|
|
@@ -1296,7 +1314,10 @@ export class ServiceStatefulRuntime {
|
|
|
1296
1314
|
if (target === undefined) {
|
|
1297
1315
|
return SubmitResult.NotFound;
|
|
1298
1316
|
}
|
|
1299
|
-
const header = encodeSpotHeader('spotSend', sourceSpotId, target
|
|
1317
|
+
const header = encodeSpotHeader('spotSend', sourceSpotId, target, undefined, {
|
|
1318
|
+
high: this.nodeGeneration,
|
|
1319
|
+
low: this.nextMessageFollowOperation++
|
|
1320
|
+
});
|
|
1300
1321
|
return this.submitOneWay(target.targetNodeRid, [header, encodeApplicationPayload(payload)]);
|
|
1301
1322
|
}
|
|
1302
1323
|
|
|
@@ -1309,13 +1330,16 @@ export class ServiceStatefulRuntime {
|
|
|
1309
1330
|
const pending = this.operations.register(timeoutMs);
|
|
1310
1331
|
const target = this.acceptSpotAuthority(requested);
|
|
1311
1332
|
if (target === undefined) {
|
|
1312
|
-
this.operations.reply(
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1333
|
+
this.operations.reply(
|
|
1334
|
+
pending.id,
|
|
1335
|
+
internalFrameworkWireReply(ZLinkFrameworkInternalErrorKind.ActorLocationStale)
|
|
1336
|
+
);
|
|
1316
1337
|
return pending;
|
|
1317
1338
|
}
|
|
1318
|
-
const header = encodeSpotHeader('spotRequest', sourceSpotId, target, pending.id
|
|
1339
|
+
const header = encodeSpotHeader('spotRequest', sourceSpotId, target, pending.id, {
|
|
1340
|
+
high: this.nodeGeneration,
|
|
1341
|
+
low: this.nextMessageFollowOperation++
|
|
1342
|
+
});
|
|
1319
1343
|
this.submitRequest(
|
|
1320
1344
|
pending,
|
|
1321
1345
|
target.targetNodeRid,
|
|
@@ -1346,7 +1370,8 @@ export class ServiceStatefulRuntime {
|
|
|
1346
1370
|
: {
|
|
1347
1371
|
...boundSession,
|
|
1348
1372
|
sequence: this.nextSessionSequence++
|
|
1349
|
-
}
|
|
1373
|
+
},
|
|
1374
|
+
{ high: this.nodeGeneration, low: this.nextMessageFollowOperation++ }
|
|
1350
1375
|
);
|
|
1351
1376
|
return this.submitOneWay(target.nodeRid, [header, encodeApplicationPayload(payload)]);
|
|
1352
1377
|
}
|
|
@@ -1363,10 +1388,10 @@ export class ServiceStatefulRuntime {
|
|
|
1363
1388
|
const pending = this.operations.register(timeoutMs);
|
|
1364
1389
|
const route = this.tryActorFence(target);
|
|
1365
1390
|
if (route === undefined) {
|
|
1366
|
-
this.operations.reply(
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1391
|
+
this.operations.reply(
|
|
1392
|
+
pending.id,
|
|
1393
|
+
internalFrameworkWireReply(ZLinkFrameworkInternalErrorKind.ActorLocationStale)
|
|
1394
|
+
);
|
|
1370
1395
|
return pending;
|
|
1371
1396
|
}
|
|
1372
1397
|
const header = encodeActorHeader(
|
|
@@ -1379,7 +1404,8 @@ export class ServiceStatefulRuntime {
|
|
|
1379
1404
|
: {
|
|
1380
1405
|
...boundSession,
|
|
1381
1406
|
sequence: this.nextSessionSequence++
|
|
1382
|
-
}
|
|
1407
|
+
},
|
|
1408
|
+
{ high: this.nodeGeneration, low: this.nextMessageFollowOperation++ }
|
|
1383
1409
|
);
|
|
1384
1410
|
this.submitRequest(
|
|
1385
1411
|
pending,
|
|
@@ -1395,7 +1421,8 @@ export class ServiceStatefulRuntime {
|
|
|
1395
1421
|
route: ServiceInstanceRouteFence,
|
|
1396
1422
|
payload: ServiceApplicationPayload,
|
|
1397
1423
|
sourceSpotId?: string,
|
|
1398
|
-
metadataFrame?: Uint8Array
|
|
1424
|
+
metadataFrame?: Uint8Array,
|
|
1425
|
+
instanceIntent = false
|
|
1399
1426
|
): Promise<number> {
|
|
1400
1427
|
return this.submitOneWay(
|
|
1401
1428
|
route.targetNodeRid,
|
|
@@ -1409,7 +1436,8 @@ export class ServiceStatefulRuntime {
|
|
|
1409
1436
|
'send',
|
|
1410
1437
|
{ high: 0n, low: 0n },
|
|
1411
1438
|
undefined,
|
|
1412
|
-
metadataFrame !== undefined
|
|
1439
|
+
metadataFrame !== undefined,
|
|
1440
|
+
instanceIntent
|
|
1413
1441
|
),
|
|
1414
1442
|
encodeApplicationPayload(payload)
|
|
1415
1443
|
],
|
|
@@ -1469,7 +1497,8 @@ export class ServiceStatefulRuntime {
|
|
|
1469
1497
|
payload: ServiceApplicationPayload,
|
|
1470
1498
|
timeoutMs: number,
|
|
1471
1499
|
sourceSpotId?: string,
|
|
1472
|
-
metadataFrame?: Uint8Array
|
|
1500
|
+
metadataFrame?: Uint8Array,
|
|
1501
|
+
instanceIntent = false
|
|
1473
1502
|
): ServiceStatefulPendingOperation {
|
|
1474
1503
|
const pending = this.operations.register(timeoutMs);
|
|
1475
1504
|
this.submitRequest(
|
|
@@ -1483,9 +1512,10 @@ export class ServiceStatefulRuntime {
|
|
|
1483
1512
|
this.nodeRid,
|
|
1484
1513
|
sourceSpotId,
|
|
1485
1514
|
'request',
|
|
1486
|
-
{ high:
|
|
1515
|
+
{ high: ZLINK_NATIVE_CORRELATION_OPERATION_NAMESPACE, low: pending.id },
|
|
1487
1516
|
pending.id,
|
|
1488
|
-
metadataFrame !== undefined
|
|
1517
|
+
metadataFrame !== undefined,
|
|
1518
|
+
instanceIntent
|
|
1489
1519
|
),
|
|
1490
1520
|
encodeApplicationPayload(payload)
|
|
1491
1521
|
],
|
|
@@ -1716,7 +1746,6 @@ export class ServiceStatefulRuntime {
|
|
|
1716
1746
|
timeoutMs: number,
|
|
1717
1747
|
deliver: ServiceSessionDelivery['deliver'],
|
|
1718
1748
|
onBindingReplaced?: ServiceSessionDelivery['onBindingReplaced'],
|
|
1719
|
-
bindingIngress?: ServiceSessionBindingIngressPort,
|
|
1720
1749
|
actorAuthority?: StreamSessionActorAuthorityFence
|
|
1721
1750
|
): ServiceStatefulPendingOperation {
|
|
1722
1751
|
const deadlineMs = performance.now() + timeoutMs;
|
|
@@ -1735,7 +1764,6 @@ export class ServiceStatefulRuntime {
|
|
|
1735
1764
|
const delivery: ServiceSessionDelivery = {
|
|
1736
1765
|
binding: localBinding,
|
|
1737
1766
|
deliver,
|
|
1738
|
-
...(bindingIngress === undefined ? {} : { bindingIngress }),
|
|
1739
1767
|
...(onBindingReplaced === undefined ? {} : { onBindingReplaced })
|
|
1740
1768
|
};
|
|
1741
1769
|
const deliveryKey = actorKey(actor);
|
|
@@ -1876,10 +1904,10 @@ export class ServiceStatefulRuntime {
|
|
|
1876
1904
|
delivery.binding.sessionRid !== sessionRid ||
|
|
1877
1905
|
delivery.binding.bindingGeneration !== expectedBindingGeneration
|
|
1878
1906
|
) {
|
|
1879
|
-
this.operations.reply(
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
|
|
1907
|
+
this.operations.reply(
|
|
1908
|
+
pending.id,
|
|
1909
|
+
internalFrameworkWireReply(ZLinkFrameworkInternalErrorKind.ActorLocationStale)
|
|
1910
|
+
);
|
|
1883
1911
|
return pending;
|
|
1884
1912
|
}
|
|
1885
1913
|
this.sessionDeliveries.delete(actorKey(actor));
|
|
@@ -1900,10 +1928,19 @@ export class ServiceStatefulRuntime {
|
|
|
1900
1928
|
return pending;
|
|
1901
1929
|
}
|
|
1902
1930
|
|
|
1903
|
-
sessionBindings(sessionRid: string): readonly
|
|
1931
|
+
sessionBindings(sessionRid: string): readonly ServiceStreamSessionBinding[] {
|
|
1904
1932
|
return [...this.sessionDeliveries.values()]
|
|
1905
1933
|
.map((value) => value.binding)
|
|
1906
|
-
.filter((binding) => binding.sessionRid === sessionRid)
|
|
1934
|
+
.filter((binding) => binding.sessionRid === sessionRid)
|
|
1935
|
+
.map((binding) => {
|
|
1936
|
+
const owner = requireSessionOwnerIdentity(binding);
|
|
1937
|
+
return {
|
|
1938
|
+
...binding,
|
|
1939
|
+
sessionOwnerNodeGeneration: owner.nodeGeneration,
|
|
1940
|
+
sessionOwnerId: owner.ownerId,
|
|
1941
|
+
sessionOwnerLeaseGeneration: owner.leaseGeneration
|
|
1942
|
+
};
|
|
1943
|
+
});
|
|
1907
1944
|
}
|
|
1908
1945
|
|
|
1909
1946
|
allSessionBindings(): readonly ServiceSessionBinding[] {
|
|
@@ -1935,16 +1972,20 @@ export class ServiceStatefulRuntime {
|
|
|
1935
1972
|
async sendBoundSession(
|
|
1936
1973
|
actor: ServiceActorRef,
|
|
1937
1974
|
expectedBindingGeneration: bigint,
|
|
1938
|
-
payload: ServiceApplicationPayload
|
|
1939
|
-
senderFence?: ServiceBoundSessionSendFence
|
|
1975
|
+
payload: ServiceApplicationPayload
|
|
1940
1976
|
): Promise<number> {
|
|
1977
|
+
// Session–Actor binding §3 item 3: the source sends by binding identity to
|
|
1978
|
+
// the registered route. The header's owner lifecycle fields are this node's
|
|
1979
|
+
// current route values, not send conditions; the Session owner alone
|
|
1980
|
+
// decides whether the binding is current.
|
|
1941
1981
|
let binding: ServiceSessionBinding;
|
|
1942
1982
|
try {
|
|
1943
1983
|
binding = this.registry.validateBoundSession(actor, expectedBindingGeneration);
|
|
1944
|
-
} catch {
|
|
1945
|
-
return SubmitResult.
|
|
1984
|
+
} catch (error) {
|
|
1985
|
+
if (error instanceof ServiceStaleGenerationError) return SubmitResult.NotFound;
|
|
1986
|
+
throw error;
|
|
1946
1987
|
}
|
|
1947
|
-
const actorFence = this.
|
|
1988
|
+
const actorFence = this.tryActorFence(actor);
|
|
1948
1989
|
if (actorFence === undefined) return SubmitResult.InvalidState;
|
|
1949
1990
|
const header = encodeBoundSessionSendHeader(actorFence, expectedBindingGeneration);
|
|
1950
1991
|
return this.submitOneWay(binding.sessionOwnerNodeRid, [
|
|
@@ -1953,27 +1994,22 @@ export class ServiceStatefulRuntime {
|
|
|
1953
1994
|
]);
|
|
1954
1995
|
}
|
|
1955
1996
|
|
|
1997
|
+
expireOperations(nowMs: number, turnDeadlineMs: number): number {
|
|
1998
|
+
return this.operations.expire(nowMs, turnDeadlineMs);
|
|
1999
|
+
}
|
|
2000
|
+
|
|
2001
|
+
get pendingOperationCount(): number {
|
|
2002
|
+
return this.operations.size;
|
|
2003
|
+
}
|
|
2004
|
+
|
|
1956
2005
|
close(): void {
|
|
1957
2006
|
if (this.closed) return;
|
|
1958
2007
|
this.closed = true;
|
|
1959
2008
|
this.operations.close();
|
|
1960
|
-
const clearedActors = new Set<string>();
|
|
1961
|
-
for (const deliveries of [this.sessionDeliveries, this.retiredSessionDeliveries]) {
|
|
1962
|
-
for (const delivery of deliveries.values()) {
|
|
1963
|
-
const actorId = delivery.binding.actor.actorId;
|
|
1964
|
-
if (clearedActors.has(actorId)) continue;
|
|
1965
|
-
clearedActors.add(actorId);
|
|
1966
|
-
delivery.bindingIngress?.clearOutbound(
|
|
1967
|
-
actorId,
|
|
1968
|
-
new Error(`Actor '${actorId}' Session service closed with retained outbound delivery.`)
|
|
1969
|
-
);
|
|
1970
|
-
}
|
|
1971
|
-
}
|
|
1972
2009
|
this.sessionDeliveries.clear();
|
|
1973
2010
|
this.retiredSessionDeliveries.clear();
|
|
1974
2011
|
this.appliedReplacementNotices.clear();
|
|
1975
2012
|
this.instanceIntents.clear();
|
|
1976
|
-
this.pendingInstanceTerminals.clear();
|
|
1977
2013
|
this.pendingInstanceAuthorityTerminals.clear();
|
|
1978
2014
|
for (const waiters of this.instanceApplicationWaiters.values()) {
|
|
1979
2015
|
for (const waiter of waiters) waiter();
|
|
@@ -2026,7 +2062,12 @@ export class ServiceStatefulRuntime {
|
|
|
2026
2062
|
}
|
|
2027
2063
|
decoded = statefulActorJoinFromCanonical(canonicalActorJoin);
|
|
2028
2064
|
} else {
|
|
2029
|
-
|
|
2065
|
+
const metadata = (record.flags & M6bServiceWireFlag.metadata) !== 0;
|
|
2066
|
+
decoded = decodeStatefulHeader(
|
|
2067
|
+
record.parts[0]!,
|
|
2068
|
+
record.parts[metadata ? 2 : 1],
|
|
2069
|
+
metadata ? record.parts[1] : undefined
|
|
2070
|
+
);
|
|
2030
2071
|
}
|
|
2031
2072
|
const hasPayload = [
|
|
2032
2073
|
'spotSend',
|
|
@@ -2039,6 +2080,12 @@ export class ServiceStatefulRuntime {
|
|
|
2039
2080
|
].includes(decoded.kind);
|
|
2040
2081
|
const instanceMetadata =
|
|
2041
2082
|
decoded.kind === 'instanceSpot' && (record.flags & M6bServiceWireFlag.metadata) !== 0;
|
|
2083
|
+
const statefulMetadata =
|
|
2084
|
+
(decoded.kind === 'spotSend' ||
|
|
2085
|
+
decoded.kind === 'spotRequest' ||
|
|
2086
|
+
decoded.kind === 'actorSend' ||
|
|
2087
|
+
decoded.kind === 'actorRequest') &&
|
|
2088
|
+
(record.flags & M6bServiceWireFlag.metadata) !== 0;
|
|
2042
2089
|
const userSpotInfrastructure =
|
|
2043
2090
|
decoded.kind === 'userSpotCreate' ||
|
|
2044
2091
|
decoded.kind === 'userSpotClose' ||
|
|
@@ -2047,16 +2094,19 @@ export class ServiceStatefulRuntime {
|
|
|
2047
2094
|
decoded.kind === 'boundSessionReplaced';
|
|
2048
2095
|
if (
|
|
2049
2096
|
record.parts.length < 1 ||
|
|
2050
|
-
record.parts.length > (instanceMetadata ? 3 : 2) ||
|
|
2051
|
-
(hasPayload &&
|
|
2097
|
+
record.parts.length > (instanceMetadata || statefulMetadata ? 3 : 2) ||
|
|
2098
|
+
(hasPayload &&
|
|
2099
|
+
decoded.kind !== 'actorJoin' &&
|
|
2100
|
+
record.parts.length !== ((record.flags & M6bServiceWireFlag.metadata) !== 0 ? 3 : 2)) ||
|
|
2052
2101
|
(decoded.kind === 'instanceSpot' && record.parts.length !== (instanceMetadata ? 3 : 2)) ||
|
|
2053
2102
|
(userSpotInfrastructure && record.parts.length !== 1)
|
|
2054
2103
|
) {
|
|
2055
2104
|
return 'protocolError';
|
|
2056
2105
|
}
|
|
2057
|
-
const metadataFrame =
|
|
2058
|
-
|
|
2059
|
-
|
|
2106
|
+
const metadataFrame =
|
|
2107
|
+
instanceMetadata || statefulMetadata
|
|
2108
|
+
? validateServiceMetadataFrame(record.parts[1]!)
|
|
2109
|
+
: undefined;
|
|
2060
2110
|
const canonicalPayload =
|
|
2061
2111
|
canonicalActorJoin?.payload === undefined
|
|
2062
2112
|
? undefined
|
|
@@ -2095,6 +2145,22 @@ export class ServiceStatefulRuntime {
|
|
|
2095
2145
|
kind === ZLinkFrameworkInternalErrorKind.SpotMoving ||
|
|
2096
2146
|
kind === ZLinkFrameworkInternalErrorKind.SpotGenerationStale
|
|
2097
2147
|
) {
|
|
2148
|
+
const reporter = this.dispatchErrors;
|
|
2149
|
+
if (decoded.kind === 'instanceSpot' && reporter?.captureEnabled() === true) {
|
|
2150
|
+
reporter.report({
|
|
2151
|
+
surface: ZLinkDispatchErrorSurface.InstanceSpot,
|
|
2152
|
+
messageKind: ZLinkDispatchMessageKind.Send,
|
|
2153
|
+
reason: ZLinkDispatchErrorReason.StaleTarget,
|
|
2154
|
+
action: ZLinkDispatchErrorAction.Drop,
|
|
2155
|
+
meshName: this.dispatchErrorMeshName,
|
|
2156
|
+
sourceRid: decoded.sourceNodeRid,
|
|
2157
|
+
spotId:
|
|
2158
|
+
decoded.activation === 'ready'
|
|
2159
|
+
? decoded.route.targetSpotId
|
|
2160
|
+
: decoded.target.targetSpotId,
|
|
2161
|
+
error
|
|
2162
|
+
});
|
|
2163
|
+
}
|
|
2098
2164
|
return 'protocolError';
|
|
2099
2165
|
}
|
|
2100
2166
|
}
|
|
@@ -2349,11 +2415,6 @@ export class ServiceStatefulRuntime {
|
|
|
2349
2415
|
targetSpotId: record.route.targetSpotId,
|
|
2350
2416
|
stableType: intent.instanceType
|
|
2351
2417
|
};
|
|
2352
|
-
// A close seals execution only after the current application count reaches
|
|
2353
|
-
// zero. A new Instance message must wait for that close even while the old
|
|
2354
|
-
// activation is still materialized; otherwise it can be admitted after
|
|
2355
|
-
// the close quiescence check and be removed with the old activation.
|
|
2356
|
-
if (lifecycle.isClosing?.(applicationTarget) === true) return true;
|
|
2357
2418
|
return !lifecycle.isMaterialized(applicationTarget);
|
|
2358
2419
|
}
|
|
2359
2420
|
|
|
@@ -2361,11 +2422,11 @@ export class ServiceStatefulRuntime {
|
|
|
2361
2422
|
ingress: RawServiceIngressRecord,
|
|
2362
2423
|
record: Extract<ServiceStatefulWireRecord, { readonly kind: 'instanceSpot' }>,
|
|
2363
2424
|
payloadFrame: Buffer,
|
|
2364
|
-
spot: ServiceSpotState,
|
|
2425
|
+
spot: Pick<ServiceSpotState, 'ref'>,
|
|
2365
2426
|
localReply?: NonNullable<ServiceStatefulMailboxData['reply']>,
|
|
2366
2427
|
onTerminalCompletion?: NonNullable<ServiceStatefulMailboxData['onTerminalCompletion']>,
|
|
2367
2428
|
metadataFrame?: Buffer,
|
|
2368
|
-
|
|
2429
|
+
onHandlerTurnStarted?: () => void,
|
|
2369
2430
|
applicationTargetOverride?: ServiceInstanceApplicationTarget
|
|
2370
2431
|
): RawServicePumpResult {
|
|
2371
2432
|
let operationKey: string | undefined;
|
|
@@ -2395,10 +2456,6 @@ export class ServiceStatefulRuntime {
|
|
|
2395
2456
|
onTerminalCompletion === undefined
|
|
2396
2457
|
? undefined
|
|
2397
2458
|
: async () => {
|
|
2398
|
-
// The application turn has returned before authority cleanup starts.
|
|
2399
|
-
// Mark it quiescent first so a close requested by that turn can finish
|
|
2400
|
-
// its local cleanup and release the exact authority fence below.
|
|
2401
|
-
this.completeInstanceApplicationOperation(applicationTarget.targetSpotId);
|
|
2402
2459
|
try {
|
|
2403
2460
|
await onTerminalCompletion();
|
|
2404
2461
|
} finally {
|
|
@@ -2413,8 +2470,11 @@ export class ServiceStatefulRuntime {
|
|
|
2413
2470
|
...(record.operationKind === 'request' ? { correlation: record.replyRouteId } : {}),
|
|
2414
2471
|
...(record.sourceSpotId === undefined ? {} : { sourceSpotId: record.sourceSpotId }),
|
|
2415
2472
|
targetSpot: spot.ref,
|
|
2473
|
+
activationRecord: record,
|
|
2474
|
+
...(record.activation === 'missing' ? { deadlineUnixMs: record.deadlineUnixMs } : {}),
|
|
2416
2475
|
...(metadataFrame === undefined ? {} : { applicationMetadata: metadataFrame }),
|
|
2417
2476
|
...(terminalCompletion === undefined ? {} : { onTerminalCompletion: terminalCompletion }),
|
|
2477
|
+
...(onHandlerTurnStarted === undefined ? {} : { onHandlerTurnStarted }),
|
|
2418
2478
|
...(record.operationKind === 'request'
|
|
2419
2479
|
? {
|
|
2420
2480
|
reply:
|
|
@@ -2431,10 +2491,6 @@ export class ServiceStatefulRuntime {
|
|
|
2431
2491
|
this.admittedInstanceOperations.set(operationKey, record.deadlineUnixMs);
|
|
2432
2492
|
}
|
|
2433
2493
|
if (onTerminalCompletion !== undefined && result === 'application') {
|
|
2434
|
-
this.beginInstanceApplicationOperation(applicationTarget.targetSpotId);
|
|
2435
|
-
if (activationTerminal) {
|
|
2436
|
-
this.beginInstanceAuthorityOperation(applicationTarget.targetSpotId);
|
|
2437
|
-
}
|
|
2438
2494
|
this.instanceApplicationLifecycle?.beginTerminal(applicationTarget);
|
|
2439
2495
|
}
|
|
2440
2496
|
return result;
|
|
@@ -2458,15 +2514,16 @@ export class ServiceStatefulRuntime {
|
|
|
2458
2514
|
metadataFrame
|
|
2459
2515
|
);
|
|
2460
2516
|
if (this.closed) return;
|
|
2517
|
+
const terminal = this.activationTerminalCompletion(record.target, activation.route);
|
|
2461
2518
|
const admitted = this.enqueueActivatedInstanceSpot(
|
|
2462
2519
|
ingress,
|
|
2463
2520
|
record,
|
|
2464
2521
|
payloadFrame,
|
|
2465
2522
|
activation.spot,
|
|
2466
2523
|
localReply,
|
|
2467
|
-
|
|
2524
|
+
terminal.onTerminalCompletion,
|
|
2468
2525
|
metadataFrame,
|
|
2469
|
-
|
|
2526
|
+
terminal.onHandlerTurnStarted,
|
|
2470
2527
|
this.instanceApplicationTarget(record, activation.route.objectGeneration)
|
|
2471
2528
|
);
|
|
2472
2529
|
if (admitted !== 'application') {
|
|
@@ -2534,12 +2591,14 @@ export class ServiceStatefulRuntime {
|
|
|
2534
2591
|
const spot = this.requireInstanceActivation(ingress, refreshedRecord);
|
|
2535
2592
|
const admitted = this.enqueueActivatedInstanceSpot(
|
|
2536
2593
|
ingress,
|
|
2537
|
-
|
|
2594
|
+
record,
|
|
2538
2595
|
payloadFrame,
|
|
2539
2596
|
spot,
|
|
2540
2597
|
undefined,
|
|
2541
2598
|
this.instanceApplicationTerminalCompletion(this.instanceApplicationTarget(refreshedRecord)),
|
|
2542
|
-
metadataFrame
|
|
2599
|
+
metadataFrame,
|
|
2600
|
+
undefined,
|
|
2601
|
+
this.instanceApplicationTarget(refreshedRecord)
|
|
2543
2602
|
);
|
|
2544
2603
|
if (admitted !== 'application') {
|
|
2545
2604
|
throw new Error('Rematerialized Instance message was not admitted to the local queue.');
|
|
@@ -2551,23 +2610,39 @@ export class ServiceStatefulRuntime {
|
|
|
2551
2610
|
}
|
|
2552
2611
|
}
|
|
2553
2612
|
|
|
2613
|
+
/**
|
|
2614
|
+
* Spot messaging §4 step 12 with §7 step 1: a Close waits for the first terminal
|
|
2615
|
+
* record only of a message whose handler turn started before it; a message queued
|
|
2616
|
+
* behind that Close is not counted, so it cannot hold the Close it follows.
|
|
2617
|
+
*/
|
|
2554
2618
|
private activationTerminalCompletion(
|
|
2555
2619
|
target: ServiceInstanceActivationTarget,
|
|
2556
2620
|
route: ServiceInstanceRouteFence
|
|
2557
|
-
):
|
|
2621
|
+
): {
|
|
2622
|
+
readonly onTerminalCompletion: () => Promise<void>;
|
|
2623
|
+
readonly onHandlerTurnStarted: () => void;
|
|
2624
|
+
} {
|
|
2558
2625
|
let completion: Promise<void> | undefined;
|
|
2626
|
+
let started = false;
|
|
2559
2627
|
const applicationTarget: ServiceInstanceApplicationTarget = {
|
|
2560
2628
|
targetSpotId: target.targetSpotId,
|
|
2561
2629
|
stableType: target.stableType,
|
|
2562
2630
|
objectGeneration: route.objectGeneration
|
|
2563
2631
|
};
|
|
2564
|
-
|
|
2632
|
+
const onHandlerTurnStarted = (): void => {
|
|
2633
|
+
if (started || completion !== undefined) return;
|
|
2634
|
+
started = true;
|
|
2635
|
+
this.beginInstanceAuthorityOperation(target.targetSpotId);
|
|
2636
|
+
};
|
|
2637
|
+
const onTerminalCompletion = (): Promise<void> =>
|
|
2565
2638
|
(completion ??= (async () => {
|
|
2566
|
-
let authorityCompletionSignaled =
|
|
2639
|
+
let authorityCompletionSignaled = !started;
|
|
2567
2640
|
try {
|
|
2568
2641
|
const released = await this.asyncInstanceAuthority?.complete(target, route);
|
|
2569
|
-
|
|
2570
|
-
|
|
2642
|
+
if (!authorityCompletionSignaled) {
|
|
2643
|
+
this.completeInstanceAuthorityOperation(target.targetSpotId);
|
|
2644
|
+
authorityCompletionSignaled = true;
|
|
2645
|
+
}
|
|
2571
2646
|
if (released !== undefined) {
|
|
2572
2647
|
const authorityReleased =
|
|
2573
2648
|
(await this.instanceApplicationLifecycle?.completeTerminal(applicationTarget)) ??
|
|
@@ -2584,6 +2659,7 @@ export class ServiceStatefulRuntime {
|
|
|
2584
2659
|
}
|
|
2585
2660
|
}
|
|
2586
2661
|
})());
|
|
2662
|
+
return { onTerminalCompletion, onHandlerTurnStarted };
|
|
2587
2663
|
}
|
|
2588
2664
|
|
|
2589
2665
|
private instanceApplicationTerminalCompletion(
|
|
@@ -2628,11 +2704,6 @@ export class ServiceStatefulRuntime {
|
|
|
2628
2704
|
};
|
|
2629
2705
|
}
|
|
2630
2706
|
|
|
2631
|
-
private beginInstanceApplicationOperation(spotId: string): void {
|
|
2632
|
-
const key = String(spotId);
|
|
2633
|
-
this.pendingInstanceTerminals.set(key, (this.pendingInstanceTerminals.get(key) ?? 0) + 1);
|
|
2634
|
-
}
|
|
2635
|
-
|
|
2636
2707
|
private beginInstanceAuthorityOperation(spotId: string): void {
|
|
2637
2708
|
const key = String(spotId);
|
|
2638
2709
|
this.pendingInstanceAuthorityTerminals.set(
|
|
@@ -2641,17 +2712,6 @@ export class ServiceStatefulRuntime {
|
|
|
2641
2712
|
);
|
|
2642
2713
|
}
|
|
2643
2714
|
|
|
2644
|
-
private completeInstanceApplicationOperation(spotId: string): void {
|
|
2645
|
-
const key = String(spotId);
|
|
2646
|
-
const pending = this.pendingInstanceTerminals.get(key);
|
|
2647
|
-
if (pending === undefined || pending <= 1) {
|
|
2648
|
-
this.pendingInstanceTerminals.delete(key);
|
|
2649
|
-
this.completeInstanceApplicationWaitersIfQuiescent(key);
|
|
2650
|
-
return;
|
|
2651
|
-
}
|
|
2652
|
-
this.pendingInstanceTerminals.set(key, pending - 1);
|
|
2653
|
-
}
|
|
2654
|
-
|
|
2655
2715
|
private completeInstanceAuthorityOperation(spotId: string): void {
|
|
2656
2716
|
const key = String(spotId);
|
|
2657
2717
|
const pending = this.pendingInstanceAuthorityTerminals.get(key);
|
|
@@ -2664,11 +2724,7 @@ export class ServiceStatefulRuntime {
|
|
|
2664
2724
|
}
|
|
2665
2725
|
|
|
2666
2726
|
private completeInstanceApplicationWaitersIfQuiescent(key: string): void {
|
|
2667
|
-
if (
|
|
2668
|
-
(this.pendingInstanceTerminals.get(key) ?? 0) !== 0 ||
|
|
2669
|
-
(this.pendingInstanceAuthorityTerminals.get(key) ?? 0) !== 0
|
|
2670
|
-
)
|
|
2671
|
-
return;
|
|
2727
|
+
if ((this.pendingInstanceAuthorityTerminals.get(key) ?? 0) !== 0) return;
|
|
2672
2728
|
const waiters = this.instanceApplicationWaiters.get(key);
|
|
2673
2729
|
if (waiters === undefined) return;
|
|
2674
2730
|
this.instanceApplicationWaiters.delete(key);
|
|
@@ -2817,8 +2873,8 @@ export class ServiceStatefulRuntime {
|
|
|
2817
2873
|
// activation continuation can publish its in-memory intent. If the
|
|
2818
2874
|
// local ready projection already carries the exact object and owner
|
|
2819
2875
|
// fence from the received route, publish that validated projection
|
|
2820
|
-
// instead of
|
|
2821
|
-
//
|
|
2876
|
+
// instead of rejecting a following request while publication finishes.
|
|
2877
|
+
// An absent Ready projection cannot validate the received owner fence.
|
|
2822
2878
|
const local = this.registry.spot(record.route.targetSpotId);
|
|
2823
2879
|
if (
|
|
2824
2880
|
local?.kind === 'instance' &&
|
|
@@ -2831,7 +2887,7 @@ export class ServiceStatefulRuntime {
|
|
|
2831
2887
|
}
|
|
2832
2888
|
if (intent === undefined) {
|
|
2833
2889
|
throw createInternalFrameworkException(
|
|
2834
|
-
ZLinkFrameworkInternalErrorKind.
|
|
2890
|
+
ZLinkFrameworkInternalErrorKind.SpotMoving,
|
|
2835
2891
|
`Instance Spot '${record.route.targetSpotId}' has no current Ready authority.`
|
|
2836
2892
|
);
|
|
2837
2893
|
}
|
|
@@ -2954,7 +3010,10 @@ export class ServiceStatefulRuntime {
|
|
|
2954
3010
|
>,
|
|
2955
3011
|
payloadFrame: Buffer,
|
|
2956
3012
|
metadataFrame?: Buffer
|
|
2957
|
-
): Promise<{
|
|
3013
|
+
): Promise<{
|
|
3014
|
+
readonly spot: Pick<ServiceSpotState, 'ref'>;
|
|
3015
|
+
readonly route: ServiceInstanceRouteFence;
|
|
3016
|
+
}> {
|
|
2958
3017
|
const key = instanceActivationKey(record);
|
|
2959
3018
|
const pending = this.pendingInstanceActivations.get(key);
|
|
2960
3019
|
if (pending !== undefined) return pending;
|
|
@@ -2976,7 +3035,10 @@ export class ServiceStatefulRuntime {
|
|
|
2976
3035
|
>,
|
|
2977
3036
|
payloadFrame: Buffer,
|
|
2978
3037
|
metadataFrame?: Buffer
|
|
2979
|
-
): Promise<{
|
|
3038
|
+
): Promise<{
|
|
3039
|
+
readonly spot: Pick<ServiceSpotState, 'ref'>;
|
|
3040
|
+
readonly route: ServiceInstanceRouteFence;
|
|
3041
|
+
}> {
|
|
2980
3042
|
const target = record.target;
|
|
2981
3043
|
if (
|
|
2982
3044
|
target.targetNodeRid !== this.nodeRid ||
|
|
@@ -2992,6 +3054,46 @@ export class ServiceStatefulRuntime {
|
|
|
2992
3054
|
|
|
2993
3055
|
const local = this.registry.spot(target.targetSpotId);
|
|
2994
3056
|
const current = await authority.read(target);
|
|
3057
|
+
if (
|
|
3058
|
+
current.kind === 'creating' &&
|
|
3059
|
+
current.authority?.allocation.state === 'active' &&
|
|
3060
|
+
this.instanceApplicationLifecycle?.isMaterializing?.(target) === true
|
|
3061
|
+
) {
|
|
3062
|
+
return {
|
|
3063
|
+
spot: { ref: { spotId: target.targetSpotId, generation: current.objectGeneration } },
|
|
3064
|
+
route: {
|
|
3065
|
+
targetSpotId: target.targetSpotId,
|
|
3066
|
+
targetNodeRid: this.nodeRid,
|
|
3067
|
+
targetNodeGeneration: this.nodeGeneration,
|
|
3068
|
+
objectGeneration: current.objectGeneration,
|
|
3069
|
+
authorityOwnerGeneration: current.authorityOwnerGeneration,
|
|
3070
|
+
ownerId: current.authority.ownerId,
|
|
3071
|
+
leaseGeneration: current.authority.ownerLeaseGeneration,
|
|
3072
|
+
storeVersion: current.authority.storeVersion.value
|
|
3073
|
+
}
|
|
3074
|
+
};
|
|
3075
|
+
}
|
|
3076
|
+
if (
|
|
3077
|
+
current.kind === 'ready' &&
|
|
3078
|
+
current.authority !== undefined &&
|
|
3079
|
+
decodeServiceClosingSpotAuthority(current.authority.payload) !== undefined
|
|
3080
|
+
) {
|
|
3081
|
+
if (current.route.targetNodeRid !== this.nodeRid) {
|
|
3082
|
+
throw new ServiceInstanceActivationRedirectError(current.route);
|
|
3083
|
+
}
|
|
3084
|
+
if (
|
|
3085
|
+
current.route.targetNodeGeneration !== this.nodeGeneration ||
|
|
3086
|
+
(local !== undefined &&
|
|
3087
|
+
!routeMatchesLocal(current.route, local, this.nodeRid, this.nodeGeneration)) ||
|
|
3088
|
+
(local === undefined && this.instanceApplicationLifecycle?.isMaterialized(target) !== true)
|
|
3089
|
+
) {
|
|
3090
|
+
throw new ServiceStaleGenerationError('spot', target.targetSpotId);
|
|
3091
|
+
}
|
|
3092
|
+
return {
|
|
3093
|
+
spot: { ref: { spotId: target.targetSpotId, generation: current.route.objectGeneration } },
|
|
3094
|
+
route: current.route
|
|
3095
|
+
};
|
|
3096
|
+
}
|
|
2995
3097
|
if (!this.acceptsLocalMissingInstancePlacement()) {
|
|
2996
3098
|
if (current.kind === 'ready' && current.route.targetNodeRid !== this.nodeRid) {
|
|
2997
3099
|
throw new ServiceInstanceActivationRedirectError(current.route);
|
|
@@ -3023,7 +3125,6 @@ export class ServiceStatefulRuntime {
|
|
|
3023
3125
|
}
|
|
3024
3126
|
if (local !== undefined) {
|
|
3025
3127
|
const lifecycle = this.instanceApplicationLifecycle;
|
|
3026
|
-
const closing = lifecycle?.isClosing?.(target) === true;
|
|
3027
3128
|
let materialized = lifecycle === undefined ? undefined : lifecycle.isMaterialized(target);
|
|
3028
3129
|
const materializing = lifecycle?.isMaterializing?.(target) === true;
|
|
3029
3130
|
if (local.kind !== 'instance' || local.stableType !== target.stableType) {
|
|
@@ -3033,10 +3134,8 @@ export class ServiceStatefulRuntime {
|
|
|
3033
3134
|
current.kind === 'creating' &&
|
|
3034
3135
|
local.ref.generation === current.objectGeneration &&
|
|
3035
3136
|
local.authorityOwnerGeneration === current.authorityOwnerGeneration;
|
|
3036
|
-
const replacesClosingProjection = current.kind === 'creating' && closing;
|
|
3037
3137
|
if (
|
|
3038
3138
|
current.kind === 'missing' &&
|
|
3039
|
-
!closing &&
|
|
3040
3139
|
!materializing &&
|
|
3041
3140
|
materialized === true &&
|
|
3042
3141
|
lifecycle !== undefined
|
|
@@ -3060,24 +3159,33 @@ export class ServiceStatefulRuntime {
|
|
|
3060
3159
|
// If disposal did not remove an orphaned materialization, keep fencing
|
|
3061
3160
|
// it instead of admitting work into two application generations.
|
|
3062
3161
|
if (
|
|
3063
|
-
(!joinsCreating &&
|
|
3064
|
-
(!joinsCreating &&
|
|
3162
|
+
(!joinsCreating && current.kind !== 'missing') ||
|
|
3163
|
+
(!joinsCreating && materialized !== false && !materializing)
|
|
3065
3164
|
) {
|
|
3066
3165
|
throw new ServiceStaleGenerationError('spot', target.targetSpotId);
|
|
3067
3166
|
}
|
|
3068
3167
|
}
|
|
3069
|
-
const
|
|
3070
|
-
|
|
3071
|
-
|
|
3072
|
-
|
|
3073
|
-
|
|
3074
|
-
|
|
3075
|
-
|
|
3076
|
-
|
|
3077
|
-
|
|
3078
|
-
|
|
3079
|
-
|
|
3080
|
-
|
|
3168
|
+
const deadline = operationDeadline(record.deadlineUnixMs);
|
|
3169
|
+
let reserved: ServiceInstanceAuthorityReserve;
|
|
3170
|
+
try {
|
|
3171
|
+
reserved = await authority.reserve(
|
|
3172
|
+
{
|
|
3173
|
+
target,
|
|
3174
|
+
sourceNodeRid: record.sourceNodeRid,
|
|
3175
|
+
sourceNodeGeneration: record.sourceNodeGeneration,
|
|
3176
|
+
...(record.sourceSpotId === undefined ? {} : { sourceSpotId: record.sourceSpotId }),
|
|
3177
|
+
operationKind: record.operationKind,
|
|
3178
|
+
operation: record.operation,
|
|
3179
|
+
...(record.replyRouteId === undefined ? {} : { replyRouteId: record.replyRouteId }),
|
|
3180
|
+
deadlineUnixMs: record.deadlineUnixMs,
|
|
3181
|
+
...(metadataFrame === undefined ? {} : { metadataFrame }),
|
|
3182
|
+
applicationPayloadFrame: payloadFrame
|
|
3183
|
+
},
|
|
3184
|
+
deadline.signal
|
|
3185
|
+
);
|
|
3186
|
+
} finally {
|
|
3187
|
+
deadline.close();
|
|
3188
|
+
}
|
|
3081
3189
|
if (reserved.kind === 'ready') {
|
|
3082
3190
|
throw new ServiceInstanceActivationRedirectError(reserved.route);
|
|
3083
3191
|
}
|
|
@@ -3102,7 +3210,12 @@ export class ServiceStatefulRuntime {
|
|
|
3102
3210
|
}
|
|
3103
3211
|
let committed: Awaited<ReturnType<ServiceAsyncInstanceActivationAuthority['commit']>>;
|
|
3104
3212
|
try {
|
|
3105
|
-
committed = await authority.commit(
|
|
3213
|
+
committed = await authority.commit(
|
|
3214
|
+
target,
|
|
3215
|
+
reserved.reservation,
|
|
3216
|
+
activation.spot,
|
|
3217
|
+
record.deadlineUnixMs
|
|
3218
|
+
);
|
|
3106
3219
|
} catch (error) {
|
|
3107
3220
|
if (activation.created) this.registry.closeSpot(activation.spot.ref);
|
|
3108
3221
|
await this.instanceApplicationLifecycle?.discard(target);
|
|
@@ -3594,7 +3707,15 @@ export class ServiceStatefulRuntime {
|
|
|
3594
3707
|
const accepted = this.raw.mailbox.tryEnqueue({
|
|
3595
3708
|
owner: `actor:${actor.actorId}\0${actor.generation}`,
|
|
3596
3709
|
domain: 'infrastructure',
|
|
3597
|
-
parts: [
|
|
3710
|
+
parts: [
|
|
3711
|
+
Buffer.from([
|
|
3712
|
+
SERVICE_WIRE_MAGIC[0],
|
|
3713
|
+
SERVICE_WIRE_MAGIC[1],
|
|
3714
|
+
SERVICE_WIRE_MAJOR,
|
|
3715
|
+
M6bServiceWireCommand.boundSessionBind,
|
|
3716
|
+
0
|
|
3717
|
+
])
|
|
3718
|
+
],
|
|
3598
3719
|
sourceRoutingId: binding.sessionOwnerNodeRid,
|
|
3599
3720
|
stateful: {
|
|
3600
3721
|
receiveKind: ReceiveKind.ActorBinding,
|
|
@@ -3627,62 +3748,25 @@ export class ServiceStatefulRuntime {
|
|
|
3627
3748
|
record: Extract<ServiceStatefulWireRecord, { readonly kind: 'boundSessionSend' }>,
|
|
3628
3749
|
payloadFrame: Uint8Array | undefined
|
|
3629
3750
|
): Promise<RawServicePumpResult> {
|
|
3751
|
+
// Session–Actor binding §3 item 3, §8.1: this Session owner's binding
|
|
3752
|
+
// record alone decides whether command 36 names the current binding
|
|
3753
|
+
// (ActorId, ObjectGeneration, binding generation; SessionRid is the
|
|
3754
|
+
// record's own). The transport boundary has already authenticated the
|
|
3755
|
+
// source peer, and the header's route fields are not compared here.
|
|
3756
|
+
if (payloadFrame === undefined) return 'protocolError';
|
|
3630
3757
|
const delivery = this.sessionDeliveries.get(actorKey(record.actor.actor));
|
|
3631
3758
|
if (
|
|
3632
3759
|
delivery === undefined ||
|
|
3633
|
-
delivery.binding.bindingGeneration !== record.expectedBindingGeneration
|
|
3634
|
-
payloadFrame === undefined ||
|
|
3635
|
-
ingress.sourceNodeGeneration === undefined ||
|
|
3636
|
-
!routingIdsEqual(ingress.sourceRoutingId, record.actor.actor.nodeRid) ||
|
|
3637
|
-
ingress.sourceNodeGeneration !== record.actor.targetNodeGeneration
|
|
3760
|
+
delivery.binding.bindingGeneration !== record.expectedBindingGeneration
|
|
3638
3761
|
) {
|
|
3762
|
+
this.traceRejectedBoundSessionSend(ingress, record, payloadFrame);
|
|
3639
3763
|
return 'protocolError';
|
|
3640
3764
|
}
|
|
3641
3765
|
const sessionRid = delivery.binding.sessionRid;
|
|
3642
|
-
let retainedPayload: Uint8Array | undefined = payloadFrame;
|
|
3643
|
-
let settled = false;
|
|
3644
|
-
const settle = () => {
|
|
3645
|
-
if (settled) return false;
|
|
3646
|
-
settled = true;
|
|
3647
|
-
retainedPayload = undefined;
|
|
3648
|
-
return true;
|
|
3649
|
-
};
|
|
3650
|
-
const operation = {
|
|
3651
|
-
deliver: async () => {
|
|
3652
|
-
if (settled || retainedPayload === undefined) return false;
|
|
3653
|
-
const delivered = await delivery.deliver(sessionRid, retainedPayload);
|
|
3654
|
-
if (delivered) settle();
|
|
3655
|
-
return delivered;
|
|
3656
|
-
},
|
|
3657
|
-
fail: (_error: unknown) => {
|
|
3658
|
-
settle();
|
|
3659
|
-
}
|
|
3660
|
-
};
|
|
3661
|
-
const decision = await delivery.bindingIngress?.retainOutbound(
|
|
3662
|
-
{
|
|
3663
|
-
actorId: record.actor.actor.actorId,
|
|
3664
|
-
objectGeneration: record.actor.actor.generation,
|
|
3665
|
-
actorNodeRid: record.actor.actor.nodeRid,
|
|
3666
|
-
actorNodeGeneration: record.actor.targetNodeGeneration,
|
|
3667
|
-
authorityOwnerGeneration: record.actor.authorityOwnerGeneration,
|
|
3668
|
-
ownerLeaseGeneration: record.actor.ownerLeaseGeneration,
|
|
3669
|
-
producerNodeRid: ingress.sourceRoutingId,
|
|
3670
|
-
producerNodeGeneration: ingress.sourceNodeGeneration,
|
|
3671
|
-
sessionIdentity: sessionRid,
|
|
3672
|
-
bindingGeneration: record.expectedBindingGeneration
|
|
3673
|
-
},
|
|
3674
|
-
operation
|
|
3675
|
-
);
|
|
3676
|
-
if (decision === 'retained') return 'application';
|
|
3677
|
-
if (decision === 'rejected') {
|
|
3678
|
-
return 'protocolError';
|
|
3679
|
-
}
|
|
3680
3766
|
try {
|
|
3681
|
-
const delivered = await delivery.deliver(sessionRid,
|
|
3682
|
-
settle();
|
|
3767
|
+
const delivered = await delivery.deliver(sessionRid, payloadFrame);
|
|
3683
3768
|
if (!delivered) return 'protocolError';
|
|
3684
3769
|
} catch (error) {
|
|
3685
|
-
operation.fail(error);
|
|
3686
3770
|
// Remote command 36 is one-way: its source transport admission has
|
|
3687
3771
|
// already completed, so a later client delivery terminal is local to
|
|
3688
3772
|
// this session owner. Local fast paths still preserve the typed result.
|
|
@@ -3698,6 +3782,37 @@ export class ServiceStatefulRuntime {
|
|
|
3698
3782
|
return 'application';
|
|
3699
3783
|
}
|
|
3700
3784
|
|
|
3785
|
+
// Session–Actor binding §3 item 4: a push refused as not current is
|
|
3786
|
+
// recorded with the closed flow vocabulary (dropped, stream_session, send,
|
|
3787
|
+
// stale_target) instead of disappearing. Nothing is built while tracing is
|
|
3788
|
+
// off.
|
|
3789
|
+
private traceRejectedBoundSessionSend(
|
|
3790
|
+
ingress: RawServiceIngressRecord,
|
|
3791
|
+
record: Extract<ServiceStatefulWireRecord, { readonly kind: 'boundSessionSend' }>,
|
|
3792
|
+
payloadFrame: Uint8Array
|
|
3793
|
+
): void {
|
|
3794
|
+
const tracePoint = flowIfEnabled(this.dispatchErrors?.flow, ZLinkMessageFlowOutcome.Dropped);
|
|
3795
|
+
if (tracePoint === undefined) return;
|
|
3796
|
+
let packetName: string | undefined;
|
|
3797
|
+
try {
|
|
3798
|
+
packetName = decodeApplicationPayloadView(payloadFrame).packetName;
|
|
3799
|
+
} catch (error) {
|
|
3800
|
+
// A malformed payload is still a refused push; it is traced without a
|
|
3801
|
+
// packet name.
|
|
3802
|
+
if (!(error instanceof ServiceWireProtocolError)) throw error;
|
|
3803
|
+
}
|
|
3804
|
+
tracePoint.trace({
|
|
3805
|
+
outcome: ZLinkMessageFlowOutcome.Dropped,
|
|
3806
|
+
surface: ZLinkDispatchErrorSurface.StreamSession,
|
|
3807
|
+
messageKind: ZLinkDispatchMessageKind.Send,
|
|
3808
|
+
...(packetName === undefined ? {} : { packetName }),
|
|
3809
|
+
...(this.dispatchErrorMeshName === undefined ? {} : { meshName: this.dispatchErrorMeshName }),
|
|
3810
|
+
sourceRid: ingress.sourceRoutingId,
|
|
3811
|
+
actorId: record.actor.actor.actorId,
|
|
3812
|
+
errorReason: ZLinkDispatchErrorReason.StaleTarget
|
|
3813
|
+
});
|
|
3814
|
+
}
|
|
3815
|
+
|
|
3701
3816
|
private enqueueApplicationFrame(
|
|
3702
3817
|
ingress: RawServiceIngressRecord,
|
|
3703
3818
|
owner: string,
|
|
@@ -3826,7 +3941,13 @@ export class ServiceStatefulRuntime {
|
|
|
3826
3941
|
control: ActorControlPayload,
|
|
3827
3942
|
onTerminalCompletion?: () => void | Promise<void>
|
|
3828
3943
|
): void {
|
|
3829
|
-
const header = Buffer.from([
|
|
3944
|
+
const header = Buffer.from([
|
|
3945
|
+
SERVICE_WIRE_MAGIC[0],
|
|
3946
|
+
SERVICE_WIRE_MAGIC[1],
|
|
3947
|
+
SERVICE_WIRE_MAJOR,
|
|
3948
|
+
M6bServiceWireCommand.actorJoined,
|
|
3949
|
+
0
|
|
3950
|
+
]);
|
|
3830
3951
|
let terminalAttempted = false;
|
|
3831
3952
|
void (async () => {
|
|
3832
3953
|
const applicationJobOwner = await this.raw.reserveLocalIngress();
|
|
@@ -3872,7 +3993,13 @@ export class ServiceStatefulRuntime {
|
|
|
3872
3993
|
): boolean {
|
|
3873
3994
|
const actor = binding.actor;
|
|
3874
3995
|
const sessionOwner = requireSessionOwnerIdentity(binding);
|
|
3875
|
-
const header = Buffer.from([
|
|
3996
|
+
const header = Buffer.from([
|
|
3997
|
+
SERVICE_WIRE_MAGIC[0],
|
|
3998
|
+
SERVICE_WIRE_MAGIC[1],
|
|
3999
|
+
SERVICE_WIRE_MAJOR,
|
|
4000
|
+
M6bServiceWireCommand.boundSessionBind,
|
|
4001
|
+
0
|
|
4002
|
+
]);
|
|
3876
4003
|
const applicationJob = requireApplicationJobOwner(ingress).takeInitial('infrastructure');
|
|
3877
4004
|
const accepted = this.raw.mailbox.tryEnqueue({
|
|
3878
4005
|
owner: `actor:${actor.actorId}\0${actor.generation}`,
|
|
@@ -4046,7 +4173,7 @@ export class ServiceStatefulRuntime {
|
|
|
4046
4173
|
handler: ServiceUserSpotOperationHandler,
|
|
4047
4174
|
record: ServiceUserSpotCreateRecord | ServiceUserSpotCloseRecord | ServiceActorCreateRecord
|
|
4048
4175
|
): Promise<ServiceUserSpotOperationResult> {
|
|
4049
|
-
const deadline =
|
|
4176
|
+
const deadline = operationDeadline(record.deadlineUnixMs);
|
|
4050
4177
|
try {
|
|
4051
4178
|
const result =
|
|
4052
4179
|
record.kind === 'userSpotCreate'
|
|
@@ -4150,7 +4277,10 @@ export class ServiceStatefulRuntime {
|
|
|
4150
4277
|
stop.signal.throwIfAborted();
|
|
4151
4278
|
if (!durableRequestCanReplay(error)) throw error;
|
|
4152
4279
|
if (durableRequestWasAdmitted(error)) wasAdmitted = true;
|
|
4153
|
-
const retryDelayMs = Math.min(
|
|
4280
|
+
const retryDelayMs = Math.min(
|
|
4281
|
+
STATEFUL_OPERATION_RETRY_TICK_MS,
|
|
4282
|
+
deadlineMs - performance.now()
|
|
4283
|
+
);
|
|
4154
4284
|
if (retryDelayMs <= 0) {
|
|
4155
4285
|
throw durableOperationExhausted(operationKind, wasAdmitted, error);
|
|
4156
4286
|
}
|
|
@@ -4201,8 +4331,8 @@ export class ServiceStatefulRuntime {
|
|
|
4201
4331
|
const applicationJobOwner = await this.raw.reserveLocalIngress();
|
|
4202
4332
|
try {
|
|
4203
4333
|
const result = await this.ingress({
|
|
4204
|
-
command: header[
|
|
4205
|
-
flags: header[
|
|
4334
|
+
command: header[SERVICE_WIRE_COMMAND_OFFSET]!,
|
|
4335
|
+
flags: header[SERVICE_WIRE_FLAGS_OFFSET]!,
|
|
4206
4336
|
sourceRoutingId: this.nodeRid,
|
|
4207
4337
|
requestSequence,
|
|
4208
4338
|
reply: finish,
|
|
@@ -4239,8 +4369,8 @@ export class ServiceStatefulRuntime {
|
|
|
4239
4369
|
void ServiceStatefulRuntime.detachedIngressScope(async () => {
|
|
4240
4370
|
try {
|
|
4241
4371
|
await this.ingress({
|
|
4242
|
-
command: parts[0]![
|
|
4243
|
-
flags: parts[0]![
|
|
4372
|
+
command: parts[0]![SERVICE_WIRE_COMMAND_OFFSET]!,
|
|
4373
|
+
flags: parts[0]![SERVICE_WIRE_FLAGS_OFFSET]!,
|
|
4244
4374
|
sourceRoutingId: this.nodeRid,
|
|
4245
4375
|
sourceNodeGeneration: this.nodeGeneration,
|
|
4246
4376
|
parts,
|
|
@@ -4258,8 +4388,8 @@ export class ServiceStatefulRuntime {
|
|
|
4258
4388
|
}
|
|
4259
4389
|
try {
|
|
4260
4390
|
const result = await this.ingress({
|
|
4261
|
-
command: parts[0]![
|
|
4262
|
-
flags: parts[0]![
|
|
4391
|
+
command: parts[0]![SERVICE_WIRE_COMMAND_OFFSET]!,
|
|
4392
|
+
flags: parts[0]![SERVICE_WIRE_FLAGS_OFFSET]!,
|
|
4263
4393
|
sourceRoutingId: this.nodeRid,
|
|
4264
4394
|
sourceNodeGeneration: this.nodeGeneration,
|
|
4265
4395
|
parts,
|
|
@@ -4300,18 +4430,30 @@ export class ServiceStatefulRuntime {
|
|
|
4300
4430
|
): void {
|
|
4301
4431
|
if (targetNodeRid === this.nodeRid) {
|
|
4302
4432
|
const deadlineUnixMs = BigInt(Date.now() + Math.max(0, timeoutMs));
|
|
4433
|
+
const capacityStop = new AbortController();
|
|
4434
|
+
void pending.promise.then(
|
|
4435
|
+
() => capacityStop.abort(),
|
|
4436
|
+
() => capacityStop.abort()
|
|
4437
|
+
);
|
|
4303
4438
|
void (async () => {
|
|
4304
|
-
const applicationJobOwner = await this.raw.reserveLocalIngress();
|
|
4305
|
-
const localIngress: RawServiceIngressRecord = {
|
|
4306
|
-
command: parts[0]![3]!,
|
|
4307
|
-
flags: parts[0]![4]!,
|
|
4308
|
-
sourceRoutingId: this.nodeRid,
|
|
4309
|
-
requestSequence: pending.id,
|
|
4310
|
-
parts,
|
|
4311
|
-
applicationJobOwner
|
|
4312
|
-
};
|
|
4439
|
+
const applicationJobOwner = await this.raw.reserveLocalIngress(capacityStop.signal);
|
|
4313
4440
|
try {
|
|
4314
|
-
this.
|
|
4441
|
+
if (!this.operations.isPending(pending.id)) return;
|
|
4442
|
+
const localIngress: RawServiceIngressRecord = {
|
|
4443
|
+
command: parts[0]![SERVICE_WIRE_COMMAND_OFFSET]!,
|
|
4444
|
+
flags: parts[0]![SERVICE_WIRE_FLAGS_OFFSET]!,
|
|
4445
|
+
sourceRoutingId: this.nodeRid,
|
|
4446
|
+
requestSequence: pending.id,
|
|
4447
|
+
parts,
|
|
4448
|
+
applicationJobOwner
|
|
4449
|
+
};
|
|
4450
|
+
await this.submitLocalRequest(
|
|
4451
|
+
localIngress,
|
|
4452
|
+
pending,
|
|
4453
|
+
operationKind,
|
|
4454
|
+
actor,
|
|
4455
|
+
deadlineUnixMs
|
|
4456
|
+
);
|
|
4315
4457
|
} catch (error) {
|
|
4316
4458
|
this.operations.reply(pending.id, failure(error));
|
|
4317
4459
|
} finally {
|
|
@@ -4340,10 +4482,10 @@ export class ServiceStatefulRuntime {
|
|
|
4340
4482
|
? this.tryActorFence(actor)
|
|
4341
4483
|
: this.acceptCanonicalActorFence(actor, canonical.actorFence);
|
|
4342
4484
|
if (target === undefined || actorRoute === undefined) {
|
|
4343
|
-
this.operations.reply(
|
|
4344
|
-
|
|
4345
|
-
|
|
4346
|
-
|
|
4485
|
+
this.operations.reply(
|
|
4486
|
+
pending.id,
|
|
4487
|
+
internalFrameworkWireReply(ZLinkFrameworkInternalErrorKind.ActorLocationStale)
|
|
4488
|
+
);
|
|
4347
4489
|
return;
|
|
4348
4490
|
}
|
|
4349
4491
|
if (canonical !== undefined) {
|
|
@@ -4412,7 +4554,7 @@ export class ServiceStatefulRuntime {
|
|
|
4412
4554
|
);
|
|
4413
4555
|
}
|
|
4414
4556
|
|
|
4415
|
-
private submitLocalRequest(
|
|
4557
|
+
private async submitLocalRequest(
|
|
4416
4558
|
ingress: RawServiceIngressRecord,
|
|
4417
4559
|
pending: ServiceStatefulPendingOperation,
|
|
4418
4560
|
operationKind:
|
|
@@ -4426,7 +4568,7 @@ export class ServiceStatefulRuntime {
|
|
|
4426
4568
|
| 'instanceSpotRequest',
|
|
4427
4569
|
actor?: ServiceActorRef,
|
|
4428
4570
|
deadlineUnixMs?: bigint
|
|
4429
|
-
): void {
|
|
4571
|
+
): Promise<void> {
|
|
4430
4572
|
const canonicalActorJoin =
|
|
4431
4573
|
operationKind === 'actorJoin' ? decodeActorJoin28(ingress.parts) : undefined;
|
|
4432
4574
|
const decoded =
|
|
@@ -4502,7 +4644,9 @@ export class ServiceStatefulRuntime {
|
|
|
4502
4644
|
operationKind: OperationKind.ActorRequest,
|
|
4503
4645
|
correlation: decoded.correlation,
|
|
4504
4646
|
targetActor: current.ref,
|
|
4505
|
-
...(decoded.sourceActor === undefined
|
|
4647
|
+
...(decoded.sourceActor === undefined
|
|
4648
|
+
? {}
|
|
4649
|
+
: { sourceActor: { ...decoded.sourceActor, nodeRid: ingress.sourceRoutingId } }),
|
|
4506
4650
|
...(decoded.boundSession === undefined
|
|
4507
4651
|
? {}
|
|
4508
4652
|
: { sourceBindingGeneration: decoded.boundSession.bindingGeneration }),
|
|
@@ -4801,7 +4945,16 @@ export class ServiceStatefulRuntime {
|
|
|
4801
4945
|
return spot;
|
|
4802
4946
|
}
|
|
4803
4947
|
|
|
4804
|
-
private validateDirectSpotFence(fence:
|
|
4948
|
+
private validateDirectSpotFence(fence: ServiceSpotRouteFence): ServiceSpotState {
|
|
4949
|
+
if (
|
|
4950
|
+
fence.targetNodeRid !== this.nodeRid ||
|
|
4951
|
+
fence.targetNodeGeneration !== this.nodeGeneration
|
|
4952
|
+
) {
|
|
4953
|
+
throw createInternalFrameworkException(
|
|
4954
|
+
ZLinkFrameworkInternalErrorKind.SpotMoving,
|
|
4955
|
+
`Spot '${fence.spot.spotId}' targets an unavailable owner route.`
|
|
4956
|
+
);
|
|
4957
|
+
}
|
|
4805
4958
|
const spot = this.registry.spot(fence.spot.spotId);
|
|
4806
4959
|
if (spot === undefined) {
|
|
4807
4960
|
throw createInternalFrameworkException(
|
|
@@ -4815,15 +4968,6 @@ export class ServiceStatefulRuntime {
|
|
|
4815
4968
|
`Spot '${fence.spot.spotId}' is not Ready.`
|
|
4816
4969
|
);
|
|
4817
4970
|
}
|
|
4818
|
-
if (
|
|
4819
|
-
fence.targetNodeRid !== this.nodeRid ||
|
|
4820
|
-
fence.targetNodeGeneration !== this.nodeGeneration
|
|
4821
|
-
) {
|
|
4822
|
-
throw createInternalFrameworkException(
|
|
4823
|
-
ZLinkFrameworkInternalErrorKind.SpotMoving,
|
|
4824
|
-
`Spot '${fence.spot.spotId}' targets an unavailable owner route.`
|
|
4825
|
-
);
|
|
4826
|
-
}
|
|
4827
4971
|
if (spot.kind === 'entry') {
|
|
4828
4972
|
if (!isEntrySpotFence(fence)) {
|
|
4829
4973
|
throw createInternalFrameworkException(
|
|
@@ -4860,7 +5004,7 @@ export class ServiceStatefulRuntime {
|
|
|
4860
5004
|
wire: Extract<ServiceStatefulWireRecord, { readonly kind: 'spotSend' | 'spotRequest' }>
|
|
4861
5005
|
): RawServicePumpResult | undefined {
|
|
4862
5006
|
const state = this.spotMessageFollow.get(spotKey(wire.target.spot));
|
|
4863
|
-
if (state === undefined || !
|
|
5007
|
+
if (state === undefined || !sameDirectSpotRouteIdentity(state.source, wire.target)) {
|
|
4864
5008
|
return undefined;
|
|
4865
5009
|
}
|
|
4866
5010
|
if (state.expiresAtMs !== undefined && state.expiresAtMs <= performance.now()) {
|
|
@@ -4912,14 +5056,22 @@ export class ServiceStatefulRuntime {
|
|
|
4912
5056
|
}
|
|
4913
5057
|
const current = this.peekSpotMessageFollow(state)!;
|
|
4914
5058
|
try {
|
|
5059
|
+
const metadata =
|
|
5060
|
+
(current.ingress.parts[0]![SERVICE_WIRE_FLAGS_OFFSET]! &
|
|
5061
|
+
M6bServiceWireFlag.metadata) !==
|
|
5062
|
+
0;
|
|
4915
5063
|
const parts = [
|
|
4916
5064
|
encodeSpotHeader(
|
|
4917
5065
|
current.wire.kind,
|
|
4918
5066
|
current.wire.sourceSpotId,
|
|
4919
5067
|
state.target,
|
|
4920
|
-
current.wire.correlation
|
|
5068
|
+
current.wire.correlation,
|
|
5069
|
+
current.wire.operation,
|
|
5070
|
+
current.wire.messageFollowHopCount + 1,
|
|
5071
|
+
metadata ? current.ingress.parts[1] : undefined
|
|
4921
5072
|
),
|
|
4922
|
-
current.ingress.parts[1]!
|
|
5073
|
+
...(metadata ? [current.ingress.parts[1]!] : []),
|
|
5074
|
+
current.ingress.parts[metadata ? 2 : 1]!
|
|
4923
5075
|
];
|
|
4924
5076
|
if (current.wire.kind === 'spotSend') {
|
|
4925
5077
|
if (!(await this.raw.sendService(state.target.targetNodeRid, parts))) continue;
|
|
@@ -5046,7 +5198,7 @@ export class ServiceStatefulRuntime {
|
|
|
5046
5198
|
if (state.queuedCount === 0) {
|
|
5047
5199
|
state.queued.length = 0;
|
|
5048
5200
|
state.queuedHead = 0;
|
|
5049
|
-
} else if (state.queuedHead
|
|
5201
|
+
} else if (shouldCompactBackingArray(state.queuedHead, state.queued.length)) {
|
|
5050
5202
|
state.queued.splice(0, state.queuedHead);
|
|
5051
5203
|
state.queuedHead = 0;
|
|
5052
5204
|
}
|
|
@@ -5058,34 +5210,6 @@ export class ServiceStatefulRuntime {
|
|
|
5058
5210
|
return route;
|
|
5059
5211
|
}
|
|
5060
5212
|
|
|
5061
|
-
private tryBoundSessionSendFence(
|
|
5062
|
-
actor: ServiceActorRef,
|
|
5063
|
-
senderFence: ServiceBoundSessionSendFence | undefined
|
|
5064
|
-
): ServiceActorRouteFence | undefined {
|
|
5065
|
-
if (
|
|
5066
|
-
senderFence === undefined ||
|
|
5067
|
-
senderFence.targetNodeGeneration !== this.nodeGeneration ||
|
|
5068
|
-
senderFence.authorityOwnerGeneration <= 0n ||
|
|
5069
|
-
senderFence.ownerLeaseGeneration <= 0n
|
|
5070
|
-
) {
|
|
5071
|
-
return undefined;
|
|
5072
|
-
}
|
|
5073
|
-
const local = actor.nodeRid === this.nodeRid ? this.registry.actor(actor.actorId) : undefined;
|
|
5074
|
-
if (
|
|
5075
|
-
local === undefined ||
|
|
5076
|
-
!sameActorRef(local.ref, actor) ||
|
|
5077
|
-
local.authorityOwnerGeneration !== senderFence.authorityOwnerGeneration
|
|
5078
|
-
) {
|
|
5079
|
-
return undefined;
|
|
5080
|
-
}
|
|
5081
|
-
return {
|
|
5082
|
-
actor,
|
|
5083
|
-
targetNodeGeneration: senderFence.targetNodeGeneration,
|
|
5084
|
-
authorityOwnerGeneration: senderFence.authorityOwnerGeneration,
|
|
5085
|
-
ownerLeaseGeneration: senderFence.ownerLeaseGeneration
|
|
5086
|
-
};
|
|
5087
|
-
}
|
|
5088
|
-
|
|
5089
5213
|
private tryActorFence(actor: ServiceActorRef): ServiceActorRouteFence | undefined {
|
|
5090
5214
|
const local = actor.nodeRid === this.nodeRid ? this.registry.actor(actor.actorId) : undefined;
|
|
5091
5215
|
if (local !== undefined && sameActorRef(local.ref, actor)) {
|
|
@@ -5295,48 +5419,32 @@ export class ServiceStatefulRuntime {
|
|
|
5295
5419
|
}
|
|
5296
5420
|
}
|
|
5297
5421
|
|
|
5298
|
-
function
|
|
5299
|
-
result: number | undefined,
|
|
5300
|
-
routeReady: boolean,
|
|
5301
|
-
closed: boolean
|
|
5302
|
-
): 'stale_target' | 'backpressure' | 'shutdown' {
|
|
5303
|
-
if (closed || result === SubmitResult.Terminated) return 'shutdown';
|
|
5304
|
-
switch (result) {
|
|
5305
|
-
case SubmitResult.Backpressured:
|
|
5306
|
-
return 'backpressure';
|
|
5307
|
-
case SubmitResult.NotAdmitted:
|
|
5308
|
-
case SubmitResult.NotConnected:
|
|
5309
|
-
case SubmitResult.NotFound:
|
|
5310
|
-
case SubmitResult.InvalidHandle:
|
|
5311
|
-
return 'stale_target';
|
|
5312
|
-
default:
|
|
5313
|
-
// RawServiceMeshRuntime exposes failed Core submissions as false. A
|
|
5314
|
-
// ready route therefore identifies queue admission failure; a route
|
|
5315
|
-
// that became unready after selection is a stale target.
|
|
5316
|
-
return routeReady ? 'backpressure' : 'stale_target';
|
|
5317
|
-
}
|
|
5318
|
-
}
|
|
5319
|
-
|
|
5320
|
-
function isEntrySpotFence(fence: ServiceDirectSpotRouteFence): boolean {
|
|
5422
|
+
function isEntrySpotFence(fence: ServiceSpotRouteFence): boolean {
|
|
5321
5423
|
return (
|
|
5322
5424
|
fence.spot.spotId === fence.targetNodeRid &&
|
|
5323
5425
|
fence.spot.generation === fence.targetNodeGeneration &&
|
|
5324
5426
|
fence.authorityOwnerGeneration === fence.targetNodeGeneration &&
|
|
5325
|
-
fence.ownerLeaseGeneration === fence.targetNodeGeneration
|
|
5326
|
-
fence.storeVersion === `entry:${fence.targetNodeGeneration}`
|
|
5427
|
+
fence.ownerLeaseGeneration === fence.targetNodeGeneration
|
|
5327
5428
|
);
|
|
5328
5429
|
}
|
|
5329
5430
|
|
|
5330
|
-
function
|
|
5431
|
+
function operationDeadline(deadlineUnixMs: bigint): {
|
|
5331
5432
|
readonly signal: AbortSignal;
|
|
5332
5433
|
close(): void;
|
|
5333
5434
|
} {
|
|
5334
5435
|
const controller = new AbortController();
|
|
5335
5436
|
const delay = Number(deadlineUnixMs - BigInt(Date.now()));
|
|
5336
|
-
const
|
|
5337
|
-
|
|
5338
|
-
|
|
5339
|
-
|
|
5437
|
+
const expire = () =>
|
|
5438
|
+
controller.abort(
|
|
5439
|
+
createInternalFrameworkException(
|
|
5440
|
+
ZLinkFrameworkInternalErrorKind.DeadlineExceeded,
|
|
5441
|
+
'Operation deadline exceeded.'
|
|
5442
|
+
)
|
|
5443
|
+
);
|
|
5444
|
+
const timeout =
|
|
5445
|
+
delay <= 0
|
|
5446
|
+
? (expire(), undefined)
|
|
5447
|
+
: setTimeout(expire, Math.min(delay, MAX_NODE_TIMER_DELAY_MS));
|
|
5340
5448
|
return {
|
|
5341
5449
|
signal: controller.signal,
|
|
5342
5450
|
close: () => clearTimeout(timeout)
|
|
@@ -5417,12 +5525,12 @@ function actorLocation(actor: ServiceActorState): ActorLocation {
|
|
|
5417
5525
|
|
|
5418
5526
|
function failure(error: unknown): ServiceStatefulResult {
|
|
5419
5527
|
if (error instanceof ServiceStaleGenerationError) {
|
|
5420
|
-
return
|
|
5528
|
+
return internalFrameworkWireReply(ZLinkFrameworkInternalErrorKind.ActorLocationStale);
|
|
5421
5529
|
}
|
|
5422
5530
|
if (error instanceof ZLinkFrameworkException) {
|
|
5423
5531
|
return internalFrameworkWireReply(error);
|
|
5424
5532
|
}
|
|
5425
|
-
return
|
|
5533
|
+
return internalFrameworkWireReply(ZLinkFrameworkInternalErrorKind.RequestFailed);
|
|
5426
5534
|
}
|
|
5427
5535
|
|
|
5428
5536
|
function actorKey(actor: ServiceActorRef): string {
|
|
@@ -5744,15 +5852,15 @@ function sameMessageFollowSpotSource(
|
|
|
5744
5852
|
}
|
|
5745
5853
|
|
|
5746
5854
|
function sameDirectSpotRouteIdentity(
|
|
5747
|
-
left:
|
|
5748
|
-
right:
|
|
5855
|
+
left: ServiceSpotRouteFence,
|
|
5856
|
+
right: ServiceSpotRouteFence
|
|
5749
5857
|
): boolean {
|
|
5750
5858
|
return sameDirectSpotOwnerIdentity(left, right) && left.spot.generation === right.spot.generation;
|
|
5751
5859
|
}
|
|
5752
5860
|
|
|
5753
5861
|
function sameDirectSpotOwnerIdentity(
|
|
5754
|
-
left:
|
|
5755
|
-
right:
|
|
5862
|
+
left: ServiceSpotRouteFence,
|
|
5863
|
+
right: ServiceSpotRouteFence
|
|
5756
5864
|
): boolean {
|
|
5757
5865
|
return (
|
|
5758
5866
|
left.spot.spotId === right.spot.spotId &&
|
|
@@ -5815,7 +5923,7 @@ function topicMatches(filter: string, topic: string): boolean {
|
|
|
5815
5923
|
function emptyPayload(): ServiceApplicationPayload {
|
|
5816
5924
|
return {
|
|
5817
5925
|
packetName: 'ZLinkFrameworkEmpty',
|
|
5818
|
-
contentType:
|
|
5926
|
+
contentType: ZlinkStreamContentType.Raw,
|
|
5819
5927
|
payload: Buffer.alloc(0)
|
|
5820
5928
|
};
|
|
5821
5929
|
}
|