@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
|
@@ -26,18 +26,12 @@ import {
|
|
|
26
26
|
type ServiceRelocationPublication
|
|
27
27
|
} from '../foundation/service-relocation-runtime';
|
|
28
28
|
import { putNewRelocationBlob } from '../locations/relocation-blob';
|
|
29
|
-
import {
|
|
30
|
-
decodeRoutingId,
|
|
31
|
-
encodeRoutingIdStorageHex,
|
|
32
|
-
routingIdWireHex
|
|
33
|
-
} from '../routing-id';
|
|
29
|
+
import { decodeRoutingId, encodeRoutingIdStorageHex, routingIdWireHex } from '../routing-id';
|
|
34
30
|
import {
|
|
35
31
|
decodeRelocatingActorAuthorityIdentity,
|
|
36
32
|
encodeActorAuthorityIdentity
|
|
37
33
|
} from './actor-authority-publication';
|
|
38
|
-
import {
|
|
39
|
-
replaceActorRelocationAuthorityApplicationPayload
|
|
40
|
-
} from './actor-authority-payload-codec';
|
|
34
|
+
import { replaceActorRelocationAuthorityApplicationPayload } from './actor-authority-payload-codec';
|
|
41
35
|
import { ZLinkBufferMessage as RuntimeMessage } from '../backend/runtime-message';
|
|
42
36
|
import { wrapFrameworkPayloadMessage } from '../messaging/payload-codec';
|
|
43
37
|
import {
|
|
@@ -51,15 +45,9 @@ const RETENTION_MS = 24 * 60 * 60 * 1_000;
|
|
|
51
45
|
const ROOT_VERSION = 2;
|
|
52
46
|
const ROOT_MAGIC = Buffer.from('ZLJR');
|
|
53
47
|
const MAX_ROOT_BYTES = 1024 * 1024;
|
|
54
|
-
const JOURNAL_INVENTORY_DOMAIN = Buffer.from(
|
|
55
|
-
'zlink-node-deferred-join-authority-v1\0',
|
|
56
|
-
'utf8'
|
|
57
|
-
);
|
|
48
|
+
const JOURNAL_INVENTORY_DOMAIN = Buffer.from('zlink-node-deferred-join-authority-v1\0', 'utf8');
|
|
58
49
|
|
|
59
|
-
export type ZLinkDeferredJoinDeliveryCursor =
|
|
60
|
-
| 'prepared'
|
|
61
|
-
| 'committed'
|
|
62
|
-
| 'delivered';
|
|
50
|
+
export type ZLinkDeferredJoinDeliveryCursor = 'prepared' | 'committed' | 'delivered';
|
|
63
51
|
|
|
64
52
|
export interface ZLinkDeferredJoinAcceptedRoot {
|
|
65
53
|
readonly authority: ZLinkAuthoritySnapshot;
|
|
@@ -94,21 +82,25 @@ export async function isDeferredJoinAcceptedRootPublication(
|
|
|
94
82
|
if (hasJournalRootMagic(read.bytes)) {
|
|
95
83
|
try {
|
|
96
84
|
const root = decodeRoot(read.bytes);
|
|
97
|
-
return
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
85
|
+
return (
|
|
86
|
+
expected.aggregateId === operationAggregateId(root.operationId) &&
|
|
87
|
+
expected.aggregateGeneration === root.actor.objectGeneration &&
|
|
88
|
+
expected.authorityKey === encodeAuthorityKey('actor', root.actor.actorId).value &&
|
|
89
|
+
expected.objectGeneration === root.actor.objectGeneration
|
|
90
|
+
);
|
|
101
91
|
} catch {
|
|
102
92
|
return false;
|
|
103
93
|
}
|
|
104
94
|
}
|
|
105
95
|
const root = await readCanonicalDeferredJoinRoot(relocation, read.bytes, signal);
|
|
106
|
-
return
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
96
|
+
return (
|
|
97
|
+
root !== undefined &&
|
|
98
|
+
root.identity.aggregateId === expected.aggregateId &&
|
|
99
|
+
root.identity.aggregateGeneration === expected.aggregateGeneration &&
|
|
100
|
+
root.identity.authorityKey === expected.authorityKey &&
|
|
101
|
+
root.identity.objectKind === expected.objectKind &&
|
|
102
|
+
root.identity.objectGeneration === expected.objectGeneration
|
|
103
|
+
);
|
|
112
104
|
}
|
|
113
105
|
|
|
114
106
|
interface DeferredJoinAuthorityPublication {
|
|
@@ -175,20 +167,20 @@ export class ZLinkDeferredJoinAcceptedJournal {
|
|
|
175
167
|
} as const;
|
|
176
168
|
const initialPublication = decodeAuthorityPublication(read.payload);
|
|
177
169
|
const initialCanonicalIdentity = serviceRelocationAuthoritySlotIdentity(read.payload);
|
|
178
|
-
const canonicalPublication =
|
|
179
|
-
? initialPublication
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
170
|
+
const canonicalPublication =
|
|
171
|
+
initialPublication?.canonical === true ? initialPublication : undefined;
|
|
172
|
+
const root =
|
|
173
|
+
canonicalPublication !== undefined &&
|
|
174
|
+
(canonicalInventoryDigest !== undefined ||
|
|
175
|
+
!canonicalPublication.reference.value.startsWith('zlink-direct:'))
|
|
176
|
+
? await this.storeCanonicalRoot(
|
|
177
|
+
rootValue,
|
|
178
|
+
read,
|
|
179
|
+
canonicalPublication,
|
|
180
|
+
signal,
|
|
181
|
+
canonicalInventoryDigest
|
|
182
|
+
)
|
|
183
|
+
: await this.storeRoot(rootValue, signal);
|
|
192
184
|
if (initialCanonicalIdentity !== undefined && canonicalInventoryDigest !== undefined) {
|
|
193
185
|
return {
|
|
194
186
|
...root,
|
|
@@ -201,17 +193,19 @@ export class ZLinkDeferredJoinAcceptedJournal {
|
|
|
201
193
|
const canonicalIdentity = serviceRelocationAuthoritySlotIdentity(expected.payload);
|
|
202
194
|
const publication: DeferredJoinAuthorityPublication = {
|
|
203
195
|
applicationPayload: Buffer.from(
|
|
204
|
-
currentPublication?.applicationPayload
|
|
205
|
-
|
|
196
|
+
currentPublication?.applicationPayload ??
|
|
197
|
+
serviceRelocationAuthorityApplicationPayload(expected.payload)
|
|
206
198
|
),
|
|
207
199
|
reference: root.reference,
|
|
208
200
|
checksumCrc32c: root.checksumCrc32c,
|
|
209
|
-
aggregateId:
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
201
|
+
aggregateId:
|
|
202
|
+
canonicalIdentity !== undefined
|
|
203
|
+
? canonicalIdentity.aggregateId
|
|
204
|
+
: operationAggregateId(operationId),
|
|
205
|
+
aggregateGeneration:
|
|
206
|
+
canonicalIdentity === undefined
|
|
207
|
+
? actor.objectGeneration
|
|
208
|
+
: requireCanonicalAggregateGeneration(canonicalIdentity.aggregateGeneration),
|
|
215
209
|
targetOwnerId: expected.ownerId,
|
|
216
210
|
targetOwnerLeaseGeneration: expected.ownerLeaseGeneration,
|
|
217
211
|
...(currentPublication?.canonicalPublication === undefined
|
|
@@ -224,15 +218,16 @@ export class ZLinkDeferredJoinAcceptedJournal {
|
|
|
224
218
|
{
|
|
225
219
|
kind: 'put',
|
|
226
220
|
generationTransition: 'preserve',
|
|
227
|
-
payload:
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
221
|
+
payload:
|
|
222
|
+
currentPublication === undefined && canonicalIdentity !== undefined
|
|
223
|
+
? new ServiceRelocationAuthorityPayloadCodec().publish(
|
|
224
|
+
expected.payload,
|
|
225
|
+
toServiceRelocationPublication(publication)
|
|
226
|
+
)
|
|
227
|
+
: replaceDeferredJoinAuthorityPublication(
|
|
228
|
+
expected.payload,
|
|
229
|
+
encodeAuthorityPublication(publication)
|
|
230
|
+
)
|
|
236
231
|
},
|
|
237
232
|
signal
|
|
238
233
|
);
|
|
@@ -263,13 +258,8 @@ export class ZLinkDeferredJoinAcceptedJournal {
|
|
|
263
258
|
actorId: string,
|
|
264
259
|
signal?: AbortSignal
|
|
265
260
|
): Promise<ZLinkDeferredJoinAcceptedRoot | undefined> {
|
|
266
|
-
const read = await this.authority.readAuthority(
|
|
267
|
-
|
|
268
|
-
signal
|
|
269
|
-
);
|
|
270
|
-
return read.kind === 'snapshot'
|
|
271
|
-
? await this.readPublished(read, signal)
|
|
272
|
-
: undefined;
|
|
261
|
+
const read = await this.authority.readAuthority(encodeAuthorityKey('actor', actorId), signal);
|
|
262
|
+
return read.kind === 'snapshot' ? await this.readPublished(read, signal) : undefined;
|
|
273
263
|
}
|
|
274
264
|
|
|
275
265
|
markCommitted(
|
|
@@ -288,10 +278,7 @@ export class ZLinkDeferredJoinAcceptedJournal {
|
|
|
288
278
|
return this.moveCursor(root, 'delivered', undefined, signal);
|
|
289
279
|
}
|
|
290
280
|
|
|
291
|
-
async discardPrepared(
|
|
292
|
-
root: ZLinkDeferredJoinAcceptedRoot,
|
|
293
|
-
signal?: AbortSignal
|
|
294
|
-
): Promise<void> {
|
|
281
|
+
async discardPrepared(root: ZLinkDeferredJoinAcceptedRoot, signal?: AbortSignal): Promise<void> {
|
|
295
282
|
const key = encodeAuthorityKey('actor', root.actor.actorId);
|
|
296
283
|
for (let attempt = 0; attempt < 3; attempt++) {
|
|
297
284
|
const read = await this.authority.readAuthority(key, signal);
|
|
@@ -320,7 +307,9 @@ export class ZLinkDeferredJoinAcceptedJournal {
|
|
|
320
307
|
return;
|
|
321
308
|
}
|
|
322
309
|
}
|
|
323
|
-
throw new Error(
|
|
310
|
+
throw new Error(
|
|
311
|
+
`Actor '${root.actor.actorId}' deferred Join preparation could not be discarded.`
|
|
312
|
+
);
|
|
324
313
|
}
|
|
325
314
|
|
|
326
315
|
async deliver(
|
|
@@ -349,17 +338,18 @@ export class ZLinkDeferredJoinAcceptedJournal {
|
|
|
349
338
|
status: 'accepted',
|
|
350
339
|
operationId: current.operationId,
|
|
351
340
|
actor: current.actor,
|
|
352
|
-
reply:
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
341
|
+
reply:
|
|
342
|
+
current.rawReply.byteLength === 0
|
|
343
|
+
? undefined
|
|
344
|
+
: current.replyContentType === undefined
|
|
345
|
+
? ZLinkMessage.fromEncoded(ZLinkEncodedPayload.from(current.rawReply))
|
|
346
|
+
: wrapFrameworkPayloadMessage(
|
|
347
|
+
RuntimeMessage.from(current.rawReply),
|
|
348
|
+
this.messageSerializers,
|
|
349
|
+
current.replyContentType,
|
|
350
|
+
undefined,
|
|
351
|
+
'reply'
|
|
352
|
+
)
|
|
363
353
|
};
|
|
364
354
|
await actor.onJoinCompleted?.(completion);
|
|
365
355
|
let delivered = current;
|
|
@@ -388,9 +378,7 @@ export class ZLinkDeferredJoinAcceptedJournal {
|
|
|
388
378
|
if (current === undefined) return;
|
|
389
379
|
requireSameOperation(current, root.operationId, root.actor);
|
|
390
380
|
if (current.cursor !== 'delivered') {
|
|
391
|
-
throw new Error(
|
|
392
|
-
`Actor '${root.actor.actorId}' Join completion root is not Delivered.`
|
|
393
|
-
);
|
|
381
|
+
throw new Error(`Actor '${root.actor.actorId}' Join completion root is not Delivered.`);
|
|
394
382
|
}
|
|
395
383
|
const publication = decodeAuthorityPublication(read.payload);
|
|
396
384
|
if (publication === undefined) return;
|
|
@@ -433,27 +421,22 @@ export class ZLinkDeferredJoinAcceptedJournal {
|
|
|
433
421
|
const key = encodeAuthorityKey('actor', root.actor.actorId);
|
|
434
422
|
const read = await this.authority.readAuthority(key, signal);
|
|
435
423
|
if (read.kind !== 'snapshot') {
|
|
436
|
-
throw new Error(
|
|
424
|
+
throw new Error(
|
|
425
|
+
`Actor '${root.actor.actorId}' authority disappeared during Join completion.`
|
|
426
|
+
);
|
|
437
427
|
}
|
|
438
428
|
let current = await this.readPublished(read, signal);
|
|
439
429
|
if (current === undefined) {
|
|
440
430
|
const retainedRoot = await this.relocation.read(root.reference, signal);
|
|
441
|
-
if (
|
|
442
|
-
retainedRoot.kind === 'found'
|
|
443
|
-
&& crc32c(retainedRoot.bytes) === root.checksumCrc32c
|
|
444
|
-
) {
|
|
431
|
+
if (retainedRoot.kind === 'found' && crc32c(retainedRoot.bytes) === root.checksumCrc32c) {
|
|
445
432
|
const retained = hasJournalRootMagic(retainedRoot.bytes)
|
|
446
433
|
? decodeRoot(retainedRoot.bytes)
|
|
447
|
-
: (await readCanonicalDeferredJoinRoot(
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
{ ...root, ...retained },
|
|
454
|
-
root.operationId,
|
|
455
|
-
root.actor
|
|
456
|
-
)) {
|
|
434
|
+
: (await readCanonicalDeferredJoinRoot(this.relocation, retainedRoot.bytes, signal))
|
|
435
|
+
?.completion;
|
|
436
|
+
if (
|
|
437
|
+
retained?.cursor === 'delivered' &&
|
|
438
|
+
isSameOperation({ ...root, ...retained }, root.operationId, root.actor)
|
|
439
|
+
) {
|
|
457
440
|
current = {
|
|
458
441
|
authority: read,
|
|
459
442
|
reference: root.reference,
|
|
@@ -462,33 +445,39 @@ export class ZLinkDeferredJoinAcceptedJournal {
|
|
|
462
445
|
};
|
|
463
446
|
}
|
|
464
447
|
}
|
|
465
|
-
if (
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
448
|
+
if (
|
|
449
|
+
current === undefined &&
|
|
450
|
+
next === 'committed' &&
|
|
451
|
+
actor !== undefined &&
|
|
452
|
+
authorityMatchesActor(read.payload, actor)
|
|
469
453
|
) {
|
|
470
454
|
throw new ZLinkFrameworkException(
|
|
471
455
|
ZLinkFrameworkErrorKind.Unavailable,
|
|
472
|
-
`Actor '${root.actor.actorId}' Join completion delivery is indeterminate: `
|
|
473
|
-
|
|
456
|
+
`Actor '${root.actor.actorId}' Join completion delivery is indeterminate: ` +
|
|
457
|
+
'the authority no longer references the operation and no matching retained root exists.'
|
|
474
458
|
);
|
|
475
459
|
}
|
|
476
460
|
if (current === undefined) {
|
|
477
|
-
throw new Error(
|
|
461
|
+
throw new Error(
|
|
462
|
+
`Actor '${root.actor.actorId}' no longer references its Join completion root.`
|
|
463
|
+
);
|
|
478
464
|
}
|
|
479
465
|
}
|
|
480
466
|
requireSameOperation(current, root.operationId, root.actor);
|
|
481
467
|
if (cursorIndex(current.cursor) >= nextIndex) return current;
|
|
482
468
|
|
|
483
|
-
const replacement = await this.storeRoot(
|
|
484
|
-
|
|
469
|
+
const replacement = await this.storeRoot(
|
|
470
|
+
{
|
|
471
|
+
operationId: current.operationId,
|
|
485
472
|
actor: actor ?? current.actor,
|
|
486
473
|
rawReply: current.rawReply,
|
|
487
474
|
...(current.replyContentType === undefined
|
|
488
475
|
? {}
|
|
489
476
|
: { replyContentType: current.replyContentType }),
|
|
490
477
|
cursor: next
|
|
491
|
-
|
|
478
|
+
},
|
|
479
|
+
signal
|
|
480
|
+
);
|
|
492
481
|
const publication = decodeAuthorityPublication(read.payload);
|
|
493
482
|
if (publication === undefined) {
|
|
494
483
|
await this.deleteBestEffort(replacement.reference);
|
|
@@ -512,12 +501,13 @@ export class ZLinkDeferredJoinAcceptedJournal {
|
|
|
512
501
|
read.payload,
|
|
513
502
|
encodeAuthorityPublication({
|
|
514
503
|
...publication,
|
|
515
|
-
applicationPayload:
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
504
|
+
applicationPayload:
|
|
505
|
+
actor === undefined
|
|
506
|
+
? publication.applicationPayload
|
|
507
|
+
: replaceActorRelocationAuthorityApplicationPayload(
|
|
508
|
+
publication.applicationPayload,
|
|
509
|
+
encodeActorAuthorityIdentity({ ...identity, actor })
|
|
510
|
+
),
|
|
521
511
|
reference: replacement.reference,
|
|
522
512
|
checksumCrc32c: replacement.checksumCrc32c
|
|
523
513
|
})
|
|
@@ -553,31 +543,31 @@ export class ZLinkDeferredJoinAcceptedJournal {
|
|
|
553
543
|
const canonicalPhase = publication.canonicalPublication?.canonicalPhase;
|
|
554
544
|
if (canonicalPhase === 1 || canonicalPhase === 2) return undefined;
|
|
555
545
|
const read = await this.relocation.read(publication.reference, signal);
|
|
556
|
-
if (read.kind !== 'found' && publication.canonical === true
|
|
557
|
-
&& publication.reference.value.startsWith('zlink-direct:')) {
|
|
558
|
-
return undefined;
|
|
559
|
-
}
|
|
560
546
|
if (
|
|
561
|
-
read.kind !== 'found'
|
|
562
|
-
|
|
547
|
+
read.kind !== 'found' &&
|
|
548
|
+
publication.canonical === true &&
|
|
549
|
+
publication.reference.value.startsWith('zlink-direct:')
|
|
563
550
|
) {
|
|
551
|
+
return undefined;
|
|
552
|
+
}
|
|
553
|
+
if (read.kind !== 'found' || crc32c(read.bytes) !== publication.checksumCrc32c) {
|
|
564
554
|
throw new Error('Published deferred Join completion root is missing or corrupt.');
|
|
565
555
|
}
|
|
566
556
|
if (publication.canonical === true && !hasJournalRootMagic(read.bytes)) {
|
|
567
|
-
const root = await readCanonicalDeferredJoinRoot(
|
|
568
|
-
this.relocation,
|
|
569
|
-
read.bytes,
|
|
570
|
-
signal
|
|
571
|
-
);
|
|
557
|
+
const root = await readCanonicalDeferredJoinRoot(this.relocation, read.bytes, signal);
|
|
572
558
|
if (root === undefined) {
|
|
573
559
|
// A canonical relocation root and the post-commit Join journal share
|
|
574
560
|
// the embedded slot. A root without a completion remains Host-owned.
|
|
575
561
|
return undefined;
|
|
576
562
|
}
|
|
577
|
-
if (
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
563
|
+
if (
|
|
564
|
+
root.identity.aggregateId !== publication.aggregateId ||
|
|
565
|
+
root.identity.aggregateGeneration !== publication.aggregateGeneration ||
|
|
566
|
+
root.identity.objectGeneration !== authority.objectGeneration
|
|
567
|
+
) {
|
|
568
|
+
throw new Error(
|
|
569
|
+
'Published deferred Join completion root identity does not match its authority slot.'
|
|
570
|
+
);
|
|
581
571
|
}
|
|
582
572
|
return {
|
|
583
573
|
authority,
|
|
@@ -595,31 +585,18 @@ export class ZLinkDeferredJoinAcceptedJournal {
|
|
|
595
585
|
}
|
|
596
586
|
|
|
597
587
|
private async storeRoot(
|
|
598
|
-
value: Omit<
|
|
599
|
-
ZLinkDeferredJoinAcceptedRoot,
|
|
600
|
-
'authority' | 'reference' | 'checksumCrc32c'
|
|
601
|
-
>,
|
|
588
|
+
value: Omit<ZLinkDeferredJoinAcceptedRoot, 'authority' | 'reference' | 'checksumCrc32c'>,
|
|
602
589
|
signal?: AbortSignal
|
|
603
590
|
): Promise<Omit<ZLinkDeferredJoinAcceptedRoot, 'authority'>> {
|
|
604
591
|
const payload = encodeRoot(value);
|
|
605
592
|
const checksumCrc32c = crc32c(payload);
|
|
606
|
-
const stored = await putNewRelocationBlob(
|
|
607
|
-
|
|
608
|
-
payload,
|
|
609
|
-
RETENTION_MS,
|
|
610
|
-
signal
|
|
611
|
-
);
|
|
612
|
-
if (
|
|
613
|
-
stored.expiresAt.getTime() <= stored.storeNow.getTime()
|
|
614
|
-
) {
|
|
593
|
+
const stored = await putNewRelocationBlob(this.relocation, payload, RETENTION_MS, signal);
|
|
594
|
+
if (stored.expiresAt.getTime() <= stored.storeNow.getTime()) {
|
|
615
595
|
await this.deleteBestEffort(stored.reference);
|
|
616
596
|
throw new Error('Relocation Store returned an invalid deferred Join root receipt.');
|
|
617
597
|
}
|
|
618
598
|
const read = await this.relocation.read(stored.reference, signal);
|
|
619
|
-
if (
|
|
620
|
-
read.kind !== 'found'
|
|
621
|
-
|| !Buffer.from(read.bytes).equals(payload)
|
|
622
|
-
) {
|
|
599
|
+
if (read.kind !== 'found' || !Buffer.from(read.bytes).equals(payload)) {
|
|
623
600
|
await this.deleteBestEffort(stored.reference);
|
|
624
601
|
throw new Error('Relocation Store failed deferred Join root verification.');
|
|
625
602
|
}
|
|
@@ -632,10 +609,7 @@ export class ZLinkDeferredJoinAcceptedJournal {
|
|
|
632
609
|
}
|
|
633
610
|
|
|
634
611
|
private async storeCanonicalRoot(
|
|
635
|
-
value: Omit<
|
|
636
|
-
ZLinkDeferredJoinAcceptedRoot,
|
|
637
|
-
'authority' | 'reference' | 'checksumCrc32c'
|
|
638
|
-
>,
|
|
612
|
+
value: Omit<ZLinkDeferredJoinAcceptedRoot, 'authority' | 'reference' | 'checksumCrc32c'>,
|
|
639
613
|
authority: ZLinkAuthoritySnapshot,
|
|
640
614
|
publication: DeferredJoinAuthorityPublication,
|
|
641
615
|
signal?: AbortSignal,
|
|
@@ -649,24 +623,13 @@ export class ZLinkDeferredJoinAcceptedJournal {
|
|
|
649
623
|
inventory = Buffer.from(canonicalInventoryDigest, 'hex');
|
|
650
624
|
} else {
|
|
651
625
|
const current = await this.relocation.read(publication.reference, signal);
|
|
652
|
-
if (current.kind !== 'found'
|
|
653
|
-
|| crc32c(current.bytes) !== publication.checksumCrc32c) {
|
|
626
|
+
if (current.kind !== 'found' || crc32c(current.bytes) !== publication.checksumCrc32c) {
|
|
654
627
|
throw new Error('Canonical relocation manifest is missing or corrupt.');
|
|
655
628
|
}
|
|
656
629
|
inventory = decodeCanonicalTreeManifest(current.bytes).inventoryDigest;
|
|
657
630
|
}
|
|
658
|
-
const logicalRoot = encodeCanonicalDeferredJoinRoot(
|
|
659
|
-
|
|
660
|
-
authority,
|
|
661
|
-
publication,
|
|
662
|
-
inventory
|
|
663
|
-
);
|
|
664
|
-
const stored = await storeCanonicalTree(
|
|
665
|
-
this.relocation,
|
|
666
|
-
logicalRoot,
|
|
667
|
-
inventory,
|
|
668
|
-
signal
|
|
669
|
-
);
|
|
631
|
+
const logicalRoot = encodeCanonicalDeferredJoinRoot(value, authority, publication, inventory);
|
|
632
|
+
const stored = await storeCanonicalTree(this.relocation, logicalRoot, inventory, signal);
|
|
670
633
|
return {
|
|
671
634
|
...value,
|
|
672
635
|
rawReply: Buffer.from(value.rawReply),
|
|
@@ -692,46 +655,46 @@ function requireAuthorityActor(payload: Uint8Array, actor: ActorRef): void {
|
|
|
692
655
|
|
|
693
656
|
function authorityMatchesActor(payload: Uint8Array, actor: ActorRef): boolean {
|
|
694
657
|
const publication = decodeAuthorityPublication(payload);
|
|
695
|
-
const applications =
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
actor.objectGeneration
|
|
658
|
+
const applications =
|
|
659
|
+
publication === undefined
|
|
660
|
+
? [serviceRelocationAuthorityApplicationPayload(payload)]
|
|
661
|
+
: [publication.applicationPayload, serviceRelocationAuthorityApplicationPayload(payload)];
|
|
662
|
+
return applications.some((application) => {
|
|
663
|
+
const identity = decodeRelocatingActorAuthorityIdentity(application, actor.objectGeneration);
|
|
664
|
+
return (
|
|
665
|
+
identity !== undefined &&
|
|
666
|
+
identity.actor.actorId === actor.actorId &&
|
|
667
|
+
identity.actor.objectGeneration === actor.objectGeneration &&
|
|
668
|
+
routingIdWireHex(identity.actor.nodeRid) === routingIdWireHex(actor.nodeRid)
|
|
705
669
|
);
|
|
706
|
-
return identity !== undefined
|
|
707
|
-
&& identity.actor.actorId === actor.actorId
|
|
708
|
-
&& identity.actor.objectGeneration === actor.objectGeneration
|
|
709
|
-
&& routingIdWireHex(identity.actor.nodeRid) === routingIdWireHex(actor.nodeRid);
|
|
710
670
|
});
|
|
711
671
|
}
|
|
712
672
|
|
|
713
673
|
function encodeRoot(
|
|
714
|
-
value: Omit<
|
|
715
|
-
ZLinkDeferredJoinAcceptedRoot,
|
|
716
|
-
'authority' | 'reference' | 'checksumCrc32c'
|
|
717
|
-
>
|
|
674
|
+
value: Omit<ZLinkDeferredJoinAcceptedRoot, 'authority' | 'reference' | 'checksumCrc32c'>
|
|
718
675
|
): Buffer {
|
|
719
676
|
const nodeRidHex = routingIdWireHex(value.actor.nodeRid);
|
|
720
|
-
const encoded = Buffer.concat([
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
677
|
+
const encoded = Buffer.concat([
|
|
678
|
+
ROOT_MAGIC,
|
|
679
|
+
Buffer.from(
|
|
680
|
+
JSON.stringify({
|
|
681
|
+
version: ROOT_VERSION,
|
|
682
|
+
operationHigh: value.operationId.high.toString(),
|
|
683
|
+
operationLow: value.operationId.low.toString(),
|
|
684
|
+
actorId: value.actor.actorId,
|
|
685
|
+
actorGeneration: value.actor.objectGeneration.toString(),
|
|
686
|
+
actorMeshName: value.actor.meshName,
|
|
687
|
+
actorNodeRid: String(value.actor.nodeRid),
|
|
688
|
+
actorNodeRidHex: nodeRidHex,
|
|
689
|
+
rawReply: Buffer.from(value.rawReply).toString('base64'),
|
|
690
|
+
...(value.replyContentType === undefined
|
|
691
|
+
? {}
|
|
692
|
+
: { replyContentType: value.replyContentType }),
|
|
693
|
+
cursor: value.cursor
|
|
694
|
+
}),
|
|
695
|
+
'utf8'
|
|
696
|
+
)
|
|
697
|
+
]);
|
|
735
698
|
if (encoded.byteLength > MAX_ROOT_BYTES) {
|
|
736
699
|
throw new Error('Deferred Join completion root exceeds 1 MiB.');
|
|
737
700
|
}
|
|
@@ -745,22 +708,20 @@ function decodeRoot(
|
|
|
745
708
|
throw new Error('Deferred Join completion root size is invalid.');
|
|
746
709
|
}
|
|
747
710
|
const bytes = Buffer.from(payload);
|
|
748
|
-
const encoded = hasJournalRootMagic(bytes)
|
|
749
|
-
? bytes.subarray(ROOT_MAGIC.byteLength)
|
|
750
|
-
: bytes;
|
|
711
|
+
const encoded = hasJournalRootMagic(bytes) ? bytes.subarray(ROOT_MAGIC.byteLength) : bytes;
|
|
751
712
|
const value = JSON.parse(encoded.toString('utf8')) as Record<string, unknown>;
|
|
752
713
|
if (
|
|
753
|
-
value.version !== ROOT_VERSION
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
714
|
+
value.version !== ROOT_VERSION ||
|
|
715
|
+
typeof value.operationHigh !== 'string' ||
|
|
716
|
+
typeof value.operationLow !== 'string' ||
|
|
717
|
+
typeof value.actorId !== 'string' ||
|
|
718
|
+
typeof value.actorGeneration !== 'string' ||
|
|
719
|
+
typeof value.actorMeshName !== 'string' ||
|
|
720
|
+
typeof value.actorNodeRid !== 'string' ||
|
|
721
|
+
typeof value.rawReply !== 'string' ||
|
|
722
|
+
(value.replyContentType !== undefined &&
|
|
723
|
+
(typeof value.replyContentType !== 'string' || value.replyContentType.length === 0)) ||
|
|
724
|
+
!isCursor(value.cursor)
|
|
764
725
|
) {
|
|
765
726
|
throw new Error('Deferred Join completion root is invalid.');
|
|
766
727
|
}
|
|
@@ -795,10 +756,12 @@ function decodeRoot(
|
|
|
795
756
|
}
|
|
796
757
|
|
|
797
758
|
function encodeAuthorityPublication(value: DeferredJoinAuthorityPublication): Buffer {
|
|
798
|
-
return Buffer.from(
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
759
|
+
return Buffer.from(
|
|
760
|
+
new ServiceRelocationAuthorityPayloadCodec().publish(
|
|
761
|
+
value.applicationPayload,
|
|
762
|
+
toServiceRelocationPublication(value)
|
|
763
|
+
)
|
|
764
|
+
);
|
|
802
765
|
}
|
|
803
766
|
|
|
804
767
|
function toServiceRelocationPublication(
|
|
@@ -837,10 +800,7 @@ function replaceDeferredJoinAuthorityPublication(
|
|
|
837
800
|
const codec = new ServiceRelocationAuthorityPayloadCodec();
|
|
838
801
|
const currentPublication = codec.read(payload);
|
|
839
802
|
const replacementPublication = codec.read(replacement);
|
|
840
|
-
if (
|
|
841
|
-
currentPublication?.canonical === true
|
|
842
|
-
|| replacementPublication?.canonical === true
|
|
843
|
-
) {
|
|
803
|
+
if (currentPublication?.canonical === true || replacementPublication?.canonical === true) {
|
|
844
804
|
// Canonical authority has exactly one embedded relocation slot. A journal
|
|
845
805
|
// cursor replaces that slot atomically; it must never be wrapped or nested
|
|
846
806
|
// under an older ZLAR/application layer.
|
|
@@ -848,8 +808,8 @@ function replaceDeferredJoinAuthorityPublication(
|
|
|
848
808
|
}
|
|
849
809
|
const outerApplication = serviceRelocationAuthorityApplicationPayload(payload);
|
|
850
810
|
if (
|
|
851
|
-
!Buffer.from(outerApplication).equals(Buffer.from(payload))
|
|
852
|
-
|
|
811
|
+
!Buffer.from(outerApplication).equals(Buffer.from(payload)) &&
|
|
812
|
+
decodeDirectAuthorityPublication(outerApplication) !== undefined
|
|
853
813
|
) {
|
|
854
814
|
return replaceServiceRelocationAuthorityApplicationPayload(payload, replacement);
|
|
855
815
|
}
|
|
@@ -864,8 +824,8 @@ function decodeDirectAuthorityPublication(
|
|
|
864
824
|
const publication = new ServiceRelocationAuthorityPayloadCodec().read(payload);
|
|
865
825
|
if (publication === undefined) return undefined;
|
|
866
826
|
const applicationPayload = serviceRelocationAuthorityApplicationPayload(payload);
|
|
867
|
-
return publication.canonical === true
|
|
868
|
-
|
|
827
|
+
return publication.canonical === true ||
|
|
828
|
+
publication.inventoryDigest === journalInventoryDigest(applicationPayload)
|
|
869
829
|
? deferredJoinPublication(applicationPayload, publication)
|
|
870
830
|
: undefined;
|
|
871
831
|
}
|
|
@@ -889,8 +849,10 @@ function deferredJoinPublication(
|
|
|
889
849
|
|
|
890
850
|
function hasJournalRootMagic(payload: Uint8Array): boolean {
|
|
891
851
|
const bytes = Buffer.from(payload);
|
|
892
|
-
return
|
|
893
|
-
|
|
852
|
+
return (
|
|
853
|
+
bytes.byteLength >= ROOT_MAGIC.byteLength &&
|
|
854
|
+
bytes.subarray(0, ROOT_MAGIC.byteLength).equals(ROOT_MAGIC)
|
|
855
|
+
);
|
|
894
856
|
}
|
|
895
857
|
|
|
896
858
|
function journalInventoryDigest(applicationPayload: Uint8Array): string {
|
|
@@ -902,10 +864,12 @@ function journalInventoryDigest(applicationPayload: Uint8Array): string {
|
|
|
902
864
|
|
|
903
865
|
function operationAggregateId(operationId: ZLinkActorJoinOperationId): string {
|
|
904
866
|
const encoded = [operationId.high, operationId.low]
|
|
905
|
-
.map(value => BigInt.asUintN(64, value).toString(16).padStart(16, '0'))
|
|
867
|
+
.map((value) => BigInt.asUintN(64, value).toString(16).padStart(16, '0'))
|
|
906
868
|
.join('');
|
|
907
|
-
return
|
|
908
|
-
|
|
869
|
+
return (
|
|
870
|
+
`${encoded.slice(0, 8)}-${encoded.slice(8, 12)}-${encoded.slice(12, 16)}` +
|
|
871
|
+
`-${encoded.slice(16, 20)}-${encoded.slice(20)}`
|
|
872
|
+
);
|
|
909
873
|
}
|
|
910
874
|
|
|
911
875
|
function requireCanonicalAggregateGeneration(value: bigint): bigint {
|
|
@@ -946,8 +910,7 @@ function decodeCanonicalTreeManifest(payload: Uint8Array): CanonicalTreeManifest
|
|
|
946
910
|
if (chunks.length === 0) {
|
|
947
911
|
throw new Error('Canonical relocation chunk count is invalid.');
|
|
948
912
|
}
|
|
949
|
-
if (chunks.reduce((total, value) => total + value.length, 0n)
|
|
950
|
-
!== generated.totalLength) {
|
|
913
|
+
if (chunks.reduce((total, value) => total + value.length, 0n) !== generated.totalLength) {
|
|
951
914
|
throw new Error('Canonical relocation manifest length is invalid.');
|
|
952
915
|
}
|
|
953
916
|
return {
|
|
@@ -966,23 +929,29 @@ async function storeCanonicalTree(
|
|
|
966
929
|
): Promise<{ readonly reference: ZLinkBlobReference; readonly checksumCrc32c: number }> {
|
|
967
930
|
const logical = Buffer.from(logicalRoot);
|
|
968
931
|
const logicalChecksumCrc32c = crc32c(logical);
|
|
969
|
-
const chunk = Buffer.from(
|
|
970
|
-
|
|
971
|
-
data: logical
|
|
972
|
-
}));
|
|
973
|
-
const storedChunk = await putAndVerifyCanonicalBlob(store, chunk, signal);
|
|
974
|
-
const manifest = Buffer.from(encodeRelocationManifestV1({
|
|
975
|
-
logicalFormatVersion: 1,
|
|
976
|
-
totalLength: BigInt(logical.byteLength),
|
|
977
|
-
totalChecksumCrc32c: logicalChecksumCrc32c,
|
|
978
|
-
inventoryDigestSha256: Buffer.from(inventoryDigest),
|
|
979
|
-
chunks: [{
|
|
932
|
+
const chunk = Buffer.from(
|
|
933
|
+
encodeRelocationDataChunkV1({
|
|
980
934
|
order: 0,
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
935
|
+
data: logical
|
|
936
|
+
})
|
|
937
|
+
);
|
|
938
|
+
const storedChunk = await putAndVerifyCanonicalBlob(store, chunk, signal);
|
|
939
|
+
const manifest = Buffer.from(
|
|
940
|
+
encodeRelocationManifestV1({
|
|
941
|
+
logicalFormatVersion: 1,
|
|
942
|
+
totalLength: BigInt(logical.byteLength),
|
|
943
|
+
totalChecksumCrc32c: logicalChecksumCrc32c,
|
|
944
|
+
inventoryDigestSha256: Buffer.from(inventoryDigest),
|
|
945
|
+
chunks: [
|
|
946
|
+
{
|
|
947
|
+
order: 0,
|
|
948
|
+
reference: storedChunk.reference.value,
|
|
949
|
+
length: BigInt(logical.byteLength),
|
|
950
|
+
checksumCrc32c: logicalChecksumCrc32c
|
|
951
|
+
}
|
|
952
|
+
]
|
|
953
|
+
})
|
|
954
|
+
);
|
|
986
955
|
const storedManifest = await putAndVerifyCanonicalBlob(store, manifest, signal);
|
|
987
956
|
return {
|
|
988
957
|
reference: storedManifest.reference,
|
|
@@ -1008,13 +977,16 @@ async function readCanonicalDeferredJoinRoot(
|
|
|
1008
977
|
store: ZLinkRelocationStore,
|
|
1009
978
|
manifestPayload: Uint8Array,
|
|
1010
979
|
signal?: AbortSignal
|
|
1011
|
-
): Promise<
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
980
|
+
): Promise<
|
|
981
|
+
| {
|
|
982
|
+
readonly identity: ZLinkDeferredJoinRootIdentity;
|
|
983
|
+
readonly completion: Omit<
|
|
984
|
+
ZLinkDeferredJoinAcceptedRoot,
|
|
985
|
+
'authority' | 'reference' | 'checksumCrc32c'
|
|
986
|
+
>;
|
|
987
|
+
}
|
|
988
|
+
| undefined
|
|
989
|
+
> {
|
|
1018
990
|
let manifest: CanonicalTreeManifest;
|
|
1019
991
|
try {
|
|
1020
992
|
manifest = decodeCanonicalTreeManifest(manifestPayload);
|
|
@@ -1026,8 +998,7 @@ async function readCanonicalDeferredJoinRoot(
|
|
|
1026
998
|
const read = await store.read(expected.reference, signal);
|
|
1027
999
|
if (read.kind !== 'found') throw new Error('Canonical relocation chunk is missing.');
|
|
1028
1000
|
const chunk = decodeRelocationDataChunkV1(read.bytes);
|
|
1029
|
-
if (chunk.order !== expected.order
|
|
1030
|
-
|| BigInt(chunk.data.byteLength) !== expected.length) {
|
|
1001
|
+
if (chunk.order !== expected.order || BigInt(chunk.data.byteLength) !== expected.length) {
|
|
1031
1002
|
throw new Error('Canonical relocation chunk identity is invalid.');
|
|
1032
1003
|
}
|
|
1033
1004
|
const data = Buffer.from(chunk.data);
|
|
@@ -1037,8 +1008,10 @@ async function readCanonicalDeferredJoinRoot(
|
|
|
1037
1008
|
parts.push(data);
|
|
1038
1009
|
}
|
|
1039
1010
|
const logical = Buffer.concat(parts);
|
|
1040
|
-
if (
|
|
1041
|
-
|
|
1011
|
+
if (
|
|
1012
|
+
BigInt(logical.byteLength) !== manifest.logicalLength ||
|
|
1013
|
+
crc32c(logical) !== manifest.logicalChecksumCrc32c
|
|
1014
|
+
) {
|
|
1042
1015
|
throw new Error('Canonical relocation logical root checksum is invalid.');
|
|
1043
1016
|
}
|
|
1044
1017
|
return decodeCanonicalDeferredJoinRoot(logical);
|
|
@@ -1053,23 +1026,33 @@ function encodeCanonicalDeferredJoinRoot(
|
|
|
1053
1026
|
const key = encodeAuthorityKey('actor', value.actor.actorId).value;
|
|
1054
1027
|
const completion = encodeDotNetDeferredJoinCompletion(value);
|
|
1055
1028
|
return Buffer.concat([
|
|
1056
|
-
u32le(0x5a4c5231),
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
u64le(
|
|
1060
|
-
|
|
1029
|
+
u32le(0x5a4c5231),
|
|
1030
|
+
u16le(2),
|
|
1031
|
+
dotNetGuidBytes(publication.aggregateId),
|
|
1032
|
+
u64le(publication.aggregateGeneration),
|
|
1033
|
+
bytes32le(inventoryDigest),
|
|
1034
|
+
u32le(1),
|
|
1035
|
+
text16le(key),
|
|
1036
|
+
Buffer.of(1),
|
|
1037
|
+
u64le(authority.objectGeneration),
|
|
1038
|
+
u64le(authority.authorityOwnerGeneration),
|
|
1039
|
+
bytes32le(Buffer.alloc(0)),
|
|
1040
|
+
u32le(0),
|
|
1041
|
+
u32le(0),
|
|
1042
|
+
bytes32le(Buffer.alloc(0)),
|
|
1043
|
+
bytes32le(completion)
|
|
1061
1044
|
]);
|
|
1062
1045
|
}
|
|
1063
1046
|
|
|
1064
|
-
function decodeCanonicalDeferredJoinRoot(
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1047
|
+
function decodeCanonicalDeferredJoinRoot(payload: Uint8Array):
|
|
1048
|
+
| {
|
|
1049
|
+
readonly identity: ZLinkDeferredJoinRootIdentity;
|
|
1050
|
+
readonly completion: Omit<
|
|
1051
|
+
ZLinkDeferredJoinAcceptedRoot,
|
|
1052
|
+
'authority' | 'reference' | 'checksumCrc32c'
|
|
1053
|
+
>;
|
|
1054
|
+
}
|
|
1055
|
+
| undefined {
|
|
1073
1056
|
const reader = new LittleEndianReader(payload);
|
|
1074
1057
|
if (reader.u32() !== 0x5a4c5231 || reader.u16() !== 2) return undefined;
|
|
1075
1058
|
const aggregateId = canonicalUuidFromDotNetBytes(reader.take(16));
|
|
@@ -1077,25 +1060,32 @@ function decodeCanonicalDeferredJoinRoot(
|
|
|
1077
1060
|
reader.bytes32();
|
|
1078
1061
|
const count = reader.u32();
|
|
1079
1062
|
let completion: ReturnType<typeof decodeDotNetDeferredJoinCompletion> | undefined;
|
|
1080
|
-
let completionIdentity:
|
|
1081
|
-
ZLinkDeferredJoinRootIdentity,
|
|
1082
|
-
|
|
1083
|
-
> | undefined;
|
|
1063
|
+
let completionIdentity:
|
|
1064
|
+
| Pick<ZLinkDeferredJoinRootIdentity, 'authorityKey' | 'objectKind' | 'objectGeneration'>
|
|
1065
|
+
| undefined;
|
|
1084
1066
|
for (let index = 0; index < count; index++) {
|
|
1085
1067
|
const authorityKey = reader.text16();
|
|
1086
1068
|
const objectKind = reader.u8();
|
|
1087
1069
|
const objectGeneration = reader.u64();
|
|
1088
|
-
reader.u64();
|
|
1070
|
+
reader.u64();
|
|
1071
|
+
reader.bytes32();
|
|
1089
1072
|
const jobs = reader.u32();
|
|
1090
|
-
for (let job = 0; job < jobs; job++) {
|
|
1073
|
+
for (let job = 0; job < jobs; job++) {
|
|
1074
|
+
reader.u64();
|
|
1075
|
+
reader.bytes32();
|
|
1076
|
+
}
|
|
1091
1077
|
const timers = reader.u32();
|
|
1092
1078
|
for (let timer = 0; timer < timers; timer++) {
|
|
1093
|
-
reader.text16();
|
|
1079
|
+
reader.text16();
|
|
1080
|
+
reader.i64();
|
|
1081
|
+
reader.i64();
|
|
1082
|
+
reader.bytes32();
|
|
1094
1083
|
}
|
|
1095
1084
|
reader.bytes32();
|
|
1096
1085
|
const encodedCompletion = reader.bytes32();
|
|
1097
1086
|
if (encodedCompletion.byteLength !== 0) {
|
|
1098
|
-
if (completion !== undefined)
|
|
1087
|
+
if (completion !== undefined)
|
|
1088
|
+
throw new Error('Canonical relocation root has duplicate completions.');
|
|
1099
1089
|
completion = decodeDotNetDeferredJoinCompletion(encodedCompletion);
|
|
1100
1090
|
if (objectKind !== 1) return undefined;
|
|
1101
1091
|
completionIdentity = {
|
|
@@ -1107,9 +1097,10 @@ function decodeCanonicalDeferredJoinRoot(
|
|
|
1107
1097
|
}
|
|
1108
1098
|
if (!reader.done) throw new Error('Canonical relocation root has trailing bytes.');
|
|
1109
1099
|
if (completion === undefined || completionIdentity === undefined) return undefined;
|
|
1110
|
-
if (
|
|
1111
|
-
|
|
1112
|
-
|
|
1100
|
+
if (
|
|
1101
|
+
completion.actor.objectGeneration !== completionIdentity.objectGeneration ||
|
|
1102
|
+
encodeAuthorityKey('actor', completion.actor.actorId).value !== completionIdentity.authorityKey
|
|
1103
|
+
) {
|
|
1113
1104
|
return undefined;
|
|
1114
1105
|
}
|
|
1115
1106
|
return {
|
|
@@ -1127,9 +1118,15 @@ function encodeDotNetDeferredJoinCompletion(
|
|
|
1127
1118
|
): Buffer {
|
|
1128
1119
|
const routingId = Buffer.from(encodeRoutingIdStorageHex(value.actor.nodeRid), 'hex');
|
|
1129
1120
|
return Buffer.concat([
|
|
1130
|
-
u32le(0x5a4c4a43),
|
|
1131
|
-
|
|
1132
|
-
text16le(value.actor.
|
|
1121
|
+
u32le(0x5a4c4a43),
|
|
1122
|
+
Buffer.of(2),
|
|
1123
|
+
text16le(value.actor.actorId),
|
|
1124
|
+
u64le(value.actor.objectGeneration),
|
|
1125
|
+
u64le(value.operationId.high),
|
|
1126
|
+
u64le(value.operationId.low),
|
|
1127
|
+
text16le(value.actor.meshName),
|
|
1128
|
+
Buffer.of(routingId.byteLength),
|
|
1129
|
+
routingId,
|
|
1133
1130
|
u64le(value.actor.objectGeneration),
|
|
1134
1131
|
Buffer.of(value.replyContentType === undefined ? 0 : 1),
|
|
1135
1132
|
...(value.replyContentType === undefined ? [] : [text16le(value.replyContentType)]),
|
|
@@ -1180,8 +1177,12 @@ function decodeDotNetDeferredJoinCompletion(
|
|
|
1180
1177
|
class LittleEndianReader {
|
|
1181
1178
|
private offset = 0;
|
|
1182
1179
|
private readonly bytes: Buffer;
|
|
1183
|
-
constructor(payload: Uint8Array) {
|
|
1184
|
-
|
|
1180
|
+
constructor(payload: Uint8Array) {
|
|
1181
|
+
this.bytes = Buffer.from(payload);
|
|
1182
|
+
}
|
|
1183
|
+
get done(): boolean {
|
|
1184
|
+
return this.offset === this.bytes.byteLength;
|
|
1185
|
+
}
|
|
1185
1186
|
take(length: number): Buffer {
|
|
1186
1187
|
if (length < 0 || this.offset + length > this.bytes.byteLength) {
|
|
1187
1188
|
throw new Error('Canonical relocation root is truncated.');
|
|
@@ -1190,23 +1191,41 @@ class LittleEndianReader {
|
|
|
1190
1191
|
this.offset += length;
|
|
1191
1192
|
return result;
|
|
1192
1193
|
}
|
|
1193
|
-
u8(): number {
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1194
|
+
u8(): number {
|
|
1195
|
+
return this.take(1)[0]!;
|
|
1196
|
+
}
|
|
1197
|
+
u16(): number {
|
|
1198
|
+
return this.take(2).readUInt16LE();
|
|
1199
|
+
}
|
|
1200
|
+
u32(): number {
|
|
1201
|
+
return this.take(4).readUInt32LE();
|
|
1202
|
+
}
|
|
1203
|
+
u64(): bigint {
|
|
1204
|
+
return this.take(8).readBigUInt64LE();
|
|
1205
|
+
}
|
|
1206
|
+
i64(): bigint {
|
|
1207
|
+
return this.take(8).readBigInt64LE();
|
|
1208
|
+
}
|
|
1198
1209
|
text16(): string {
|
|
1199
1210
|
const bytes = this.take(this.u16());
|
|
1200
1211
|
return new TextDecoder('utf-8', { fatal: true }).decode(bytes);
|
|
1201
1212
|
}
|
|
1202
|
-
bytes32(): Buffer {
|
|
1213
|
+
bytes32(): Buffer {
|
|
1214
|
+
return this.take(this.u32());
|
|
1215
|
+
}
|
|
1203
1216
|
}
|
|
1204
1217
|
|
|
1205
1218
|
function dotNetGuidBytes(value: string): Buffer {
|
|
1206
1219
|
const bytes = Buffer.from(value.replaceAll('-', ''), 'hex');
|
|
1207
1220
|
return Buffer.from([
|
|
1208
|
-
bytes[3]!,
|
|
1209
|
-
bytes[
|
|
1221
|
+
bytes[3]!,
|
|
1222
|
+
bytes[2]!,
|
|
1223
|
+
bytes[1]!,
|
|
1224
|
+
bytes[0]!,
|
|
1225
|
+
bytes[5]!,
|
|
1226
|
+
bytes[4]!,
|
|
1227
|
+
bytes[7]!,
|
|
1228
|
+
bytes[6]!,
|
|
1210
1229
|
...bytes.subarray(8)
|
|
1211
1230
|
]);
|
|
1212
1231
|
}
|
|
@@ -1217,13 +1236,20 @@ function canonicalUuidFromDotNetBytes(value: Uint8Array): string {
|
|
|
1217
1236
|
throw new TypeError('Canonical relocation aggregate id is invalid.');
|
|
1218
1237
|
}
|
|
1219
1238
|
const canonical = Buffer.from([
|
|
1220
|
-
bytes[3]!,
|
|
1221
|
-
bytes[
|
|
1222
|
-
bytes[
|
|
1239
|
+
bytes[3]!,
|
|
1240
|
+
bytes[2]!,
|
|
1241
|
+
bytes[1]!,
|
|
1242
|
+
bytes[0]!,
|
|
1243
|
+
bytes[5]!,
|
|
1244
|
+
bytes[4]!,
|
|
1245
|
+
bytes[7]!,
|
|
1246
|
+
bytes[6]!,
|
|
1223
1247
|
...bytes.subarray(8)
|
|
1224
1248
|
]).toString('hex');
|
|
1225
|
-
return
|
|
1226
|
-
|
|
1249
|
+
return (
|
|
1250
|
+
`${canonical.slice(0, 8)}-${canonical.slice(8, 12)}-${canonical.slice(12, 16)}` +
|
|
1251
|
+
`-${canonical.slice(16, 20)}-${canonical.slice(20)}`
|
|
1252
|
+
);
|
|
1227
1253
|
}
|
|
1228
1254
|
|
|
1229
1255
|
function text16le(value: string): Buffer {
|
|
@@ -1237,15 +1263,21 @@ function bytes32le(value: Uint8Array): Buffer {
|
|
|
1237
1263
|
}
|
|
1238
1264
|
|
|
1239
1265
|
function u16le(value: number): Buffer {
|
|
1240
|
-
const result = Buffer.alloc(2);
|
|
1266
|
+
const result = Buffer.alloc(2);
|
|
1267
|
+
result.writeUInt16LE(value);
|
|
1268
|
+
return result;
|
|
1241
1269
|
}
|
|
1242
1270
|
|
|
1243
1271
|
function u32le(value: number): Buffer {
|
|
1244
|
-
const result = Buffer.alloc(4);
|
|
1272
|
+
const result = Buffer.alloc(4);
|
|
1273
|
+
result.writeUInt32LE(value);
|
|
1274
|
+
return result;
|
|
1245
1275
|
}
|
|
1246
1276
|
|
|
1247
1277
|
function u64le(value: bigint): Buffer {
|
|
1248
|
-
const result = Buffer.alloc(8);
|
|
1278
|
+
const result = Buffer.alloc(8);
|
|
1279
|
+
result.writeBigUInt64LE(value);
|
|
1280
|
+
return result;
|
|
1249
1281
|
}
|
|
1250
1282
|
|
|
1251
1283
|
function validateIdentity(
|
|
@@ -1254,10 +1286,10 @@ function validateIdentity(
|
|
|
1254
1286
|
actor: ActorRef
|
|
1255
1287
|
): void {
|
|
1256
1288
|
if (
|
|
1257
|
-
actorId.length === 0
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1289
|
+
actorId.length === 0 ||
|
|
1290
|
+
actor.actorId !== actorId ||
|
|
1291
|
+
actor.objectGeneration <= 0n ||
|
|
1292
|
+
(operationId.high === 0n && operationId.low === 0n)
|
|
1261
1293
|
) {
|
|
1262
1294
|
throw new Error('Deferred Join completion identity is invalid.');
|
|
1263
1295
|
}
|
|
@@ -1278,24 +1310,23 @@ function isSameOperation(
|
|
|
1278
1310
|
operationId: ZLinkActorJoinOperationId,
|
|
1279
1311
|
actor: ActorRef
|
|
1280
1312
|
): boolean {
|
|
1281
|
-
return
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1313
|
+
return (
|
|
1314
|
+
root.operationId.high === operationId.high &&
|
|
1315
|
+
root.operationId.low === operationId.low &&
|
|
1316
|
+
root.actor.actorId === actor.actorId &&
|
|
1317
|
+
root.actor.objectGeneration === actor.objectGeneration
|
|
1318
|
+
);
|
|
1285
1319
|
}
|
|
1286
1320
|
|
|
1287
|
-
function requireSameActor(
|
|
1288
|
-
root: ZLinkDeferredJoinAcceptedRoot,
|
|
1289
|
-
actor: ActorRef
|
|
1290
|
-
): void {
|
|
1321
|
+
function requireSameActor(root: ZLinkDeferredJoinAcceptedRoot, actor: ActorRef): void {
|
|
1291
1322
|
if (
|
|
1292
|
-
root.actor.actorId !== actor.actorId
|
|
1293
|
-
|
|
1323
|
+
root.actor.actorId !== actor.actorId ||
|
|
1324
|
+
root.actor.objectGeneration !== actor.objectGeneration
|
|
1294
1325
|
) {
|
|
1295
1326
|
throw new Error(
|
|
1296
|
-
'Deferred Join completion generation fence is stale '
|
|
1297
|
-
|
|
1298
|
-
|
|
1327
|
+
'Deferred Join completion generation fence is stale ' +
|
|
1328
|
+
`(root ${root.actor.actorId}/${root.actor.objectGeneration}, ` +
|
|
1329
|
+
`actor ${actor.actorId}/${actor.objectGeneration}).`
|
|
1299
1330
|
);
|
|
1300
1331
|
}
|
|
1301
1332
|
}
|