@zlink-systems/framework 0.30.0 → 0.30.2
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/LICENSE +150 -68
- package/dist/.tsbuildinfo +1 -1
- package/dist/contracts/Actors/ZLinkActorClient.d.ts +2 -1
- package/dist/contracts/Channels/Calls.d.ts +2 -1
- package/dist/contracts/Common/ZLinkEncodedPayload.d.ts +6 -0
- package/dist/contracts/Common/ZLinkEncodedPayload.js +18 -3
- package/dist/contracts/Common/ZLinkMessageMetadata.js +11 -5
- package/dist/contracts/Common/encoded-payload-storage.d.ts +1 -1
- package/dist/contracts/Common/encoded-payload-storage.js +5 -2
- package/dist/contracts/Configuration/Builders.d.ts +1 -1
- package/dist/contracts/Configuration/RegistrationBuilderPolicy.d.ts +2 -1
- package/dist/contracts/Configuration/RegistrationBuilderPolicy.js +5 -1
- package/dist/contracts/Configuration/RegistrationBuilders.js +2 -2
- package/dist/contracts/Configuration/RegistrationTypes.d.ts +1 -0
- package/dist/contracts/Dispatch/ZLinkDispatchOptions.d.ts +2 -2
- package/dist/contracts/Handlers/Attributes.d.ts +5 -13
- package/dist/contracts/Handlers/Attributes.js +7 -11
- package/dist/contracts/Handlers/JsonContract.d.ts +2 -46
- package/dist/contracts/Handlers/JsonContract.js +4 -153
- package/dist/contracts/Locations/Rows.d.ts +2 -0
- package/dist/contracts/Spots/Contracts.d.ts +6 -1
- package/dist/contracts/Spots/ZLinkSpot.d.ts +3 -3
- package/dist/nest-integration.d.ts +1 -1
- package/dist/nest-integration.js +2 -1
- package/dist/runtime/abort.d.ts +5 -0
- package/dist/runtime/abort.js +10 -0
- package/dist/runtime/actors/actor-authority-publication.js +3 -2
- package/dist/runtime/actors/actor-client.d.ts +1 -2
- package/dist/runtime/actors/actor-client.js +52 -57
- package/dist/runtime/actors/actor-context.d.ts +2 -0
- package/dist/runtime/actors/actor-context.js +46 -9
- package/dist/runtime/actors/actor-handoff.d.ts +8 -4
- package/dist/runtime/actors/actor-handoff.js +219 -92
- package/dist/runtime/actors/actor-join-relocation.d.ts +3 -0
- package/dist/runtime/actors/actor-local-native-join.js +13 -12
- package/dist/runtime/actors/actor-mailbox.js +27 -1
- package/dist/runtime/actors/actor-remote-joiner.js +3 -1
- package/dist/runtime/actors/actor-remote-wire.js +15 -0
- package/dist/runtime/actors/actor-reply.d.ts +4 -0
- package/dist/runtime/actors/actor-reply.js +29 -0
- package/dist/runtime/actors/actor-routed-join-transport.d.ts +6 -2
- package/dist/runtime/actors/actor-routed-json-request.d.ts +2 -0
- package/dist/runtime/actors/actor-runtime-contracts.d.ts +2 -0
- package/dist/runtime/actors/actor-runtime-state.js +2 -20
- package/dist/runtime/actors/actor-source-transfer.d.ts +1 -17
- package/dist/runtime/actors/index.d.ts +8 -3
- package/dist/runtime/actors/index.js +55 -27
- package/dist/runtime/actors/session-disconnected-wire.d.ts +8 -0
- package/dist/runtime/actors/session-disconnected-wire.js +48 -0
- package/dist/runtime/actors/spot-actor-dispatch.js +2 -2
- package/dist/runtime/admission.d.ts +9 -1
- package/dist/runtime/admission.js +56 -23
- package/dist/runtime/application-jobs/application-ingress-record-owner.d.ts +6 -8
- package/dist/runtime/application-jobs/application-ingress-record-owner.js +39 -22
- package/dist/runtime/application-jobs/application-job-queue-scope.d.ts +15 -1
- package/dist/runtime/application-jobs/application-job-queue-scope.js +61 -20
- package/dist/runtime/application-jobs/contracts.d.ts +12 -1
- package/dist/runtime/backend/contracts/index.d.ts +37 -12
- package/dist/runtime/backend/mesh-actor-session-node-adapter.js +2 -2
- package/dist/runtime/backend/mesh-completion-table.d.ts +9 -1
- package/dist/runtime/backend/mesh-completion-table.js +154 -49
- package/dist/runtime/backend/mesh-dispatch-pump.d.ts +28 -1
- package/dist/runtime/backend/mesh-dispatch-pump.js +208 -101
- package/dist/runtime/backend/node/node-backend-adapter-support.d.ts +2 -2
- package/dist/runtime/backend/node/node-backend-adapter-support.js +16 -9
- package/dist/runtime/backend/node/node-dealer-channel-client-transport.d.ts +1 -1
- package/dist/runtime/backend/node/node-dealer-channel-client-transport.js +5 -2
- package/dist/runtime/backend/node/node-raw-binding-port.js +124 -72
- package/dist/runtime/backend/node/node-raw-mesh-backend.d.ts +46 -13
- package/dist/runtime/backend/node/node-raw-mesh-backend.js +181 -164
- package/dist/runtime/backend/node/node-socket-backend-adapter.d.ts +1 -1
- package/dist/runtime/backend/node/node-socket-backend-adapter.js +11 -11
- package/dist/runtime/backend/raw-binding-port.d.ts +2 -2
- package/dist/runtime/backend/runtime-message.d.ts +1 -0
- package/dist/runtime/backend/runtime-message.js +5 -0
- package/dist/runtime/backend/runtime-values.d.ts +1 -0
- package/dist/runtime/backend/runtime-values.js +2 -1
- package/dist/runtime/channels/channel-clients.d.ts +2 -0
- package/dist/runtime/channels/channel-clients.js +75 -23
- package/dist/runtime/channels/channel-dispatch-pipeline.d.ts +25 -5
- package/dist/runtime/channels/channel-dispatch-pipeline.js +111 -56
- package/dist/runtime/channels/channel-dispatch-services.d.ts +1 -0
- package/dist/runtime/channels/channel-dispatch-services.js +45 -0
- package/dist/runtime/channels/channel-dispatchers.d.ts +4 -3
- package/dist/runtime/channels/channel-dispatchers.js +62 -54
- package/dist/runtime/channels/channel-envelope-inspection.d.ts +1 -2
- package/dist/runtime/channels/channel-envelope-inspection.js +1 -16
- package/dist/runtime/channels/channel-envelope.d.ts +2 -0
- package/dist/runtime/channels/channel-envelope.js +146 -28
- package/dist/runtime/channels/channel-outbound-operations.d.ts +2 -2
- package/dist/runtime/channels/channel-outbound-operations.js +8 -8
- package/dist/runtime/channels/channel-runtime-lifecycle.d.ts +4 -3
- package/dist/runtime/channels/channel-runtime-lifecycle.js +19 -24
- package/dist/runtime/channels/channel-runtime-manager.d.ts +9 -8
- package/dist/runtime/channels/channel-runtime-manager.js +16 -16
- package/dist/runtime/channels/channel-transports.d.ts +18 -16
- package/dist/runtime/channels/channel-transports.js +77 -58
- package/dist/runtime/channels/client-server-location-runtime.js +5 -4
- package/dist/runtime/channels/dispatch-error-reporter.d.ts +2 -1
- package/dist/runtime/channels/dispatch-error-reporter.js +2 -1
- package/dist/runtime/channels/fanout-location-runtime.d.ts +1 -1
- package/dist/runtime/channels/fanout-location-runtime.js +3 -3
- package/dist/runtime/channels/local-spot-route-transport.d.ts +1 -1
- package/dist/runtime/channels/local-spot-route-transport.js +2 -1
- package/dist/runtime/channels/router-socket-spot-route-transport.d.ts +2 -2
- package/dist/runtime/channels/router-socket-spot-route-transport.js +4 -4
- package/dist/runtime/channels/source-spot-router.d.ts +2 -2
- package/dist/runtime/channels/source-spot-router.js +4 -4
- package/dist/runtime/channels/spot-node-route-transport.d.ts +2 -2
- package/dist/runtime/channels/spot-node-route-transport.js +4 -4
- package/dist/runtime/channels/spot-route-bridge-transport.d.ts +2 -2
- package/dist/runtime/channels/spot-route-bridge-transport.js +4 -4
- package/dist/runtime/channels/spot-route-dispatch-strategy.d.ts +5 -4
- package/dist/runtime/channels/spot-route-dispatch-strategy.js +18 -18
- package/dist/runtime/diagnostics/flow-context.js +19 -7
- package/dist/runtime/diagnostics/index.js +4 -9
- package/dist/runtime/diagnostics/message-flow.d.ts +8 -0
- package/dist/runtime/diagnostics/message-flow.js +35 -5
- package/dist/runtime/diagnostics/runtime-metrics.d.ts +2 -2
- package/dist/runtime/diagnostics/runtime-metrics.js +10 -8
- package/dist/runtime/execution/index.d.ts +4 -2
- package/dist/runtime/execution/index.js +33 -10
- package/dist/runtime/execution/serial-execution-queue.d.ts +5 -0
- package/dist/runtime/execution/serial-execution-queue.js +22 -2
- package/dist/runtime/execution/state-lane.d.ts +2 -0
- package/dist/runtime/execution/state-lane.js +5 -0
- package/dist/runtime/foundation/actor-join-recovery-codec.js +2 -2
- package/dist/runtime/foundation/durable-service-request.d.ts +14 -0
- package/dist/runtime/foundation/durable-service-request.js +98 -0
- package/dist/runtime/foundation/operation-identity.d.ts +1 -0
- package/dist/runtime/foundation/operation-identity.js +5 -1
- package/dist/runtime/foundation/operation-registry.d.ts +25 -1
- package/dist/runtime/foundation/operation-registry.js +86 -18
- package/dist/runtime/foundation/raw-service-mesh-runtime.d.ts +61 -8
- package/dist/runtime/foundation/raw-service-mesh-runtime.js +486 -266
- package/dist/runtime/foundation/service-liveness-registry.d.ts +12 -1
- package/dist/runtime/foundation/service-liveness-registry.js +38 -0
- package/dist/runtime/foundation/service-mailbox.d.ts +7 -0
- package/dist/runtime/foundation/service-maintenance-runtime.js +1 -6
- package/dist/runtime/foundation/service-relocation-object-owner.d.ts +3 -3
- package/dist/runtime/foundation/service-relocation-object-owner.js +48 -34
- package/dist/runtime/foundation/service-relocation-runtime.d.ts +2 -0
- package/dist/runtime/foundation/service-relocation-runtime.js +20 -4
- package/dist/runtime/foundation/service-runtime-contracts.d.ts +10 -1
- package/dist/runtime/foundation/service-session-binding-ingress-port.d.ts +2 -1
- package/dist/runtime/foundation/service-stateful-registry.d.ts +5 -4
- package/dist/runtime/foundation/service-stateful-registry.js +24 -26
- package/dist/runtime/foundation/service-stateful-runtime.d.ts +75 -9
- package/dist/runtime/foundation/service-stateful-runtime.js +486 -218
- package/dist/runtime/foundation/service-stateful-wire-codec.d.ts +14 -6
- package/dist/runtime/foundation/service-stateful-wire-codec.js +48 -27
- package/dist/runtime/foundation/service-topology-registry.d.ts +12 -2
- package/dist/runtime/foundation/service-topology-registry.js +61 -27
- package/dist/runtime/foundation/service-wire-binary-primitives.d.ts +6 -1
- package/dist/runtime/foundation/service-wire-binary-primitives.js +27 -11
- package/dist/runtime/foundation/service-wire-constants.generated.d.ts +1 -0
- package/dist/runtime/foundation/service-wire-constants.generated.js +1 -0
- package/dist/runtime/foundation/service-wire-m6a-codec.d.ts +13 -3
- package/dist/runtime/foundation/service-wire-m6a-codec.js +189 -78
- package/dist/runtime/handlers/handler-instance-scope.d.ts +8 -0
- package/dist/runtime/handlers/handler-instance-scope.js +54 -11
- package/dist/runtime/host/actor-packet-relay.d.ts +6 -4
- package/dist/runtime/host/actor-packet-relay.js +59 -72
- package/dist/runtime/host/actor-placement-coordinator.js +25 -8
- package/dist/runtime/host/actor-runtime-options-factory.js +2 -2
- package/dist/runtime/host/actor-transfer-runtime.d.ts +7 -31
- package/dist/runtime/host/actor-transfer-runtime.js +85 -331
- package/dist/runtime/host/application-job-queue.d.ts +40 -7
- package/dist/runtime/host/application-job-queue.js +137 -42
- package/dist/runtime/host/entry-actor-runtime.d.ts +1 -0
- package/dist/runtime/host/entry-actor-runtime.js +3 -0
- package/dist/runtime/host/index.d.ts +12 -2
- package/dist/runtime/host/index.js +300 -202
- package/dist/runtime/host/location-runtime-owner.js +2 -6
- package/dist/runtime/host/mesh-router-resolver.d.ts +4 -0
- package/dist/runtime/host/mesh-router-resolver.js +14 -6
- package/dist/runtime/host/remote-bound-session-relay.d.ts +2 -4
- package/dist/runtime/host/remote-bound-session-relay.js +73 -208
- package/dist/runtime/host/route-mesh-runtime.d.ts +2 -2
- package/dist/runtime/host/route-mesh-runtime.js +6 -4
- package/dist/runtime/host/runtime-shutdown.d.ts +1 -0
- package/dist/runtime/host/runtime-shutdown.js +3 -2
- package/dist/runtime/host/service-relocation-control.d.ts +1 -0
- package/dist/runtime/host/service-relocation-control.js +10 -4
- package/dist/runtime/host/service-relocation-host-runtime.d.ts +22 -14
- package/dist/runtime/host/service-relocation-host-runtime.js +754 -599
- package/dist/runtime/host/spot-address-transport.js +3 -2
- package/dist/runtime/host/spot-runtime-options-factory.js +16 -7
- package/dist/runtime/host/user-spot-creation-coordinator.js +33 -84
- package/dist/runtime/locations/actor-location-claims.d.ts +2 -2
- package/dist/runtime/locations/actor-location-claims.js +34 -19
- package/dist/runtime/locations/auto-connect-loop.d.ts +2 -0
- package/dist/runtime/locations/auto-connect-loop.js +22 -14
- package/dist/runtime/locations/auto-connect-reconciler.js +0 -6
- package/dist/runtime/locations/auto-connect-types.d.ts +0 -1
- package/dist/runtime/locations/descriptor-publication.d.ts +4 -0
- package/dist/runtime/locations/descriptor-publication.js +11 -0
- package/dist/runtime/locations/domain-store-contract.d.ts +1 -0
- package/dist/runtime/locations/in-memory-authority-store.d.ts +7 -1
- package/dist/runtime/locations/in-memory-authority-store.js +56 -19
- package/dist/runtime/locations/in-memory-location-store.js +1 -10
- package/dist/runtime/locations/index.d.ts +1 -0
- package/dist/runtime/locations/index.js +1 -0
- package/dist/runtime/locations/lease-tracker.js +1 -6
- package/dist/runtime/locations/lifecycle.d.ts +1 -2
- package/dist/runtime/locations/lifecycle.js +2 -5
- package/dist/runtime/locations/location-store-repository.d.ts +51 -1
- package/dist/runtime/locations/location-store-repository.js +363 -139
- package/dist/runtime/locations/relocation-blob.d.ts +18 -1
- package/dist/runtime/locations/relocation-blob.js +52 -1
- package/dist/runtime/locations/request-source-resolver.d.ts +37 -0
- package/dist/runtime/locations/request-source-resolver.js +80 -0
- package/dist/runtime/locations/resolvers.js +1 -1
- package/dist/runtime/locations/runtime.d.ts +7 -3
- package/dist/runtime/locations/runtime.js +61 -53
- package/dist/runtime/messaging/framework-json-v1.d.ts +4 -6
- package/dist/runtime/messaging/framework-json-v1.js +38 -294
- package/dist/runtime/messaging/packet-name.d.ts +1 -1
- package/dist/runtime/messaging/packet-name.js +8 -24
- package/dist/runtime/messaging/payload-codec.d.ts +7 -1
- package/dist/runtime/messaging/payload-codec.js +7 -6
- package/dist/runtime/messaging/request-result.d.ts +2 -0
- package/dist/runtime/messaging/request-result.js +57 -0
- package/dist/runtime/messaging/submission-result.d.ts +1 -0
- package/dist/runtime/messaging/submission-result.js +5 -2
- package/dist/runtime/protocol/service_wire_codec.generated.d.ts +34 -1
- package/dist/runtime/protocol/service_wire_codec.generated.js +229 -0
- package/dist/runtime/protocol/service_wire_pilot_codec.generated.d.ts +16 -1
- package/dist/runtime/protocol/service_wire_pilot_codec.generated.js +37 -8
- package/dist/runtime/spots/formal-remote-actor-admission-registry.d.ts +7 -2
- package/dist/runtime/spots/formal-remote-actor-admission-registry.js +36 -21
- package/dist/runtime/spots/index.d.ts +21 -11
- package/dist/runtime/spots/index.js +243 -178
- package/dist/runtime/spots/spot-activation-registry.d.ts +4 -2
- package/dist/runtime/spots/spot-activation-registry.js +21 -11
- package/dist/runtime/spots/spot-activation-state.d.ts +1 -1
- package/dist/runtime/spots/spot-activation-state.js +7 -7
- package/dist/runtime/spots/spot-activation.d.ts +7 -3
- package/dist/runtime/spots/spot-activation.js +140 -52
- package/dist/runtime/spots/spot-actor-admission-coordinator.d.ts +1 -0
- package/dist/runtime/spots/spot-actor-admission-coordinator.js +13 -22
- package/dist/runtime/spots/spot-actor-membership.d.ts +0 -1
- package/dist/runtime/spots/spot-actor-membership.js +0 -8
- package/dist/runtime/spots/spot-actor-packet-dispatch.js +33 -8
- package/dist/runtime/spots/spot-actor-packet-drain.js +5 -33
- package/dist/runtime/spots/spot-entry-activation.d.ts +2 -0
- package/dist/runtime/spots/spot-entry-activation.js +20 -11
- package/dist/runtime/spots/spot-handler-registry.d.ts +7 -4
- package/dist/runtime/spots/spot-handler-registry.js +24 -10
- package/dist/runtime/spots/spot-manager-internal-contracts.d.ts +2 -2
- package/dist/runtime/spots/spot-manager-public.js +2 -2
- package/dist/runtime/spots/spot-node-autoconnect.d.ts +2 -1
- package/dist/runtime/spots/spot-node-autoconnect.js +22 -42
- package/dist/runtime/spots/spot-node-runtime-manager.d.ts +19 -2
- package/dist/runtime/spots/spot-node-runtime-manager.js +115 -50
- package/dist/runtime/spots/spot-outbound.d.ts +3 -0
- package/dist/runtime/spots/spot-outbound.js +27 -18
- package/dist/runtime/spots/spot-remote-codec.js +5 -1
- package/dist/runtime/spots/spot-routed-spot-packet-dispatch.d.ts +1 -0
- package/dist/runtime/spots/spot-routed-spot-packet-dispatch.js +1 -1
- package/dist/runtime/spots/spot-runtime-ports.d.ts +1 -1
- package/dist/runtime/spots/spot-serial-executor.d.ts +10 -0
- package/dist/runtime/spots/spot-serial-executor.js +61 -8
- package/dist/runtime/spots/spot-serial-turn-executor.js +19 -2
- package/dist/runtime/spots/spot-subscription-dispatch.js +1 -4
- package/dist/runtime/spots/spot-timer.d.ts +57 -5
- package/dist/runtime/spots/spot-timer.js +288 -103
- package/dist/runtime/streams/actor-session-binding-registry.d.ts +42 -11
- package/dist/runtime/streams/actor-session-binding-registry.js +165 -48
- package/dist/runtime/streams/actor-session-binding-runtime-owner.d.ts +8 -4
- package/dist/runtime/streams/bound-actor-relay-sender.d.ts +2 -1
- package/dist/runtime/streams/bound-actor-relay-sender.js +15 -8
- package/dist/runtime/streams/bound-session-service.d.ts +1 -1
- package/dist/runtime/streams/bound-session-service.js +6 -11
- package/dist/runtime/streams/index.d.ts +3 -2
- package/dist/runtime/streams/index.js +6 -4
- package/dist/runtime/streams/managed-stream.js +3 -2
- package/dist/runtime/streams/native-fallback-bound-session.js +8 -73
- package/dist/runtime/streams/session-actor-coordinator.d.ts +2 -8
- package/dist/runtime/streams/session-actor-coordinator.js +15 -32
- package/dist/runtime/streams/stream-binding-runtime-ports.d.ts +3 -10
- package/dist/runtime/streams/stream-session-runtime.d.ts +1 -1
- package/dist/runtime/streams/stream-session-runtime.js +14 -31
- package/dist/runtime/workers/index.js +1 -1
- package/package.json +3 -3
- package/src/contracts/Actors/ZLinkActorClient.ts +2 -1
- package/src/contracts/Channels/Calls.ts +2 -1
- package/src/contracts/Common/ZLinkEncodedPayload.ts +24 -4
- package/src/contracts/Common/ZLinkMessageMetadata.ts +13 -8
- package/src/contracts/Common/encoded-payload-storage.ts +6 -3
- package/src/contracts/Configuration/Builders.ts +4 -1
- package/src/contracts/Configuration/RegistrationBuilderPolicy.ts +7 -2
- package/src/contracts/Configuration/RegistrationBuilders.ts +6 -2
- package/src/contracts/Configuration/RegistrationTypes.ts +1 -0
- package/src/contracts/Dispatch/ZLinkDispatchOptions.ts +2 -1
- package/src/contracts/Handlers/Attributes.ts +14 -21
- package/src/contracts/Handlers/JsonContract.ts +8 -216
- package/src/contracts/Locations/Rows.ts +2 -0
- package/src/contracts/Spots/Contracts.ts +10 -1
- package/src/contracts/Spots/ZLinkSpot.ts +3 -3
- package/src/nest-integration.ts +1 -0
- package/src/runtime/abort.ts +12 -0
- package/src/runtime/actors/actor-authority-publication.ts +3 -2
- package/src/runtime/actors/actor-client.ts +100 -85
- package/src/runtime/actors/actor-context.ts +49 -9
- package/src/runtime/actors/actor-handoff.ts +291 -110
- package/src/runtime/actors/actor-join-relocation.ts +3 -0
- package/src/runtime/actors/actor-local-native-join.ts +21 -26
- package/src/runtime/actors/actor-mailbox.ts +40 -2
- package/src/runtime/actors/actor-remote-joiner.ts +6 -1
- package/src/runtime/actors/actor-remote-wire.ts +17 -0
- package/src/runtime/actors/actor-reply.ts +42 -0
- package/src/runtime/actors/actor-routed-join-transport.ts +14 -4
- package/src/runtime/actors/actor-routed-json-request.ts +10 -2
- package/src/runtime/actors/actor-runtime-contracts.ts +2 -0
- package/src/runtime/actors/actor-runtime-state.ts +2 -20
- package/src/runtime/actors/actor-source-transfer.ts +1 -34
- package/src/runtime/actors/index.ts +60 -32
- package/src/runtime/actors/session-disconnected-wire.ts +66 -0
- package/src/runtime/actors/spot-actor-dispatch.ts +4 -2
- package/src/runtime/admission.ts +69 -21
- package/src/runtime/application-jobs/application-ingress-record-owner.ts +41 -25
- package/src/runtime/application-jobs/application-job-queue-scope.ts +83 -22
- package/src/runtime/application-jobs/contracts.ts +16 -1
- package/src/runtime/backend/contracts/index.ts +92 -18
- package/src/runtime/backend/mesh-actor-session-node-adapter.ts +5 -3
- package/src/runtime/backend/mesh-completion-table.ts +160 -57
- package/src/runtime/backend/mesh-dispatch-pump.ts +237 -108
- package/src/runtime/backend/node/node-backend-adapter-support.ts +17 -8
- package/src/runtime/backend/node/node-dealer-channel-client-transport.ts +12 -2
- package/src/runtime/backend/node/node-raw-binding-port.ts +148 -85
- package/src/runtime/backend/node/node-raw-mesh-backend.ts +315 -201
- package/src/runtime/backend/node/node-socket-backend-adapter.ts +26 -11
- package/src/runtime/backend/raw-binding-port.ts +7 -2
- package/src/runtime/backend/runtime-message.ts +6 -0
- package/src/runtime/backend/runtime-values.ts +1 -0
- package/src/runtime/channels/channel-clients.ts +132 -58
- package/src/runtime/channels/channel-dispatch-pipeline.ts +198 -114
- package/src/runtime/channels/channel-dispatch-services.ts +69 -1
- package/src/runtime/channels/channel-dispatchers.ts +136 -90
- package/src/runtime/channels/channel-envelope-inspection.ts +2 -16
- package/src/runtime/channels/channel-envelope.ts +225 -31
- package/src/runtime/channels/channel-outbound-operations.ts +22 -8
- package/src/runtime/channels/channel-runtime-lifecycle.ts +13 -13
- package/src/runtime/channels/channel-runtime-manager.ts +41 -17
- package/src/runtime/channels/channel-transports.ts +171 -112
- package/src/runtime/channels/client-server-location-runtime.ts +11 -10
- package/src/runtime/channels/dispatch-error-reporter.ts +4 -2
- package/src/runtime/channels/fanout-location-runtime.ts +17 -9
- package/src/runtime/channels/local-spot-route-transport.ts +3 -1
- package/src/runtime/channels/router-socket-spot-route-transport.ts +13 -4
- package/src/runtime/channels/source-spot-router.ts +8 -4
- package/src/runtime/channels/spot-node-route-transport.ts +8 -4
- package/src/runtime/channels/spot-route-bridge-transport.ts +6 -4
- package/src/runtime/channels/spot-route-dispatch-strategy.ts +47 -18
- package/src/runtime/diagnostics/flow-context.ts +20 -7
- package/src/runtime/diagnostics/index.ts +1 -7
- package/src/runtime/diagnostics/message-flow.ts +47 -9
- package/src/runtime/diagnostics/runtime-metrics.ts +12 -10
- package/src/runtime/execution/index.ts +40 -14
- package/src/runtime/execution/serial-execution-queue.ts +33 -4
- package/src/runtime/execution/state-lane.ts +7 -0
- package/src/runtime/foundation/actor-join-recovery-codec.ts +2 -2
- package/src/runtime/foundation/durable-service-request.ts +137 -0
- package/src/runtime/foundation/operation-identity.ts +5 -1
- package/src/runtime/foundation/operation-registry.ts +98 -20
- package/src/runtime/foundation/raw-service-mesh-runtime.ts +704 -336
- package/src/runtime/foundation/service-liveness-registry.ts +39 -0
- package/src/runtime/foundation/service-mailbox.ts +8 -0
- package/src/runtime/foundation/service-maintenance-runtime.ts +1 -8
- package/src/runtime/foundation/service-relocation-object-owner.ts +55 -36
- package/src/runtime/foundation/service-relocation-runtime.ts +25 -4
- package/src/runtime/foundation/service-runtime-contracts.ts +19 -2
- package/src/runtime/foundation/service-session-binding-ingress-port.ts +2 -1
- package/src/runtime/foundation/service-stateful-registry.ts +38 -35
- package/src/runtime/foundation/service-stateful-runtime.ts +732 -275
- package/src/runtime/foundation/service-stateful-wire-codec.ts +49 -16
- package/src/runtime/foundation/service-topology-registry.ts +91 -36
- package/src/runtime/foundation/service-wire-binary-primitives.ts +35 -12
- package/src/runtime/foundation/service-wire-constants.generated.ts +1 -0
- package/src/runtime/foundation/service-wire-m6a-codec.ts +231 -76
- package/src/runtime/handlers/handler-instance-scope.ts +67 -16
- package/src/runtime/host/actor-packet-relay.ts +113 -94
- package/src/runtime/host/actor-placement-coordinator.ts +31 -8
- package/src/runtime/host/actor-runtime-options-factory.ts +13 -2
- package/src/runtime/host/actor-transfer-runtime.ts +104 -430
- package/src/runtime/host/application-job-queue.ts +160 -41
- package/src/runtime/host/entry-actor-runtime.ts +4 -0
- package/src/runtime/host/index.ts +473 -271
- package/src/runtime/host/location-runtime-owner.ts +2 -6
- package/src/runtime/host/mesh-router-resolver.ts +13 -5
- package/src/runtime/host/remote-bound-session-relay.ts +88 -271
- package/src/runtime/host/route-mesh-runtime.ts +12 -6
- package/src/runtime/host/runtime-shutdown.ts +15 -4
- package/src/runtime/host/service-relocation-control.ts +11 -5
- package/src/runtime/host/service-relocation-host-runtime.ts +1092 -759
- package/src/runtime/host/spot-address-transport.ts +4 -2
- package/src/runtime/host/spot-runtime-options-factory.ts +20 -7
- package/src/runtime/host/user-spot-creation-coordinator.ts +41 -100
- package/src/runtime/locations/actor-location-claims.ts +52 -30
- package/src/runtime/locations/auto-connect-loop.ts +22 -14
- package/src/runtime/locations/auto-connect-reconciler.ts +0 -6
- package/src/runtime/locations/auto-connect-types.ts +0 -1
- package/src/runtime/locations/descriptor-publication.ts +7 -0
- package/src/runtime/locations/domain-store-contract.ts +5 -0
- package/src/runtime/locations/in-memory-authority-store.ts +85 -23
- package/src/runtime/locations/in-memory-location-store.ts +1 -12
- package/src/runtime/locations/index.ts +1 -0
- package/src/runtime/locations/lease-tracker.ts +2 -9
- package/src/runtime/locations/lifecycle.ts +8 -26
- package/src/runtime/locations/location-store-repository.ts +628 -152
- package/src/runtime/locations/relocation-blob.ts +75 -1
- package/src/runtime/locations/request-source-resolver.ts +138 -0
- package/src/runtime/locations/resolvers.ts +2 -2
- package/src/runtime/locations/runtime.ts +98 -64
- package/src/runtime/messaging/framework-json-v1.ts +5 -325
- package/src/runtime/messaging/packet-name.ts +5 -25
- package/src/runtime/messaging/payload-codec.ts +8 -11
- package/src/runtime/messaging/request-result.ts +62 -0
- package/src/runtime/messaging/submission-result.ts +5 -1
- package/src/runtime/protocol/service_wire_codec.generated.ts +218 -5
- package/src/runtime/protocol/service_wire_pilot_codec.generated.ts +16 -13
- package/src/runtime/spots/formal-remote-actor-admission-registry.ts +46 -25
- package/src/runtime/spots/index.ts +389 -283
- package/src/runtime/spots/spot-activation-registry.ts +25 -13
- package/src/runtime/spots/spot-activation-state.ts +12 -19
- package/src/runtime/spots/spot-activation.ts +198 -96
- package/src/runtime/spots/spot-actor-admission-coordinator.ts +25 -55
- package/src/runtime/spots/spot-actor-membership.ts +0 -15
- package/src/runtime/spots/spot-actor-packet-dispatch.ts +56 -11
- package/src/runtime/spots/spot-actor-packet-drain.ts +9 -52
- package/src/runtime/spots/spot-entry-activation.ts +33 -21
- package/src/runtime/spots/spot-handler-registry.ts +56 -12
- package/src/runtime/spots/spot-manager-internal-contracts.ts +2 -2
- package/src/runtime/spots/spot-manager-public.ts +2 -2
- package/src/runtime/spots/spot-node-autoconnect.ts +28 -47
- package/src/runtime/spots/spot-node-runtime-manager.ts +197 -67
- package/src/runtime/spots/spot-outbound.ts +39 -19
- package/src/runtime/spots/spot-remote-codec.ts +9 -2
- package/src/runtime/spots/spot-routed-spot-packet-dispatch.ts +2 -1
- package/src/runtime/spots/spot-runtime-ports.ts +1 -1
- package/src/runtime/spots/spot-serial-executor.ts +97 -25
- package/src/runtime/spots/spot-serial-turn-executor.ts +22 -3
- package/src/runtime/spots/spot-subscription-dispatch.ts +1 -4
- package/src/runtime/spots/spot-timer.ts +418 -158
- package/src/runtime/streams/actor-session-binding-registry.ts +236 -64
- package/src/runtime/streams/actor-session-binding-runtime-owner.ts +16 -8
- package/src/runtime/streams/bound-actor-relay-sender.ts +23 -9
- package/src/runtime/streams/bound-session-service.ts +7 -10
- package/src/runtime/streams/index.ts +12 -6
- package/src/runtime/streams/managed-stream.ts +4 -2
- package/src/runtime/streams/native-fallback-bound-session.ts +14 -103
- package/src/runtime/streams/session-actor-coordinator.ts +39 -88
- package/src/runtime/streams/stream-binding-runtime-ports.ts +3 -9
- package/src/runtime/streams/stream-session-runtime.ts +13 -34
- package/src/runtime/workers/index.ts +1 -1
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import type { ZLinkRuntimeMetrics } from '../diagnostics/runtime-metrics';
|
|
2
|
+
import { routingIdsEqual, toBackendRoutingId } from '../routing-id';
|
|
1
3
|
import {
|
|
2
4
|
ServiceRelocationAuthorityPayloadCodec,
|
|
3
5
|
serviceRelocationAuthorityApplicationPayload
|
|
@@ -22,6 +24,7 @@ import {
|
|
|
22
24
|
type ZLinkStoreKey,
|
|
23
25
|
type ZLinkStoreReadResult,
|
|
24
26
|
type ZLinkStoreScanCursor,
|
|
27
|
+
type ZLinkStoreValue,
|
|
25
28
|
type ZLinkStoreVersion,
|
|
26
29
|
type ZLinkStoreWriteRequest,
|
|
27
30
|
ZLinkFrameworkException,
|
|
@@ -43,6 +46,7 @@ import {
|
|
|
43
46
|
import { ZLinkLocationWriteStatus as WriteStatus } from '../../contracts/Locations';
|
|
44
47
|
import {
|
|
45
48
|
ZLINK_PROVIDER_MAX_PAGE_SIZE,
|
|
49
|
+
ZLINK_PROVIDER_MAX_WRITE_KEYS,
|
|
46
50
|
ZLINK_PROVIDER_MAX_VALUE_BYTES
|
|
47
51
|
} from '../../contracts/Locations/Stores';
|
|
48
52
|
import { SHA256_DIGEST_BYTES } from '../foundation/actor-join-recovery-codec';
|
|
@@ -130,6 +134,15 @@ interface AuthorityRecord {
|
|
|
130
134
|
readonly visibleStoreVersion?: string;
|
|
131
135
|
}
|
|
132
136
|
|
|
137
|
+
/** An Actor membership of an ended User Spot incarnation (location runtime §6.1). */
|
|
138
|
+
interface EndedSpotMember {
|
|
139
|
+
readonly key: ZLinkStoreKey;
|
|
140
|
+
readonly version: ZLinkStoreVersion;
|
|
141
|
+
readonly ownerId: string;
|
|
142
|
+
readonly leaseGeneration: bigint;
|
|
143
|
+
readonly allocation: StoredAuthoritySnapshot['allocation'];
|
|
144
|
+
}
|
|
145
|
+
|
|
133
146
|
interface CapacityRecord {
|
|
134
147
|
readonly active: CapacityUsage;
|
|
135
148
|
readonly pending: CapacityUsage;
|
|
@@ -207,28 +220,48 @@ const MAX_OWNER_CLEANUP_BATCH_ROWS = 2_047;
|
|
|
207
220
|
*/
|
|
208
221
|
export class ZLinkLocationStoreRepository extends ZLinkInMemoryLocationStore {
|
|
209
222
|
private readonly provider: ZLinkLocationStore;
|
|
223
|
+
private readonly confirmedCapacities = new Map<string, CapacityRecord | undefined>();
|
|
210
224
|
private readonly aggregateInventory: ZLinkAggregateInventoryStore;
|
|
211
225
|
|
|
212
226
|
constructor(
|
|
213
227
|
provider: ZLinkLocationStore,
|
|
214
|
-
private readonly nowProvider: () => Date = () => new Date()
|
|
228
|
+
private readonly nowProvider: () => Date = () => new Date(),
|
|
229
|
+
private readonly metrics?: ZLinkRuntimeMetrics
|
|
215
230
|
) {
|
|
216
231
|
super(nowProvider);
|
|
217
232
|
// Classify only failures of the opaque SPI, before interpreting its records.
|
|
233
|
+
const confirm = (key: ZLinkStoreKey, bytes?: Uint8Array) => {
|
|
234
|
+
if (this.confirmedCapacities.has(key.value)) {
|
|
235
|
+
this.confirmedCapacities.set(
|
|
236
|
+
key.value,
|
|
237
|
+
bytes === undefined ? emptyCapacityRecord() : decodeJson<CapacityRecord>(bytes)
|
|
238
|
+
);
|
|
239
|
+
}
|
|
240
|
+
};
|
|
218
241
|
this.provider = {
|
|
219
242
|
async read(key, signal) {
|
|
243
|
+
let result: ZLinkStoreReadResult;
|
|
220
244
|
try {
|
|
221
|
-
|
|
245
|
+
result = await provider.read(key, signal);
|
|
222
246
|
} catch (error) {
|
|
223
247
|
throw locationStoreProviderFailure(error, signal);
|
|
224
248
|
}
|
|
249
|
+
confirm(key, result.kind === 'found' ? result.value.bytes : undefined);
|
|
250
|
+
return result;
|
|
225
251
|
},
|
|
226
252
|
async write(request, signal) {
|
|
253
|
+
let result;
|
|
227
254
|
try {
|
|
228
|
-
|
|
255
|
+
result = await provider.write(request, signal);
|
|
229
256
|
} catch (error) {
|
|
230
257
|
throw locationStoreProviderFailure(error, signal);
|
|
231
258
|
}
|
|
259
|
+
if (result.kind === 'applied') {
|
|
260
|
+
for (const mutation of request.mutations) {
|
|
261
|
+
if (mutation.kind === 'put') confirm(mutation.key, mutation.bytes);
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
return result;
|
|
232
265
|
},
|
|
233
266
|
async scan(request, signal) {
|
|
234
267
|
try {
|
|
@@ -241,9 +274,38 @@ export class ZLinkLocationStoreRepository extends ZLinkInMemoryLocationStore {
|
|
|
241
274
|
this.aggregateInventory = new ZLinkAggregateInventoryStore(this.provider);
|
|
242
275
|
}
|
|
243
276
|
|
|
277
|
+
private async observeStore<T>(operation: string, request: () => Promise<T>): Promise<T> {
|
|
278
|
+
try {
|
|
279
|
+
return await request();
|
|
280
|
+
} catch (error) {
|
|
281
|
+
if (
|
|
282
|
+
error instanceof ZLinkFrameworkException &&
|
|
283
|
+
error.kind === ZLinkFrameworkErrorKind.Unavailable
|
|
284
|
+
) {
|
|
285
|
+
this.metrics?.recordLocationStoreError(operation);
|
|
286
|
+
}
|
|
287
|
+
throw error;
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
confirmedCapacity(
|
|
292
|
+
key: ZLinkMeshNodeDescriptorKey,
|
|
293
|
+
limits: ZLinkMeshNodeDescriptor['populationCapacity']
|
|
294
|
+
): ZLinkMeshNodeDescriptor['populationCapacity'] | undefined {
|
|
295
|
+
const record = this.confirmedCapacities.get(capacityKey(key.meshName, String(key.rid)).value);
|
|
296
|
+
return record === undefined ? undefined : projectCapacity(limits, record);
|
|
297
|
+
}
|
|
298
|
+
|
|
244
299
|
override async readAuthority(
|
|
245
300
|
key: ZLinkAuthorityKey,
|
|
246
301
|
signal?: AbortSignal
|
|
302
|
+
): Promise<ZLinkAuthorityReadResult> {
|
|
303
|
+
return this.observeStore('read', () => this.readAuthorityRequest(key, signal));
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
private async readAuthorityRequest(
|
|
307
|
+
key: ZLinkAuthorityKey,
|
|
308
|
+
signal?: AbortSignal
|
|
247
309
|
): Promise<ZLinkAuthorityReadResult> {
|
|
248
310
|
const result = await this.provider.read(authorityKey(key.value), signal);
|
|
249
311
|
if (result.kind === 'missing') {
|
|
@@ -262,6 +324,17 @@ export class ZLinkLocationStoreRepository extends ZLinkInMemoryLocationStore {
|
|
|
262
324
|
cursor: ZLinkAuthorityScanCursor | undefined,
|
|
263
325
|
limit: number,
|
|
264
326
|
signal?: AbortSignal
|
|
327
|
+
): Promise<ZLinkAuthorityScanResult> {
|
|
328
|
+
return this.observeStore('read', () =>
|
|
329
|
+
this.listAuthoritiesRequest(prefix, cursor, limit, signal)
|
|
330
|
+
);
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
private async listAuthoritiesRequest(
|
|
334
|
+
prefix: string,
|
|
335
|
+
cursor: ZLinkAuthorityScanCursor | undefined,
|
|
336
|
+
limit: number,
|
|
337
|
+
signal?: AbortSignal
|
|
265
338
|
): Promise<ZLinkAuthorityScanResult> {
|
|
266
339
|
if (!Number.isInteger(limit) || limit < 1 || limit > ZLINK_PROVIDER_MAX_PAGE_SIZE) {
|
|
267
340
|
throw new RangeError(`Authority scan limit must be in 1..${ZLINK_PROVIDER_MAX_PAGE_SIZE}.`);
|
|
@@ -303,6 +376,17 @@ export class ZLinkLocationStoreRepository extends ZLinkInMemoryLocationStore {
|
|
|
303
376
|
expectedStoreVersion: ZLinkAuthorityStoreVersion,
|
|
304
377
|
mutation: ZLinkAuthorityMutation,
|
|
305
378
|
signal?: AbortSignal
|
|
379
|
+
): Promise<ZLinkAuthorityCompareExchangeResult> {
|
|
380
|
+
return this.observeStore('compare_exchange', () =>
|
|
381
|
+
this.compareExchangeAuthorityRequest(key, expectedStoreVersion, mutation, signal)
|
|
382
|
+
);
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
private async compareExchangeAuthorityRequest(
|
|
386
|
+
key: ZLinkAuthorityKey,
|
|
387
|
+
expectedStoreVersion: ZLinkAuthorityStoreVersion,
|
|
388
|
+
mutation: ZLinkAuthorityMutation,
|
|
389
|
+
signal?: AbortSignal
|
|
306
390
|
): Promise<ZLinkAuthorityCompareExchangeResult> {
|
|
307
391
|
if (mutation.kind !== 'delete') {
|
|
308
392
|
validatePayloadSize(mutation.payload, 'Authority payload');
|
|
@@ -551,6 +635,15 @@ export class ZLinkLocationStoreRepository extends ZLinkInMemoryLocationStore {
|
|
|
551
635
|
override async prepareAggregate(
|
|
552
636
|
request: ZLinkAggregatePrepareRequest,
|
|
553
637
|
signal?: AbortSignal
|
|
638
|
+
): Promise<ZLinkAggregatePrepareResult> {
|
|
639
|
+
return this.observeStore('compare_exchange', () =>
|
|
640
|
+
this.prepareAggregateRequest(request, signal)
|
|
641
|
+
);
|
|
642
|
+
}
|
|
643
|
+
|
|
644
|
+
private async prepareAggregateRequest(
|
|
645
|
+
request: ZLinkAggregatePrepareRequest,
|
|
646
|
+
signal?: AbortSignal
|
|
554
647
|
): Promise<ZLinkAggregatePrepareResult> {
|
|
555
648
|
validateProviderAggregateRequest(request);
|
|
556
649
|
const fence = aggregateFence(request.aggregateId, request.aggregateGeneration);
|
|
@@ -838,7 +931,7 @@ export class ZLinkLocationStoreRepository extends ZLinkInMemoryLocationStore {
|
|
|
838
931
|
aggregateRecord.requestFingerprint === fingerprint &&
|
|
839
932
|
(aggregateRecord.state === 'staging' || aggregateRecord.state === 'prepared')
|
|
840
933
|
) {
|
|
841
|
-
return await this.
|
|
934
|
+
return await this.prepareAggregateRequest(request, signal);
|
|
842
935
|
}
|
|
843
936
|
}
|
|
844
937
|
await this.clearAggregateMarkers(fence, installed, signal);
|
|
@@ -915,6 +1008,13 @@ export class ZLinkLocationStoreRepository extends ZLinkInMemoryLocationStore {
|
|
|
915
1008
|
override async commitAggregate(
|
|
916
1009
|
fence: ZLinkAggregateFence,
|
|
917
1010
|
signal?: AbortSignal
|
|
1011
|
+
): Promise<ZLinkAggregateCommitResult> {
|
|
1012
|
+
return this.observeStore('compare_exchange', () => this.commitAggregateRequest(fence, signal));
|
|
1013
|
+
}
|
|
1014
|
+
|
|
1015
|
+
private async commitAggregateRequest(
|
|
1016
|
+
fence: ZLinkAggregateFence,
|
|
1017
|
+
signal?: AbortSignal
|
|
918
1018
|
): Promise<ZLinkAggregateCommitResult> {
|
|
919
1019
|
validateAggregateFence(fence);
|
|
920
1020
|
return await this.commitAggregateCore(fence, signal);
|
|
@@ -1146,6 +1246,13 @@ export class ZLinkLocationStoreRepository extends ZLinkInMemoryLocationStore {
|
|
|
1146
1246
|
override async abortAggregate(
|
|
1147
1247
|
fence: ZLinkAggregateFence,
|
|
1148
1248
|
signal?: AbortSignal
|
|
1249
|
+
): Promise<ZLinkAggregateAbortResult> {
|
|
1250
|
+
return this.observeStore('compare_exchange', () => this.abortAggregateRequest(fence, signal));
|
|
1251
|
+
}
|
|
1252
|
+
|
|
1253
|
+
private async abortAggregateRequest(
|
|
1254
|
+
fence: ZLinkAggregateFence,
|
|
1255
|
+
signal?: AbortSignal
|
|
1149
1256
|
): Promise<ZLinkAggregateAbortResult> {
|
|
1150
1257
|
validateAggregateFence(fence);
|
|
1151
1258
|
const rowKey = aggregateKey(fence);
|
|
@@ -1206,6 +1313,17 @@ export class ZLinkLocationStoreRepository extends ZLinkInMemoryLocationStore {
|
|
|
1206
1313
|
expectedStoreVersion: string,
|
|
1207
1314
|
signal?: AbortSignal,
|
|
1208
1315
|
request?: ZLinkEndedOwnerReleaseIntent
|
|
1316
|
+
): Promise<boolean> {
|
|
1317
|
+
return this.observeStore('release', () =>
|
|
1318
|
+
this.releaseEndedReservationRequest(key, expectedStoreVersion, signal, request)
|
|
1319
|
+
);
|
|
1320
|
+
}
|
|
1321
|
+
|
|
1322
|
+
private async releaseEndedReservationRequest(
|
|
1323
|
+
key: ZLinkAuthorityKey,
|
|
1324
|
+
expectedStoreVersion: string,
|
|
1325
|
+
signal?: AbortSignal,
|
|
1326
|
+
request?: ZLinkEndedOwnerReleaseIntent
|
|
1209
1327
|
): Promise<boolean> {
|
|
1210
1328
|
return (
|
|
1211
1329
|
(await this.tryReleaseEndedReservation(key, expectedStoreVersion, signal, request)) ===
|
|
@@ -1245,9 +1363,8 @@ export class ZLinkLocationStoreRepository extends ZLinkInMemoryLocationStore {
|
|
|
1245
1363
|
this.provider.read(descriptorKey, signal),
|
|
1246
1364
|
this.provider.read(capacityRowKey, signal)
|
|
1247
1365
|
]);
|
|
1248
|
-
if (lease.kind === 'found' && lease.value.expiresAt === undefined)
|
|
1249
|
-
throw new Error('Location Store owner lease record is invalid.');
|
|
1250
1366
|
const ownerLive = sameLiveOwner(lease, snapshot);
|
|
1367
|
+
let members: EndedSpotMember[] = [];
|
|
1251
1368
|
if (snapshot.allocation.state === 'active') {
|
|
1252
1369
|
if (ownerLive) return 'notReclaimable';
|
|
1253
1370
|
let unavailable = record.aggregate !== undefined || hasRelocationAuthority(snapshot.payload);
|
|
@@ -1259,46 +1376,12 @@ export class ZLinkLocationStoreRepository extends ZLinkInMemoryLocationStore {
|
|
|
1259
1376
|
spot.stableType !== request.intent.stableType ||
|
|
1260
1377
|
spot.spotId !== request.key.globalId ||
|
|
1261
1378
|
spot.activationRecovery !== undefined;
|
|
1262
|
-
if (
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
do {
|
|
1269
|
-
const page = await this.provider.scan(
|
|
1270
|
-
{ prefix, cursor, limit: ZLINK_PROVIDER_MAX_PAGE_SIZE },
|
|
1271
|
-
signal
|
|
1272
|
-
);
|
|
1273
|
-
if (page.kind === 'expired') continue membershipSnapshot;
|
|
1274
|
-
for (const item of page.value.items) {
|
|
1275
|
-
if (prefix === `${PREFIX}actor:`) {
|
|
1276
|
-
const actor = normalizeActor(
|
|
1277
|
-
decodeJson<DescriptorRecord<ZLinkActorLocation>>(item.value.bytes).descriptor
|
|
1278
|
-
);
|
|
1279
|
-
snapshotHasMember ||=
|
|
1280
|
-
actor.spotKind === ZLinkSpotKind.User &&
|
|
1281
|
-
String(actor.spotId) === spot.spotId &&
|
|
1282
|
-
actor.spotGeneration === snapshot.objectGeneration;
|
|
1283
|
-
} else {
|
|
1284
|
-
const authority = decodeAuthorityRecord(item.value.bytes).snapshot;
|
|
1285
|
-
if (authority.allocation.objectKind !== 'actor') continue;
|
|
1286
|
-
const actor = decodeActorAuthorityPayload(
|
|
1287
|
-
serviceRelocationAuthorityApplicationPayload(authority.payload)
|
|
1288
|
-
);
|
|
1289
|
-
snapshotHasMember ||=
|
|
1290
|
-
actor?.currentSpotKind === ZLinkSpotKind.User &&
|
|
1291
|
-
actor.currentSpotId === spot.spotId &&
|
|
1292
|
-
actor.currentSpotGeneration === snapshot.objectGeneration;
|
|
1293
|
-
}
|
|
1294
|
-
}
|
|
1295
|
-
cursor = page.value.nextCursor;
|
|
1296
|
-
} while (cursor !== undefined);
|
|
1297
|
-
unavailable ||= snapshotHasMember;
|
|
1298
|
-
break;
|
|
1299
|
-
}
|
|
1300
|
-
}
|
|
1301
|
-
}
|
|
1379
|
+
if (
|
|
1380
|
+
spot?.kind === 'user_spot' &&
|
|
1381
|
+
!unavailable &&
|
|
1382
|
+
request?.actorRelocationPolicy === 'disabled'
|
|
1383
|
+
)
|
|
1384
|
+
members = await this.readEndedSpotMembers(spot.spotId, snapshot.objectGeneration, signal);
|
|
1302
1385
|
}
|
|
1303
1386
|
if (unavailable || request?.actorRelocationPolicy !== 'disabled')
|
|
1304
1387
|
throw new ZLinkFrameworkException(
|
|
@@ -1318,60 +1401,171 @@ export class ZLinkLocationStoreRepository extends ZLinkInMemoryLocationStore {
|
|
|
1318
1401
|
(record.aggregate !== undefined || hasRelocationAuthority(snapshot.payload))
|
|
1319
1402
|
)
|
|
1320
1403
|
return 'notReclaimable';
|
|
1404
|
+
// Location runtime §6.1: the authority and every ended-owner member are released in
|
|
1405
|
+
// one conditional batch. Each member is fenced by its row version and the observed
|
|
1406
|
+
// (invalid) state of its own owner lease; member capacity is returned like the Spot's.
|
|
1407
|
+
const conditions: ZLinkStoreCondition[] = [
|
|
1408
|
+
{ kind: 'version', key: rowKey, expected: current.value.version },
|
|
1409
|
+
conditionFor(descriptorKey, descriptor)
|
|
1410
|
+
];
|
|
1321
1411
|
const mutations: ZLinkStoreWriteRequest['mutations'][number][] = [
|
|
1322
1412
|
{ kind: 'delete', key: rowKey }
|
|
1323
1413
|
];
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1414
|
+
const owners = new Map<string, ZLinkStoreReadResult>([[snapshot.ownerId, lease]]);
|
|
1415
|
+
for (const member of members) {
|
|
1416
|
+
let memberLease = owners.get(member.ownerId);
|
|
1417
|
+
if (memberLease === undefined) {
|
|
1418
|
+
memberLease = await this.provider.read(ownerKey(member.ownerId), signal);
|
|
1419
|
+
owners.set(member.ownerId, memberLease);
|
|
1420
|
+
}
|
|
1421
|
+
if (
|
|
1422
|
+
memberLease.kind === 'found' &&
|
|
1423
|
+
matchesLiveOwnerLease(memberLease, member.ownerId, member.leaseGeneration)
|
|
1424
|
+
)
|
|
1425
|
+
throw new ZLinkFrameworkException(
|
|
1426
|
+
ZLinkFrameworkErrorKind.Unavailable,
|
|
1427
|
+
'User Spot still has a member with a live owner lease.'
|
|
1428
|
+
);
|
|
1429
|
+
conditions.push({ kind: 'version', key: member.key, expected: member.version });
|
|
1430
|
+
mutations.push({ kind: 'delete', key: member.key });
|
|
1431
|
+
}
|
|
1432
|
+
for (const [ownerId, read] of owners) conditions.push(conditionFor(ownerKey(ownerId), read));
|
|
1433
|
+
const capacities = new Map<string, { read: ZLinkStoreReadResult; next?: CapacityRecord }>([
|
|
1434
|
+
[capacityRowKey.value, { read: capacity }]
|
|
1435
|
+
]);
|
|
1436
|
+
const releases: { allocation: StoredAuthoritySnapshot['allocation'] }[] = [
|
|
1437
|
+
{ allocation: snapshot.allocation },
|
|
1438
|
+
...members.map((member) => ({ allocation: member.allocation }))
|
|
1439
|
+
];
|
|
1440
|
+
try {
|
|
1441
|
+
for (const { allocation } of releases) {
|
|
1442
|
+
const key = capacityKey(allocation.descriptor.meshName, String(allocation.descriptor.rid));
|
|
1443
|
+
let entry = capacities.get(key.value);
|
|
1444
|
+
if (entry === undefined) {
|
|
1445
|
+
entry = { read: await this.provider.read(key, signal) };
|
|
1446
|
+
capacities.set(key.value, entry);
|
|
1447
|
+
}
|
|
1448
|
+
if (entry.read.kind !== 'found') continue;
|
|
1449
|
+
const stored = entry.next ?? decodeJson<CapacityRecord>(entry.read.value.bytes);
|
|
1450
|
+
entry.next = {
|
|
1451
|
+
active:
|
|
1452
|
+
allocation.state === 'active'
|
|
1453
|
+
? subtractCapacity(stored.active, allocation.capacity)
|
|
1454
|
+
: stored.active,
|
|
1455
|
+
pending:
|
|
1456
|
+
allocation.state === 'reserved'
|
|
1457
|
+
? subtractCapacity(stored.pending, allocation.capacity)
|
|
1458
|
+
: stored.pending
|
|
1459
|
+
};
|
|
1460
|
+
}
|
|
1461
|
+
} catch (error) {
|
|
1462
|
+
if (
|
|
1463
|
+
!(error instanceof ZLinkFrameworkException) ||
|
|
1464
|
+
error.kind !== ZLinkFrameworkErrorKind.DataLost
|
|
1465
|
+
)
|
|
1466
|
+
throw error;
|
|
1467
|
+
for (const authority of [{ key: rowKey, version: current.value.version }, ...members]) {
|
|
1468
|
+
const observed = await this.provider.read(authority.key, signal);
|
|
1469
|
+
if (observed.kind === 'missing' || observed.value.version.value !== authority.version.value)
|
|
1470
|
+
return 'conflict';
|
|
1471
|
+
}
|
|
1472
|
+
throw error;
|
|
1473
|
+
}
|
|
1474
|
+
for (const [key, entry] of capacities) {
|
|
1475
|
+
conditions.push(conditionFor(storeKey(key), entry.read));
|
|
1476
|
+
if (entry.next !== undefined)
|
|
1327
1477
|
mutations.push({
|
|
1328
1478
|
kind: 'put',
|
|
1329
|
-
key:
|
|
1330
|
-
bytes: encodeJson(
|
|
1331
|
-
active:
|
|
1332
|
-
snapshot.allocation.state === 'active'
|
|
1333
|
-
? subtractCapacity(stored.active, snapshot.allocation.capacity)
|
|
1334
|
-
: stored.active,
|
|
1335
|
-
pending:
|
|
1336
|
-
snapshot.allocation.state === 'reserved'
|
|
1337
|
-
? subtractCapacity(stored.pending, snapshot.allocation.capacity)
|
|
1338
|
-
: stored.pending
|
|
1339
|
-
} satisfies CapacityRecord)
|
|
1479
|
+
key: storeKey(key),
|
|
1480
|
+
bytes: encodeJson(entry.next satisfies CapacityRecord)
|
|
1340
1481
|
});
|
|
1341
|
-
} catch (error) {
|
|
1342
|
-
if (
|
|
1343
|
-
!(error instanceof ZLinkFrameworkException) ||
|
|
1344
|
-
error.kind !== ZLinkFrameworkErrorKind.DataLost
|
|
1345
|
-
)
|
|
1346
|
-
throw error;
|
|
1347
|
-
const observed = await this.provider.read(rowKey, signal);
|
|
1348
|
-
if (
|
|
1349
|
-
observed.kind === 'missing' ||
|
|
1350
|
-
observed.value.version.value !== current.value.version.value
|
|
1351
|
-
)
|
|
1352
|
-
return 'conflict';
|
|
1353
|
-
throw error;
|
|
1354
|
-
}
|
|
1355
1482
|
}
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
mutations
|
|
1365
|
-
},
|
|
1366
|
-
signal
|
|
1367
|
-
);
|
|
1483
|
+
// Every mutated key is also a condition key, so the condition count is the batch's
|
|
1484
|
+
// unique key count. A release beyond the provider bound changes nothing.
|
|
1485
|
+
if (conditions.length > ZLINK_PROVIDER_MAX_WRITE_KEYS)
|
|
1486
|
+
throw new ZLinkFrameworkException(
|
|
1487
|
+
ZLinkFrameworkErrorKind.Unavailable,
|
|
1488
|
+
'User Spot member release exceeds one Location Store batch.'
|
|
1489
|
+
);
|
|
1490
|
+
const result = await this.provider.write({ conditions, mutations }, signal);
|
|
1368
1491
|
return result.kind === 'applied' ? 'reclaimed' : 'conflict';
|
|
1369
1492
|
}
|
|
1370
1493
|
|
|
1494
|
+
/**
|
|
1495
|
+
* Reads every Actor membership of one User Spot incarnation from complete snapshot scans
|
|
1496
|
+
* (location runtime §6.1), from Actor authorities alone. An expired snapshot
|
|
1497
|
+
* discards the earlier pages and restarts; a Store failure propagates. A member authority
|
|
1498
|
+
* that is relocating, part of an aggregate or not yet activated keeps the Spot.
|
|
1499
|
+
*/
|
|
1500
|
+
private async readEndedSpotMembers(
|
|
1501
|
+
spotId: string,
|
|
1502
|
+
spotGeneration: bigint,
|
|
1503
|
+
signal?: AbortSignal
|
|
1504
|
+
): Promise<EndedSpotMember[]> {
|
|
1505
|
+
membershipSnapshot: for (;;) {
|
|
1506
|
+
const members: EndedSpotMember[] = [];
|
|
1507
|
+
let cursor: ZLinkStoreScanCursor | undefined;
|
|
1508
|
+
do {
|
|
1509
|
+
const page = await this.provider.scan(
|
|
1510
|
+
{
|
|
1511
|
+
prefix: `${AUTHORITY_PREIMAGE_PREFIX}actor\0`,
|
|
1512
|
+
cursor,
|
|
1513
|
+
limit: ZLINK_PROVIDER_MAX_PAGE_SIZE
|
|
1514
|
+
},
|
|
1515
|
+
signal
|
|
1516
|
+
);
|
|
1517
|
+
if (page.kind === 'expired') continue membershipSnapshot;
|
|
1518
|
+
for (const item of page.value.items) {
|
|
1519
|
+
const record = decodeAuthorityRecord(item.value.bytes);
|
|
1520
|
+
const authority = record.snapshot;
|
|
1521
|
+
if (authority.allocation.objectKind !== 'actor') continue;
|
|
1522
|
+
const actor = decodeActorAuthorityPayload(
|
|
1523
|
+
serviceRelocationAuthorityApplicationPayload(authority.payload)
|
|
1524
|
+
);
|
|
1525
|
+
if (
|
|
1526
|
+
actor?.currentSpotKind !== ZLinkSpotKind.User ||
|
|
1527
|
+
actor.currentSpotId !== spotId ||
|
|
1528
|
+
actor.currentSpotGeneration !== spotGeneration
|
|
1529
|
+
)
|
|
1530
|
+
continue;
|
|
1531
|
+
if (
|
|
1532
|
+
authority.allocation.state !== 'active' ||
|
|
1533
|
+
record.aggregate !== undefined ||
|
|
1534
|
+
hasRelocationAuthority(authority.payload) ||
|
|
1535
|
+
decodeActorAuthorityPayload(authority.payload)?.state !== 'ready'
|
|
1536
|
+
)
|
|
1537
|
+
throw new ZLinkFrameworkException(
|
|
1538
|
+
ZLinkFrameworkErrorKind.Unavailable,
|
|
1539
|
+
'User Spot still has a relocating or unactivated member.'
|
|
1540
|
+
);
|
|
1541
|
+
members.push({
|
|
1542
|
+
key: item.key,
|
|
1543
|
+
version: item.value.version,
|
|
1544
|
+
ownerId: authority.ownerId,
|
|
1545
|
+
leaseGeneration: authority.ownerLeaseGeneration,
|
|
1546
|
+
allocation: authority.allocation
|
|
1547
|
+
});
|
|
1548
|
+
}
|
|
1549
|
+
cursor = page.value.nextCursor;
|
|
1550
|
+
} while (cursor !== undefined);
|
|
1551
|
+
return members;
|
|
1552
|
+
}
|
|
1553
|
+
}
|
|
1554
|
+
|
|
1371
1555
|
override async reserve(
|
|
1372
1556
|
request: ZLinkObjectReserveRequest,
|
|
1373
1557
|
signal?: AbortSignal,
|
|
1374
1558
|
deadlineUnixMs?: bigint
|
|
1559
|
+
): Promise<ZLinkObjectReserveResult> {
|
|
1560
|
+
return this.observeStore('compare_exchange', () =>
|
|
1561
|
+
this.reserveRequest(request, signal, deadlineUnixMs)
|
|
1562
|
+
);
|
|
1563
|
+
}
|
|
1564
|
+
|
|
1565
|
+
private async reserveRequest(
|
|
1566
|
+
request: ZLinkObjectReserveRequest,
|
|
1567
|
+
signal?: AbortSignal,
|
|
1568
|
+
deadlineUnixMs?: bigint
|
|
1375
1569
|
): Promise<ZLinkObjectReserveResult> {
|
|
1376
1570
|
const encodedAuthorityKey = encodeAuthorityKey(request.key.kind, request.key.globalId);
|
|
1377
1571
|
const reservationId = randomUUID();
|
|
@@ -1517,6 +1711,16 @@ export class ZLinkLocationStoreRepository extends ZLinkInMemoryLocationStore {
|
|
|
1517
1711
|
request: ZLinkObjectCommitRequest,
|
|
1518
1712
|
signal?: AbortSignal,
|
|
1519
1713
|
deadlineUnixMs?: bigint
|
|
1714
|
+
): Promise<ZLinkObjectCommitResult> {
|
|
1715
|
+
return this.observeStore('compare_exchange', () =>
|
|
1716
|
+
this.commitRequest(request, signal, deadlineUnixMs)
|
|
1717
|
+
);
|
|
1718
|
+
}
|
|
1719
|
+
|
|
1720
|
+
private async commitRequest(
|
|
1721
|
+
request: ZLinkObjectCommitRequest,
|
|
1722
|
+
signal?: AbortSignal,
|
|
1723
|
+
deadlineUnixMs?: bigint
|
|
1520
1724
|
): Promise<ZLinkObjectCommitResult> {
|
|
1521
1725
|
const key = encodeAuthorityKey(request.key.kind, request.key.globalId);
|
|
1522
1726
|
const rowKey = authorityKey(key.value);
|
|
@@ -1603,6 +1807,16 @@ export class ZLinkLocationStoreRepository extends ZLinkInMemoryLocationStore {
|
|
|
1603
1807
|
request: ZLinkObjectAbortRequest,
|
|
1604
1808
|
signal?: AbortSignal,
|
|
1605
1809
|
deadlineUnixMs?: bigint
|
|
1810
|
+
): Promise<ZLinkObjectAbortResult> {
|
|
1811
|
+
return this.observeStore('compare_exchange', () =>
|
|
1812
|
+
this.abortRequest(request, signal, deadlineUnixMs)
|
|
1813
|
+
);
|
|
1814
|
+
}
|
|
1815
|
+
|
|
1816
|
+
private async abortRequest(
|
|
1817
|
+
request: ZLinkObjectAbortRequest,
|
|
1818
|
+
signal?: AbortSignal,
|
|
1819
|
+
deadlineUnixMs?: bigint
|
|
1606
1820
|
): Promise<ZLinkObjectAbortResult> {
|
|
1607
1821
|
const key = encodeAuthorityKey(request.key.kind, request.key.globalId);
|
|
1608
1822
|
const rowKey = authorityKey(key.value);
|
|
@@ -1627,12 +1841,6 @@ export class ZLinkLocationStoreRepository extends ZLinkInMemoryLocationStore {
|
|
|
1627
1841
|
this.provider.read(leaseKey, signal),
|
|
1628
1842
|
this.provider.read(capacityRowKey, signal)
|
|
1629
1843
|
]);
|
|
1630
|
-
if (leaseRead.kind === 'found' && leaseRead.value.expiresAt === undefined) {
|
|
1631
|
-
// A lease is always written with a positive TTL, so a missing expiry
|
|
1632
|
-
// is a corrupt record. Abort deletes authority state, so refuse
|
|
1633
|
-
// rather than read the absence as expiry.
|
|
1634
|
-
throw new Error('Location Store owner lease record is invalid.');
|
|
1635
|
-
}
|
|
1636
1844
|
if (liveTargetDescriptor(descriptorRead, leaseRead, request.target) === undefined)
|
|
1637
1845
|
return { kind: 'stale' };
|
|
1638
1846
|
const capacity =
|
|
@@ -1672,6 +1880,15 @@ export class ZLinkLocationStoreRepository extends ZLinkInMemoryLocationStore {
|
|
|
1672
1880
|
override async completeCreation(
|
|
1673
1881
|
request: ZLinkObjectCreationCompleteRequest,
|
|
1674
1882
|
signal?: AbortSignal
|
|
1883
|
+
): Promise<ZLinkObjectCreationCompleteResult> {
|
|
1884
|
+
return this.observeStore('compare_exchange', () =>
|
|
1885
|
+
this.completeCreationRequest(request, signal)
|
|
1886
|
+
);
|
|
1887
|
+
}
|
|
1888
|
+
|
|
1889
|
+
private async completeCreationRequest(
|
|
1890
|
+
request: ZLinkObjectCreationCompleteRequest,
|
|
1891
|
+
signal?: AbortSignal
|
|
1675
1892
|
): Promise<ZLinkObjectCreationCompleteResult> {
|
|
1676
1893
|
if (request.key.kind !== 'actor') {
|
|
1677
1894
|
throw new TypeError('completeCreation is reserved for Actor creation.');
|
|
@@ -1840,6 +2057,13 @@ export class ZLinkLocationStoreRepository extends ZLinkInMemoryLocationStore {
|
|
|
1840
2057
|
override async readCreationTerminal(
|
|
1841
2058
|
operation: ZLinkCreationOperationIdentity,
|
|
1842
2059
|
signal?: AbortSignal
|
|
2060
|
+
): Promise<ZLinkCreationTerminalReadResult> {
|
|
2061
|
+
return this.observeStore('read', () => this.readCreationTerminalRequest(operation, signal));
|
|
2062
|
+
}
|
|
2063
|
+
|
|
2064
|
+
private async readCreationTerminalRequest(
|
|
2065
|
+
operation: ZLinkCreationOperationIdentity,
|
|
2066
|
+
signal?: AbortSignal
|
|
1843
2067
|
): Promise<ZLinkCreationTerminalReadResult> {
|
|
1844
2068
|
validateCreationOperation(operation);
|
|
1845
2069
|
const result = await this.provider.read(creationTerminalKey(operation), signal);
|
|
@@ -1855,6 +2079,16 @@ export class ZLinkLocationStoreRepository extends ZLinkInMemoryLocationStore {
|
|
|
1855
2079
|
ownerId: string,
|
|
1856
2080
|
leaseTtlMs: number,
|
|
1857
2081
|
signal?: AbortSignal
|
|
2082
|
+
): Promise<ZLinkOwnerLeaseClaimResult> {
|
|
2083
|
+
return this.observeStore('compare_exchange', () =>
|
|
2084
|
+
this.claimOwnerLeaseRequest(ownerId, leaseTtlMs, signal)
|
|
2085
|
+
);
|
|
2086
|
+
}
|
|
2087
|
+
|
|
2088
|
+
private async claimOwnerLeaseRequest(
|
|
2089
|
+
ownerId: string,
|
|
2090
|
+
leaseTtlMs: number,
|
|
2091
|
+
signal?: AbortSignal
|
|
1858
2092
|
): Promise<ZLinkOwnerLeaseClaimResult> {
|
|
1859
2093
|
requireOwnerInput(ownerId, leaseTtlMs);
|
|
1860
2094
|
for (;;) {
|
|
@@ -1906,17 +2140,25 @@ export class ZLinkLocationStoreRepository extends ZLinkInMemoryLocationStore {
|
|
|
1906
2140
|
override async readOwnerLease(
|
|
1907
2141
|
ownerId: string,
|
|
1908
2142
|
signal?: AbortSignal
|
|
2143
|
+
): Promise<ZLinkOwnerLeaseReadResult> {
|
|
2144
|
+
return this.observeStore('read', () => this.readOwnerLeaseRequest(ownerId, signal));
|
|
2145
|
+
}
|
|
2146
|
+
|
|
2147
|
+
private async readOwnerLeaseRequest(
|
|
2148
|
+
ownerId: string,
|
|
2149
|
+
signal?: AbortSignal
|
|
1909
2150
|
): Promise<ZLinkOwnerLeaseReadResult> {
|
|
1910
2151
|
const result = await this.provider.read(ownerKey(ownerId), signal);
|
|
1911
2152
|
if (result.kind === 'missing') return { kind: 'missing' };
|
|
2153
|
+
const leaseExpiresAt = requireOwnerLeaseExpiry(result.value);
|
|
1912
2154
|
const record = decodeOwnerRecord(result.value.bytes);
|
|
1913
|
-
if (record.ownerId !== ownerId
|
|
2155
|
+
if (record.ownerId !== ownerId) {
|
|
1914
2156
|
throw new Error('Location Store owner lease record is invalid.');
|
|
1915
2157
|
}
|
|
1916
2158
|
return {
|
|
1917
2159
|
kind: 'found',
|
|
1918
2160
|
token: { ownerId, leaseGeneration: BigInt(record.leaseGeneration) },
|
|
1919
|
-
leaseExpiresAt
|
|
2161
|
+
leaseExpiresAt,
|
|
1920
2162
|
storeNow: result.value.storeNow
|
|
1921
2163
|
};
|
|
1922
2164
|
}
|
|
@@ -1925,6 +2167,16 @@ export class ZLinkLocationStoreRepository extends ZLinkInMemoryLocationStore {
|
|
|
1925
2167
|
token: ZLinkLocationOwnerToken,
|
|
1926
2168
|
leaseTtlMs: number,
|
|
1927
2169
|
signal?: AbortSignal
|
|
2170
|
+
): Promise<ZLinkOwnerLeaseRenewResult> {
|
|
2171
|
+
return this.observeStore('lease_renew', () =>
|
|
2172
|
+
this.renewOwnerLeaseRequest(token, leaseTtlMs, signal)
|
|
2173
|
+
);
|
|
2174
|
+
}
|
|
2175
|
+
|
|
2176
|
+
private async renewOwnerLeaseRequest(
|
|
2177
|
+
token: ZLinkLocationOwnerToken,
|
|
2178
|
+
leaseTtlMs: number,
|
|
2179
|
+
signal?: AbortSignal
|
|
1928
2180
|
): Promise<ZLinkOwnerLeaseRenewResult> {
|
|
1929
2181
|
requireOwnerInput(token.ownerId, leaseTtlMs);
|
|
1930
2182
|
const key = ownerKey(token.ownerId);
|
|
@@ -1957,6 +2209,13 @@ export class ZLinkLocationStoreRepository extends ZLinkInMemoryLocationStore {
|
|
|
1957
2209
|
override async releaseOwnerLease(
|
|
1958
2210
|
token: ZLinkLocationOwnerToken,
|
|
1959
2211
|
signal?: AbortSignal
|
|
2212
|
+
): Promise<ZLinkOwnerLeaseReleaseResult> {
|
|
2213
|
+
return this.observeStore('release', () => this.releaseOwnerLeaseRequest(token, signal));
|
|
2214
|
+
}
|
|
2215
|
+
|
|
2216
|
+
private async releaseOwnerLeaseRequest(
|
|
2217
|
+
token: ZLinkLocationOwnerToken,
|
|
2218
|
+
signal?: AbortSignal
|
|
1960
2219
|
): Promise<ZLinkOwnerLeaseReleaseResult> {
|
|
1961
2220
|
const key = ownerKey(token.ownerId);
|
|
1962
2221
|
const current = await this.provider.read(key, signal);
|
|
@@ -1978,6 +2237,19 @@ export class ZLinkLocationStoreRepository extends ZLinkInMemoryLocationStore {
|
|
|
1978
2237
|
intent: ZLinkLocationWriteIntent,
|
|
1979
2238
|
signal?: AbortSignal
|
|
1980
2239
|
): Promise<ZLinkLocationWriteResult> {
|
|
2240
|
+
return this.observeStore('compare_exchange', () =>
|
|
2241
|
+
this.updateMeshNodeRequest(descriptor, intent, signal)
|
|
2242
|
+
);
|
|
2243
|
+
}
|
|
2244
|
+
|
|
2245
|
+
private async updateMeshNodeRequest(
|
|
2246
|
+
descriptor: ZLinkMeshNodeDescriptor,
|
|
2247
|
+
intent: ZLinkLocationWriteIntent,
|
|
2248
|
+
signal?: AbortSignal
|
|
2249
|
+
): Promise<ZLinkLocationWriteResult> {
|
|
2250
|
+
const capacityRowKey = capacityKey(descriptor.meshName, String(descriptor.rid));
|
|
2251
|
+
if (!this.confirmedCapacities.has(capacityRowKey.value))
|
|
2252
|
+
this.confirmedCapacities.set(capacityRowKey.value, undefined);
|
|
1981
2253
|
return this.updateDescriptor(
|
|
1982
2254
|
meshKey(descriptor.meshName, descriptor.rid),
|
|
1983
2255
|
descriptor,
|
|
@@ -1993,6 +2265,14 @@ export class ZLinkLocationStoreRepository extends ZLinkInMemoryLocationStore {
|
|
|
1993
2265
|
key: ZLinkMeshNodeDescriptorKey,
|
|
1994
2266
|
owner: ZLinkLocationOwnerToken,
|
|
1995
2267
|
signal?: AbortSignal
|
|
2268
|
+
): Promise<ZLinkLocationWriteStatus> {
|
|
2269
|
+
return this.observeStore('release', () => this.removeMeshNodeRequest(key, owner, signal));
|
|
2270
|
+
}
|
|
2271
|
+
|
|
2272
|
+
private async removeMeshNodeRequest(
|
|
2273
|
+
key: ZLinkMeshNodeDescriptorKey,
|
|
2274
|
+
owner: ZLinkLocationOwnerToken,
|
|
2275
|
+
signal?: AbortSignal
|
|
1996
2276
|
): Promise<ZLinkLocationWriteStatus> {
|
|
1997
2277
|
const rowKey = meshKey(key.meshName, key.rid);
|
|
1998
2278
|
const current = await this.provider.read(rowKey, signal);
|
|
@@ -2013,6 +2293,8 @@ export class ZLinkLocationStoreRepository extends ZLinkInMemoryLocationStore {
|
|
|
2013
2293
|
},
|
|
2014
2294
|
signal
|
|
2015
2295
|
);
|
|
2296
|
+
if (result.kind === 'applied')
|
|
2297
|
+
this.confirmedCapacities.delete(capacityKey(key.meshName, String(key.rid)).value);
|
|
2016
2298
|
return result.kind === 'applied' ? WriteStatus.Stored : WriteStatus.IgnoredStale;
|
|
2017
2299
|
}
|
|
2018
2300
|
|
|
@@ -2020,6 +2302,14 @@ export class ZLinkLocationStoreRepository extends ZLinkInMemoryLocationStore {
|
|
|
2020
2302
|
meshName: string,
|
|
2021
2303
|
page: ZLinkPageRequest = {},
|
|
2022
2304
|
signal?: AbortSignal
|
|
2305
|
+
): Promise<ZLinkLocationPage<ZLinkMeshNodeDescriptor>> {
|
|
2306
|
+
return this.observeStore('read', () => this.listMeshNodesRequest(meshName, page, signal));
|
|
2307
|
+
}
|
|
2308
|
+
|
|
2309
|
+
private async listMeshNodesRequest(
|
|
2310
|
+
meshName: string,
|
|
2311
|
+
page: ZLinkPageRequest = {},
|
|
2312
|
+
signal?: AbortSignal
|
|
2023
2313
|
): Promise<ZLinkLocationPage<ZLinkMeshNodeDescriptor>> {
|
|
2024
2314
|
const result = await this.provider.scan(
|
|
2025
2315
|
{
|
|
@@ -2050,30 +2340,7 @@ export class ZLinkLocationStoreRepository extends ZLinkInMemoryLocationStore {
|
|
|
2050
2340
|
: decodeJson<CapacityRecord>(capacityRead.value.bytes);
|
|
2051
2341
|
return {
|
|
2052
2342
|
...descriptor,
|
|
2053
|
-
populationCapacity:
|
|
2054
|
-
actors: {
|
|
2055
|
-
...descriptor.populationCapacity.actors,
|
|
2056
|
-
active: capacity.active.actors,
|
|
2057
|
-
reserved: capacity.pending.actors
|
|
2058
|
-
},
|
|
2059
|
-
spots: {
|
|
2060
|
-
...descriptor.populationCapacity.spots,
|
|
2061
|
-
active: capacity.active.spots,
|
|
2062
|
-
reserved: capacity.pending.spots
|
|
2063
|
-
},
|
|
2064
|
-
spotTypes: descriptor.populationCapacity.spotTypes.map((value) => {
|
|
2065
|
-
const key = capacityTypeKey({
|
|
2066
|
-
objectKind: value.objectKind,
|
|
2067
|
-
stableType: value.stableType,
|
|
2068
|
-
count: 0
|
|
2069
|
-
});
|
|
2070
|
-
return {
|
|
2071
|
-
...value,
|
|
2072
|
-
active: capacity.active.spotTypes[key] ?? 0,
|
|
2073
|
-
reserved: capacity.pending.spotTypes[key] ?? 0
|
|
2074
|
-
};
|
|
2075
|
-
})
|
|
2076
|
-
}
|
|
2343
|
+
populationCapacity: projectCapacity(descriptor.populationCapacity, capacity)
|
|
2077
2344
|
};
|
|
2078
2345
|
})
|
|
2079
2346
|
);
|
|
@@ -2087,6 +2354,16 @@ export class ZLinkLocationStoreRepository extends ZLinkInMemoryLocationStore {
|
|
|
2087
2354
|
descriptor: ZLinkClientServerServerDescriptor,
|
|
2088
2355
|
intent: ZLinkLocationWriteIntent,
|
|
2089
2356
|
signal?: AbortSignal
|
|
2357
|
+
): Promise<ZLinkLocationWriteResult> {
|
|
2358
|
+
return this.observeStore('compare_exchange', () =>
|
|
2359
|
+
this.updateClientServerRequest(descriptor, intent, signal)
|
|
2360
|
+
);
|
|
2361
|
+
}
|
|
2362
|
+
|
|
2363
|
+
private async updateClientServerRequest(
|
|
2364
|
+
descriptor: ZLinkClientServerServerDescriptor,
|
|
2365
|
+
intent: ZLinkLocationWriteIntent,
|
|
2366
|
+
signal?: AbortSignal
|
|
2090
2367
|
): Promise<ZLinkLocationWriteResult> {
|
|
2091
2368
|
validateClientServerDescriptor(descriptor);
|
|
2092
2369
|
const normalized = reviveClientServerDescriptor(descriptor);
|
|
@@ -2105,6 +2382,14 @@ export class ZLinkLocationStoreRepository extends ZLinkInMemoryLocationStore {
|
|
|
2105
2382
|
key: ZLinkClientServerServerDescriptorKey,
|
|
2106
2383
|
owner: ZLinkLocationOwnerToken,
|
|
2107
2384
|
signal?: AbortSignal
|
|
2385
|
+
): Promise<ZLinkLocationWriteStatus> {
|
|
2386
|
+
return this.observeStore('release', () => this.removeClientServerRequest(key, owner, signal));
|
|
2387
|
+
}
|
|
2388
|
+
|
|
2389
|
+
private async removeClientServerRequest(
|
|
2390
|
+
key: ZLinkClientServerServerDescriptorKey,
|
|
2391
|
+
owner: ZLinkLocationOwnerToken,
|
|
2392
|
+
signal?: AbortSignal
|
|
2108
2393
|
): Promise<ZLinkLocationWriteStatus> {
|
|
2109
2394
|
return this.removeDescriptor(
|
|
2110
2395
|
clientServerKey(key.channelName, key.serverRid),
|
|
@@ -2118,6 +2403,16 @@ export class ZLinkLocationStoreRepository extends ZLinkInMemoryLocationStore {
|
|
|
2118
2403
|
channelName: string,
|
|
2119
2404
|
page: ZLinkPageRequest = {},
|
|
2120
2405
|
signal?: AbortSignal
|
|
2406
|
+
): Promise<ZLinkLocationPage<ZLinkClientServerServerDescriptor>> {
|
|
2407
|
+
return this.observeStore('read', () =>
|
|
2408
|
+
this.listClientServersRequest(channelName, page, signal)
|
|
2409
|
+
);
|
|
2410
|
+
}
|
|
2411
|
+
|
|
2412
|
+
private async listClientServersRequest(
|
|
2413
|
+
channelName: string,
|
|
2414
|
+
page: ZLinkPageRequest = {},
|
|
2415
|
+
signal?: AbortSignal
|
|
2121
2416
|
): Promise<ZLinkLocationPage<ZLinkClientServerServerDescriptor>> {
|
|
2122
2417
|
return this.listDescriptors(
|
|
2123
2418
|
clientServerPrefix(channelName),
|
|
@@ -2131,6 +2426,16 @@ export class ZLinkLocationStoreRepository extends ZLinkInMemoryLocationStore {
|
|
|
2131
2426
|
descriptor: ZLinkFanoutPublisherDescriptor,
|
|
2132
2427
|
intent: ZLinkLocationWriteIntent,
|
|
2133
2428
|
signal?: AbortSignal
|
|
2429
|
+
): Promise<ZLinkLocationWriteResult> {
|
|
2430
|
+
return this.observeStore('compare_exchange', () =>
|
|
2431
|
+
this.updateFanoutPublisherRequest(descriptor, intent, signal)
|
|
2432
|
+
);
|
|
2433
|
+
}
|
|
2434
|
+
|
|
2435
|
+
private async updateFanoutPublisherRequest(
|
|
2436
|
+
descriptor: ZLinkFanoutPublisherDescriptor,
|
|
2437
|
+
intent: ZLinkLocationWriteIntent,
|
|
2438
|
+
signal?: AbortSignal
|
|
2134
2439
|
): Promise<ZLinkLocationWriteResult> {
|
|
2135
2440
|
validateFanoutPublisherDescriptor(descriptor);
|
|
2136
2441
|
const normalized = reviveFanoutDescriptor(descriptor);
|
|
@@ -2149,6 +2454,16 @@ export class ZLinkLocationStoreRepository extends ZLinkInMemoryLocationStore {
|
|
|
2149
2454
|
key: ZLinkFanoutPublisherDescriptorKey,
|
|
2150
2455
|
owner: ZLinkLocationOwnerToken,
|
|
2151
2456
|
signal?: AbortSignal
|
|
2457
|
+
): Promise<ZLinkLocationWriteStatus> {
|
|
2458
|
+
return this.observeStore('release', () =>
|
|
2459
|
+
this.removeFanoutPublisherRequest(key, owner, signal)
|
|
2460
|
+
);
|
|
2461
|
+
}
|
|
2462
|
+
|
|
2463
|
+
private async removeFanoutPublisherRequest(
|
|
2464
|
+
key: ZLinkFanoutPublisherDescriptorKey,
|
|
2465
|
+
owner: ZLinkLocationOwnerToken,
|
|
2466
|
+
signal?: AbortSignal
|
|
2152
2467
|
): Promise<ZLinkLocationWriteStatus> {
|
|
2153
2468
|
return this.removeDescriptor(
|
|
2154
2469
|
fanoutKey(key.channelName, key.publisherRid),
|
|
@@ -2162,6 +2477,16 @@ export class ZLinkLocationStoreRepository extends ZLinkInMemoryLocationStore {
|
|
|
2162
2477
|
channelName: string,
|
|
2163
2478
|
page: ZLinkPageRequest = {},
|
|
2164
2479
|
signal?: AbortSignal
|
|
2480
|
+
): Promise<ZLinkLocationPage<ZLinkFanoutPublisherDescriptor>> {
|
|
2481
|
+
return this.observeStore('read', () =>
|
|
2482
|
+
this.listFanoutPublishersRequest(channelName, page, signal)
|
|
2483
|
+
);
|
|
2484
|
+
}
|
|
2485
|
+
|
|
2486
|
+
private async listFanoutPublishersRequest(
|
|
2487
|
+
channelName: string,
|
|
2488
|
+
page: ZLinkPageRequest = {},
|
|
2489
|
+
signal?: AbortSignal
|
|
2165
2490
|
): Promise<ZLinkLocationPage<ZLinkFanoutPublisherDescriptor>> {
|
|
2166
2491
|
return this.listDescriptors(fanoutPrefix(channelName), page, reviveFanoutDescriptor, signal);
|
|
2167
2492
|
}
|
|
@@ -2170,6 +2495,16 @@ export class ZLinkLocationStoreRepository extends ZLinkInMemoryLocationStore {
|
|
|
2170
2495
|
location: ZLinkSpotLocation,
|
|
2171
2496
|
intent: ZLinkLocationWriteIntent,
|
|
2172
2497
|
signal?: AbortSignal
|
|
2498
|
+
): Promise<ZLinkLocationWriteResult> {
|
|
2499
|
+
return this.observeStore('compare_exchange', () =>
|
|
2500
|
+
this.updateSpotRequest(location, intent, signal)
|
|
2501
|
+
);
|
|
2502
|
+
}
|
|
2503
|
+
|
|
2504
|
+
private async updateSpotRequest(
|
|
2505
|
+
location: ZLinkSpotLocation,
|
|
2506
|
+
intent: ZLinkLocationWriteIntent,
|
|
2507
|
+
signal?: AbortSignal
|
|
2173
2508
|
): Promise<ZLinkLocationWriteResult> {
|
|
2174
2509
|
return this.updateOwnedLocation(
|
|
2175
2510
|
spotKey(location.meshName, String(location.spotId)),
|
|
@@ -2183,6 +2518,14 @@ export class ZLinkLocationStoreRepository extends ZLinkInMemoryLocationStore {
|
|
|
2183
2518
|
key: ZLinkSpotLocationKey,
|
|
2184
2519
|
owner: ZLinkLocationOwnerToken,
|
|
2185
2520
|
signal?: AbortSignal
|
|
2521
|
+
): Promise<ZLinkLocationWriteStatus> {
|
|
2522
|
+
return this.observeStore('release', () => this.removeSpotRequest(key, owner, signal));
|
|
2523
|
+
}
|
|
2524
|
+
|
|
2525
|
+
private async removeSpotRequest(
|
|
2526
|
+
key: ZLinkSpotLocationKey,
|
|
2527
|
+
owner: ZLinkLocationOwnerToken,
|
|
2528
|
+
signal?: AbortSignal
|
|
2186
2529
|
): Promise<ZLinkLocationWriteStatus> {
|
|
2187
2530
|
return this.removeOwnedLocation(spotKey(key.meshName, String(key.spotId)), owner, signal);
|
|
2188
2531
|
}
|
|
@@ -2190,6 +2533,13 @@ export class ZLinkLocationStoreRepository extends ZLinkInMemoryLocationStore {
|
|
|
2190
2533
|
override async resolveSpot(
|
|
2191
2534
|
key: ZLinkSpotLocationKey,
|
|
2192
2535
|
signal?: AbortSignal
|
|
2536
|
+
): Promise<ZLinkSpotLocation | undefined> {
|
|
2537
|
+
return this.observeStore('read', () => this.resolveSpotRequest(key, signal));
|
|
2538
|
+
}
|
|
2539
|
+
|
|
2540
|
+
private async resolveSpotRequest(
|
|
2541
|
+
key: ZLinkSpotLocationKey,
|
|
2542
|
+
signal?: AbortSignal
|
|
2193
2543
|
): Promise<ZLinkSpotLocation | undefined> {
|
|
2194
2544
|
const value = await this.readOwnedLocation<ZLinkSpotLocation>(
|
|
2195
2545
|
spotKey(key.meshName, String(key.spotId)),
|
|
@@ -2202,6 +2552,14 @@ export class ZLinkLocationStoreRepository extends ZLinkInMemoryLocationStore {
|
|
|
2202
2552
|
filter: ZLinkSpotLocationFilter,
|
|
2203
2553
|
page: ZLinkPageRequest = {},
|
|
2204
2554
|
signal?: AbortSignal
|
|
2555
|
+
): Promise<ZLinkLocationPage<ZLinkSpotLocation>> {
|
|
2556
|
+
return this.observeStore('read', () => this.listSpotsRequest(filter, page, signal));
|
|
2557
|
+
}
|
|
2558
|
+
|
|
2559
|
+
private async listSpotsRequest(
|
|
2560
|
+
filter: ZLinkSpotLocationFilter,
|
|
2561
|
+
page: ZLinkPageRequest = {},
|
|
2562
|
+
signal?: AbortSignal
|
|
2205
2563
|
): Promise<ZLinkLocationPage<ZLinkSpotLocation>> {
|
|
2206
2564
|
return this.listOwnedLocations(
|
|
2207
2565
|
`${PREFIX}spot:`,
|
|
@@ -2216,6 +2574,16 @@ export class ZLinkLocationStoreRepository extends ZLinkInMemoryLocationStore {
|
|
|
2216
2574
|
location: ZLinkActorLocation,
|
|
2217
2575
|
intent: ZLinkLocationWriteIntent,
|
|
2218
2576
|
signal?: AbortSignal
|
|
2577
|
+
): Promise<ZLinkLocationWriteResult> {
|
|
2578
|
+
return this.observeStore('compare_exchange', () =>
|
|
2579
|
+
this.updateActorRequest(location, intent, signal)
|
|
2580
|
+
);
|
|
2581
|
+
}
|
|
2582
|
+
|
|
2583
|
+
private async updateActorRequest(
|
|
2584
|
+
location: ZLinkActorLocation,
|
|
2585
|
+
intent: ZLinkLocationWriteIntent,
|
|
2586
|
+
signal?: AbortSignal
|
|
2219
2587
|
): Promise<ZLinkLocationWriteResult> {
|
|
2220
2588
|
return this.updateOwnedLocation(
|
|
2221
2589
|
actorKey(location.meshName, location.actorId),
|
|
@@ -2230,6 +2598,14 @@ export class ZLinkLocationStoreRepository extends ZLinkInMemoryLocationStore {
|
|
|
2230
2598
|
key: ZLinkActorLocationKey,
|
|
2231
2599
|
owner: ZLinkLocationOwnerToken,
|
|
2232
2600
|
signal?: AbortSignal
|
|
2601
|
+
): Promise<ZLinkLocationWriteStatus> {
|
|
2602
|
+
return this.observeStore('release', () => this.removeActorRequest(key, owner, signal));
|
|
2603
|
+
}
|
|
2604
|
+
|
|
2605
|
+
private async removeActorRequest(
|
|
2606
|
+
key: ZLinkActorLocationKey,
|
|
2607
|
+
owner: ZLinkLocationOwnerToken,
|
|
2608
|
+
signal?: AbortSignal
|
|
2233
2609
|
): Promise<ZLinkLocationWriteStatus> {
|
|
2234
2610
|
return this.removeOwnedLocation(actorKey(key.meshName, key.actorId), owner, signal);
|
|
2235
2611
|
}
|
|
@@ -2237,6 +2613,13 @@ export class ZLinkLocationStoreRepository extends ZLinkInMemoryLocationStore {
|
|
|
2237
2613
|
override async resolveActor(
|
|
2238
2614
|
key: ZLinkActorLocationKey,
|
|
2239
2615
|
signal?: AbortSignal
|
|
2616
|
+
): Promise<ZLinkActorLocation | undefined> {
|
|
2617
|
+
return this.observeStore('read', () => this.resolveActorRequest(key, signal));
|
|
2618
|
+
}
|
|
2619
|
+
|
|
2620
|
+
private async resolveActorRequest(
|
|
2621
|
+
key: ZLinkActorLocationKey,
|
|
2622
|
+
signal?: AbortSignal
|
|
2240
2623
|
): Promise<ZLinkActorLocation | undefined> {
|
|
2241
2624
|
const value = await this.readOwnedLocation<ZLinkActorLocation>(
|
|
2242
2625
|
actorKey(key.meshName, key.actorId),
|
|
@@ -2249,6 +2632,14 @@ export class ZLinkLocationStoreRepository extends ZLinkInMemoryLocationStore {
|
|
|
2249
2632
|
filter: ZLinkActorLocationFilter,
|
|
2250
2633
|
page: ZLinkPageRequest = {},
|
|
2251
2634
|
signal?: AbortSignal
|
|
2635
|
+
): Promise<ZLinkLocationPage<ZLinkActorLocation>> {
|
|
2636
|
+
return this.observeStore('read', () => this.listActorsRequest(filter, page, signal));
|
|
2637
|
+
}
|
|
2638
|
+
|
|
2639
|
+
private async listActorsRequest(
|
|
2640
|
+
filter: ZLinkActorLocationFilter,
|
|
2641
|
+
page: ZLinkPageRequest = {},
|
|
2642
|
+
signal?: AbortSignal
|
|
2252
2643
|
): Promise<ZLinkLocationPage<ZLinkActorLocation>> {
|
|
2253
2644
|
return this.listOwnedLocations(
|
|
2254
2645
|
`${PREFIX}actor:`,
|
|
@@ -2263,6 +2654,16 @@ export class ZLinkLocationStoreRepository extends ZLinkInMemoryLocationStore {
|
|
|
2263
2654
|
location: ZLinkRouteLocation,
|
|
2264
2655
|
intent: ZLinkLocationWriteIntent,
|
|
2265
2656
|
signal?: AbortSignal
|
|
2657
|
+
): Promise<ZLinkLocationWriteResult> {
|
|
2658
|
+
return this.observeStore('compare_exchange', () =>
|
|
2659
|
+
this.updateRouteRequest(location, intent, signal)
|
|
2660
|
+
);
|
|
2661
|
+
}
|
|
2662
|
+
|
|
2663
|
+
private async updateRouteRequest(
|
|
2664
|
+
location: ZLinkRouteLocation,
|
|
2665
|
+
intent: ZLinkLocationWriteIntent,
|
|
2666
|
+
signal?: AbortSignal
|
|
2266
2667
|
): Promise<ZLinkLocationWriteResult> {
|
|
2267
2668
|
const rowKey = routeKey(String(location.routeKind), location.routeKey);
|
|
2268
2669
|
const normalized = normalizeRoute(location);
|
|
@@ -2324,6 +2725,14 @@ export class ZLinkLocationStoreRepository extends ZLinkInMemoryLocationStore {
|
|
|
2324
2725
|
key: ZLinkRouteLocationKey,
|
|
2325
2726
|
owner: ZLinkLocationOwnerToken,
|
|
2326
2727
|
signal?: AbortSignal
|
|
2728
|
+
): Promise<ZLinkLocationWriteResult> {
|
|
2729
|
+
return this.observeStore('release', () => this.removeRouteRequest(key, owner, signal));
|
|
2730
|
+
}
|
|
2731
|
+
|
|
2732
|
+
private async removeRouteRequest(
|
|
2733
|
+
key: ZLinkRouteLocationKey,
|
|
2734
|
+
owner: ZLinkLocationOwnerToken,
|
|
2735
|
+
signal?: AbortSignal
|
|
2327
2736
|
): Promise<ZLinkLocationWriteResult> {
|
|
2328
2737
|
const rowKey = routeKey(String(key.routeKind), key.routeKey);
|
|
2329
2738
|
const current = await this.provider.read(rowKey, signal);
|
|
@@ -2358,6 +2767,13 @@ export class ZLinkLocationStoreRepository extends ZLinkInMemoryLocationStore {
|
|
|
2358
2767
|
override async resolveRoute(
|
|
2359
2768
|
key: ZLinkRouteLocationKey,
|
|
2360
2769
|
signal?: AbortSignal
|
|
2770
|
+
): Promise<ZLinkRouteLocation | undefined> {
|
|
2771
|
+
return this.observeStore('read', () => this.resolveRouteRequest(key, signal));
|
|
2772
|
+
}
|
|
2773
|
+
|
|
2774
|
+
private async resolveRouteRequest(
|
|
2775
|
+
key: ZLinkRouteLocationKey,
|
|
2776
|
+
signal?: AbortSignal
|
|
2361
2777
|
): Promise<ZLinkRouteLocation | undefined> {
|
|
2362
2778
|
const value = await this.readOwnedLocation<ZLinkRouteLocation>(
|
|
2363
2779
|
routeKey(String(key.routeKind), key.routeKey),
|
|
@@ -2370,6 +2786,14 @@ export class ZLinkLocationStoreRepository extends ZLinkInMemoryLocationStore {
|
|
|
2370
2786
|
filter: ZLinkRouteLocationFilter,
|
|
2371
2787
|
page: ZLinkPageRequest = {},
|
|
2372
2788
|
signal?: AbortSignal
|
|
2789
|
+
): Promise<ZLinkLocationPage<ZLinkRouteLocation>> {
|
|
2790
|
+
return this.observeStore('read', () => this.listRoutesRequest(filter, page, signal));
|
|
2791
|
+
}
|
|
2792
|
+
|
|
2793
|
+
private async listRoutesRequest(
|
|
2794
|
+
filter: ZLinkRouteLocationFilter,
|
|
2795
|
+
page: ZLinkPageRequest = {},
|
|
2796
|
+
signal?: AbortSignal
|
|
2373
2797
|
): Promise<ZLinkLocationPage<ZLinkRouteLocation>> {
|
|
2374
2798
|
return this.listOwnedLocations(
|
|
2375
2799
|
`${PREFIX}route:`,
|
|
@@ -2383,6 +2807,13 @@ export class ZLinkLocationStoreRepository extends ZLinkInMemoryLocationStore {
|
|
|
2383
2807
|
override async removeAllByOwner(
|
|
2384
2808
|
owner: ZLinkLocationOwnerToken,
|
|
2385
2809
|
signal?: AbortSignal
|
|
2810
|
+
): Promise<bigint> {
|
|
2811
|
+
return this.observeStore('release', () => this.removeAllByOwnerRequest(owner, signal));
|
|
2812
|
+
}
|
|
2813
|
+
|
|
2814
|
+
private async removeAllByOwnerRequest(
|
|
2815
|
+
owner: ZLinkLocationOwnerToken,
|
|
2816
|
+
signal?: AbortSignal
|
|
2386
2817
|
): Promise<bigint> {
|
|
2387
2818
|
const leaseKey = ownerKey(owner.ownerId);
|
|
2388
2819
|
const lease = await this.provider.read(leaseKey, signal);
|
|
@@ -2484,7 +2915,7 @@ export class ZLinkLocationStoreRepository extends ZLinkInMemoryLocationStore {
|
|
|
2484
2915
|
const encodedAuthority = authorityContractValueFromPreimage(candidate.key.value);
|
|
2485
2916
|
const identity = decodeAuthorityKey({ value: encodedAuthority } as ZLinkAuthorityKey);
|
|
2486
2917
|
if (record.snapshot.allocation.state === 'active') {
|
|
2487
|
-
const result = await this.
|
|
2918
|
+
const result = await this.compareExchangeAuthorityRequest(
|
|
2488
2919
|
{ value: encodedAuthority } as ZLinkAuthorityKey,
|
|
2489
2920
|
current.value.version as unknown as ZLinkAuthorityStoreVersion,
|
|
2490
2921
|
{ kind: 'delete' },
|
|
@@ -2495,7 +2926,7 @@ export class ZLinkLocationStoreRepository extends ZLinkInMemoryLocationStore {
|
|
|
2495
2926
|
}
|
|
2496
2927
|
const reservationId = record.snapshot.pendingCreation?.reservationId;
|
|
2497
2928
|
if (reservationId === undefined) continue;
|
|
2498
|
-
const aborted = await this.
|
|
2929
|
+
const aborted = await this.abortRequest(
|
|
2499
2930
|
{
|
|
2500
2931
|
key: identity,
|
|
2501
2932
|
reservationId,
|
|
@@ -2682,13 +3113,27 @@ export class ZLinkLocationStoreRepository extends ZLinkInMemoryLocationStore {
|
|
|
2682
3113
|
currentRow.kind === 'found'
|
|
2683
3114
|
? { kind: 'version', key: rowKey, expected: currentRow.value.version }
|
|
2684
3115
|
: { kind: 'missing', key: rowKey };
|
|
2685
|
-
|
|
2686
|
-
|
|
2687
|
-
|
|
2688
|
-
|
|
2689
|
-
|
|
2690
|
-
|
|
2691
|
-
|
|
3116
|
+
let result: Awaited<ReturnType<ZLinkLocationStore['write']>>;
|
|
3117
|
+
try {
|
|
3118
|
+
result = await this.provider.write(
|
|
3119
|
+
{
|
|
3120
|
+
conditions: [leaseValueCondition(leaseKey, { ownerId, leaseGeneration }), rowCondition],
|
|
3121
|
+
mutations: [{ kind: 'put', key: rowKey, bytes: encodedDescriptor }]
|
|
3122
|
+
},
|
|
3123
|
+
signal
|
|
3124
|
+
);
|
|
3125
|
+
} catch (failure) {
|
|
3126
|
+
// Location runtime §10: the Store may have applied a write whose result
|
|
3127
|
+
// was lost. Re-read the same key; the same bytes confirm the write.
|
|
3128
|
+
const confirmed = await this.provider.read(rowKey, signal).catch(() => undefined);
|
|
3129
|
+
if (
|
|
3130
|
+
confirmed?.kind === 'found' &&
|
|
3131
|
+
Buffer.from(confirmed.value.bytes).equals(Buffer.from(encodedDescriptor))
|
|
3132
|
+
) {
|
|
3133
|
+
return { status: WriteStatus.Stored, generation, updatedAt: confirmed.value.storeNow };
|
|
3134
|
+
}
|
|
3135
|
+
throw failure;
|
|
3136
|
+
}
|
|
2692
3137
|
if (result.kind === 'applied') {
|
|
2693
3138
|
return { status: WriteStatus.Stored, generation, updatedAt: result.storeNow };
|
|
2694
3139
|
}
|
|
@@ -3737,6 +4182,12 @@ function reviveCanonical(value: unknown, key = ''): unknown {
|
|
|
3737
4182
|
return value;
|
|
3738
4183
|
}
|
|
3739
4184
|
|
|
4185
|
+
function requireOwnerLeaseExpiry(value: ZLinkStoreValue): Date {
|
|
4186
|
+
if (value.expiresAt === undefined)
|
|
4187
|
+
throw new Error('Location Store owner lease record is invalid.');
|
|
4188
|
+
return value.expiresAt;
|
|
4189
|
+
}
|
|
4190
|
+
|
|
3740
4191
|
function decodeOwnerRecord(bytes: Uint8Array): OwnerRecord {
|
|
3741
4192
|
const record = decodeJson<OwnerRecord>(bytes);
|
|
3742
4193
|
requireRecordVersion(record, 'owner lease');
|
|
@@ -4196,21 +4647,22 @@ function liveTargetDescriptor(
|
|
|
4196
4647
|
readonly owner: ZLinkLocationOwnerToken;
|
|
4197
4648
|
}
|
|
4198
4649
|
): ZLinkMeshNodeDescriptor | undefined {
|
|
4199
|
-
if (
|
|
4650
|
+
if (leaseRead.kind === 'missing') return undefined;
|
|
4651
|
+
const leaseExpiresAt = requireOwnerLeaseExpiry(leaseRead.value);
|
|
4652
|
+
if (descriptorRead.kind === 'missing') return undefined;
|
|
4200
4653
|
const descriptor = reviveMeshDescriptor(
|
|
4201
4654
|
decodeCanonicalDescriptorRecord<ZLinkMeshNodeDescriptor>(descriptorRead.value.bytes).descriptor
|
|
4202
4655
|
);
|
|
4203
4656
|
const lease = decodeOwnerRecord(leaseRead.value.bytes);
|
|
4204
4657
|
return descriptor.meshName === target.meshName &&
|
|
4205
|
-
|
|
4658
|
+
routingIdsEqual(descriptor.rid, toBackendRoutingId(target.nodeRid)) &&
|
|
4206
4659
|
descriptor.lifecycleGeneration === target.nodeLifecycleGeneration &&
|
|
4207
4660
|
descriptor.ownerId === target.owner.ownerId &&
|
|
4208
4661
|
descriptor.leaseGeneration === target.owner.leaseGeneration &&
|
|
4209
4662
|
descriptor.objectRole === ZLinkObjectRole.Server &&
|
|
4210
4663
|
lease.ownerId === target.owner.ownerId &&
|
|
4211
4664
|
BigInt(lease.leaseGeneration) === target.owner.leaseGeneration &&
|
|
4212
|
-
leaseRead.value.
|
|
4213
|
-
leaseRead.value.expiresAt.getTime() > leaseRead.value.storeNow.getTime()
|
|
4665
|
+
leaseExpiresAt.getTime() > leaseRead.value.storeNow.getTime()
|
|
4214
4666
|
? descriptor
|
|
4215
4667
|
: undefined;
|
|
4216
4668
|
}
|
|
@@ -4337,7 +4789,7 @@ function sameCreationTarget(
|
|
|
4337
4789
|
): boolean {
|
|
4338
4790
|
return (
|
|
4339
4791
|
snapshot.allocation.descriptor.meshName === target.meshName &&
|
|
4340
|
-
|
|
4792
|
+
routingIdsEqual(snapshot.allocation.descriptor.rid, target.nodeRid) &&
|
|
4341
4793
|
snapshot.allocation.descriptorLifecycleGeneration === target.nodeLifecycleGeneration &&
|
|
4342
4794
|
snapshot.ownerId === target.owner.ownerId &&
|
|
4343
4795
|
snapshot.ownerLeaseGeneration === target.owner.leaseGeneration
|
|
@@ -4360,10 +4812,7 @@ function matchesLiveOwnerLease(
|
|
|
4360
4812
|
ownerId: string,
|
|
4361
4813
|
leaseGeneration: bigint
|
|
4362
4814
|
): boolean {
|
|
4363
|
-
if (
|
|
4364
|
-
lease.value.expiresAt === undefined ||
|
|
4365
|
-
lease.value.expiresAt.getTime() <= lease.value.storeNow.getTime()
|
|
4366
|
-
) {
|
|
4815
|
+
if (requireOwnerLeaseExpiry(lease.value).getTime() <= lease.value.storeNow.getTime()) {
|
|
4367
4816
|
return false;
|
|
4368
4817
|
}
|
|
4369
4818
|
const owner = decodeOwnerRecord(lease.value.bytes);
|
|
@@ -4381,11 +4830,8 @@ function sameDescriptorPredecessor(
|
|
|
4381
4830
|
}
|
|
4382
4831
|
|
|
4383
4832
|
function liveOwnerLeaseGeneration(lease: ZLinkStoreReadResult): bigint | undefined {
|
|
4384
|
-
if (
|
|
4385
|
-
|
|
4386
|
-
lease.value.expiresAt === undefined ||
|
|
4387
|
-
lease.value.expiresAt.getTime() <= lease.value.storeNow.getTime()
|
|
4388
|
-
) {
|
|
4833
|
+
if (lease.kind === 'missing') return undefined;
|
|
4834
|
+
if (requireOwnerLeaseExpiry(lease.value).getTime() <= lease.value.storeNow.getTime()) {
|
|
4389
4835
|
return undefined;
|
|
4390
4836
|
}
|
|
4391
4837
|
return BigInt(decodeOwnerRecord(lease.value.bytes).leaseGeneration);
|
|
@@ -4415,10 +4861,6 @@ function canTakeOverStoredLocation(
|
|
|
4415
4861
|
);
|
|
4416
4862
|
}
|
|
4417
4863
|
|
|
4418
|
-
function persistMeshDescriptor(descriptor: ZLinkMeshNodeDescriptor): ZLinkMeshNodeDescriptor {
|
|
4419
|
-
return descriptor;
|
|
4420
|
-
}
|
|
4421
|
-
|
|
4422
4864
|
function reviveMeshDescriptor(descriptor: ZLinkMeshNodeDescriptor): ZLinkMeshNodeDescriptor {
|
|
4423
4865
|
const value = descriptor as unknown as Record<string, unknown>;
|
|
4424
4866
|
if ('routingIdHex' in value) {
|
|
@@ -4550,7 +4992,7 @@ function matchesSpot(value: ZLinkSpotLocation, filter: ZLinkSpotLocationFilter):
|
|
|
4550
4992
|
return (
|
|
4551
4993
|
(filter.meshName === undefined || value.meshName === filter.meshName) &&
|
|
4552
4994
|
(filter.spotType === undefined || value.spotType === filter.spotType) &&
|
|
4553
|
-
(filter.nodeRid === undefined ||
|
|
4995
|
+
(filter.nodeRid === undefined || routingIdsEqual(value.ownerNodeRid, filter.nodeRid)) &&
|
|
4554
4996
|
(filter.spotKind === undefined || value.spotKind === filter.spotKind)
|
|
4555
4997
|
);
|
|
4556
4998
|
}
|
|
@@ -4558,7 +5000,7 @@ function matchesSpot(value: ZLinkSpotLocation, filter: ZLinkSpotLocationFilter):
|
|
|
4558
5000
|
function matchesActor(value: ZLinkActorLocation, filter: ZLinkActorLocationFilter): boolean {
|
|
4559
5001
|
return (
|
|
4560
5002
|
(filter.actorType === undefined || value.actorType === filter.actorType) &&
|
|
4561
|
-
(filter.nodeRid === undefined ||
|
|
5003
|
+
(filter.nodeRid === undefined || routingIdsEqual(value.ownerNodeRid, filter.nodeRid)) &&
|
|
4562
5004
|
(filter.spotId === undefined || String(value.spotId) === String(filter.spotId)) &&
|
|
4563
5005
|
(filter.locationKind === undefined || value.spotKind === filter.locationKind)
|
|
4564
5006
|
);
|
|
@@ -4568,7 +5010,7 @@ function matchesRoute(value: ZLinkRouteLocation, filter: ZLinkRouteLocationFilte
|
|
|
4568
5010
|
return (
|
|
4569
5011
|
(filter.routeKind === undefined || value.routeKind === filter.routeKind) &&
|
|
4570
5012
|
(filter.ownerNodeRid === undefined ||
|
|
4571
|
-
|
|
5013
|
+
routingIdsEqual(value.ownerNodeRid, filter.ownerNodeRid)) &&
|
|
4572
5014
|
(filter.ownerId === undefined || value.ownerId === filter.ownerId)
|
|
4573
5015
|
);
|
|
4574
5016
|
}
|
|
@@ -4589,13 +5031,14 @@ function descriptorOwnerLeaseGeneration(value: OwnedStoreRecord): bigint | undef
|
|
|
4589
5031
|
return undefined;
|
|
4590
5032
|
}
|
|
4591
5033
|
|
|
5034
|
+
// Location runtime §10: a write whose result was lost is confirmed by reading
|
|
5035
|
+
// the same key. The stored row already is this write when it differs only in
|
|
5036
|
+
// the time the Store stamped, as for every other descriptor kind.
|
|
4592
5037
|
function sameMeshDescriptor(
|
|
4593
5038
|
left: ZLinkMeshNodeDescriptor,
|
|
4594
5039
|
right: ZLinkMeshNodeDescriptor
|
|
4595
5040
|
): boolean {
|
|
4596
|
-
return
|
|
4597
|
-
Buffer.from(encodeJson(persistMeshDescriptor(right)))
|
|
4598
|
-
);
|
|
5041
|
+
return descriptorFingerprint(left, ['updatedAt']) === descriptorFingerprint(right, ['updatedAt']);
|
|
4599
5042
|
}
|
|
4600
5043
|
|
|
4601
5044
|
function sameClientServerDescriptor(
|
|
@@ -4740,7 +5183,10 @@ function requireOwnerInput(ownerId: string, leaseTtlMs: number): void {
|
|
|
4740
5183
|
function throwIfOperationExpired(signal?: AbortSignal, deadlineUnixMs?: bigint): void {
|
|
4741
5184
|
signal?.throwIfAborted();
|
|
4742
5185
|
if (deadlineUnixMs !== undefined && Date.now() >= Number(deadlineUnixMs)) {
|
|
4743
|
-
throw new
|
|
5186
|
+
throw new ZLinkFrameworkException(
|
|
5187
|
+
ZLinkFrameworkErrorKind.DeadlineExceeded,
|
|
5188
|
+
'Operation deadline exceeded.'
|
|
5189
|
+
);
|
|
4744
5190
|
}
|
|
4745
5191
|
}
|
|
4746
5192
|
|
|
@@ -4759,3 +5205,33 @@ function locationStoreProviderFailure(error: unknown, signal?: AbortSignal): unk
|
|
|
4759
5205
|
error
|
|
4760
5206
|
);
|
|
4761
5207
|
}
|
|
5208
|
+
|
|
5209
|
+
function projectCapacity(
|
|
5210
|
+
limits: ZLinkMeshNodeDescriptor['populationCapacity'],
|
|
5211
|
+
capacity: CapacityRecord
|
|
5212
|
+
): ZLinkMeshNodeDescriptor['populationCapacity'] {
|
|
5213
|
+
return {
|
|
5214
|
+
actors: {
|
|
5215
|
+
...limits.actors,
|
|
5216
|
+
active: capacity.active.actors,
|
|
5217
|
+
reserved: capacity.pending.actors
|
|
5218
|
+
},
|
|
5219
|
+
spots: {
|
|
5220
|
+
...limits.spots,
|
|
5221
|
+
active: capacity.active.spots,
|
|
5222
|
+
reserved: capacity.pending.spots
|
|
5223
|
+
},
|
|
5224
|
+
spotTypes: limits.spotTypes.map((value) => {
|
|
5225
|
+
const key = capacityTypeKey({
|
|
5226
|
+
objectKind: value.objectKind,
|
|
5227
|
+
stableType: value.stableType,
|
|
5228
|
+
count: 0
|
|
5229
|
+
});
|
|
5230
|
+
return {
|
|
5231
|
+
...value,
|
|
5232
|
+
active: capacity.active.spotTypes[key] ?? 0,
|
|
5233
|
+
reserved: capacity.pending.spotTypes[key] ?? 0
|
|
5234
|
+
};
|
|
5235
|
+
})
|
|
5236
|
+
};
|
|
5237
|
+
}
|