@zlink-systems/framework 0.21.0 → 0.22.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/.tsbuildinfo +1 -1
- package/dist/contracts/Common/ZLinkMessage.js +5 -5
- package/dist/contracts/Configuration/CodecContentType.js +5 -7
- package/dist/contracts/Configuration/DiagnosticsValidation.js +1 -6
- package/dist/contracts/Configuration/EndpointNotation.js +4 -8
- package/dist/contracts/Configuration/Registration.js +14 -11
- package/dist/contracts/Configuration/RegistrationBuilders.js +32 -25
- package/dist/contracts/Configuration/RegistrationNormalizers.js +25 -26
- package/dist/contracts/Configuration/RegistrationValidators.js +36 -38
- package/dist/contracts/Configuration/SendTimeoutValidation.js +4 -4
- package/dist/contracts/Configuration/TimerRegistrationValidator.js +7 -7
- package/dist/contracts/Handlers/JsonContract.js +23 -11
- package/dist/contracts/Spots/SpotKind.js +16 -8
- package/dist/location-store-integration.js +16 -16
- package/dist/nest-integration.js +17 -11
- package/dist/runtime/abort.js +9 -5
- package/dist/runtime/actors/actor-authority-payload-codec.js +12 -16
- package/dist/runtime/actors/actor-authority-publication.js +18 -17
- package/dist/runtime/actors/actor-client.js +83 -63
- package/dist/runtime/actors/actor-context.js +24 -18
- package/dist/runtime/actors/actor-creation.js +4 -3
- package/dist/runtime/actors/actor-handoff.js +89 -92
- package/dist/runtime/actors/actor-local-native-join.js +18 -19
- package/dist/runtime/actors/actor-mailbox.js +1 -1
- package/dist/runtime/actors/actor-message-follow-context.js +24 -21
- package/dist/runtime/actors/actor-packet-relay-wire.js +1 -3
- package/dist/runtime/actors/actor-remote-joiner.js +20 -17
- package/dist/runtime/actors/actor-remote-wire.js +6 -7
- package/dist/runtime/actors/actor-runtime-state.js +87 -81
- package/dist/runtime/actors/actor-transfer-registry.js +3 -5
- package/dist/runtime/actors/bound-session-wire.js +14 -9
- package/dist/runtime/actors/deferred-join-accepted-journal.js +158 -124
- package/dist/runtime/actors/index.js +2 -5
- package/dist/runtime/actors/post-commit-actor-binder.js +3 -6
- package/dist/runtime/actors/post-commit-actor-location.js +1 -1
- package/dist/runtime/actors/spot-actor-dispatch.js +5 -5
- package/dist/runtime/actors/transferred-actor-rollback.js +4 -4
- package/dist/runtime/admission.js +2 -6
- package/dist/runtime/application-jobs/application-ingress-record-owner.js +2 -6
- package/dist/runtime/application-jobs/receive-flow-controller.js +11 -12
- package/dist/runtime/backend/mesh-completion-table.js +1 -3
- package/dist/runtime/backend/mesh-dispatch-pump.js +12 -16
- package/dist/runtime/backend/node/node-backend-adapter-factory.js +1 -3
- package/dist/runtime/backend/node/node-backend-adapter-support.js +26 -17
- package/dist/runtime/backend/node/node-mesh-backend-adapter.js +4 -3
- package/dist/runtime/backend/node/node-raw-binding-port.js +7 -6
- package/dist/runtime/backend/node/node-raw-mesh-backend.js +116 -113
- package/dist/runtime/backend/node/node-socket-backend-adapter.js +12 -13
- package/dist/runtime/backend/runtime-message.js +3 -3
- package/dist/runtime/backend/runtime-values.d.ts +2 -2
- package/dist/runtime/backend/runtime-values.js +4 -5
- package/dist/runtime/channels/channel-clients.js +27 -24
- package/dist/runtime/channels/channel-dispatch-pipeline.js +10 -18
- package/dist/runtime/channels/channel-dispatch-services.js +7 -4
- package/dist/runtime/channels/channel-dispatchers.js +9 -9
- package/dist/runtime/channels/channel-envelope-inspection.js +16 -13
- package/dist/runtime/channels/channel-envelope.js +83 -47
- package/dist/runtime/channels/channel-outbound-operations.js +8 -8
- package/dist/runtime/channels/channel-receive-loops.js +20 -22
- package/dist/runtime/channels/channel-receive-task-tracker.js +1 -1
- package/dist/runtime/channels/channel-runtime-lifecycle.js +61 -56
- package/dist/runtime/channels/channel-runtime-manager.js +18 -9
- package/dist/runtime/channels/channel-socket-registry.js +126 -123
- package/dist/runtime/channels/channel-transports.js +43 -33
- package/dist/runtime/channels/client-server-location-runtime.js +32 -40
- package/dist/runtime/channels/client-server-service-wire.js +29 -22
- package/dist/runtime/channels/dispatch-error-reporter.js +9 -7
- package/dist/runtime/channels/fanout-location-runtime.js +34 -47
- package/dist/runtime/channels/fanout-service-wire.js +3 -5
- package/dist/runtime/channels/local-spot-route-transport.js +7 -1
- package/dist/runtime/channels/route-member-snapshot.js +3 -3
- package/dist/runtime/channels/source-spot-router.js +6 -2
- package/dist/runtime/channels/spot-route-bridge-transport.js +5 -2
- package/dist/runtime/channels/spot-route-dispatch-strategy.js +2 -2
- package/dist/runtime/channels/spot-route-target-resolver.js +6 -6
- package/dist/runtime/diagnostics/index.js +38 -10
- package/dist/runtime/diagnostics/message-flow.js +47 -39
- package/dist/runtime/diagnostics/runtime-metrics.js +18 -9
- package/dist/runtime/diagnostics/runtime-observation-queue.js +8 -10
- package/dist/runtime/diagnostics/topology-runtime-projections.js +17 -10
- package/dist/runtime/execution/index.js +7 -6
- package/dist/runtime/execution/serial-execution-queue.js +12 -18
- package/dist/runtime/execution/state-lane.js +2 -2
- package/dist/runtime/foundation/actor-join-recovery-codec.js +31 -23
- package/dist/runtime/foundation/event-loop-resources.js +4 -4
- package/dist/runtime/foundation/message-follow-suppression-registry.js +4 -4
- package/dist/runtime/foundation/raw-service-mesh-runtime.js +136 -136
- package/dist/runtime/foundation/route-mesh-connection-policy.js +4 -4
- package/dist/runtime/foundation/runtime-state-projections.js +22 -11
- package/dist/runtime/foundation/service-authority-payload-codec.js +13 -15
- package/dist/runtime/foundation/service-discovery-registry.js +35 -33
- package/dist/runtime/foundation/service-instance-activation-recovery-codec.js +20 -22
- package/dist/runtime/foundation/service-liveness-registry.js +16 -12
- package/dist/runtime/foundation/service-maintenance-runtime.js +2 -4
- package/dist/runtime/foundation/service-relocation-aggregate-committer.js +24 -24
- package/dist/runtime/foundation/service-relocation-object-owner.js +6 -6
- package/dist/runtime/foundation/service-relocation-runtime.js +137 -94
- package/dist/runtime/foundation/service-runtime-contracts.js +5 -5
- package/dist/runtime/foundation/service-stateful-registry.js +24 -23
- package/dist/runtime/foundation/service-stateful-runtime.js +416 -438
- package/dist/runtime/foundation/service-stateful-wire-codec.js +95 -98
- package/dist/runtime/foundation/service-topology-registry.js +96 -95
- package/dist/runtime/foundation/service-weighted-selection.js +6 -11
- package/dist/runtime/foundation/service-wire-binary-primitives.js +5 -6
- package/dist/runtime/foundation/service-wire-m6a-codec.js +46 -35
- package/dist/runtime/framework-errors-internal.js +7 -10
- package/dist/runtime/handlers/handler-instance-scope.js +4 -5
- package/dist/runtime/handlers/index.js +3 -1
- package/dist/runtime/host/actor-packet-relay.js +74 -70
- package/dist/runtime/host/actor-placement-coordinator.js +29 -31
- package/dist/runtime/host/actor-runtime-options-factory.js +12 -14
- package/dist/runtime/host/actor-transfer-authority-runtime.js +7 -9
- package/dist/runtime/host/actor-transfer-runtime.js +176 -153
- package/dist/runtime/host/application-job-queue.js +18 -22
- package/dist/runtime/host/bound-session-relay.js +3 -1
- package/dist/runtime/host/channel-runtime-options-factory.js +31 -14
- package/dist/runtime/host/host-capacity-status.js +8 -4
- package/dist/runtime/host/index.js +244 -227
- package/dist/runtime/host/instance-activation-authority.js +93 -96
- package/dist/runtime/host/location-runtime-owner.js +16 -14
- package/dist/runtime/host/mesh-router-resolver.js +11 -13
- package/dist/runtime/host/relocation-direct-transfer.js +10 -9
- package/dist/runtime/host/remote-actor-join-receiver.js +20 -15
- package/dist/runtime/host/remote-actor-packet-target-store.js +18 -22
- package/dist/runtime/host/remote-bound-session-relay.js +97 -73
- package/dist/runtime/host/route-mesh-runtime.js +64 -69
- package/dist/runtime/host/runtime-shutdown.js +1 -2
- package/dist/runtime/host/service-relocation-host-runtime.js +586 -511
- package/dist/runtime/host/spot-address-transport.js +69 -71
- package/dist/runtime/host/spot-runtime-options-factory.js +30 -29
- package/dist/runtime/host/stateful-authority-route-runtime.js +65 -68
- package/dist/runtime/host/user-spot-creation-coordinator.js +61 -67
- package/dist/runtime/locations/actor-location-claims.js +26 -20
- package/dist/runtime/locations/aggregate-inventory-store.js +72 -75
- package/dist/runtime/locations/authority-key-codec.js +7 -7
- package/dist/runtime/locations/auto-connect-loop.js +3 -3
- package/dist/runtime/locations/auto-connect-planner.js +25 -19
- package/dist/runtime/locations/auto-connect-reconciler.js +51 -31
- package/dist/runtime/locations/in-memory-authority-store.js +128 -118
- package/dist/runtime/locations/in-memory-location-store.js +195 -168
- package/dist/runtime/locations/in-memory-provider-location-store.js +8 -10
- package/dist/runtime/locations/key-codec.js +1 -1
- package/dist/runtime/locations/lease-tracker.js +23 -21
- package/dist/runtime/locations/lifecycle.js +4 -5
- package/dist/runtime/locations/location-store-repository.js +368 -324
- package/dist/runtime/locations/opaque-record-key.js +2 -2
- package/dist/runtime/locations/resolvers.js +73 -82
- package/dist/runtime/locations/runtime.js +68 -63
- package/dist/runtime/locations/spot-location-claims.js +39 -35
- package/dist/runtime/messaging/framework-json-v1.js +7 -7
- package/dist/runtime/messaging/packet-name.js +7 -6
- package/dist/runtime/messaging/payload-codec.js +21 -18
- package/dist/runtime/protocol/service_wire_codec.generated.d.ts +30 -2
- package/dist/runtime/protocol/service_wire_codec.generated.js +1671 -234
- package/dist/runtime/routing-id.js +3 -5
- package/dist/runtime/spots/formal-remote-actor-admission-registry.js +35 -31
- package/dist/runtime/spots/formal-remote-actor-transfer-registry.js +1 -2
- package/dist/runtime/spots/index.js +208 -219
- package/dist/runtime/spots/spot-activation-registry.js +15 -14
- package/dist/runtime/spots/spot-activation-state.js +17 -15
- package/dist/runtime/spots/spot-activation.js +33 -16
- package/dist/runtime/spots/spot-actor-admission-coordinator.js +18 -15
- package/dist/runtime/spots/spot-actor-membership.js +1 -3
- package/dist/runtime/spots/spot-actor-packet-dispatch.js +23 -20
- package/dist/runtime/spots/spot-actor-packet-drain.js +12 -10
- package/dist/runtime/spots/spot-actor-packet-relay-dispatch.js +10 -6
- package/dist/runtime/spots/spot-closing.js +3 -7
- package/dist/runtime/spots/spot-context.js +2 -2
- package/dist/runtime/spots/spot-entry-activation.js +13 -14
- package/dist/runtime/spots/spot-handle.js +6 -3
- package/dist/runtime/spots/spot-handler-registry.js +12 -12
- package/dist/runtime/spots/spot-manager-public.js +5 -6
- package/dist/runtime/spots/spot-native-actor-join-admission.js +4 -3
- package/dist/runtime/spots/spot-node-autoconnect.js +15 -18
- package/dist/runtime/spots/spot-node-runtime-manager.js +74 -85
- package/dist/runtime/spots/spot-outbound.js +10 -14
- package/dist/runtime/spots/spot-remote-codec.js +22 -26
- package/dist/runtime/spots/spot-remote-route-codec.js +5 -7
- package/dist/runtime/spots/spot-route-packet-dispatch.js +16 -14
- package/dist/runtime/spots/spot-route-replies.js +4 -6
- package/dist/runtime/spots/spot-routed-actor-admission.js +9 -7
- package/dist/runtime/spots/spot-routed-bound-session-dispatch.js +1 -2
- package/dist/runtime/spots/spot-routed-frame-dispatch.js +5 -5
- package/dist/runtime/spots/spot-routed-spot-packet-dispatch.js +14 -10
- package/dist/runtime/spots/spot-serial-executor.js +5 -8
- package/dist/runtime/spots/spot-serial-turn-executor.js +4 -6
- package/dist/runtime/spots/spot-subscription-dispatch.js +5 -5
- package/dist/runtime/spots/spot-timer.js +25 -29
- package/dist/runtime/streams/actor-session-binding-registry.js +98 -107
- package/dist/runtime/streams/actor-session-lifecycle-coordinator.js +3 -1
- package/dist/runtime/streams/bound-actor-relay-sender.js +18 -16
- package/dist/runtime/streams/bound-session-service.js +8 -9
- package/dist/runtime/streams/index.js +20 -19
- package/dist/runtime/streams/managed-stream.js +32 -30
- package/dist/runtime/streams/native-fallback-bound-session.js +21 -17
- package/dist/runtime/streams/protocol.js +29 -18
- package/dist/runtime/streams/session-actor-coordinator.js +34 -37
- package/dist/runtime/streams/session-context.js +30 -28
- package/dist/runtime/streams/session-provider.js +2 -2
- package/dist/runtime/streams/session-serial-executor.js +1 -2
- package/dist/runtime/streams/stream-frame-factory.js +11 -5
- package/dist/runtime/streams/stream-session-runtime.js +70 -66
- package/dist/runtime/workers/index.js +15 -4
- package/package.json +2 -2
- package/src/contracts/Channels/RouteCalls.ts +6 -1
- package/src/contracts/Common/ZLinkMessage.ts +5 -5
- package/src/contracts/Common/ZLinkMessageMetadata.ts +4 -3
- package/src/contracts/Configuration/Builders.ts +14 -14
- package/src/contracts/Configuration/CodecContentType.ts +8 -10
- package/src/contracts/Configuration/DiagnosticsValidation.ts +1 -6
- package/src/contracts/Configuration/EndpointNotation.ts +11 -11
- package/src/contracts/Configuration/ObjectRoles.ts +1 -3
- package/src/contracts/Configuration/Registration.ts +46 -17
- package/src/contracts/Configuration/RegistrationBuilderPolicy.ts +10 -8
- package/src/contracts/Configuration/RegistrationBuilders.ts +107 -96
- package/src/contracts/Configuration/RegistrationCodecRegistry.ts +9 -3
- package/src/contracts/Configuration/RegistrationNormalizers.ts +116 -84
- package/src/contracts/Configuration/RegistrationTypes.ts +21 -25
- package/src/contracts/Configuration/RegistrationValidators.ts +122 -73
- package/src/contracts/Configuration/RouteChannelInternalState.ts +1 -4
- package/src/contracts/Configuration/RuntimeEndpointConnections.ts +4 -1
- package/src/contracts/Configuration/SendTimeoutValidation.ts +6 -4
- package/src/contracts/Configuration/TimerRegistrationValidator.ts +8 -13
- package/src/contracts/Dispatch/ZLinkDispatchOptions.ts +1 -6
- package/src/contracts/Errors/index.ts +1 -4
- package/src/contracts/Handlers/Attributes.ts +15 -9
- package/src/contracts/Handlers/IZLinkChannelHandlers.ts +24 -4
- package/src/contracts/Handlers/JsonContract.ts +53 -19
- package/src/contracts/Locations/ActorTransfer.ts +1 -5
- package/src/contracts/Locations/Authority.ts +4 -11
- package/src/contracts/Locations/Keys.ts +6 -1
- package/src/contracts/Locations/Options.ts +3 -2
- package/src/contracts/Locations/RelocationStore.ts +1 -4
- package/src/contracts/Locations/Resolvers.ts +5 -5
- package/src/contracts/Locations/RuntimeQuery.ts +6 -2
- package/src/contracts/Locations/Stores.ts +1 -2
- package/src/contracts/Locations/index.ts +2 -8
- package/src/contracts/RouteMesh/Contracts.ts +1 -7
- package/src/contracts/RouteMesh/RuntimeTopology.ts +1 -4
- package/src/contracts/Spots/Contracts.ts +2 -8
- package/src/contracts/Spots/SpotKind.ts +16 -8
- package/src/contracts/Spots/ZLinkSpot.ts +8 -11
- package/src/contracts/Streams/IZLinkSession.ts +0 -1
- package/src/contracts/Streams/IZLinkSessionActor.ts +5 -1
- package/src/contracts/Streams/IZLinkSessionPacketHandler.ts +5 -1
- package/src/internal.ts +5 -4
- package/src/location-store-integration.ts +24 -16
- package/src/nest-integration.ts +40 -25
- package/src/runtime/abort.ts +10 -4
- package/src/runtime/actors/actor-authority-payload-codec.ts +20 -29
- package/src/runtime/actors/actor-authority-publication.ts +92 -77
- package/src/runtime/actors/actor-client.ts +162 -133
- package/src/runtime/actors/actor-context.ts +138 -130
- package/src/runtime/actors/actor-creation.ts +47 -44
- package/src/runtime/actors/actor-execution-context.ts +6 -4
- package/src/runtime/actors/actor-handoff.ts +269 -293
- package/src/runtime/actors/actor-join-deferred-scope.ts +5 -4
- package/src/runtime/actors/actor-lifecycle-snapshot.ts +5 -8
- package/src/runtime/actors/actor-local-native-join.ts +131 -159
- package/src/runtime/actors/actor-mailbox.ts +16 -19
- package/src/runtime/actors/actor-message-follow-context.ts +46 -36
- package/src/runtime/actors/actor-packet-relay-wire.ts +32 -21
- package/src/runtime/actors/actor-remote-joiner.ts +50 -54
- package/src/runtime/actors/actor-remote-wire.ts +9 -13
- package/src/runtime/actors/actor-routed-join-transport.ts +10 -2
- package/src/runtime/actors/actor-runtime-contracts.ts +2 -5
- package/src/runtime/actors/actor-runtime-state.ts +127 -124
- package/src/runtime/actors/actor-transfer-registry.ts +9 -14
- package/src/runtime/actors/actor-transport-delivery-gate.ts +4 -6
- package/src/runtime/actors/bound-session-wire.ts +37 -17
- package/src/runtime/actors/deferred-join-accepted-journal.ts +351 -320
- package/src/runtime/actors/index.ts +43 -86
- package/src/runtime/actors/post-commit-actor-binder.ts +10 -10
- package/src/runtime/actors/post-commit-actor-location.ts +30 -23
- package/src/runtime/actors/spot-actor-dispatch.ts +78 -53
- package/src/runtime/actors/transferred-actor-rollback.ts +18 -13
- package/src/runtime/admission.ts +9 -9
- package/src/runtime/application-jobs/application-ingress-record-owner.ts +5 -15
- package/src/runtime/application-jobs/application-job-queue-handler-start-gate.ts +3 -2
- package/src/runtime/application-jobs/receive-flow-controller.ts +17 -14
- package/src/runtime/backend/contracts/index.ts +73 -52
- package/src/runtime/backend/mesh-actor-session-node-adapter.ts +4 -14
- package/src/runtime/backend/mesh-completion-table.ts +6 -9
- package/src/runtime/backend/mesh-dispatch-pump.ts +38 -30
- package/src/runtime/backend/node/node-backend-adapter-factory.ts +23 -21
- package/src/runtime/backend/node/node-backend-adapter-support.ts +36 -22
- package/src/runtime/backend/node/node-dealer-channel-client-transport.ts +59 -58
- package/src/runtime/backend/node/node-event-loop-poller.ts +2 -10
- package/src/runtime/backend/node/node-mesh-backend-adapter.ts +12 -5
- package/src/runtime/backend/node/node-monitor-backend-adapter.ts +4 -3
- package/src/runtime/backend/node/node-raw-binding-port.ts +29 -29
- package/src/runtime/backend/node/node-raw-mesh-backend.ts +335 -383
- package/src/runtime/backend/node/node-socket-backend-adapter.ts +101 -54
- package/src/runtime/backend/runtime-message.ts +5 -3
- package/src/runtime/backend/runtime-values.ts +10 -7
- package/src/runtime/channels/channel-autoconnect.ts +1 -4
- package/src/runtime/channels/channel-clients.ts +93 -73
- package/src/runtime/channels/channel-dispatch-pipeline.ts +40 -42
- package/src/runtime/channels/channel-dispatch-services.ts +51 -49
- package/src/runtime/channels/channel-dispatchers.ts +152 -96
- package/src/runtime/channels/channel-envelope-inspection.ts +20 -16
- package/src/runtime/channels/channel-envelope.ts +256 -150
- package/src/runtime/channels/channel-multipart.ts +13 -5
- package/src/runtime/channels/channel-outbound-operations.ts +37 -41
- package/src/runtime/channels/channel-receive-loops.ts +102 -98
- package/src/runtime/channels/channel-receive-task-tracker.ts +1 -1
- package/src/runtime/channels/channel-runtime-lifecycle.ts +248 -190
- package/src/runtime/channels/channel-runtime-manager.ts +63 -37
- package/src/runtime/channels/channel-socket-options.ts +3 -10
- package/src/runtime/channels/channel-socket-registry.ts +331 -273
- package/src/runtime/channels/channel-transports.ts +215 -197
- package/src/runtime/channels/client-server-location-runtime.ts +116 -100
- package/src/runtime/channels/client-server-service-wire.ts +37 -36
- package/src/runtime/channels/dispatch-error-reporter.ts +11 -8
- package/src/runtime/channels/fanout-location-runtime.ts +91 -94
- package/src/runtime/channels/fanout-service-wire.ts +5 -12
- package/src/runtime/channels/handler-filter-scope.ts +1 -4
- package/src/runtime/channels/index.ts +1 -4
- package/src/runtime/channels/local-spot-route-transport.ts +20 -5
- package/src/runtime/channels/route-member-snapshot.ts +11 -5
- package/src/runtime/channels/router-socket-spot-route-transport.ts +1 -7
- package/src/runtime/channels/source-spot-router.ts +26 -22
- package/src/runtime/channels/spot-direct-envelope.ts +10 -8
- package/src/runtime/channels/spot-node-route-transport.ts +13 -16
- package/src/runtime/channels/spot-route-bridge-transport.ts +26 -9
- package/src/runtime/channels/spot-route-dispatch-strategy.ts +40 -13
- package/src/runtime/channels/spot-route-target-resolver.ts +18 -9
- package/src/runtime/codecs/index.ts +3 -2
- package/src/runtime/diagnostics/flow-context.ts +12 -3
- package/src/runtime/diagnostics/index.ts +96 -61
- package/src/runtime/diagnostics/internal-event-contracts.ts +87 -33
- package/src/runtime/diagnostics/message-flow.ts +95 -76
- package/src/runtime/diagnostics/runtime-metrics.ts +46 -24
- package/src/runtime/diagnostics/runtime-observation-queue.ts +17 -28
- package/src/runtime/diagnostics/topology-runtime-projections.ts +62 -43
- package/src/runtime/execution/index.ts +18 -26
- package/src/runtime/execution/serial-execution-queue.ts +31 -40
- package/src/runtime/execution/state-lane.ts +2 -2
- package/src/runtime/foundation/actor-join-recovery-codec.ts +69 -51
- package/src/runtime/foundation/event-loop-resources.ts +8 -4
- package/src/runtime/foundation/message-follow-suppression-registry.ts +7 -14
- package/src/runtime/foundation/operation-identity.ts +1 -2
- package/src/runtime/foundation/operation-registry.ts +8 -2
- package/src/runtime/foundation/raw-service-mesh-runtime.ts +312 -385
- package/src/runtime/foundation/route-mesh-connection-policy.ts +7 -8
- package/src/runtime/foundation/runtime-state-projections.ts +24 -23
- package/src/runtime/foundation/service-authority-payload-codec.ts +54 -57
- package/src/runtime/foundation/service-discovery-registry.ts +67 -59
- package/src/runtime/foundation/service-instance-activation-recovery-codec.ts +28 -29
- package/src/runtime/foundation/service-liveness-registry.ts +18 -13
- package/src/runtime/foundation/service-mailbox.ts +14 -14
- package/src/runtime/foundation/service-maintenance-runtime.ts +22 -21
- package/src/runtime/foundation/service-metadata-codec.ts +2 -9
- package/src/runtime/foundation/service-relocation-aggregate-committer.ts +39 -36
- package/src/runtime/foundation/service-relocation-coordinator.ts +1 -4
- package/src/runtime/foundation/service-relocation-object-owner.ts +40 -58
- package/src/runtime/foundation/service-relocation-runtime.ts +292 -216
- package/src/runtime/foundation/service-runtime-contracts.ts +8 -8
- package/src/runtime/foundation/service-session-binding-ingress-port.ts +1 -4
- package/src/runtime/foundation/service-stateful-registry.ts +69 -59
- package/src/runtime/foundation/service-stateful-runtime.ts +1174 -1112
- package/src/runtime/foundation/service-stateful-wire-codec.ts +318 -270
- package/src/runtime/foundation/service-topology-registry.ts +157 -159
- package/src/runtime/foundation/service-weighted-selection.ts +9 -15
- package/src/runtime/foundation/service-wire-binary-primitives.ts +6 -12
- package/src/runtime/foundation/service-wire-m6a-codec.ts +69 -47
- package/src/runtime/framework-errors-internal.ts +31 -30
- package/src/runtime/handlers/handler-instance-scope.ts +18 -29
- package/src/runtime/handlers/index.ts +18 -8
- package/src/runtime/host/actor-packet-relay.ts +290 -261
- package/src/runtime/host/actor-placement-coordinator.ts +165 -150
- package/src/runtime/host/actor-runtime-options-factory.ts +89 -87
- package/src/runtime/host/actor-transfer-authority-runtime.ts +46 -38
- package/src/runtime/host/actor-transfer-runtime.ts +391 -395
- package/src/runtime/host/application-job-queue.ts +32 -48
- package/src/runtime/host/bound-session-relay.ts +7 -9
- package/src/runtime/host/channel-runtime-options-factory.ts +75 -35
- package/src/runtime/host/host-capacity-status.ts +10 -9
- package/src/runtime/host/index.ts +861 -789
- package/src/runtime/host/instance-activation-authority.ts +125 -143
- package/src/runtime/host/location-runtime-owner.ts +38 -26
- package/src/runtime/host/mesh-router-resolver.ts +30 -23
- package/src/runtime/host/relocation-direct-transfer.ts +15 -15
- package/src/runtime/host/relocation-integrity-fault-gate.ts +3 -2
- package/src/runtime/host/remote-actor-join-receiver.ts +43 -34
- package/src/runtime/host/remote-actor-packet-target-store.ts +54 -52
- package/src/runtime/host/remote-bound-session-relay.ts +274 -247
- package/src/runtime/host/route-mesh-runtime-options.ts +1 -3
- package/src/runtime/host/route-mesh-runtime.ts +227 -181
- package/src/runtime/host/runtime-shutdown.ts +4 -3
- package/src/runtime/host/service-relocation-control.ts +14 -5
- package/src/runtime/host/service-relocation-host-runtime.ts +1388 -1165
- package/src/runtime/host/spot-address-transport.ts +284 -237
- package/src/runtime/host/spot-node-runtime-options-factory.ts +14 -8
- package/src/runtime/host/spot-runtime-options-factory.ts +71 -62
- package/src/runtime/host/stateful-authority-route-runtime.ts +117 -116
- package/src/runtime/host/user-spot-creation-coordinator.ts +225 -220
- package/src/runtime/locations/actor-location-claims.ts +61 -49
- package/src/runtime/locations/actor-session-route-claims.ts +1 -4
- package/src/runtime/locations/aggregate-inventory-store.ts +105 -134
- package/src/runtime/locations/authority-key-codec.ts +13 -10
- package/src/runtime/locations/auto-connect-loop.ts +14 -11
- package/src/runtime/locations/auto-connect-planner.ts +42 -31
- package/src/runtime/locations/auto-connect-reconciler.ts +106 -63
- package/src/runtime/locations/canonical-codec.ts +3 -1
- package/src/runtime/locations/creation-operation-id.ts +4 -3
- package/src/runtime/locations/domain-store-contract.ts +13 -7
- package/src/runtime/locations/in-memory-authority-store.ts +232 -199
- package/src/runtime/locations/in-memory-location-store.ts +432 -250
- package/src/runtime/locations/in-memory-provider-location-store.ts +16 -17
- package/src/runtime/locations/internal-store-contracts.ts +95 -38
- package/src/runtime/locations/key-codec.ts +3 -4
- package/src/runtime/locations/lease-tracker.ts +36 -27
- package/src/runtime/locations/lifecycle-runtime.ts +15 -3
- package/src/runtime/locations/lifecycle.ts +33 -28
- package/src/runtime/locations/location-store-repository.ts +1329 -1185
- package/src/runtime/locations/opaque-record-key.ts +4 -9
- package/src/runtime/locations/resolvers.ts +201 -178
- package/src/runtime/locations/runtime.ts +251 -159
- package/src/runtime/locations/spot-location-claims.ts +110 -112
- package/src/runtime/messaging/creation-payload-codec.ts +4 -1
- package/src/runtime/messaging/framework-json-v1.ts +34 -15
- package/src/runtime/messaging/packet-name.ts +8 -6
- package/src/runtime/messaging/payload-codec.ts +70 -50
- package/src/runtime/messaging/submission-result.ts +6 -9
- package/src/runtime/protocol/service_wire_codec.generated.ts +1376 -159
- package/src/runtime/protocol/service_wire_pilot_codec.generated.ts +1 -1
- package/src/runtime/routing-id.ts +10 -7
- package/src/runtime/spots/formal-remote-actor-admission-registry.ts +56 -62
- package/src/runtime/spots/formal-remote-actor-transfer-registry.ts +23 -20
- package/src/runtime/spots/index.ts +593 -563
- package/src/runtime/spots/spot-activation-registry.ts +38 -34
- package/src/runtime/spots/spot-activation-state.ts +43 -51
- package/src/runtime/spots/spot-activation.ts +179 -116
- package/src/runtime/spots/spot-actor-admission-coordinator.ts +110 -78
- package/src/runtime/spots/spot-actor-join-dispatch.ts +57 -41
- package/src/runtime/spots/spot-actor-lifecycle-drain.ts +5 -7
- package/src/runtime/spots/spot-actor-membership.ts +25 -27
- package/src/runtime/spots/spot-actor-packet-dispatch.ts +184 -153
- package/src/runtime/spots/spot-actor-packet-drain.ts +54 -42
- package/src/runtime/spots/spot-actor-packet-relay-dispatch.ts +37 -39
- package/src/runtime/spots/spot-closing.ts +11 -12
- package/src/runtime/spots/spot-context.ts +46 -26
- package/src/runtime/spots/spot-entry-activation.ts +84 -65
- package/src/runtime/spots/spot-handle.ts +17 -15
- package/src/runtime/spots/spot-handler-registry.ts +44 -31
- package/src/runtime/spots/spot-location-claim.ts +5 -4
- package/src/runtime/spots/spot-manager-public.ts +62 -82
- package/src/runtime/spots/spot-native-actor-join-admission.ts +20 -16
- package/src/runtime/spots/spot-node-autoconnect.ts +54 -61
- package/src/runtime/spots/spot-node-runtime-manager.ts +230 -221
- package/src/runtime/spots/spot-outbound.ts +47 -59
- package/src/runtime/spots/spot-publisher-transport.ts +5 -4
- package/src/runtime/spots/spot-remote-codec.ts +66 -65
- package/src/runtime/spots/spot-remote-route-codec.ts +61 -41
- package/src/runtime/spots/spot-route-packet-dispatch.ts +128 -95
- package/src/runtime/spots/spot-route-replies.ts +23 -24
- package/src/runtime/spots/spot-route-reply-wire.ts +3 -2
- package/src/runtime/spots/spot-routed-actor-admission.ts +37 -27
- package/src/runtime/spots/spot-routed-bound-session-dispatch.ts +11 -17
- package/src/runtime/spots/spot-routed-frame-dispatch.ts +18 -15
- package/src/runtime/spots/spot-routed-spot-packet-dispatch.ts +35 -26
- package/src/runtime/spots/spot-routing-internal.ts +1 -4
- package/src/runtime/spots/spot-runtime-ports.ts +5 -5
- package/src/runtime/spots/spot-serial-executor.ts +5 -9
- package/src/runtime/spots/spot-serial-turn-executor.ts +19 -26
- package/src/runtime/spots/spot-subscription-dispatch.ts +56 -46
- package/src/runtime/spots/spot-timer.ts +98 -91
- package/src/runtime/streams/actor-session-binding-registry.ts +277 -235
- package/src/runtime/streams/actor-session-binding-runtime-owner.ts +7 -4
- package/src/runtime/streams/actor-session-lifecycle-coordinator.ts +3 -1
- package/src/runtime/streams/bound-actor-relay-sender.ts +53 -51
- package/src/runtime/streams/bound-session-response-target.ts +29 -8
- package/src/runtime/streams/bound-session-service.ts +39 -39
- package/src/runtime/streams/index.ts +176 -100
- package/src/runtime/streams/managed-stream.ts +98 -87
- package/src/runtime/streams/native-fallback-bound-session.ts +57 -52
- package/src/runtime/streams/protocol.ts +73 -43
- package/src/runtime/streams/session-actor-coordinator.ts +97 -89
- package/src/runtime/streams/session-calls.ts +2 -8
- package/src/runtime/streams/session-context.ts +66 -48
- package/src/runtime/streams/session-provider.ts +5 -7
- package/src/runtime/streams/session-serial-executor.ts +7 -6
- package/src/runtime/streams/stream-binding-runtime-ports.ts +79 -29
- package/src/runtime/streams/stream-frame-factory.ts +55 -38
- package/src/runtime/streams/stream-session-runtime.ts +268 -210
- package/src/runtime/workers/index.ts +68 -29
|
@@ -56,9 +56,7 @@ class ZLinkLocationStoreRepository extends in_memory_location_store_1.ZLinkInMem
|
|
|
56
56
|
}
|
|
57
57
|
const scan = await this.provider.scan({
|
|
58
58
|
prefix: AUTHORITY_PREIMAGE_PREFIX,
|
|
59
|
-
cursor: cursor === undefined
|
|
60
|
-
? undefined
|
|
61
|
-
: { value: cursor.encoded },
|
|
59
|
+
cursor: cursor === undefined ? undefined : { value: cursor.encoded },
|
|
62
60
|
limit
|
|
63
61
|
}, signal);
|
|
64
62
|
if (scan.kind === 'expired')
|
|
@@ -95,16 +93,15 @@ class ZLinkLocationStoreRepository extends in_memory_location_store_1.ZLinkInMem
|
|
|
95
93
|
if (record.aggregate !== undefined) {
|
|
96
94
|
return { kind: 'conflict', current: snapshot };
|
|
97
95
|
}
|
|
98
|
-
if (record.snapshot.allocation.state !== 'active'
|
|
99
|
-
|
|
100
|
-
!== expectedStoreVersion.value) {
|
|
96
|
+
if (record.snapshot.allocation.state !== 'active' ||
|
|
97
|
+
(record.visibleStoreVersion ?? current.value.version.value) !== expectedStoreVersion.value) {
|
|
101
98
|
return { kind: 'conflict', current: snapshot };
|
|
102
99
|
}
|
|
103
100
|
if (mutation.kind === 'rebindOwnerLease') {
|
|
104
|
-
if (mutation.expectedOwner.ownerId !== record.snapshot.ownerId
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
101
|
+
if (mutation.expectedOwner.ownerId !== record.snapshot.ownerId ||
|
|
102
|
+
mutation.expectedOwner.leaseGeneration !== record.snapshot.ownerLeaseGeneration ||
|
|
103
|
+
mutation.targetOwner.ownerId !== record.snapshot.ownerId ||
|
|
104
|
+
mutation.targetOwner.leaseGeneration === record.snapshot.ownerLeaseGeneration) {
|
|
108
105
|
return { kind: 'conflict', current: snapshot };
|
|
109
106
|
}
|
|
110
107
|
const descriptorKey = meshKey(record.snapshot.allocation.descriptor.meshName, record.snapshot.allocation.descriptor.rid);
|
|
@@ -139,7 +136,7 @@ class ZLinkLocationStoreRepository extends in_memory_location_store_1.ZLinkInMem
|
|
|
139
136
|
}, signal);
|
|
140
137
|
if (result.kind === 'conflict')
|
|
141
138
|
continue;
|
|
142
|
-
const storeVersion = result.putVersions.find(entry => entry.key.value === rowKey.value)?.version;
|
|
139
|
+
const storeVersion = result.putVersions.find((entry) => entry.key.value === rowKey.value)?.version;
|
|
143
140
|
if (storeVersion === undefined) {
|
|
144
141
|
throw new Error('Authority lease rebind did not return a row version.');
|
|
145
142
|
}
|
|
@@ -147,22 +144,18 @@ class ZLinkLocationStoreRepository extends in_memory_location_store_1.ZLinkInMem
|
|
|
147
144
|
const { kind: _kind, ...withoutKind } = stored;
|
|
148
145
|
return { kind: 'stored', ...withoutKind };
|
|
149
146
|
}
|
|
150
|
-
if (mutation.kind === 'restore'
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
!== record.snapshot.ownerLeaseGeneration)) {
|
|
147
|
+
if (mutation.kind === 'restore' &&
|
|
148
|
+
(mutation.expectedOwner.ownerId !== record.snapshot.ownerId ||
|
|
149
|
+
mutation.expectedOwner.leaseGeneration !== record.snapshot.ownerLeaseGeneration)) {
|
|
154
150
|
return { kind: 'conflict', current: snapshot };
|
|
155
151
|
}
|
|
156
152
|
const leaseKey = ownerKey(record.snapshot.ownerId);
|
|
157
153
|
const lease = await this.provider.read(leaseKey, signal);
|
|
158
|
-
if (mutation.kind !== 'restore'
|
|
159
|
-
&& !sameLiveOwner(lease, record.snapshot)) {
|
|
154
|
+
if (mutation.kind !== 'restore' && !sameLiveOwner(lease, record.snapshot)) {
|
|
160
155
|
return { kind: 'conflict', current: snapshot };
|
|
161
156
|
}
|
|
162
157
|
const capacityRowKey = capacityKey(record.snapshot.allocation.descriptor.meshName, String(record.snapshot.allocation.descriptor.rid));
|
|
163
|
-
const capacityRead = mutation.kind === 'delete'
|
|
164
|
-
? await this.provider.read(capacityRowKey, signal)
|
|
165
|
-
: undefined;
|
|
158
|
+
const capacityRead = mutation.kind === 'delete' ? await this.provider.read(capacityRowKey, signal) : undefined;
|
|
166
159
|
const nextRecord = mutation.kind === 'delete'
|
|
167
160
|
? undefined
|
|
168
161
|
: {
|
|
@@ -176,12 +169,8 @@ class ZLinkLocationStoreRepository extends in_memory_location_store_1.ZLinkInMem
|
|
|
176
169
|
const result = await this.provider.write({
|
|
177
170
|
conditions: [
|
|
178
171
|
{ kind: 'version', key: rowKey, expected: current.value.version },
|
|
179
|
-
...(mutation.kind === 'restore'
|
|
180
|
-
|
|
181
|
-
: [versionCondition(leaseKey, lease)]),
|
|
182
|
-
...(capacityRead === undefined
|
|
183
|
-
? []
|
|
184
|
-
: [conditionFor(capacityRowKey, capacityRead)])
|
|
172
|
+
...(mutation.kind === 'restore' ? [] : [versionCondition(leaseKey, lease)]),
|
|
173
|
+
...(capacityRead === undefined ? [] : [conditionFor(capacityRowKey, capacityRead)])
|
|
185
174
|
],
|
|
186
175
|
mutations: mutation.kind === 'delete'
|
|
187
176
|
? [
|
|
@@ -203,7 +192,7 @@ class ZLinkLocationStoreRepository extends in_memory_location_store_1.ZLinkInMem
|
|
|
203
192
|
}, signal);
|
|
204
193
|
if (result.kind === 'conflict')
|
|
205
194
|
continue;
|
|
206
|
-
const storeVersion = result.putVersions.find(entry => entry.key.value === rowKey.value)?.version;
|
|
195
|
+
const storeVersion = result.putVersions.find((entry) => entry.key.value === rowKey.value)?.version;
|
|
207
196
|
if (mutation.kind === 'delete') {
|
|
208
197
|
return {
|
|
209
198
|
kind: 'deleted',
|
|
@@ -253,7 +242,7 @@ class ZLinkLocationStoreRepository extends in_memory_location_store_1.ZLinkInMem
|
|
|
253
242
|
return reconciled;
|
|
254
243
|
}
|
|
255
244
|
else {
|
|
256
|
-
const version = claimed.putVersions.find(value => value.key.value === rowKey.value)?.version;
|
|
245
|
+
const version = claimed.putVersions.find((value) => value.key.value === rowKey.value)?.version;
|
|
257
246
|
if (version === undefined) {
|
|
258
247
|
throw new Error('Aggregate staging did not return a Store version.');
|
|
259
248
|
}
|
|
@@ -268,8 +257,7 @@ class ZLinkLocationStoreRepository extends in_memory_location_store_1.ZLinkInMem
|
|
|
268
257
|
}
|
|
269
258
|
}
|
|
270
259
|
const aggregate = decodeJson(aggregateRead.value.bytes);
|
|
271
|
-
if (aggregate.state !== 'staging'
|
|
272
|
-
|| aggregate.requestFingerprint !== fingerprint) {
|
|
260
|
+
if (aggregate.state !== 'staging' || aggregate.requestFingerprint !== fingerprint) {
|
|
273
261
|
return { kind: 'conflict' };
|
|
274
262
|
}
|
|
275
263
|
try {
|
|
@@ -280,9 +268,9 @@ class ZLinkLocationStoreRepository extends in_memory_location_store_1.ZLinkInMem
|
|
|
280
268
|
}
|
|
281
269
|
await parallelForEach(request.participants, 64, async (participant, index) => {
|
|
282
270
|
const entry = entries[index];
|
|
283
|
-
if (entry.authorityKey !== participant.authorityKey.value
|
|
284
|
-
|
|
285
|
-
|
|
271
|
+
if (entry.authorityKey !== participant.authorityKey.value ||
|
|
272
|
+
entry.expectedStoreVersion !== participant.expectedStoreVersion.value ||
|
|
273
|
+
entry.ownerTransition !== participant.ownerTransition) {
|
|
286
274
|
throw new Error('Aggregate inventory differs from its participant request.');
|
|
287
275
|
}
|
|
288
276
|
await this.putImmutable(aggregateParticipantPayloadKey(fence, index), participant.authorityPayload, signal);
|
|
@@ -300,8 +288,8 @@ class ZLinkLocationStoreRepository extends in_memory_location_store_1.ZLinkInMem
|
|
|
300
288
|
const targetCapacity = targetCapacityRead.kind === 'missing'
|
|
301
289
|
? emptyCapacityRecord()
|
|
302
290
|
: decodeJson(targetCapacityRead.value.bytes);
|
|
303
|
-
if (descriptor === undefined
|
|
304
|
-
|
|
291
|
+
if (descriptor === undefined ||
|
|
292
|
+
!capacityAvailable(descriptor, request.capacity, targetCapacity)) {
|
|
305
293
|
await this.abortAggregateStaging(fence, signal);
|
|
306
294
|
return { kind: 'conflict' };
|
|
307
295
|
}
|
|
@@ -318,7 +306,8 @@ class ZLinkLocationStoreRepository extends in_memory_location_store_1.ZLinkInMem
|
|
|
318
306
|
return { kind: 'generationExhausted' };
|
|
319
307
|
}
|
|
320
308
|
}
|
|
321
|
-
else if (ownerGenerationEnd !==
|
|
309
|
+
else if (ownerGenerationEnd !==
|
|
310
|
+
ownerGenerationStart + BigInt(request.participants.length) - 1n) {
|
|
322
311
|
await this.abortAggregateStaging(fence, signal);
|
|
323
312
|
return { kind: 'conflict' };
|
|
324
313
|
}
|
|
@@ -339,8 +328,8 @@ class ZLinkLocationStoreRepository extends in_memory_location_store_1.ZLinkInMem
|
|
|
339
328
|
if (reservedAggregate.kind === 'missing')
|
|
340
329
|
return { kind: 'conflict' };
|
|
341
330
|
const reservedRecord = decodeJson(reservedAggregate.value.bytes);
|
|
342
|
-
if (reservedRecord.ownerGenerationStart === undefined
|
|
343
|
-
|
|
331
|
+
if (reservedRecord.ownerGenerationStart === undefined ||
|
|
332
|
+
reservedRecord.ownerGenerationEnd === undefined) {
|
|
344
333
|
return { kind: 'conflict' };
|
|
345
334
|
}
|
|
346
335
|
ownerGenerationStart = reservedRecord.ownerGenerationStart;
|
|
@@ -357,10 +346,10 @@ class ZLinkLocationStoreRepository extends in_memory_location_store_1.ZLinkInMem
|
|
|
357
346
|
}
|
|
358
347
|
continue;
|
|
359
348
|
}
|
|
360
|
-
if (record.aggregate !== undefined
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
349
|
+
if (record.aggregate !== undefined ||
|
|
350
|
+
record.snapshot.allocation.state !== 'active' ||
|
|
351
|
+
(record.visibleStoreVersion ?? current.value.version.value) !==
|
|
352
|
+
participant.expectedStoreVersion.value) {
|
|
364
353
|
await this.clearAggregateMarkers(fence, installed, signal);
|
|
365
354
|
await this.abortAggregateStaging(fence, signal);
|
|
366
355
|
return { kind: 'conflict' };
|
|
@@ -402,7 +391,9 @@ class ZLinkLocationStoreRepository extends in_memory_location_store_1.ZLinkInMem
|
|
|
402
391
|
],
|
|
403
392
|
mutations: [
|
|
404
393
|
{
|
|
405
|
-
kind: 'put',
|
|
394
|
+
kind: 'put',
|
|
395
|
+
key: authorityRowKey,
|
|
396
|
+
bytes: encodeAuthorityRecord({
|
|
406
397
|
...record,
|
|
407
398
|
aggregate: marker,
|
|
408
399
|
visibleStoreVersion: record.visibleStoreVersion ?? current.value.version.value
|
|
@@ -430,14 +421,15 @@ class ZLinkLocationStoreRepository extends in_memory_location_store_1.ZLinkInMem
|
|
|
430
421
|
}, signal);
|
|
431
422
|
if (stored.kind === 'conflict') {
|
|
432
423
|
const raced = await this.provider.read(authorityRowKey, signal);
|
|
433
|
-
if (raced.kind === 'found' &&
|
|
424
|
+
if (raced.kind === 'found' &&
|
|
425
|
+
sameAggregateMarker(decodeAuthorityRecord(raced.value.bytes).aggregate, fence, index, participant)) {
|
|
434
426
|
if (reservingOwnerGenerationBlock) {
|
|
435
427
|
const reservedAggregate = await this.provider.read(rowKey, signal);
|
|
436
428
|
if (reservedAggregate.kind === 'missing')
|
|
437
429
|
return { kind: 'conflict' };
|
|
438
430
|
const reservedRecord = decodeJson(reservedAggregate.value.bytes);
|
|
439
|
-
if (reservedRecord.ownerGenerationStart === undefined
|
|
440
|
-
|
|
431
|
+
if (reservedRecord.ownerGenerationStart === undefined ||
|
|
432
|
+
reservedRecord.ownerGenerationEnd === undefined) {
|
|
441
433
|
return { kind: 'conflict' };
|
|
442
434
|
}
|
|
443
435
|
ownerGenerationStart = reservedRecord.ownerGenerationStart;
|
|
@@ -445,7 +437,10 @@ class ZLinkLocationStoreRepository extends in_memory_location_store_1.ZLinkInMem
|
|
|
445
437
|
ownerGenerationCounterRead = undefined;
|
|
446
438
|
aggregateRead = reservedAggregate;
|
|
447
439
|
}
|
|
448
|
-
installed.push({
|
|
440
|
+
installed.push({
|
|
441
|
+
key: authorityRowKey,
|
|
442
|
+
expectedStoreVersion: participant.expectedStoreVersion.value
|
|
443
|
+
});
|
|
449
444
|
continue;
|
|
450
445
|
}
|
|
451
446
|
// A peer can be in the middle of publishing this same aggregate.
|
|
@@ -454,8 +449,8 @@ class ZLinkLocationStoreRepository extends in_memory_location_store_1.ZLinkInMem
|
|
|
454
449
|
const aggregateRaced = await this.provider.read(rowKey, signal);
|
|
455
450
|
if (aggregateRaced.kind === 'found') {
|
|
456
451
|
const aggregateRecord = decodeJson(aggregateRaced.value.bytes);
|
|
457
|
-
if (aggregateRecord.requestFingerprint === fingerprint
|
|
458
|
-
|
|
452
|
+
if (aggregateRecord.requestFingerprint === fingerprint &&
|
|
453
|
+
(aggregateRecord.state === 'staging' || aggregateRecord.state === 'prepared')) {
|
|
459
454
|
return await this.prepareAggregate(request, signal);
|
|
460
455
|
}
|
|
461
456
|
}
|
|
@@ -575,8 +570,8 @@ class ZLinkLocationStoreRepository extends in_memory_location_store_1.ZLinkInMem
|
|
|
575
570
|
requireProviderBytes(this.provider, aggregateParticipantPayloadKey(fence, index), signal),
|
|
576
571
|
requireProviderBytes(this.provider, aggregateParticipantMembershipKey(fence, index), signal)
|
|
577
572
|
]);
|
|
578
|
-
if (sha256Hex(payload) !== entry.authorityPayloadSha256
|
|
579
|
-
|
|
573
|
+
if (sha256Hex(payload) !== entry.authorityPayloadSha256 ||
|
|
574
|
+
sha256Hex(membership) !== entry.membershipMutationSha256) {
|
|
580
575
|
throw new Error('Aggregate participant staging checksum does not match inventory.');
|
|
581
576
|
}
|
|
582
577
|
authorityRows.push({ key: rowKeyForParticipant, current, record, entry });
|
|
@@ -588,7 +583,8 @@ class ZLinkLocationStoreRepository extends in_memory_location_store_1.ZLinkInMem
|
|
|
588
583
|
this.provider.read(targetDescriptorKey, signal),
|
|
589
584
|
this.provider.read(targetLeaseKey, signal)
|
|
590
585
|
]);
|
|
591
|
-
if (liveTargetDescriptor(descriptorRead, leaseRead, aggregateTargetFromRecord(aggregate)) ===
|
|
586
|
+
if (liveTargetDescriptor(descriptorRead, leaseRead, aggregateTargetFromRecord(aggregate)) ===
|
|
587
|
+
undefined) {
|
|
592
588
|
return { kind: 'stale' };
|
|
593
589
|
}
|
|
594
590
|
const capacityDeltas = new Map();
|
|
@@ -666,9 +662,9 @@ class ZLinkLocationStoreRepository extends in_memory_location_store_1.ZLinkInMem
|
|
|
666
662
|
if (aggregateRead.kind === 'missing')
|
|
667
663
|
return { kind: 'stale' };
|
|
668
664
|
aggregate = decodeJson(aggregateRead.value.bytes);
|
|
669
|
-
if (aggregate.state === 'prepared'
|
|
670
|
-
|
|
671
|
-
|
|
665
|
+
if (aggregate.state === 'prepared' &&
|
|
666
|
+
retryAttempt < MAX_AGGREGATE_COMMIT_CONFLICT_RETRIES &&
|
|
667
|
+
performance.now() < retryDeadlineAtMs) {
|
|
672
668
|
// The commit CAS also fences the target's live owner lease, descriptor,
|
|
673
669
|
// and capacity rows. Re-read the whole prepared fence after an
|
|
674
670
|
// auxiliary-row race; a changed aggregate or participant fence exits
|
|
@@ -699,16 +695,20 @@ class ZLinkLocationStoreRepository extends in_memory_location_store_1.ZLinkInMem
|
|
|
699
695
|
}
|
|
700
696
|
if (aggregate.state === 'committed')
|
|
701
697
|
return { kind: 'stale' };
|
|
702
|
-
const conditions = [
|
|
698
|
+
const conditions = [
|
|
699
|
+
{
|
|
703
700
|
kind: 'version',
|
|
704
701
|
key: rowKey,
|
|
705
702
|
expected: current.value.version
|
|
706
|
-
}
|
|
707
|
-
|
|
703
|
+
}
|
|
704
|
+
];
|
|
705
|
+
const mutations = [
|
|
706
|
+
{
|
|
708
707
|
kind: 'put',
|
|
709
708
|
key: rowKey,
|
|
710
709
|
bytes: encodeJson({ ...aggregate, state: 'aborted' })
|
|
711
|
-
}
|
|
710
|
+
}
|
|
711
|
+
];
|
|
712
712
|
if (aggregate.state === 'prepared') {
|
|
713
713
|
const targetCapacityKey = capacityKey(aggregate.targetDescriptor.meshName, String(aggregate.targetDescriptor.rid));
|
|
714
714
|
const targetCapacityRead = await this.provider.read(targetCapacityKey, signal);
|
|
@@ -755,15 +755,15 @@ class ZLinkLocationStoreRepository extends in_memory_location_store_1.ZLinkInMem
|
|
|
755
755
|
if (current.kind === 'found') {
|
|
756
756
|
const record = decodeAuthorityRecord(current.value.bytes);
|
|
757
757
|
const snapshot = authoritySnapshot(record.snapshot, current.value.version, current.value.storeNow);
|
|
758
|
-
if (snapshot.allocation.objectKind !== request.key.kind
|
|
759
|
-
|
|
758
|
+
if (snapshot.allocation.objectKind !== request.key.kind ||
|
|
759
|
+
snapshot.allocation.stableType !== request.intent.stableType) {
|
|
760
760
|
return { kind: 'typeMismatch', current: snapshot };
|
|
761
761
|
}
|
|
762
762
|
if (snapshot.allocation.state === 'active') {
|
|
763
763
|
return { kind: 'alreadyExists', current: snapshot };
|
|
764
764
|
}
|
|
765
|
-
if (record.aggregate !== undefined
|
|
766
|
-
|
|
765
|
+
if (record.aggregate !== undefined ||
|
|
766
|
+
isCanonicalAuthorityPayload(record.snapshot.payload)) {
|
|
767
767
|
// A relocation record carries its own recovery protocol. Reserve
|
|
768
768
|
// may reclaim only an unfinished plain creation.
|
|
769
769
|
return { kind: 'conflict', current: snapshot };
|
|
@@ -777,8 +777,7 @@ class ZLinkLocationStoreRepository extends in_memory_location_store_1.ZLinkInMem
|
|
|
777
777
|
this.provider.read(staleOwnerKey, signal),
|
|
778
778
|
this.provider.read(staleCapacityKey, signal)
|
|
779
779
|
]);
|
|
780
|
-
if (staleOwnerRead.kind === 'found'
|
|
781
|
-
&& staleOwnerRead.value.expiresAt === undefined) {
|
|
780
|
+
if (staleOwnerRead.kind === 'found' && staleOwnerRead.value.expiresAt === undefined) {
|
|
782
781
|
// A lease is always written with a positive TTL, so a missing
|
|
783
782
|
// expiry is a corrupt record. Reclaiming deletes authority state,
|
|
784
783
|
// so refuse rather than read the absence as expiry.
|
|
@@ -889,7 +888,7 @@ class ZLinkLocationStoreRepository extends in_memory_location_store_1.ZLinkInMem
|
|
|
889
888
|
}, signal);
|
|
890
889
|
if (result.kind === 'conflict')
|
|
891
890
|
continue;
|
|
892
|
-
const version = result.putVersions.find(entry => entry.key.value === rowKey.value)?.version;
|
|
891
|
+
const version = result.putVersions.find((entry) => entry.key.value === rowKey.value)?.version;
|
|
893
892
|
if (version === undefined)
|
|
894
893
|
throw new Error('Authority reserve did not return a row version.');
|
|
895
894
|
return {
|
|
@@ -908,18 +907,18 @@ class ZLinkLocationStoreRepository extends in_memory_location_store_1.ZLinkInMem
|
|
|
908
907
|
if (current.kind === 'missing')
|
|
909
908
|
return { kind: 'stale' };
|
|
910
909
|
const record = decodeAuthorityRecord(current.value.bytes);
|
|
911
|
-
if (record.terminal === 'committed'
|
|
912
|
-
|
|
913
|
-
|
|
910
|
+
if (record.terminal === 'committed' &&
|
|
911
|
+
record.snapshot.pendingCreation === undefined &&
|
|
912
|
+
record.snapshot.allocation.state === 'active') {
|
|
914
913
|
return {
|
|
915
914
|
kind: 'alreadyCommitted',
|
|
916
915
|
ready: authoritySnapshot(record.snapshot, current.value.version, current.value.storeNow)
|
|
917
916
|
};
|
|
918
917
|
}
|
|
919
|
-
if (record.snapshot.pendingCreation?.reservationId !== request.reservationId
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
918
|
+
if (record.snapshot.pendingCreation?.reservationId !== request.reservationId ||
|
|
919
|
+
current.value.version.value !== request.expectedStoreVersion ||
|
|
920
|
+
record.snapshot.allocation.state !== 'reserved' ||
|
|
921
|
+
!sameCreationTarget(record.snapshot, request.target)) {
|
|
923
922
|
return { kind: 'stale' };
|
|
924
923
|
}
|
|
925
924
|
const descriptorKey = meshKey(request.target.meshName, request.target.nodeRid);
|
|
@@ -966,7 +965,7 @@ class ZLinkLocationStoreRepository extends in_memory_location_store_1.ZLinkInMem
|
|
|
966
965
|
}, signal);
|
|
967
966
|
if (result.kind === 'conflict')
|
|
968
967
|
continue;
|
|
969
|
-
const version = result.putVersions.find(entry => entry.key.value === rowKey.value)?.version;
|
|
968
|
+
const version = result.putVersions.find((entry) => entry.key.value === rowKey.value)?.version;
|
|
970
969
|
if (version === undefined)
|
|
971
970
|
throw new Error('Authority commit did not return a row version.');
|
|
972
971
|
return {
|
|
@@ -984,10 +983,10 @@ class ZLinkLocationStoreRepository extends in_memory_location_store_1.ZLinkInMem
|
|
|
984
983
|
if (current.kind === 'missing')
|
|
985
984
|
return { kind: 'stale' };
|
|
986
985
|
const record = decodeAuthorityRecord(current.value.bytes);
|
|
987
|
-
if (record.snapshot.pendingCreation?.reservationId !== request.reservationId
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
986
|
+
if (record.snapshot.pendingCreation?.reservationId !== request.reservationId ||
|
|
987
|
+
current.value.version.value !== request.expectedStoreVersion ||
|
|
988
|
+
record.snapshot.allocation.state !== 'reserved' ||
|
|
989
|
+
!sameCreationTarget(record.snapshot, request.target)) {
|
|
991
990
|
return { kind: 'stale' };
|
|
992
991
|
}
|
|
993
992
|
const leaseKey = ownerKey(request.target.owner.ownerId);
|
|
@@ -1052,10 +1051,10 @@ class ZLinkLocationStoreRepository extends in_memory_location_store_1.ZLinkInMem
|
|
|
1052
1051
|
if (current.kind === 'missing')
|
|
1053
1052
|
return { kind: 'stale' };
|
|
1054
1053
|
const record = decodeAuthorityRecord(current.value.bytes);
|
|
1055
|
-
if (record.snapshot.pendingCreation?.reservationId !== request.reservationId
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1054
|
+
if (record.snapshot.pendingCreation?.reservationId !== request.reservationId ||
|
|
1055
|
+
current.value.version.value !== request.expectedStoreVersion ||
|
|
1056
|
+
record.snapshot.allocation.state !== 'reserved' ||
|
|
1057
|
+
!sameCreationTarget(record.snapshot, request.target)) {
|
|
1059
1058
|
return { kind: 'stale' };
|
|
1060
1059
|
}
|
|
1061
1060
|
const descriptorKey = meshKey(request.target.meshName, request.target.nodeRid);
|
|
@@ -1076,8 +1075,7 @@ class ZLinkLocationStoreRepository extends in_memory_location_store_1.ZLinkInMem
|
|
|
1076
1075
|
...terminal,
|
|
1077
1076
|
storeNow: current.value.storeNow
|
|
1078
1077
|
};
|
|
1079
|
-
const retentionMs = terminalAtStore.expiresAt.getTime()
|
|
1080
|
-
- current.value.storeNow.getTime();
|
|
1078
|
+
const retentionMs = terminalAtStore.expiresAt.getTime() - current.value.storeNow.getTime();
|
|
1081
1079
|
if (retentionMs <= 0) {
|
|
1082
1080
|
throw new RangeError('Creation terminal expiry must be the live operation deadline plus five minutes.');
|
|
1083
1081
|
}
|
|
@@ -1143,7 +1141,7 @@ class ZLinkLocationStoreRepository extends in_memory_location_store_1.ZLinkInMem
|
|
|
1143
1141
|
if (request.completion.kind !== 'created') {
|
|
1144
1142
|
return { kind: request.completion.kind, terminal: publishedTerminal };
|
|
1145
1143
|
}
|
|
1146
|
-
const version = result.putVersions.find(entry => entry.key.value === rowKey.value)?.version;
|
|
1144
|
+
const version = result.putVersions.find((entry) => entry.key.value === rowKey.value)?.version;
|
|
1147
1145
|
if (version === undefined) {
|
|
1148
1146
|
throw new Error('Actor creation completion did not return an authority row version.');
|
|
1149
1147
|
}
|
|
@@ -1246,12 +1244,14 @@ class ZLinkLocationStoreRepository extends in_memory_location_store_1.ZLinkInMem
|
|
|
1246
1244
|
return { kind: 'stale' };
|
|
1247
1245
|
const result = await this.provider.write({
|
|
1248
1246
|
conditions: [{ kind: 'version', key, expected: current.value.version }],
|
|
1249
|
-
mutations: [
|
|
1247
|
+
mutations: [
|
|
1248
|
+
{
|
|
1250
1249
|
kind: 'put',
|
|
1251
1250
|
key,
|
|
1252
1251
|
bytes: current.value.bytes,
|
|
1253
1252
|
retentionMs: leaseTtlMs
|
|
1254
|
-
}
|
|
1253
|
+
}
|
|
1254
|
+
]
|
|
1255
1255
|
}, signal);
|
|
1256
1256
|
if (result.kind === 'conflict')
|
|
1257
1257
|
return { kind: 'stale' };
|
|
@@ -1284,8 +1284,8 @@ class ZLinkLocationStoreRepository extends in_memory_location_store_1.ZLinkInMem
|
|
|
1284
1284
|
if (current.kind === 'missing')
|
|
1285
1285
|
return Locations_1.ZLinkLocationWriteStatus.IgnoredStale;
|
|
1286
1286
|
const descriptor = reviveMeshDescriptor(decodeCanonicalDescriptorRecord(current.value.bytes).descriptor);
|
|
1287
|
-
if (descriptor.ownerId !== owner.ownerId
|
|
1288
|
-
|
|
1287
|
+
if (descriptor.ownerId !== owner.ownerId ||
|
|
1288
|
+
descriptor.leaseGeneration !== owner.leaseGeneration) {
|
|
1289
1289
|
return Locations_1.ZLinkLocationWriteStatus.IgnoredStale;
|
|
1290
1290
|
}
|
|
1291
1291
|
const result = await this.provider.write({
|
|
@@ -1324,7 +1324,7 @@ class ZLinkLocationStoreRepository extends in_memory_location_store_1.ZLinkInMem
|
|
|
1324
1324
|
active: capacity.active.spots,
|
|
1325
1325
|
reserved: capacity.pending.spots
|
|
1326
1326
|
},
|
|
1327
|
-
spotTypes: descriptor.populationCapacity.spotTypes.map(value => {
|
|
1327
|
+
spotTypes: descriptor.populationCapacity.spotTypes.map((value) => {
|
|
1328
1328
|
const key = capacityTypeKey({
|
|
1329
1329
|
objectKind: value.objectKind,
|
|
1330
1330
|
stableType: value.stableType,
|
|
@@ -1377,7 +1377,7 @@ class ZLinkLocationStoreRepository extends in_memory_location_store_1.ZLinkInMem
|
|
|
1377
1377
|
return value === undefined ? undefined : normalizeSpot(value);
|
|
1378
1378
|
}
|
|
1379
1379
|
async listSpots(filter, page = {}, signal) {
|
|
1380
|
-
return this.listOwnedLocations(`${PREFIX}spot:`, page, normalizeSpot, value => matchesSpot(value, filter), signal);
|
|
1380
|
+
return this.listOwnedLocations(`${PREFIX}spot:`, page, normalizeSpot, (value) => matchesSpot(value, filter), signal);
|
|
1381
1381
|
}
|
|
1382
1382
|
async updateActor(location, intent, signal) {
|
|
1383
1383
|
return this.updateOwnedLocation(actorKey(location.meshName, location.actorId), normalizeActor(location), intent, signal);
|
|
@@ -1390,7 +1390,7 @@ class ZLinkLocationStoreRepository extends in_memory_location_store_1.ZLinkInMem
|
|
|
1390
1390
|
return value === undefined ? undefined : normalizeActor(value);
|
|
1391
1391
|
}
|
|
1392
1392
|
async listActors(filter, page = {}, signal) {
|
|
1393
|
-
return this.listOwnedLocations(`${PREFIX}actor:`, page, normalizeActor, value => matchesActor(value, filter), signal);
|
|
1393
|
+
return this.listOwnedLocations(`${PREFIX}actor:`, page, normalizeActor, (value) => matchesActor(value, filter), signal);
|
|
1394
1394
|
}
|
|
1395
1395
|
async updateRoute(location, intent, signal) {
|
|
1396
1396
|
const rowKey = routeKey(String(location.routeKind), location.routeKey);
|
|
@@ -1412,9 +1412,9 @@ class ZLinkLocationStoreRepository extends in_memory_location_store_1.ZLinkInMem
|
|
|
1412
1412
|
};
|
|
1413
1413
|
}
|
|
1414
1414
|
}
|
|
1415
|
-
else if (intent === 2
|
|
1416
|
-
|
|
1417
|
-
|
|
1415
|
+
else if (intent === 2 &&
|
|
1416
|
+
(stored.ownerId !== normalized.ownerId ||
|
|
1417
|
+
(normalized.generation !== 0n && stored.generation !== normalized.generation))) {
|
|
1418
1418
|
return {
|
|
1419
1419
|
status: Locations_1.ZLinkLocationWriteStatus.IgnoredStale,
|
|
1420
1420
|
generation,
|
|
@@ -1431,14 +1431,16 @@ class ZLinkLocationStoreRepository extends in_memory_location_store_1.ZLinkInMem
|
|
|
1431
1431
|
const stored = { ...normalized, generation };
|
|
1432
1432
|
const result = await this.provider.write({
|
|
1433
1433
|
conditions: [condition],
|
|
1434
|
-
mutations: [
|
|
1434
|
+
mutations: [
|
|
1435
|
+
{
|
|
1435
1436
|
kind: 'put',
|
|
1436
1437
|
key: rowKey,
|
|
1437
1438
|
bytes: encodeJson({
|
|
1438
1439
|
generation: generation.toString(),
|
|
1439
1440
|
descriptor: stored
|
|
1440
1441
|
})
|
|
1441
|
-
}
|
|
1442
|
+
}
|
|
1443
|
+
]
|
|
1442
1444
|
}, signal);
|
|
1443
1445
|
return result.kind === 'applied'
|
|
1444
1446
|
? { status: Locations_1.ZLinkLocationWriteStatus.Stored, generation, updatedAt: result.storeNow }
|
|
@@ -1450,8 +1452,8 @@ class ZLinkLocationStoreRepository extends in_memory_location_store_1.ZLinkInMem
|
|
|
1450
1452
|
if (current.kind === 'missing')
|
|
1451
1453
|
return rejected(current.storeNow);
|
|
1452
1454
|
const record = decodeJson(current.value.bytes);
|
|
1453
|
-
if (record.descriptor.ownerId !== owner.ownerId
|
|
1454
|
-
|
|
1455
|
+
if (record.descriptor.ownerId !== owner.ownerId ||
|
|
1456
|
+
record.descriptor.generation !== owner.leaseGeneration) {
|
|
1455
1457
|
return {
|
|
1456
1458
|
status: Locations_1.ZLinkLocationWriteStatus.IgnoredStale,
|
|
1457
1459
|
generation: BigInt(record.generation),
|
|
@@ -1463,7 +1465,11 @@ class ZLinkLocationStoreRepository extends in_memory_location_store_1.ZLinkInMem
|
|
|
1463
1465
|
mutations: [{ kind: 'delete', key: rowKey }]
|
|
1464
1466
|
}, signal);
|
|
1465
1467
|
return result.kind === 'applied'
|
|
1466
|
-
? {
|
|
1468
|
+
? {
|
|
1469
|
+
status: Locations_1.ZLinkLocationWriteStatus.Stored,
|
|
1470
|
+
generation: BigInt(record.generation),
|
|
1471
|
+
updatedAt: result.storeNow
|
|
1472
|
+
}
|
|
1467
1473
|
: rejected(result.storeNow);
|
|
1468
1474
|
}
|
|
1469
1475
|
async resolveRoute(key, signal) {
|
|
@@ -1471,7 +1477,7 @@ class ZLinkLocationStoreRepository extends in_memory_location_store_1.ZLinkInMem
|
|
|
1471
1477
|
return value === undefined ? undefined : normalizeRoute(value);
|
|
1472
1478
|
}
|
|
1473
1479
|
async listRoutes(filter, page = {}, signal) {
|
|
1474
|
-
return this.listOwnedLocations(`${PREFIX}route:`, page, normalizeRoute, value => matchesRoute(value, filter), signal);
|
|
1480
|
+
return this.listOwnedLocations(`${PREFIX}route:`, page, normalizeRoute, (value) => matchesRoute(value, filter), signal);
|
|
1475
1481
|
}
|
|
1476
1482
|
async removeAllByOwner(owner, signal) {
|
|
1477
1483
|
const leaseKey = ownerKey(owner.ownerId);
|
|
@@ -1516,7 +1522,7 @@ class ZLinkLocationStoreRepository extends in_memory_location_store_1.ZLinkInMem
|
|
|
1516
1522
|
for (let offset = 0; offset < candidates.length; offset += MAX_OWNER_CLEANUP_BATCH_ROWS) {
|
|
1517
1523
|
removed += await this.removeOwnerCleanupBatch(owner, leaseKey, candidates.slice(offset, offset + MAX_OWNER_CLEANUP_BATCH_ROWS), signal);
|
|
1518
1524
|
}
|
|
1519
|
-
return removed + await super.removeAllByOwner(owner);
|
|
1525
|
+
return removed + (await super.removeAllByOwner(owner));
|
|
1520
1526
|
}
|
|
1521
1527
|
async removeOwnedAuthorities(owner, signal) {
|
|
1522
1528
|
const candidates = [];
|
|
@@ -1550,13 +1556,12 @@ class ZLinkLocationStoreRepository extends in_memory_location_store_1.ZLinkInMem
|
|
|
1550
1556
|
for (const candidate of candidates) {
|
|
1551
1557
|
signal?.throwIfAborted();
|
|
1552
1558
|
const current = await this.provider.read(candidate.key, signal);
|
|
1553
|
-
if (current.kind === 'missing'
|
|
1554
|
-
|| current.value.version.value !== candidate.scanVersion.value)
|
|
1559
|
+
if (current.kind === 'missing' || current.value.version.value !== candidate.scanVersion.value)
|
|
1555
1560
|
continue;
|
|
1556
1561
|
const record = decodeAuthorityRecord(current.value.bytes);
|
|
1557
|
-
if (record.snapshot.ownerId !== owner.ownerId
|
|
1558
|
-
|
|
1559
|
-
|
|
1562
|
+
if (record.snapshot.ownerId !== owner.ownerId ||
|
|
1563
|
+
record.snapshot.ownerLeaseGeneration !== owner.leaseGeneration ||
|
|
1564
|
+
record.aggregate !== undefined)
|
|
1560
1565
|
continue;
|
|
1561
1566
|
const encodedAuthority = authorityContractValueFromPreimage(candidate.key.value);
|
|
1562
1567
|
const identity = (0, authority_key_codec_1.decodeAuthorityKey)({ value: encodedAuthority });
|
|
@@ -1591,19 +1596,19 @@ class ZLinkLocationStoreRepository extends in_memory_location_store_1.ZLinkInMem
|
|
|
1591
1596
|
async removeOwnerCleanupBatch(owner, leaseKey, candidates, signal) {
|
|
1592
1597
|
if (candidates.length === 0)
|
|
1593
1598
|
return 0n;
|
|
1594
|
-
const currentRows = await Promise.all(candidates.map(candidate => this.provider.read(candidate.key, signal)));
|
|
1599
|
+
const currentRows = await Promise.all(candidates.map((candidate) => this.provider.read(candidate.key, signal)));
|
|
1595
1600
|
const unchangedOwnedRows = [];
|
|
1596
1601
|
for (let index = 0; index < candidates.length; index += 1) {
|
|
1597
1602
|
const candidate = candidates[index];
|
|
1598
1603
|
const current = currentRows[index];
|
|
1599
|
-
if (current.kind === 'missing'
|
|
1600
|
-
|
|
1604
|
+
if (current.kind === 'missing' ||
|
|
1605
|
+
current.value.version.value !== candidate.scanVersion.value) {
|
|
1601
1606
|
continue;
|
|
1602
1607
|
}
|
|
1603
1608
|
const record = decodeJson(current.value.bytes);
|
|
1604
1609
|
const descriptor = record.descriptor;
|
|
1605
|
-
if (descriptor.ownerId !== owner.ownerId
|
|
1606
|
-
|
|
1610
|
+
if (descriptor.ownerId !== owner.ownerId ||
|
|
1611
|
+
descriptorOwnerLeaseGeneration(descriptor) !== owner.leaseGeneration) {
|
|
1607
1612
|
continue;
|
|
1608
1613
|
}
|
|
1609
1614
|
unchangedOwnedRows.push({
|
|
@@ -1614,20 +1619,20 @@ class ZLinkLocationStoreRepository extends in_memory_location_store_1.ZLinkInMem
|
|
|
1614
1619
|
if (unchangedOwnedRows.length === 0)
|
|
1615
1620
|
return 0n;
|
|
1616
1621
|
const currentLease = await this.provider.read(leaseKey, signal);
|
|
1617
|
-
if (currentLease.kind === 'missing'
|
|
1618
|
-
|
|
1622
|
+
if (currentLease.kind === 'missing' ||
|
|
1623
|
+
liveOwnerLeaseGeneration(currentLease) !== owner.leaseGeneration) {
|
|
1619
1624
|
return 0n;
|
|
1620
1625
|
}
|
|
1621
1626
|
const result = await this.provider.write({
|
|
1622
1627
|
conditions: [
|
|
1623
1628
|
{ kind: 'version', key: leaseKey, expected: currentLease.value.version },
|
|
1624
|
-
...unchangedOwnedRows.map(row => ({
|
|
1629
|
+
...unchangedOwnedRows.map((row) => ({
|
|
1625
1630
|
kind: 'version',
|
|
1626
1631
|
key: row.key,
|
|
1627
1632
|
expected: row.scanVersion
|
|
1628
1633
|
}))
|
|
1629
1634
|
],
|
|
1630
|
-
mutations: unchangedOwnedRows.map(row => ({
|
|
1635
|
+
mutations: unchangedOwnedRows.map((row) => ({
|
|
1631
1636
|
kind: 'delete',
|
|
1632
1637
|
key: row.key
|
|
1633
1638
|
}))
|
|
@@ -1706,9 +1711,9 @@ class ZLinkLocationStoreRepository extends in_memory_location_store_1.ZLinkInMem
|
|
|
1706
1711
|
this.provider.read(leaseKey, signal),
|
|
1707
1712
|
this.provider.read(rowKey, signal)
|
|
1708
1713
|
]);
|
|
1709
|
-
if (refreshedLease.kind === 'missing'
|
|
1710
|
-
|
|
1711
|
-
|
|
1714
|
+
if (refreshedLease.kind === 'missing' ||
|
|
1715
|
+
!matchesLiveOwnerLease(refreshedLease, ownerId, leaseGeneration) ||
|
|
1716
|
+
!sameDescriptorPredecessor(predecessor, refreshedRow)) {
|
|
1712
1717
|
return ignoredStale(result.storeNow);
|
|
1713
1718
|
}
|
|
1714
1719
|
currentLease = refreshedLease;
|
|
@@ -1721,8 +1726,8 @@ class ZLinkLocationStoreRepository extends in_memory_location_store_1.ZLinkInMem
|
|
|
1721
1726
|
if (current.kind === 'missing')
|
|
1722
1727
|
return Locations_1.ZLinkLocationWriteStatus.IgnoredStale;
|
|
1723
1728
|
const descriptor = revive(decodeCanonicalDescriptorRecord(current.value.bytes).descriptor);
|
|
1724
|
-
if (descriptor.ownerId !== owner.ownerId
|
|
1725
|
-
|
|
1729
|
+
if (descriptor.ownerId !== owner.ownerId ||
|
|
1730
|
+
descriptor.leaseGeneration !== owner.leaseGeneration) {
|
|
1726
1731
|
return Locations_1.ZLinkLocationWriteStatus.IgnoredStale;
|
|
1727
1732
|
}
|
|
1728
1733
|
const result = await this.provider.write({
|
|
@@ -1743,7 +1748,7 @@ class ZLinkLocationStoreRepository extends in_memory_location_store_1.ZLinkInMem
|
|
|
1743
1748
|
throw new Error('Location Store scan snapshot expired.');
|
|
1744
1749
|
}
|
|
1745
1750
|
return {
|
|
1746
|
-
items: result.value.items.map(item => revive(decodeCanonicalDescriptorRecord(item.value.bytes).descriptor)),
|
|
1751
|
+
items: result.value.items.map((item) => revive(decodeCanonicalDescriptorRecord(item.value.bytes).descriptor)),
|
|
1747
1752
|
continuationToken: result.value.nextCursor?.value
|
|
1748
1753
|
};
|
|
1749
1754
|
}
|
|
@@ -1765,8 +1770,8 @@ class ZLinkLocationStoreRepository extends in_memory_location_store_1.ZLinkInMem
|
|
|
1765
1770
|
generation = BigInt(record.generation);
|
|
1766
1771
|
const stored = record.descriptor;
|
|
1767
1772
|
if (intent === 2) {
|
|
1768
|
-
if (stored.ownerId !== location.ownerId
|
|
1769
|
-
|
|
1773
|
+
if (stored.ownerId !== location.ownerId ||
|
|
1774
|
+
locationOwnerGeneration(stored) !== locationOwnerGeneration(location)) {
|
|
1770
1775
|
return {
|
|
1771
1776
|
status: Locations_1.ZLinkLocationWriteStatus.IgnoredStale,
|
|
1772
1777
|
generation,
|
|
@@ -1797,14 +1802,16 @@ class ZLinkLocationStoreRepository extends in_memory_location_store_1.ZLinkInMem
|
|
|
1797
1802
|
{ kind: 'version', key: leaseKey, expected: lease.value.version },
|
|
1798
1803
|
rowCondition
|
|
1799
1804
|
],
|
|
1800
|
-
mutations: [
|
|
1805
|
+
mutations: [
|
|
1806
|
+
{
|
|
1801
1807
|
kind: 'put',
|
|
1802
1808
|
key: rowKey,
|
|
1803
1809
|
bytes: encodeJson({
|
|
1804
1810
|
generation: generation.toString(),
|
|
1805
1811
|
descriptor: location
|
|
1806
1812
|
})
|
|
1807
|
-
}
|
|
1813
|
+
}
|
|
1814
|
+
]
|
|
1808
1815
|
}, signal);
|
|
1809
1816
|
return result.kind === 'applied'
|
|
1810
1817
|
? { status: Locations_1.ZLinkLocationWriteStatus.Stored, generation, updatedAt: result.storeNow }
|
|
@@ -1817,8 +1824,7 @@ class ZLinkLocationStoreRepository extends in_memory_location_store_1.ZLinkInMem
|
|
|
1817
1824
|
const record = decodeJson(current.value.bytes);
|
|
1818
1825
|
const descriptor = record.descriptor;
|
|
1819
1826
|
const leaseGeneration = descriptor.leaseGeneration ?? BigInt(record.generation);
|
|
1820
|
-
if (descriptor.ownerId !== owner.ownerId
|
|
1821
|
-
|| leaseGeneration !== owner.leaseGeneration) {
|
|
1827
|
+
if (descriptor.ownerId !== owner.ownerId || leaseGeneration !== owner.leaseGeneration) {
|
|
1822
1828
|
return Locations_1.ZLinkLocationWriteStatus.IgnoredStale;
|
|
1823
1829
|
}
|
|
1824
1830
|
const result = await this.provider.write({
|
|
@@ -1951,16 +1957,20 @@ class ZLinkLocationStoreRepository extends in_memory_location_store_1.ZLinkInMem
|
|
|
1951
1957
|
visibleStoreVersion: undefined
|
|
1952
1958
|
};
|
|
1953
1959
|
const result = await this.provider.write({
|
|
1954
|
-
conditions: [
|
|
1960
|
+
conditions: [
|
|
1961
|
+
{
|
|
1955
1962
|
kind: 'version',
|
|
1956
1963
|
key: rowKey,
|
|
1957
1964
|
expected: current.value.version
|
|
1958
|
-
}
|
|
1959
|
-
|
|
1965
|
+
}
|
|
1966
|
+
],
|
|
1967
|
+
mutations: [
|
|
1968
|
+
{
|
|
1960
1969
|
kind: 'put',
|
|
1961
1970
|
key: rowKey,
|
|
1962
1971
|
bytes: encodeAuthorityRecord(normalized)
|
|
1963
|
-
}
|
|
1972
|
+
}
|
|
1973
|
+
]
|
|
1964
1974
|
}, signal);
|
|
1965
1975
|
if (result.kind === 'applied')
|
|
1966
1976
|
return;
|
|
@@ -1978,8 +1988,7 @@ class ZLinkLocationStoreRepository extends in_memory_location_store_1.ZLinkInMem
|
|
|
1978
1988
|
if (result.kind === 'applied')
|
|
1979
1989
|
return;
|
|
1980
1990
|
const current = await this.provider.read(key, signal);
|
|
1981
|
-
if (current.kind !== 'found'
|
|
1982
|
-
|| !Buffer.from(current.value.bytes).equals(Buffer.from(bytes))) {
|
|
1991
|
+
if (current.kind !== 'found' || !Buffer.from(current.value.bytes).equals(Buffer.from(bytes))) {
|
|
1983
1992
|
throw new Error(`Immutable aggregate participant value changed: ${key.value}.`);
|
|
1984
1993
|
}
|
|
1985
1994
|
}
|
|
@@ -1998,11 +2007,13 @@ class ZLinkLocationStoreRepository extends in_memory_location_store_1.ZLinkInMem
|
|
|
1998
2007
|
return;
|
|
1999
2008
|
const result = await this.provider.write({
|
|
2000
2009
|
conditions: [{ kind: 'version', key, expected: current.value.version }],
|
|
2001
|
-
mutations: [
|
|
2010
|
+
mutations: [
|
|
2011
|
+
{
|
|
2002
2012
|
kind: 'put',
|
|
2003
2013
|
key,
|
|
2004
2014
|
bytes: encodeJson({ ...record, state: 'aborted' })
|
|
2005
|
-
}
|
|
2015
|
+
}
|
|
2016
|
+
]
|
|
2006
2017
|
}, signal);
|
|
2007
2018
|
if (result.kind === 'applied') {
|
|
2008
2019
|
await this.clearAggregateMarkersByScan(fence, signal);
|
|
@@ -2027,10 +2038,10 @@ class ZLinkLocationStoreRepository extends in_memory_location_store_1.ZLinkInMem
|
|
|
2027
2038
|
cursor = undefined;
|
|
2028
2039
|
continue;
|
|
2029
2040
|
}
|
|
2030
|
-
const matching = result.value.items.filter(item => {
|
|
2041
|
+
const matching = result.value.items.filter((item) => {
|
|
2031
2042
|
const record = decodeAuthorityRecord(item.value.bytes);
|
|
2032
|
-
return record.aggregate?.aggregateId === fence.aggregateId.value
|
|
2033
|
-
|
|
2043
|
+
return (record.aggregate?.aggregateId === fence.aggregateId.value &&
|
|
2044
|
+
record.aggregate.aggregateGeneration === fence.aggregateGeneration);
|
|
2034
2045
|
});
|
|
2035
2046
|
await parallelForEach(matching, 64, async (item) => {
|
|
2036
2047
|
await this.clearAggregateMarker(fence, item.key, signal);
|
|
@@ -2046,18 +2057,23 @@ class ZLinkLocationStoreRepository extends in_memory_location_store_1.ZLinkInMem
|
|
|
2046
2057
|
if (current.kind === 'missing')
|
|
2047
2058
|
return;
|
|
2048
2059
|
const record = decodeAuthorityRecord(current.value.bytes);
|
|
2049
|
-
if (record.aggregate === undefined
|
|
2050
|
-
|
|
2051
|
-
|
|
2060
|
+
if (record.aggregate === undefined ||
|
|
2061
|
+
record.aggregate.aggregateId !== fence.aggregateId.value ||
|
|
2062
|
+
record.aggregate.aggregateGeneration !== fence.aggregateGeneration) {
|
|
2052
2063
|
return;
|
|
2053
2064
|
}
|
|
2054
2065
|
const result = await this.provider.write({
|
|
2055
2066
|
conditions: [{ kind: 'version', key, expected: current.value.version }],
|
|
2056
|
-
mutations: [
|
|
2067
|
+
mutations: [
|
|
2068
|
+
{
|
|
2057
2069
|
kind: 'put',
|
|
2058
2070
|
key,
|
|
2059
|
-
bytes: encodeAuthorityRecord({
|
|
2060
|
-
|
|
2071
|
+
bytes: encodeAuthorityRecord({
|
|
2072
|
+
...record,
|
|
2073
|
+
aggregate: undefined
|
|
2074
|
+
})
|
|
2075
|
+
}
|
|
2076
|
+
]
|
|
2061
2077
|
}, signal);
|
|
2062
2078
|
if (result.kind === 'applied')
|
|
2063
2079
|
return;
|
|
@@ -2105,23 +2121,24 @@ class AmbiguousWriteReconcilingLocationStore {
|
|
|
2105
2121
|
throw new Error('Cannot reconcile an opaque Store write without mutations.');
|
|
2106
2122
|
}
|
|
2107
2123
|
const reconciliationSignal = AbortSignal.timeout(AMBIGUOUS_WRITE_RECONCILIATION_TIMEOUT_MS);
|
|
2108
|
-
const reads = await Promise.all(request.mutations.map(mutation => this.inner.read(mutation.key, reconciliationSignal)));
|
|
2124
|
+
const reads = await Promise.all(request.mutations.map((mutation) => this.inner.read(mutation.key, reconciliationSignal)));
|
|
2109
2125
|
const putVersions = [];
|
|
2110
2126
|
let storeNow = new Date(0);
|
|
2111
2127
|
for (let index = 0; index < request.mutations.length; index += 1) {
|
|
2112
2128
|
const mutation = request.mutations[index];
|
|
2113
2129
|
const read = reads[index];
|
|
2114
|
-
storeNow =
|
|
2115
|
-
|
|
2116
|
-
|
|
2130
|
+
storeNow =
|
|
2131
|
+
read.kind === 'found'
|
|
2132
|
+
? latestDate(storeNow, read.value.storeNow)
|
|
2133
|
+
: latestDate(storeNow, read.storeNow);
|
|
2117
2134
|
if (mutation.kind === 'delete') {
|
|
2118
2135
|
if (read.kind !== 'missing')
|
|
2119
2136
|
return { kind: 'conflict', storeNow };
|
|
2120
2137
|
continue;
|
|
2121
2138
|
}
|
|
2122
|
-
if (read.kind !== 'found'
|
|
2123
|
-
|
|
2124
|
-
|
|
2139
|
+
if (read.kind !== 'found' ||
|
|
2140
|
+
!Buffer.from(read.value.bytes).equals(Buffer.from(mutation.bytes)) ||
|
|
2141
|
+
!versionAdvanced(request.conditions, mutation.key, read.value.version)) {
|
|
2125
2142
|
return { kind: 'conflict', storeNow };
|
|
2126
2143
|
}
|
|
2127
2144
|
putVersions.push({ key: mutation.key, version: read.value.version });
|
|
@@ -2130,7 +2147,7 @@ class AmbiguousWriteReconcilingLocationStore {
|
|
|
2130
2147
|
}
|
|
2131
2148
|
}
|
|
2132
2149
|
function versionAdvanced(conditions, key, current) {
|
|
2133
|
-
const condition = conditions.find(candidate => candidate.key.value === key.value);
|
|
2150
|
+
const condition = conditions.find((candidate) => candidate.key.value === key.value);
|
|
2134
2151
|
return condition?.kind !== 'version' || condition.expected.value !== current.value;
|
|
2135
2152
|
}
|
|
2136
2153
|
function latestDate(left, right) {
|
|
@@ -2144,16 +2161,16 @@ function validateProviderAggregateRequest(request) {
|
|
|
2144
2161
|
if (request.inventoryDigest.byteLength !== 32) {
|
|
2145
2162
|
throw new TypeError('Aggregate inventory digest must contain 32 bytes.');
|
|
2146
2163
|
}
|
|
2147
|
-
const keys = request.participants.map(value => value.authorityKey.value);
|
|
2148
|
-
if (new Set(keys).size !== keys.length
|
|
2149
|
-
|
|
2164
|
+
const keys = request.participants.map((value) => value.authorityKey.value);
|
|
2165
|
+
if (new Set(keys).size !== keys.length ||
|
|
2166
|
+
keys.some((key, index) => index > 0 && keys[index - 1].localeCompare(key) >= 0)) {
|
|
2150
2167
|
throw new TypeError('Aggregate participants must be unique and canonically sorted.');
|
|
2151
2168
|
}
|
|
2152
2169
|
for (const participant of request.participants) {
|
|
2153
2170
|
requireText(participant.authorityKey.value, 'aggregate authority key');
|
|
2154
2171
|
requireText(participant.expectedStoreVersion.value, 'aggregate expected Store version');
|
|
2155
|
-
if (participant.authorityPayload.byteLength > 1024 * 1024
|
|
2156
|
-
|
|
2172
|
+
if (participant.authorityPayload.byteLength > 1024 * 1024 ||
|
|
2173
|
+
participant.membershipMutation.byteLength > 1024 * 1024) {
|
|
2157
2174
|
throw new RangeError('Aggregate participant value exceeds 1 MiB.');
|
|
2158
2175
|
}
|
|
2159
2176
|
}
|
|
@@ -2188,22 +2205,22 @@ function reconcileAggregatePrepare(record, fingerprint, fence) {
|
|
|
2188
2205
|
return undefined;
|
|
2189
2206
|
}
|
|
2190
2207
|
function sameAggregateMarker(marker, fence, index, participant) {
|
|
2191
|
-
return marker !== undefined
|
|
2192
|
-
|
|
2193
|
-
|
|
2194
|
-
|
|
2195
|
-
|
|
2196
|
-
|
|
2208
|
+
return (marker !== undefined &&
|
|
2209
|
+
marker.aggregateId === fence.aggregateId.value &&
|
|
2210
|
+
marker.aggregateGeneration === fence.aggregateGeneration &&
|
|
2211
|
+
marker.index === index &&
|
|
2212
|
+
marker.expectedStoreVersion === participant.expectedStoreVersion.value &&
|
|
2213
|
+
marker.ownerTransition === participant.ownerTransition);
|
|
2197
2214
|
}
|
|
2198
2215
|
function sameAggregateMarkerEntry(marker, fence, index, entry) {
|
|
2199
|
-
return marker !== undefined
|
|
2200
|
-
|
|
2201
|
-
|
|
2202
|
-
|
|
2203
|
-
|
|
2204
|
-
|
|
2205
|
-
|
|
2206
|
-
|
|
2216
|
+
return (marker !== undefined &&
|
|
2217
|
+
marker.aggregateId === fence.aggregateId.value &&
|
|
2218
|
+
marker.aggregateGeneration === fence.aggregateGeneration &&
|
|
2219
|
+
marker.index === index &&
|
|
2220
|
+
marker.expectedStoreVersion === entry.expectedStoreVersion &&
|
|
2221
|
+
marker.ownerTransition === entry.ownerTransition &&
|
|
2222
|
+
marker.authorityPayloadSha256 === entry.authorityPayloadSha256 &&
|
|
2223
|
+
marker.membershipMutationSha256 === entry.membershipMutationSha256);
|
|
2207
2224
|
}
|
|
2208
2225
|
function aggregateTarget(request) {
|
|
2209
2226
|
return {
|
|
@@ -2224,9 +2241,9 @@ function aggregateTargetFromRecord(record) {
|
|
|
2224
2241
|
function addCapacityVector(left, right) {
|
|
2225
2242
|
let spotType = left.spotType;
|
|
2226
2243
|
if (right.spotType !== undefined) {
|
|
2227
|
-
if (spotType !== undefined
|
|
2228
|
-
|
|
2229
|
-
|
|
2244
|
+
if (spotType !== undefined &&
|
|
2245
|
+
(spotType.objectKind !== right.spotType.objectKind ||
|
|
2246
|
+
spotType.stableType !== right.spotType.stableType)) {
|
|
2230
2247
|
throw new TypeError('Aggregate capacity contains more than one Spot type.');
|
|
2231
2248
|
}
|
|
2232
2249
|
spotType = {
|
|
@@ -2337,12 +2354,12 @@ function aggregateKey(fence) {
|
|
|
2337
2354
|
return (0, in_memory_provider_location_store_1.storeKey)(`${PREFIX}aggregate:${encodeURIComponent(fence.aggregateId.value)}:${fence.aggregateGeneration}`);
|
|
2338
2355
|
}
|
|
2339
2356
|
function aggregateParticipantPayloadKey(fence, index) {
|
|
2340
|
-
return (0, in_memory_provider_location_store_1.storeKey)(`${PREFIX}aggregate-participant:${encodeURIComponent(fence.aggregateId.value)}:`
|
|
2341
|
-
|
|
2357
|
+
return (0, in_memory_provider_location_store_1.storeKey)(`${PREFIX}aggregate-participant:${encodeURIComponent(fence.aggregateId.value)}:` +
|
|
2358
|
+
`${fence.aggregateGeneration}:${index}:authority`);
|
|
2342
2359
|
}
|
|
2343
2360
|
function aggregateParticipantMembershipKey(fence, index) {
|
|
2344
|
-
return (0, in_memory_provider_location_store_1.storeKey)(`${PREFIX}aggregate-participant:${encodeURIComponent(fence.aggregateId.value)}:`
|
|
2345
|
-
|
|
2361
|
+
return (0, in_memory_provider_location_store_1.storeKey)(`${PREFIX}aggregate-participant:${encodeURIComponent(fence.aggregateId.value)}:` +
|
|
2362
|
+
`${fence.aggregateGeneration}:${index}:membership`);
|
|
2346
2363
|
}
|
|
2347
2364
|
function capacityKey(meshName, nodeRid) {
|
|
2348
2365
|
return (0, in_memory_provider_location_store_1.storeKey)(`${PREFIX}capacity:${encodeURIComponent(meshName)}:${encodeURIComponent(nodeRid)}`);
|
|
@@ -2405,12 +2422,11 @@ function encodeJson(value) {
|
|
|
2405
2422
|
if (candidate instanceof Uint8Array) {
|
|
2406
2423
|
return { $bytes: Buffer.from(candidate).toString('base64') };
|
|
2407
2424
|
}
|
|
2408
|
-
if (key === 'spotTypes'
|
|
2409
|
-
|
|
2410
|
-
|
|
2411
|
-
|
|
2412
|
-
return Object.fromEntries(Object.entries(candidate)
|
|
2413
|
-
.sort(([left], [right]) => compareUtf16Ordinal(left, right)));
|
|
2425
|
+
if (key === 'spotTypes' &&
|
|
2426
|
+
candidate !== null &&
|
|
2427
|
+
typeof candidate === 'object' &&
|
|
2428
|
+
!Array.isArray(candidate)) {
|
|
2429
|
+
return Object.fromEntries(Object.entries(candidate).sort(([left], [right]) => compareUtf16Ordinal(left, right)));
|
|
2414
2430
|
}
|
|
2415
2431
|
return candidate;
|
|
2416
2432
|
}), 'utf8');
|
|
@@ -2420,24 +2436,25 @@ function compareUtf16Ordinal(left, right) {
|
|
|
2420
2436
|
}
|
|
2421
2437
|
function decodeJson(value) {
|
|
2422
2438
|
return JSON.parse(decodeText(value), (_key, candidate) => {
|
|
2423
|
-
if (candidate !== null
|
|
2424
|
-
|
|
2425
|
-
|
|
2426
|
-
|
|
2439
|
+
if (candidate !== null &&
|
|
2440
|
+
typeof candidate === 'object' &&
|
|
2441
|
+
Object.keys(candidate).length === 1 &&
|
|
2442
|
+
typeof candidate.$bigint === 'string') {
|
|
2427
2443
|
return BigInt(candidate.$bigint);
|
|
2428
2444
|
}
|
|
2429
|
-
if (candidate !== null
|
|
2430
|
-
|
|
2431
|
-
|
|
2432
|
-
|
|
2445
|
+
if (candidate !== null &&
|
|
2446
|
+
typeof candidate === 'object' &&
|
|
2447
|
+
Object.keys(candidate).length === 1 &&
|
|
2448
|
+
typeof candidate.$bytes === 'string') {
|
|
2433
2449
|
return Buffer.from(candidate.$bytes, 'base64');
|
|
2434
2450
|
}
|
|
2435
2451
|
return candidate;
|
|
2436
2452
|
});
|
|
2437
2453
|
}
|
|
2438
2454
|
function requireRecordVersion(value, kind) {
|
|
2439
|
-
if (value === null ||
|
|
2440
|
-
|
|
2455
|
+
if (value === null ||
|
|
2456
|
+
typeof value !== 'object' ||
|
|
2457
|
+
value.recordVersion !== 1) {
|
|
2441
2458
|
throw new Error(`Location Store ${kind} record has an unrecognized recordVersion.`);
|
|
2442
2459
|
}
|
|
2443
2460
|
}
|
|
@@ -2457,14 +2474,22 @@ function canonicalize(value) {
|
|
|
2457
2474
|
}
|
|
2458
2475
|
function reviveCanonical(value, key = '') {
|
|
2459
2476
|
const generationKeys = new Set([
|
|
2460
|
-
'generation',
|
|
2461
|
-
'
|
|
2462
|
-
'
|
|
2477
|
+
'generation',
|
|
2478
|
+
'leaseGeneration',
|
|
2479
|
+
'ownerLeaseGeneration',
|
|
2480
|
+
'objectGeneration',
|
|
2481
|
+
'authorityOwnerGeneration',
|
|
2482
|
+
'aggregateGeneration',
|
|
2483
|
+
'lifecycleGeneration',
|
|
2484
|
+
'descriptorRevision',
|
|
2485
|
+
'nodeGeneration',
|
|
2486
|
+
'applicationVersion',
|
|
2487
|
+
'requestEncodedSize'
|
|
2463
2488
|
]);
|
|
2464
2489
|
if (typeof value === 'string' && generationKeys.has(key))
|
|
2465
2490
|
return BigInt(value);
|
|
2466
2491
|
if (Array.isArray(value))
|
|
2467
|
-
return value.map(item => reviveCanonical(item));
|
|
2492
|
+
return value.map((item) => reviveCanonical(item));
|
|
2468
2493
|
if (value !== null && typeof value === 'object') {
|
|
2469
2494
|
return Object.fromEntries(Object.entries(value).map(([name, item]) => [name, reviveCanonical(item, name)]));
|
|
2470
2495
|
}
|
|
@@ -2476,7 +2501,11 @@ function decodeOwnerRecord(bytes) {
|
|
|
2476
2501
|
return record;
|
|
2477
2502
|
}
|
|
2478
2503
|
function encodeOwnerRecord(ownerId, leaseGeneration) {
|
|
2479
|
-
return encodeJson({
|
|
2504
|
+
return encodeJson({
|
|
2505
|
+
recordVersion: 1,
|
|
2506
|
+
ownerId,
|
|
2507
|
+
leaseGeneration: leaseGeneration.toString()
|
|
2508
|
+
});
|
|
2480
2509
|
}
|
|
2481
2510
|
function encodeCanonicalDescriptorRecord(generation, descriptor) {
|
|
2482
2511
|
// `generation` is an old Node-local row counter. The opaque record's
|
|
@@ -2540,7 +2569,7 @@ function canonicalMeshDescriptor(descriptor) {
|
|
|
2540
2569
|
entrySpotId: descriptor.entrySpotId ?? null,
|
|
2541
2570
|
channelWeights: descriptor.channelWeights,
|
|
2542
2571
|
applicationVersion: descriptor.applicationVersion.toString(),
|
|
2543
|
-
objectCapabilities: descriptor.objectCapabilities.map(capability => ({
|
|
2572
|
+
objectCapabilities: descriptor.objectCapabilities.map((capability) => ({
|
|
2544
2573
|
...capability,
|
|
2545
2574
|
objectKind: canonicalObjectKind(capability.objectKind),
|
|
2546
2575
|
policy: capability.policy === 'disabled' ? 'disabled' : capability.policy
|
|
@@ -2550,7 +2579,7 @@ function canonicalMeshDescriptor(descriptor) {
|
|
|
2550
2579
|
capacity: {
|
|
2551
2580
|
actors: descriptor.populationCapacity.actors,
|
|
2552
2581
|
spots: descriptor.populationCapacity.spots,
|
|
2553
|
-
spotTypes: descriptor.populationCapacity.spotTypes.map(capacity => ({
|
|
2582
|
+
spotTypes: descriptor.populationCapacity.spotTypes.map((capacity) => ({
|
|
2554
2583
|
...capacity,
|
|
2555
2584
|
objectKind: canonicalObjectKind(capacity.objectKind)
|
|
2556
2585
|
}))
|
|
@@ -2568,14 +2597,14 @@ function reviveCanonicalCapacity(value) {
|
|
|
2568
2597
|
return {
|
|
2569
2598
|
actors: value.actors,
|
|
2570
2599
|
spots: value.spots,
|
|
2571
|
-
spotTypes: value.spotTypes.map(capacity => ({
|
|
2600
|
+
spotTypes: value.spotTypes.map((capacity) => ({
|
|
2572
2601
|
...capacity,
|
|
2573
2602
|
objectKind: runtimeSpotObjectKind(String(capacity.objectKind))
|
|
2574
2603
|
}))
|
|
2575
2604
|
};
|
|
2576
2605
|
}
|
|
2577
2606
|
function reviveCanonicalCapabilities(value) {
|
|
2578
|
-
return value.map(capability => ({
|
|
2607
|
+
return value.map((capability) => ({
|
|
2579
2608
|
...capability,
|
|
2580
2609
|
objectKind: runtimeObjectKind(String(capability.objectKind))
|
|
2581
2610
|
}));
|
|
@@ -2599,11 +2628,21 @@ function runtimeSpotObjectKind(kind) {
|
|
|
2599
2628
|
return result;
|
|
2600
2629
|
}
|
|
2601
2630
|
function canonicalRuntimeState(state) {
|
|
2602
|
-
return ['preparing', 'serving', 'relocating', 'relocated', 'draining', 'stopped', 'error'][state]
|
|
2603
|
-
|
|
2631
|
+
return (['preparing', 'serving', 'relocating', 'relocated', 'draining', 'stopped', 'error'][state] ??
|
|
2632
|
+
(() => {
|
|
2633
|
+
throw new TypeError(`Location Store descriptor has invalid state '${state}'.`);
|
|
2634
|
+
})());
|
|
2604
2635
|
}
|
|
2605
2636
|
function runtimeState(state) {
|
|
2606
|
-
const index = [
|
|
2637
|
+
const index = [
|
|
2638
|
+
'preparing',
|
|
2639
|
+
'serving',
|
|
2640
|
+
'relocating',
|
|
2641
|
+
'relocated',
|
|
2642
|
+
'draining',
|
|
2643
|
+
'stopped',
|
|
2644
|
+
'error'
|
|
2645
|
+
].indexOf(state);
|
|
2607
2646
|
if (index < 0)
|
|
2608
2647
|
throw new TypeError(`Location Store descriptor has invalid state '${state}'.`);
|
|
2609
2648
|
return index;
|
|
@@ -2629,12 +2668,14 @@ function encodeAuthorityRecord(record) {
|
|
|
2629
2668
|
descriptorLifecycleGeneration: allocation.descriptorLifecycleGeneration.toString(),
|
|
2630
2669
|
capacity: canonicalAuthorityCapacity(allocation.capacity)
|
|
2631
2670
|
},
|
|
2632
|
-
pendingCreation: snapshot.pendingCreation === undefined
|
|
2633
|
-
|
|
2634
|
-
|
|
2635
|
-
|
|
2636
|
-
|
|
2637
|
-
|
|
2671
|
+
pendingCreation: snapshot.pendingCreation === undefined
|
|
2672
|
+
? null
|
|
2673
|
+
: {
|
|
2674
|
+
reservationId: snapshot.pendingCreation.reservationId,
|
|
2675
|
+
requestContentReference: snapshot.pendingCreation.requestContentReference,
|
|
2676
|
+
requestSha256: Buffer.from(snapshot.pendingCreation.requestSha256).toString('hex'),
|
|
2677
|
+
requestEncodedSize: Number(snapshot.pendingCreation.requestEncodedSize)
|
|
2678
|
+
}
|
|
2638
2679
|
};
|
|
2639
2680
|
// These fields gate Node-only creation/aggregate recovery. They are absent
|
|
2640
2681
|
// from normal authority values (including the golden vector), while the
|
|
@@ -2660,8 +2701,7 @@ function decodeAuthorityRecord(bytes) {
|
|
|
2660
2701
|
aggregate: value.aggregate === undefined
|
|
2661
2702
|
? undefined
|
|
2662
2703
|
: reviveCanonical(value.aggregate),
|
|
2663
|
-
visibleStoreVersion: typeof value.visibleStoreVersion === 'string'
|
|
2664
|
-
? value.visibleStoreVersion : undefined,
|
|
2704
|
+
visibleStoreVersion: typeof value.visibleStoreVersion === 'string' ? value.visibleStoreVersion : undefined,
|
|
2665
2705
|
snapshot: {
|
|
2666
2706
|
payload: Buffer.from(String(value.payload), 'base64'),
|
|
2667
2707
|
objectGeneration: BigInt(String(value.objectGeneration)),
|
|
@@ -2680,33 +2720,40 @@ function decodeAuthorityRecord(bytes) {
|
|
|
2680
2720
|
capacity: {
|
|
2681
2721
|
actors: Number(capacity.actors),
|
|
2682
2722
|
spots: Number(capacity.spots),
|
|
2683
|
-
spotType: capacity.spotType === null
|
|
2684
|
-
? undefined
|
|
2685
|
-
: decodeAuthoritySpotType(capacity.spotType)
|
|
2723
|
+
spotType: capacity.spotType === null ? undefined : decodeAuthoritySpotType(capacity.spotType)
|
|
2686
2724
|
}
|
|
2687
2725
|
},
|
|
2688
|
-
pendingCreation: pending === null
|
|
2689
|
-
|
|
2690
|
-
|
|
2691
|
-
|
|
2692
|
-
|
|
2693
|
-
|
|
2726
|
+
pendingCreation: pending === null
|
|
2727
|
+
? undefined
|
|
2728
|
+
: {
|
|
2729
|
+
reservationId: String(pending.reservationId),
|
|
2730
|
+
requestContentReference: String(pending.requestContentReference),
|
|
2731
|
+
requestSha256: Buffer.from(String(pending.requestSha256), 'hex'),
|
|
2732
|
+
requestEncodedSize: BigInt(String(pending.requestEncodedSize))
|
|
2733
|
+
}
|
|
2694
2734
|
}
|
|
2695
2735
|
};
|
|
2696
2736
|
}
|
|
2697
2737
|
function canonicalPlacementObjectKind(kind) {
|
|
2698
2738
|
switch (kind) {
|
|
2699
|
-
case 'actor':
|
|
2700
|
-
|
|
2701
|
-
case '
|
|
2739
|
+
case 'actor':
|
|
2740
|
+
return 'actor';
|
|
2741
|
+
case 'user_spot':
|
|
2742
|
+
return 'userSpot';
|
|
2743
|
+
case 'instance_spot':
|
|
2744
|
+
return 'instanceSpot';
|
|
2702
2745
|
}
|
|
2703
2746
|
}
|
|
2704
2747
|
function runtimePlacementObjectKind(kind) {
|
|
2705
2748
|
switch (kind) {
|
|
2706
|
-
case 'actor':
|
|
2707
|
-
|
|
2708
|
-
case '
|
|
2709
|
-
|
|
2749
|
+
case 'actor':
|
|
2750
|
+
return 'actor';
|
|
2751
|
+
case 'userSpot':
|
|
2752
|
+
return 'user_spot';
|
|
2753
|
+
case 'instanceSpot':
|
|
2754
|
+
return 'instance_spot';
|
|
2755
|
+
default:
|
|
2756
|
+
throw new Error(`Location Store authority record has an invalid allocation objectKind '${kind}'.`);
|
|
2710
2757
|
}
|
|
2711
2758
|
}
|
|
2712
2759
|
function canonicalAuthorityCapacity(capacity) {
|
|
@@ -2745,9 +2792,9 @@ function createTerminalRecord(request, now) {
|
|
|
2745
2792
|
}
|
|
2746
2793
|
const deadlineMs = publication.operationDeadline.getTime();
|
|
2747
2794
|
const expiresAtMs = deadlineMs + CREATION_TERMINAL_RETENTION_MS;
|
|
2748
|
-
if (!Number.isSafeInteger(deadlineMs)
|
|
2749
|
-
|
|
2750
|
-
|
|
2795
|
+
if (!Number.isSafeInteger(deadlineMs) ||
|
|
2796
|
+
!Number.isSafeInteger(expiresAtMs) ||
|
|
2797
|
+
expiresAtMs <= now.getTime()) {
|
|
2751
2798
|
throw new RangeError('Creation terminal expiry must be the live operation deadline plus five minutes.');
|
|
2752
2799
|
}
|
|
2753
2800
|
if (request.completion.kind === 'created') {
|
|
@@ -2785,13 +2832,13 @@ function validateCreationOperation(operation) {
|
|
|
2785
2832
|
if (sourceRidBytes < 1 || sourceRidBytes > 255 || sourceRid.includes('\0')) {
|
|
2786
2833
|
throw new TypeError('Creation terminal source node RID must contain 1..255 UTF-8 bytes without NUL.');
|
|
2787
2834
|
}
|
|
2788
|
-
if (operation.sourceNodeGeneration < 1n
|
|
2789
|
-
|
|
2790
|
-
|
|
2791
|
-
|
|
2792
|
-
|
|
2793
|
-
|
|
2794
|
-
|
|
2835
|
+
if (operation.sourceNodeGeneration < 1n ||
|
|
2836
|
+
operation.sourceNodeGeneration > MAX_U64 ||
|
|
2837
|
+
operation.operationId.high < 0n ||
|
|
2838
|
+
operation.operationId.high > MAX_U64 ||
|
|
2839
|
+
operation.operationId.low < 0n ||
|
|
2840
|
+
operation.operationId.low > MAX_U64 ||
|
|
2841
|
+
(operation.operationId.high === 0n && operation.operationId.low === 0n)) {
|
|
2795
2842
|
throw new RangeError('Creation terminal source generation and operation ID are invalid.');
|
|
2796
2843
|
}
|
|
2797
2844
|
}
|
|
@@ -2826,17 +2873,17 @@ function liveTargetDescriptor(descriptorRead, leaseRead, target) {
|
|
|
2826
2873
|
return undefined;
|
|
2827
2874
|
const descriptor = reviveMeshDescriptor(decodeCanonicalDescriptorRecord(descriptorRead.value.bytes).descriptor);
|
|
2828
2875
|
const lease = decodeOwnerRecord(leaseRead.value.bytes);
|
|
2829
|
-
return descriptor.meshName === target.meshName
|
|
2830
|
-
|
|
2831
|
-
|
|
2832
|
-
|
|
2833
|
-
|
|
2834
|
-
|
|
2835
|
-
|
|
2836
|
-
|
|
2837
|
-
|
|
2838
|
-
|
|
2839
|
-
|
|
2876
|
+
return descriptor.meshName === target.meshName &&
|
|
2877
|
+
String(descriptor.rid) === String(target.nodeRid) &&
|
|
2878
|
+
descriptor.lifecycleGeneration === target.nodeLifecycleGeneration &&
|
|
2879
|
+
descriptor.ownerId === target.owner.ownerId &&
|
|
2880
|
+
descriptor.leaseGeneration === target.owner.leaseGeneration &&
|
|
2881
|
+
descriptor.objectRole === contracts_1.ZLinkObjectRole.Server &&
|
|
2882
|
+
descriptor.state === contracts_1.ZLinkFrameworkRuntimeState.Serving &&
|
|
2883
|
+
lease.ownerId === target.owner.ownerId &&
|
|
2884
|
+
BigInt(lease.leaseGeneration) === target.owner.leaseGeneration &&
|
|
2885
|
+
leaseRead.value.expiresAt !== undefined &&
|
|
2886
|
+
leaseRead.value.expiresAt.getTime() > leaseRead.value.storeNow.getTime()
|
|
2840
2887
|
? descriptor
|
|
2841
2888
|
: undefined;
|
|
2842
2889
|
}
|
|
@@ -2861,21 +2908,22 @@ function capacityAvailable(descriptor, requested, capacity) {
|
|
|
2861
2908
|
const spotType = requested.spotType;
|
|
2862
2909
|
const typeCapacity = spotType === undefined
|
|
2863
2910
|
? undefined
|
|
2864
|
-
: descriptor.populationCapacity.spotTypes.find(candidate => candidate.objectKind === spotType.objectKind
|
|
2865
|
-
|
|
2911
|
+
: descriptor.populationCapacity.spotTypes.find((candidate) => candidate.objectKind === spotType.objectKind &&
|
|
2912
|
+
candidate.stableType === spotType.stableType);
|
|
2866
2913
|
const typeKey = spotType === undefined ? undefined : capacityTypeKey(spotType);
|
|
2867
|
-
return (descriptor.populationCapacity.actors.limit === 0
|
|
2868
|
-
|
|
2869
|
-
|
|
2870
|
-
|
|
2871
|
-
|
|
2872
|
-
|
|
2873
|
-
|
|
2874
|
-
|
|
2875
|
-
|
|
2876
|
-
|
|
2877
|
-
|
|
2878
|
-
|
|
2914
|
+
return ((descriptor.populationCapacity.actors.limit === 0 ||
|
|
2915
|
+
capacity.active.actors + capacity.pending.actors + requested.actors <=
|
|
2916
|
+
descriptor.populationCapacity.actors.limit) &&
|
|
2917
|
+
(descriptor.populationCapacity.spots.limit === 0 ||
|
|
2918
|
+
capacity.active.spots + capacity.pending.spots + requested.spots <=
|
|
2919
|
+
descriptor.populationCapacity.spots.limit) &&
|
|
2920
|
+
(spotType === undefined ||
|
|
2921
|
+
(typeCapacity !== undefined &&
|
|
2922
|
+
(typeCapacity.limit === 0 ||
|
|
2923
|
+
(capacity.active.spotTypes[typeKey] ?? 0) +
|
|
2924
|
+
(capacity.pending.spotTypes[typeKey] ?? 0) +
|
|
2925
|
+
spotType.count <=
|
|
2926
|
+
typeCapacity.limit))));
|
|
2879
2927
|
}
|
|
2880
2928
|
function addCapacity(usage, delta) {
|
|
2881
2929
|
return adjustCapacity(usage, delta, 1);
|
|
@@ -2912,24 +2960,23 @@ function cloneCapacity(value) {
|
|
|
2912
2960
|
};
|
|
2913
2961
|
}
|
|
2914
2962
|
function sameCapacityVector(left, right) {
|
|
2915
|
-
return left.actors === right.actors
|
|
2916
|
-
|
|
2917
|
-
|
|
2918
|
-
|
|
2919
|
-
|
|
2963
|
+
return (left.actors === right.actors &&
|
|
2964
|
+
left.spots === right.spots &&
|
|
2965
|
+
left.spotType?.objectKind === right.spotType?.objectKind &&
|
|
2966
|
+
left.spotType?.stableType === right.spotType?.stableType &&
|
|
2967
|
+
left.spotType?.count === right.spotType?.count);
|
|
2920
2968
|
}
|
|
2921
2969
|
function sameCreationTarget(snapshot, target) {
|
|
2922
|
-
return snapshot.allocation.descriptor.meshName === target.meshName
|
|
2923
|
-
|
|
2924
|
-
|
|
2925
|
-
|
|
2926
|
-
|
|
2927
|
-
&& snapshot.ownerLeaseGeneration === target.owner.leaseGeneration;
|
|
2970
|
+
return (snapshot.allocation.descriptor.meshName === target.meshName &&
|
|
2971
|
+
String(snapshot.allocation.descriptor.rid) === String(target.nodeRid) &&
|
|
2972
|
+
snapshot.allocation.descriptorLifecycleGeneration === target.nodeLifecycleGeneration &&
|
|
2973
|
+
snapshot.ownerId === target.owner.ownerId &&
|
|
2974
|
+
snapshot.ownerLeaseGeneration === target.owner.leaseGeneration);
|
|
2928
2975
|
}
|
|
2929
2976
|
const CANONICAL_AUTHORITY_MAGIC = Buffer.from('ZLAU');
|
|
2930
2977
|
function isCanonicalAuthorityPayload(payload) {
|
|
2931
|
-
return payload.byteLength >= CANONICAL_AUTHORITY_MAGIC.byteLength
|
|
2932
|
-
|
|
2978
|
+
return (payload.byteLength >= CANONICAL_AUTHORITY_MAGIC.byteLength &&
|
|
2979
|
+
Buffer.from(payload.buffer, payload.byteOffset, CANONICAL_AUTHORITY_MAGIC.byteLength).equals(CANONICAL_AUTHORITY_MAGIC));
|
|
2933
2980
|
}
|
|
2934
2981
|
function sameLiveOwner(lease, snapshot) {
|
|
2935
2982
|
if (lease.kind === 'missing')
|
|
@@ -2937,13 +2984,12 @@ function sameLiveOwner(lease, snapshot) {
|
|
|
2937
2984
|
return matchesLiveOwnerLease(lease, snapshot.ownerId, snapshot.ownerLeaseGeneration);
|
|
2938
2985
|
}
|
|
2939
2986
|
function matchesLiveOwnerLease(lease, ownerId, leaseGeneration) {
|
|
2940
|
-
if (lease.value.expiresAt === undefined
|
|
2941
|
-
|
|
2987
|
+
if (lease.value.expiresAt === undefined ||
|
|
2988
|
+
lease.value.expiresAt.getTime() <= lease.value.storeNow.getTime()) {
|
|
2942
2989
|
return false;
|
|
2943
2990
|
}
|
|
2944
2991
|
const owner = decodeOwnerRecord(lease.value.bytes);
|
|
2945
|
-
return owner.ownerId === ownerId
|
|
2946
|
-
&& BigInt(owner.leaseGeneration) === leaseGeneration;
|
|
2992
|
+
return owner.ownerId === ownerId && BigInt(owner.leaseGeneration) === leaseGeneration;
|
|
2947
2993
|
}
|
|
2948
2994
|
function sameDescriptorPredecessor(expected, current) {
|
|
2949
2995
|
if (expected.kind === 'missing' || current.kind === 'missing') {
|
|
@@ -2952,9 +2998,9 @@ function sameDescriptorPredecessor(expected, current) {
|
|
|
2952
2998
|
return Buffer.from(expected.value.bytes).equals(Buffer.from(current.value.bytes));
|
|
2953
2999
|
}
|
|
2954
3000
|
function liveOwnerLeaseGeneration(lease) {
|
|
2955
|
-
if (lease.kind === 'missing'
|
|
2956
|
-
|
|
2957
|
-
|
|
3001
|
+
if (lease.kind === 'missing' ||
|
|
3002
|
+
lease.value.expiresAt === undefined ||
|
|
3003
|
+
lease.value.expiresAt.getTime() <= lease.value.storeNow.getTime()) {
|
|
2958
3004
|
return undefined;
|
|
2959
3005
|
}
|
|
2960
3006
|
return BigInt(decodeOwnerRecord(lease.value.bytes).leaseGeneration);
|
|
@@ -2970,9 +3016,9 @@ function canTakeOverStoredLocation(intent, currentOwnerId, currentLeaseGeneratio
|
|
|
2970
3016
|
}
|
|
2971
3017
|
if (liveLeaseGeneration === undefined)
|
|
2972
3018
|
return true;
|
|
2973
|
-
return currentOwnerId === nextOwnerId
|
|
2974
|
-
|
|
2975
|
-
|
|
3019
|
+
return (currentOwnerId === nextOwnerId &&
|
|
3020
|
+
currentLeaseGeneration !== nextLeaseGeneration &&
|
|
3021
|
+
liveLeaseGeneration === nextLeaseGeneration);
|
|
2976
3022
|
}
|
|
2977
3023
|
function persistMeshDescriptor(descriptor) {
|
|
2978
3024
|
return descriptor;
|
|
@@ -3007,9 +3053,7 @@ function reviveMeshDescriptor(descriptor) {
|
|
|
3007
3053
|
return {
|
|
3008
3054
|
...descriptor,
|
|
3009
3055
|
rid: descriptor.rid,
|
|
3010
|
-
updatedAt: descriptor.updatedAt instanceof Date
|
|
3011
|
-
? descriptor.updatedAt
|
|
3012
|
-
: new Date(descriptor.updatedAt)
|
|
3056
|
+
updatedAt: descriptor.updatedAt instanceof Date ? descriptor.updatedAt : new Date(descriptor.updatedAt)
|
|
3013
3057
|
};
|
|
3014
3058
|
}
|
|
3015
3059
|
function reviveClientServerDescriptor(descriptor) {
|
|
@@ -3089,22 +3133,22 @@ function normalizeRoute(value) {
|
|
|
3089
3133
|
};
|
|
3090
3134
|
}
|
|
3091
3135
|
function matchesSpot(value, filter) {
|
|
3092
|
-
return (filter.meshName === undefined || value.meshName === filter.meshName)
|
|
3093
|
-
|
|
3094
|
-
|
|
3095
|
-
|
|
3136
|
+
return ((filter.meshName === undefined || value.meshName === filter.meshName) &&
|
|
3137
|
+
(filter.spotType === undefined || value.spotType === filter.spotType) &&
|
|
3138
|
+
(filter.nodeRid === undefined || String(value.ownerNodeRid) === String(filter.nodeRid)) &&
|
|
3139
|
+
(filter.spotKind === undefined || value.spotKind === filter.spotKind));
|
|
3096
3140
|
}
|
|
3097
3141
|
function matchesActor(value, filter) {
|
|
3098
|
-
return (filter.actorType === undefined || value.actorType === filter.actorType)
|
|
3099
|
-
|
|
3100
|
-
|
|
3101
|
-
|
|
3142
|
+
return ((filter.actorType === undefined || value.actorType === filter.actorType) &&
|
|
3143
|
+
(filter.nodeRid === undefined || String(value.ownerNodeRid) === String(filter.nodeRid)) &&
|
|
3144
|
+
(filter.spotId === undefined || String(value.spotId) === String(filter.spotId)) &&
|
|
3145
|
+
(filter.locationKind === undefined || value.spotKind === filter.locationKind));
|
|
3102
3146
|
}
|
|
3103
3147
|
function matchesRoute(value, filter) {
|
|
3104
|
-
return (filter.routeKind === undefined || value.routeKind === filter.routeKind)
|
|
3105
|
-
|
|
3106
|
-
|
|
3107
|
-
|
|
3148
|
+
return ((filter.routeKind === undefined || value.routeKind === filter.routeKind) &&
|
|
3149
|
+
(filter.ownerNodeRid === undefined ||
|
|
3150
|
+
String(value.ownerNodeRid) === String(filter.ownerNodeRid)) &&
|
|
3151
|
+
(filter.ownerId === undefined || value.ownerId === filter.ownerId));
|
|
3108
3152
|
}
|
|
3109
3153
|
function locationOwnerGeneration(value) {
|
|
3110
3154
|
return value.leaseGeneration;
|
|
@@ -3116,9 +3160,7 @@ function descriptorOwnerLeaseGeneration(value) {
|
|
|
3116
3160
|
: BigInt(value.leaseGeneration);
|
|
3117
3161
|
}
|
|
3118
3162
|
if ('generation' in value) {
|
|
3119
|
-
return typeof value.generation === 'bigint'
|
|
3120
|
-
? value.generation
|
|
3121
|
-
: BigInt(value.generation);
|
|
3163
|
+
return typeof value.generation === 'bigint' ? value.generation : BigInt(value.generation);
|
|
3122
3164
|
}
|
|
3123
3165
|
return undefined;
|
|
3124
3166
|
}
|
|
@@ -3132,25 +3174,24 @@ function sameFanoutDescriptor(left, right) {
|
|
|
3132
3174
|
return descriptorFingerprint(left, ['updatedAt']) === descriptorFingerprint(right, ['updatedAt']);
|
|
3133
3175
|
}
|
|
3134
3176
|
function canRenewMesh(current, next) {
|
|
3135
|
-
return sameOwnerGeneration(current, next)
|
|
3136
|
-
&& next.descriptorRevision > current.descriptorRevision;
|
|
3177
|
+
return sameOwnerGeneration(current, next) && next.descriptorRevision > current.descriptorRevision;
|
|
3137
3178
|
}
|
|
3138
3179
|
function canRenewClientServer(current, next) {
|
|
3139
|
-
return sameOwnerGeneration(current, next)
|
|
3140
|
-
|
|
3141
|
-
|
|
3142
|
-
|
|
3180
|
+
return (sameOwnerGeneration(current, next) &&
|
|
3181
|
+
next.descriptorRevision > current.descriptorRevision &&
|
|
3182
|
+
descriptorFingerprint(current, ['descriptorRevision', 'weight', 'state', 'updatedAt']) ===
|
|
3183
|
+
descriptorFingerprint(next, ['descriptorRevision', 'weight', 'state', 'updatedAt']));
|
|
3143
3184
|
}
|
|
3144
3185
|
function canRenewFanout(current, next) {
|
|
3145
|
-
return sameOwnerGeneration(current, next)
|
|
3146
|
-
|
|
3147
|
-
|
|
3148
|
-
|
|
3186
|
+
return (sameOwnerGeneration(current, next) &&
|
|
3187
|
+
next.descriptorRevision > current.descriptorRevision &&
|
|
3188
|
+
descriptorFingerprint(current, ['descriptorRevision', 'state', 'updatedAt']) ===
|
|
3189
|
+
descriptorFingerprint(next, ['descriptorRevision', 'state', 'updatedAt']));
|
|
3149
3190
|
}
|
|
3150
3191
|
function sameOwnerGeneration(left, right) {
|
|
3151
|
-
return left.ownerId === right.ownerId
|
|
3152
|
-
|
|
3153
|
-
|
|
3192
|
+
return (left.ownerId === right.ownerId &&
|
|
3193
|
+
left.leaseGeneration === right.leaseGeneration &&
|
|
3194
|
+
left.lifecycleGeneration === right.lifecycleGeneration);
|
|
3154
3195
|
}
|
|
3155
3196
|
function descriptorFingerprint(descriptor, omitted) {
|
|
3156
3197
|
// Descriptor rows are canonicalized through routing-id hex. Comparing the
|
|
@@ -3187,14 +3228,17 @@ function validateFanoutPublisherDescriptor(descriptor) {
|
|
|
3187
3228
|
validateDescriptorGenerations(descriptor, 'Fanout publisher');
|
|
3188
3229
|
}
|
|
3189
3230
|
function validateDescriptorIdentity(values, kind) {
|
|
3190
|
-
if (values.some(value => Buffer.byteLength(value, 'utf8') < 1 || value.includes('\0'))) {
|
|
3231
|
+
if (values.some((value) => Buffer.byteLength(value, 'utf8') < 1 || value.includes('\0'))) {
|
|
3191
3232
|
throw new TypeError(`${kind} descriptor identity and endpoint are required.`);
|
|
3192
3233
|
}
|
|
3193
3234
|
}
|
|
3194
3235
|
function validateDescriptorGenerations(descriptor, kind) {
|
|
3195
|
-
if (descriptor.lifecycleGeneration < 1n ||
|
|
3196
|
-
|
|
3197
|
-
|
|
3236
|
+
if (descriptor.lifecycleGeneration < 1n ||
|
|
3237
|
+
descriptor.lifecycleGeneration > MAX_GENERATION ||
|
|
3238
|
+
descriptor.descriptorRevision < 1n ||
|
|
3239
|
+
descriptor.descriptorRevision > MAX_GENERATION ||
|
|
3240
|
+
descriptor.leaseGeneration < 1n ||
|
|
3241
|
+
descriptor.leaseGeneration > MAX_GENERATION) {
|
|
3198
3242
|
throw new RangeError(`${kind} descriptor generations are invalid.`);
|
|
3199
3243
|
}
|
|
3200
3244
|
}
|