@zlink-systems/framework 0.20.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
|
@@ -12,9 +12,7 @@ import type {
|
|
|
12
12
|
ApplicationJobPermitPort,
|
|
13
13
|
ApplicationJobQueuePort
|
|
14
14
|
} from '../application-jobs/contracts';
|
|
15
|
-
import {
|
|
16
|
-
ApplicationIngressRecordOwner
|
|
17
|
-
} from '../application-jobs/application-ingress-record-owner';
|
|
15
|
+
import { ApplicationIngressRecordOwner } from '../application-jobs/application-ingress-record-owner';
|
|
18
16
|
import { OperationRegistry, type PendingOperation } from './operation-registry';
|
|
19
17
|
import { ServiceLivenessRegistry, type ServiceLivenessTick } from './service-liveness-registry';
|
|
20
18
|
import { ServiceMailbox, type ServiceMailboxRecord } from './service-mailbox';
|
|
@@ -55,16 +53,9 @@ import {
|
|
|
55
53
|
} from './service-wire-constants.generated';
|
|
56
54
|
|
|
57
55
|
export type RawServicePumpResult =
|
|
58
|
-
| '
|
|
59
|
-
| 'infrastructure'
|
|
60
|
-
| 'application'
|
|
61
|
-
| 'dropped'
|
|
62
|
-
| 'protocolError';
|
|
56
|
+
'noData' | 'infrastructure' | 'application' | 'dropped' | 'protocolError';
|
|
63
57
|
|
|
64
|
-
export type RawServicePumpObserver = (
|
|
65
|
-
sourceRoutingId: string,
|
|
66
|
-
byteCount: number
|
|
67
|
-
) => void;
|
|
58
|
+
export type RawServicePumpObserver = (sourceRoutingId: string, byteCount: number) => void;
|
|
68
59
|
|
|
69
60
|
export interface RawServiceRequestResult {
|
|
70
61
|
readonly terminalResult: number;
|
|
@@ -101,10 +92,7 @@ export interface RawServiceMeshRuntimeOptions {
|
|
|
101
92
|
readonly peerAdmissionSealed?: () => boolean;
|
|
102
93
|
readonly onReceiveFlowConfigFailure?: (error: unknown) => void;
|
|
103
94
|
readonly onMailboxReady?: (domain: 'application' | 'infrastructure') => void;
|
|
104
|
-
readonly onPeerNotRequired?: (
|
|
105
|
-
nodeRoutingId: string,
|
|
106
|
-
endpoint: string
|
|
107
|
-
) => void;
|
|
95
|
+
readonly onPeerNotRequired?: (nodeRoutingId: string, endpoint: string) => void;
|
|
108
96
|
readonly onPeerDisconnected?: (
|
|
109
97
|
nodeRoutingId: string,
|
|
110
98
|
endpoint: string,
|
|
@@ -153,13 +141,16 @@ export class RawServiceMeshRuntime {
|
|
|
153
141
|
readonly liveness: ServiceLivenessRegistry;
|
|
154
142
|
|
|
155
143
|
private readonly operations = new OperationRegistry<RawServiceRequestResult>();
|
|
156
|
-
private readonly expectedPeers = new Map<
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
144
|
+
private readonly expectedPeers = new Map<
|
|
145
|
+
string,
|
|
146
|
+
{
|
|
147
|
+
readonly meshName: string;
|
|
148
|
+
readonly nodeRoutingId: string;
|
|
149
|
+
readonly endpoint?: string;
|
|
150
|
+
readonly securityIdentity?: string;
|
|
151
|
+
readonly lifecycleGeneration?: bigint;
|
|
152
|
+
}
|
|
153
|
+
>();
|
|
163
154
|
private readonly endpointOnlyPeers = new Set<string>();
|
|
164
155
|
private readonly peerConnectionIntentRemoved = new Set<(nodeRoutingId: string) => void>();
|
|
165
156
|
private readonly connectionCandidates = new Map<
|
|
@@ -183,8 +174,7 @@ export class RawServiceMeshRuntime {
|
|
|
183
174
|
private readonly onPeerNotRequired?: RawServiceMeshRuntimeOptions['onPeerNotRequired'];
|
|
184
175
|
private readonly onPeerDisconnected?: RawServiceMeshRuntimeOptions['onPeerDisconnected'];
|
|
185
176
|
private readonly onProtocolError?: RawServiceMeshRuntimeOptions['onProtocolError'];
|
|
186
|
-
private readonly onReceiveFlowConfigFailure?:
|
|
187
|
-
RawServiceMeshRuntimeOptions['onReceiveFlowConfigFailure'];
|
|
177
|
+
private readonly onReceiveFlowConfigFailure?: RawServiceMeshRuntimeOptions['onReceiveFlowConfigFailure'];
|
|
188
178
|
private readonly resolveAdvertisedEndpoint?: RawServiceMeshRuntimeOptions['resolveAdvertisedEndpoint'];
|
|
189
179
|
private descriptor: ServiceNodeDescriptor;
|
|
190
180
|
private host?: ZLinkRawHostPort;
|
|
@@ -223,15 +213,14 @@ export class RawServiceMeshRuntime {
|
|
|
223
213
|
router.setRoutingId(this.descriptor.nodeRoutingId);
|
|
224
214
|
this.applicationJobQueue.registerReceiveFlowTarget?.(
|
|
225
215
|
router,
|
|
226
|
-
state => receiveFlowRouter.setReceiveFlowState(state),
|
|
216
|
+
(state) => receiveFlowRouter.setReceiveFlowState(state),
|
|
227
217
|
this.onReceiveFlowConfigFailure
|
|
228
218
|
);
|
|
229
219
|
router.bind(this.descriptor.advertisedEndpoint);
|
|
230
220
|
const boundEndpoint = router.localEndpoint();
|
|
231
221
|
const next = {
|
|
232
222
|
...this.descriptor,
|
|
233
|
-
advertisedEndpoint: this.resolveAdvertisedEndpoint?.(boundEndpoint)
|
|
234
|
-
?? boundEndpoint,
|
|
223
|
+
advertisedEndpoint: this.resolveAdvertisedEndpoint?.(boundEndpoint) ?? boundEndpoint,
|
|
235
224
|
descriptorRevision: this.descriptor.descriptorRevision + 1n,
|
|
236
225
|
state: 'serving' as const
|
|
237
226
|
};
|
|
@@ -297,35 +286,20 @@ export class RawServiceMeshRuntime {
|
|
|
297
286
|
this.endpointOnlyPeers.add(endpoint);
|
|
298
287
|
}
|
|
299
288
|
|
|
300
|
-
disconnectPeer(
|
|
301
|
-
endpoint: string,
|
|
302
|
-
nodeRoutingId: string,
|
|
303
|
-
lifecycleGeneration?: bigint
|
|
304
|
-
): void {
|
|
289
|
+
disconnectPeer(endpoint: string, nodeRoutingId: string, lifecycleGeneration?: bigint): void {
|
|
305
290
|
const current = this.topology.peer(nodeRoutingId);
|
|
306
291
|
const expected = this.expectedPeers.get(nodeRoutingId);
|
|
307
292
|
if (
|
|
308
|
-
lifecycleGeneration !== undefined
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
)
|
|
319
|
-
||
|
|
320
|
-
(
|
|
321
|
-
current !== undefined
|
|
322
|
-
&& current.descriptor.lifecycleGeneration !== lifecycleGeneration
|
|
323
|
-
)
|
|
324
|
-
|| (
|
|
325
|
-
current === undefined
|
|
326
|
-
&& expected?.lifecycleGeneration !== lifecycleGeneration
|
|
327
|
-
)
|
|
328
|
-
)
|
|
293
|
+
lifecycleGeneration !== undefined &&
|
|
294
|
+
// Discovery has already fenced this RID to a replacement process.
|
|
295
|
+
// The old auto-connect intent must not use disconnectRid here: that
|
|
296
|
+
// is RID-wide and can close the provisional replacement before its
|
|
297
|
+
// Hello/admission promotes it. admitPeer owns exact old-pair teardown
|
|
298
|
+
// after the replacement descriptor is accepted.
|
|
299
|
+
((expected?.lifecycleGeneration !== undefined &&
|
|
300
|
+
expected.lifecycleGeneration !== lifecycleGeneration) ||
|
|
301
|
+
(current !== undefined && current.descriptor.lifecycleGeneration !== lifecycleGeneration) ||
|
|
302
|
+
(current === undefined && expected?.lifecycleGeneration !== lifecycleGeneration))
|
|
329
303
|
) {
|
|
330
304
|
return;
|
|
331
305
|
}
|
|
@@ -342,9 +316,9 @@ export class RawServiceMeshRuntime {
|
|
|
342
316
|
if (current !== undefined) this.removePeer(current);
|
|
343
317
|
this.topology.forgetNotRequired(nodeRoutingId);
|
|
344
318
|
if (
|
|
345
|
-
lifecycleGeneration === undefined
|
|
346
|
-
|
|
347
|
-
|
|
319
|
+
lifecycleGeneration === undefined ||
|
|
320
|
+
expected?.lifecycleGeneration === undefined ||
|
|
321
|
+
expected.lifecycleGeneration === lifecycleGeneration
|
|
348
322
|
) {
|
|
349
323
|
this.expectedPeers.delete(nodeRoutingId);
|
|
350
324
|
}
|
|
@@ -378,34 +352,38 @@ export class RawServiceMeshRuntime {
|
|
|
378
352
|
|
|
379
353
|
observePeerConnectionIntentRemoved(listener: (nodeRoutingId: string) => void): () => void {
|
|
380
354
|
this.peerConnectionIntentRemoved.add(listener);
|
|
381
|
-
return () => {
|
|
355
|
+
return () => {
|
|
356
|
+
this.peerConnectionIntentRemoved.delete(listener);
|
|
357
|
+
};
|
|
382
358
|
}
|
|
383
359
|
|
|
384
360
|
private notifyPeerConnectionIntentRemoved(nodeRoutingId: string): void {
|
|
385
361
|
// Only the logical owner's removal publishes lifecycle termination.
|
|
386
362
|
// A physical disconnect alone retains the connection expectation.
|
|
387
|
-
if (this.expectedPeers.has(nodeRoutingId) || this.topology.peer(nodeRoutingId) !== undefined)
|
|
363
|
+
if (this.expectedPeers.has(nodeRoutingId) || this.topology.peer(nodeRoutingId) !== undefined)
|
|
364
|
+
return;
|
|
388
365
|
for (const listener of this.peerConnectionIntentRemoved) listener(nodeRoutingId);
|
|
389
366
|
}
|
|
390
367
|
|
|
391
368
|
async announcePeer(nodeRoutingId: string): Promise<boolean> {
|
|
392
|
-
if (!this.expectedPeers.has(nodeRoutingId) || this.peerAdmissionSealed?.() === true)
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
);
|
|
369
|
+
if (!this.expectedPeers.has(nodeRoutingId) || this.peerAdmissionSealed?.() === true)
|
|
370
|
+
return false;
|
|
371
|
+
return this.send(nodeRoutingId, [
|
|
372
|
+
encodeRouteMeshAdmission(M6aServiceWireCommand.hello, this.topology.localDescriptor())
|
|
373
|
+
]);
|
|
397
374
|
}
|
|
398
375
|
|
|
399
376
|
isPeerRouteReady(nodeRoutingId: string, lifecycleGeneration?: bigint): boolean {
|
|
400
377
|
const peer = this.topology.peer(nodeRoutingId);
|
|
401
378
|
const monitorConnection = this.monitorConnectionStates.get(nodeRoutingId);
|
|
402
|
-
const applicationRouteReady =
|
|
403
|
-
|| monitorConnection === peer?.connectionId;
|
|
404
|
-
const ready =
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
&&
|
|
379
|
+
const applicationRouteReady =
|
|
380
|
+
monitorConnection === undefined || monitorConnection === peer?.connectionId;
|
|
381
|
+
const ready =
|
|
382
|
+
peer !== undefined &&
|
|
383
|
+
(lifecycleGeneration === undefined ||
|
|
384
|
+
peer.descriptor.lifecycleGeneration === lifecycleGeneration) &&
|
|
385
|
+
applicationRouteReady &&
|
|
386
|
+
this.liveness.isReady(nodeRoutingId, peer.connectionId);
|
|
409
387
|
return ready;
|
|
410
388
|
}
|
|
411
389
|
|
|
@@ -430,14 +408,16 @@ export class RawServiceMeshRuntime {
|
|
|
430
408
|
readonly state?: 'draining';
|
|
431
409
|
}): Promise<void> {
|
|
432
410
|
const current = this.topology.localDescriptor();
|
|
433
|
-
const channels =
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
channel
|
|
439
|
-
|
|
440
|
-
|
|
411
|
+
const channels =
|
|
412
|
+
options.state === 'draining'
|
|
413
|
+
? current.channels.map((channel) => ({ ...channel, weight: 0 }))
|
|
414
|
+
: options.channelName === undefined
|
|
415
|
+
? current.channels
|
|
416
|
+
: current.channels.map((channel) =>
|
|
417
|
+
channel.name === options.channelName
|
|
418
|
+
? { ...channel, weight: options.channelWeight! }
|
|
419
|
+
: channel
|
|
420
|
+
);
|
|
441
421
|
const next = {
|
|
442
422
|
...current,
|
|
443
423
|
descriptorRevision: current.descriptorRevision + 1n,
|
|
@@ -461,16 +441,15 @@ export class RawServiceMeshRuntime {
|
|
|
461
441
|
await this.announceExpectedPeers();
|
|
462
442
|
}
|
|
463
443
|
|
|
464
|
-
replaceDiscoveredNotRequired(
|
|
465
|
-
descriptors: readonly ServiceNodeDescriptor[]
|
|
466
|
-
): void {
|
|
444
|
+
replaceDiscoveredNotRequired(descriptors: readonly ServiceNodeDescriptor[]): void {
|
|
467
445
|
this.topology.replaceDiscoveredNotRequired(descriptors);
|
|
468
446
|
}
|
|
469
447
|
|
|
470
448
|
isObjectClientNodeDirectTarget(nodeRoutingId: string): boolean {
|
|
471
|
-
const descriptor =
|
|
472
|
-
|
|
473
|
-
|
|
449
|
+
const descriptor =
|
|
450
|
+
nodeRoutingId === this.descriptor.nodeRoutingId
|
|
451
|
+
? this.topology.localDescriptor()
|
|
452
|
+
: this.topology.knownDescriptor(nodeRoutingId);
|
|
474
453
|
return descriptor?.objectRole === 'client';
|
|
475
454
|
}
|
|
476
455
|
|
|
@@ -478,19 +457,15 @@ export class RawServiceMeshRuntime {
|
|
|
478
457
|
targetNodeRoutingId: string,
|
|
479
458
|
payload: ServiceApplicationPayloadInput
|
|
480
459
|
): Promise<boolean> {
|
|
481
|
-
return this.send(
|
|
482
|
-
targetNodeRoutingId,
|
|
483
|
-
[encodeNodeSendHeader(), this.applicationFrame(payload)]
|
|
484
|
-
);
|
|
460
|
+
return this.send(targetNodeRoutingId, [encodeNodeSendHeader(), this.applicationFrame(payload)]);
|
|
485
461
|
}
|
|
486
462
|
|
|
487
463
|
async sendToChannel(
|
|
488
464
|
channelName: string,
|
|
489
465
|
payload: ServiceApplicationPayloadInput
|
|
490
466
|
): Promise<boolean> {
|
|
491
|
-
const selected = this.topology.selectChannel(
|
|
492
|
-
|
|
493
|
-
peer => this.isLocalOrReadyPeer(peer.descriptor.nodeRoutingId)
|
|
467
|
+
const selected = this.topology.selectChannel(channelName, (peer) =>
|
|
468
|
+
this.isLocalOrReadyPeer(peer.descriptor.nodeRoutingId)
|
|
494
469
|
);
|
|
495
470
|
if (selected === undefined) return false;
|
|
496
471
|
const applicationFrame = this.applicationFrame(payload);
|
|
@@ -530,9 +505,8 @@ export class RawServiceMeshRuntime {
|
|
|
530
505
|
payload: ServiceApplicationPayloadInput,
|
|
531
506
|
timeoutMs: number
|
|
532
507
|
): PendingOperation<RawServiceRequestResult> | undefined {
|
|
533
|
-
const selected = this.topology.selectChannel(
|
|
534
|
-
|
|
535
|
-
peer => this.isLocalOrReadyPeer(peer.descriptor.nodeRoutingId)
|
|
508
|
+
const selected = this.topology.selectChannel(channelName, (peer) =>
|
|
509
|
+
this.isLocalOrReadyPeer(peer.descriptor.nodeRoutingId)
|
|
536
510
|
);
|
|
537
511
|
return selected === undefined
|
|
538
512
|
? undefined
|
|
@@ -540,8 +514,7 @@ export class RawServiceMeshRuntime {
|
|
|
540
514
|
}
|
|
541
515
|
|
|
542
516
|
private isLocalOrReadyPeer(nodeRoutingId: string): boolean {
|
|
543
|
-
return nodeRoutingId === this.descriptor.nodeRoutingId
|
|
544
|
-
|| this.isPeerRouteReady(nodeRoutingId);
|
|
517
|
+
return nodeRoutingId === this.descriptor.nodeRoutingId || this.isPeerRouteReady(nodeRoutingId);
|
|
545
518
|
}
|
|
546
519
|
|
|
547
520
|
setServiceIngress(handler: RawServiceIngressHandler): void {
|
|
@@ -551,24 +524,16 @@ export class RawServiceMeshRuntime {
|
|
|
551
524
|
this.serviceIngress = handler;
|
|
552
525
|
}
|
|
553
526
|
|
|
554
|
-
async reserveLocalIngress(
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
: AbortSignal.any([this.applicationJobStop.signal, signal]);
|
|
527
|
+
async reserveLocalIngress(signal?: AbortSignal): Promise<ApplicationIngressRecordOwner> {
|
|
528
|
+
const waitSignal =
|
|
529
|
+
signal === undefined
|
|
530
|
+
? this.applicationJobStop.signal
|
|
531
|
+
: AbortSignal.any([this.applicationJobStop.signal, signal]);
|
|
560
532
|
const permit = await this.applicationJobQueue.acquire(waitSignal);
|
|
561
|
-
return ApplicationIngressRecordOwner.create(
|
|
562
|
-
this.applicationJobQueue,
|
|
563
|
-
permit,
|
|
564
|
-
{ close() {} }
|
|
565
|
-
);
|
|
533
|
+
return ApplicationIngressRecordOwner.create(this.applicationJobQueue, permit, { close() {} });
|
|
566
534
|
}
|
|
567
535
|
|
|
568
|
-
async sendService(
|
|
569
|
-
targetNodeRoutingId: string,
|
|
570
|
-
parts: readonly Uint8Array[]
|
|
571
|
-
): Promise<boolean> {
|
|
536
|
+
async sendService(targetNodeRoutingId: string, parts: readonly Uint8Array[]): Promise<boolean> {
|
|
572
537
|
return this.send(targetNodeRoutingId, parts);
|
|
573
538
|
}
|
|
574
539
|
|
|
@@ -637,7 +602,9 @@ export class RawServiceMeshRuntime {
|
|
|
637
602
|
const startedAtMs = performance.now();
|
|
638
603
|
let messages = 0;
|
|
639
604
|
let bytes = 0;
|
|
640
|
-
const observe: RawServicePumpObserver = (_source, byteCount) => {
|
|
605
|
+
const observe: RawServicePumpObserver = (_source, byteCount) => {
|
|
606
|
+
bytes += byteCount;
|
|
607
|
+
};
|
|
641
608
|
while (receiveReady && messages < 64 && !this.closed) {
|
|
642
609
|
const result = await this.receiveOne(performance.now(), observe);
|
|
643
610
|
if (result === 'noData') {
|
|
@@ -704,13 +671,13 @@ export class RawServiceMeshRuntime {
|
|
|
704
671
|
}
|
|
705
672
|
|
|
706
673
|
private pullMonitorEvents(): void {
|
|
707
|
-
this.monitor?.drain(event => {
|
|
674
|
+
this.monitor?.drain((event) => {
|
|
708
675
|
this.observeMonitorEvent(event);
|
|
709
676
|
if (this.monitorEvents.length < MAX_PENDING_MONITOR_EVENTS) {
|
|
710
677
|
this.monitorEvents.push(event);
|
|
711
678
|
return;
|
|
712
679
|
}
|
|
713
|
-
const existingIndex = this.monitorEvents.findIndex(candidate =>
|
|
680
|
+
const existingIndex = this.monitorEvents.findIndex((candidate) =>
|
|
714
681
|
sameMonitorConnection(candidate, event)
|
|
715
682
|
);
|
|
716
683
|
if (existingIndex >= 0) this.monitorEvents[existingIndex] = event;
|
|
@@ -740,17 +707,20 @@ export class RawServiceMeshRuntime {
|
|
|
740
707
|
if (received.requestSeq === undefined || received.parts.length === 0) return false;
|
|
741
708
|
try {
|
|
742
709
|
const header = decodeHeader(received.parts[0]!);
|
|
743
|
-
const correlation =
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
710
|
+
const correlation =
|
|
711
|
+
header.command === M6aServiceWireCommand.nodeRequest
|
|
712
|
+
? decodeNodeRequestHeader(received.parts[0]!)
|
|
713
|
+
: header.command === M6aServiceWireCommand.channelRequest
|
|
714
|
+
? decodeChannelRequestHeader(received.parts[0]!).correlation
|
|
715
|
+
: undefined;
|
|
748
716
|
if (correlation === undefined) return false;
|
|
749
|
-
const reply = [
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
717
|
+
const reply = [
|
|
718
|
+
encodeReplyHeader(
|
|
719
|
+
correlation,
|
|
720
|
+
RequestResult.ProtocolError,
|
|
721
|
+
ServiceWireFrameworkErrorCode.requestProtocolError
|
|
722
|
+
)
|
|
723
|
+
];
|
|
754
724
|
if (received.reply === undefined) return false;
|
|
755
725
|
received.reply(reply);
|
|
756
726
|
return true;
|
|
@@ -766,17 +736,13 @@ export class RawServiceMeshRuntime {
|
|
|
766
736
|
applicationJobOwner: ApplicationIngressRecordOwner
|
|
767
737
|
): Promise<RawServicePumpResult> {
|
|
768
738
|
if (
|
|
769
|
-
received.parts.length === 0
|
|
770
|
-
|
|
771
|
-
received.parts.length === 1
|
|
772
|
-
&& received.parts[0]!.byteLength === 0
|
|
773
|
-
)
|
|
739
|
+
received.parts.length === 0 ||
|
|
740
|
+
(received.parts.length === 1 && received.parts[0]!.byteLength === 0)
|
|
774
741
|
) {
|
|
775
742
|
if (this.peerAdmissionSealed?.() === true) return 'dropped';
|
|
776
|
-
return await this.send(
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
)
|
|
743
|
+
return (await this.send(received.sourceRid, [
|
|
744
|
+
encodeRouteMeshAdmission(M6aServiceWireCommand.hello, this.topology.localDescriptor())
|
|
745
|
+
]))
|
|
780
746
|
? 'infrastructure'
|
|
781
747
|
: 'dropped';
|
|
782
748
|
}
|
|
@@ -786,9 +752,9 @@ export class RawServiceMeshRuntime {
|
|
|
786
752
|
return 'dropped';
|
|
787
753
|
}
|
|
788
754
|
if (
|
|
789
|
-
header.command === M6aServiceWireCommand.hello
|
|
790
|
-
|
|
791
|
-
|
|
755
|
+
header.command === M6aServiceWireCommand.hello ||
|
|
756
|
+
header.command === M6aServiceWireCommand.admit ||
|
|
757
|
+
header.command === M6aServiceWireCommand.update
|
|
792
758
|
) {
|
|
793
759
|
if (received.parts.length !== 1) return 'protocolError';
|
|
794
760
|
const descriptor = decodeRouteMeshAdmission(
|
|
@@ -798,11 +764,9 @@ export class RawServiceMeshRuntime {
|
|
|
798
764
|
);
|
|
799
765
|
const expected = this.expectedPeers.get(received.sourceRid);
|
|
800
766
|
if (
|
|
801
|
-
expected !== undefined
|
|
802
|
-
|
|
803
|
-
expected.
|
|
804
|
-
|| expected.nodeRoutingId !== descriptor.nodeRoutingId
|
|
805
|
-
)
|
|
767
|
+
expected !== undefined &&
|
|
768
|
+
(expected.meshName !== descriptor.meshName ||
|
|
769
|
+
expected.nodeRoutingId !== descriptor.nodeRoutingId)
|
|
806
770
|
) {
|
|
807
771
|
await this.send(received.sourceRid, [encodeReject(3)]);
|
|
808
772
|
return 'infrastructure';
|
|
@@ -811,23 +775,19 @@ export class RawServiceMeshRuntime {
|
|
|
811
775
|
received.sourceRid,
|
|
812
776
|
descriptor.advertisedEndpoint
|
|
813
777
|
);
|
|
814
|
-
const result = this.admitPeer(
|
|
815
|
-
descriptor,
|
|
816
|
-
connection,
|
|
817
|
-
nowMs,
|
|
818
|
-
expected
|
|
819
|
-
);
|
|
778
|
+
const result = this.admitPeer(descriptor, connection, nowMs, expected);
|
|
820
779
|
if (result !== 'admitted' && result !== 'notRequired') {
|
|
821
|
-
const detail =
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
780
|
+
const detail =
|
|
781
|
+
result === 'invalidDescriptor'
|
|
782
|
+
? describeInvalidAdmissionDescriptor(
|
|
783
|
+
descriptor,
|
|
784
|
+
expected,
|
|
785
|
+
this.topology.peer(descriptor.nodeRoutingId)?.descriptor
|
|
786
|
+
)
|
|
787
|
+
: undefined;
|
|
828
788
|
console.warn(
|
|
829
|
-
`RouteMesh admission rejected peer '${received.sourceRid}' as ${result}`
|
|
830
|
-
|
|
789
|
+
`RouteMesh admission rejected peer '${received.sourceRid}' as ${result}` +
|
|
790
|
+
(detail === undefined ? '.' : ` (${detail}).`)
|
|
831
791
|
);
|
|
832
792
|
await this.send(received.sourceRid, [encodeReject(admissionReason(result))]);
|
|
833
793
|
return 'infrastructure';
|
|
@@ -837,15 +797,11 @@ export class RawServiceMeshRuntime {
|
|
|
837
797
|
// Hello supplies only the sender's descriptor. Even NotRequired
|
|
838
798
|
// peers must receive ours before the intent owner closes transport;
|
|
839
799
|
// submitting a response does not guarantee delivery before close.
|
|
840
|
-
await this.send(
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
);
|
|
800
|
+
await this.send(received.sourceRid, [
|
|
801
|
+
encodeRouteMeshAdmission(M6aServiceWireCommand.admit, this.topology.localDescriptor())
|
|
802
|
+
]);
|
|
844
803
|
} else if (result === 'notRequired') {
|
|
845
|
-
this.retireNotRequiredExpectedPeer(
|
|
846
|
-
received.sourceRid,
|
|
847
|
-
descriptor.advertisedEndpoint
|
|
848
|
-
);
|
|
804
|
+
this.retireNotRequiredExpectedPeer(received.sourceRid, descriptor.advertisedEndpoint);
|
|
849
805
|
}
|
|
850
806
|
return 'infrastructure';
|
|
851
807
|
}
|
|
@@ -875,8 +831,8 @@ export class RawServiceMeshRuntime {
|
|
|
875
831
|
const peer = this.topology.peer(received.sourceRid);
|
|
876
832
|
if (peer === undefined) return 'protocolError';
|
|
877
833
|
if (
|
|
878
|
-
header.command === M6aServiceWireCommand.livenessProbe
|
|
879
|
-
|
|
834
|
+
header.command === M6aServiceWireCommand.livenessProbe ||
|
|
835
|
+
header.command === M6aServiceWireCommand.livenessAck
|
|
880
836
|
) {
|
|
881
837
|
if (received.parts.length !== 1) return 'protocolError';
|
|
882
838
|
const record = livenessCodec.decodeLivenessRecord(received.parts[0]!);
|
|
@@ -886,23 +842,19 @@ export class RawServiceMeshRuntime {
|
|
|
886
842
|
peer.connectionId,
|
|
887
843
|
record.probeId
|
|
888
844
|
);
|
|
889
|
-
const sent =
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
845
|
+
const sent =
|
|
846
|
+
ack !== undefined &&
|
|
847
|
+
(await this.send(received.sourceRid, [
|
|
848
|
+
livenessCodec.encodeLivenessRecord({
|
|
849
|
+
command: M6aServiceWireCommand.livenessAck,
|
|
850
|
+
probeId: record.probeId
|
|
851
|
+
})
|
|
852
|
+
]));
|
|
896
853
|
if (!sent) {
|
|
897
854
|
return 'protocolError';
|
|
898
855
|
}
|
|
899
856
|
} else {
|
|
900
|
-
this.liveness.acknowledge(
|
|
901
|
-
received.sourceRid,
|
|
902
|
-
peer.connectionId,
|
|
903
|
-
record.probeId,
|
|
904
|
-
nowMs
|
|
905
|
-
);
|
|
857
|
+
this.liveness.acknowledge(received.sourceRid, peer.connectionId, record.probeId, nowMs);
|
|
906
858
|
}
|
|
907
859
|
return 'infrastructure';
|
|
908
860
|
}
|
|
@@ -919,7 +871,7 @@ export class RawServiceMeshRuntime {
|
|
|
919
871
|
});
|
|
920
872
|
if (stateful !== undefined) return stateful;
|
|
921
873
|
if (
|
|
922
|
-
header.flags === 0
|
|
874
|
+
header.flags === 0 &&
|
|
923
875
|
// A bare infrastructure control is normally exactly one frame, but a
|
|
924
876
|
// relocation Prepare now rides its bound-session journal as
|
|
925
877
|
// node-internal ZLNI frames trailing the canonical command frame
|
|
@@ -931,8 +883,8 @@ export class RawServiceMeshRuntime {
|
|
|
931
883
|
// protocolError (surfaced downstream as `invalid_frame`, stalling
|
|
932
884
|
// the source's Prepare resend loop past the relocation admission
|
|
933
885
|
// budget).
|
|
934
|
-
|
|
935
|
-
|
|
886
|
+
received.parts.length >= 1 &&
|
|
887
|
+
isBareInfrastructureControl(header.command)
|
|
936
888
|
) {
|
|
937
889
|
const accepted = this.mailbox.tryEnqueue({
|
|
938
890
|
owner: `node:${this.descriptor.nodeRoutingId}`,
|
|
@@ -946,9 +898,9 @@ export class RawServiceMeshRuntime {
|
|
|
946
898
|
return accepted ? 'infrastructure' : 'dropped';
|
|
947
899
|
}
|
|
948
900
|
if (
|
|
949
|
-
header.flags !== 0
|
|
950
|
-
|
|
951
|
-
|
|
901
|
+
header.flags !== 0 ||
|
|
902
|
+
received.parts.length !== 2 ||
|
|
903
|
+
![
|
|
952
904
|
M6aServiceWireCommand.nodeSend,
|
|
953
905
|
M6aServiceWireCommand.nodeRequest,
|
|
954
906
|
M6aServiceWireCommand.channelSend,
|
|
@@ -986,18 +938,15 @@ export class RawServiceMeshRuntime {
|
|
|
986
938
|
if (accepted) return 'application';
|
|
987
939
|
applicationJob.close();
|
|
988
940
|
if (correlation !== undefined && received.requestSeq !== undefined) {
|
|
989
|
-
this.replyService(
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
0
|
|
999
|
-
)
|
|
1000
|
-
]);
|
|
941
|
+
this.replyService(
|
|
942
|
+
{
|
|
943
|
+
sourceRoutingId: received.sourceRid,
|
|
944
|
+
sourceRoute: received.sourceRoute,
|
|
945
|
+
requestSequence: received.requestSeq,
|
|
946
|
+
...(received.reply === undefined ? {} : { reply: received.reply })
|
|
947
|
+
},
|
|
948
|
+
[encodeReplyHeader(correlation, RequestResult.NotConnected, 0)]
|
|
949
|
+
);
|
|
1001
950
|
return 'infrastructure';
|
|
1002
951
|
}
|
|
1003
952
|
return 'dropped';
|
|
@@ -1011,10 +960,12 @@ export class RawServiceMeshRuntime {
|
|
|
1011
960
|
const result = this.liveness.tick(nowMs);
|
|
1012
961
|
this.requireStarted();
|
|
1013
962
|
for (const probe of result.probes) {
|
|
1014
|
-
await this.send(probe.nodeRoutingId, [
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
963
|
+
await this.send(probe.nodeRoutingId, [
|
|
964
|
+
livenessCodec.encodeLivenessRecord({
|
|
965
|
+
command: M6aServiceWireCommand.livenessProbe,
|
|
966
|
+
probeId: probe.probeId
|
|
967
|
+
})
|
|
968
|
+
]);
|
|
1018
969
|
}
|
|
1019
970
|
for (const nodeRoutingId of result.timedOutNodes) {
|
|
1020
971
|
const peer = this.topology.peer(nodeRoutingId);
|
|
@@ -1039,15 +990,17 @@ export class RawServiceMeshRuntime {
|
|
|
1039
990
|
this.monitorEvents.length = 0;
|
|
1040
991
|
for (const event of events) {
|
|
1041
992
|
handled++;
|
|
1042
|
-
const nodeRoutingId = event.routingId
|
|
1043
|
-
?? this.expectedPeerRoutingId(event.remoteAddress);
|
|
993
|
+
const nodeRoutingId = event.routingId ?? this.expectedPeerRoutingId(event.remoteAddress);
|
|
1044
994
|
if (event.event === MONITOR_CONNECTION_READY && isConnectionReadyEdge(event)) {
|
|
1045
995
|
if (nodeRoutingId === undefined) {
|
|
1046
996
|
const candidate = this.createUnresolvedConnectionCandidate(event);
|
|
1047
997
|
const alreadyQueued = this.unresolvedConnectionCandidates.some(
|
|
1048
|
-
value => value.connectionId === candidate.connectionId
|
|
998
|
+
(value) => value.connectionId === candidate.connectionId
|
|
1049
999
|
);
|
|
1050
|
-
if (
|
|
1000
|
+
if (
|
|
1001
|
+
!alreadyQueued &&
|
|
1002
|
+
this.unresolvedConnectionCandidates.length < MAX_UNRESOLVED_CONNECTION_CANDIDATES
|
|
1003
|
+
) {
|
|
1051
1004
|
this.unresolvedConnectionCandidates.push(candidate);
|
|
1052
1005
|
}
|
|
1053
1006
|
continue;
|
|
@@ -1064,7 +1017,8 @@ export class RawServiceMeshRuntime {
|
|
|
1064
1017
|
if (existingPeer !== undefined) {
|
|
1065
1018
|
if (this.liveness.isReady(nodeRoutingId, existingPeer.connectionId)) {
|
|
1066
1019
|
const existingCandidate = this.connectionCandidates
|
|
1067
|
-
.get(nodeRoutingId)
|
|
1020
|
+
.get(nodeRoutingId)
|
|
1021
|
+
?.get(existingPeer.connectionId);
|
|
1068
1022
|
if (this.isDiscoveredLifecycleReplacement(existingPeer, nodeRoutingId)) {
|
|
1069
1023
|
// A current discovery descriptor with the same RID but a
|
|
1070
1024
|
// different lifecycle token denotes a replacement process.
|
|
@@ -1117,22 +1071,17 @@ export class RawServiceMeshRuntime {
|
|
|
1117
1071
|
// route evidence available to the admission message.
|
|
1118
1072
|
this.connectionIds.set(nodeRoutingId, candidate.connectionId);
|
|
1119
1073
|
await this.announcePeer(nodeRoutingId);
|
|
1120
|
-
} else if (
|
|
1121
|
-
event.event === MONITOR_DISCONNECTED
|
|
1122
|
-
&& nodeRoutingId !== undefined
|
|
1123
|
-
) {
|
|
1074
|
+
} else if (event.event === MONITOR_DISCONNECTED && nodeRoutingId !== undefined) {
|
|
1124
1075
|
const peer = this.topology.peer(nodeRoutingId);
|
|
1125
1076
|
const disconnectedId = monitorConnectionId(event, nodeRoutingId);
|
|
1126
1077
|
this.removeConnectionCandidate(nodeRoutingId, disconnectedId);
|
|
1127
1078
|
if (peer !== undefined && peer.connectionId === disconnectedId) {
|
|
1128
1079
|
this.removePeer(peer);
|
|
1129
1080
|
}
|
|
1130
|
-
} else if (
|
|
1131
|
-
event.event === MONITOR_DISCONNECTED
|
|
1132
|
-
) {
|
|
1081
|
+
} else if (event.event === MONITOR_DISCONNECTED) {
|
|
1133
1082
|
const disconnectedId = monitorConnectionId(event);
|
|
1134
1083
|
const index = this.unresolvedConnectionCandidates.findIndex(
|
|
1135
|
-
candidate => candidate.connectionId === disconnectedId
|
|
1084
|
+
(candidate) => candidate.connectionId === disconnectedId
|
|
1136
1085
|
);
|
|
1137
1086
|
if (index >= 0) this.unresolvedConnectionCandidates.splice(index, 1);
|
|
1138
1087
|
}
|
|
@@ -1170,15 +1119,16 @@ export class RawServiceMeshRuntime {
|
|
|
1170
1119
|
channelName?: string
|
|
1171
1120
|
): PendingOperation<RawServiceRequestResult> {
|
|
1172
1121
|
const correlation = this.nextCorrelation++;
|
|
1173
|
-
const header =
|
|
1174
|
-
|
|
1175
|
-
|
|
1122
|
+
const header =
|
|
1123
|
+
channelName === undefined
|
|
1124
|
+
? encodeNodeRequestHeader(correlation)
|
|
1125
|
+
: encodeChannelRequestHeader(correlation, channelName);
|
|
1176
1126
|
const encodedPayload = this.applicationFrame(payload);
|
|
1177
1127
|
const pending = this.operations.register(timeoutMs);
|
|
1178
1128
|
let selectedTargetNodeRoutingId = targetNodeRoutingId;
|
|
1179
1129
|
if (
|
|
1180
|
-
selectedTargetNodeRoutingId !== this.descriptor.nodeRoutingId
|
|
1181
|
-
|
|
1130
|
+
selectedTargetNodeRoutingId !== this.descriptor.nodeRoutingId &&
|
|
1131
|
+
!this.isPeerRouteReady(selectedTargetNodeRoutingId)
|
|
1182
1132
|
) {
|
|
1183
1133
|
// Channel selection happens before native admission. If that selection
|
|
1184
1134
|
// becomes stale during a peer drain, choose another ready channel peer
|
|
@@ -1188,19 +1138,15 @@ export class RawServiceMeshRuntime {
|
|
|
1188
1138
|
if (channelName !== undefined) {
|
|
1189
1139
|
const excludedTargets = new Set([selectedTargetNodeRoutingId]);
|
|
1190
1140
|
for (;;) {
|
|
1191
|
-
const alternate = this.topology.selectChannel(
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
return !excludedTargets.has(candidate)
|
|
1196
|
-
&& this.isLocalOrReadyPeer(candidate);
|
|
1197
|
-
}
|
|
1198
|
-
);
|
|
1141
|
+
const alternate = this.topology.selectChannel(channelName, (peer) => {
|
|
1142
|
+
const candidate = peer.descriptor.nodeRoutingId;
|
|
1143
|
+
return !excludedTargets.has(candidate) && this.isLocalOrReadyPeer(candidate);
|
|
1144
|
+
});
|
|
1199
1145
|
if (alternate === undefined) break;
|
|
1200
1146
|
selectedTargetNodeRoutingId = alternate.descriptor.nodeRoutingId;
|
|
1201
1147
|
if (
|
|
1202
|
-
selectedTargetNodeRoutingId === this.descriptor.nodeRoutingId
|
|
1203
|
-
|
|
1148
|
+
selectedTargetNodeRoutingId === this.descriptor.nodeRoutingId ||
|
|
1149
|
+
this.isPeerRouteReady(selectedTargetNodeRoutingId)
|
|
1204
1150
|
) {
|
|
1205
1151
|
break;
|
|
1206
1152
|
}
|
|
@@ -1225,9 +1171,10 @@ export class RawServiceMeshRuntime {
|
|
|
1225
1171
|
return;
|
|
1226
1172
|
}
|
|
1227
1173
|
const accepted = this.mailbox.tryEnqueue({
|
|
1228
|
-
owner:
|
|
1229
|
-
|
|
1230
|
-
|
|
1174
|
+
owner:
|
|
1175
|
+
channelName === undefined
|
|
1176
|
+
? `node:${this.descriptor.nodeRoutingId}`
|
|
1177
|
+
: `channel:${channelName}`,
|
|
1231
1178
|
domain: 'application',
|
|
1232
1179
|
parts,
|
|
1233
1180
|
sourceRoutingId: this.descriptor.nodeRoutingId,
|
|
@@ -1250,7 +1197,7 @@ export class RawServiceMeshRuntime {
|
|
|
1250
1197
|
} finally {
|
|
1251
1198
|
applicationJobOwner.close();
|
|
1252
1199
|
}
|
|
1253
|
-
})().catch(error => this.operations.fail(pending.id, error));
|
|
1200
|
+
})().catch((error) => this.operations.fail(pending.id, error));
|
|
1254
1201
|
return pending;
|
|
1255
1202
|
}
|
|
1256
1203
|
if (!this.isPeerRouteReady(selectedTargetNodeRoutingId)) {
|
|
@@ -1258,12 +1205,11 @@ export class RawServiceMeshRuntime {
|
|
|
1258
1205
|
// topology has never observed. A known peer without a usable route is
|
|
1259
1206
|
// a Framework NotConnected result; an unknown RID is completed locally
|
|
1260
1207
|
// as RequestTargetNotFound without submitting an application frame.
|
|
1261
|
-
const knownTarget =
|
|
1262
|
-
|
|
1208
|
+
const knownTarget =
|
|
1209
|
+
this.topology.peer(selectedTargetNodeRoutingId) !== undefined ||
|
|
1210
|
+
this.topology.knownDescriptor(selectedTargetNodeRoutingId) !== undefined;
|
|
1263
1211
|
this.operations.complete(pending.id, {
|
|
1264
|
-
terminalResult: knownTarget
|
|
1265
|
-
? RequestResult.NotConnected
|
|
1266
|
-
: RequestResult.NotFound,
|
|
1212
|
+
terminalResult: knownTarget ? RequestResult.NotConnected : RequestResult.NotFound,
|
|
1267
1213
|
failureCode: knownTarget ? 0 : REQUEST_TARGET_NOT_FOUND_FAILURE_CODE
|
|
1268
1214
|
});
|
|
1269
1215
|
return pending;
|
|
@@ -1273,25 +1219,24 @@ export class RawServiceMeshRuntime {
|
|
|
1273
1219
|
let request: Promise<readonly Uint8Array[]>;
|
|
1274
1220
|
try {
|
|
1275
1221
|
router = this.requireStarted();
|
|
1276
|
-
request = router.request(
|
|
1277
|
-
selectedTargetNodeRoutingId,
|
|
1278
|
-
parts,
|
|
1279
|
-
timeoutMs
|
|
1280
|
-
);
|
|
1222
|
+
request = router.request(selectedTargetNodeRoutingId, parts, timeoutMs);
|
|
1281
1223
|
} catch (error) {
|
|
1282
1224
|
this.operations.fail(pending.id, error);
|
|
1283
1225
|
return pending;
|
|
1284
1226
|
}
|
|
1285
1227
|
void request.then(
|
|
1286
|
-
replyParts => {
|
|
1228
|
+
(replyParts) => {
|
|
1287
1229
|
try {
|
|
1288
1230
|
if (replyParts.length < 1 || replyParts.length > 2) {
|
|
1289
1231
|
throw new ServiceWireProtocolError('Invalid reply parts.');
|
|
1290
1232
|
}
|
|
1291
1233
|
const reply = decodeReplyHeader(replyParts[0]!);
|
|
1292
|
-
if (reply.correlation !== correlation)
|
|
1234
|
+
if (reply.correlation !== correlation)
|
|
1235
|
+
throw new ServiceWireProtocolError('Reply correlation mismatch.');
|
|
1293
1236
|
if (reply.tail.byteLength !== 0) {
|
|
1294
|
-
throw new ServiceWireProtocolError(
|
|
1237
|
+
throw new ServiceWireProtocolError(
|
|
1238
|
+
'Generic node/channel reply carries an operation-specific tail.'
|
|
1239
|
+
);
|
|
1295
1240
|
}
|
|
1296
1241
|
if (reply.terminalResult === 0 && replyParts.length !== 2) {
|
|
1297
1242
|
throw new ServiceWireProtocolError('Successful reply omits its payload.');
|
|
@@ -1313,7 +1258,7 @@ export class RawServiceMeshRuntime {
|
|
|
1313
1258
|
this.operations.fail(pending.id, error);
|
|
1314
1259
|
}
|
|
1315
1260
|
},
|
|
1316
|
-
error => {
|
|
1261
|
+
(error) => {
|
|
1317
1262
|
this.operations.fail(pending.id, error);
|
|
1318
1263
|
}
|
|
1319
1264
|
);
|
|
@@ -1344,15 +1289,11 @@ export class RawServiceMeshRuntime {
|
|
|
1344
1289
|
): PeerAdmissionResult {
|
|
1345
1290
|
const previous = this.topology.peer(descriptor.nodeRoutingId);
|
|
1346
1291
|
if (
|
|
1347
|
-
previous !== undefined
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
descriptor.descriptorRevision
|
|
1351
|
-
|
|
1352
|
-
descriptor.descriptorRevision === previous.descriptor.descriptorRevision
|
|
1353
|
-
&& !sameServiceNodeDescriptor(previous.descriptor, descriptor)
|
|
1354
|
-
)
|
|
1355
|
-
)
|
|
1292
|
+
previous !== undefined &&
|
|
1293
|
+
previous.descriptor.lifecycleGeneration === descriptor.lifecycleGeneration &&
|
|
1294
|
+
(descriptor.descriptorRevision < previous.descriptor.descriptorRevision ||
|
|
1295
|
+
(descriptor.descriptorRevision === previous.descriptor.descriptorRevision &&
|
|
1296
|
+
!sameServiceNodeDescriptor(previous.descriptor, descriptor)))
|
|
1356
1297
|
) {
|
|
1357
1298
|
throw new ServiceWireProtocolError(
|
|
1358
1299
|
`RouteMesh peer '${descriptor.nodeRoutingId}' descriptor revision is stale or conflicting.`
|
|
@@ -1365,45 +1306,24 @@ export class RawServiceMeshRuntime {
|
|
|
1365
1306
|
connection.discriminator
|
|
1366
1307
|
);
|
|
1367
1308
|
if (result === 'admitted') {
|
|
1368
|
-
this.connectionIds.set(
|
|
1369
|
-
descriptor.nodeRoutingId,
|
|
1370
|
-
connection.connectionId
|
|
1371
|
-
);
|
|
1309
|
+
this.connectionIds.set(descriptor.nodeRoutingId, connection.connectionId);
|
|
1372
1310
|
this.liveness.admit(descriptor.nodeRoutingId, connection.connectionId, nowMs);
|
|
1373
|
-
this.liveness.requestProbe(
|
|
1374
|
-
|
|
1375
|
-
connection.connectionId,
|
|
1376
|
-
nowMs
|
|
1377
|
-
);
|
|
1378
|
-
this.monitorConnectionStates.set(
|
|
1379
|
-
descriptor.nodeRoutingId,
|
|
1380
|
-
connection.connectionId
|
|
1381
|
-
);
|
|
1311
|
+
this.liveness.requestProbe(descriptor.nodeRoutingId, connection.connectionId, nowMs);
|
|
1312
|
+
this.monitorConnectionStates.set(descriptor.nodeRoutingId, connection.connectionId);
|
|
1382
1313
|
if (previous !== undefined && previous.connectionId !== connection.connectionId) {
|
|
1383
1314
|
const previousCandidate = this.connectionCandidates
|
|
1384
|
-
.get(descriptor.nodeRoutingId)
|
|
1315
|
+
.get(descriptor.nodeRoutingId)
|
|
1316
|
+
?.get(previous.connectionId);
|
|
1385
1317
|
if (previousCandidate !== undefined) {
|
|
1386
|
-
this.removeConnectionCandidate(
|
|
1387
|
-
descriptor.nodeRoutingId,
|
|
1388
|
-
previousCandidate.connectionId
|
|
1389
|
-
);
|
|
1318
|
+
this.removeConnectionCandidate(descriptor.nodeRoutingId, previousCandidate.connectionId);
|
|
1390
1319
|
}
|
|
1391
1320
|
}
|
|
1392
1321
|
} else if (result === 'notRequired' && previous !== undefined) {
|
|
1393
|
-
this.liveness.disconnect(
|
|
1394
|
-
descriptor.nodeRoutingId,
|
|
1395
|
-
previous.connectionId
|
|
1396
|
-
);
|
|
1322
|
+
this.liveness.disconnect(descriptor.nodeRoutingId, previous.connectionId);
|
|
1397
1323
|
} else if (previous !== undefined) {
|
|
1398
|
-
this.connectionIds.set(
|
|
1399
|
-
descriptor.nodeRoutingId,
|
|
1400
|
-
previous.connectionId
|
|
1401
|
-
);
|
|
1324
|
+
this.connectionIds.set(descriptor.nodeRoutingId, previous.connectionId);
|
|
1402
1325
|
if (connection.connectionId !== previous.connectionId) {
|
|
1403
|
-
this.removeConnectionCandidate(
|
|
1404
|
-
descriptor.nodeRoutingId,
|
|
1405
|
-
connection.connectionId
|
|
1406
|
-
);
|
|
1326
|
+
this.removeConnectionCandidate(descriptor.nodeRoutingId, connection.connectionId);
|
|
1407
1327
|
}
|
|
1408
1328
|
}
|
|
1409
1329
|
return result;
|
|
@@ -1414,32 +1334,30 @@ export class RawServiceMeshRuntime {
|
|
|
1414
1334
|
advertisedEndpoint: string
|
|
1415
1335
|
): PhysicalConnectionCandidate {
|
|
1416
1336
|
let connectionId = this.connectionIds.get(nodeRoutingId);
|
|
1417
|
-
let candidate =
|
|
1418
|
-
|
|
1419
|
-
|
|
1337
|
+
let candidate =
|
|
1338
|
+
connectionId === undefined
|
|
1339
|
+
? undefined
|
|
1340
|
+
: this.connectionCandidates.get(nodeRoutingId)?.get(connectionId);
|
|
1420
1341
|
if (candidate === undefined) {
|
|
1421
|
-
candidate = this.promoteUnresolvedConnectionCandidate(
|
|
1422
|
-
nodeRoutingId,
|
|
1423
|
-
advertisedEndpoint
|
|
1424
|
-
);
|
|
1342
|
+
candidate = this.promoteUnresolvedConnectionCandidate(nodeRoutingId, advertisedEndpoint);
|
|
1425
1343
|
connectionId = candidate?.connectionId;
|
|
1426
1344
|
}
|
|
1427
1345
|
if (candidate === undefined) {
|
|
1428
1346
|
const localRid = this.topology.localDescriptor().nodeRoutingId;
|
|
1429
1347
|
const endpointOnly = this.endpointOnlyPeers.has(advertisedEndpoint);
|
|
1430
|
-
const direction: PhysicalConnectionDirection =
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
?
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1348
|
+
const direction: PhysicalConnectionDirection = this.expectedPeers.has(nodeRoutingId)
|
|
1349
|
+
? 'outbound'
|
|
1350
|
+
: endpointOnly
|
|
1351
|
+
? localRid.localeCompare(nodeRoutingId) <= 0
|
|
1352
|
+
? 'outbound'
|
|
1353
|
+
: 'inbound'
|
|
1354
|
+
: 'inbound';
|
|
1355
|
+
const initiator =
|
|
1356
|
+
endpointOnly && localRid.localeCompare(nodeRoutingId) > 0
|
|
1357
|
+
? nodeRoutingId
|
|
1358
|
+
: direction === 'outbound'
|
|
1359
|
+
? localRid
|
|
1360
|
+
: nodeRoutingId;
|
|
1443
1361
|
connectionId = `unmonitored:${direction}:${randomUUID()}`;
|
|
1444
1362
|
candidate = {
|
|
1445
1363
|
connectionId,
|
|
@@ -1473,17 +1391,19 @@ export class RawServiceMeshRuntime {
|
|
|
1473
1391
|
: this.endpointOnlyPeers.has(event.remoteAddress)
|
|
1474
1392
|
? 'outbound'
|
|
1475
1393
|
: 'unknown';
|
|
1476
|
-
const initiator =
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1394
|
+
const initiator =
|
|
1395
|
+
direction === 'outbound'
|
|
1396
|
+
? local.nodeRoutingId
|
|
1397
|
+
: direction === 'inbound'
|
|
1398
|
+
? nodeRoutingId
|
|
1399
|
+
: undefined;
|
|
1481
1400
|
return {
|
|
1482
1401
|
connectionId: monitorConnectionId(event, nodeRoutingId),
|
|
1483
1402
|
direction,
|
|
1484
|
-
discriminator:
|
|
1485
|
-
|
|
1486
|
-
|
|
1403
|
+
discriminator:
|
|
1404
|
+
initiator === undefined
|
|
1405
|
+
? `unknown:${monitorConnectionId(event, nodeRoutingId)}`
|
|
1406
|
+
: `initiator:${initiator}`,
|
|
1487
1407
|
localAddress: event.localAddress,
|
|
1488
1408
|
remoteAddress: event.remoteAddress
|
|
1489
1409
|
};
|
|
@@ -1495,8 +1415,8 @@ export class RawServiceMeshRuntime {
|
|
|
1495
1415
|
const connectionId = monitorConnectionId(event);
|
|
1496
1416
|
const local = this.topology.localDescriptor();
|
|
1497
1417
|
const direction: PhysicalConnectionDirection =
|
|
1498
|
-
this.endpointOnlyPeers.has(event.remoteAddress)
|
|
1499
|
-
|
|
1418
|
+
this.endpointOnlyPeers.has(event.remoteAddress) ||
|
|
1419
|
+
this.expectedPeerRoutingId(event.remoteAddress) !== undefined
|
|
1500
1420
|
? 'outbound'
|
|
1501
1421
|
: event.localAddress === local.advertisedEndpoint
|
|
1502
1422
|
? 'inbound'
|
|
@@ -1516,11 +1436,12 @@ export class RawServiceMeshRuntime {
|
|
|
1516
1436
|
): PhysicalConnectionCandidate | undefined {
|
|
1517
1437
|
const relevant = this.unresolvedConnectionCandidates
|
|
1518
1438
|
.map((candidate, index) => ({ candidate, index }))
|
|
1519
|
-
.filter(
|
|
1520
|
-
candidate
|
|
1521
|
-
|
|
1439
|
+
.filter(
|
|
1440
|
+
({ candidate }) =>
|
|
1441
|
+
candidate.remoteAddress === advertisedEndpoint || candidate.direction === 'inbound'
|
|
1442
|
+
);
|
|
1522
1443
|
if (relevant.length === 0) return undefined;
|
|
1523
|
-
const directions = new Set(relevant.map(value => value.candidate.direction));
|
|
1444
|
+
const directions = new Set(relevant.map((value) => value.candidate.direction));
|
|
1524
1445
|
const localRid = this.topology.localDescriptor().nodeRoutingId;
|
|
1525
1446
|
const preferredDirection: PhysicalConnectionDirection =
|
|
1526
1447
|
directions.has('inbound') && directions.has('outbound')
|
|
@@ -1528,21 +1449,22 @@ export class RawServiceMeshRuntime {
|
|
|
1528
1449
|
? 'outbound'
|
|
1529
1450
|
: 'inbound'
|
|
1530
1451
|
: relevant.at(-1)!.candidate.direction;
|
|
1531
|
-
const selected =
|
|
1532
|
-
.reverse()
|
|
1533
|
-
.
|
|
1534
|
-
?? relevant.at(-1)!;
|
|
1452
|
+
const selected =
|
|
1453
|
+
[...relevant].reverse().find((value) => value.candidate.direction === preferredDirection) ??
|
|
1454
|
+
relevant.at(-1)!;
|
|
1535
1455
|
this.unresolvedConnectionCandidates.splice(selected.index, 1);
|
|
1536
|
-
const initiator =
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1456
|
+
const initiator =
|
|
1457
|
+
selected.candidate.direction === 'outbound'
|
|
1458
|
+
? localRid
|
|
1459
|
+
: selected.candidate.direction === 'inbound'
|
|
1460
|
+
? nodeRoutingId
|
|
1461
|
+
: undefined;
|
|
1541
1462
|
const candidate: PhysicalConnectionCandidate = {
|
|
1542
1463
|
...selected.candidate,
|
|
1543
|
-
discriminator:
|
|
1544
|
-
|
|
1545
|
-
|
|
1464
|
+
discriminator:
|
|
1465
|
+
initiator === undefined
|
|
1466
|
+
? `unknown:${selected.candidate.connectionId}`
|
|
1467
|
+
: `initiator:${initiator}`
|
|
1546
1468
|
};
|
|
1547
1469
|
let candidates = this.connectionCandidates.get(nodeRoutingId);
|
|
1548
1470
|
if (candidates === undefined) {
|
|
@@ -1571,10 +1493,12 @@ export class RawServiceMeshRuntime {
|
|
|
1571
1493
|
// A same-RID replacement is permitted only from a complete discovery
|
|
1572
1494
|
// fence. Manual/endpoint-only intent has no authority to replace a ready
|
|
1573
1495
|
// peer, and lifecycle generations are opaque equality tokens.
|
|
1574
|
-
return
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1496
|
+
return (
|
|
1497
|
+
expected?.endpoint !== undefined &&
|
|
1498
|
+
expected.securityIdentity !== undefined &&
|
|
1499
|
+
expected.lifecycleGeneration !== undefined &&
|
|
1500
|
+
admitted.descriptor.lifecycleGeneration !== expected.lifecycleGeneration
|
|
1501
|
+
);
|
|
1578
1502
|
}
|
|
1579
1503
|
|
|
1580
1504
|
private expectedPeerRoutingId(endpoint: string): string | undefined {
|
|
@@ -1594,22 +1518,20 @@ export class RawServiceMeshRuntime {
|
|
|
1594
1518
|
// discovery advertised endpoint would reject valid READY events.
|
|
1595
1519
|
if (event.routingId === nodeRoutingId) return true;
|
|
1596
1520
|
const expected = this.expectedPeers.get(nodeRoutingId);
|
|
1597
|
-
return
|
|
1598
|
-
|
|
1521
|
+
return (
|
|
1522
|
+
expected === undefined ||
|
|
1523
|
+
expected.endpoint === undefined ||
|
|
1524
|
+
expected.endpoint === event.remoteAddress
|
|
1525
|
+
);
|
|
1599
1526
|
}
|
|
1600
1527
|
|
|
1601
|
-
private retireNotRequiredExpectedPeer(
|
|
1602
|
-
nodeRoutingId: string,
|
|
1603
|
-
advertisedEndpoint?: string
|
|
1604
|
-
): void {
|
|
1528
|
+
private retireNotRequiredExpectedPeer(nodeRoutingId: string, advertisedEndpoint?: string): void {
|
|
1605
1529
|
const expected = this.expectedPeers.get(nodeRoutingId);
|
|
1606
|
-
const endpoint =
|
|
1607
|
-
??
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
: undefined
|
|
1612
|
-
);
|
|
1530
|
+
const endpoint =
|
|
1531
|
+
expected?.endpoint ??
|
|
1532
|
+
(advertisedEndpoint !== undefined && this.endpointOnlyPeers.has(advertisedEndpoint)
|
|
1533
|
+
? advertisedEndpoint
|
|
1534
|
+
: undefined);
|
|
1613
1535
|
if (endpoint !== undefined) {
|
|
1614
1536
|
this.requireStarted().disconnect(endpoint);
|
|
1615
1537
|
this.endpointOnlyPeers.delete(endpoint);
|
|
@@ -1647,8 +1569,7 @@ export class RawServiceMeshRuntime {
|
|
|
1647
1569
|
}
|
|
1648
1570
|
|
|
1649
1571
|
private observeMonitorEvent(event: ZLinkRawMonitorRecord): void {
|
|
1650
|
-
const nodeRoutingId = event.routingId
|
|
1651
|
-
?? this.expectedPeerRoutingId(event.remoteAddress);
|
|
1572
|
+
const nodeRoutingId = event.routingId ?? this.expectedPeerRoutingId(event.remoteAddress);
|
|
1652
1573
|
if (nodeRoutingId === undefined) return;
|
|
1653
1574
|
const connectionId = monitorConnectionId(event, nodeRoutingId);
|
|
1654
1575
|
if (event.event === MONITOR_CONNECTION_READY && isConnectionReadyEdge(event)) {
|
|
@@ -1657,9 +1578,11 @@ export class RawServiceMeshRuntime {
|
|
|
1657
1578
|
// allow a late stale READY to overwrite the admitted replacement.
|
|
1658
1579
|
return;
|
|
1659
1580
|
}
|
|
1660
|
-
if (
|
|
1661
|
-
|
|
1662
|
-
|
|
1581
|
+
if (
|
|
1582
|
+
event.event === MONITOR_DISCONNECTED &&
|
|
1583
|
+
this.monitorConnectionStates.get(nodeRoutingId) === connectionId &&
|
|
1584
|
+
this.topology.peer(nodeRoutingId)?.connectionId === connectionId
|
|
1585
|
+
) {
|
|
1663
1586
|
this.monitorConnectionStates.set(nodeRoutingId, null);
|
|
1664
1587
|
}
|
|
1665
1588
|
}
|
|
@@ -1669,10 +1592,7 @@ export class RawServiceMeshRuntime {
|
|
|
1669
1592
|
return this.router;
|
|
1670
1593
|
}
|
|
1671
1594
|
|
|
1672
|
-
private async send(
|
|
1673
|
-
targetNodeRoutingId: string,
|
|
1674
|
-
parts: readonly Uint8Array[]
|
|
1675
|
-
): Promise<boolean> {
|
|
1595
|
+
private async send(targetNodeRoutingId: string, parts: readonly Uint8Array[]): Promise<boolean> {
|
|
1676
1596
|
try {
|
|
1677
1597
|
await this.requireStarted().send(targetNodeRoutingId, parts);
|
|
1678
1598
|
return true;
|
|
@@ -1680,7 +1600,6 @@ export class RawServiceMeshRuntime {
|
|
|
1680
1600
|
return false;
|
|
1681
1601
|
}
|
|
1682
1602
|
}
|
|
1683
|
-
|
|
1684
1603
|
}
|
|
1685
1604
|
|
|
1686
1605
|
/**
|
|
@@ -1725,11 +1644,7 @@ function monitorConnectionId(
|
|
|
1725
1644
|
resolvedNodeRoutingId = event.routingId ?? ''
|
|
1726
1645
|
): string {
|
|
1727
1646
|
if (event.connectionId !== undefined && event.connectionId !== 0n) {
|
|
1728
|
-
return JSON.stringify([
|
|
1729
|
-
resolvedNodeRoutingId,
|
|
1730
|
-
'connection',
|
|
1731
|
-
event.connectionId.toString()
|
|
1732
|
-
]);
|
|
1647
|
+
return JSON.stringify([resolvedNodeRoutingId, 'connection', event.connectionId.toString()]);
|
|
1733
1648
|
}
|
|
1734
1649
|
return JSON.stringify([
|
|
1735
1650
|
// Monitor `value` is event-specific: CONNECTION_READY reports the
|
|
@@ -1742,12 +1657,11 @@ function monitorConnectionId(
|
|
|
1742
1657
|
]);
|
|
1743
1658
|
}
|
|
1744
1659
|
|
|
1745
|
-
function sameMonitorConnection(
|
|
1746
|
-
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
&& left.remoteAddress === right.remoteAddress;
|
|
1660
|
+
function sameMonitorConnection(left: ZLinkRawMonitorRecord, right: ZLinkRawMonitorRecord): boolean {
|
|
1661
|
+
return (
|
|
1662
|
+
monitorConnectionId(left) === monitorConnectionId(right) &&
|
|
1663
|
+
left.remoteAddress === right.remoteAddress
|
|
1664
|
+
);
|
|
1751
1665
|
}
|
|
1752
1666
|
|
|
1753
1667
|
function isConnectionReadyEdge(event: ZLinkRawMonitorRecord): boolean {
|
|
@@ -1766,21 +1680,26 @@ function describeInvalidAdmissionDescriptor(
|
|
|
1766
1680
|
} catch (error) {
|
|
1767
1681
|
return `descriptor validation: ${error instanceof Error ? error.message : String(error)}`;
|
|
1768
1682
|
}
|
|
1769
|
-
if (expected?.endpoint !== undefined
|
|
1770
|
-
&& descriptor.advertisedEndpoint !== expected.endpoint) {
|
|
1683
|
+
if (expected?.endpoint !== undefined && descriptor.advertisedEndpoint !== expected.endpoint) {
|
|
1771
1684
|
return `advertisedEndpoint expected='${expected.endpoint}' actual='${descriptor.advertisedEndpoint}'`;
|
|
1772
1685
|
}
|
|
1773
|
-
if (
|
|
1774
|
-
|
|
1686
|
+
if (
|
|
1687
|
+
expected?.securityIdentity !== undefined &&
|
|
1688
|
+
descriptor.securityIdentity !== expected.securityIdentity
|
|
1689
|
+
) {
|
|
1775
1690
|
return `securityIdentity expected='${expected.securityIdentity}' actual='${descriptor.securityIdentity}'`;
|
|
1776
1691
|
}
|
|
1777
|
-
if (
|
|
1778
|
-
|
|
1692
|
+
if (
|
|
1693
|
+
expected?.lifecycleGeneration !== undefined &&
|
|
1694
|
+
descriptor.lifecycleGeneration !== expected.lifecycleGeneration
|
|
1695
|
+
) {
|
|
1779
1696
|
return `lifecycleGeneration expected=${expected.lifecycleGeneration} actual=${descriptor.lifecycleGeneration}`;
|
|
1780
1697
|
}
|
|
1781
|
-
if (
|
|
1782
|
-
|
|
1783
|
-
|
|
1698
|
+
if (
|
|
1699
|
+
current !== undefined &&
|
|
1700
|
+
current.lifecycleGeneration === descriptor.lifecycleGeneration &&
|
|
1701
|
+
descriptor.descriptorRevision > current.descriptorRevision
|
|
1702
|
+
) {
|
|
1784
1703
|
const immutableField = immutableDescriptorMismatch(current, descriptor);
|
|
1785
1704
|
if (immutableField !== undefined) return immutableField;
|
|
1786
1705
|
}
|
|
@@ -1792,19 +1711,27 @@ function immutableDescriptorMismatch(
|
|
|
1792
1711
|
descriptor: ServiceNodeDescriptor
|
|
1793
1712
|
): string | undefined {
|
|
1794
1713
|
const fields: ReadonlyArray<keyof ServiceNodeDescriptor> = [
|
|
1795
|
-
'advertisedEndpoint',
|
|
1796
|
-
'
|
|
1714
|
+
'advertisedEndpoint',
|
|
1715
|
+
'securityIdentity',
|
|
1716
|
+
'applicationVersion',
|
|
1717
|
+
'objectRole',
|
|
1718
|
+
'activeCapacityLimit',
|
|
1719
|
+
'pendingCapacityLimit'
|
|
1797
1720
|
];
|
|
1798
1721
|
for (const field of fields) {
|
|
1799
1722
|
if (current[field] !== descriptor[field]) {
|
|
1800
1723
|
return `${field} changed within lifecycle expected=${String(current[field])} actual=${String(descriptor[field])}`;
|
|
1801
1724
|
}
|
|
1802
1725
|
}
|
|
1803
|
-
if (
|
|
1726
|
+
if (
|
|
1727
|
+
JSON.stringify(current.protocolCapabilities) !== JSON.stringify(descriptor.protocolCapabilities)
|
|
1728
|
+
) {
|
|
1804
1729
|
return `protocolCapabilities changed within lifecycle expected=${JSON.stringify(current.protocolCapabilities)} actual=${JSON.stringify(descriptor.protocolCapabilities)}`;
|
|
1805
1730
|
}
|
|
1806
|
-
if (
|
|
1807
|
-
|
|
1731
|
+
if (
|
|
1732
|
+
JSON.stringify(current.channels.map((channel) => channel.name)) !==
|
|
1733
|
+
JSON.stringify(descriptor.channels.map((channel) => channel.name))
|
|
1734
|
+
) {
|
|
1808
1735
|
return 'channels changed within lifecycle';
|
|
1809
1736
|
}
|
|
1810
1737
|
return undefined;
|