@zlink-systems/framework 0.30.1 → 0.30.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/.tsbuildinfo +1 -1
- package/dist/contracts/Common/ZLinkEncodedPayload.d.ts +6 -0
- package/dist/contracts/Common/ZLinkEncodedPayload.js +18 -3
- package/dist/contracts/Common/encoded-payload-storage.d.ts +1 -1
- package/dist/contracts/Common/encoded-payload-storage.js +5 -2
- package/dist/contracts/Configuration/Builders.d.ts +1 -1
- package/dist/contracts/Configuration/RegistrationBuilderPolicy.d.ts +2 -1
- package/dist/contracts/Configuration/RegistrationBuilderPolicy.js +5 -1
- package/dist/contracts/Configuration/RegistrationBuilders.js +2 -2
- package/dist/contracts/Configuration/RegistrationTypes.d.ts +1 -0
- package/dist/contracts/Dispatch/ZLinkDispatchOptions.d.ts +2 -2
- package/dist/contracts/Locations/Rows.d.ts +2 -0
- package/dist/contracts/Spots/Contracts.d.ts +4 -0
- package/dist/contracts/Spots/ZLinkSpot.d.ts +3 -3
- package/dist/runtime/abort.d.ts +5 -0
- package/dist/runtime/abort.js +10 -0
- package/dist/runtime/actors/actor-authority-publication.js +3 -2
- package/dist/runtime/actors/actor-client.d.ts +0 -1
- package/dist/runtime/actors/actor-client.js +38 -45
- package/dist/runtime/actors/actor-context.d.ts +2 -0
- package/dist/runtime/actors/actor-context.js +46 -9
- package/dist/runtime/actors/actor-handoff.d.ts +7 -3
- package/dist/runtime/actors/actor-handoff.js +212 -88
- package/dist/runtime/actors/actor-join-relocation.d.ts +2 -0
- package/dist/runtime/actors/actor-local-native-join.js +4 -0
- package/dist/runtime/actors/actor-mailbox.js +27 -1
- package/dist/runtime/actors/actor-remote-joiner.js +3 -1
- package/dist/runtime/actors/actor-reply.d.ts +4 -0
- package/dist/runtime/actors/actor-reply.js +29 -0
- package/dist/runtime/actors/actor-runtime-contracts.d.ts +2 -0
- package/dist/runtime/actors/actor-runtime-state.js +2 -20
- package/dist/runtime/actors/actor-source-transfer.d.ts +1 -17
- package/dist/runtime/actors/index.d.ts +6 -2
- package/dist/runtime/actors/index.js +37 -21
- package/dist/runtime/actors/session-disconnected-wire.d.ts +8 -0
- package/dist/runtime/actors/session-disconnected-wire.js +48 -0
- package/dist/runtime/admission.d.ts +9 -1
- package/dist/runtime/admission.js +55 -32
- package/dist/runtime/application-jobs/application-job-queue-scope.d.ts +13 -0
- package/dist/runtime/application-jobs/application-job-queue-scope.js +27 -1
- package/dist/runtime/application-jobs/contracts.d.ts +2 -0
- package/dist/runtime/backend/contracts/index.d.ts +19 -3
- package/dist/runtime/backend/mesh-actor-session-node-adapter.js +2 -2
- package/dist/runtime/backend/mesh-completion-table.js +5 -0
- package/dist/runtime/backend/mesh-dispatch-pump.d.ts +26 -2
- package/dist/runtime/backend/mesh-dispatch-pump.js +193 -107
- package/dist/runtime/backend/node/node-raw-binding-port.js +90 -58
- package/dist/runtime/backend/node/node-raw-mesh-backend.d.ts +33 -8
- package/dist/runtime/backend/node/node-raw-mesh-backend.js +142 -143
- package/dist/runtime/backend/node/node-socket-backend-adapter.d.ts +1 -1
- package/dist/runtime/backend/node/node-socket-backend-adapter.js +5 -5
- package/dist/runtime/channels/channel-clients.d.ts +1 -0
- package/dist/runtime/channels/channel-clients.js +20 -5
- package/dist/runtime/channels/channel-dispatch-pipeline.d.ts +22 -3
- package/dist/runtime/channels/channel-dispatch-pipeline.js +103 -57
- package/dist/runtime/channels/channel-dispatchers.d.ts +3 -2
- package/dist/runtime/channels/channel-dispatchers.js +44 -37
- package/dist/runtime/channels/channel-envelope.d.ts +1 -0
- package/dist/runtime/channels/channel-envelope.js +74 -31
- package/dist/runtime/channels/channel-runtime-lifecycle.d.ts +4 -3
- package/dist/runtime/channels/channel-runtime-lifecycle.js +19 -24
- package/dist/runtime/channels/channel-runtime-manager.d.ts +3 -2
- package/dist/runtime/channels/channel-runtime-manager.js +4 -4
- package/dist/runtime/channels/channel-transports.d.ts +0 -1
- package/dist/runtime/channels/channel-transports.js +35 -33
- package/dist/runtime/channels/client-server-location-runtime.js +5 -4
- package/dist/runtime/channels/dispatch-error-reporter.d.ts +2 -1
- package/dist/runtime/channels/dispatch-error-reporter.js +2 -1
- package/dist/runtime/channels/fanout-location-runtime.d.ts +1 -1
- package/dist/runtime/channels/fanout-location-runtime.js +3 -3
- package/dist/runtime/diagnostics/flow-context.js +19 -7
- package/dist/runtime/diagnostics/index.js +4 -9
- package/dist/runtime/diagnostics/message-flow.d.ts +8 -0
- package/dist/runtime/diagnostics/message-flow.js +35 -5
- package/dist/runtime/diagnostics/runtime-metrics.d.ts +2 -2
- package/dist/runtime/diagnostics/runtime-metrics.js +10 -8
- package/dist/runtime/execution/index.d.ts +4 -2
- package/dist/runtime/execution/index.js +33 -10
- package/dist/runtime/execution/serial-execution-queue.d.ts +4 -0
- package/dist/runtime/execution/serial-execution-queue.js +21 -2
- package/dist/runtime/execution/state-lane.d.ts +2 -0
- package/dist/runtime/execution/state-lane.js +5 -0
- package/dist/runtime/foundation/operation-registry.d.ts +25 -1
- package/dist/runtime/foundation/operation-registry.js +86 -18
- package/dist/runtime/foundation/raw-service-mesh-runtime.d.ts +39 -3
- package/dist/runtime/foundation/raw-service-mesh-runtime.js +151 -55
- package/dist/runtime/foundation/service-liveness-registry.d.ts +12 -1
- package/dist/runtime/foundation/service-liveness-registry.js +38 -0
- package/dist/runtime/foundation/service-mailbox.d.ts +7 -0
- package/dist/runtime/foundation/service-maintenance-runtime.js +1 -6
- package/dist/runtime/foundation/service-relocation-object-owner.d.ts +2 -3
- package/dist/runtime/foundation/service-relocation-object-owner.js +48 -35
- package/dist/runtime/foundation/service-relocation-runtime.js +7 -3
- package/dist/runtime/foundation/service-runtime-contracts.d.ts +8 -1
- package/dist/runtime/foundation/service-session-binding-ingress-port.d.ts +2 -1
- package/dist/runtime/foundation/service-stateful-registry.d.ts +5 -4
- package/dist/runtime/foundation/service-stateful-registry.js +24 -26
- package/dist/runtime/foundation/service-stateful-runtime.d.ts +72 -6
- package/dist/runtime/foundation/service-stateful-runtime.js +444 -117
- package/dist/runtime/foundation/service-stateful-wire-codec.d.ts +14 -1
- package/dist/runtime/foundation/service-stateful-wire-codec.js +48 -27
- package/dist/runtime/foundation/service-wire-binary-primitives.d.ts +6 -1
- package/dist/runtime/foundation/service-wire-binary-primitives.js +27 -11
- package/dist/runtime/foundation/service-wire-constants.generated.d.ts +1 -0
- package/dist/runtime/foundation/service-wire-constants.generated.js +1 -0
- package/dist/runtime/foundation/service-wire-m6a-codec.d.ts +10 -0
- package/dist/runtime/foundation/service-wire-m6a-codec.js +166 -53
- package/dist/runtime/host/actor-packet-relay.d.ts +6 -4
- package/dist/runtime/host/actor-packet-relay.js +59 -72
- package/dist/runtime/host/actor-placement-coordinator.js +25 -8
- package/dist/runtime/host/actor-transfer-runtime.d.ts +7 -31
- package/dist/runtime/host/actor-transfer-runtime.js +85 -331
- package/dist/runtime/host/application-job-queue.d.ts +24 -3
- package/dist/runtime/host/application-job-queue.js +28 -41
- package/dist/runtime/host/index.d.ts +5 -1
- package/dist/runtime/host/index.js +171 -97
- package/dist/runtime/host/location-runtime-owner.js +2 -6
- package/dist/runtime/host/mesh-router-resolver.d.ts +4 -0
- package/dist/runtime/host/mesh-router-resolver.js +14 -6
- package/dist/runtime/host/remote-bound-session-relay.d.ts +2 -4
- package/dist/runtime/host/remote-bound-session-relay.js +71 -190
- package/dist/runtime/host/route-mesh-runtime.d.ts +2 -2
- package/dist/runtime/host/route-mesh-runtime.js +5 -3
- package/dist/runtime/host/runtime-shutdown.d.ts +1 -0
- package/dist/runtime/host/runtime-shutdown.js +3 -2
- package/dist/runtime/host/service-relocation-host-runtime.d.ts +17 -7
- package/dist/runtime/host/service-relocation-host-runtime.js +550 -367
- package/dist/runtime/host/spot-runtime-options-factory.js +15 -7
- package/dist/runtime/host/user-spot-creation-coordinator.js +33 -84
- package/dist/runtime/locations/auto-connect-loop.d.ts +2 -0
- package/dist/runtime/locations/auto-connect-loop.js +22 -14
- package/dist/runtime/locations/auto-connect-reconciler.js +0 -6
- package/dist/runtime/locations/auto-connect-types.d.ts +0 -1
- package/dist/runtime/locations/descriptor-publication.d.ts +4 -0
- package/dist/runtime/locations/descriptor-publication.js +11 -0
- package/dist/runtime/locations/domain-store-contract.d.ts +1 -0
- package/dist/runtime/locations/in-memory-authority-store.d.ts +7 -1
- package/dist/runtime/locations/in-memory-authority-store.js +56 -19
- package/dist/runtime/locations/in-memory-location-store.js +1 -10
- package/dist/runtime/locations/index.d.ts +1 -0
- package/dist/runtime/locations/index.js +1 -0
- package/dist/runtime/locations/lease-tracker.js +1 -6
- package/dist/runtime/locations/location-store-repository.d.ts +51 -1
- package/dist/runtime/locations/location-store-repository.js +363 -139
- package/dist/runtime/locations/relocation-blob.d.ts +18 -1
- package/dist/runtime/locations/relocation-blob.js +52 -1
- package/dist/runtime/locations/request-source-resolver.d.ts +37 -0
- package/dist/runtime/locations/request-source-resolver.js +80 -0
- package/dist/runtime/locations/resolvers.js +1 -1
- package/dist/runtime/locations/runtime.d.ts +6 -2
- package/dist/runtime/locations/runtime.js +37 -30
- package/dist/runtime/messaging/payload-codec.d.ts +7 -1
- package/dist/runtime/messaging/payload-codec.js +7 -6
- package/dist/runtime/messaging/request-result.js +29 -26
- package/dist/runtime/protocol/service_wire_codec.generated.d.ts +19 -1
- package/dist/runtime/protocol/service_wire_codec.generated.js +85 -0
- package/dist/runtime/protocol/service_wire_pilot_codec.generated.d.ts +7 -1
- package/dist/runtime/protocol/service_wire_pilot_codec.generated.js +23 -7
- package/dist/runtime/spots/formal-remote-actor-admission-registry.js +3 -2
- package/dist/runtime/spots/index.d.ts +18 -11
- package/dist/runtime/spots/index.js +234 -176
- package/dist/runtime/spots/spot-activation-registry.d.ts +4 -2
- package/dist/runtime/spots/spot-activation-registry.js +21 -11
- package/dist/runtime/spots/spot-activation-state.d.ts +1 -1
- package/dist/runtime/spots/spot-activation-state.js +7 -7
- package/dist/runtime/spots/spot-activation.d.ts +6 -3
- package/dist/runtime/spots/spot-activation.js +123 -44
- package/dist/runtime/spots/spot-actor-admission-coordinator.d.ts +1 -0
- package/dist/runtime/spots/spot-actor-admission-coordinator.js +13 -22
- package/dist/runtime/spots/spot-actor-membership.d.ts +0 -1
- package/dist/runtime/spots/spot-actor-membership.js +0 -8
- package/dist/runtime/spots/spot-actor-packet-dispatch.js +33 -8
- package/dist/runtime/spots/spot-actor-packet-drain.js +5 -33
- package/dist/runtime/spots/spot-entry-activation.d.ts +2 -0
- package/dist/runtime/spots/spot-entry-activation.js +14 -9
- package/dist/runtime/spots/spot-handler-registry.d.ts +4 -3
- package/dist/runtime/spots/spot-handler-registry.js +6 -2
- package/dist/runtime/spots/spot-manager-internal-contracts.d.ts +2 -2
- package/dist/runtime/spots/spot-manager-public.js +2 -2
- package/dist/runtime/spots/spot-node-autoconnect.d.ts +2 -1
- package/dist/runtime/spots/spot-node-autoconnect.js +18 -39
- package/dist/runtime/spots/spot-node-runtime-manager.d.ts +19 -2
- package/dist/runtime/spots/spot-node-runtime-manager.js +115 -50
- package/dist/runtime/spots/spot-outbound.js +3 -3
- package/dist/runtime/spots/spot-remote-codec.js +5 -1
- package/dist/runtime/spots/spot-runtime-ports.d.ts +0 -1
- package/dist/runtime/spots/spot-serial-executor.d.ts +10 -0
- package/dist/runtime/spots/spot-serial-executor.js +61 -8
- package/dist/runtime/spots/spot-serial-turn-executor.js +19 -2
- package/dist/runtime/spots/spot-subscription-dispatch.js +1 -1
- package/dist/runtime/spots/spot-timer.d.ts +57 -5
- package/dist/runtime/spots/spot-timer.js +287 -103
- package/dist/runtime/streams/actor-session-binding-registry.d.ts +42 -11
- package/dist/runtime/streams/actor-session-binding-registry.js +165 -48
- package/dist/runtime/streams/actor-session-binding-runtime-owner.d.ts +8 -4
- package/dist/runtime/streams/bound-actor-relay-sender.d.ts +2 -1
- package/dist/runtime/streams/bound-actor-relay-sender.js +15 -8
- package/dist/runtime/streams/bound-session-service.d.ts +1 -1
- package/dist/runtime/streams/bound-session-service.js +6 -11
- package/dist/runtime/streams/index.d.ts +3 -2
- package/dist/runtime/streams/index.js +6 -4
- package/dist/runtime/streams/managed-stream.js +3 -2
- package/dist/runtime/streams/native-fallback-bound-session.js +8 -73
- package/dist/runtime/streams/session-actor-coordinator.d.ts +2 -8
- package/dist/runtime/streams/session-actor-coordinator.js +15 -32
- package/dist/runtime/streams/stream-binding-runtime-ports.d.ts +3 -10
- package/dist/runtime/streams/stream-session-runtime.js +1 -4
- package/dist/runtime/workers/index.js +1 -1
- package/package.json +3 -3
- package/src/contracts/Common/ZLinkEncodedPayload.ts +24 -4
- package/src/contracts/Common/encoded-payload-storage.ts +6 -3
- package/src/contracts/Configuration/Builders.ts +4 -1
- package/src/contracts/Configuration/RegistrationBuilderPolicy.ts +7 -2
- package/src/contracts/Configuration/RegistrationBuilders.ts +6 -2
- package/src/contracts/Configuration/RegistrationTypes.ts +1 -0
- package/src/contracts/Dispatch/ZLinkDispatchOptions.ts +2 -1
- package/src/contracts/Locations/Rows.ts +2 -0
- package/src/contracts/Spots/Contracts.ts +8 -0
- package/src/contracts/Spots/ZLinkSpot.ts +3 -3
- package/src/runtime/abort.ts +12 -0
- package/src/runtime/actors/actor-authority-publication.ts +3 -2
- package/src/runtime/actors/actor-client.ts +61 -70
- package/src/runtime/actors/actor-context.ts +49 -9
- package/src/runtime/actors/actor-handoff.ts +282 -106
- package/src/runtime/actors/actor-join-relocation.ts +2 -0
- package/src/runtime/actors/actor-local-native-join.ts +4 -0
- package/src/runtime/actors/actor-mailbox.ts +40 -2
- package/src/runtime/actors/actor-remote-joiner.ts +6 -1
- package/src/runtime/actors/actor-reply.ts +42 -0
- package/src/runtime/actors/actor-runtime-contracts.ts +2 -0
- package/src/runtime/actors/actor-runtime-state.ts +2 -20
- package/src/runtime/actors/actor-source-transfer.ts +1 -34
- package/src/runtime/actors/index.ts +41 -27
- package/src/runtime/actors/session-disconnected-wire.ts +66 -0
- package/src/runtime/admission.ts +69 -34
- package/src/runtime/application-jobs/application-job-queue-scope.ts +33 -1
- package/src/runtime/application-jobs/contracts.ts +2 -0
- package/src/runtime/backend/contracts/index.ts +39 -4
- package/src/runtime/backend/mesh-actor-session-node-adapter.ts +5 -3
- package/src/runtime/backend/mesh-completion-table.ts +4 -0
- package/src/runtime/backend/mesh-dispatch-pump.ts +223 -124
- package/src/runtime/backend/node/node-raw-binding-port.ts +106 -70
- package/src/runtime/backend/node/node-raw-mesh-backend.ts +221 -170
- package/src/runtime/backend/node/node-socket-backend-adapter.ts +5 -5
- package/src/runtime/channels/channel-clients.ts +49 -24
- package/src/runtime/channels/channel-dispatch-pipeline.ts +173 -124
- package/src/runtime/channels/channel-dispatchers.ts +116 -72
- package/src/runtime/channels/channel-envelope.ts +105 -36
- package/src/runtime/channels/channel-runtime-lifecycle.ts +13 -13
- package/src/runtime/channels/channel-runtime-manager.ts +12 -5
- package/src/runtime/channels/channel-transports.ts +49 -58
- package/src/runtime/channels/client-server-location-runtime.ts +11 -10
- package/src/runtime/channels/dispatch-error-reporter.ts +4 -2
- package/src/runtime/channels/fanout-location-runtime.ts +17 -9
- package/src/runtime/diagnostics/flow-context.ts +20 -7
- package/src/runtime/diagnostics/index.ts +1 -7
- package/src/runtime/diagnostics/message-flow.ts +47 -9
- package/src/runtime/diagnostics/runtime-metrics.ts +12 -10
- package/src/runtime/execution/index.ts +40 -14
- package/src/runtime/execution/serial-execution-queue.ts +31 -4
- package/src/runtime/execution/state-lane.ts +7 -0
- package/src/runtime/foundation/operation-registry.ts +98 -20
- package/src/runtime/foundation/raw-service-mesh-runtime.ts +244 -67
- package/src/runtime/foundation/service-liveness-registry.ts +39 -0
- package/src/runtime/foundation/service-mailbox.ts +8 -0
- package/src/runtime/foundation/service-maintenance-runtime.ts +1 -8
- package/src/runtime/foundation/service-relocation-object-owner.ts +54 -37
- package/src/runtime/foundation/service-relocation-runtime.ts +7 -3
- package/src/runtime/foundation/service-runtime-contracts.ts +12 -1
- package/src/runtime/foundation/service-session-binding-ingress-port.ts +2 -1
- package/src/runtime/foundation/service-stateful-registry.ts +38 -35
- package/src/runtime/foundation/service-stateful-runtime.ts +667 -152
- package/src/runtime/foundation/service-stateful-wire-codec.ts +49 -11
- package/src/runtime/foundation/service-wire-binary-primitives.ts +35 -12
- package/src/runtime/foundation/service-wire-constants.generated.ts +1 -0
- package/src/runtime/foundation/service-wire-m6a-codec.ts +187 -51
- package/src/runtime/host/actor-packet-relay.ts +113 -94
- package/src/runtime/host/actor-placement-coordinator.ts +31 -8
- package/src/runtime/host/actor-transfer-runtime.ts +104 -430
- package/src/runtime/host/application-job-queue.ts +29 -44
- package/src/runtime/host/index.ts +286 -129
- package/src/runtime/host/location-runtime-owner.ts +2 -6
- package/src/runtime/host/mesh-router-resolver.ts +13 -5
- package/src/runtime/host/remote-bound-session-relay.ts +86 -248
- package/src/runtime/host/route-mesh-runtime.ts +11 -5
- package/src/runtime/host/runtime-shutdown.ts +15 -4
- package/src/runtime/host/service-relocation-host-runtime.ts +784 -475
- package/src/runtime/host/spot-runtime-options-factory.ts +18 -7
- package/src/runtime/host/user-spot-creation-coordinator.ts +41 -100
- package/src/runtime/locations/auto-connect-loop.ts +22 -14
- package/src/runtime/locations/auto-connect-reconciler.ts +0 -6
- package/src/runtime/locations/auto-connect-types.ts +0 -1
- package/src/runtime/locations/descriptor-publication.ts +7 -0
- package/src/runtime/locations/domain-store-contract.ts +5 -0
- package/src/runtime/locations/in-memory-authority-store.ts +85 -23
- package/src/runtime/locations/in-memory-location-store.ts +1 -12
- package/src/runtime/locations/index.ts +1 -0
- package/src/runtime/locations/lease-tracker.ts +2 -9
- package/src/runtime/locations/location-store-repository.ts +628 -152
- package/src/runtime/locations/relocation-blob.ts +75 -1
- package/src/runtime/locations/request-source-resolver.ts +138 -0
- package/src/runtime/locations/resolvers.ts +2 -2
- package/src/runtime/locations/runtime.ts +70 -40
- package/src/runtime/messaging/payload-codec.ts +8 -11
- package/src/runtime/messaging/request-result.ts +33 -29
- package/src/runtime/protocol/service_wire_codec.generated.ts +87 -4
- package/src/runtime/protocol/service_wire_pilot_codec.generated.ts +13 -10
- package/src/runtime/spots/formal-remote-actor-admission-registry.ts +3 -2
- package/src/runtime/spots/index.ts +375 -281
- package/src/runtime/spots/spot-activation-registry.ts +25 -13
- package/src/runtime/spots/spot-activation-state.ts +12 -19
- package/src/runtime/spots/spot-activation.ts +170 -86
- package/src/runtime/spots/spot-actor-admission-coordinator.ts +25 -55
- package/src/runtime/spots/spot-actor-membership.ts +0 -15
- package/src/runtime/spots/spot-actor-packet-dispatch.ts +56 -11
- package/src/runtime/spots/spot-actor-packet-drain.ts +9 -52
- package/src/runtime/spots/spot-entry-activation.ts +24 -19
- package/src/runtime/spots/spot-handler-registry.ts +15 -4
- package/src/runtime/spots/spot-manager-internal-contracts.ts +2 -2
- package/src/runtime/spots/spot-manager-public.ts +2 -2
- package/src/runtime/spots/spot-node-autoconnect.ts +22 -45
- package/src/runtime/spots/spot-node-runtime-manager.ts +197 -67
- package/src/runtime/spots/spot-outbound.ts +3 -3
- package/src/runtime/spots/spot-remote-codec.ts +9 -2
- package/src/runtime/spots/spot-runtime-ports.ts +0 -1
- package/src/runtime/spots/spot-serial-executor.ts +97 -25
- package/src/runtime/spots/spot-serial-turn-executor.ts +22 -3
- package/src/runtime/spots/spot-subscription-dispatch.ts +1 -1
- package/src/runtime/spots/spot-timer.ts +413 -157
- package/src/runtime/streams/actor-session-binding-registry.ts +236 -64
- package/src/runtime/streams/actor-session-binding-runtime-owner.ts +16 -8
- package/src/runtime/streams/bound-actor-relay-sender.ts +23 -9
- package/src/runtime/streams/bound-session-service.ts +7 -10
- package/src/runtime/streams/index.ts +12 -6
- package/src/runtime/streams/managed-stream.ts +4 -2
- package/src/runtime/streams/native-fallback-bound-session.ts +14 -103
- package/src/runtime/streams/session-actor-coordinator.ts +39 -88
- package/src/runtime/streams/stream-binding-runtime-ports.ts +3 -9
- package/src/runtime/streams/stream-session-runtime.ts +1 -5
- package/src/runtime/workers/index.ts +1 -1
|
@@ -29,7 +29,14 @@ class OperationRegistry {
|
|
|
29
29
|
entries = new Map();
|
|
30
30
|
nextId = 1n;
|
|
31
31
|
deadlineCursor;
|
|
32
|
+
/**
|
|
33
|
+
* A lower bound of the earliest pending deadline. Completed entries only
|
|
34
|
+
* leave it early; a full expiry pass replaces it with the exact value.
|
|
35
|
+
*/
|
|
36
|
+
earliestDeadlineMs = Number.POSITIVE_INFINITY;
|
|
37
|
+
scanEarliestDeadlineMs = Number.POSITIVE_INFINITY;
|
|
32
38
|
closed = false;
|
|
39
|
+
pendingCount = 0;
|
|
33
40
|
constructor(clock = systemClock, onPendingChanged) {
|
|
34
41
|
this.clock = clock;
|
|
35
42
|
this.onPendingChanged = onPendingChanged;
|
|
@@ -47,36 +54,63 @@ class OperationRegistry {
|
|
|
47
54
|
resolve = onResolve;
|
|
48
55
|
reject = onReject;
|
|
49
56
|
});
|
|
50
|
-
const
|
|
51
|
-
|
|
52
|
-
deadlineMs: timeoutOwner === 'registry' ? this.clock.now() + timeoutMs : undefined,
|
|
53
|
-
resolve,
|
|
54
|
-
reject
|
|
55
|
-
};
|
|
57
|
+
const deadlineMs = timeoutOwner === 'registry' ? this.clock.now() + timeoutMs : undefined;
|
|
58
|
+
const entry = { context, deadlineMs, resolve, reject };
|
|
56
59
|
this.entries.set(id, entry);
|
|
57
|
-
|
|
58
|
-
this.onPendingChanged?.();
|
|
60
|
+
this.notePending(deadlineMs);
|
|
59
61
|
return { id, promise };
|
|
60
62
|
}
|
|
61
|
-
|
|
63
|
+
/** Registers an operation whose terminal goes to `observer` instead of a Promise. */
|
|
64
|
+
registerObserved(timeoutMs, observer, context) {
|
|
65
|
+
if (this.closed)
|
|
66
|
+
throw new Error('Operation registry is closed.');
|
|
67
|
+
if (!Number.isFinite(timeoutMs) || timeoutMs < 0) {
|
|
68
|
+
throw new RangeError('timeoutMs must be a non-negative finite number.');
|
|
69
|
+
}
|
|
70
|
+
const id = this.nextId++;
|
|
71
|
+
const deadlineMs = this.clock.now() + timeoutMs;
|
|
72
|
+
this.entries.set(id, { context, deadlineMs, observer });
|
|
73
|
+
this.notePending(deadlineMs);
|
|
74
|
+
return id;
|
|
75
|
+
}
|
|
76
|
+
/** The time the next expiry pass has work, as a lower bound (spec 08 §4.2). */
|
|
77
|
+
nextDeadlineMs() {
|
|
78
|
+
return this.earliestDeadlineMs;
|
|
79
|
+
}
|
|
80
|
+
notePending(deadlineMs) {
|
|
81
|
+
this.pendingCount++;
|
|
82
|
+
const earlier = deadlineMs !== undefined && deadlineMs < this.earliestDeadlineMs;
|
|
83
|
+
if (earlier)
|
|
84
|
+
this.earliestDeadlineMs = deadlineMs;
|
|
85
|
+
if (earlier || this.pendingCount === 1)
|
|
86
|
+
this.onPendingChanged?.();
|
|
87
|
+
}
|
|
88
|
+
complete(id, value, terminalContextRetentionMs = 0) {
|
|
62
89
|
const entry = this.take(id);
|
|
63
90
|
if (entry === undefined)
|
|
64
91
|
return false;
|
|
65
|
-
entry.
|
|
92
|
+
if (entry.observer !== undefined)
|
|
93
|
+
entry.observer.operationCompleted(id, value, entry.context);
|
|
94
|
+
else
|
|
95
|
+
entry.resolve(value);
|
|
96
|
+
this.retainTerminal(id, entry, terminalContextRetentionMs);
|
|
66
97
|
return true;
|
|
67
98
|
}
|
|
68
99
|
fail(id, reason) {
|
|
69
100
|
const entry = this.take(id);
|
|
70
101
|
if (entry === undefined)
|
|
71
102
|
return false;
|
|
72
|
-
entry.
|
|
103
|
+
if (entry.observer !== undefined)
|
|
104
|
+
entry.observer.operationFailed(id, reason, entry.context);
|
|
105
|
+
else
|
|
106
|
+
entry.reject(reason);
|
|
73
107
|
return true;
|
|
74
108
|
}
|
|
75
109
|
cancel(id, message) {
|
|
76
110
|
return this.fail(id, new OperationCancelledError(id, message));
|
|
77
111
|
}
|
|
78
112
|
isPending(id) {
|
|
79
|
-
return this.
|
|
113
|
+
return this.pendingEntry(id) !== undefined;
|
|
80
114
|
}
|
|
81
115
|
context(id) {
|
|
82
116
|
return this.entries.get(id)?.context;
|
|
@@ -87,36 +121,70 @@ class OperationRegistry {
|
|
|
87
121
|
this.closed = true;
|
|
88
122
|
for (const id of this.entries.keys())
|
|
89
123
|
this.cancel(id, reason);
|
|
124
|
+
this.entries.clear();
|
|
90
125
|
this.deadlineCursor = undefined;
|
|
91
126
|
}
|
|
127
|
+
failAll(reason) {
|
|
128
|
+
for (const id of this.entries.keys())
|
|
129
|
+
this.fail(id, reason);
|
|
130
|
+
}
|
|
92
131
|
get size() {
|
|
93
|
-
return this.
|
|
132
|
+
return this.pendingCount;
|
|
94
133
|
}
|
|
95
134
|
expire(nowMs, turnDeadlineMs) {
|
|
96
135
|
let expired = 0;
|
|
97
136
|
while (this.clock.now() < turnDeadlineMs) {
|
|
98
|
-
this.deadlineCursor
|
|
137
|
+
if (this.deadlineCursor === undefined) {
|
|
138
|
+
this.deadlineCursor = this.entries.entries();
|
|
139
|
+
this.scanEarliestDeadlineMs = Number.POSITIVE_INFINITY;
|
|
140
|
+
}
|
|
99
141
|
const current = this.deadlineCursor.next();
|
|
100
142
|
if (current.done === true) {
|
|
101
143
|
this.deadlineCursor = undefined;
|
|
144
|
+
// Entries registered during the pass are appended and were scanned.
|
|
145
|
+
this.earliestDeadlineMs = this.scanEarliestDeadlineMs;
|
|
102
146
|
break;
|
|
103
147
|
}
|
|
104
148
|
const [id, entry] = current.value;
|
|
105
|
-
if (entry.deadlineMs
|
|
106
|
-
|
|
149
|
+
if (entry.deadlineMs === undefined)
|
|
150
|
+
continue;
|
|
151
|
+
if (entry.deadlineMs <= nowMs) {
|
|
152
|
+
if (!this.isPending(id))
|
|
153
|
+
this.entries.delete(id);
|
|
154
|
+
else if (this.fail(id, new OperationTimeoutError(id)))
|
|
107
155
|
expired++;
|
|
108
156
|
}
|
|
157
|
+
else if (entry.deadlineMs < this.scanEarliestDeadlineMs) {
|
|
158
|
+
this.scanEarliestDeadlineMs = entry.deadlineMs;
|
|
159
|
+
}
|
|
109
160
|
}
|
|
110
161
|
return expired;
|
|
111
162
|
}
|
|
112
163
|
take(id) {
|
|
113
|
-
const entry = this.
|
|
164
|
+
const entry = this.pendingEntry(id);
|
|
114
165
|
if (entry === undefined)
|
|
115
166
|
return undefined;
|
|
116
167
|
this.entries.delete(id);
|
|
117
|
-
|
|
168
|
+
this.pendingCount--;
|
|
169
|
+
if (this.pendingCount === 0)
|
|
118
170
|
this.onPendingChanged?.();
|
|
119
171
|
return entry;
|
|
120
172
|
}
|
|
173
|
+
pendingEntry(id) {
|
|
174
|
+
const entry = this.entries.get(id);
|
|
175
|
+
return entry !== undefined && (entry.resolve !== undefined || entry.observer !== undefined)
|
|
176
|
+
? entry
|
|
177
|
+
: undefined;
|
|
178
|
+
}
|
|
179
|
+
retainTerminal(id, entry, retentionMs) {
|
|
180
|
+
if (this.closed || entry.context === undefined || retentionMs === 0)
|
|
181
|
+
return;
|
|
182
|
+
entry.resolve = undefined;
|
|
183
|
+
entry.reject = undefined;
|
|
184
|
+
entry.observer = undefined;
|
|
185
|
+
entry.deadlineMs = this.clock.now() + retentionMs;
|
|
186
|
+
this.entries.set(id, entry);
|
|
187
|
+
this.earliestDeadlineMs = Math.min(this.earliestDeadlineMs, entry.deadlineMs);
|
|
188
|
+
}
|
|
121
189
|
}
|
|
122
190
|
exports.OperationRegistry = OperationRegistry;
|
|
@@ -2,7 +2,7 @@ import { ApplicationIngressRecordOwner } from '../application-jobs/application-i
|
|
|
2
2
|
import type { ApplicationJobQueuePort } from '../application-jobs/contracts';
|
|
3
3
|
import type { ZLinkRawBindingPort } from '../backend/raw-binding-port';
|
|
4
4
|
import { SubmitResult } from '../backend/runtime-values';
|
|
5
|
-
import { type PendingOperation } from './operation-registry';
|
|
5
|
+
import { type OperationObserver, type PendingOperation } from './operation-registry';
|
|
6
6
|
import { ServiceLivenessRegistry, type ServiceLivenessTick } from './service-liveness-registry';
|
|
7
7
|
import { ServiceMailbox, type ServiceMailboxRecord } from './service-mailbox';
|
|
8
8
|
import { ServiceTopologyRegistry, type ServiceNodeDescriptor } from './service-topology-registry';
|
|
@@ -14,9 +14,22 @@ export interface RawServiceRequestResult {
|
|
|
14
14
|
readonly failureCode: number;
|
|
15
15
|
readonly payload?: ServiceApplicationPayload;
|
|
16
16
|
}
|
|
17
|
+
/** Receives observed request terminals; the context is the caller's operation kind. */
|
|
18
|
+
export type RawServiceRequestObserver = OperationObserver<RawServiceRequestResult, number>;
|
|
19
|
+
/**
|
|
20
|
+
* A registered request. An observed remote request has no Promise; its
|
|
21
|
+
* terminal reaches the observer. Local and Promise-contract requests carry
|
|
22
|
+
* the Promise.
|
|
23
|
+
*/
|
|
24
|
+
export interface RawServiceObservedRequest {
|
|
25
|
+
readonly id: bigint;
|
|
26
|
+
readonly promise?: Promise<RawServiceRequestResult>;
|
|
27
|
+
}
|
|
17
28
|
/** An M6A application frame already owned by the Framework runtime. */
|
|
18
29
|
type ServiceApplicationPayloadInput = ServiceApplicationPayload | Buffer;
|
|
19
30
|
export interface RawServiceIngressRecord {
|
|
31
|
+
/** Source identity recorded once by the first accepting owner (Location runtime §9.3). */
|
|
32
|
+
requestSource?: import('../locations/request-source-resolver').ZLinkRequestSourceFence;
|
|
20
33
|
readonly onAdmitted?: () => void;
|
|
21
34
|
readonly command: number;
|
|
22
35
|
readonly flags: number;
|
|
@@ -104,12 +117,14 @@ export declare class RawServiceMeshRuntime {
|
|
|
104
117
|
disconnectPeerEndpoint(endpoint: string): void;
|
|
105
118
|
observePeerConnectionIntentRemoved(listener: (nodeRoutingId: string) => void): () => void;
|
|
106
119
|
observePeerRoute(nodeRoutingId: string): import('./durable-service-request').PeerRouteObservation;
|
|
120
|
+
waitForPeerRoute(nodeRoutingId: string, lifecycleGeneration: bigint, deadlineUnixMs: bigint, signal?: AbortSignal): Promise<void>;
|
|
107
121
|
get requestStopSignal(): AbortSignal;
|
|
108
122
|
observePeerRouteChanged(listener: (nodeRoutingId: string) => void): () => void;
|
|
109
123
|
hasSelectedPeerRoute(nodeRoutingId: string): boolean;
|
|
110
124
|
private notifyPeerRouteChanged;
|
|
111
125
|
private notifyPeerConnectionIntentRemoved;
|
|
112
|
-
announcePeer(nodeRoutingId: string):
|
|
126
|
+
announcePeer(nodeRoutingId: string): boolean;
|
|
127
|
+
private isPeerAnnouncementCurrent;
|
|
113
128
|
isPeerRouteReady(nodeRoutingId: string, lifecycleGeneration?: bigint): boolean;
|
|
114
129
|
announceExpectedPeers(): Promise<number>;
|
|
115
130
|
updateLocalDescriptor(options: {
|
|
@@ -124,7 +139,20 @@ export declare class RawServiceMeshRuntime {
|
|
|
124
139
|
sendToNode(targetNodeRoutingId: string, payload: ServiceApplicationPayloadInput): boolean | Promise<boolean>;
|
|
125
140
|
sendToChannel(channelName: string, payload: ServiceApplicationPayloadInput): Promise<SubmitResult>;
|
|
126
141
|
requestToNode(targetNodeRoutingId: string, payload: ServiceApplicationPayloadInput, timeoutMs: number, onAdmitted?: () => void): PendingOperation<RawServiceRequestResult>;
|
|
142
|
+
requestToNode(targetNodeRoutingId: string, payload: ServiceApplicationPayloadInput, timeoutMs: number, onAdmitted: (() => void) | undefined, observer: RawServiceRequestObserver, operationKind: number): RawServiceObservedRequest;
|
|
127
143
|
requestToChannel(channelName: string, payload: ServiceApplicationPayloadInput, timeoutMs: number, onAdmitted?: () => void): PendingOperation<RawServiceRequestResult>;
|
|
144
|
+
requestToChannel(channelName: string, payload: ServiceApplicationPayloadInput, timeoutMs: number, onAdmitted: (() => void) | undefined, observer: RawServiceRequestObserver, operationKind: number): RawServiceObservedRequest;
|
|
145
|
+
/**
|
|
146
|
+
* One pending entry per request: an observed request reports its terminal
|
|
147
|
+
* to the caller's observer; any other request keeps the Promise contract.
|
|
148
|
+
*/
|
|
149
|
+
private registerRequest;
|
|
150
|
+
/**
|
|
151
|
+
* An observed caller learns the operation id only when the request call
|
|
152
|
+
* returns, so a terminal decided inside that call is delivered after it.
|
|
153
|
+
*/
|
|
154
|
+
private completeRequest;
|
|
155
|
+
private failRequest;
|
|
128
156
|
private selectChannelTarget;
|
|
129
157
|
setServiceIngress(handler: RawServiceIngressHandler, accepts?: (command: number) => boolean): void;
|
|
130
158
|
reserveLocalIngress(signal?: AbortSignal): Promise<ApplicationIngressRecordOwner>;
|
|
@@ -148,6 +176,14 @@ export declare class RawServiceMeshRuntime {
|
|
|
148
176
|
private enqueueOrdinaryRecord;
|
|
149
177
|
expireOperations(nowMs: number, turnDeadlineMs: number): number;
|
|
150
178
|
get pendingOperationCount(): number;
|
|
179
|
+
cancelPendingOperations(reason: unknown): void;
|
|
180
|
+
/**
|
|
181
|
+
* The next management deadline of this node (spec 08 §4.2): request expiry,
|
|
182
|
+
* liveness probe or timeout, or an owned HELLO exchange still awaiting
|
|
183
|
+
* ADMIT, which keeps the existing announce cadence.
|
|
184
|
+
*/
|
|
185
|
+
nextMaintenanceDeadlineMs(nowMs: number): number;
|
|
186
|
+
private refreshAdmissionPending;
|
|
151
187
|
tickLiveness(nowMs?: number): ServiceLivenessTick;
|
|
152
188
|
/**
|
|
153
189
|
* The socket's one route observer (Core ROUTER §10.1). It replaces the
|
|
@@ -172,7 +208,7 @@ export declare class RawServiceMeshRuntime {
|
|
|
172
208
|
private sendControl;
|
|
173
209
|
private submitControl;
|
|
174
210
|
private startControlSend;
|
|
175
|
-
|
|
211
|
+
reportInfrastructureFailure(error: unknown): void;
|
|
176
212
|
private observeInfrastructureFailure;
|
|
177
213
|
private send;
|
|
178
214
|
private sendFailure;
|
|
@@ -177,13 +177,15 @@ class RawServiceMeshRuntime {
|
|
|
177
177
|
router.disconnectRid(nodeRoutingId);
|
|
178
178
|
}
|
|
179
179
|
else {
|
|
180
|
-
|
|
180
|
+
try {
|
|
181
|
+
router.disconnect(endpoint);
|
|
182
|
+
}
|
|
183
|
+
catch (error) {
|
|
184
|
+
if (!isAlreadyDisconnectedError(error))
|
|
185
|
+
throw error;
|
|
186
|
+
}
|
|
181
187
|
}
|
|
182
188
|
}
|
|
183
|
-
catch (error) {
|
|
184
|
-
if (!isAlreadyDisconnectedError(error))
|
|
185
|
-
throw error;
|
|
186
|
-
}
|
|
187
189
|
finally {
|
|
188
190
|
if (current !== undefined)
|
|
189
191
|
this.removePeer(current);
|
|
@@ -237,6 +239,34 @@ class RawServiceMeshRuntime {
|
|
|
237
239
|
ready: admitted !== undefined && (selected === undefined || admitted === selected)
|
|
238
240
|
};
|
|
239
241
|
}
|
|
242
|
+
async waitForPeerRoute(nodeRoutingId, lifecycleGeneration, deadlineUnixMs, signal) {
|
|
243
|
+
const remaining = deadlineUnixMs - BigInt(Date.now());
|
|
244
|
+
if (remaining <= 0n)
|
|
245
|
+
throw new operation_registry_1.OperationTimeoutError(0n);
|
|
246
|
+
const pending = this.operations.register(Number(remaining));
|
|
247
|
+
const check = () => {
|
|
248
|
+
if (this.isPeerRouteReady(nodeRoutingId, lifecycleGeneration)) {
|
|
249
|
+
this.operations.complete(pending.id, { terminalResult: runtime_values_1.RequestResult.Ok, failureCode: 0 });
|
|
250
|
+
}
|
|
251
|
+
};
|
|
252
|
+
const unsubscribe = this.observePeerRouteChanged((rid) => {
|
|
253
|
+
if (rid === nodeRoutingId)
|
|
254
|
+
check();
|
|
255
|
+
});
|
|
256
|
+
const abort = () => this.operations.fail(pending.id, signal?.reason);
|
|
257
|
+
signal?.addEventListener('abort', abort, { once: true });
|
|
258
|
+
try {
|
|
259
|
+
if (signal?.aborted === true)
|
|
260
|
+
abort();
|
|
261
|
+
else
|
|
262
|
+
check();
|
|
263
|
+
await pending.promise;
|
|
264
|
+
}
|
|
265
|
+
finally {
|
|
266
|
+
unsubscribe();
|
|
267
|
+
signal?.removeEventListener('abort', abort);
|
|
268
|
+
}
|
|
269
|
+
}
|
|
240
270
|
get requestStopSignal() {
|
|
241
271
|
return this.applicationJobStop.signal;
|
|
242
272
|
}
|
|
@@ -262,26 +292,29 @@ class RawServiceMeshRuntime {
|
|
|
262
292
|
listener(nodeRoutingId);
|
|
263
293
|
}
|
|
264
294
|
announcePeer(nodeRoutingId) {
|
|
295
|
+
if (this.closed)
|
|
296
|
+
return false;
|
|
265
297
|
const generation = this.selectedRoutes.get(nodeRoutingId);
|
|
266
298
|
if (generation === undefined)
|
|
267
|
-
return
|
|
268
|
-
const current = () => {
|
|
269
|
-
const admission = this.topology.routeAdmission(nodeRoutingId);
|
|
270
|
-
return (this.selectedRoutes.get(nodeRoutingId) === generation &&
|
|
271
|
-
!(admission?.connectionId === routeConnectionId(generation) &&
|
|
272
|
-
admission.remoteAdmitReceived === true) &&
|
|
273
|
-
this.peerAdmissionSealed?.() !== true);
|
|
274
|
-
};
|
|
299
|
+
return false;
|
|
275
300
|
const key = controlSendKey(nodeRoutingId, service_wire_m6a_codec_1.M6aServiceWireCommand.hello);
|
|
276
|
-
if (!
|
|
301
|
+
if (!this.isPeerAnnouncementCurrent(nodeRoutingId, generation)) {
|
|
277
302
|
this.controlSends.delete(key);
|
|
278
|
-
return
|
|
303
|
+
return false;
|
|
279
304
|
}
|
|
305
|
+
const current = () => this.isPeerAnnouncementCurrent(nodeRoutingId, generation);
|
|
280
306
|
const existing = this.controlSends.get(key);
|
|
281
307
|
const hello = existing?.current?.() === true
|
|
282
308
|
? existing.hello
|
|
283
309
|
: (0, service_wire_m6a_codec_1.encodeRouteMeshAdmission)(service_wire_m6a_codec_1.M6aServiceWireCommand.hello, this.topology.localDescriptor());
|
|
284
|
-
return
|
|
310
|
+
return this.startControlSend(nodeRoutingId, service_wire_m6a_codec_1.M6aServiceWireCommand.hello, () => this.submitControl(nodeRoutingId, [hello]), current, hello);
|
|
311
|
+
}
|
|
312
|
+
isPeerAnnouncementCurrent(nodeRoutingId, generation) {
|
|
313
|
+
const admission = this.topology.routeAdmission(nodeRoutingId);
|
|
314
|
+
return (this.selectedRoutes.get(nodeRoutingId) === generation &&
|
|
315
|
+
!(admission?.connectionId === routeConnectionId(generation) &&
|
|
316
|
+
admission.remoteAdmitReceived === true) &&
|
|
317
|
+
this.peerAdmissionSealed?.() !== true);
|
|
285
318
|
}
|
|
286
319
|
isPeerRouteReady(nodeRoutingId, lifecycleGeneration) {
|
|
287
320
|
// Admission is bound to the observed selected route: the route observer
|
|
@@ -353,17 +386,42 @@ class RawServiceMeshRuntime {
|
|
|
353
386
|
? runtime_values_1.SubmitResult.Ok
|
|
354
387
|
: runtime_values_1.SubmitResult.NotConnected;
|
|
355
388
|
}
|
|
356
|
-
requestToNode(targetNodeRoutingId, payload, timeoutMs, onAdmitted) {
|
|
357
|
-
return this.requestToTarget(targetNodeRoutingId, payload, timeoutMs, undefined, onAdmitted);
|
|
389
|
+
requestToNode(targetNodeRoutingId, payload, timeoutMs, onAdmitted, observer, operationKind) {
|
|
390
|
+
return this.requestToTarget(targetNodeRoutingId, payload, timeoutMs, undefined, onAdmitted, observer, operationKind);
|
|
358
391
|
}
|
|
359
|
-
requestToChannel(channelName, payload, timeoutMs, onAdmitted) {
|
|
392
|
+
requestToChannel(channelName, payload, timeoutMs, onAdmitted, observer, operationKind) {
|
|
360
393
|
const selection = this.selectChannelTarget(channelName);
|
|
361
394
|
if (selection.kind !== 'selected') {
|
|
362
|
-
const pending = this.
|
|
363
|
-
this.
|
|
395
|
+
const pending = this.registerRequest(timeoutMs, observer, operationKind);
|
|
396
|
+
this.completeRequest(pending, selection.requestResult);
|
|
364
397
|
return pending;
|
|
365
398
|
}
|
|
366
|
-
return this.requestToTarget(selection.peer.descriptor.nodeRoutingId, payload, timeoutMs, channelName, onAdmitted);
|
|
399
|
+
return this.requestToTarget(selection.peer.descriptor.nodeRoutingId, payload, timeoutMs, channelName, onAdmitted, observer, operationKind);
|
|
400
|
+
}
|
|
401
|
+
/**
|
|
402
|
+
* One pending entry per request: an observed request reports its terminal
|
|
403
|
+
* to the caller's observer; any other request keeps the Promise contract.
|
|
404
|
+
*/
|
|
405
|
+
registerRequest(timeoutMs, observer, operationKind) {
|
|
406
|
+
return observer === undefined
|
|
407
|
+
? this.operations.register(timeoutMs)
|
|
408
|
+
: { id: this.operations.registerObserved(timeoutMs, observer, operationKind) };
|
|
409
|
+
}
|
|
410
|
+
/**
|
|
411
|
+
* An observed caller learns the operation id only when the request call
|
|
412
|
+
* returns, so a terminal decided inside that call is delivered after it.
|
|
413
|
+
*/
|
|
414
|
+
completeRequest(pending, result) {
|
|
415
|
+
if (pending.promise === undefined)
|
|
416
|
+
queueMicrotask(() => this.operations.complete(pending.id, result));
|
|
417
|
+
else
|
|
418
|
+
this.operations.complete(pending.id, result);
|
|
419
|
+
}
|
|
420
|
+
failRequest(pending, error) {
|
|
421
|
+
if (pending.promise === undefined)
|
|
422
|
+
queueMicrotask(() => this.operations.fail(pending.id, error));
|
|
423
|
+
else
|
|
424
|
+
this.operations.fail(pending.id, error);
|
|
367
425
|
}
|
|
368
426
|
selectChannelTarget(channelName) {
|
|
369
427
|
const selected = this.topology.selectChannel(channelName, (peer) => this.isPeerRouteReady(peer.descriptor.nodeRoutingId));
|
|
@@ -718,6 +776,7 @@ class RawServiceMeshRuntime {
|
|
|
718
776
|
}
|
|
719
777
|
else if (header.command === service_wire_m6a_codec_1.M6aServiceWireCommand.admit) {
|
|
720
778
|
this.controlSends.delete(helloKey);
|
|
779
|
+
this.refreshAdmissionPending(nowMs);
|
|
721
780
|
if (result === 'notRequired') {
|
|
722
781
|
this.retireNotRequiredExpectedPeer(received.sourceRid, descriptor.advertisedEndpoint);
|
|
723
782
|
}
|
|
@@ -779,12 +838,7 @@ class RawServiceMeshRuntime {
|
|
|
779
838
|
}
|
|
780
839
|
if (header.flags !== 0 ||
|
|
781
840
|
received.parts.length !== 2 ||
|
|
782
|
-
!
|
|
783
|
-
service_wire_m6a_codec_1.M6aServiceWireCommand.nodeSend,
|
|
784
|
-
service_wire_m6a_codec_1.M6aServiceWireCommand.nodeRequest,
|
|
785
|
-
service_wire_m6a_codec_1.M6aServiceWireCommand.channelSend,
|
|
786
|
-
service_wire_m6a_codec_1.M6aServiceWireCommand.channelRequest
|
|
787
|
-
].includes(header.command)) {
|
|
841
|
+
!isApplicationEnvelopeCommand(header.command)) {
|
|
788
842
|
return 'protocolError';
|
|
789
843
|
}
|
|
790
844
|
let owner;
|
|
@@ -820,9 +874,9 @@ class RawServiceMeshRuntime {
|
|
|
820
874
|
parts: received.parts,
|
|
821
875
|
sourceRoutingId: received.sourceRid,
|
|
822
876
|
sourceRoute: received.sourceRoute,
|
|
823
|
-
|
|
877
|
+
reply: received.reply,
|
|
824
878
|
requestSequence: received.requestSeq,
|
|
825
|
-
|
|
879
|
+
correlation,
|
|
826
880
|
applicationJob
|
|
827
881
|
});
|
|
828
882
|
if (accepted)
|
|
@@ -845,11 +899,38 @@ class RawServiceMeshRuntime {
|
|
|
845
899
|
get pendingOperationCount() {
|
|
846
900
|
return this.operations.size;
|
|
847
901
|
}
|
|
902
|
+
cancelPendingOperations(reason) {
|
|
903
|
+
this.operations.failAll(reason);
|
|
904
|
+
}
|
|
905
|
+
/**
|
|
906
|
+
* The next management deadline of this node (spec 08 §4.2): request expiry,
|
|
907
|
+
* liveness probe or timeout, or an owned HELLO exchange still awaiting
|
|
908
|
+
* ADMIT, which keeps the existing announce cadence.
|
|
909
|
+
*/
|
|
910
|
+
nextMaintenanceDeadlineMs(nowMs) {
|
|
911
|
+
this.refreshAdmissionPending(nowMs);
|
|
912
|
+
return Math.min(this.operations.nextDeadlineMs(), this.liveness.nextDeadlineMs());
|
|
913
|
+
}
|
|
914
|
+
refreshAdmissionPending(nowMs) {
|
|
915
|
+
let pending = false;
|
|
916
|
+
if (!this.closed && this.controlSends.size !== 0) {
|
|
917
|
+
for (const nodeRoutingId of this.selectedRoutes.keys()) {
|
|
918
|
+
const exchange = this.controlSends.get(controlSendKey(nodeRoutingId, service_wire_m6a_codec_1.M6aServiceWireCommand.hello));
|
|
919
|
+
if (exchange?.current?.() === true) {
|
|
920
|
+
pending = true;
|
|
921
|
+
break;
|
|
922
|
+
}
|
|
923
|
+
}
|
|
924
|
+
}
|
|
925
|
+
this.liveness.setAdmissionPending(pending, nowMs);
|
|
926
|
+
}
|
|
848
927
|
tickLiveness(nowMs = performance.now()) {
|
|
928
|
+
const admissionDue = this.liveness.tickAdmission(nowMs);
|
|
849
929
|
const result = this.liveness.tick(nowMs);
|
|
850
930
|
this.requireStarted();
|
|
851
|
-
|
|
852
|
-
|
|
931
|
+
if (admissionDue)
|
|
932
|
+
for (const nodeRoutingId of this.selectedRoutes.keys())
|
|
933
|
+
void this.announcePeer(nodeRoutingId);
|
|
853
934
|
for (const probe of result.probes) {
|
|
854
935
|
const parts = [
|
|
855
936
|
livenessCodec.encodeLivenessRecord({
|
|
@@ -907,6 +988,7 @@ class RawServiceMeshRuntime {
|
|
|
907
988
|
// A new selected route admits only through a new handshake.
|
|
908
989
|
for (const nodeRoutingId of selected)
|
|
909
990
|
await this.announcePeer(nodeRoutingId);
|
|
991
|
+
this.refreshAdmissionPending(performance.now());
|
|
910
992
|
return changes;
|
|
911
993
|
}
|
|
912
994
|
close() {
|
|
@@ -933,13 +1015,12 @@ class RawServiceMeshRuntime {
|
|
|
933
1015
|
this.router = undefined;
|
|
934
1016
|
this.host = undefined;
|
|
935
1017
|
}
|
|
936
|
-
requestToTarget(targetNodeRoutingId, payload, timeoutMs, channelName, onAdmitted) {
|
|
1018
|
+
requestToTarget(targetNodeRoutingId, payload, timeoutMs, channelName, onAdmitted, observer, operationKind) {
|
|
937
1019
|
const correlation = this.nextCorrelation++;
|
|
938
1020
|
const header = channelName === undefined
|
|
939
1021
|
? (0, service_wire_m6a_codec_1.encodeNodeRequestHeader)(correlation)
|
|
940
1022
|
: (0, service_wire_m6a_codec_1.encodeChannelRequestHeader)(correlation, channelName);
|
|
941
1023
|
const encodedPayload = this.applicationFrame(payload);
|
|
942
|
-
const pending = this.operations.register(timeoutMs);
|
|
943
1024
|
let selectedTargetNodeRoutingId = targetNodeRoutingId;
|
|
944
1025
|
if (selectedTargetNodeRoutingId !== this.descriptor.nodeRoutingId &&
|
|
945
1026
|
!this.isPeerRouteReady(selectedTargetNodeRoutingId)) {
|
|
@@ -966,6 +1047,9 @@ class RawServiceMeshRuntime {
|
|
|
966
1047
|
}
|
|
967
1048
|
}
|
|
968
1049
|
if (selectedTargetNodeRoutingId === this.descriptor.nodeRoutingId) {
|
|
1050
|
+
// The local admission path aborts its capacity wait on the terminal
|
|
1051
|
+
// Promise, so a local request always keeps the Promise entry.
|
|
1052
|
+
const pending = this.operations.register(timeoutMs);
|
|
969
1053
|
const parts = [header, encodedPayload];
|
|
970
1054
|
const capacityStop = new AbortController();
|
|
971
1055
|
void pending.promise.finally(() => capacityStop.abort()).catch(() => undefined);
|
|
@@ -1009,12 +1093,13 @@ class RawServiceMeshRuntime {
|
|
|
1009
1093
|
})().catch((error) => this.operations.fail(pending.id, error));
|
|
1010
1094
|
return pending;
|
|
1011
1095
|
}
|
|
1096
|
+
const pending = this.registerRequest(timeoutMs, observer, operationKind);
|
|
1012
1097
|
const selectedPeer = this.topology.admittedPeer(selectedTargetNodeRoutingId);
|
|
1013
1098
|
if (selectedPeer === undefined) {
|
|
1014
1099
|
// Logical target selection is the requester's decision: an RID that is
|
|
1015
1100
|
// not an admitted peer is not a target. Whether an admitted target's
|
|
1016
1101
|
// route can carry the request is Core's REQUEST result.
|
|
1017
|
-
this.
|
|
1102
|
+
this.completeRequest(pending, {
|
|
1018
1103
|
terminalResult: runtime_values_1.RequestResult.NotFound,
|
|
1019
1104
|
failureCode: REQUEST_TARGET_NOT_FOUND_FAILURE_CODE
|
|
1020
1105
|
});
|
|
@@ -1026,7 +1111,7 @@ class RawServiceMeshRuntime {
|
|
|
1026
1111
|
request = this.requireStarted().request(selectedTargetNodeRoutingId, parts, timeoutMs, selectedPeer.liveness?.recordReceived, onAdmitted);
|
|
1027
1112
|
}
|
|
1028
1113
|
catch (error) {
|
|
1029
|
-
this.
|
|
1114
|
+
this.failRequest(pending, error);
|
|
1030
1115
|
return pending;
|
|
1031
1116
|
}
|
|
1032
1117
|
void request.then((replyParts) => {
|
|
@@ -1146,6 +1231,8 @@ class RawServiceMeshRuntime {
|
|
|
1146
1231
|
}
|
|
1147
1232
|
startControlSend(target, command, attempt, current, hello) {
|
|
1148
1233
|
const key = controlSendKey(target, command);
|
|
1234
|
+
if (command === service_wire_m6a_codec_1.M6aServiceWireCommand.hello)
|
|
1235
|
+
this.liveness.setAdmissionPending(true, performance.now());
|
|
1149
1236
|
const existing = this.controlSends.get(key);
|
|
1150
1237
|
if (existing !== undefined &&
|
|
1151
1238
|
existing.task !== undefined &&
|
|
@@ -1185,15 +1272,17 @@ class RawServiceMeshRuntime {
|
|
|
1185
1272
|
this.controlSends.set(key, state);
|
|
1186
1273
|
task.then(() => { }, (error) => {
|
|
1187
1274
|
completeSend();
|
|
1188
|
-
|
|
1189
|
-
this.reportInfrastructureFailure(error);
|
|
1190
|
-
});
|
|
1191
|
-
this.infrastructureTaskRunner?.runDetached('RouteMesh control SEND', async () => {
|
|
1192
|
-
await task;
|
|
1275
|
+
this.reportInfrastructureFailure(error);
|
|
1193
1276
|
});
|
|
1194
1277
|
return true;
|
|
1195
1278
|
}
|
|
1196
1279
|
reportInfrastructureFailure(error) {
|
|
1280
|
+
if (this.infrastructureTaskRunner !== undefined) {
|
|
1281
|
+
this.infrastructureTaskRunner.runDetached('RouteMesh infrastructure', async () => {
|
|
1282
|
+
throw error;
|
|
1283
|
+
});
|
|
1284
|
+
return;
|
|
1285
|
+
}
|
|
1197
1286
|
this.infrastructureFailure = {
|
|
1198
1287
|
error: this.infrastructureFailure === undefined
|
|
1199
1288
|
? error
|
|
@@ -1229,7 +1318,7 @@ class RawServiceMeshRuntime {
|
|
|
1229
1318
|
}
|
|
1230
1319
|
exports.RawServiceMeshRuntime = RawServiceMeshRuntime;
|
|
1231
1320
|
function controlSendKey(target, command) {
|
|
1232
|
-
return
|
|
1321
|
+
return `${command}:${target}`;
|
|
1233
1322
|
}
|
|
1234
1323
|
function routeConnectionId(generation) {
|
|
1235
1324
|
return `route:${generation}`;
|
|
@@ -1239,20 +1328,27 @@ function routeConnectionId(generation) {
|
|
|
1239
1328
|
* not application NodeSend(16) envelopes. Keep this list closed: a bare
|
|
1240
1329
|
* record outside the frozen control vocabulary remains a protocol error.
|
|
1241
1330
|
*/
|
|
1331
|
+
const BARE_INFRASTRUCTURE_CONTROLS = new Set([
|
|
1332
|
+
service_wire_constants_generated_1.ServiceWireCommand.relocationReady,
|
|
1333
|
+
service_wire_constants_generated_1.ServiceWireCommand.relocationData,
|
|
1334
|
+
service_wire_constants_generated_1.ServiceWireCommand.replyRelay,
|
|
1335
|
+
service_wire_constants_generated_1.ServiceWireCommand.relocationCutover,
|
|
1336
|
+
service_wire_constants_generated_1.ServiceWireCommand.relocationPrepare,
|
|
1337
|
+
service_wire_constants_generated_1.ServiceWireCommand.sessionRelocationSeal,
|
|
1338
|
+
service_wire_constants_generated_1.ServiceWireCommand.sessionRelocationSealed,
|
|
1339
|
+
service_wire_constants_generated_1.ServiceWireCommand.sessionRelocationRoute,
|
|
1340
|
+
service_wire_constants_generated_1.ServiceWireCommand.replyRelayAck,
|
|
1341
|
+
service_wire_constants_generated_1.ServiceWireCommand.relocationState,
|
|
1342
|
+
service_wire_constants_generated_1.ServiceWireCommand.relocationFailed
|
|
1343
|
+
]);
|
|
1242
1344
|
function isBareInfrastructureControl(command) {
|
|
1243
|
-
return
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
service_wire_constants_generated_1.ServiceWireCommand.sessionRelocationSealed,
|
|
1251
|
-
service_wire_constants_generated_1.ServiceWireCommand.sessionRelocationRoute,
|
|
1252
|
-
service_wire_constants_generated_1.ServiceWireCommand.replyRelayAck,
|
|
1253
|
-
service_wire_constants_generated_1.ServiceWireCommand.relocationState,
|
|
1254
|
-
service_wire_constants_generated_1.ServiceWireCommand.relocationFailed
|
|
1255
|
-
].includes(command);
|
|
1345
|
+
return BARE_INFRASTRUCTURE_CONTROLS.has(command);
|
|
1346
|
+
}
|
|
1347
|
+
function isApplicationEnvelopeCommand(command) {
|
|
1348
|
+
return (command === service_wire_m6a_codec_1.M6aServiceWireCommand.nodeSend ||
|
|
1349
|
+
command === service_wire_m6a_codec_1.M6aServiceWireCommand.nodeRequest ||
|
|
1350
|
+
command === service_wire_m6a_codec_1.M6aServiceWireCommand.channelSend ||
|
|
1351
|
+
command === service_wire_m6a_codec_1.M6aServiceWireCommand.channelRequest);
|
|
1256
1352
|
}
|
|
1257
1353
|
function protocolCommand(parts) {
|
|
1258
1354
|
if (parts.length === 0)
|
|
@@ -22,14 +22,25 @@ export declare class ServiceLivenessConnection {
|
|
|
22
22
|
tryGetProbe(nowMs: number, allocateProbeId: () => bigint): bigint | undefined;
|
|
23
23
|
acknowledge(probeId: bigint, nowMs: number): boolean;
|
|
24
24
|
}
|
|
25
|
-
/** Uses monotonic milliseconds and never treats application traffic as a probe ACK. */
|
|
26
25
|
export declare class ServiceLivenessRegistry {
|
|
27
26
|
private readonly probeIntervalMs;
|
|
28
27
|
private readonly peerTimeoutMs;
|
|
29
28
|
private readonly peers;
|
|
30
29
|
private nextProbeId;
|
|
30
|
+
/**
|
|
31
|
+
* The earliest probe or timeout among admitted peers. Received traffic only
|
|
32
|
+
* extends a peer's deadline, so this stays a lower bound between ticks.
|
|
33
|
+
*/
|
|
34
|
+
private nextDueMs;
|
|
35
|
+
private admissionActivityMs?;
|
|
31
36
|
constructor(probeIntervalMs?: number, peerTimeoutMs?: number);
|
|
32
37
|
admit(nodeRoutingId: string, connectionId: string | bigint, nowMs: number): ServiceLivenessConnection;
|
|
38
|
+
/** When the next tick has probe or timeout work (spec 08 §4.2 management deadline). */
|
|
39
|
+
nextDeadlineMs(): number;
|
|
40
|
+
/** Pending admission shares the existing liveness management cadence (MeshNode §7.1). */
|
|
41
|
+
setAdmissionPending(pending: boolean, nowMs: number): void;
|
|
42
|
+
private nextAdmissionDeadlineMs;
|
|
43
|
+
tickAdmission(nowMs: number): boolean;
|
|
33
44
|
recordReceived(connection: ServiceLivenessConnection, nowMs: number): void;
|
|
34
45
|
disconnect(nodeRoutingId: string, connectionId: string | bigint): boolean;
|
|
35
46
|
acknowledge(nodeRoutingId: string, connectionId: string | bigint, probeId: bigint, nowMs: number): boolean;
|