@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
|
@@ -14,6 +14,7 @@ export interface ZLinkSpotCloseOperation {
|
|
|
14
14
|
readonly started: boolean;
|
|
15
15
|
}
|
|
16
16
|
export declare class ZLinkSpotActivationRegistry {
|
|
17
|
+
private readonly isCommittedClose;
|
|
17
18
|
private nextId;
|
|
18
19
|
private readonly activations;
|
|
19
20
|
private readonly staged;
|
|
@@ -23,14 +24,15 @@ export declare class ZLinkSpotActivationRegistry {
|
|
|
23
24
|
private readonly emptyWaiters;
|
|
24
25
|
private readonly lifecycleMetrics;
|
|
25
26
|
private activeScan;
|
|
26
|
-
constructor(metrics?: import('../diagnostics').ZLinkRuntimeMetrics);
|
|
27
|
+
constructor(metrics?: import('../diagnostics').ZLinkRuntimeMetrics, isCommittedClose?: (meshName: string, spotId: RoutingId) => boolean);
|
|
27
28
|
allocateSpotId(meshName: string): RoutingId;
|
|
28
29
|
resolve(meshName: string, spotId: RoutingId): ZLinkSpotActivation | undefined;
|
|
29
30
|
resolveUnique(spotId: RoutingId): ZLinkSpotActivation | undefined;
|
|
30
31
|
has(meshName: string, spotId: RoutingId): boolean;
|
|
31
|
-
canClose(meshName: string, spotId: RoutingId): boolean;
|
|
32
32
|
list(meshName: string): readonly ZLinkSpotInfo[];
|
|
33
33
|
activeActivations(): readonly ZLinkSpotActivation[];
|
|
34
|
+
activationForClose(meshName: string, spotId: RoutingId): ZLinkSpotActivation | undefined;
|
|
35
|
+
finishClose(meshName: string, spotId: RoutingId): void;
|
|
34
36
|
hasActiveActivations(): boolean;
|
|
35
37
|
nextActiveActivationBatch(limit?: number): readonly ZLinkSpotActivation[];
|
|
36
38
|
closingOperation(meshName: string, spotId: RoutingId): ZLinkSpotCloseOperation | undefined;
|
|
@@ -3,13 +3,13 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.ZLinkSpotActivationRegistry = exports.ZLinkSpotActivation = void 0;
|
|
4
4
|
const framework_errors_internal_1 = require("../framework-errors-internal");
|
|
5
5
|
const contracts_1 = require("../../contracts");
|
|
6
|
-
const spot_activation_state_1 = require("./spot-activation-state");
|
|
7
6
|
const configuration_1 = require("../configuration");
|
|
8
7
|
const abort_1 = require("../abort");
|
|
9
8
|
const spot_lifecycle_metrics_1 = require("./spot-lifecycle-metrics");
|
|
10
|
-
var
|
|
11
|
-
Object.defineProperty(exports, "ZLinkSpotActivation", { enumerable: true, get: function () { return
|
|
9
|
+
var spot_activation_state_1 = require("./spot-activation-state");
|
|
10
|
+
Object.defineProperty(exports, "ZLinkSpotActivation", { enumerable: true, get: function () { return spot_activation_state_1.ZLinkSpotActivation; } });
|
|
12
11
|
class ZLinkSpotActivationRegistry {
|
|
12
|
+
isCommittedClose;
|
|
13
13
|
nextId = 1;
|
|
14
14
|
activations = new Map();
|
|
15
15
|
staged = new Set();
|
|
@@ -19,7 +19,8 @@ class ZLinkSpotActivationRegistry {
|
|
|
19
19
|
emptyWaiters = new Set();
|
|
20
20
|
lifecycleMetrics;
|
|
21
21
|
activeScan;
|
|
22
|
-
constructor(metrics) {
|
|
22
|
+
constructor(metrics, isCommittedClose = () => false) {
|
|
23
|
+
this.isCommittedClose = isCommittedClose;
|
|
23
24
|
this.lifecycleMetrics = new spot_lifecycle_metrics_1.ZLinkSpotLifecycleMetrics(metrics);
|
|
24
25
|
}
|
|
25
26
|
allocateSpotId(meshName) {
|
|
@@ -32,12 +33,16 @@ class ZLinkSpotActivationRegistry {
|
|
|
32
33
|
}
|
|
33
34
|
resolve(meshName, spotId) {
|
|
34
35
|
const key = spotActivationKey(meshName, spotId);
|
|
35
|
-
return this.
|
|
36
|
+
return this.isCommittedClose(meshName, spotId) ||
|
|
37
|
+
this.closing.has(key) ||
|
|
38
|
+
this.failedClose.has(key) ||
|
|
39
|
+
this.staged.has(key)
|
|
36
40
|
? undefined
|
|
37
41
|
: this.activations.get(key);
|
|
38
42
|
}
|
|
39
43
|
resolveUnique(spotId) {
|
|
40
44
|
const matches = [...this.activations.values()].filter((activation) => String(activation.spotId) === String(spotId) &&
|
|
45
|
+
!this.isCommittedClose(activation.meshName, activation.spotId) &&
|
|
41
46
|
!this.staged.has(spotActivationKey(activation.meshName, activation.spotId)) &&
|
|
42
47
|
!this.closing.has(spotActivationKey(activation.meshName, activation.spotId)) &&
|
|
43
48
|
!this.failedClose.has(spotActivationKey(activation.meshName, activation.spotId)));
|
|
@@ -45,25 +50,22 @@ class ZLinkSpotActivationRegistry {
|
|
|
45
50
|
}
|
|
46
51
|
has(meshName, spotId) {
|
|
47
52
|
const key = spotActivationKey(meshName, spotId);
|
|
48
|
-
return (!this.
|
|
53
|
+
return (!this.isCommittedClose(meshName, spotId) &&
|
|
54
|
+
!this.staged.has(key) &&
|
|
49
55
|
!this.closing.has(key) &&
|
|
50
56
|
!this.failedClose.has(key) &&
|
|
51
57
|
this.activations.has(key));
|
|
52
58
|
}
|
|
53
|
-
canClose(meshName, spotId) {
|
|
54
|
-
const key = spotActivationKey(meshName, spotId);
|
|
55
|
-
return (!this.staged.has(key) &&
|
|
56
|
-
!this.closing.has(key) &&
|
|
57
|
-
!this.failedClose.has(key) &&
|
|
58
|
-
this.activations.get(key)?.canClose() === true);
|
|
59
|
-
}
|
|
60
59
|
list(meshName) {
|
|
61
60
|
return [...this.activations.values()]
|
|
62
61
|
.filter((activation) => {
|
|
63
62
|
if (activation.meshName !== meshName)
|
|
64
63
|
return false;
|
|
65
64
|
const key = spotActivationKey(activation.meshName, activation.spotId);
|
|
66
|
-
return !this.
|
|
65
|
+
return (!this.isCommittedClose(meshName, activation.spotId) &&
|
|
66
|
+
!this.staged.has(key) &&
|
|
67
|
+
!this.closing.has(key) &&
|
|
68
|
+
!this.failedClose.has(key));
|
|
67
69
|
})
|
|
68
70
|
.map((activation) => String(activation.spotId))
|
|
69
71
|
.sort((left, right) => left.localeCompare(right))
|
|
@@ -72,6 +74,17 @@ class ZLinkSpotActivationRegistry {
|
|
|
72
74
|
activeActivations() {
|
|
73
75
|
return [...this.activations.values()];
|
|
74
76
|
}
|
|
77
|
+
activationForClose(meshName, spotId) {
|
|
78
|
+
return this.activations.get(spotActivationKey(meshName, spotId));
|
|
79
|
+
}
|
|
80
|
+
finishClose(meshName, spotId) {
|
|
81
|
+
const key = spotActivationKey(meshName, spotId);
|
|
82
|
+
if (this.activations.delete(key))
|
|
83
|
+
this.lifecycleMetrics.closed('user');
|
|
84
|
+
this.staged.delete(key);
|
|
85
|
+
this.failedClose.delete(key);
|
|
86
|
+
this.resolveEmptyWaiters();
|
|
87
|
+
}
|
|
75
88
|
hasActiveActivations() {
|
|
76
89
|
return this.activations.size > 0;
|
|
77
90
|
}
|
|
@@ -165,30 +178,14 @@ class ZLinkSpotActivationRegistry {
|
|
|
165
178
|
}
|
|
166
179
|
const operation = {};
|
|
167
180
|
let completed = false;
|
|
168
|
-
let occupiedAfterQuiescence = false;
|
|
169
181
|
const ready = Promise.resolve()
|
|
170
182
|
.then(() => close(activation))
|
|
171
183
|
.then(() => {
|
|
172
184
|
completed = true;
|
|
173
|
-
})
|
|
174
|
-
.catch((error) => {
|
|
175
|
-
// The seal's post-quiescence recheck (spot-activation.ts
|
|
176
|
-
// closeAfterSeal) found a new join and released the seal instead of
|
|
177
|
-
// closing. The activation is already back to normal operation, so
|
|
178
|
-
// this is a "did not close" outcome, not a close failure.
|
|
179
|
-
if (error instanceof spot_activation_state_1.ZLinkSpotCloseOccupiedError) {
|
|
180
|
-
occupiedAfterQuiescence = true;
|
|
181
|
-
return;
|
|
182
|
-
}
|
|
183
|
-
throw error;
|
|
184
185
|
})
|
|
185
186
|
.finally(() => {
|
|
186
187
|
if (this.closing.get(key) === operation) {
|
|
187
188
|
this.closing.delete(key);
|
|
188
|
-
if (occupiedAfterQuiescence) {
|
|
189
|
-
this.resolveEmptyWaiters();
|
|
190
|
-
return;
|
|
191
|
-
}
|
|
192
189
|
if (completed || resourcesReleased(activation)) {
|
|
193
190
|
this.activations.delete(key);
|
|
194
191
|
this.staged.delete(key);
|
|
@@ -201,13 +198,19 @@ class ZLinkSpotActivationRegistry {
|
|
|
201
198
|
this.resolveEmptyWaiters();
|
|
202
199
|
}
|
|
203
200
|
})
|
|
204
|
-
.then(() =>
|
|
201
|
+
.then(() => true);
|
|
205
202
|
Object.assign(operation, { activation, ready, started: true });
|
|
206
203
|
this.closing.set(key, operation);
|
|
207
204
|
return operation;
|
|
208
205
|
}
|
|
209
206
|
getOrBegin(meshName, spotType, spotId, create) {
|
|
210
207
|
const key = spotActivationKey(meshName, spotId);
|
|
208
|
+
if (this.isCommittedClose(meshName, spotId)) {
|
|
209
|
+
return {
|
|
210
|
+
owner: false,
|
|
211
|
+
ready: Promise.reject((0, framework_errors_internal_1.createInternalFrameworkException)(framework_errors_internal_1.ZLinkFrameworkInternalErrorKind.RequestRejected, `Spot '${String(spotId)}' is Closing.`))
|
|
212
|
+
};
|
|
213
|
+
}
|
|
211
214
|
const closing = this.closing.get(key);
|
|
212
215
|
if (closing !== undefined) {
|
|
213
216
|
return {
|
|
@@ -12,6 +12,7 @@ import { ZLinkExecutionBarrier, type ZLinkExecutionBarrierSeal } from '../execut
|
|
|
12
12
|
import type { ZLinkTimerRelocationState } from './spot-timer';
|
|
13
13
|
export type ZLinkSpotActivationDomain = {
|
|
14
14
|
readonly kind: 'user';
|
|
15
|
+
readonly objectGeneration?: bigint;
|
|
15
16
|
readonly executionMode: ZLinkUserSpotExecutionMode;
|
|
16
17
|
readonly relocationCoordinationMode: ZLinkSpotRelocationCoordinationMode;
|
|
17
18
|
} | {
|
|
@@ -39,16 +40,6 @@ export interface ZLinkSpotRelocationCapture {
|
|
|
39
40
|
readonly seal: ZLinkExecutionBarrierSeal;
|
|
40
41
|
readonly timers: readonly ZLinkTimerRelocationState[];
|
|
41
42
|
}
|
|
42
|
-
/**
|
|
43
|
-
* Internal signal that a close seal reached quiescence but the activation
|
|
44
|
-
* became occupied again while it waited (an actor join queued ahead of the
|
|
45
|
-
* close finished after the eager pre-seal occupancy check). This is not a
|
|
46
|
-
* close failure: the seal is released, the Spot stays open, and the caller
|
|
47
|
-
* reports `close(...)` as `false` instead of throwing.
|
|
48
|
-
*/
|
|
49
|
-
export declare class ZLinkSpotCloseOccupiedError extends Error {
|
|
50
|
-
constructor(spotId: RoutingId);
|
|
51
|
-
}
|
|
52
43
|
export declare class ZLinkSpotActivation {
|
|
53
44
|
readonly meshName: string;
|
|
54
45
|
readonly spotId: RoutingId;
|
|
@@ -81,7 +72,7 @@ export declare class ZLinkSpotActivation {
|
|
|
81
72
|
completeConsumedRelocationBoundary(outcome: ZLinkSpotRelocationReadyOutcome): Promise<void>;
|
|
82
73
|
notifyRelocatedBoundary(): Promise<void>;
|
|
83
74
|
executeActor<T>(actorId: string, operation: (serial: ZLinkSpotSerialTurnExecutor) => Promise<T> | T): Promise<T>;
|
|
84
|
-
sealExecution(): ZLinkExecutionBarrierSeal;
|
|
75
|
+
sealExecution(drainsYieldedTurns?: boolean): ZLinkExecutionBarrierSeal;
|
|
85
76
|
waitForExecutionQuiescence(seal: ZLinkExecutionBarrierSeal, signal?: AbortSignal): Promise<void>;
|
|
86
77
|
abortExecutionSeal(seal: ZLinkExecutionBarrierSeal): boolean;
|
|
87
78
|
commitExecutionSeal(seal: ZLinkExecutionBarrierSeal): boolean;
|
|
@@ -1,25 +1,12 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.ZLinkSpotActivation =
|
|
3
|
+
exports.ZLinkSpotActivation = void 0;
|
|
4
4
|
const framework_errors_internal_1 = require("../framework-errors-internal");
|
|
5
5
|
const contracts_1 = require("../../contracts");
|
|
6
6
|
const configuration_1 = require("../configuration");
|
|
7
7
|
const abort_1 = require("../abort");
|
|
8
8
|
const spot_serial_executor_1 = require("./spot-serial-executor");
|
|
9
9
|
const execution_1 = require("../execution");
|
|
10
|
-
/**
|
|
11
|
-
* Internal signal that a close seal reached quiescence but the activation
|
|
12
|
-
* became occupied again while it waited (an actor join queued ahead of the
|
|
13
|
-
* close finished after the eager pre-seal occupancy check). This is not a
|
|
14
|
-
* close failure: the seal is released, the Spot stays open, and the caller
|
|
15
|
-
* reports `close(...)` as `false` instead of throwing.
|
|
16
|
-
*/
|
|
17
|
-
class ZLinkSpotCloseOccupiedError extends Error {
|
|
18
|
-
constructor(spotId) {
|
|
19
|
-
super(`Spot '${String(spotId)}' became occupied while its close seal reached quiescence.`);
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
exports.ZLinkSpotCloseOccupiedError = ZLinkSpotCloseOccupiedError;
|
|
23
10
|
class ZLinkSpotActivation {
|
|
24
11
|
meshName;
|
|
25
12
|
spotId;
|
|
@@ -68,7 +55,7 @@ class ZLinkSpotActivation {
|
|
|
68
55
|
this.actorDispatch = options.actorDispatch;
|
|
69
56
|
}
|
|
70
57
|
get objectGeneration() {
|
|
71
|
-
return this.domain.
|
|
58
|
+
return this.domain.objectGeneration;
|
|
72
59
|
}
|
|
73
60
|
get executionMode() {
|
|
74
61
|
return this.domain.kind === 'user'
|
|
@@ -171,8 +158,8 @@ class ZLinkSpotActivation {
|
|
|
171
158
|
admitActorDurablePrefix(actorId, records) {
|
|
172
159
|
return this.serialExecutor.admitActorDurablePrefix(actorId, records);
|
|
173
160
|
}
|
|
174
|
-
sealExecution() {
|
|
175
|
-
return this.executionBarrier.seal();
|
|
161
|
+
sealExecution(drainsYieldedTurns = false) {
|
|
162
|
+
return this.executionBarrier.seal(drainsYieldedTurns);
|
|
176
163
|
}
|
|
177
164
|
waitForExecutionQuiescence(seal, signal) {
|
|
178
165
|
return this.executionBarrier.waitForQuiescence(seal, signal);
|
|
@@ -6,7 +6,7 @@ import type { ZLinkSpotActorRequestHandlerRegistration, ZLinkSpotActorSendHandle
|
|
|
6
6
|
import { ZLinkSpotCloseReason, ZLinkSpotRelocationCoordinationMode, ZLinkUserSpotExecutionMode } from '../../contracts';
|
|
7
7
|
import type { Message } from '../../contracts/Common/Message';
|
|
8
8
|
import type { ZLinkMessageFollowOrigin } from '../foundation/service-runtime-contracts';
|
|
9
|
-
import type {
|
|
9
|
+
import type { ZLinkBackendSpot, ZLinkBackendSpotNode, ZLinkBackendTopicMessage } from '../backend/contracts';
|
|
10
10
|
import { ZLinkDispatchErrorReporter } from '../channels';
|
|
11
11
|
import { type ZLinkRemoteBoundSessionTarget } from '../actors';
|
|
12
12
|
import { ZLinkWorkerRuntime } from '../workers';
|
|
@@ -39,12 +39,12 @@ export interface ZLinkSpotActivationLifecycleOptions {
|
|
|
39
39
|
readonly channelMeshNameForChannel?: (channelName: string) => string | undefined;
|
|
40
40
|
readonly providerResolver?: ZLinkProviderResolver;
|
|
41
41
|
readonly dispatchErrors?: ZLinkDispatchErrorReporter;
|
|
42
|
+
readonly closeErrorSink?: import('../diagnostics/dispatch-error-port').ZLinkDispatchErrorSink;
|
|
42
43
|
readonly runtimeEventPublisher?: ZLinkRuntimeEventPublisher;
|
|
43
44
|
readonly workerRuntime: ZLinkWorkerRuntime;
|
|
44
45
|
readonly messageSerializers?: ReadonlyMap<string, ZLinkMessageSerializer>;
|
|
45
46
|
readonly locationClaim: ZLinkSpotLocationClaim;
|
|
46
47
|
readonly createNativeSpot?: (meshName: string, spotId: RoutingId, authority?: ZLinkNativeSpotAuthority) => ZLinkBackendSpot | undefined;
|
|
47
|
-
readonly createReceived?: () => ZLinkBackendReceived;
|
|
48
48
|
readonly createTopicMessage?: () => ZLinkBackendTopicMessage;
|
|
49
49
|
readonly nativeSpotNodeProvider?: (meshName: string) => ZLinkBackendSpotNode | undefined;
|
|
50
50
|
readonly actorResolver?: (actorId: string) => ZLinkActor | undefined;
|
|
@@ -55,7 +55,9 @@ export interface ZLinkSpotActivationLifecycleOptions {
|
|
|
55
55
|
readonly admission?: ZLinkRuntimeAdmissionGate;
|
|
56
56
|
readonly statefulExecutionAllowed?: () => boolean;
|
|
57
57
|
readonly leaveActor: (spotId: RoutingId, actor: ZLinkActor, signal?: AbortSignal, meshName?: string) => Promise<void>;
|
|
58
|
-
|
|
58
|
+
/** Starts a context Close request after its calling turn has ended. */
|
|
59
|
+
readonly requestContextClose: (activation: ZLinkSpotActivation, objectGeneration: bigint, signal?: AbortSignal) => Promise<boolean>;
|
|
60
|
+
readonly isSpotClosing: (activation: ZLinkSpotActivation) => boolean;
|
|
59
61
|
readonly registerActivation: (activation: ZLinkSpotActivation) => void;
|
|
60
62
|
readonly routeToActorJoinPrewarm?: ZLinkRouteToActorJoinPrewarm;
|
|
61
63
|
readonly releaseLocation: (activation: ZLinkSpotActivation, meshName: string, spotId: RoutingId) => Promise<void>;
|
|
@@ -75,12 +77,12 @@ export declare class ZLinkSpotActivationLifecycle {
|
|
|
75
77
|
materializeRelocation<TSpot extends ZLinkSpot | ZLinkInstanceSpot>(meshName: string, objectKind: 'user_spot' | 'instance_spot', stableType: string, implementation: Type<TSpot>, spotId: RoutingId, objectGeneration: bigint, authorityOwnerGeneration: bigint, signal?: AbortSignal): Promise<ZLinkSpotActivation>;
|
|
76
78
|
materializeInstance<TSpot extends ZLinkInstanceSpot>(meshName: string, instanceType: string, implementation: Type<TSpot>, spotId: RoutingId, objectGeneration: bigint, signal?: AbortSignal): Promise<ZLinkSpotActivation>;
|
|
77
79
|
discardInstance(activation: ZLinkSpotActivation): Promise<void>;
|
|
78
|
-
resourcesReleased(activation: ZLinkSpotActivation): boolean;
|
|
79
80
|
create<TSpot extends ZLinkSpot>(meshName: string, spotType: Type<TSpot>, spotId: RoutingId, request: Message, signal?: AbortSignal, authority?: ZLinkNativeSpotAuthority): Promise<ZLinkLocalSpotCreateResult>;
|
|
80
81
|
private createWithoutNativeSpot;
|
|
81
82
|
private contextClose;
|
|
82
|
-
|
|
83
|
-
|
|
83
|
+
sealForClose(activation: ZLinkSpotActivation, seal: import('../execution').ZLinkExecutionBarrierSeal, signal?: AbortSignal): Promise<void>;
|
|
84
|
+
/** Returns the OnClosing failure, which cleanup records and does not rethrow. */
|
|
85
|
+
cleanupClosedActivation(activation: ZLinkSpotActivation, reason?: ZLinkSpotCloseReason, deadline?: Date): Promise<unknown>;
|
|
84
86
|
dispatchActorPacket(activation: ZLinkSpotActivation, actorId: string, parts: readonly Message[], returnResponse?: boolean, remoteBoundSessionTarget?: ZLinkRemoteBoundSessionTarget, fallbackActorRef?: ActorRef, requestTerminal?: (response: unknown) => Promise<void> | void, messageFollowOrigin?: ZLinkMessageFollowOrigin): Promise<unknown>;
|
|
85
87
|
private runCreateLifecycle;
|
|
86
88
|
private cleanupActivation;
|
|
@@ -4,6 +4,7 @@ exports.ZLinkSpotActivationLifecycle = void 0;
|
|
|
4
4
|
const contracts_1 = require("../../contracts");
|
|
5
5
|
const abort_1 = require("../abort");
|
|
6
6
|
const configuration_1 = require("../configuration");
|
|
7
|
+
const framework_errors_internal_1 = require("../framework-errors-internal");
|
|
7
8
|
const actors_1 = require("../actors");
|
|
8
9
|
const handler_instance_scope_1 = require("../handlers/handler-instance-scope");
|
|
9
10
|
const payload_codec_1 = require("../messaging/payload-codec");
|
|
@@ -72,7 +73,7 @@ class ZLinkSpotActivationLifecycle {
|
|
|
72
73
|
providerResolver: this.options.providerResolver,
|
|
73
74
|
runtimeEventPublisher: this.options.runtimeEventPublisher,
|
|
74
75
|
workerRuntime: this.options.workerRuntime,
|
|
75
|
-
close: this.contextClose(
|
|
76
|
+
close: this.contextClose(objectGeneration, () => activation)
|
|
76
77
|
};
|
|
77
78
|
const context = objectKind === 'user_spot'
|
|
78
79
|
? (0, spot_context_1.createSpotContext)({
|
|
@@ -110,6 +111,7 @@ class ZLinkSpotActivationLifecycle {
|
|
|
110
111
|
domain: objectKind === 'user_spot'
|
|
111
112
|
? {
|
|
112
113
|
kind: 'user',
|
|
114
|
+
objectGeneration,
|
|
113
115
|
executionMode,
|
|
114
116
|
relocationCoordinationMode: this.options.userSpotRelocationCoordinationMode?.(meshName, implementation) ?? contracts_1.ZLinkSpotRelocationCoordinationMode.FrameworkManaged
|
|
115
117
|
}
|
|
@@ -171,7 +173,7 @@ class ZLinkSpotActivationLifecycle {
|
|
|
171
173
|
providerResolver: this.options.providerResolver,
|
|
172
174
|
runtimeEventPublisher: this.options.runtimeEventPublisher,
|
|
173
175
|
workerRuntime: this.options.workerRuntime,
|
|
174
|
-
close: this.contextClose(
|
|
176
|
+
close: this.contextClose(objectGeneration, () => activation)
|
|
175
177
|
});
|
|
176
178
|
instance = await (0, spot_provider_1.createFreshProviderInstance)(implementation, this.options.providerResolver, context);
|
|
177
179
|
Object.defineProperty(instance, 'context', {
|
|
@@ -241,13 +243,6 @@ class ZLinkSpotActivationLifecycle {
|
|
|
241
243
|
throw new AggregateError(errors, `Instance Spot '${String(activation.spotId)}' cleanup failed.`);
|
|
242
244
|
}
|
|
243
245
|
}
|
|
244
|
-
resourcesReleased(activation) {
|
|
245
|
-
const state = this.cleanupStates.get(activation);
|
|
246
|
-
return (state?.timersDisposed === true &&
|
|
247
|
-
state.handlersDisposed === true &&
|
|
248
|
-
state.nativeDisposed === true &&
|
|
249
|
-
state.locationReleased === true);
|
|
250
|
-
}
|
|
251
246
|
async create(meshName, spotType, spotId, request, signal, authority) {
|
|
252
247
|
const executionMode = this.options.userSpotExecutionMode?.(meshName, spotType) ??
|
|
253
248
|
contracts_1.ZLinkUserSpotExecutionMode.SpotWide;
|
|
@@ -315,7 +310,7 @@ class ZLinkSpotActivationLifecycle {
|
|
|
315
310
|
},
|
|
316
311
|
ensureOperationAllowed: () => activation?.ensureContextOperationAllowed(),
|
|
317
312
|
leaveActor: (actor, contextSignal) => this.options.leaveActor(spotId, actor, contextSignal, meshName),
|
|
318
|
-
close: this.contextClose(
|
|
313
|
+
close: this.contextClose(spotGeneration, () => activation)
|
|
319
314
|
});
|
|
320
315
|
try {
|
|
321
316
|
spot = await (0, spot_provider_1.createFreshProviderInstance)(spotType, this.options.providerResolver, context);
|
|
@@ -331,6 +326,7 @@ class ZLinkSpotActivationLifecycle {
|
|
|
331
326
|
spotId,
|
|
332
327
|
domain: {
|
|
333
328
|
kind: 'user',
|
|
329
|
+
objectGeneration: spotGeneration,
|
|
334
330
|
executionMode,
|
|
335
331
|
relocationCoordinationMode: this.options.userSpotRelocationCoordinationMode?.(meshName, spotType) ??
|
|
336
332
|
contracts_1.ZLinkSpotRelocationCoordinationMode.FrameworkManaged
|
|
@@ -408,7 +404,7 @@ class ZLinkSpotActivationLifecycle {
|
|
|
408
404
|
},
|
|
409
405
|
ensureOperationAllowed: () => activation?.ensureContextOperationAllowed(),
|
|
410
406
|
leaveActor: (actor, contextSignal) => this.options.leaveActor(spotId, actor, contextSignal, meshName),
|
|
411
|
-
close: this.contextClose(
|
|
407
|
+
close: this.contextClose(objectGeneration, () => activation)
|
|
412
408
|
});
|
|
413
409
|
spot = await (0, spot_provider_1.createFreshProviderInstance)(spotType, this.options.providerResolver, context);
|
|
414
410
|
Object.defineProperty(spot, 'context', {
|
|
@@ -421,6 +417,7 @@ class ZLinkSpotActivationLifecycle {
|
|
|
421
417
|
spotId,
|
|
422
418
|
domain: {
|
|
423
419
|
kind: 'user',
|
|
420
|
+
objectGeneration,
|
|
424
421
|
executionMode,
|
|
425
422
|
relocationCoordinationMode: this.options.userSpotRelocationCoordinationMode?.(meshName, spotType) ??
|
|
426
423
|
contracts_1.ZLinkSpotRelocationCoordinationMode.FrameworkManaged
|
|
@@ -437,31 +434,16 @@ class ZLinkSpotActivationLifecycle {
|
|
|
437
434
|
});
|
|
438
435
|
return await this.runCreateLifecycle(activation, spotType, request, locationClaim, undefined, signal);
|
|
439
436
|
}
|
|
440
|
-
contextClose(
|
|
441
|
-
return
|
|
437
|
+
contextClose(objectGeneration, activationProvider) {
|
|
438
|
+
return (signal) => {
|
|
442
439
|
const activation = activationProvider();
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
// so the callback never waits for work behind its own serial turn.
|
|
446
|
-
if (activation?.serial.isExecuting === true && !activation.serial.isCurrentTurn) {
|
|
447
|
-
activation.requestClose();
|
|
448
|
-
const retry = activation.serial.post(() => this.options.closeSpot(meshName, spotId, signal));
|
|
449
|
-
this.options.detachedTaskRunner?.runDetached(`spot close ${String(spotId)}`, async () => {
|
|
450
|
-
await retry;
|
|
451
|
-
});
|
|
452
|
-
if (this.options.detachedTaskRunner === undefined) {
|
|
453
|
-
void retry.catch(() => undefined);
|
|
454
|
-
}
|
|
455
|
-
return true;
|
|
440
|
+
if (activation === undefined) {
|
|
441
|
+
throw (0, framework_errors_internal_1.createInternalFrameworkException)(framework_errors_internal_1.ZLinkFrameworkInternalErrorKind.InvalidOperation, 'Spot context Close requires its active generation.');
|
|
456
442
|
}
|
|
457
|
-
return
|
|
443
|
+
return this.options.requestContextClose(activation, objectGeneration, signal);
|
|
458
444
|
};
|
|
459
445
|
}
|
|
460
|
-
async
|
|
461
|
-
const seal = activation.sealExecution();
|
|
462
|
-
await this.closeAfterSeal(activation, seal, signal, reason);
|
|
463
|
-
}
|
|
464
|
-
async closeAfterSeal(activation, seal, signal, reason = contracts_1.ZLinkSpotCloseReason.ExplicitClose, deadline) {
|
|
446
|
+
async sealForClose(activation, seal, signal) {
|
|
465
447
|
try {
|
|
466
448
|
await activation.waitForExecutionQuiescence(seal, signal);
|
|
467
449
|
}
|
|
@@ -469,19 +451,13 @@ class ZLinkSpotActivationLifecycle {
|
|
|
469
451
|
activation.abortExecutionSeal(seal);
|
|
470
452
|
throw error;
|
|
471
453
|
}
|
|
472
|
-
// The eager occupancy check that authorized this seal (startClose ->
|
|
473
|
-
// canClose()) ran before quiescence, so it can miss an actor join that
|
|
474
|
-
// was already queued on the serial executor at that moment. Recheck now
|
|
475
|
-
// that every turn admitted before the seal has finished, and release the
|
|
476
|
-
// seal instead of closing an occupied Spot.
|
|
477
|
-
if (!activation.canClose(reason)) {
|
|
478
|
-
activation.abortExecutionSeal(seal);
|
|
479
|
-
throw new spot_activation_state_1.ZLinkSpotCloseOccupiedError(activation.spotId);
|
|
480
|
-
}
|
|
481
454
|
if (!activation.commitExecutionSeal(seal)) {
|
|
482
455
|
throw new Error(`Spot '${String(activation.spotId)}' close seal is stale.`);
|
|
483
456
|
}
|
|
484
|
-
|
|
457
|
+
}
|
|
458
|
+
/** Returns the OnClosing failure, which cleanup records and does not rethrow. */
|
|
459
|
+
async cleanupClosedActivation(activation, reason = contracts_1.ZLinkSpotCloseReason.ExplicitClose, deadline) {
|
|
460
|
+
return await this.cleanupActivation(activation, activation.meshName, true, undefined, reason, deadline, true);
|
|
485
461
|
}
|
|
486
462
|
async dispatchActorPacket(activation, actorId, parts, returnResponse = false, remoteBoundSessionTarget, fallbackActorRef, requestTerminal, messageFollowOrigin) {
|
|
487
463
|
return await this.actorAdmission.dispatchActorPacket(activation, actorId, parts, returnResponse, remoteBoundSessionTarget, fallbackActorRef, requestTerminal, messageFollowOrigin);
|
|
@@ -536,25 +512,28 @@ class ZLinkSpotActivationLifecycle {
|
|
|
536
512
|
throw error;
|
|
537
513
|
}
|
|
538
514
|
}
|
|
539
|
-
async cleanupActivation(activation, locationMeshName, notifyClosing, signal, reason = contracts_1.ZLinkSpotCloseReason.ExplicitClose, deadline) {
|
|
515
|
+
async cleanupActivation(activation, locationMeshName, notifyClosing, signal, reason = contracts_1.ZLinkSpotCloseReason.ExplicitClose, deadline, owningLifecycle = false) {
|
|
540
516
|
(0, abort_1.throwIfAborted)(signal);
|
|
541
517
|
const state = this.cleanupStates.get(activation) ?? {
|
|
542
518
|
closingAttempted: false,
|
|
543
519
|
timersDisposed: false,
|
|
520
|
+
serialDisposed: false,
|
|
544
521
|
handlersDisposed: false,
|
|
522
|
+
actorDispatchDisposed: false,
|
|
545
523
|
nativeDisposed: false,
|
|
546
524
|
locationReleased: false
|
|
547
525
|
};
|
|
548
526
|
this.cleanupStates.set(activation, state);
|
|
549
527
|
if (state.inFlight !== undefined)
|
|
550
528
|
return await state.inFlight;
|
|
551
|
-
state.inFlight = this.runCleanup(activation, locationMeshName, notifyClosing, reason, state, deadline).finally(() => {
|
|
529
|
+
state.inFlight = this.runCleanup(activation, locationMeshName, notifyClosing, reason, state, deadline, owningLifecycle).finally(() => {
|
|
552
530
|
state.inFlight = undefined;
|
|
553
531
|
});
|
|
554
532
|
return await state.inFlight;
|
|
555
533
|
}
|
|
556
|
-
async runCleanup(activation, locationMeshName, notifyClosing, reason, state, deadline) {
|
|
534
|
+
async runCleanup(activation, locationMeshName, notifyClosing, reason, state, deadline, owningLifecycle = false) {
|
|
557
535
|
const errors = [];
|
|
536
|
+
let closingFailure;
|
|
558
537
|
const cleanup = async (operation, completed) => {
|
|
559
538
|
try {
|
|
560
539
|
await operation();
|
|
@@ -566,26 +545,51 @@ class ZLinkSpotActivationLifecycle {
|
|
|
566
545
|
};
|
|
567
546
|
if (notifyClosing && !state.closingAttempted) {
|
|
568
547
|
state.closingAttempted = true;
|
|
569
|
-
|
|
548
|
+
try {
|
|
549
|
+
// OnClosing is user code: it runs as a Framework turn through the
|
|
550
|
+
// execution gate while the Close lifecycle item keeps its FIFO slot.
|
|
551
|
+
await activation.serial.postBarrierTurn(() => (0, spot_closing_1.invokeSpotClosing)(activation.spot.onClosing?.bind(activation.spot), reason, deadline));
|
|
552
|
+
}
|
|
553
|
+
catch (error) {
|
|
554
|
+
// An OnClosing failure is diagnostic and cleanup continues. It is
|
|
555
|
+
// returned so host shutdown can classify its teardown outcome.
|
|
556
|
+
this.options.closeErrorSink?.reportRuntimeTaskException(`spot ${String(activation.spotId)} onClosing`, error);
|
|
557
|
+
closingFailure = error;
|
|
558
|
+
}
|
|
570
559
|
}
|
|
571
560
|
if (!state.timersDisposed) {
|
|
572
561
|
await cleanup(() => activation.timers.dispose(), () => {
|
|
573
562
|
state.timersDisposed = true;
|
|
574
563
|
});
|
|
575
564
|
}
|
|
576
|
-
|
|
565
|
+
if (!state.serialDisposed && state.timersDisposed) {
|
|
566
|
+
await cleanup(() => owningLifecycle
|
|
567
|
+
? activation.serialExecutor.closeChildren()
|
|
568
|
+
: activation.serialExecutor.close(), () => {
|
|
569
|
+
state.serialDisposed = true;
|
|
570
|
+
});
|
|
571
|
+
}
|
|
577
572
|
if (!state.handlersDisposed) {
|
|
578
573
|
await cleanup(() => (0, handler_instance_scope_1.disposeLifecycleHandlers)(activation.spot), () => {
|
|
579
574
|
state.handlersDisposed = true;
|
|
580
575
|
});
|
|
581
576
|
}
|
|
577
|
+
if (!state.actorDispatchDisposed) {
|
|
578
|
+
await cleanup(() => activation.actorDispatch?.dispose(), () => {
|
|
579
|
+
state.actorDispatchDisposed = true;
|
|
580
|
+
});
|
|
581
|
+
}
|
|
582
582
|
if (!state.nativeDisposed) {
|
|
583
|
-
await cleanup(() => activation.actorDispatch?.dispose(), () => undefined);
|
|
584
583
|
await cleanup(() => activation.nativeSpot?.dispose(), () => {
|
|
585
584
|
state.nativeDisposed = true;
|
|
586
585
|
});
|
|
587
586
|
}
|
|
588
|
-
if (!state.locationReleased
|
|
587
|
+
if (!state.locationReleased &&
|
|
588
|
+
state.timersDisposed &&
|
|
589
|
+
state.serialDisposed &&
|
|
590
|
+
state.handlersDisposed &&
|
|
591
|
+
state.actorDispatchDisposed &&
|
|
592
|
+
state.nativeDisposed) {
|
|
589
593
|
await cleanup(() => this.options.releaseLocation(activation, locationMeshName, activation.spotId), () => {
|
|
590
594
|
state.locationReleased = true;
|
|
591
595
|
});
|
|
@@ -595,6 +599,7 @@ class ZLinkSpotActivationLifecycle {
|
|
|
595
599
|
if (errors.length > 1) {
|
|
596
600
|
throw new AggregateError(errors, `Spot '${activation.spotId}' cleanup failed.`);
|
|
597
601
|
}
|
|
602
|
+
return closingFailure;
|
|
598
603
|
}
|
|
599
604
|
decodeCreateReply(reply) {
|
|
600
605
|
if (reply === undefined) {
|
|
@@ -6,7 +6,7 @@ import { type ZLinkRemoteBoundSessionTarget } from '../actors';
|
|
|
6
6
|
import type { ZLinkSpotActivationLifecycleOptions } from './spot-activation';
|
|
7
7
|
import { ZLinkSpotActivation } from './spot-activation-state';
|
|
8
8
|
import { ZLinkSpotActorJoinDispatch } from './spot-actor-join-dispatch';
|
|
9
|
-
type AdmissionOptions = Pick<ZLinkSpotActivationLifecycleOptions, 'actorHandoffRuntime' | 'admission' | 'actorResolver' | 'actorTransferRuntime' | 'boundSessionRuntime' | 'detachedTaskRunner' | 'dispatchErrors' | 'locationClaim' | 'messageSerializers' | 'nativeSpotNodeProvider' | '
|
|
9
|
+
type AdmissionOptions = Pick<ZLinkSpotActivationLifecycleOptions, 'actorHandoffRuntime' | 'admission' | 'actorResolver' | 'actorTransferRuntime' | 'boundSessionRuntime' | 'detachedTaskRunner' | 'dispatchErrors' | 'locationClaim' | 'messageSerializers' | 'nativeSpotNodeProvider' | 'createTopicMessage' | 'providerResolver' | 'runtimeEventPublisher' | 'routeToActorJoinPrewarm' | 'isSpotClosing'>;
|
|
10
10
|
export declare class ZLinkSpotActorAdmissionCoordinator {
|
|
11
11
|
private readonly options;
|
|
12
12
|
constructor(options: AdmissionOptions);
|
|
@@ -21,9 +21,9 @@ class ZLinkSpotActorAdmissionCoordinator {
|
|
|
21
21
|
return undefined;
|
|
22
22
|
const nativeDispatch = new spot_actor_join_dispatch_1.ZLinkSpotActorJoinDispatch({
|
|
23
23
|
nativeSpot,
|
|
24
|
-
createReceived: requireBackendValueFactory(this.options.createReceived, 'Received'),
|
|
25
24
|
createTopicMessage: requireBackendValueFactory(this.options.createTopicMessage, 'TopicMessage'),
|
|
26
25
|
serial: activation.serial,
|
|
26
|
+
isSpotClosing: () => this.options.isSpotClosing(activation),
|
|
27
27
|
actors: {
|
|
28
28
|
resolveActor: (actorId) => activation.hasDepartedActor(actorId)
|
|
29
29
|
? undefined
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { RoutingId, ZLinkActor, ZLinkMessage, ZLinkMessageSerializer, ZLinkSpotActorJoinResult } from '../../contracts';
|
|
2
2
|
import type { ZLinkProviderResolver } from '../../contracts/Common/ZLinkProviderResolver';
|
|
3
|
-
import type { ZLinkBackendActorRef, ZLinkBackendActorRecvInfo,
|
|
3
|
+
import type { ZLinkBackendActorRef, ZLinkBackendActorRecvInfo, ZLinkBackendSpot, ZLinkBackendTopicMessage } from '../backend/contracts';
|
|
4
4
|
import type { Message } from '../../contracts/Common/Message';
|
|
5
5
|
import type { RequestResult } from '../backend/runtime-values';
|
|
6
6
|
type RuntimeMessage = Message;
|
|
@@ -47,9 +47,9 @@ export interface ZLinkDetachedTaskRunner {
|
|
|
47
47
|
}
|
|
48
48
|
interface ZLinkSpotActorJoinDispatchOptions {
|
|
49
49
|
readonly nativeSpot: ZLinkBackendSpot;
|
|
50
|
-
readonly createReceived: () => ZLinkBackendReceived;
|
|
51
50
|
readonly createTopicMessage: () => ZLinkBackendTopicMessage;
|
|
52
51
|
readonly serial: ZLinkSpotSerialTurnExecutor;
|
|
52
|
+
readonly isSpotClosing?: () => boolean;
|
|
53
53
|
readonly actors: ZLinkSpotActorAdmissionRuntime;
|
|
54
54
|
readonly packets?: ZLinkSpotActorPacketRuntime;
|
|
55
55
|
readonly boundSessionRuntime?: ZLinkSpotBoundSessionRuntime;
|
|
@@ -54,10 +54,9 @@ class ZLinkSpotActorJoinDispatch {
|
|
|
54
54
|
dispatchErrors: options.dispatchErrors
|
|
55
55
|
});
|
|
56
56
|
this.routedFrames = new spot_routed_frame_dispatch_1.ZLinkSpotRoutedFrameDispatch({
|
|
57
|
-
nativeSpot: options.nativeSpot,
|
|
58
|
-
createReceived: options.createReceived,
|
|
59
57
|
nativeSpotId: this.nativeSpotId,
|
|
60
58
|
serial: options.serial,
|
|
59
|
+
isSpotClosing: options.isSpotClosing,
|
|
61
60
|
resolveActor: actors.resolveActor,
|
|
62
61
|
getTarget: () => actors.getTarget(),
|
|
63
62
|
defaultAccept: actors.defaultAccept,
|
|
@@ -78,8 +77,7 @@ class ZLinkSpotActorJoinDispatch {
|
|
|
78
77
|
messageSerializers: options.messageSerializers,
|
|
79
78
|
providerResolver: options.providerResolver,
|
|
80
79
|
dispatchErrors: options.dispatchErrors,
|
|
81
|
-
claimApplicationWork: options.claimApplicationWork
|
|
82
|
-
waitIdle: waitSpotDispatchIdle
|
|
80
|
+
claimApplicationWork: options.claimApplicationWork
|
|
83
81
|
});
|
|
84
82
|
this.subscriptions = new spot_subscription_dispatch_1.ZLinkSpotSubscriptionDispatch({
|
|
85
83
|
nativeSpot: options.nativeSpot,
|
|
@@ -175,7 +173,7 @@ class ZLinkSpotActorJoinDispatch {
|
|
|
175
173
|
await waitSpotDispatchIdle();
|
|
176
174
|
return;
|
|
177
175
|
}
|
|
178
|
-
await this.nativeActorJoinAdmission.admit(request);
|
|
176
|
+
await this.options.serial.executeLifecycleOperation(() => this.nativeActorJoinAdmission.admit(request, this.options.isSpotClosing?.() === true));
|
|
179
177
|
}
|
|
180
178
|
}
|
|
181
179
|
}
|
|
@@ -26,7 +26,7 @@ class ZLinkSpotActorLifecycleDrain {
|
|
|
26
26
|
}
|
|
27
27
|
if (actorRef === null || actorRef === undefined)
|
|
28
28
|
continue;
|
|
29
|
-
await this.options.serial.execute(() => {
|
|
29
|
+
await this.options.serial.executeLifecycleOperation(() => this.options.serial.execute(() => {
|
|
30
30
|
const actor = this.options.resolveActor(actorId);
|
|
31
31
|
if (actor === undefined) {
|
|
32
32
|
return undefined;
|
|
@@ -44,7 +44,7 @@ class ZLinkSpotActorLifecycleDrain {
|
|
|
44
44
|
return target.onDisconnectActor?.(actor);
|
|
45
45
|
}
|
|
46
46
|
return undefined;
|
|
47
|
-
});
|
|
47
|
+
}));
|
|
48
48
|
}
|
|
49
49
|
}
|
|
50
50
|
}
|