@zlink-systems/framework 0.25.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
|
@@ -63,10 +63,6 @@ export function isRouteRecvRetryable(error: unknown): boolean {
|
|
|
63
63
|
);
|
|
64
64
|
}
|
|
65
65
|
|
|
66
|
-
export function isPollerInterruptedError(error: unknown): boolean {
|
|
67
|
-
return error instanceof zlink.RecvError && error.nativeErrno === 4;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
66
|
function isNativeBadAddress(error: { nativeErrno?: unknown; message?: unknown }): boolean {
|
|
71
67
|
return error.nativeErrno === 14 || /Bad address/i.test(String(error.message ?? ''));
|
|
72
68
|
}
|
|
@@ -176,32 +172,16 @@ export async function submitBindingRequest(
|
|
|
176
172
|
}
|
|
177
173
|
}
|
|
178
174
|
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
}
|
|
189
|
-
if (!isBusyCloseError(error)) {
|
|
190
|
-
throw error;
|
|
191
|
-
}
|
|
192
|
-
lastError = error;
|
|
193
|
-
await new Promise<void>((resolve) => setImmediate(resolve));
|
|
194
|
-
}
|
|
175
|
+
/**
|
|
176
|
+
* Closes a binding handle once. An already closed or terminated handle counts as
|
|
177
|
+
* closed. A busy close propagates to the caller.
|
|
178
|
+
*/
|
|
179
|
+
export function closeBindingHandle(target: { close(): void }): void {
|
|
180
|
+
try {
|
|
181
|
+
target.close();
|
|
182
|
+
} catch (error) {
|
|
183
|
+
if (!isSuccessfulOrAlreadyShutdownCloseError(error)) throw error;
|
|
195
184
|
}
|
|
196
|
-
throw lastError;
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
function isBusyCloseError(error: unknown): boolean {
|
|
200
|
-
return (
|
|
201
|
-
error instanceof Error &&
|
|
202
|
-
'code' in error &&
|
|
203
|
-
[401, 404].includes((error as { code: number }).code)
|
|
204
|
-
);
|
|
205
185
|
}
|
|
206
186
|
|
|
207
187
|
function isSuccessfulOrAlreadyShutdownCloseError(error: unknown): boolean {
|
|
@@ -12,11 +12,19 @@ export class ZLinkNodeEventLoopPoller {
|
|
|
12
12
|
private readableHandler: () => void;
|
|
13
13
|
private disposed = false;
|
|
14
14
|
|
|
15
|
-
constructor(
|
|
15
|
+
constructor(
|
|
16
|
+
socket: Socket,
|
|
17
|
+
pollCompletion: boolean,
|
|
18
|
+
readableHandler: () => void,
|
|
19
|
+
pollRoute = false
|
|
20
|
+
) {
|
|
16
21
|
this.readableHandler = readableHandler;
|
|
17
22
|
try {
|
|
18
23
|
const pollEvents: PollEventFlagValue[] = [zlink.PollEventFlag.PollIn];
|
|
19
24
|
if (pollCompletion) pollEvents.push(zlink.PollEventFlag.PollCompletion);
|
|
25
|
+
// A ROUTER selected-route change (Core ROUTER §10.1) wakes the same
|
|
26
|
+
// handler, whose owner is the socket's one route observer.
|
|
27
|
+
if (pollRoute) pollEvents.push(zlink.PollEventFlag.PollRoute);
|
|
20
28
|
this.poller.add(socket as BaseSocket, pollEvents, 0);
|
|
21
29
|
socket.setReadableHandler(this.onReady);
|
|
22
30
|
} catch (error) {
|
|
@@ -40,7 +48,11 @@ export class ZLinkNodeEventLoopPoller {
|
|
|
40
48
|
private readonly onReady = (): void => {
|
|
41
49
|
if (this.disposed) return;
|
|
42
50
|
const ready = this.poller.wait(this.events, 0);
|
|
43
|
-
if (
|
|
51
|
+
if (
|
|
52
|
+
ready === 0 ||
|
|
53
|
+
this.events.hasEvent(0, zlink.PollEventFlag.PollIn) ||
|
|
54
|
+
this.events.hasEvent(0, zlink.PollEventFlag.PollRoute)
|
|
55
|
+
) {
|
|
44
56
|
this.readableHandler();
|
|
45
57
|
}
|
|
46
58
|
};
|
|
@@ -33,6 +33,7 @@ import type {
|
|
|
33
33
|
ZLinkRawMonitorRecord,
|
|
34
34
|
ZLinkRawReceivedRecord,
|
|
35
35
|
ZLinkRawRouterPort,
|
|
36
|
+
ZLinkRawRouterRoute,
|
|
36
37
|
ZLinkRawSocketPort
|
|
37
38
|
} from '../raw-binding-port';
|
|
38
39
|
export type {
|
|
@@ -43,6 +44,7 @@ export type {
|
|
|
43
44
|
ZLinkRawMonitorRecord,
|
|
44
45
|
ZLinkRawReceivedRecord,
|
|
45
46
|
ZLinkRawRouterPort,
|
|
47
|
+
ZLinkRawRouterRoute,
|
|
46
48
|
ZLinkRawSocketPort
|
|
47
49
|
} from '../raw-binding-port';
|
|
48
50
|
|
|
@@ -131,8 +133,11 @@ abstract class NodeRawSocketPort<TSocket extends Socket> implements ZLinkRawSock
|
|
|
131
133
|
private readonly eventLoopPoller: ZLinkNodeEventLoopPoller;
|
|
132
134
|
private closed = false;
|
|
133
135
|
|
|
134
|
-
protected constructor(
|
|
135
|
-
|
|
136
|
+
protected constructor(
|
|
137
|
+
protected readonly socket: TSocket,
|
|
138
|
+
pollRoute = false
|
|
139
|
+
) {
|
|
140
|
+
this.eventLoopPoller = new ZLinkNodeEventLoopPoller(socket, true, () => {}, pollRoute);
|
|
136
141
|
}
|
|
137
142
|
|
|
138
143
|
setReadableHandler(handler: () => void): void {
|
|
@@ -236,7 +241,7 @@ class NodeRawRouterPort extends NodeRawSocketPort<RouterSocket> implements ZLink
|
|
|
236
241
|
}
|
|
237
242
|
|
|
238
243
|
constructor(socket: RouterSocket, receiveTimeoutMs?: number) {
|
|
239
|
-
super(socket);
|
|
244
|
+
super(socket, true);
|
|
240
245
|
socket.options.handover = true;
|
|
241
246
|
socket.options.mandatory = true;
|
|
242
247
|
socket.options.probe = true;
|
|
@@ -291,6 +296,14 @@ class NodeRawRouterPort extends NodeRawSocketPort<RouterSocket> implements ZLink
|
|
|
291
296
|
}
|
|
292
297
|
}
|
|
293
298
|
|
|
299
|
+
routesSnapshot(): readonly ZLinkRawRouterRoute[] {
|
|
300
|
+
this.requireOpen();
|
|
301
|
+
return this.socket.routesSnapshot().map((route) => ({
|
|
302
|
+
routingId: route.routingId.toString(),
|
|
303
|
+
routeGeneration: route.routeGeneration
|
|
304
|
+
}));
|
|
305
|
+
}
|
|
306
|
+
|
|
294
307
|
receive(dontWait = false): ZLinkRawReceivedRecord | undefined {
|
|
295
308
|
this.requireOpen();
|
|
296
309
|
return receiveRecord(
|
|
@@ -450,6 +463,7 @@ function receiveRecord(
|
|
|
450
463
|
return {
|
|
451
464
|
sourceRid,
|
|
452
465
|
sourceRoute,
|
|
466
|
+
routeGeneration: received.routeGeneration,
|
|
453
467
|
...(requestSeq === undefined ? {} : { requestSeq }),
|
|
454
468
|
...(receivedReply === undefined
|
|
455
469
|
? {}
|
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
encodeStreamWireHeader
|
|
8
8
|
} from '@zlink-systems/stream-wire';
|
|
9
9
|
import { disconnectStreamPeer } from './node-socket-backend-adapter';
|
|
10
|
+
import { translateBindingResultError } from './node-backend-adapter-support';
|
|
10
11
|
import { ZLinkFrameworkException } from '../../../contracts';
|
|
11
12
|
import { internalFrameworkWireReply } from '../../framework-errors-internal';
|
|
12
13
|
import {
|
|
@@ -105,7 +106,6 @@ import { buildAdvertisedEndpoint } from '../../../contracts/Configuration/Endpoi
|
|
|
105
106
|
import { ZLinkConfigurationException } from '../../../contracts/Configuration/ConfigurationException';
|
|
106
107
|
import type {
|
|
107
108
|
ZLinkBackendActorRef,
|
|
108
|
-
ZLinkBackendActorSessionSendFence,
|
|
109
109
|
ZLinkBackendObjectPlacement,
|
|
110
110
|
ZLinkBackendMeshNode
|
|
111
111
|
} from '../contracts';
|
|
@@ -116,7 +116,7 @@ const MULTIPART_PACKET_NAME = SERVICE_FRAMEWORK_MULTIPART_PACKET_NAME;
|
|
|
116
116
|
const MULTIPART_CONTENT_TYPE = SERVICE_FRAMEWORK_MULTIPART_CONTENT_TYPE;
|
|
117
117
|
const FATAL_UTF8 = new TextDecoder('utf-8', { fatal: true });
|
|
118
118
|
const MAX_DRAIN_RECORDS = 64;
|
|
119
|
-
// Preserve the existing
|
|
119
|
+
// Preserve the existing route observation/admission/liveness cadence. Only the binding
|
|
120
120
|
// readable handler admits receive work; this timer never probes the socket.
|
|
121
121
|
const MESH_BACKEND_MAINTENANCE_INTERVAL_MS = 1;
|
|
122
122
|
/**
|
|
@@ -186,6 +186,7 @@ export class ZLinkNodeRawMeshBackend implements ZLinkBackendMeshNode {
|
|
|
186
186
|
record: import('../../foundation/service-stateful-wire-codec').ServiceMessageFollowRecord
|
|
187
187
|
) => void;
|
|
188
188
|
private dispatchErrors?: ZLinkDispatchErrorReporter;
|
|
189
|
+
private spotAdmissionProvider?: Parameters<ServiceStatefulRuntime['setSpotAdmissionProvider']>[0];
|
|
189
190
|
private readonly peerDisconnectedHandlers = new Set<(endpoint: string) => void>();
|
|
190
191
|
constructor(
|
|
191
192
|
private readonly meshName: string,
|
|
@@ -241,6 +242,13 @@ export class ZLinkNodeRawMeshBackend implements ZLinkBackendMeshNode {
|
|
|
241
242
|
this.stateful?.setDispatchErrorReporter(reporter, this.meshName);
|
|
242
243
|
}
|
|
243
244
|
|
|
245
|
+
setSpotAdmissionProvider(
|
|
246
|
+
provider: Parameters<ServiceStatefulRuntime['setSpotAdmissionProvider']>[0]
|
|
247
|
+
): void {
|
|
248
|
+
this.spotAdmissionProvider = provider;
|
|
249
|
+
this.stateful?.setSpotAdmissionProvider(provider);
|
|
250
|
+
}
|
|
251
|
+
|
|
244
252
|
setProtocolErrorHandler(
|
|
245
253
|
handler: (record: {
|
|
246
254
|
readonly sourceNodeRid: string;
|
|
@@ -394,6 +402,9 @@ export class ZLinkNodeRawMeshBackend implements ZLinkBackendMeshNode {
|
|
|
394
402
|
descriptor.nodeRoutingId,
|
|
395
403
|
descriptor.lifecycleGeneration
|
|
396
404
|
);
|
|
405
|
+
if (this.spotAdmissionProvider !== undefined) {
|
|
406
|
+
this.stateful.setSpotAdmissionProvider(this.spotAdmissionProvider);
|
|
407
|
+
}
|
|
397
408
|
if (this.dispatchErrors !== undefined) {
|
|
398
409
|
this.stateful.setDispatchErrorReporter(this.dispatchErrors, this.meshName);
|
|
399
410
|
}
|
|
@@ -1327,14 +1338,12 @@ export class ZLinkNodeRawMeshBackend implements ZLinkBackendMeshNode {
|
|
|
1327
1338
|
actor: ZLinkBackendActorRef,
|
|
1328
1339
|
expectedBindingGeneration: bigint,
|
|
1329
1340
|
parts: MessageLike | readonly MessageLike[],
|
|
1330
|
-
_flags?: number
|
|
1331
|
-
actorFence?: ZLinkBackendActorSessionSendFence
|
|
1341
|
+
_flags?: number
|
|
1332
1342
|
): Promise<SubmitResultValue> {
|
|
1333
1343
|
return (await this.requireStateful().sendBoundSession(
|
|
1334
1344
|
actor,
|
|
1335
1345
|
expectedBindingGeneration,
|
|
1336
|
-
encodeMultipart(parts)
|
|
1337
|
-
actorFence
|
|
1346
|
+
encodeMultipart(parts)
|
|
1338
1347
|
)) as SubmitResultValue;
|
|
1339
1348
|
}
|
|
1340
1349
|
|
|
@@ -1524,7 +1533,7 @@ export class ZLinkNodeRawMeshBackend implements ZLinkBackendMeshNode {
|
|
|
1524
1533
|
const id = { high: 1n, low };
|
|
1525
1534
|
void promise.then(
|
|
1526
1535
|
(result) => this.enqueueCompletion(id, operationKind, result),
|
|
1527
|
-
(error) => this.enqueueCompletion(id, operationKind,
|
|
1536
|
+
(error) => this.enqueueCompletion(id, operationKind, requestFailureResult(error))
|
|
1528
1537
|
);
|
|
1529
1538
|
return id;
|
|
1530
1539
|
}
|
|
@@ -1536,7 +1545,7 @@ export class ZLinkNodeRawMeshBackend implements ZLinkBackendMeshNode {
|
|
|
1536
1545
|
const id = { high: 2n, low: pending.id };
|
|
1537
1546
|
void pending.promise.then(
|
|
1538
1547
|
(result) => this.enqueueCompletion(id, operationKind, result),
|
|
1539
|
-
(error) => this.enqueueCompletion(id, operationKind,
|
|
1548
|
+
(error) => this.enqueueCompletion(id, operationKind, requestFailureResult(error))
|
|
1540
1549
|
);
|
|
1541
1550
|
return id;
|
|
1542
1551
|
}
|
|
@@ -2430,40 +2439,64 @@ function readyDomain(domain: ServiceMailboxDomain): number {
|
|
|
2430
2439
|
}
|
|
2431
2440
|
|
|
2432
2441
|
/**
|
|
2433
|
-
*
|
|
2434
|
-
* terminal.
|
|
2435
|
-
*
|
|
2436
|
-
*
|
|
2437
|
-
*
|
|
2442
|
+
* The one classification of a failed node/channel/stateful request into its
|
|
2443
|
+
* completion terminal. A binding REQUEST result is Core's decision and is kept
|
|
2444
|
+
* as is; a submit failure retains its Core meaning at the request boundary.
|
|
2445
|
+
* A reply that could not be decoded is a protocol
|
|
2446
|
+
* failure (spec 32-framework-error-model:91-92). The failure code is a wire
|
|
2447
|
+
* code, so a Core result carries 0.
|
|
2438
2448
|
*/
|
|
2439
|
-
export function
|
|
2449
|
+
export function requestFailureResult(error: unknown): RawServiceRequestResult {
|
|
2450
|
+
const failure = translateBindingResultError(error);
|
|
2451
|
+
if (isZLinkBackendResultError(failure)) {
|
|
2452
|
+
return {
|
|
2453
|
+
terminalResult:
|
|
2454
|
+
failure.operation === 'request' ? failure.result : submitFailureTerminal(failure.result),
|
|
2455
|
+
failureCode: 0
|
|
2456
|
+
};
|
|
2457
|
+
}
|
|
2440
2458
|
// requestProtocolError(16): the schema terminal-failure-integrity rule
|
|
2441
|
-
// forbids a typed terminal (104) with failure none
|
|
2442
|
-
|
|
2443
|
-
|
|
2444
|
-
? { terminalResult: RequestResult.ProtocolError, failureCode: 16 }
|
|
2445
|
-
: { terminalResult: RequestResult.NotConnected, failureCode: 0 };
|
|
2446
|
-
}
|
|
2447
|
-
|
|
2448
|
-
function statefulOperationFailure(error: unknown): RawServiceRequestResult {
|
|
2449
|
-
if (error instanceof ZLinkFrameworkException) {
|
|
2450
|
-
return internalFrameworkWireReply(error);
|
|
2459
|
+
// forbids a typed terminal (104) with failure none.
|
|
2460
|
+
if (failure instanceof ServiceWireProtocolError) {
|
|
2461
|
+
return { terminalResult: RequestResult.ProtocolError, failureCode: 16 };
|
|
2451
2462
|
}
|
|
2452
|
-
if (
|
|
2453
|
-
return
|
|
2463
|
+
if (failure instanceof ZLinkFrameworkException) {
|
|
2464
|
+
return internalFrameworkWireReply(failure);
|
|
2454
2465
|
}
|
|
2455
|
-
if (
|
|
2456
|
-
return {
|
|
2457
|
-
terminalResult: error.result,
|
|
2458
|
-
failureCode: error.nativeErrno ?? 0
|
|
2459
|
-
};
|
|
2466
|
+
if (failure instanceof OperationTimeoutError) {
|
|
2467
|
+
return { terminalResult: RequestResult.TimedOut, failureCode: 0 };
|
|
2460
2468
|
}
|
|
2461
|
-
if (
|
|
2469
|
+
if (failure instanceof OperationCancelledError) {
|
|
2462
2470
|
return { terminalResult: RequestResult.NotConnected, failureCode: 0 };
|
|
2463
2471
|
}
|
|
2464
2472
|
return { terminalResult: RequestResult.InternalError, failureCode: 17 };
|
|
2465
2473
|
}
|
|
2466
2474
|
|
|
2475
|
+
function submitFailureTerminal(result: number): number {
|
|
2476
|
+
switch (result) {
|
|
2477
|
+
case SubmitResult.Backpressured:
|
|
2478
|
+
return RequestResult.Backpressured;
|
|
2479
|
+
case SubmitResult.NotConnected:
|
|
2480
|
+
return RequestResult.NotConnected;
|
|
2481
|
+
case SubmitResult.NotFound:
|
|
2482
|
+
return RequestResult.NotFound;
|
|
2483
|
+
case SubmitResult.NotAdmitted:
|
|
2484
|
+
return RequestResult.Rejected;
|
|
2485
|
+
case SubmitResult.InvalidHandle:
|
|
2486
|
+
case SubmitResult.InvalidArgument:
|
|
2487
|
+
case SubmitResult.ThreadViolation:
|
|
2488
|
+
return RequestResult.InvalidArgument;
|
|
2489
|
+
case SubmitResult.InvalidState:
|
|
2490
|
+
return RequestResult.InvalidState;
|
|
2491
|
+
case SubmitResult.NotSupported:
|
|
2492
|
+
return RequestResult.NotSupported;
|
|
2493
|
+
case SubmitResult.Terminated:
|
|
2494
|
+
return RequestResult.Terminated;
|
|
2495
|
+
default:
|
|
2496
|
+
return RequestResult.InternalError;
|
|
2497
|
+
}
|
|
2498
|
+
}
|
|
2499
|
+
|
|
2467
2500
|
function encodeMultipart(parts: MessageLike | readonly MessageLike[]) {
|
|
2468
2501
|
const values = Array.isArray(parts) ? parts : [parts];
|
|
2469
2502
|
if (values.length === 0) throw new TypeError('Multipart payload must contain at least one part.');
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { Socket } from '@zlink-systems/zlink';
|
|
2
2
|
import type { ZLinkBackendObject } from '../contracts';
|
|
3
3
|
import {
|
|
4
|
-
|
|
4
|
+
closeBindingHandle,
|
|
5
5
|
disableSocketLinger,
|
|
6
6
|
isBindingNotFound,
|
|
7
7
|
isContextTerminatedError,
|
|
@@ -52,7 +52,7 @@ export function wrapSocket<T extends { close(): void }>(
|
|
|
52
52
|
async dispose(): Promise<void> {
|
|
53
53
|
eventLoopPoller?.dispose();
|
|
54
54
|
disableSocketLinger(nativeInstance);
|
|
55
|
-
|
|
55
|
+
closeBindingHandle(nativeInstance);
|
|
56
56
|
},
|
|
57
57
|
close(): void {
|
|
58
58
|
eventLoopPoller?.dispose();
|
|
@@ -2,6 +2,11 @@ export interface ZLinkRawReceivedRecord {
|
|
|
2
2
|
readonly sourceRid: string;
|
|
3
3
|
readonly sourceRoute: Uint8Array;
|
|
4
4
|
readonly requestSeq?: bigint;
|
|
5
|
+
/**
|
|
6
|
+
* Core selected-route generation of the ROUTER route that delivered this
|
|
7
|
+
* record (Core ROUTER §10.1); 0n for a non-ROUTER receive. Equality only.
|
|
8
|
+
*/
|
|
9
|
+
readonly routeGeneration: bigint;
|
|
5
10
|
readonly reply?: (parts: readonly Uint8Array[]) => void;
|
|
6
11
|
readonly parts: readonly Buffer[];
|
|
7
12
|
/** Releases the ordinary Framework-owned receive record exactly once. */
|
|
@@ -37,6 +42,12 @@ export interface ZLinkRawMonitorPort {
|
|
|
37
42
|
close(): void;
|
|
38
43
|
}
|
|
39
44
|
|
|
45
|
+
/** One row of the ROUTER selected-route snapshot (Core ROUTER §10.1). */
|
|
46
|
+
export interface ZLinkRawRouterRoute {
|
|
47
|
+
readonly routingId: string;
|
|
48
|
+
readonly routeGeneration: bigint;
|
|
49
|
+
}
|
|
50
|
+
|
|
40
51
|
export interface ZLinkRawRouterPort extends ZLinkRawSocketPort {
|
|
41
52
|
disconnectRid?(routingId: string): void;
|
|
42
53
|
localEndpoint(): string;
|
|
@@ -49,6 +60,8 @@ export interface ZLinkRawRouterPort extends ZLinkRawSocketPort {
|
|
|
49
60
|
timeoutMs: number
|
|
50
61
|
): Promise<readonly Buffer[]>;
|
|
51
62
|
receive(dontWait?: boolean): ZLinkRawReceivedRecord | undefined;
|
|
63
|
+
/** The selected route of every RID. The socket's one route observer calls it. */
|
|
64
|
+
routesSnapshot(): readonly ZLinkRawRouterRoute[];
|
|
52
65
|
}
|
|
53
66
|
|
|
54
67
|
export interface ZLinkRawDealerPort extends ZLinkRawSocketPort {
|
|
@@ -138,17 +138,6 @@ export class DefaultZLinkFanoutClient implements ZLinkFanoutClient {
|
|
|
138
138
|
);
|
|
139
139
|
}
|
|
140
140
|
|
|
141
|
-
getListenerStatus(channelName: string): import('../../contracts').ZLinkFanoutListenerStatus {
|
|
142
|
-
this.requirePublisherChannel(channelName);
|
|
143
|
-
const status = this.requireTransport().getFanoutListenerStatus?.(channelName);
|
|
144
|
-
if (status === undefined) {
|
|
145
|
-
throw new ZLinkConfigurationException(
|
|
146
|
-
`Fanout publisher '${channelName}' has not reported a bound listener.`
|
|
147
|
-
);
|
|
148
|
-
}
|
|
149
|
-
return status;
|
|
150
|
-
}
|
|
151
|
-
|
|
152
141
|
private requirePublisherChannel(channelName: string): void {
|
|
153
142
|
if (!this.registration.fanoutPublishers.has(channelName)) {
|
|
154
143
|
throw new ZLinkConfigurationException(
|
|
@@ -72,11 +72,7 @@ export class ZLinkChannelOutboundOperations {
|
|
|
72
72
|
throwIfAborted(signal);
|
|
73
73
|
const dealer = await this.sockets.awaitClientDealerForOutbound(channelName, signal);
|
|
74
74
|
if (dealer === undefined) {
|
|
75
|
-
return {
|
|
76
|
-
status: this.sockets.hasKnownClientServerTargets(channelName)
|
|
77
|
-
? ZLinkSubmitStatus.RouteNotConnected
|
|
78
|
-
: ZLinkSubmitStatus.TargetNotFound
|
|
79
|
-
};
|
|
75
|
+
return { status: ZLinkSubmitStatus.RouteNotConnected };
|
|
80
76
|
}
|
|
81
77
|
const parts = encodeChannelEnvelopeParts(
|
|
82
78
|
ZLinkChannelMessageKind.Command,
|
|
@@ -185,12 +181,8 @@ export class ZLinkChannelOutboundOperations {
|
|
|
185
181
|
deadlineAtMs === undefined ? undefined : Math.floor(deadlineAtMs - performance.now());
|
|
186
182
|
if (dealer === undefined || (remainingMs !== undefined && remainingMs <= 0)) {
|
|
187
183
|
throw createInternalFrameworkException(
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
: ZLinkFrameworkInternalErrorKind.RequestTargetNotFound,
|
|
191
|
-
this.sockets.hasKnownClientServerTargets(channelName)
|
|
192
|
-
? `Channel '${channelName}' has known ClientServer targets but no ready server.`
|
|
193
|
-
: `Channel '${channelName}' has no ready ClientServer server.`
|
|
184
|
+
ZLinkFrameworkInternalErrorKind.RouteNotConnected,
|
|
185
|
+
`Channel '${channelName}' has no ready ClientServer server.`
|
|
194
186
|
);
|
|
195
187
|
}
|
|
196
188
|
const serverRid = this.sockets.selectedClientServerRid(channelName, dealer);
|
|
@@ -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';
|
|
@@ -62,7 +63,8 @@ export class ZLinkChannelRuntimeManager {
|
|
|
62
63
|
context,
|
|
63
64
|
options.monitoringAdapter,
|
|
64
65
|
options.oneWayFailureSink,
|
|
65
|
-
applicationJobQueue
|
|
66
|
+
applicationJobQueue,
|
|
67
|
+
options.listenerRecords
|
|
66
68
|
);
|
|
67
69
|
const codecs: ZLinkChannelEnvelopeCodecRegistry = {
|
|
68
70
|
serializers: registration.messageSerializers
|
|
@@ -118,20 +120,6 @@ export class ZLinkChannelRuntimeManager {
|
|
|
118
120
|
return { descriptors: this.sockets.fanoutActiveTargets(channelName) };
|
|
119
121
|
}
|
|
120
122
|
|
|
121
|
-
getFanoutListenerStatus(channelName: string) {
|
|
122
|
-
const endpoint = this.sockets.fanoutPublisherEndpoint(channelName);
|
|
123
|
-
if (endpoint === undefined) {
|
|
124
|
-
throw new ZLinkConfigurationException(
|
|
125
|
-
`Fanout publisher '${channelName}' has not reported a bound listener.`
|
|
126
|
-
);
|
|
127
|
-
}
|
|
128
|
-
return {
|
|
129
|
-
channelName,
|
|
130
|
-
endpoint,
|
|
131
|
-
observedAt: new Date()
|
|
132
|
-
};
|
|
133
|
-
}
|
|
134
|
-
|
|
135
123
|
observeClientServerTopology(channelName: string, changed: () => void): () => void {
|
|
136
124
|
const monitor = this.sockets.clientServerMonitoringSource(channelName);
|
|
137
125
|
monitor.onEvent(changed);
|
|
@@ -447,6 +435,7 @@ function splitMonitoringSocketSourceName(sourceName: string): readonly [string,
|
|
|
447
435
|
}
|
|
448
436
|
|
|
449
437
|
export interface ZLinkChannelRuntimeManagerOptions {
|
|
438
|
+
readonly listenerRecords?: ZLinkListenerRecords;
|
|
450
439
|
readonly internalRouteSendHandlers?: ReadonlyMap<string, ZLinkRouteRuntimeSendHandler>;
|
|
451
440
|
readonly internalRouteRequestHandlers?: ReadonlyMap<string, ZLinkRouteRuntimeRequestHandler>;
|
|
452
441
|
readonly monitoringAdapter?: ZLinkMonitoringBackendAdapter;
|