@zlink-systems/framework 0.24.0 → 0.26.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/Channels/IZLinkFanoutClient.d.ts +0 -6
- package/dist/contracts/RouteMesh/RuntimeTopology.d.ts +8 -0
- package/dist/internal.d.ts +1 -0
- package/dist/internal.js +1 -0
- package/dist/runtime/activation-admission.d.ts +29 -0
- package/dist/runtime/activation-admission.js +61 -0
- package/dist/runtime/actors/actor-context.js +6 -6
- package/dist/runtime/actors/actor-handoff.d.ts +9 -3
- package/dist/runtime/actors/actor-handoff.js +28 -17
- package/dist/runtime/actors/actor-local-native-join.js +2 -18
- package/dist/runtime/actors/actor-remote-joiner.d.ts +2 -2
- package/dist/runtime/actors/actor-remote-joiner.js +6 -8
- package/dist/runtime/actors/actor-runtime-contracts.d.ts +4 -2
- package/dist/runtime/actors/actor-source-transfer.d.ts +5 -5
- package/dist/runtime/actors/deferred-join-completion.d.ts +14 -0
- package/dist/runtime/actors/deferred-join-completion.js +20 -0
- package/dist/runtime/actors/index.d.ts +1 -1
- package/dist/runtime/actors/index.js +15 -5
- package/dist/runtime/admission.d.ts +5 -1
- package/dist/runtime/admission.js +4 -0
- package/dist/runtime/backend/contracts/index.d.ts +2 -10
- package/dist/runtime/backend/mesh-actor-session-node-adapter.js +2 -9
- package/dist/runtime/backend/node/node-backend-adapter-factory.d.ts +1 -2
- package/dist/runtime/backend/node/node-backend-adapter-factory.js +4 -18
- package/dist/runtime/backend/node/node-backend-adapter-support.d.ts +6 -3
- package/dist/runtime/backend/node/node-backend-adapter-support.js +12 -28
- package/dist/runtime/backend/node/node-event-loop-poller.d.ts +1 -1
- package/dist/runtime/backend/node/node-event-loop-poller.js +8 -2
- package/dist/runtime/backend/node/node-raw-binding-port.d.ts +1 -1
- package/dist/runtime/backend/node/node-raw-binding-port.js +11 -3
- package/dist/runtime/backend/node/node-raw-mesh-backend.d.ts +12 -9
- package/dist/runtime/backend/node/node-raw-mesh-backend.js +61 -29
- package/dist/runtime/backend/node/node-socket-backend-adapter.js +1 -1
- package/dist/runtime/backend/raw-binding-port.d.ts +12 -0
- package/dist/runtime/channels/channel-clients.d.ts +0 -1
- package/dist/runtime/channels/channel-clients.js +0 -8
- package/dist/runtime/channels/channel-outbound-operations.js +2 -10
- package/dist/runtime/channels/channel-runtime-manager.d.ts +2 -5
- package/dist/runtime/channels/channel-runtime-manager.js +1 -12
- package/dist/runtime/channels/channel-socket-registry.d.ts +17 -4
- package/dist/runtime/channels/channel-socket-registry.js +49 -62
- package/dist/runtime/channels/channel-transports.d.ts +0 -3
- package/dist/runtime/channels/fanout-location-runtime.js +3 -9
- package/dist/runtime/execution/index.d.ts +18 -8
- package/dist/runtime/execution/index.js +55 -29
- package/dist/runtime/execution/serial-execution-queue.d.ts +5 -6
- package/dist/runtime/execution/serial-execution-queue.js +49 -15
- package/dist/runtime/foundation/listener-records.d.ts +11 -0
- package/dist/runtime/foundation/listener-records.js +20 -0
- package/dist/runtime/foundation/raw-service-mesh-runtime.d.ts +10 -21
- package/dist/runtime/foundation/raw-service-mesh-runtime.js +66 -392
- package/dist/runtime/foundation/service-authority-payload-codec.d.ts +1 -0
- package/dist/runtime/foundation/service-authority-payload-codec.js +8 -0
- package/dist/runtime/foundation/service-maintenance-runtime.js +23 -2
- package/dist/runtime/foundation/service-relocation-coordinator.d.ts +9 -0
- package/dist/runtime/foundation/service-relocation-coordinator.js +14 -1
- package/dist/runtime/foundation/service-relocation-object-owner.d.ts +8 -0
- package/dist/runtime/foundation/service-relocation-object-owner.js +16 -4
- package/dist/runtime/foundation/service-session-binding-ingress-port.d.ts +6 -13
- package/dist/runtime/foundation/service-stateful-runtime.d.ts +10 -7
- package/dist/runtime/foundation/service-stateful-runtime.js +100 -60
- package/dist/runtime/foundation/service-stateful-wire-codec.d.ts +9 -4
- package/dist/runtime/foundation/service-stateful-wire-codec.js +153 -90
- package/dist/runtime/foundation/service-topology-registry.d.ts +1 -2
- package/dist/runtime/foundation/service-topology-registry.js +6 -30
- package/dist/runtime/host/actor-transfer-runtime.d.ts +17 -15
- package/dist/runtime/host/actor-transfer-runtime.js +73 -86
- package/dist/runtime/host/index.d.ts +6 -2
- package/dist/runtime/host/index.js +63 -37
- package/dist/runtime/host/remote-bound-session-relay.js +4 -3
- package/dist/runtime/host/route-mesh-runtime.d.ts +2 -0
- package/dist/runtime/host/route-mesh-runtime.js +7 -5
- package/dist/runtime/host/service-relocation-host-runtime.d.ts +50 -8
- package/dist/runtime/host/service-relocation-host-runtime.js +343 -270
- package/dist/runtime/host/spot-runtime-options-factory.d.ts +7 -4
- package/dist/runtime/host/spot-runtime-options-factory.js +4 -8
- package/dist/runtime/host/stateful-authority-route-runtime.js +6 -2
- package/dist/runtime/host/user-spot-creation-coordinator.d.ts +11 -3
- package/dist/runtime/host/user-spot-creation-coordinator.js +85 -87
- package/dist/runtime/locations/in-memory-provider-location-store.js +8 -6
- package/dist/runtime/locations/lifecycle.d.ts +1 -1
- package/dist/runtime/locations/lifecycle.js +2 -2
- package/dist/runtime/locations/resolvers.js +7 -2
- package/dist/runtime/locations/spot-location-claims.d.ts +2 -2
- package/dist/runtime/locations/spot-location-claims.js +3 -27
- package/dist/runtime/protocol/service_wire_codec.generated.d.ts +1 -0
- package/dist/runtime/protocol/service_wire_codec.generated.js +5 -1
- package/dist/runtime/protocol/service_wire_pilot_codec.generated.d.ts +1 -0
- package/dist/runtime/protocol/service_wire_pilot_codec.generated.js +3 -2
- package/dist/runtime/spots/formal-remote-actor-admission-registry.d.ts +3 -3
- package/dist/runtime/spots/formal-remote-actor-admission-registry.js +4 -4
- package/dist/runtime/spots/formal-remote-actor-transfer-registry.d.ts +3 -3
- package/dist/runtime/spots/index.d.ts +25 -19
- package/dist/runtime/spots/index.js +207 -205
- package/dist/runtime/spots/spot-activation-registry.d.ts +4 -2
- package/dist/runtime/spots/spot-activation-registry.js +34 -31
- package/dist/runtime/spots/spot-activation-state.d.ts +2 -11
- package/dist/runtime/spots/spot-activation-state.js +4 -17
- package/dist/runtime/spots/spot-activation.d.ts +8 -6
- package/dist/runtime/spots/spot-activation.js +54 -49
- package/dist/runtime/spots/spot-actor-admission-coordinator.d.ts +1 -1
- package/dist/runtime/spots/spot-actor-admission-coordinator.js +1 -1
- package/dist/runtime/spots/spot-actor-join-dispatch.d.ts +2 -2
- package/dist/runtime/spots/spot-actor-join-dispatch.js +3 -5
- package/dist/runtime/spots/spot-actor-lifecycle-drain.js +2 -2
- package/dist/runtime/spots/spot-actor-membership.d.ts +4 -0
- package/dist/runtime/spots/spot-actor-membership.js +26 -12
- package/dist/runtime/spots/spot-entry-activation.d.ts +1 -2
- package/dist/runtime/spots/spot-entry-activation.js +0 -1
- package/dist/runtime/spots/spot-manager-public.js +1 -1
- package/dist/runtime/spots/spot-native-actor-join-admission.d.ts +1 -1
- package/dist/runtime/spots/spot-native-actor-join-admission.js +2 -2
- package/dist/runtime/spots/spot-node-runtime-manager.d.ts +5 -5
- package/dist/runtime/spots/spot-node-runtime-manager.js +7 -11
- package/dist/runtime/spots/spot-outbound.js +1 -29
- package/dist/runtime/spots/spot-routed-actor-admission.d.ts +1 -0
- package/dist/runtime/spots/spot-routed-actor-admission.js +10 -0
- package/dist/runtime/spots/spot-routed-frame-dispatch.d.ts +2 -6
- package/dist/runtime/spots/spot-routed-frame-dispatch.js +2 -70
- package/dist/runtime/spots/spot-runtime-ports.d.ts +3 -5
- package/dist/runtime/spots/spot-serial-executor.d.ts +5 -0
- package/dist/runtime/spots/spot-serial-executor.js +8 -1
- package/dist/runtime/spots/spot-serial-turn-executor.d.ts +3 -0
- package/dist/runtime/spots/spot-serial-turn-executor.js +8 -4
- package/dist/runtime/streams/actor-session-binding-registry.d.ts +13 -15
- package/dist/runtime/streams/actor-session-binding-registry.js +19 -171
- package/dist/runtime/streams/actor-session-binding-runtime-owner.d.ts +3 -4
- package/dist/runtime/streams/bound-session-service.js +1 -18
- package/dist/runtime/streams/index.d.ts +2 -0
- package/dist/runtime/streams/index.js +19 -19
- package/dist/runtime/streams/session-serial-executor.js +2 -2
- package/package.json +3 -3
- package/src/contracts/Channels/IZLinkFanoutClient.ts +0 -7
- package/src/contracts/RouteMesh/RuntimeTopology.ts +10 -0
- package/src/internal.ts +1 -0
- package/src/runtime/activation-admission.ts +78 -0
- package/src/runtime/actors/actor-context.ts +6 -6
- package/src/runtime/actors/actor-handoff.ts +31 -23
- package/src/runtime/actors/actor-local-native-join.ts +3 -42
- package/src/runtime/actors/actor-remote-joiner.ts +6 -25
- package/src/runtime/actors/actor-runtime-contracts.ts +4 -10
- package/src/runtime/actors/actor-source-transfer.ts +5 -18
- package/src/runtime/actors/deferred-join-completion.ts +40 -0
- package/src/runtime/actors/index.ts +22 -9
- package/src/runtime/admission.ts +5 -1
- package/src/runtime/backend/contracts/index.ts +2 -13
- package/src/runtime/backend/mesh-actor-session-node-adapter.ts +2 -10
- package/src/runtime/backend/node/node-backend-adapter-factory.ts +5 -25
- package/src/runtime/backend/node/node-backend-adapter-support.ts +9 -29
- package/src/runtime/backend/node/node-event-loop-poller.ts +14 -2
- package/src/runtime/backend/node/node-raw-binding-port.ts +17 -3
- package/src/runtime/backend/node/node-raw-mesh-backend.ts +65 -32
- package/src/runtime/backend/node/node-socket-backend-adapter.ts +2 -2
- package/src/runtime/backend/raw-binding-port.ts +13 -0
- package/src/runtime/channels/channel-clients.ts +0 -11
- package/src/runtime/channels/channel-outbound-operations.ts +3 -11
- package/src/runtime/channels/channel-runtime-manager.ts +4 -15
- package/src/runtime/channels/channel-socket-registry.ts +69 -71
- package/src/runtime/channels/channel-transports.ts +0 -3
- package/src/runtime/channels/fanout-location-runtime.ts +4 -16
- package/src/runtime/execution/index.ts +68 -30
- package/src/runtime/execution/serial-execution-queue.ts +52 -20
- package/src/runtime/foundation/listener-records.ts +21 -0
- package/src/runtime/foundation/raw-service-mesh-runtime.ts +66 -466
- package/src/runtime/foundation/service-authority-payload-codec.ts +10 -0
- package/src/runtime/foundation/service-maintenance-runtime.ts +30 -9
- package/src/runtime/foundation/service-relocation-coordinator.ts +13 -0
- package/src/runtime/foundation/service-relocation-object-owner.ts +18 -5
- package/src/runtime/foundation/service-session-binding-ingress-port.ts +6 -14
- package/src/runtime/foundation/service-stateful-runtime.ts +151 -89
- package/src/runtime/foundation/service-stateful-wire-codec.ts +203 -121
- package/src/runtime/foundation/service-topology-registry.ts +8 -48
- package/src/runtime/host/actor-transfer-runtime.ts +94 -166
- package/src/runtime/host/index.ts +119 -54
- package/src/runtime/host/remote-bound-session-relay.ts +4 -3
- package/src/runtime/host/route-mesh-runtime.ts +9 -5
- package/src/runtime/host/service-relocation-host-runtime.ts +495 -376
- package/src/runtime/host/spot-runtime-options-factory.ts +24 -13
- package/src/runtime/host/stateful-authority-route-runtime.ts +8 -4
- package/src/runtime/host/user-spot-creation-coordinator.ts +147 -142
- package/src/runtime/locations/in-memory-provider-location-store.ts +11 -7
- package/src/runtime/locations/lifecycle.ts +3 -2
- package/src/runtime/locations/resolvers.ts +19 -13
- package/src/runtime/locations/spot-location-claims.ts +5 -34
- package/src/runtime/protocol/service_wire_codec.generated.ts +9 -2
- package/src/runtime/protocol/service_wire_pilot_codec.generated.ts +4 -4
- package/src/runtime/spots/formal-remote-actor-admission-registry.ts +6 -6
- package/src/runtime/spots/formal-remote-actor-transfer-registry.ts +3 -3
- package/src/runtime/spots/index.ts +341 -295
- package/src/runtime/spots/spot-activation-registry.ts +41 -31
- package/src/runtime/spots/spot-activation-state.ts +4 -16
- package/src/runtime/spots/spot-activation.ts +102 -80
- package/src/runtime/spots/spot-actor-admission-coordinator.ts +2 -2
- package/src/runtime/spots/spot-actor-join-dispatch.ts +6 -7
- package/src/runtime/spots/spot-actor-lifecycle-drain.ts +20 -18
- package/src/runtime/spots/spot-actor-membership.ts +81 -17
- package/src/runtime/spots/spot-entry-activation.ts +0 -3
- package/src/runtime/spots/spot-manager-public.ts +8 -4
- package/src/runtime/spots/spot-native-actor-join-admission.ts +2 -2
- package/src/runtime/spots/spot-node-runtime-manager.ts +12 -18
- package/src/runtime/spots/spot-outbound.ts +4 -47
- package/src/runtime/spots/spot-routed-actor-admission.ts +20 -0
- package/src/runtime/spots/spot-routed-frame-dispatch.ts +6 -76
- package/src/runtime/spots/spot-runtime-ports.ts +6 -17
- package/src/runtime/spots/spot-serial-executor.ts +9 -1
- package/src/runtime/spots/spot-serial-turn-executor.ts +10 -4
- package/src/runtime/streams/actor-session-binding-registry.ts +20 -308
- package/src/runtime/streams/actor-session-binding-runtime-owner.ts +2 -12
- package/src/runtime/streams/bound-session-service.ts +2 -36
- package/src/runtime/streams/index.ts +29 -27
- package/src/runtime/streams/session-serial-executor.ts +2 -2
- package/dist/runtime/actors/deferred-join-accepted-journal.d.ts +0 -47
- package/dist/runtime/actors/deferred-join-accepted-journal.js +0 -992
- package/src/runtime/actors/deferred-join-accepted-journal.ts +0 -1346
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { ZLinkListenerRecords } from '../foundation/listener-records';
|
|
1
2
|
import type { ZLinkLocationOptionOverrides } from '../../contracts/Locations/Options';
|
|
2
3
|
import type { RoutingId } from '../../contracts';
|
|
3
4
|
import type { ZLinkProviderResolver } from '../../contracts/Common/ZLinkProviderResolver';
|
|
@@ -27,11 +28,6 @@ export declare class ZLinkChannelRuntimeManager {
|
|
|
27
28
|
fanoutTopology(channelName: string): {
|
|
28
29
|
descriptors: readonly import("../foundation").FanoutPublisherDescriptor[];
|
|
29
30
|
};
|
|
30
|
-
getFanoutListenerStatus(channelName: string): {
|
|
31
|
-
channelName: string;
|
|
32
|
-
endpoint: string;
|
|
33
|
-
observedAt: Date;
|
|
34
|
-
};
|
|
35
31
|
observeClientServerTopology(channelName: string, changed: () => void): () => void;
|
|
36
32
|
observeFanoutTopology(channelName: string, changed: () => void): () => void;
|
|
37
33
|
configureLocationAutoConnect(runtime: ZLinkLocationRuntime, stores: ZLinkLocationRuntimeStores, options: ZLinkLocationOptionOverrides, events?: ZLinkLocationEventSink): void;
|
|
@@ -65,6 +61,7 @@ export declare class ZLinkChannelRuntimeManager {
|
|
|
65
61
|
dispose(signal?: AbortSignal): Promise<void>;
|
|
66
62
|
}
|
|
67
63
|
export interface ZLinkChannelRuntimeManagerOptions {
|
|
64
|
+
readonly listenerRecords?: ZLinkListenerRecords;
|
|
68
65
|
readonly internalRouteSendHandlers?: ReadonlyMap<string, ZLinkRouteRuntimeSendHandler>;
|
|
69
66
|
readonly internalRouteRequestHandlers?: ReadonlyMap<string, ZLinkRouteRuntimeRequestHandler>;
|
|
70
67
|
readonly monitoringAdapter?: ZLinkMonitoringBackendAdapter;
|
|
@@ -18,7 +18,7 @@ class ZLinkChannelRuntimeManager {
|
|
|
18
18
|
this.registration = registration;
|
|
19
19
|
const applicationJobQueue = options.applicationJobQueue ??
|
|
20
20
|
new application_job_queue_1.ApplicationJobQueue((0, application_job_queue_1.resolveApplicationJobQueueConfiguration)());
|
|
21
|
-
this.sockets = new channel_socket_registry_1.ZLinkChannelSocketRegistry(registration, adapter, context, options.monitoringAdapter, options.oneWayFailureSink, applicationJobQueue);
|
|
21
|
+
this.sockets = new channel_socket_registry_1.ZLinkChannelSocketRegistry(registration, adapter, context, options.monitoringAdapter, options.oneWayFailureSink, applicationJobQueue, options.listenerRecords);
|
|
22
22
|
const codecs = {
|
|
23
23
|
serializers: registration.messageSerializers
|
|
24
24
|
};
|
|
@@ -65,17 +65,6 @@ class ZLinkChannelRuntimeManager {
|
|
|
65
65
|
fanoutTopology(channelName) {
|
|
66
66
|
return { descriptors: this.sockets.fanoutActiveTargets(channelName) };
|
|
67
67
|
}
|
|
68
|
-
getFanoutListenerStatus(channelName) {
|
|
69
|
-
const endpoint = this.sockets.fanoutPublisherEndpoint(channelName);
|
|
70
|
-
if (endpoint === undefined) {
|
|
71
|
-
throw new configuration_1.ZLinkConfigurationException(`Fanout publisher '${channelName}' has not reported a bound listener.`);
|
|
72
|
-
}
|
|
73
|
-
return {
|
|
74
|
-
channelName,
|
|
75
|
-
endpoint,
|
|
76
|
-
observedAt: new Date()
|
|
77
|
-
};
|
|
78
|
-
}
|
|
79
68
|
observeClientServerTopology(channelName, changed) {
|
|
80
69
|
const monitor = this.sockets.clientServerMonitoringSource(channelName);
|
|
81
70
|
monitor.onEvent(changed);
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { ZLinkListenerRecords } from '../foundation/listener-records';
|
|
1
2
|
import { type ZLinkClientServerServerDescriptor, type ZLinkFanoutPublisherDescriptor } from '../../contracts';
|
|
2
3
|
import { type ZLinkFrameworkRegistration } from '../configuration';
|
|
3
4
|
import type { ZLinkBackendContext, ZLinkBackendDealerSocket, ZLinkBackendPublisherSocket, ZLinkBackendRouterSocket, ZLinkBackendSocketMonitor, ZLinkBackendSubscriberSocket, ZLinkChannelBackendAdapter, ZLinkMonitoringBackendAdapter } from '../backend/contracts';
|
|
@@ -48,11 +49,14 @@ export declare class ZLinkChannelSocketRegistry {
|
|
|
48
49
|
private readonly clientServerMonitorHandlers;
|
|
49
50
|
private readonly fanoutMonitorHandlers;
|
|
50
51
|
private readonly fanoutTopologyHandlers;
|
|
51
|
-
|
|
52
|
+
private readonly listenerRecords;
|
|
53
|
+
constructor(registration: ZLinkFrameworkRegistration, adapter: ZLinkChannelBackendAdapter, context: ZLinkBackendContext, monitoringAdapter?: ZLinkMonitoringBackendAdapter | undefined, oneWayFailureSink?: ((error: unknown) => void) | undefined, applicationJobQueue?: ApplicationJobQueue | undefined, listenerRecords?: ZLinkListenerRecords);
|
|
52
54
|
dispose(): Promise<void>;
|
|
53
55
|
clientDealer(channelName: string): ZLinkBackendDealerSocket;
|
|
54
56
|
channelRouter(channelName: string): ZLinkBackendRouterSocket;
|
|
55
57
|
clientServerServerIdentity(channelName: string): ZLinkClientServerServerSocketIdentity;
|
|
58
|
+
fanoutPublisherEndpoint(channelName: string): string | undefined;
|
|
59
|
+
private recordListener;
|
|
56
60
|
clientServerServerSocket(channelName: string): ZLinkBackendRouterSocket;
|
|
57
61
|
clientServerServerWeight(channelName: string): number;
|
|
58
62
|
setClientServerServerWeight(channelName: string, weight: number): void;
|
|
@@ -90,7 +94,6 @@ export declare class ZLinkChannelSocketRegistry {
|
|
|
90
94
|
startLocalClientServerConnections(): void;
|
|
91
95
|
clientServerMonitoringSource(channelName: string): ZLinkBackendSocketMonitor;
|
|
92
96
|
clientServerActiveTargets(channelName: string): readonly Pick<ClientServerDiscoveryDescriptor, 'serverRoutingId' | 'weight' | 'state'>[];
|
|
93
|
-
hasKnownClientServerTargets(channelName: string): boolean;
|
|
94
97
|
fanoutActiveTargets(channelName: string): readonly import("../foundation/service-discovery-registry").FanoutPublisherDescriptor[];
|
|
95
98
|
admitFanoutPublisher(descriptor: ZLinkFanoutPublisherDescriptor, connectionId: string): boolean;
|
|
96
99
|
removeFanoutPublisher(descriptor: ZLinkFanoutPublisherDescriptor, connectionId: string): boolean;
|
|
@@ -130,7 +133,18 @@ export declare class ZLinkChannelSocketRegistry {
|
|
|
130
133
|
private openConfiguredClientServerConnection;
|
|
131
134
|
private admitConfiguredClientServerConnection;
|
|
132
135
|
private drainClientServerControl;
|
|
133
|
-
|
|
136
|
+
/**
|
|
137
|
+
* Ends the current logical admission of this connection: later replies of
|
|
138
|
+
* the fenced attempt no longer apply and its ready target is withdrawn.
|
|
139
|
+
*/
|
|
140
|
+
private endClientServerAdmission;
|
|
141
|
+
/**
|
|
142
|
+
* A peer deadline or an invalid pushed control ends only the current logical
|
|
143
|
+
* admission. The connect intent stays with Core, which owns the endpoint
|
|
144
|
+
* reconnect (transport liveness §6); the service handshake starts again on
|
|
145
|
+
* the existing admission path.
|
|
146
|
+
*/
|
|
147
|
+
private restartClientServerAdmission;
|
|
134
148
|
private applyClientServerDescriptorUpdate;
|
|
135
149
|
private ensureClientServerLivenessTimer;
|
|
136
150
|
private drainSocketMonitors;
|
|
@@ -143,7 +157,6 @@ export declare class ZLinkChannelSocketRegistry {
|
|
|
143
157
|
private pushClientServerDescriptorUpdate;
|
|
144
158
|
private allocateClientServerProbeId;
|
|
145
159
|
publisher(channelName: string): ZLinkBackendPublisherSocket;
|
|
146
|
-
fanoutPublisherEndpoint(channelName: string): string | undefined;
|
|
147
160
|
routeRouter(routerChannelId: string): ZLinkBackendRouterSocket;
|
|
148
161
|
routeMeshSocket(routerChannelId: string): ZLinkBackendRouterSocket;
|
|
149
162
|
routeMeshWeight(routerChannelId: string): number;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.ZLinkChannelSocketRegistry = void 0;
|
|
4
|
+
const listener_records_1 = require("../foundation/listener-records");
|
|
4
5
|
const contracts_1 = require("../../contracts");
|
|
5
6
|
const internal_event_contracts_1 = require("../diagnostics/internal-event-contracts");
|
|
6
7
|
const configuration_1 = require("../configuration");
|
|
@@ -51,13 +52,15 @@ class ZLinkChannelSocketRegistry {
|
|
|
51
52
|
clientServerMonitorHandlers = new Map();
|
|
52
53
|
fanoutMonitorHandlers = new Map();
|
|
53
54
|
fanoutTopologyHandlers = new Map();
|
|
54
|
-
|
|
55
|
+
listenerRecords;
|
|
56
|
+
constructor(registration, adapter, context, monitoringAdapter, oneWayFailureSink, applicationJobQueue, listenerRecords) {
|
|
55
57
|
this.registration = registration;
|
|
56
58
|
this.adapter = adapter;
|
|
57
59
|
this.context = context;
|
|
58
60
|
this.monitoringAdapter = monitoringAdapter;
|
|
59
61
|
this.oneWayFailureSink = oneWayFailureSink;
|
|
60
62
|
this.applicationJobQueue = applicationJobQueue;
|
|
63
|
+
this.listenerRecords = listenerRecords ?? new listener_records_1.ZLinkListenerRecords();
|
|
61
64
|
}
|
|
62
65
|
async dispose() {
|
|
63
66
|
const clientServerConnections = [...new Set(this.clientServerConnections.values())];
|
|
@@ -177,14 +180,15 @@ class ZLinkChannelSocketRegistry {
|
|
|
177
180
|
});
|
|
178
181
|
}
|
|
179
182
|
this.channelRouters.set(channelName, router);
|
|
183
|
+
const endpoint = advertisedEndpoint(router.lastEndpoint ?? channel.server.bind, channel.server.advertiseHost);
|
|
184
|
+
this.recordListener('clientServer', channelName, endpoint);
|
|
180
185
|
if (!this.clientServerServerDescriptors.has(channelName)) {
|
|
181
|
-
const boundEndpoint = router.lastEndpoint ?? channel.server.bind;
|
|
182
186
|
this.clientServerServerDescriptors.set(channelName, {
|
|
183
187
|
channelName,
|
|
184
188
|
serverRid: identity.serverRid,
|
|
185
189
|
lifecycleGeneration: identity.lifecycleGeneration,
|
|
186
190
|
descriptorRevision: 1n,
|
|
187
|
-
endpoint
|
|
191
|
+
endpoint,
|
|
188
192
|
weight: publicWeight,
|
|
189
193
|
state: contracts_1.ZLinkFrameworkRuntimeState.Serving,
|
|
190
194
|
securityIdentity: 'default',
|
|
@@ -196,20 +200,19 @@ class ZLinkChannelSocketRegistry {
|
|
|
196
200
|
return router;
|
|
197
201
|
}
|
|
198
202
|
clientServerServerIdentity(channelName) {
|
|
199
|
-
|
|
203
|
+
this.channelRouter(channelName);
|
|
200
204
|
const identity = this.clientServerIdentities.get(channelName);
|
|
201
|
-
const
|
|
202
|
-
if (identity === undefined ||
|
|
205
|
+
const endpoint = this.listenerRecords.endpoint('clientServer', channelName);
|
|
206
|
+
if (identity === undefined || endpoint === undefined) {
|
|
203
207
|
throw new configuration_1.ZLinkConfigurationException(`Channel server '${channelName}' is not registered.`);
|
|
204
208
|
}
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
};
|
|
209
|
+
return { ...identity, endpoint };
|
|
210
|
+
}
|
|
211
|
+
fanoutPublisherEndpoint(channelName) {
|
|
212
|
+
return this.listenerRecords.endpoint('fanout', channelName);
|
|
213
|
+
}
|
|
214
|
+
recordListener(kind, name, endpoint) {
|
|
215
|
+
this.listenerRecords.record(kind, name, endpoint);
|
|
213
216
|
}
|
|
214
217
|
clientServerServerSocket(channelName) {
|
|
215
218
|
return this.channelRouter(channelName);
|
|
@@ -275,8 +278,7 @@ class ZLinkChannelSocketRegistry {
|
|
|
275
278
|
monitor,
|
|
276
279
|
aliases: new Set([connectionId]),
|
|
277
280
|
callbacksByAlias: new Map([[connectionId, callbacks]]),
|
|
278
|
-
physicalConnectionId: Symbol(connectionId)
|
|
279
|
-
terminationRequested: false
|
|
281
|
+
physicalConnectionId: Symbol(connectionId)
|
|
280
282
|
};
|
|
281
283
|
this.clientServerConnections.set(connectionId, connection);
|
|
282
284
|
this.ensureClientServerLivenessTimer();
|
|
@@ -290,7 +292,7 @@ class ZLinkChannelSocketRegistry {
|
|
|
290
292
|
const routingId = event.routingId === undefined ? undefined : String(event.routingId);
|
|
291
293
|
if (event.nativeEvent === internal_event_contracts_1.ZLinkSocketNativeEventType.ConnectionReady) {
|
|
292
294
|
// This single-endpoint DEALER also receives its disconnected ready-count snapshot.
|
|
293
|
-
if (event.value === 0n
|
|
295
|
+
if (event.value === 0n)
|
|
294
296
|
return;
|
|
295
297
|
connection.physicalConnectionId = Symbol(connectionId);
|
|
296
298
|
connection.admissionAttempt = undefined;
|
|
@@ -304,24 +306,9 @@ class ZLinkChannelSocketRegistry {
|
|
|
304
306
|
event.nativeEvent === internal_event_contracts_1.ZLinkSocketNativeEventType.HandshakeFailedNoDetail ||
|
|
305
307
|
event.nativeEvent === internal_event_contracts_1.ZLinkSocketNativeEventType.HandshakeFailedProtocol ||
|
|
306
308
|
event.nativeEvent === internal_event_contracts_1.ZLinkSocketNativeEventType.HandshakeFailedAuth) {
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
event.nativeEvent !== internal_event_contracts_1.ZLinkSocketNativeEventType.Closed)))
|
|
311
|
-
return;
|
|
312
|
-
connection.physicalConnectionId = Symbol(connectionId);
|
|
313
|
-
connection.admissionAttempt = undefined;
|
|
314
|
-
if (connection.readyConnectionId !== undefined) {
|
|
315
|
-
this.removeReadyConnection(connection.readyConnectionId);
|
|
316
|
-
}
|
|
317
|
-
for (const currentCallbacks of [...connection.callbacksByAlias.values()]) {
|
|
318
|
-
currentCallbacks.onTerminated(routingId, event.remoteAddr);
|
|
319
|
-
}
|
|
320
|
-
if (connection.terminationRequested) {
|
|
321
|
-
connection.terminationRequested = false;
|
|
322
|
-
// Explicit disconnect removes intent; restore it once after this endpoint closes.
|
|
323
|
-
connection.dealer.connect(connection.endpoint);
|
|
324
|
-
}
|
|
309
|
+
// Core owns the endpoint reconnect (transport liveness §6); the
|
|
310
|
+
// connect intent stays and the next READY starts a new admission.
|
|
311
|
+
this.endClientServerAdmission(connectionId, connection, routingId, event.remoteAddr);
|
|
325
312
|
}
|
|
326
313
|
});
|
|
327
314
|
dealer.connect(endpoint);
|
|
@@ -588,9 +575,6 @@ class ZLinkChannelSocketRegistry {
|
|
|
588
575
|
? 1
|
|
589
576
|
: 0);
|
|
590
577
|
}
|
|
591
|
-
hasKnownClientServerTargets(channelName) {
|
|
592
|
-
return this.clientServerDiscovery.clientServerDescriptors(channelName).length > 0;
|
|
593
|
-
}
|
|
594
578
|
fanoutActiveTargets(channelName) {
|
|
595
579
|
return this.clientServerDiscovery.fanoutEndpoints(channelName);
|
|
596
580
|
}
|
|
@@ -689,7 +673,7 @@ class ZLinkChannelSocketRegistry {
|
|
|
689
673
|
if (connection.deadlineAt === undefined)
|
|
690
674
|
continue;
|
|
691
675
|
if (nowMs >= connection.deadlineAt) {
|
|
692
|
-
this.
|
|
676
|
+
this.restartClientServerAdmission(connectionId, connection);
|
|
693
677
|
continue;
|
|
694
678
|
}
|
|
695
679
|
if (connection.nextProbeAt === undefined || nowMs < connection.nextProbeAt)
|
|
@@ -993,8 +977,6 @@ class ZLinkChannelSocketRegistry {
|
|
|
993
977
|
}
|
|
994
978
|
}
|
|
995
979
|
drainClientServerControl(connectionId, connection) {
|
|
996
|
-
if (connection.terminationRequested)
|
|
997
|
-
return;
|
|
998
980
|
for (;;) {
|
|
999
981
|
if (!connection.readablePoller.wait(0))
|
|
1000
982
|
return;
|
|
@@ -1025,7 +1007,7 @@ class ZLinkChannelSocketRegistry {
|
|
|
1025
1007
|
this.applyClientServerDescriptorUpdate(connectionId, connection, record.admission);
|
|
1026
1008
|
}
|
|
1027
1009
|
catch (error) {
|
|
1028
|
-
this.
|
|
1010
|
+
this.restartClientServerAdmission(connectionId, connection);
|
|
1029
1011
|
this.oneWayFailureSink?.(error);
|
|
1030
1012
|
return;
|
|
1031
1013
|
}
|
|
@@ -1034,18 +1016,30 @@ class ZLinkChannelSocketRegistry {
|
|
|
1034
1016
|
}
|
|
1035
1017
|
}
|
|
1036
1018
|
}
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1019
|
+
/**
|
|
1020
|
+
* Ends the current logical admission of this connection: later replies of
|
|
1021
|
+
* the fenced attempt no longer apply and its ready target is withdrawn.
|
|
1022
|
+
*/
|
|
1023
|
+
endClientServerAdmission(connectionId, connection, routingId, endpoint) {
|
|
1041
1024
|
connection.physicalConnectionId = Symbol(connectionId);
|
|
1042
1025
|
connection.admissionAttempt = undefined;
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
connection.dealer.disconnect(connection.endpoint);
|
|
1026
|
+
if (connection.readyConnectionId !== undefined) {
|
|
1027
|
+
this.removeReadyConnection(connection.readyConnectionId);
|
|
1046
1028
|
}
|
|
1047
|
-
|
|
1048
|
-
|
|
1029
|
+
for (const callbacks of [...connection.callbacksByAlias.values()]) {
|
|
1030
|
+
callbacks.onTerminated(routingId, endpoint);
|
|
1031
|
+
}
|
|
1032
|
+
}
|
|
1033
|
+
/**
|
|
1034
|
+
* A peer deadline or an invalid pushed control ends only the current logical
|
|
1035
|
+
* admission. The connect intent stays with Core, which owns the endpoint
|
|
1036
|
+
* reconnect (transport liveness §6); the service handshake starts again on
|
|
1037
|
+
* the existing admission path.
|
|
1038
|
+
*/
|
|
1039
|
+
restartClientServerAdmission(connectionId, connection) {
|
|
1040
|
+
this.endClientServerAdmission(connectionId, connection, undefined, connection.endpoint);
|
|
1041
|
+
for (const callbacks of [...connection.callbacksByAlias.values()]) {
|
|
1042
|
+
callbacks.onTransportReady('', connection.endpoint);
|
|
1049
1043
|
}
|
|
1050
1044
|
}
|
|
1051
1045
|
applyClientServerDescriptorUpdate(connectionId, connection, admission) {
|
|
@@ -1223,21 +1217,14 @@ class ZLinkChannelSocketRegistry {
|
|
|
1223
1217
|
applyFanoutPublisherSocketOptions(publisher, channel);
|
|
1224
1218
|
publisher.bind(channel.publisher.bind);
|
|
1225
1219
|
this.publishers.set(channelName, publisher);
|
|
1220
|
+
const endpoint = (0, configuration_1.buildAdvertisedEndpoint)(publisher.lastEndpoint ?? channel.publisher.bind, channel.publisher.advertiseHost);
|
|
1221
|
+
if (endpoint !== undefined && endpoint.length > 0) {
|
|
1222
|
+
this.recordListener('fanout', channelName, endpoint);
|
|
1223
|
+
}
|
|
1226
1224
|
this.fanoutPublisherNextBeacon.set(channelName, performance.now() + CLIENT_SERVER_PROBE_INTERVAL_MS);
|
|
1227
1225
|
this.ensureClientServerLivenessTimer();
|
|
1228
1226
|
return publisher;
|
|
1229
1227
|
}
|
|
1230
|
-
fanoutPublisherEndpoint(channelName) {
|
|
1231
|
-
const channel = this.registration.channels.get(channelName);
|
|
1232
|
-
const publisher = this.publishers.get(channelName);
|
|
1233
|
-
const boundEndpoint = publisher?.lastEndpoint;
|
|
1234
|
-
if (channel?.publisher === undefined ||
|
|
1235
|
-
boundEndpoint === undefined ||
|
|
1236
|
-
boundEndpoint.length === 0) {
|
|
1237
|
-
return undefined;
|
|
1238
|
-
}
|
|
1239
|
-
return advertisedEndpoint(boundEndpoint, channel.publisher.advertiseHost);
|
|
1240
|
-
}
|
|
1241
1228
|
routeRouter(routerChannelId) {
|
|
1242
1229
|
const existing = this.routeRouters.get(routerChannelId);
|
|
1243
1230
|
if (existing !== undefined) {
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { type ZLinkBackendMessageLike as MessageLike } from '../backend/runtime-values';
|
|
2
2
|
import type { ZLinkBackendMeshNode, ZLinkBackendSpot } from '../backend/contracts';
|
|
3
3
|
import { ZLinkFrameworkException } from '../../contracts';
|
|
4
|
-
import type { ZLinkFanoutListenerStatus } from '../../contracts';
|
|
5
4
|
import type { Message } from '../../contracts/Common/Message';
|
|
6
5
|
import { type ZLinkSubmitResult } from '../messaging/submission-result';
|
|
7
6
|
import type { ZLinkSpotRouteTarget } from '../spots/spot-routing-internal';
|
|
@@ -13,7 +12,6 @@ export interface ZLinkChannelClientTransport {
|
|
|
13
12
|
request<TReply>(channelName: string, packetName: string | undefined, request: unknown, timeoutMs: number | undefined, signal?: AbortSignal, metadata?: ReadonlyMap<string, string>): Promise<TReply>;
|
|
14
13
|
tryPublish?(channelName: string, topic: string, packetName: string | undefined, event: unknown, metadata?: ReadonlyMap<string, string>): ZLinkSubmitResult;
|
|
15
14
|
publish(channelName: string, topic: string, packetName: string | undefined, event: unknown, signal?: AbortSignal, metadata?: ReadonlyMap<string, string>): ZLinkSubmitResult | Promise<ZLinkSubmitResult>;
|
|
16
|
-
getFanoutListenerStatus?(channelName: string): ZLinkFanoutListenerStatus;
|
|
17
15
|
}
|
|
18
16
|
export type ZLinkChannelClientTransportSource = ZLinkChannelClientTransport | (() => ZLinkChannelClientTransport | undefined);
|
|
19
17
|
export interface ZLinkSpotPublisherClientTransport {
|
|
@@ -43,7 +41,6 @@ interface ZLinkChannelTransportRuntime {
|
|
|
43
41
|
request<TReply>(channelName: string, packetName: string | undefined, request: unknown, timeoutMs: number | undefined, signal?: AbortSignal, metadata?: ReadonlyMap<string, string>): Promise<TReply>;
|
|
44
42
|
tryPublish(channelName: string, topic: string, packetName: string | undefined, event: unknown, metadata?: ReadonlyMap<string, string>): ZLinkSubmitResult;
|
|
45
43
|
publish(channelName: string, topic: string, packetName: string | undefined, event: unknown, signal?: AbortSignal, metadata?: ReadonlyMap<string, string>): Promise<ZLinkSubmitResult>;
|
|
46
|
-
getFanoutListenerStatus(channelName: string): ZLinkFanoutListenerStatus;
|
|
47
44
|
canRouteChannel(routerChannelId: string): boolean;
|
|
48
45
|
canRoutePacketChannel(routerChannelId: string): boolean;
|
|
49
46
|
routeSubmit(routerChannelId: string, targetNodeRid: string, packetName: string | undefined, message: unknown, signal?: AbortSignal, metadata?: ReadonlyMap<string, string>): Promise<ZLinkSubmitResult>;
|
|
@@ -101,8 +101,9 @@ class ZLinkFanoutLocationRuntime {
|
|
|
101
101
|
for (const [channelName, channel] of this.registration.channels) {
|
|
102
102
|
if (channel.publisher === undefined)
|
|
103
103
|
continue;
|
|
104
|
-
|
|
105
|
-
|
|
104
|
+
// Opening the publisher binds it and fixes its advertised endpoint.
|
|
105
|
+
this.sockets.publisher(channelName);
|
|
106
|
+
const endpoint = this.sockets.fanoutPublisherEndpoint(channelName) ?? '';
|
|
106
107
|
if (endpoint.length === 0) {
|
|
107
108
|
throw new configuration_1.ZLinkConfigurationException(`Fanout publisher '${channelName}' did not report a bound endpoint.`);
|
|
108
109
|
}
|
|
@@ -316,13 +317,6 @@ class ZLinkFanoutLocationRuntime {
|
|
|
316
317
|
}
|
|
317
318
|
}
|
|
318
319
|
exports.ZLinkFanoutLocationRuntime = ZLinkFanoutLocationRuntime;
|
|
319
|
-
function advertisedEndpoint(boundEndpoint, advertiseHost) {
|
|
320
|
-
const result = (0, configuration_1.buildAdvertisedEndpoint)(boundEndpoint, advertiseHost);
|
|
321
|
-
if (result === undefined) {
|
|
322
|
-
throw new configuration_1.ZLinkConfigurationException(`Fanout publisher bound endpoint '${boundEndpoint}' cannot be advertised.`);
|
|
323
|
-
}
|
|
324
|
-
return result;
|
|
325
|
-
}
|
|
326
320
|
function fanoutConnectionId(descriptor) {
|
|
327
321
|
return (`${descriptor.channelName}\0${String(descriptor.publisherRid)}\0` +
|
|
328
322
|
descriptor.lifecycleGeneration.toString());
|
|
@@ -23,11 +23,14 @@ export declare class ZLinkSpotSerialTurn {
|
|
|
23
23
|
private owner;
|
|
24
24
|
private frameworkOperationsBlocked;
|
|
25
25
|
constructor(postResume: (turn: ZLinkSpotSerialTurn, resume: () => void, reject: (reason: unknown) => void) => boolean, executionClaim: ZLinkExecutionBarrierClaim | undefined, yieldAllowed: boolean);
|
|
26
|
-
bindExecutionClaim(claim: ZLinkExecutionBarrierClaim | undefined): void;
|
|
27
26
|
get isSuspended(): boolean;
|
|
27
|
+
/** False when a seal that does not drain yielded turns won before this resume. */
|
|
28
|
+
resumeExecutionClaim(): boolean;
|
|
28
29
|
releaseBoundExecutionClaim(): void;
|
|
29
30
|
get suspended(): Promise<void>;
|
|
30
31
|
bindOwner(owner: Promise<unknown>): void;
|
|
32
|
+
/** Settles when the whole turn ends by any path, including yielded continuations. */
|
|
33
|
+
get completion(): Promise<void>;
|
|
31
34
|
blockFrameworkOperations(): void;
|
|
32
35
|
ensureFrameworkOperationAllowed(): void;
|
|
33
36
|
resetSuspension(): void;
|
|
@@ -51,9 +54,18 @@ export declare function captureZLinkExecutionTurn(): ZLinkCapturedExecutionTurn
|
|
|
51
54
|
export declare function isCurrentZLinkSpotSerialTurn(executor: ZLinkSpotSerialTurnExecutorLike): boolean;
|
|
52
55
|
export interface ZLinkExecutionBarrierSeal {
|
|
53
56
|
readonly generation: bigint;
|
|
57
|
+
/**
|
|
58
|
+
* A Spot Close seal waits for yielded turns accepted before it and lets them
|
|
59
|
+
* resume (Spot address messaging §7 step 2); a relocation seal does not, and
|
|
60
|
+
* their continuation fails (execution gate §4).
|
|
61
|
+
*/
|
|
62
|
+
readonly drainsYieldedTurns: boolean;
|
|
54
63
|
}
|
|
55
64
|
export interface ZLinkExecutionBarrierClaim {
|
|
56
65
|
release(): void;
|
|
66
|
+
/** The turn yielded; it no longer runs until resume() admits it again. */
|
|
67
|
+
suspend(): void;
|
|
68
|
+
resume(): boolean;
|
|
57
69
|
}
|
|
58
70
|
/**
|
|
59
71
|
* Seals application-lane admission and waits for every active Promise turn to
|
|
@@ -63,22 +75,20 @@ export interface ZLinkExecutionBarrierClaim {
|
|
|
63
75
|
export declare class ZLinkExecutionBarrier {
|
|
64
76
|
private generation;
|
|
65
77
|
private activeClaims;
|
|
78
|
+
private suspendedClaims;
|
|
66
79
|
private currentSeal;
|
|
67
80
|
private readonly admissionWaiters;
|
|
68
81
|
private readonly quiescenceWaiters;
|
|
69
82
|
private committed;
|
|
83
|
+
get isSealed(): boolean;
|
|
70
84
|
enter(): Promise<ZLinkExecutionBarrierClaim>;
|
|
71
|
-
|
|
72
|
-
* Re-enters a previously yielded application turn only while admission is
|
|
73
|
-
* open. A continuation must fail instead of waiting behind a relocation
|
|
74
|
-
* seal that already won the turn-boundary race.
|
|
75
|
-
*/
|
|
76
|
-
tryEnter(): ZLinkExecutionBarrierClaim | undefined;
|
|
77
|
-
seal(): ZLinkExecutionBarrierSeal;
|
|
85
|
+
seal(drainsYieldedTurns?: boolean): ZLinkExecutionBarrierSeal;
|
|
78
86
|
waitForQuiescence(seal: ZLinkExecutionBarrierSeal, signal?: AbortSignal): Promise<void>;
|
|
79
87
|
abort(seal: ZLinkExecutionBarrierSeal): boolean;
|
|
80
88
|
commit(seal: ZLinkExecutionBarrierSeal): boolean;
|
|
81
89
|
isCurrent(seal: ZLinkExecutionBarrierSeal): boolean;
|
|
90
|
+
private isQuiescent;
|
|
91
|
+
private notifyQuiescence;
|
|
82
92
|
private createClaim;
|
|
83
93
|
private requireCurrent;
|
|
84
94
|
}
|
|
@@ -43,15 +43,13 @@ class ZLinkSpotSerialTurn {
|
|
|
43
43
|
this.executionClaim = executionClaim;
|
|
44
44
|
this.yieldAllowed = yieldAllowed;
|
|
45
45
|
}
|
|
46
|
-
bindExecutionClaim(claim) {
|
|
47
|
-
if (this.executionClaim !== undefined) {
|
|
48
|
-
throw new Error('ZLink Spot serial turn already owns an execution claim.');
|
|
49
|
-
}
|
|
50
|
-
this.executionClaim = claim;
|
|
51
|
-
}
|
|
52
46
|
get isSuspended() {
|
|
53
47
|
return this.suspendSignaled;
|
|
54
48
|
}
|
|
49
|
+
/** False when a seal that does not drain yielded turns won before this resume. */
|
|
50
|
+
resumeExecutionClaim() {
|
|
51
|
+
return this.executionClaim?.resume() ?? true;
|
|
52
|
+
}
|
|
55
53
|
releaseBoundExecutionClaim() {
|
|
56
54
|
this.executionClaim?.release();
|
|
57
55
|
this.executionClaim = undefined;
|
|
@@ -68,6 +66,10 @@ class ZLinkSpotSerialTurn {
|
|
|
68
66
|
bindOwner(owner) {
|
|
69
67
|
this.owner = owner;
|
|
70
68
|
}
|
|
69
|
+
/** Settles when the whole turn ends by any path, including yielded continuations. */
|
|
70
|
+
get completion() {
|
|
71
|
+
return (this.owner ?? Promise.resolve()).then(() => undefined, () => undefined);
|
|
72
|
+
}
|
|
71
73
|
blockFrameworkOperations() {
|
|
72
74
|
this.frameworkOperationsBlocked = true;
|
|
73
75
|
}
|
|
@@ -109,7 +111,7 @@ class ZLinkSpotSerialTurn {
|
|
|
109
111
|
return;
|
|
110
112
|
}
|
|
111
113
|
this.suspendSignaled = true;
|
|
112
|
-
this.
|
|
114
|
+
this.executionClaim?.suspend();
|
|
113
115
|
this.suspendedResolve?.();
|
|
114
116
|
}
|
|
115
117
|
awaitResumePermit() {
|
|
@@ -175,10 +177,14 @@ function isCurrentZLinkSpotSerialTurn(executor) {
|
|
|
175
177
|
class ZLinkExecutionBarrier {
|
|
176
178
|
generation = 0n;
|
|
177
179
|
activeClaims = 0;
|
|
180
|
+
suspendedClaims = 0;
|
|
178
181
|
currentSeal;
|
|
179
182
|
admissionWaiters = [];
|
|
180
183
|
quiescenceWaiters = new Set();
|
|
181
184
|
committed = false;
|
|
185
|
+
get isSealed() {
|
|
186
|
+
return this.currentSeal !== undefined || this.committed;
|
|
187
|
+
}
|
|
182
188
|
async enter() {
|
|
183
189
|
if (this.committed) {
|
|
184
190
|
throw (0, framework_errors_internal_1.createInternalFrameworkException)(framework_errors_internal_1.ZLinkFrameworkInternalErrorKind.SpotMoving, 'ZLink execution barrier is committed.');
|
|
@@ -190,36 +196,28 @@ class ZLinkExecutionBarrier {
|
|
|
190
196
|
}
|
|
191
197
|
return this.createClaim();
|
|
192
198
|
}
|
|
193
|
-
|
|
194
|
-
* Re-enters a previously yielded application turn only while admission is
|
|
195
|
-
* open. A continuation must fail instead of waiting behind a relocation
|
|
196
|
-
* seal that already won the turn-boundary race.
|
|
197
|
-
*/
|
|
198
|
-
tryEnter() {
|
|
199
|
-
if (this.committed || this.currentSeal !== undefined) {
|
|
200
|
-
return undefined;
|
|
201
|
-
}
|
|
202
|
-
return this.createClaim();
|
|
203
|
-
}
|
|
204
|
-
seal() {
|
|
199
|
+
seal(drainsYieldedTurns = false) {
|
|
205
200
|
if (this.committed) {
|
|
206
201
|
throw (0, framework_errors_internal_1.createInternalFrameworkException)(framework_errors_internal_1.ZLinkFrameworkInternalErrorKind.SpotMoving, 'ZLink execution barrier is committed.');
|
|
207
202
|
}
|
|
208
203
|
if (this.currentSeal !== undefined) {
|
|
209
204
|
throw new Error('ZLink execution barrier is already sealed.');
|
|
210
205
|
}
|
|
211
|
-
const seal = Object.freeze({ generation: ++this.generation });
|
|
206
|
+
const seal = Object.freeze({ generation: ++this.generation, drainsYieldedTurns });
|
|
212
207
|
this.currentSeal = seal;
|
|
213
208
|
return seal;
|
|
214
209
|
}
|
|
215
210
|
async waitForQuiescence(seal, signal) {
|
|
216
211
|
this.requireCurrent(seal);
|
|
217
|
-
if (this.
|
|
212
|
+
if (this.isQuiescent(seal))
|
|
218
213
|
return;
|
|
219
214
|
if (signal?.aborted === true)
|
|
220
215
|
throw signal.reason;
|
|
221
216
|
await new Promise((resolve, reject) => {
|
|
222
217
|
const complete = () => {
|
|
218
|
+
if (!this.isQuiescent(seal))
|
|
219
|
+
return;
|
|
220
|
+
this.quiescenceWaiters.delete(complete);
|
|
223
221
|
signal?.removeEventListener('abort', abort);
|
|
224
222
|
resolve();
|
|
225
223
|
};
|
|
@@ -255,20 +253,48 @@ class ZLinkExecutionBarrier {
|
|
|
255
253
|
isCurrent(seal) {
|
|
256
254
|
return this.currentSeal?.generation === seal.generation;
|
|
257
255
|
}
|
|
256
|
+
isQuiescent(seal) {
|
|
257
|
+
return this.activeClaims === 0 && (!seal.drainsYieldedTurns || this.suspendedClaims === 0);
|
|
258
|
+
}
|
|
259
|
+
notifyQuiescence() {
|
|
260
|
+
for (const waiter of [...this.quiescenceWaiters])
|
|
261
|
+
waiter();
|
|
262
|
+
}
|
|
258
263
|
createClaim() {
|
|
259
264
|
this.activeClaims++;
|
|
260
|
-
let
|
|
265
|
+
let state = 'active';
|
|
266
|
+
const release = () => {
|
|
267
|
+
if (state === 'released')
|
|
268
|
+
return;
|
|
269
|
+
if (state === 'active')
|
|
270
|
+
this.activeClaims--;
|
|
271
|
+
else
|
|
272
|
+
this.suspendedClaims--;
|
|
273
|
+
state = 'released';
|
|
274
|
+
this.notifyQuiescence();
|
|
275
|
+
};
|
|
261
276
|
return {
|
|
262
|
-
release
|
|
263
|
-
|
|
277
|
+
release,
|
|
278
|
+
suspend: () => {
|
|
279
|
+
if (state !== 'active')
|
|
264
280
|
return;
|
|
265
|
-
|
|
281
|
+
state = 'suspended';
|
|
266
282
|
this.activeClaims--;
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
283
|
+
this.suspendedClaims++;
|
|
284
|
+
this.notifyQuiescence();
|
|
285
|
+
},
|
|
286
|
+
resume: () => {
|
|
287
|
+
if (state !== 'suspended')
|
|
288
|
+
return state === 'active';
|
|
289
|
+
if (this.committed ||
|
|
290
|
+
(this.currentSeal !== undefined && !this.currentSeal.drainsYieldedTurns)) {
|
|
291
|
+
release();
|
|
292
|
+
return false;
|
|
271
293
|
}
|
|
294
|
+
state = 'active';
|
|
295
|
+
this.suspendedClaims--;
|
|
296
|
+
this.activeClaims++;
|
|
297
|
+
return true;
|
|
272
298
|
}
|
|
273
299
|
};
|
|
274
300
|
}
|
|
@@ -34,6 +34,7 @@ export declare class ZLinkSerialExecutionQueue {
|
|
|
34
34
|
private readonly executeRecord;
|
|
35
35
|
private readonly application;
|
|
36
36
|
private readonly lifecycle;
|
|
37
|
+
private activeLifecycle?;
|
|
37
38
|
private readonly ownerTimeBudget;
|
|
38
39
|
private readonly lifecycleBurstLimit;
|
|
39
40
|
private nextAcceptedSequence;
|
|
@@ -56,16 +57,14 @@ export declare class ZLinkSerialExecutionQueue {
|
|
|
56
57
|
* It remains held through handler terminal completion.
|
|
57
58
|
*/
|
|
58
59
|
submitPreAdmitted<T>(operation: () => Promise<T> | T, options?: ZLinkSerialWorkOptions, context?: unknown): Promise<T>;
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
readonly applicationBytes: number;
|
|
62
|
-
readonly lifecycleMessages: number;
|
|
63
|
-
readonly lifecycleBytes: number;
|
|
64
|
-
};
|
|
60
|
+
/** Holds lifecycle FIFO through an operation result while its application turns can run. */
|
|
61
|
+
submitLifecycleOperation<T>(operation: () => Promise<T> | T): Promise<T>;
|
|
65
62
|
get hasPendingWork(): boolean;
|
|
66
63
|
whenIdle(): Promise<void>;
|
|
67
64
|
/** Stops new submissions while allowing the accepted FIFO to finish. */
|
|
68
65
|
close(): Promise<void>;
|
|
66
|
+
/** Stops admission within the lifecycle operation that owns this queue's close. */
|
|
67
|
+
closeAdmission(): void;
|
|
69
68
|
private admit;
|
|
70
69
|
private scheduleDrain;
|
|
71
70
|
private drain;
|