@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
|
@@ -6,7 +6,6 @@ import type { RoutingId, Type, ZLinkSpot, ZLinkSpotInfo } from '../../contracts'
|
|
|
6
6
|
import type { ZLinkLocalSpotCreateResult } from './spot-manager-internal-contracts';
|
|
7
7
|
import { ZLinkSpotCreateState, ZLinkSpotCloseReason } from '../../contracts';
|
|
8
8
|
import type { ZLinkSpotActivation } from './spot-activation-state';
|
|
9
|
-
import { ZLinkSpotCloseOccupiedError } from './spot-activation-state';
|
|
10
9
|
import { ZLinkConfigurationException } from '../configuration';
|
|
11
10
|
import { createAbortError } from '../abort';
|
|
12
11
|
import { ZLinkSpotLifecycleMetrics } from './spot-lifecycle-metrics';
|
|
@@ -40,7 +39,11 @@ export class ZLinkSpotActivationRegistry {
|
|
|
40
39
|
private readonly lifecycleMetrics: ZLinkSpotLifecycleMetrics;
|
|
41
40
|
private activeScan: Iterator<ZLinkSpotActivation> | undefined;
|
|
42
41
|
|
|
43
|
-
constructor(
|
|
42
|
+
constructor(
|
|
43
|
+
metrics?: import('../diagnostics').ZLinkRuntimeMetrics,
|
|
44
|
+
private readonly isCommittedClose: (meshName: string, spotId: RoutingId) => boolean = () =>
|
|
45
|
+
false
|
|
46
|
+
) {
|
|
44
47
|
this.lifecycleMetrics = new ZLinkSpotLifecycleMetrics(metrics);
|
|
45
48
|
}
|
|
46
49
|
|
|
@@ -55,7 +58,10 @@ export class ZLinkSpotActivationRegistry {
|
|
|
55
58
|
|
|
56
59
|
resolve(meshName: string, spotId: RoutingId): ZLinkSpotActivation | undefined {
|
|
57
60
|
const key = spotActivationKey(meshName, spotId);
|
|
58
|
-
return this.
|
|
61
|
+
return this.isCommittedClose(meshName, spotId) ||
|
|
62
|
+
this.closing.has(key) ||
|
|
63
|
+
this.failedClose.has(key) ||
|
|
64
|
+
this.staged.has(key)
|
|
59
65
|
? undefined
|
|
60
66
|
: this.activations.get(key);
|
|
61
67
|
}
|
|
@@ -64,6 +70,7 @@ export class ZLinkSpotActivationRegistry {
|
|
|
64
70
|
const matches = [...this.activations.values()].filter(
|
|
65
71
|
(activation) =>
|
|
66
72
|
String(activation.spotId) === String(spotId) &&
|
|
73
|
+
!this.isCommittedClose(activation.meshName, activation.spotId) &&
|
|
67
74
|
!this.staged.has(spotActivationKey(activation.meshName, activation.spotId)) &&
|
|
68
75
|
!this.closing.has(spotActivationKey(activation.meshName, activation.spotId)) &&
|
|
69
76
|
!this.failedClose.has(spotActivationKey(activation.meshName, activation.spotId))
|
|
@@ -74,6 +81,7 @@ export class ZLinkSpotActivationRegistry {
|
|
|
74
81
|
has(meshName: string, spotId: RoutingId): boolean {
|
|
75
82
|
const key = spotActivationKey(meshName, spotId);
|
|
76
83
|
return (
|
|
84
|
+
!this.isCommittedClose(meshName, spotId) &&
|
|
77
85
|
!this.staged.has(key) &&
|
|
78
86
|
!this.closing.has(key) &&
|
|
79
87
|
!this.failedClose.has(key) &&
|
|
@@ -81,22 +89,17 @@ export class ZLinkSpotActivationRegistry {
|
|
|
81
89
|
);
|
|
82
90
|
}
|
|
83
91
|
|
|
84
|
-
canClose(meshName: string, spotId: RoutingId): boolean {
|
|
85
|
-
const key = spotActivationKey(meshName, spotId);
|
|
86
|
-
return (
|
|
87
|
-
!this.staged.has(key) &&
|
|
88
|
-
!this.closing.has(key) &&
|
|
89
|
-
!this.failedClose.has(key) &&
|
|
90
|
-
this.activations.get(key)?.canClose() === true
|
|
91
|
-
);
|
|
92
|
-
}
|
|
93
|
-
|
|
94
92
|
list(meshName: string): readonly ZLinkSpotInfo[] {
|
|
95
93
|
return [...this.activations.values()]
|
|
96
94
|
.filter((activation) => {
|
|
97
95
|
if (activation.meshName !== meshName) return false;
|
|
98
96
|
const key = spotActivationKey(activation.meshName, activation.spotId);
|
|
99
|
-
return
|
|
97
|
+
return (
|
|
98
|
+
!this.isCommittedClose(meshName, activation.spotId) &&
|
|
99
|
+
!this.staged.has(key) &&
|
|
100
|
+
!this.closing.has(key) &&
|
|
101
|
+
!this.failedClose.has(key)
|
|
102
|
+
);
|
|
100
103
|
})
|
|
101
104
|
.map((activation) => String(activation.spotId))
|
|
102
105
|
.sort((left, right) => left.localeCompare(right))
|
|
@@ -107,6 +110,18 @@ export class ZLinkSpotActivationRegistry {
|
|
|
107
110
|
return [...this.activations.values()];
|
|
108
111
|
}
|
|
109
112
|
|
|
113
|
+
activationForClose(meshName: string, spotId: RoutingId): ZLinkSpotActivation | undefined {
|
|
114
|
+
return this.activations.get(spotActivationKey(meshName, spotId));
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
finishClose(meshName: string, spotId: RoutingId): void {
|
|
118
|
+
const key = spotActivationKey(meshName, spotId);
|
|
119
|
+
if (this.activations.delete(key)) this.lifecycleMetrics.closed('user');
|
|
120
|
+
this.staged.delete(key);
|
|
121
|
+
this.failedClose.delete(key);
|
|
122
|
+
this.resolveEmptyWaiters();
|
|
123
|
+
}
|
|
124
|
+
|
|
110
125
|
hasActiveActivations(): boolean {
|
|
111
126
|
return this.activations.size > 0;
|
|
112
127
|
}
|
|
@@ -215,30 +230,14 @@ export class ZLinkSpotActivationRegistry {
|
|
|
215
230
|
}
|
|
216
231
|
const operation = {} as ZLinkSpotCloseOperation;
|
|
217
232
|
let completed = false;
|
|
218
|
-
let occupiedAfterQuiescence = false;
|
|
219
233
|
const ready = Promise.resolve()
|
|
220
234
|
.then(() => close(activation))
|
|
221
235
|
.then(() => {
|
|
222
236
|
completed = true;
|
|
223
237
|
})
|
|
224
|
-
.catch((error: unknown) => {
|
|
225
|
-
// The seal's post-quiescence recheck (spot-activation.ts
|
|
226
|
-
// closeAfterSeal) found a new join and released the seal instead of
|
|
227
|
-
// closing. The activation is already back to normal operation, so
|
|
228
|
-
// this is a "did not close" outcome, not a close failure.
|
|
229
|
-
if (error instanceof ZLinkSpotCloseOccupiedError) {
|
|
230
|
-
occupiedAfterQuiescence = true;
|
|
231
|
-
return;
|
|
232
|
-
}
|
|
233
|
-
throw error;
|
|
234
|
-
})
|
|
235
238
|
.finally(() => {
|
|
236
239
|
if (this.closing.get(key) === operation) {
|
|
237
240
|
this.closing.delete(key);
|
|
238
|
-
if (occupiedAfterQuiescence) {
|
|
239
|
-
this.resolveEmptyWaiters();
|
|
240
|
-
return;
|
|
241
|
-
}
|
|
242
241
|
if (completed || resourcesReleased(activation)) {
|
|
243
242
|
this.activations.delete(key);
|
|
244
243
|
this.staged.delete(key);
|
|
@@ -250,7 +249,7 @@ export class ZLinkSpotActivationRegistry {
|
|
|
250
249
|
this.resolveEmptyWaiters();
|
|
251
250
|
}
|
|
252
251
|
})
|
|
253
|
-
.then(() =>
|
|
252
|
+
.then(() => true);
|
|
254
253
|
Object.assign(operation, { activation, ready, started: true });
|
|
255
254
|
this.closing.set(key, operation);
|
|
256
255
|
return operation;
|
|
@@ -263,6 +262,17 @@ export class ZLinkSpotActivationRegistry {
|
|
|
263
262
|
create: () => Promise<ZLinkLocalSpotCreateResult>
|
|
264
263
|
): ZLinkSpotActivationOperation {
|
|
265
264
|
const key = spotActivationKey(meshName, spotId);
|
|
265
|
+
if (this.isCommittedClose(meshName, spotId)) {
|
|
266
|
+
return {
|
|
267
|
+
owner: false,
|
|
268
|
+
ready: Promise.reject(
|
|
269
|
+
createInternalFrameworkException(
|
|
270
|
+
ZLinkFrameworkInternalErrorKind.RequestRejected,
|
|
271
|
+
`Spot '${String(spotId)}' is Closing.`
|
|
272
|
+
)
|
|
273
|
+
)
|
|
274
|
+
};
|
|
275
|
+
}
|
|
266
276
|
const closing = this.closing.get(key);
|
|
267
277
|
if (closing !== undefined) {
|
|
268
278
|
return {
|
|
@@ -25,6 +25,7 @@ import type { ZLinkTimerRelocationState } from './spot-timer';
|
|
|
25
25
|
export type ZLinkSpotActivationDomain =
|
|
26
26
|
| {
|
|
27
27
|
readonly kind: 'user';
|
|
28
|
+
readonly objectGeneration?: bigint;
|
|
28
29
|
readonly executionMode: ZLinkUserSpotExecutionMode;
|
|
29
30
|
readonly relocationCoordinationMode: ZLinkSpotRelocationCoordinationMode;
|
|
30
31
|
}
|
|
@@ -56,19 +57,6 @@ export interface ZLinkSpotRelocationCapture {
|
|
|
56
57
|
readonly timers: readonly ZLinkTimerRelocationState[];
|
|
57
58
|
}
|
|
58
59
|
|
|
59
|
-
/**
|
|
60
|
-
* Internal signal that a close seal reached quiescence but the activation
|
|
61
|
-
* became occupied again while it waited (an actor join queued ahead of the
|
|
62
|
-
* close finished after the eager pre-seal occupancy check). This is not a
|
|
63
|
-
* close failure: the seal is released, the Spot stays open, and the caller
|
|
64
|
-
* reports `close(...)` as `false` instead of throwing.
|
|
65
|
-
*/
|
|
66
|
-
export class ZLinkSpotCloseOccupiedError extends Error {
|
|
67
|
-
constructor(spotId: RoutingId) {
|
|
68
|
-
super(`Spot '${String(spotId)}' became occupied while its close seal reached quiescence.`);
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
|
|
72
60
|
export class ZLinkSpotActivation {
|
|
73
61
|
readonly meshName: string;
|
|
74
62
|
readonly spotId: RoutingId;
|
|
@@ -126,7 +114,7 @@ export class ZLinkSpotActivation {
|
|
|
126
114
|
}
|
|
127
115
|
|
|
128
116
|
get objectGeneration(): bigint | undefined {
|
|
129
|
-
return this.domain.
|
|
117
|
+
return this.domain.objectGeneration;
|
|
130
118
|
}
|
|
131
119
|
|
|
132
120
|
get executionMode(): ZLinkUserSpotExecutionMode {
|
|
@@ -274,8 +262,8 @@ export class ZLinkSpotActivation {
|
|
|
274
262
|
return this.serialExecutor.admitActorDurablePrefix(actorId, records);
|
|
275
263
|
}
|
|
276
264
|
|
|
277
|
-
sealExecution(): ZLinkExecutionBarrierSeal {
|
|
278
|
-
return this.executionBarrier.seal();
|
|
265
|
+
sealExecution(drainsYieldedTurns = false): ZLinkExecutionBarrierSeal {
|
|
266
|
+
return this.executionBarrier.seal(drainsYieldedTurns);
|
|
279
267
|
}
|
|
280
268
|
|
|
281
269
|
waitForExecutionQuiescence(seal: ZLinkExecutionBarrierSeal, signal?: AbortSignal): Promise<void> {
|
|
@@ -31,8 +31,11 @@ import type { Message } from '../../contracts/Common/Message';
|
|
|
31
31
|
import type { ZLinkMessageFollowOrigin } from '../foundation/service-runtime-contracts';
|
|
32
32
|
import { throwIfAborted } from '../abort';
|
|
33
33
|
import { ZLinkConfigurationException } from '../configuration';
|
|
34
|
+
import {
|
|
35
|
+
ZLinkFrameworkInternalErrorKind,
|
|
36
|
+
createInternalFrameworkException
|
|
37
|
+
} from '../framework-errors-internal';
|
|
34
38
|
import type {
|
|
35
|
-
ZLinkBackendReceived,
|
|
36
39
|
ZLinkBackendSpot,
|
|
37
40
|
ZLinkBackendSpotNode,
|
|
38
41
|
ZLinkBackendTopicMessage
|
|
@@ -77,7 +80,7 @@ import type {
|
|
|
77
80
|
} from './spot-actor-join-dispatch';
|
|
78
81
|
import { ZLinkSpotActorAdmissionCoordinator } from './spot-actor-admission-coordinator';
|
|
79
82
|
import type { ZLinkRouteToActorJoinPrewarm } from './spot-actor-packet-dispatch';
|
|
80
|
-
import { ZLinkSpotActivation
|
|
83
|
+
import { ZLinkSpotActivation } from './spot-activation-state';
|
|
81
84
|
import type { ZLinkSpotLocationClaim } from './spot-location-claim';
|
|
82
85
|
import type {
|
|
83
86
|
ZLinkSpotActorHandoffRuntime,
|
|
@@ -114,6 +117,7 @@ export interface ZLinkSpotActivationLifecycleOptions {
|
|
|
114
117
|
readonly channelMeshNameForChannel?: (channelName: string) => string | undefined;
|
|
115
118
|
readonly providerResolver?: ZLinkProviderResolver;
|
|
116
119
|
readonly dispatchErrors?: ZLinkDispatchErrorReporter;
|
|
120
|
+
readonly closeErrorSink?: import('../diagnostics/dispatch-error-port').ZLinkDispatchErrorSink;
|
|
117
121
|
readonly runtimeEventPublisher?: ZLinkRuntimeEventPublisher;
|
|
118
122
|
readonly workerRuntime: ZLinkWorkerRuntime;
|
|
119
123
|
readonly messageSerializers?: ReadonlyMap<string, ZLinkMessageSerializer>;
|
|
@@ -123,7 +127,6 @@ export interface ZLinkSpotActivationLifecycleOptions {
|
|
|
123
127
|
spotId: RoutingId,
|
|
124
128
|
authority?: ZLinkNativeSpotAuthority
|
|
125
129
|
) => ZLinkBackendSpot | undefined;
|
|
126
|
-
readonly createReceived?: () => ZLinkBackendReceived;
|
|
127
130
|
readonly createTopicMessage?: () => ZLinkBackendTopicMessage;
|
|
128
131
|
readonly nativeSpotNodeProvider?: (meshName: string) => ZLinkBackendSpotNode | undefined;
|
|
129
132
|
readonly actorResolver?: (actorId: string) => ZLinkActor | undefined;
|
|
@@ -139,12 +142,13 @@ export interface ZLinkSpotActivationLifecycleOptions {
|
|
|
139
142
|
signal?: AbortSignal,
|
|
140
143
|
meshName?: string
|
|
141
144
|
) => Promise<void>;
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
145
|
+
/** Starts a context Close request after its calling turn has ended. */
|
|
146
|
+
readonly requestContextClose: (
|
|
147
|
+
activation: ZLinkSpotActivation,
|
|
148
|
+
objectGeneration: bigint,
|
|
149
|
+
signal?: AbortSignal
|
|
147
150
|
) => Promise<boolean>;
|
|
151
|
+
readonly isSpotClosing: (activation: ZLinkSpotActivation) => boolean;
|
|
148
152
|
readonly registerActivation: (activation: ZLinkSpotActivation) => void;
|
|
149
153
|
readonly routeToActorJoinPrewarm?: ZLinkRouteToActorJoinPrewarm;
|
|
150
154
|
readonly releaseLocation: (
|
|
@@ -173,10 +177,12 @@ export class ZLinkSpotActivationLifecycle {
|
|
|
173
177
|
{
|
|
174
178
|
closingAttempted: boolean;
|
|
175
179
|
timersDisposed: boolean;
|
|
180
|
+
serialDisposed: boolean;
|
|
176
181
|
handlersDisposed: boolean;
|
|
182
|
+
actorDispatchDisposed: boolean;
|
|
177
183
|
nativeDisposed: boolean;
|
|
178
184
|
locationReleased: boolean;
|
|
179
|
-
inFlight?: Promise<
|
|
185
|
+
inFlight?: Promise<unknown>;
|
|
180
186
|
}
|
|
181
187
|
>();
|
|
182
188
|
|
|
@@ -259,7 +265,7 @@ export class ZLinkSpotActivationLifecycle {
|
|
|
259
265
|
providerResolver: this.options.providerResolver,
|
|
260
266
|
runtimeEventPublisher: this.options.runtimeEventPublisher,
|
|
261
267
|
workerRuntime: this.options.workerRuntime,
|
|
262
|
-
close: this.contextClose(
|
|
268
|
+
close: this.contextClose(objectGeneration, () => activation)
|
|
263
269
|
};
|
|
264
270
|
const context =
|
|
265
271
|
objectKind === 'user_spot'
|
|
@@ -314,6 +320,7 @@ export class ZLinkSpotActivationLifecycle {
|
|
|
314
320
|
objectKind === 'user_spot'
|
|
315
321
|
? {
|
|
316
322
|
kind: 'user',
|
|
323
|
+
objectGeneration,
|
|
317
324
|
executionMode,
|
|
318
325
|
relocationCoordinationMode:
|
|
319
326
|
this.options.userSpotRelocationCoordinationMode?.(
|
|
@@ -398,7 +405,7 @@ export class ZLinkSpotActivationLifecycle {
|
|
|
398
405
|
providerResolver: this.options.providerResolver,
|
|
399
406
|
runtimeEventPublisher: this.options.runtimeEventPublisher,
|
|
400
407
|
workerRuntime: this.options.workerRuntime,
|
|
401
|
-
close: this.contextClose(
|
|
408
|
+
close: this.contextClose(objectGeneration, () => activation)
|
|
402
409
|
});
|
|
403
410
|
instance = await createFreshProviderInstance(
|
|
404
411
|
implementation,
|
|
@@ -487,16 +494,6 @@ export class ZLinkSpotActivationLifecycle {
|
|
|
487
494
|
}
|
|
488
495
|
}
|
|
489
496
|
|
|
490
|
-
resourcesReleased(activation: ZLinkSpotActivation): boolean {
|
|
491
|
-
const state = this.cleanupStates.get(activation);
|
|
492
|
-
return (
|
|
493
|
-
state?.timersDisposed === true &&
|
|
494
|
-
state.handlersDisposed === true &&
|
|
495
|
-
state.nativeDisposed === true &&
|
|
496
|
-
state.locationReleased === true
|
|
497
|
-
);
|
|
498
|
-
}
|
|
499
|
-
|
|
500
497
|
async create<TSpot extends ZLinkSpot>(
|
|
501
498
|
meshName: string,
|
|
502
499
|
spotType: Type<TSpot>,
|
|
@@ -607,7 +604,7 @@ export class ZLinkSpotActivationLifecycle {
|
|
|
607
604
|
ensureOperationAllowed: () => activation?.ensureContextOperationAllowed(),
|
|
608
605
|
leaveActor: (actor, contextSignal) =>
|
|
609
606
|
this.options.leaveActor(spotId, actor, contextSignal, meshName),
|
|
610
|
-
close: this.contextClose(
|
|
607
|
+
close: this.contextClose(spotGeneration, () => activation)
|
|
611
608
|
});
|
|
612
609
|
try {
|
|
613
610
|
spot = await createFreshProviderInstance(spotType, this.options.providerResolver, context);
|
|
@@ -624,6 +621,7 @@ export class ZLinkSpotActivationLifecycle {
|
|
|
624
621
|
spotId,
|
|
625
622
|
domain: {
|
|
626
623
|
kind: 'user',
|
|
624
|
+
objectGeneration: spotGeneration,
|
|
627
625
|
executionMode,
|
|
628
626
|
relocationCoordinationMode:
|
|
629
627
|
this.options.userSpotRelocationCoordinationMode?.(meshName, spotType) ??
|
|
@@ -738,7 +736,7 @@ export class ZLinkSpotActivationLifecycle {
|
|
|
738
736
|
ensureOperationAllowed: () => activation?.ensureContextOperationAllowed(),
|
|
739
737
|
leaveActor: (actor, contextSignal) =>
|
|
740
738
|
this.options.leaveActor(spotId, actor, contextSignal, meshName),
|
|
741
|
-
close: this.contextClose(
|
|
739
|
+
close: this.contextClose(objectGeneration, () => activation)
|
|
742
740
|
});
|
|
743
741
|
spot = await createFreshProviderInstance(spotType, this.options.providerResolver, context);
|
|
744
742
|
Object.defineProperty(spot, 'context', {
|
|
@@ -751,6 +749,7 @@ export class ZLinkSpotActivationLifecycle {
|
|
|
751
749
|
spotId,
|
|
752
750
|
domain: {
|
|
753
751
|
kind: 'user',
|
|
752
|
+
objectGeneration,
|
|
754
753
|
executionMode,
|
|
755
754
|
relocationCoordinationMode:
|
|
756
755
|
this.options.userSpotRelocationCoordinationMode?.(meshName, spotType) ??
|
|
@@ -777,47 +776,25 @@ export class ZLinkSpotActivationLifecycle {
|
|
|
777
776
|
}
|
|
778
777
|
|
|
779
778
|
private contextClose(
|
|
780
|
-
|
|
781
|
-
spotId: RoutingId,
|
|
779
|
+
objectGeneration: bigint,
|
|
782
780
|
activationProvider: () => ZLinkSpotActivation | undefined
|
|
783
781
|
): (signal?: AbortSignal) => Promise<boolean> {
|
|
784
|
-
return
|
|
782
|
+
return (signal) => {
|
|
785
783
|
const activation = activationProvider();
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
activation.requestClose();
|
|
791
|
-
const retry = activation.serial.post(() =>
|
|
792
|
-
this.options.closeSpot(meshName, spotId, signal)
|
|
784
|
+
if (activation === undefined) {
|
|
785
|
+
throw createInternalFrameworkException(
|
|
786
|
+
ZLinkFrameworkInternalErrorKind.InvalidOperation,
|
|
787
|
+
'Spot context Close requires its active generation.'
|
|
793
788
|
);
|
|
794
|
-
this.options.detachedTaskRunner?.runDetached(`spot close ${String(spotId)}`, async () => {
|
|
795
|
-
await retry;
|
|
796
|
-
});
|
|
797
|
-
if (this.options.detachedTaskRunner === undefined) {
|
|
798
|
-
void retry.catch(() => undefined);
|
|
799
|
-
}
|
|
800
|
-
return true;
|
|
801
789
|
}
|
|
802
|
-
return
|
|
790
|
+
return this.options.requestContextClose(activation, objectGeneration, signal);
|
|
803
791
|
};
|
|
804
792
|
}
|
|
805
793
|
|
|
806
|
-
async
|
|
807
|
-
activation: ZLinkSpotActivation,
|
|
808
|
-
signal?: AbortSignal,
|
|
809
|
-
reason = ZLinkSpotCloseReason.ExplicitClose
|
|
810
|
-
): Promise<void> {
|
|
811
|
-
const seal = activation.sealExecution();
|
|
812
|
-
await this.closeAfterSeal(activation, seal, signal, reason);
|
|
813
|
-
}
|
|
814
|
-
|
|
815
|
-
async closeAfterSeal(
|
|
794
|
+
async sealForClose(
|
|
816
795
|
activation: ZLinkSpotActivation,
|
|
817
796
|
seal: import('../execution').ZLinkExecutionBarrierSeal,
|
|
818
|
-
signal?: AbortSignal
|
|
819
|
-
reason = ZLinkSpotCloseReason.ExplicitClose,
|
|
820
|
-
deadline?: Date
|
|
797
|
+
signal?: AbortSignal
|
|
821
798
|
): Promise<void> {
|
|
822
799
|
try {
|
|
823
800
|
await activation.waitForExecutionQuiescence(seal, signal);
|
|
@@ -825,19 +802,26 @@ export class ZLinkSpotActivationLifecycle {
|
|
|
825
802
|
activation.abortExecutionSeal(seal);
|
|
826
803
|
throw error;
|
|
827
804
|
}
|
|
828
|
-
// The eager occupancy check that authorized this seal (startClose ->
|
|
829
|
-
// canClose()) ran before quiescence, so it can miss an actor join that
|
|
830
|
-
// was already queued on the serial executor at that moment. Recheck now
|
|
831
|
-
// that every turn admitted before the seal has finished, and release the
|
|
832
|
-
// seal instead of closing an occupied Spot.
|
|
833
|
-
if (!activation.canClose(reason)) {
|
|
834
|
-
activation.abortExecutionSeal(seal);
|
|
835
|
-
throw new ZLinkSpotCloseOccupiedError(activation.spotId);
|
|
836
|
-
}
|
|
837
805
|
if (!activation.commitExecutionSeal(seal)) {
|
|
838
806
|
throw new Error(`Spot '${String(activation.spotId)}' close seal is stale.`);
|
|
839
807
|
}
|
|
840
|
-
|
|
808
|
+
}
|
|
809
|
+
|
|
810
|
+
/** Returns the OnClosing failure, which cleanup records and does not rethrow. */
|
|
811
|
+
async cleanupClosedActivation(
|
|
812
|
+
activation: ZLinkSpotActivation,
|
|
813
|
+
reason = ZLinkSpotCloseReason.ExplicitClose,
|
|
814
|
+
deadline?: Date
|
|
815
|
+
): Promise<unknown> {
|
|
816
|
+
return await this.cleanupActivation(
|
|
817
|
+
activation,
|
|
818
|
+
activation.meshName,
|
|
819
|
+
true,
|
|
820
|
+
undefined,
|
|
821
|
+
reason,
|
|
822
|
+
deadline,
|
|
823
|
+
true
|
|
824
|
+
);
|
|
841
825
|
}
|
|
842
826
|
|
|
843
827
|
async dispatchActorPacket(
|
|
@@ -961,13 +945,16 @@ export class ZLinkSpotActivationLifecycle {
|
|
|
961
945
|
notifyClosing: boolean,
|
|
962
946
|
signal?: AbortSignal,
|
|
963
947
|
reason = ZLinkSpotCloseReason.ExplicitClose,
|
|
964
|
-
deadline?: Date
|
|
965
|
-
|
|
948
|
+
deadline?: Date,
|
|
949
|
+
owningLifecycle = false
|
|
950
|
+
): Promise<unknown> {
|
|
966
951
|
throwIfAborted(signal);
|
|
967
952
|
const state = this.cleanupStates.get(activation) ?? {
|
|
968
953
|
closingAttempted: false,
|
|
969
954
|
timersDisposed: false,
|
|
955
|
+
serialDisposed: false,
|
|
970
956
|
handlersDisposed: false,
|
|
957
|
+
actorDispatchDisposed: false,
|
|
971
958
|
nativeDisposed: false,
|
|
972
959
|
locationReleased: false
|
|
973
960
|
};
|
|
@@ -979,7 +966,8 @@ export class ZLinkSpotActivationLifecycle {
|
|
|
979
966
|
notifyClosing,
|
|
980
967
|
reason,
|
|
981
968
|
state,
|
|
982
|
-
deadline
|
|
969
|
+
deadline,
|
|
970
|
+
owningLifecycle
|
|
983
971
|
).finally(() => {
|
|
984
972
|
state.inFlight = undefined;
|
|
985
973
|
});
|
|
@@ -994,13 +982,17 @@ export class ZLinkSpotActivationLifecycle {
|
|
|
994
982
|
state: {
|
|
995
983
|
closingAttempted: boolean;
|
|
996
984
|
timersDisposed: boolean;
|
|
985
|
+
serialDisposed: boolean;
|
|
997
986
|
handlersDisposed: boolean;
|
|
987
|
+
actorDispatchDisposed: boolean;
|
|
998
988
|
nativeDisposed: boolean;
|
|
999
989
|
locationReleased: boolean;
|
|
1000
990
|
},
|
|
1001
|
-
deadline?: Date
|
|
1002
|
-
|
|
991
|
+
deadline?: Date,
|
|
992
|
+
owningLifecycle = false
|
|
993
|
+
): Promise<unknown> {
|
|
1003
994
|
const errors: unknown[] = [];
|
|
995
|
+
let closingFailure: unknown;
|
|
1004
996
|
const cleanup = async (operation: () => Promise<void> | void, completed: () => void) => {
|
|
1005
997
|
try {
|
|
1006
998
|
await operation();
|
|
@@ -1011,10 +1003,21 @@ export class ZLinkSpotActivationLifecycle {
|
|
|
1011
1003
|
};
|
|
1012
1004
|
if (notifyClosing && !state.closingAttempted) {
|
|
1013
1005
|
state.closingAttempted = true;
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1006
|
+
try {
|
|
1007
|
+
// OnClosing is user code: it runs as a Framework turn through the
|
|
1008
|
+
// execution gate while the Close lifecycle item keeps its FIFO slot.
|
|
1009
|
+
await activation.serial.postBarrierTurn(() =>
|
|
1010
|
+
invokeSpotClosing(activation.spot.onClosing?.bind(activation.spot), reason, deadline)
|
|
1011
|
+
);
|
|
1012
|
+
} catch (error) {
|
|
1013
|
+
// An OnClosing failure is diagnostic and cleanup continues. It is
|
|
1014
|
+
// returned so host shutdown can classify its teardown outcome.
|
|
1015
|
+
this.options.closeErrorSink?.reportRuntimeTaskException(
|
|
1016
|
+
`spot ${String(activation.spotId)} onClosing`,
|
|
1017
|
+
error
|
|
1018
|
+
);
|
|
1019
|
+
closingFailure = error;
|
|
1020
|
+
}
|
|
1018
1021
|
}
|
|
1019
1022
|
if (!state.timersDisposed) {
|
|
1020
1023
|
await cleanup(
|
|
@@ -1024,10 +1027,17 @@ export class ZLinkSpotActivationLifecycle {
|
|
|
1024
1027
|
}
|
|
1025
1028
|
);
|
|
1026
1029
|
}
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1030
|
+
if (!state.serialDisposed && state.timersDisposed) {
|
|
1031
|
+
await cleanup(
|
|
1032
|
+
() =>
|
|
1033
|
+
owningLifecycle
|
|
1034
|
+
? activation.serialExecutor.closeChildren()
|
|
1035
|
+
: activation.serialExecutor.close(),
|
|
1036
|
+
() => {
|
|
1037
|
+
state.serialDisposed = true;
|
|
1038
|
+
}
|
|
1039
|
+
);
|
|
1040
|
+
}
|
|
1031
1041
|
if (!state.handlersDisposed) {
|
|
1032
1042
|
await cleanup(
|
|
1033
1043
|
() => disposeLifecycleHandlers(activation.spot),
|
|
@@ -1036,11 +1046,15 @@ export class ZLinkSpotActivationLifecycle {
|
|
|
1036
1046
|
}
|
|
1037
1047
|
);
|
|
1038
1048
|
}
|
|
1039
|
-
if (!state.
|
|
1049
|
+
if (!state.actorDispatchDisposed) {
|
|
1040
1050
|
await cleanup(
|
|
1041
1051
|
() => activation.actorDispatch?.dispose(),
|
|
1042
|
-
() =>
|
|
1052
|
+
() => {
|
|
1053
|
+
state.actorDispatchDisposed = true;
|
|
1054
|
+
}
|
|
1043
1055
|
);
|
|
1056
|
+
}
|
|
1057
|
+
if (!state.nativeDisposed) {
|
|
1044
1058
|
await cleanup(
|
|
1045
1059
|
() => activation.nativeSpot?.dispose(),
|
|
1046
1060
|
() => {
|
|
@@ -1048,7 +1062,14 @@ export class ZLinkSpotActivationLifecycle {
|
|
|
1048
1062
|
}
|
|
1049
1063
|
);
|
|
1050
1064
|
}
|
|
1051
|
-
if (
|
|
1065
|
+
if (
|
|
1066
|
+
!state.locationReleased &&
|
|
1067
|
+
state.timersDisposed &&
|
|
1068
|
+
state.serialDisposed &&
|
|
1069
|
+
state.handlersDisposed &&
|
|
1070
|
+
state.actorDispatchDisposed &&
|
|
1071
|
+
state.nativeDisposed
|
|
1072
|
+
) {
|
|
1052
1073
|
await cleanup(
|
|
1053
1074
|
() => this.options.releaseLocation(activation, locationMeshName, activation.spotId),
|
|
1054
1075
|
() => {
|
|
@@ -1060,6 +1081,7 @@ export class ZLinkSpotActivationLifecycle {
|
|
|
1060
1081
|
if (errors.length > 1) {
|
|
1061
1082
|
throw new AggregateError(errors, `Spot '${activation.spotId}' cleanup failed.`);
|
|
1062
1083
|
}
|
|
1084
|
+
return closingFailure;
|
|
1063
1085
|
}
|
|
1064
1086
|
|
|
1065
1087
|
private decodeCreateReply(reply: unknown): unknown {
|
|
@@ -30,11 +30,11 @@ type AdmissionOptions = Pick<
|
|
|
30
30
|
| 'locationClaim'
|
|
31
31
|
| 'messageSerializers'
|
|
32
32
|
| 'nativeSpotNodeProvider'
|
|
33
|
-
| 'createReceived'
|
|
34
33
|
| 'createTopicMessage'
|
|
35
34
|
| 'providerResolver'
|
|
36
35
|
| 'runtimeEventPublisher'
|
|
37
36
|
| 'routeToActorJoinPrewarm'
|
|
37
|
+
| 'isSpotClosing'
|
|
38
38
|
>;
|
|
39
39
|
|
|
40
40
|
export class ZLinkSpotActorAdmissionCoordinator {
|
|
@@ -92,12 +92,12 @@ export class ZLinkSpotActorAdmissionCoordinator {
|
|
|
92
92
|
if (nativeSpot === undefined) return undefined;
|
|
93
93
|
const nativeDispatch = new ZLinkSpotActorJoinDispatch({
|
|
94
94
|
nativeSpot,
|
|
95
|
-
createReceived: requireBackendValueFactory(this.options.createReceived, 'Received'),
|
|
96
95
|
createTopicMessage: requireBackendValueFactory(
|
|
97
96
|
this.options.createTopicMessage,
|
|
98
97
|
'TopicMessage'
|
|
99
98
|
),
|
|
100
99
|
serial: activation.serial,
|
|
100
|
+
isSpotClosing: () => this.options.isSpotClosing(activation),
|
|
101
101
|
actors: {
|
|
102
102
|
resolveActor: (actorId) =>
|
|
103
103
|
activation.hasDepartedActor(actorId)
|
|
@@ -11,7 +11,6 @@ import { ZLinkBackendSpotDispatchEvent } from '../backend/contracts';
|
|
|
11
11
|
import type {
|
|
12
12
|
ZLinkBackendActorRef,
|
|
13
13
|
ZLinkBackendActorRecvInfo,
|
|
14
|
-
ZLinkBackendReceived,
|
|
15
14
|
ZLinkBackendSpot,
|
|
16
15
|
ZLinkBackendTopicMessage
|
|
17
16
|
} from '../backend/contracts';
|
|
@@ -92,9 +91,9 @@ export interface ZLinkDetachedTaskRunner {
|
|
|
92
91
|
|
|
93
92
|
interface ZLinkSpotActorJoinDispatchOptions {
|
|
94
93
|
readonly nativeSpot: ZLinkBackendSpot;
|
|
95
|
-
readonly createReceived: () => ZLinkBackendReceived;
|
|
96
94
|
readonly createTopicMessage: () => ZLinkBackendTopicMessage;
|
|
97
95
|
readonly serial: ZLinkSpotSerialTurnExecutor;
|
|
96
|
+
readonly isSpotClosing?: () => boolean;
|
|
98
97
|
readonly actors: ZLinkSpotActorAdmissionRuntime;
|
|
99
98
|
readonly packets?: ZLinkSpotActorPacketRuntime;
|
|
100
99
|
readonly boundSessionRuntime?: ZLinkSpotBoundSessionRuntime;
|
|
@@ -148,10 +147,9 @@ export class ZLinkSpotActorJoinDispatch {
|
|
|
148
147
|
dispatchErrors: options.dispatchErrors
|
|
149
148
|
});
|
|
150
149
|
this.routedFrames = new ZLinkSpotRoutedFrameDispatch({
|
|
151
|
-
nativeSpot: options.nativeSpot,
|
|
152
|
-
createReceived: options.createReceived,
|
|
153
150
|
nativeSpotId: this.nativeSpotId,
|
|
154
151
|
serial: options.serial,
|
|
152
|
+
isSpotClosing: options.isSpotClosing,
|
|
155
153
|
resolveActor: actors.resolveActor,
|
|
156
154
|
getTarget: () => actors.getTarget() as ZLinkActorJoinAdmissionTarget & ZLinkSpot,
|
|
157
155
|
defaultAccept: actors.defaultAccept,
|
|
@@ -189,8 +187,7 @@ export class ZLinkSpotActorJoinDispatch {
|
|
|
189
187
|
messageSerializers: options.messageSerializers,
|
|
190
188
|
providerResolver: options.providerResolver,
|
|
191
189
|
dispatchErrors: options.dispatchErrors,
|
|
192
|
-
claimApplicationWork: options.claimApplicationWork
|
|
193
|
-
waitIdle: waitSpotDispatchIdle
|
|
190
|
+
claimApplicationWork: options.claimApplicationWork
|
|
194
191
|
});
|
|
195
192
|
this.subscriptions = new ZLinkSpotSubscriptionDispatch({
|
|
196
193
|
nativeSpot: options.nativeSpot,
|
|
@@ -309,7 +306,9 @@ export class ZLinkSpotActorJoinDispatch {
|
|
|
309
306
|
await waitSpotDispatchIdle();
|
|
310
307
|
return;
|
|
311
308
|
}
|
|
312
|
-
await this.
|
|
309
|
+
await this.options.serial.executeLifecycleOperation(() =>
|
|
310
|
+
this.nativeActorJoinAdmission.admit(request, this.options.isSpotClosing?.() === true)
|
|
311
|
+
);
|
|
313
312
|
}
|
|
314
313
|
}
|
|
315
314
|
}
|