@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
|
@@ -53,25 +53,27 @@ export class ZLinkSpotActorLifecycleDrain {
|
|
|
53
53
|
continue;
|
|
54
54
|
}
|
|
55
55
|
if (actorRef === null || actorRef === undefined) continue;
|
|
56
|
-
await this.options.serial.
|
|
57
|
-
|
|
58
|
-
|
|
56
|
+
await this.options.serial.executeLifecycleOperation(() =>
|
|
57
|
+
this.options.serial.execute(() => {
|
|
58
|
+
const actor = this.options.resolveActor(actorId);
|
|
59
|
+
if (actor === undefined) {
|
|
60
|
+
return undefined;
|
|
61
|
+
}
|
|
62
|
+
const target = this.options.getTarget();
|
|
63
|
+
if (event.kind === ZLINK_SPOT_ACTOR_LIFECYCLE_JOINED) {
|
|
64
|
+
return target.onJoinedActor?.(actor);
|
|
65
|
+
}
|
|
66
|
+
if (event.kind === ZLINK_SPOT_ACTOR_LIFECYCLE_LEFT) {
|
|
67
|
+
return Promise.resolve(target.onLeaveActor?.(actor)).then(() => {
|
|
68
|
+
this.options.commitActorDeparture?.(actorId);
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
if (event.kind === ZLINK_SPOT_ACTOR_LIFECYCLE_DISCONNECTED) {
|
|
72
|
+
return target.onDisconnectActor?.(actor);
|
|
73
|
+
}
|
|
59
74
|
return undefined;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
if (event.kind === ZLINK_SPOT_ACTOR_LIFECYCLE_JOINED) {
|
|
63
|
-
return target.onJoinedActor?.(actor);
|
|
64
|
-
}
|
|
65
|
-
if (event.kind === ZLINK_SPOT_ACTOR_LIFECYCLE_LEFT) {
|
|
66
|
-
return Promise.resolve(target.onLeaveActor?.(actor)).then(() => {
|
|
67
|
-
this.options.commitActorDeparture?.(actorId);
|
|
68
|
-
});
|
|
69
|
-
}
|
|
70
|
-
if (event.kind === ZLINK_SPOT_ACTOR_LIFECYCLE_DISCONNECTED) {
|
|
71
|
-
return target.onDisconnectActor?.(actor);
|
|
72
|
-
}
|
|
73
|
-
return undefined;
|
|
74
|
-
});
|
|
75
|
+
})
|
|
76
|
+
);
|
|
75
77
|
}
|
|
76
78
|
}
|
|
77
79
|
}
|
|
@@ -11,6 +11,10 @@ import { throwIfAborted } from '../abort';
|
|
|
11
11
|
import type { Message } from '../../contracts/Common/Message';
|
|
12
12
|
import { ZLinkBufferMessage as RuntimeMessage } from '../backend/runtime-message';
|
|
13
13
|
import { ZLinkConfigurationException } from '../configuration';
|
|
14
|
+
import {
|
|
15
|
+
ZLinkFrameworkInternalErrorKind,
|
|
16
|
+
createInternalFrameworkException
|
|
17
|
+
} from '../framework-errors-internal';
|
|
14
18
|
import { ZLinkDispatchErrorReporter } from '../channels';
|
|
15
19
|
import { ZLINK_ACTOR_JOIN_ENTRY_SPOT_RUNTIME, ZLinkSpotActorDispatcher } from '../actors';
|
|
16
20
|
import { encodeFrameworkPayloadMessage } from '../messaging/payload-codec';
|
|
@@ -37,6 +41,7 @@ export interface ZLinkSpotActorMembershipOptions {
|
|
|
37
41
|
readonly entrySpotIdProvider?: (meshName: string) => string | undefined;
|
|
38
42
|
readonly spotRouteResolver?: ZLinkSpotRouteResolver;
|
|
39
43
|
readonly actorTransferRuntime?: ZLinkSpotActorTransferRuntime;
|
|
44
|
+
readonly isSpotClosing?: (activation: ZLinkSpotActivation) => boolean;
|
|
40
45
|
}
|
|
41
46
|
|
|
42
47
|
export type ZLinkActorJoinRollback = () => Promise<void> | void;
|
|
@@ -57,6 +62,36 @@ export class ZLinkSpotActorMembership {
|
|
|
57
62
|
): Promise<ZLinkSpotActorJoinResult> {
|
|
58
63
|
throwIfAborted(signal);
|
|
59
64
|
const activation = this.requireActivation(spotId);
|
|
65
|
+
return await this.runLifecycleOperation(activation, async () => {
|
|
66
|
+
if (this.options.isSpotClosing?.(activation) === true) {
|
|
67
|
+
throw createInternalFrameworkException(
|
|
68
|
+
ZLinkFrameworkInternalErrorKind.RequestRejected,
|
|
69
|
+
`User Spot '${String(spotId)}' is closing.`
|
|
70
|
+
);
|
|
71
|
+
}
|
|
72
|
+
return await this.admitActorJoinCore(
|
|
73
|
+
activation,
|
|
74
|
+
actor,
|
|
75
|
+
request,
|
|
76
|
+
commit,
|
|
77
|
+
signal,
|
|
78
|
+
leaveSource,
|
|
79
|
+
contentType
|
|
80
|
+
);
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
private async admitActorJoinCore(
|
|
85
|
+
activation: ZLinkSpotActivation,
|
|
86
|
+
actor: ZLinkActor,
|
|
87
|
+
request: Message,
|
|
88
|
+
commit: (
|
|
89
|
+
spot: ZLinkSpot
|
|
90
|
+
) => Promise<ZLinkActorJoinRollback | void> | ZLinkActorJoinRollback | void,
|
|
91
|
+
signal: AbortSignal | undefined,
|
|
92
|
+
leaveSource: (() => Promise<void>) | undefined,
|
|
93
|
+
contentType: string
|
|
94
|
+
): Promise<ZLinkSpotActorJoinResult> {
|
|
60
95
|
const dispatcher = this.createActorDispatcher(activation);
|
|
61
96
|
const transaction: {
|
|
62
97
|
rollbackExternal?: ZLinkActorJoinRollback;
|
|
@@ -103,6 +138,17 @@ export class ZLinkSpotActorMembership {
|
|
|
103
138
|
): Promise<void> {
|
|
104
139
|
throwIfAborted(signal);
|
|
105
140
|
const activation = this.requireActivation(spotId, meshName);
|
|
141
|
+
await this.runLifecycleOperation(activation, () =>
|
|
142
|
+
this.leaveActorCore(activation, actor, signal, meshName)
|
|
143
|
+
);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
private async leaveActorCore(
|
|
147
|
+
activation: ZLinkSpotActivation,
|
|
148
|
+
actor: ZLinkActor,
|
|
149
|
+
signal?: AbortSignal,
|
|
150
|
+
meshName?: string
|
|
151
|
+
): Promise<void> {
|
|
106
152
|
const localEntryNodeRid =
|
|
107
153
|
(meshName === undefined ? undefined : this.options.nodeRidProvider?.(meshName)) ??
|
|
108
154
|
this.options.entryNodeRidProvider?.() ??
|
|
@@ -177,11 +223,13 @@ export class ZLinkSpotActorMembership {
|
|
|
177
223
|
): Promise<void> {
|
|
178
224
|
throwIfAborted(signal);
|
|
179
225
|
const activation = this.requireActivation(spotId);
|
|
180
|
-
await
|
|
181
|
-
activation.
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
226
|
+
await this.runLifecycleOperation(activation, () =>
|
|
227
|
+
activation.serial.execute(async () => {
|
|
228
|
+
activation.beginActorTransfer(actor.context.actorId);
|
|
229
|
+
await activation.spot.onLeaveActor(actor);
|
|
230
|
+
activation.commitActorDeparture(actor.context.actorId);
|
|
231
|
+
})
|
|
232
|
+
);
|
|
185
233
|
}
|
|
186
234
|
|
|
187
235
|
async prepareActorLeaveForTransfer(
|
|
@@ -191,12 +239,16 @@ export class ZLinkSpotActorMembership {
|
|
|
191
239
|
): Promise<void> {
|
|
192
240
|
throwIfAborted(signal);
|
|
193
241
|
const activation = this.requireActivation(spotId);
|
|
194
|
-
await
|
|
242
|
+
await this.runLifecycleOperation(activation, () =>
|
|
243
|
+
activation.serial.execute(() => activation.spot.onLeaveActor(actor))
|
|
244
|
+
);
|
|
195
245
|
}
|
|
196
246
|
|
|
197
247
|
async commitActorLeaveAfterTransfer(spotId: RoutingId, actorId: string): Promise<void> {
|
|
198
248
|
const activation = this.requireActivation(spotId);
|
|
199
|
-
await
|
|
249
|
+
await this.runLifecycleOperation(activation, () =>
|
|
250
|
+
activation.serial.execute(() => activation.commitActorDeparture(actorId))
|
|
251
|
+
);
|
|
200
252
|
}
|
|
201
253
|
|
|
202
254
|
async restoreActorAfterFailedTransfer(
|
|
@@ -206,24 +258,26 @@ export class ZLinkSpotActorMembership {
|
|
|
206
258
|
): Promise<void> {
|
|
207
259
|
throwIfAborted(signal);
|
|
208
260
|
const activation = this.requireActivation(spotId);
|
|
209
|
-
await
|
|
210
|
-
activation.
|
|
211
|
-
|
|
212
|
-
|
|
261
|
+
await this.runLifecycleOperation(activation, () =>
|
|
262
|
+
activation.serial.execute(async () => {
|
|
263
|
+
activation.cancelActorTransfer(actor.context.actorId);
|
|
264
|
+
await activation.spot.onJoinedActor(actor);
|
|
265
|
+
})
|
|
266
|
+
);
|
|
213
267
|
}
|
|
214
268
|
|
|
215
269
|
async beginActorTransfer(spotId: RoutingId, actorId: string): Promise<void> {
|
|
216
270
|
const activation = this.requireActivation(spotId);
|
|
217
|
-
await
|
|
218
|
-
activation.beginActorTransfer(actorId)
|
|
219
|
-
|
|
271
|
+
await this.runLifecycleOperation(activation, () =>
|
|
272
|
+
activation.serial.execute(() => activation.beginActorTransfer(actorId))
|
|
273
|
+
);
|
|
220
274
|
}
|
|
221
275
|
|
|
222
276
|
async cancelActorTransfer(spotId: RoutingId, actorId: string): Promise<void> {
|
|
223
277
|
const activation = this.requireActivation(spotId);
|
|
224
|
-
await
|
|
225
|
-
activation.cancelActorTransfer(actorId)
|
|
226
|
-
|
|
278
|
+
await this.runLifecycleOperation(activation, () =>
|
|
279
|
+
activation.serial.execute(() => activation.cancelActorTransfer(actorId))
|
|
280
|
+
);
|
|
227
281
|
}
|
|
228
282
|
|
|
229
283
|
async notifyJoinedActorDisconnected(
|
|
@@ -252,6 +306,16 @@ export class ZLinkSpotActorMembership {
|
|
|
252
306
|
return activation;
|
|
253
307
|
}
|
|
254
308
|
|
|
309
|
+
private async runLifecycleOperation<T>(
|
|
310
|
+
activation: ZLinkSpotActivation,
|
|
311
|
+
operation: () => Promise<T> | T
|
|
312
|
+
): Promise<T> {
|
|
313
|
+
const pending = activation.serial.executeLifecycleOperation(operation);
|
|
314
|
+
return activation.serial.isCurrentTurn
|
|
315
|
+
? await activation.serial.currentTurn!.yieldFrameworkPromise(pending)
|
|
316
|
+
: await pending;
|
|
317
|
+
}
|
|
318
|
+
|
|
255
319
|
private createActorDispatcher(activation: ZLinkSpotActivation): ZLinkSpotActorDispatcher {
|
|
256
320
|
return new ZLinkSpotActorDispatcher({
|
|
257
321
|
registry: activation.actorHandlers,
|
|
@@ -29,7 +29,6 @@ import { routingIdsEqual } from '../routing-id';
|
|
|
29
29
|
import { ZLinkSpotActorHandlerRegistryRuntime } from '../actors';
|
|
30
30
|
import type {
|
|
31
31
|
ZLinkBackendActorRecvInfo,
|
|
32
|
-
ZLinkBackendReceived,
|
|
33
32
|
ZLinkBackendSpot,
|
|
34
33
|
ZLinkBackendSpotNode,
|
|
35
34
|
ZLinkBackendTopicMessage
|
|
@@ -81,7 +80,6 @@ interface ZLinkEntrySpotActivationOptions {
|
|
|
81
80
|
readonly actorRequestHandlers?: readonly ZLinkEntrySpotActorRequestHandlerRegistration[];
|
|
82
81
|
readonly nativeSpot: ZLinkBackendSpot;
|
|
83
82
|
readonly nativeNode: ZLinkBackendSpotNode;
|
|
84
|
-
readonly createReceived: () => ZLinkBackendReceived;
|
|
85
83
|
readonly createTopicMessage: () => ZLinkBackendTopicMessage;
|
|
86
84
|
readonly nodeRid: RoutingId;
|
|
87
85
|
readonly spotNodeName: string;
|
|
@@ -382,7 +380,6 @@ export class ZLinkEntrySpotActivation {
|
|
|
382
380
|
private attachActorJoinDispatch(): void {
|
|
383
381
|
const dispatch = new ZLinkSpotActorJoinDispatch({
|
|
384
382
|
nativeSpot: this.options.nativeSpot,
|
|
385
|
-
createReceived: this.options.createReceived,
|
|
386
383
|
createTopicMessage: this.options.createTopicMessage,
|
|
387
384
|
serial: this.serial,
|
|
388
385
|
actors: {
|
|
@@ -100,10 +100,14 @@ export class ZLinkPublicSpotManager implements ZLinkSpotManager {
|
|
|
100
100
|
if (this.options.isLocalNode(current.meshName, current.nodeRid)) {
|
|
101
101
|
const closed = await this.options.coordinator.close(
|
|
102
102
|
spot,
|
|
103
|
-
(local) =>
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
103
|
+
(local, beginAuthority) =>
|
|
104
|
+
this.options.local.closeUserWithAuthority(
|
|
105
|
+
local.meshName,
|
|
106
|
+
local.spotId,
|
|
107
|
+
beginAuthority,
|
|
108
|
+
signal
|
|
109
|
+
),
|
|
110
|
+
signal
|
|
107
111
|
);
|
|
108
112
|
if (closed) this.options.resolver()?.invalidate?.(spot.spotId);
|
|
109
113
|
return closed;
|
|
@@ -40,7 +40,7 @@ interface ZLinkSpotNativeActorJoinAdmissionOptions {
|
|
|
40
40
|
export class ZLinkSpotNativeActorJoinAdmission {
|
|
41
41
|
constructor(private readonly options: ZLinkSpotNativeActorJoinAdmissionOptions) {}
|
|
42
42
|
|
|
43
|
-
async admit(request: ZLinkBackendActorJoinRequest): Promise<void> {
|
|
43
|
+
async admit(request: ZLinkBackendActorJoinRequest, rejectClosing = false): Promise<void> {
|
|
44
44
|
const actorId = request.info.targetActor.actorId;
|
|
45
45
|
let accepted = false;
|
|
46
46
|
let acceptedActor: ZLinkActor | undefined;
|
|
@@ -51,7 +51,7 @@ export class ZLinkSpotNativeActorJoinAdmission {
|
|
|
51
51
|
throw new Error('Remote actor join requires the two-phase routed transfer protocol.');
|
|
52
52
|
}
|
|
53
53
|
const actor = this.options.resolveActor(actorId);
|
|
54
|
-
if (actor !== undefined) {
|
|
54
|
+
if (!rejectClosing && actor !== undefined) {
|
|
55
55
|
const target = this.options.getTarget();
|
|
56
56
|
const joinRequest = request.message;
|
|
57
57
|
const joinPayload = wrapFrameworkPayloadMessage(
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { ZLinkListenerRecords } from '../foundation/listener-records';
|
|
1
2
|
import {
|
|
2
3
|
ZLinkFrameworkInternalErrorKind,
|
|
3
4
|
createInternalFrameworkException
|
|
@@ -88,6 +89,7 @@ import type {
|
|
|
88
89
|
ZLinkSpotBoundSessionRuntime
|
|
89
90
|
} from './spot-runtime-ports';
|
|
90
91
|
import { createAbortError } from '../abort';
|
|
92
|
+
import type { ZLinkActivationConcurrency } from '../activation-admission';
|
|
91
93
|
import type { ServiceMessageFollowRecord } from '../foundation/service-stateful-wire-codec';
|
|
92
94
|
import {
|
|
93
95
|
ApplicationJobQueue,
|
|
@@ -101,6 +103,7 @@ const ZLINK_SEND_DONT_WAIT = 1;
|
|
|
101
103
|
const EMPTY_SPOT_METADATA: ReadonlyMap<string, string> = new Map();
|
|
102
104
|
|
|
103
105
|
export interface ZLinkSpotNodeRuntimeManagerOptions {
|
|
106
|
+
readonly listenerRecords?: ZLinkListenerRecords;
|
|
104
107
|
readonly registration: ZLinkFrameworkRegistration;
|
|
105
108
|
readonly primaryMeshName?: string;
|
|
106
109
|
readonly backendAdapterFactory: ZLinkBackendAdapterFactory;
|
|
@@ -130,10 +133,8 @@ export interface ZLinkSpotNodeRuntimeManagerOptions {
|
|
|
130
133
|
record: ReceiveRecord
|
|
131
134
|
) => void | Promise<void>;
|
|
132
135
|
readonly messageFollowReceiver?: (record: ServiceMessageFollowRecord) => void;
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
readonly limit: number;
|
|
136
|
-
};
|
|
136
|
+
/** MeshNode §5.1 activation admission record; the descriptor projects it for placement. */
|
|
137
|
+
readonly activationConcurrency?: (meshName: string) => ZLinkActivationConcurrency;
|
|
137
138
|
}
|
|
138
139
|
|
|
139
140
|
export class ZLinkSpotNodeRuntimeManager {
|
|
@@ -168,10 +169,6 @@ export class ZLinkSpotNodeRuntimeManager {
|
|
|
168
169
|
new ApplicationJobQueue(resolveApplicationJobQueueConfiguration());
|
|
169
170
|
}
|
|
170
171
|
|
|
171
|
-
createReceived() {
|
|
172
|
-
return this.options.backendAdapterFactory.createReceived();
|
|
173
|
-
}
|
|
174
|
-
|
|
175
172
|
createTopicMessage() {
|
|
176
173
|
return this.options.backendAdapterFactory.createTopicMessage();
|
|
177
174
|
}
|
|
@@ -378,6 +375,10 @@ export class ZLinkSpotNodeRuntimeManager {
|
|
|
378
375
|
this.meshNodes.set(spotNodeName, node);
|
|
379
376
|
this.meshPumps.set(spotNodeName, pump);
|
|
380
377
|
this.meshCompletions.set(spotNodeName, completions);
|
|
378
|
+
const listenerEndpoint = node.status().localEndpoint;
|
|
379
|
+
if (listenerEndpoint.length > 0) {
|
|
380
|
+
this.options.listenerRecords?.record('routeMesh', spotNodeName, listenerEndpoint);
|
|
381
|
+
}
|
|
381
382
|
} catch (error) {
|
|
382
383
|
this.entryActivations.delete(spotNodeName);
|
|
383
384
|
this.publishers.get(spotNodeName)?.close();
|
|
@@ -488,15 +489,9 @@ export class ZLinkSpotNodeRuntimeManager {
|
|
|
488
489
|
};
|
|
489
490
|
})
|
|
490
491
|
},
|
|
491
|
-
activationConcurrency: {
|
|
492
|
-
active:
|
|
493
|
-
|
|
494
|
-
current?.activationConcurrency.active ??
|
|
495
|
-
0,
|
|
496
|
-
limit:
|
|
497
|
-
this.options.instanceActivationConcurrencyProvider?.(meshName).limit ??
|
|
498
|
-
registration.activationConcurrencyLimit ??
|
|
499
|
-
128
|
|
492
|
+
activationConcurrency: this.options.activationConcurrency?.(meshName) ?? {
|
|
493
|
+
active: 0,
|
|
494
|
+
limit: registration.activationConcurrencyLimit ?? 128
|
|
500
495
|
},
|
|
501
496
|
channelWeights: Object.fromEntries(
|
|
502
497
|
this.serverChannels(meshName).map(([channelName, channel]) => [
|
|
@@ -975,7 +970,6 @@ export class ZLinkSpotNodeRuntimeManager {
|
|
|
975
970
|
entrySpotType: spotNode.entrySpotType,
|
|
976
971
|
nativeSpot: node.entrySpot() as never,
|
|
977
972
|
nativeNode: node as unknown as ZLinkBackendSpotNode,
|
|
978
|
-
createReceived: () => this.options.backendAdapterFactory.createReceived(),
|
|
979
973
|
createTopicMessage: () => this.options.backendAdapterFactory.createTopicMessage(),
|
|
980
974
|
nodeRid: String(node.status().routingId),
|
|
981
975
|
spotNodeName,
|
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
import {
|
|
2
2
|
ZLinkFrameworkInternalErrorKind,
|
|
3
|
-
createInternalFrameworkException
|
|
4
|
-
internalFrameworkErrorKind
|
|
3
|
+
createInternalFrameworkException
|
|
5
4
|
} from '../framework-errors-internal';
|
|
6
|
-
import {
|
|
7
|
-
import { ZLinkFrameworkException } from '../../contracts/Errors';
|
|
5
|
+
import { ZLinkSpotKind } from '../../contracts';
|
|
8
6
|
import type {
|
|
9
7
|
RoutingId,
|
|
10
8
|
ZLinkChannelClient,
|
|
@@ -31,12 +29,7 @@ import { requireZLinkYieldTurn } from '../execution';
|
|
|
31
29
|
import { resolveFrameworkPacketName } from '../messaging/packet-name';
|
|
32
30
|
import type { ZLinkSpotRouteTarget } from './spot-routing-internal';
|
|
33
31
|
import { ZLinkSpotSerialTurnExecutor } from './spot-serial-turn-executor';
|
|
34
|
-
import {
|
|
35
|
-
resolveSpotHandle,
|
|
36
|
-
refreshSpotHandle,
|
|
37
|
-
type SpotHandle,
|
|
38
|
-
type ResolvedSpotHandle
|
|
39
|
-
} from './spot-handle';
|
|
32
|
+
import { resolveSpotHandle, type SpotHandle, type ResolvedSpotHandle } from './spot-handle';
|
|
40
33
|
|
|
41
34
|
export interface DefaultZLinkSpotOutboundOptions {
|
|
42
35
|
readonly serial: ZLinkSpotSerialTurnExecutor;
|
|
@@ -680,29 +673,7 @@ export async function requestToSpotHandle<TReply = unknown>(
|
|
|
680
673
|
return transport.requestToSpot<TReply>(target, request, transportOptions);
|
|
681
674
|
};
|
|
682
675
|
|
|
683
|
-
|
|
684
|
-
try {
|
|
685
|
-
return await requestResolved(resolved);
|
|
686
|
-
} catch (error) {
|
|
687
|
-
if (!shouldRefreshAfterRouteDisconnect(resolved, error)) {
|
|
688
|
-
throw error;
|
|
689
|
-
}
|
|
690
|
-
let refreshed: ResolvedSpotHandle | undefined;
|
|
691
|
-
try {
|
|
692
|
-
refreshed = await refreshSpotHandle(spot, options.signal);
|
|
693
|
-
} catch {
|
|
694
|
-
throw error;
|
|
695
|
-
}
|
|
696
|
-
if (isShutdownTargetState(refreshed?.targetNodeState)) {
|
|
697
|
-
throw createInternalFrameworkException(
|
|
698
|
-
ZLinkFrameworkInternalErrorKind.RuntimeShutdown,
|
|
699
|
-
`Spot '${String(spot.spotId)}' target host is shutting down.`,
|
|
700
|
-
false,
|
|
701
|
-
error
|
|
702
|
-
);
|
|
703
|
-
}
|
|
704
|
-
throw error;
|
|
705
|
-
}
|
|
676
|
+
return requestResolved(await requireSpotRef(spot, options.signal));
|
|
706
677
|
}
|
|
707
678
|
|
|
708
679
|
async function requireSpotRef(
|
|
@@ -730,20 +701,6 @@ function spotRefToSpotRouteTarget(
|
|
|
730
701
|
};
|
|
731
702
|
}
|
|
732
703
|
|
|
733
|
-
function shouldRefreshAfterRouteDisconnect(target: ResolvedSpotHandle, error: unknown): boolean {
|
|
734
|
-
return (
|
|
735
|
-
target.targetNodeState === ZLinkFrameworkRuntimeState.Serving &&
|
|
736
|
-
error instanceof ZLinkFrameworkException &&
|
|
737
|
-
internalFrameworkErrorKind(error) === ZLinkFrameworkInternalErrorKind.RouteNotConnected
|
|
738
|
-
);
|
|
739
|
-
}
|
|
740
|
-
|
|
741
|
-
function isShutdownTargetState(state: ResolvedSpotHandle['targetNodeState']): boolean {
|
|
742
|
-
return (
|
|
743
|
-
state === ZLinkFrameworkRuntimeState.Draining || state === ZLinkFrameworkRuntimeState.Stopped
|
|
744
|
-
);
|
|
745
|
-
}
|
|
746
|
-
|
|
747
704
|
function normalizeSpotRefRoutingId(routingId: RoutingId): RoutingId {
|
|
748
705
|
return normalizeOpaqueRoutingId(routingId);
|
|
749
706
|
}
|
|
@@ -29,6 +29,10 @@ import {
|
|
|
29
29
|
import { submitRoutedActorJoinError, submitRoutedActorJoinReply } from './spot-route-replies';
|
|
30
30
|
import type { ZLinkSpotSerialTurnExecutor } from './spot-serial-turn-executor';
|
|
31
31
|
import type { ZLinkActorHandoffPacket, ZLinkActorHandoffResult } from '../actors/actor-handoff';
|
|
32
|
+
import {
|
|
33
|
+
ZLinkFrameworkInternalErrorKind,
|
|
34
|
+
createInternalFrameworkException
|
|
35
|
+
} from '../framework-errors-internal';
|
|
32
36
|
|
|
33
37
|
interface ZLinkRoutedActorAdmissionTarget {
|
|
34
38
|
onActorJoin?(actorId: string, request: ZLinkMessage): Promise<ZLinkSpotActorJoinResult>;
|
|
@@ -36,6 +40,7 @@ interface ZLinkRoutedActorAdmissionTarget {
|
|
|
36
40
|
|
|
37
41
|
interface ZLinkSpotRoutedActorAdmissionOptions {
|
|
38
42
|
readonly serial: ZLinkSpotSerialTurnExecutor;
|
|
43
|
+
readonly isSpotClosing?: () => boolean;
|
|
39
44
|
readonly getTarget: () => ZLinkRoutedActorAdmissionTarget;
|
|
40
45
|
readonly defaultAccept: boolean;
|
|
41
46
|
readonly routedActorTransferProvider?: ZLinkRoutedActorTransferProvider;
|
|
@@ -73,6 +78,21 @@ export class ZLinkSpotRoutedActorAdmission {
|
|
|
73
78
|
if (decoded === undefined) {
|
|
74
79
|
return false;
|
|
75
80
|
}
|
|
81
|
+
if (this.options.isSpotClosing?.() === true) {
|
|
82
|
+
try {
|
|
83
|
+
submitRoutedActorJoinError(
|
|
84
|
+
received,
|
|
85
|
+
decoded,
|
|
86
|
+
createInternalFrameworkException(
|
|
87
|
+
ZLinkFrameworkInternalErrorKind.RequestRejected,
|
|
88
|
+
`Actor '${decoded.actorId}' target Spot is closing.`
|
|
89
|
+
)
|
|
90
|
+
);
|
|
91
|
+
} finally {
|
|
92
|
+
this.closeDecoded(decoded);
|
|
93
|
+
}
|
|
94
|
+
return true;
|
|
95
|
+
}
|
|
76
96
|
if (decoded.phase === 'admission') {
|
|
77
97
|
await this.admitTransfer(decoded, received);
|
|
78
98
|
return true;
|
|
@@ -9,11 +9,10 @@ import type { ZLinkProviderResolver } from '../../contracts/Common/ZLinkProvider
|
|
|
9
9
|
import type { RoutingId } from '../../contracts';
|
|
10
10
|
import type { ActorRef } from '../../contracts/Common/ActorRef';
|
|
11
11
|
import type { ZLinkRemoteActorPacketTarget, ZLinkRemoteBoundSessionTarget } from '../actors';
|
|
12
|
-
import type { ZLinkBackendReceived
|
|
12
|
+
import type { ZLinkBackendReceived } from '../backend/contracts';
|
|
13
13
|
import type { ZLinkDispatchErrorReporter } from '../channels';
|
|
14
14
|
import type { ZLinkChannelEnvelopeCodecRegistry } from '../channels/channel-envelope';
|
|
15
15
|
import { decodeRemoteActorPacketRelay } from './spot-remote-route-codec';
|
|
16
|
-
import { ZLINK_RECV_DONT_WAIT } from './spot-native-flags';
|
|
17
16
|
import { ZLinkSpotActorPacketRelayDispatch } from './spot-actor-packet-relay-dispatch';
|
|
18
17
|
import type {
|
|
19
18
|
ZLinkActorPacketDelivery,
|
|
@@ -33,10 +32,9 @@ interface ZLinkRoutedFrameAdmissionTarget {
|
|
|
33
32
|
}
|
|
34
33
|
|
|
35
34
|
interface ZLinkSpotRoutedFrameDispatchOptions {
|
|
36
|
-
readonly nativeSpot: ZLinkBackendSpot;
|
|
37
|
-
readonly createReceived: () => ZLinkBackendReceived;
|
|
38
35
|
readonly nativeSpotId: string;
|
|
39
36
|
readonly serial: ZLinkSpotSerialTurnExecutor;
|
|
37
|
+
readonly isSpotClosing?: () => boolean;
|
|
40
38
|
readonly resolveActor: (actorId: string) => ZLinkActor | undefined;
|
|
41
39
|
readonly getTarget: () => ZLinkRoutedFrameAdmissionTarget & ZLinkSpot;
|
|
42
40
|
readonly defaultAccept: boolean;
|
|
@@ -86,11 +84,9 @@ interface ZLinkSpotRoutedFrameDispatchOptions {
|
|
|
86
84
|
readonly providerResolver?: ZLinkProviderResolver;
|
|
87
85
|
readonly dispatchErrors?: ZLinkDispatchErrorReporter;
|
|
88
86
|
readonly claimApplicationWork?: () => ZLinkApplicationWorkClaim;
|
|
89
|
-
readonly waitIdle: () => Promise<void>;
|
|
90
87
|
}
|
|
91
88
|
|
|
92
89
|
export class ZLinkSpotRoutedFrameDispatch {
|
|
93
|
-
private routeDraining = false;
|
|
94
90
|
private readonly packetHandlers = new Map<string, ZLinkSpotHandlerRegistration[]>();
|
|
95
91
|
private readonly routedBoundSessionDispatch: ZLinkSpotRoutedBoundSessionDispatch;
|
|
96
92
|
private readonly actorPacketRelayDispatch: ZLinkSpotActorPacketRelayDispatch;
|
|
@@ -123,6 +119,7 @@ export class ZLinkSpotRoutedFrameDispatch {
|
|
|
123
119
|
});
|
|
124
120
|
this.routedActorAdmission = new ZLinkSpotRoutedActorAdmission({
|
|
125
121
|
serial: options.serial,
|
|
122
|
+
isSpotClosing: options.isSpotClosing,
|
|
126
123
|
getTarget: options.getTarget,
|
|
127
124
|
defaultAccept: options.defaultAccept,
|
|
128
125
|
routedActorTransferProvider: options.routedActorTransferProvider,
|
|
@@ -144,61 +141,6 @@ export class ZLinkSpotRoutedFrameDispatch {
|
|
|
144
141
|
}
|
|
145
142
|
}
|
|
146
143
|
|
|
147
|
-
async drain(
|
|
148
|
-
received: ZLinkBackendReceived | undefined = undefined,
|
|
149
|
-
retryDeadlineMs = performance.now()
|
|
150
|
-
): Promise<void> {
|
|
151
|
-
if (this.routeDraining) {
|
|
152
|
-
if (received !== undefined) {
|
|
153
|
-
try {
|
|
154
|
-
await this.dispatch(received);
|
|
155
|
-
} finally {
|
|
156
|
-
received.close();
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
return;
|
|
160
|
-
}
|
|
161
|
-
this.routeDraining = true;
|
|
162
|
-
try {
|
|
163
|
-
if (received !== undefined) {
|
|
164
|
-
try {
|
|
165
|
-
await this.dispatch(received);
|
|
166
|
-
} finally {
|
|
167
|
-
received.close();
|
|
168
|
-
}
|
|
169
|
-
received = undefined;
|
|
170
|
-
}
|
|
171
|
-
for (;;) {
|
|
172
|
-
received ??= this.options.createReceived();
|
|
173
|
-
try {
|
|
174
|
-
if (!this.options.nativeSpot.recvRoute(received, ZLINK_RECV_DONT_WAIT)) {
|
|
175
|
-
received.close();
|
|
176
|
-
await this.options.waitIdle();
|
|
177
|
-
return;
|
|
178
|
-
}
|
|
179
|
-
} catch (error) {
|
|
180
|
-
if (isRouteRecvRetryable(error)) {
|
|
181
|
-
closeReceivedQuietly(received);
|
|
182
|
-
if (performance.now() < retryDeadlineMs) {
|
|
183
|
-
setTimeout(() => void this.drain(undefined, retryDeadlineMs), 10);
|
|
184
|
-
}
|
|
185
|
-
return;
|
|
186
|
-
}
|
|
187
|
-
received.close();
|
|
188
|
-
throw error;
|
|
189
|
-
}
|
|
190
|
-
try {
|
|
191
|
-
await this.dispatch(received);
|
|
192
|
-
} finally {
|
|
193
|
-
received.close();
|
|
194
|
-
}
|
|
195
|
-
received = this.options.createReceived();
|
|
196
|
-
}
|
|
197
|
-
} finally {
|
|
198
|
-
this.routeDraining = false;
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
|
|
202
144
|
async dispatchFromEvent(received: ZLinkBackendReceived): Promise<void> {
|
|
203
145
|
try {
|
|
204
146
|
await this.dispatch(received);
|
|
@@ -234,20 +176,8 @@ export class ZLinkSpotRoutedFrameDispatch {
|
|
|
234
176
|
if (await this.routePacketDispatch.dispatch(received)) {
|
|
235
177
|
return;
|
|
236
178
|
}
|
|
237
|
-
await this.
|
|
179
|
+
await this.options.serial.executeLifecycleOperation(() =>
|
|
180
|
+
this.routedActorAdmission.admit(received)
|
|
181
|
+
);
|
|
238
182
|
}
|
|
239
183
|
}
|
|
240
|
-
|
|
241
|
-
function isRouteRecvRetryable(error: unknown): boolean {
|
|
242
|
-
return (
|
|
243
|
-
typeof error === 'object' &&
|
|
244
|
-
error !== null &&
|
|
245
|
-
[201, 202, 204].includes(Number((error as { result?: unknown }).result))
|
|
246
|
-
);
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
function closeReceivedQuietly(received: ZLinkBackendReceived): void {
|
|
250
|
-
try {
|
|
251
|
-
received.close();
|
|
252
|
-
} catch {}
|
|
253
|
-
}
|
|
@@ -10,7 +10,7 @@ import type { ZLinkMessageFollowOrigin } from '../foundation/service-runtime-con
|
|
|
10
10
|
import type {
|
|
11
11
|
ZLinkRemoteActorPacketTarget,
|
|
12
12
|
ZLinkRemoteBoundSessionTarget,
|
|
13
|
-
|
|
13
|
+
ZLinkDeferredJoinCompletion
|
|
14
14
|
} from '../actors';
|
|
15
15
|
import type { ZLinkActorHandoffDispatch } from '../actors/actor-handoff';
|
|
16
16
|
import type { ZLinkActorResponseOptions } from './spot-actor-packet-dispatch';
|
|
@@ -44,26 +44,15 @@ export interface ZLinkSpotActorTransferRuntime {
|
|
|
44
44
|
operationId: ZLinkActorJoinOperationId,
|
|
45
45
|
actorRef: ActorRef,
|
|
46
46
|
rawReply: Uint8Array,
|
|
47
|
-
replyContentType?: string
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
discardDeferredJoinAccepted(
|
|
52
|
-
root: ZLinkDeferredJoinAcceptedRoot,
|
|
53
|
-
signal?: AbortSignal
|
|
54
|
-
): Promise<void>;
|
|
55
|
-
markDeferredJoinAcceptedCommitted(
|
|
56
|
-
root: ZLinkDeferredJoinAcceptedRoot,
|
|
57
|
-
actorRef: ActorRef,
|
|
58
|
-
signal?: AbortSignal
|
|
59
|
-
): Promise<ZLinkDeferredJoinAcceptedRoot>;
|
|
60
|
-
commitAndDeliverDeferredJoinAccepted(
|
|
61
|
-
root: ZLinkDeferredJoinAcceptedRoot,
|
|
47
|
+
replyContentType?: string
|
|
48
|
+
): ZLinkDeferredJoinCompletion;
|
|
49
|
+
deliverDeferredJoinAccepted(
|
|
50
|
+
completion: ZLinkDeferredJoinCompletion,
|
|
62
51
|
actor: ZLinkActor,
|
|
63
52
|
actorRef: ActorRef,
|
|
64
53
|
submitMailbox: <T>(operation: () => Promise<T>) => Promise<T>,
|
|
65
54
|
signal?: AbortSignal
|
|
66
|
-
): Promise<
|
|
55
|
+
): Promise<void>;
|
|
67
56
|
getOrCreateRoutedActor(
|
|
68
57
|
actorId: string,
|
|
69
58
|
actorType: string,
|
|
@@ -107,6 +107,15 @@ export class ZLinkSpotSerialExecutor {
|
|
|
107
107
|
* ownership turn. Already accepted work remains drainable.
|
|
108
108
|
*/
|
|
109
109
|
close(): Promise<void> {
|
|
110
|
+
const children = this.closeChildren();
|
|
111
|
+
return Promise.all([children, this.spotSerial.close()]).then(() => undefined);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Closes the Actor and timer queues. The Spot queue stays open for the Spot
|
|
116
|
+
* Close lifecycle item that owns it; that Close closes it when it finishes.
|
|
117
|
+
*/
|
|
118
|
+
closeChildren(): Promise<void> {
|
|
110
119
|
if (this.closePromise !== undefined) return this.closePromise;
|
|
111
120
|
this.closing = true;
|
|
112
121
|
const childSerials = [...this.actorSerials.values(), ...this.timerSerials.values()];
|
|
@@ -115,7 +124,6 @@ export class ZLinkSpotSerialExecutor {
|
|
|
115
124
|
this.timerSerials.clear();
|
|
116
125
|
this.actorExecutors.clear();
|
|
117
126
|
this.closePromise = Promise.all([
|
|
118
|
-
this.spotSerial.close(),
|
|
119
127
|
...childSerials.map((serial) => serial.close()),
|
|
120
128
|
...actorExecutors.map((executor) => executor.close())
|
|
121
129
|
]).then(() => undefined);
|