@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
|
@@ -44,7 +44,6 @@ Object.defineProperty(exports, "DefaultZLinkSpotHandlerRegistry", { enumerable:
|
|
|
44
44
|
var spot_publisher_transport_1 = require("./spot-publisher-transport");
|
|
45
45
|
Object.defineProperty(exports, "ZLinkRuntimeSpotPublisherTransport", { enumerable: true, get: function () { return spot_publisher_transport_1.ZLinkRuntimeSpotPublisherTransport; } });
|
|
46
46
|
const spot_activation_registry_1 = require("./spot-activation-registry");
|
|
47
|
-
const spot_activation_state_1 = require("./spot-activation-state");
|
|
48
47
|
const spot_activation_1 = require("./spot-activation");
|
|
49
48
|
const spot_actor_membership_1 = require("./spot-actor-membership");
|
|
50
49
|
const formal_remote_actor_transfer_registry_1 = require("./formal-remote-actor-transfer-registry");
|
|
@@ -74,8 +73,7 @@ class DefaultZLinkSpotManager {
|
|
|
74
73
|
// callbacks (isInstanceMaterializing, sibling-generation lookups) resolve
|
|
75
74
|
// in O(1) instead of scanning every pending key.
|
|
76
75
|
pendingInstanceMaterializationsByPrefix = new Map();
|
|
77
|
-
|
|
78
|
-
pendingInstanceCloses = new Map();
|
|
76
|
+
closeOperations = new Map();
|
|
79
77
|
pendingInstanceTerminals = new Map();
|
|
80
78
|
pendingInstanceTerminalGenerations = new Map();
|
|
81
79
|
deferredInstanceAuthorityReleases = new Map();
|
|
@@ -83,7 +81,7 @@ class DefaultZLinkSpotManager {
|
|
|
83
81
|
idleSweepRunning = false;
|
|
84
82
|
constructor(options, timerClock) {
|
|
85
83
|
this.options = options;
|
|
86
|
-
this.activations = new spot_activation_registry_1.ZLinkSpotActivationRegistry(options.metrics);
|
|
84
|
+
this.activations = new spot_activation_registry_1.ZLinkSpotActivationRegistry(options.metrics, (meshName, spotId) => this.isSpotClosing(meshName, spotId));
|
|
87
85
|
this.factories = new Set(options.spotFactories);
|
|
88
86
|
this.workerRuntime = options.workerRuntime ?? new workers_1.ZLinkWorkerRuntime();
|
|
89
87
|
this.locationClaim = new spot_location_claim_1.ZLinkSpotLocationClaim({
|
|
@@ -101,6 +99,8 @@ class DefaultZLinkSpotManager {
|
|
|
101
99
|
dispatchErrors: options.dispatchErrors
|
|
102
100
|
});
|
|
103
101
|
this.actorMembership = new spot_actor_membership_1.ZLinkSpotActorMembership({
|
|
102
|
+
isSpotClosing: (activation) => this.isSpotClosing(activation.meshName, activation.spotId) ||
|
|
103
|
+
this.activations.resolve(activation.meshName, activation.spotId) !== activation,
|
|
104
104
|
resolveActivation: (spotId, meshName) => meshName === undefined
|
|
105
105
|
? this.activations.resolveUnique(spotId)
|
|
106
106
|
: this.activations.resolve(meshName, spotId),
|
|
@@ -136,12 +136,12 @@ class DefaultZLinkSpotManager {
|
|
|
136
136
|
spotRouterChannelIdForMesh: options.spotRouterChannelIdForMesh,
|
|
137
137
|
providerResolver: options.providerResolver,
|
|
138
138
|
dispatchErrors: options.dispatchErrors,
|
|
139
|
+
closeErrorSink: options.closeErrorSink,
|
|
139
140
|
runtimeEventPublisher: options.runtimeEventPublisher,
|
|
140
141
|
workerRuntime: this.workerRuntime,
|
|
141
142
|
messageSerializers: options.messageSerializers,
|
|
142
143
|
locationClaim: this.locationClaim,
|
|
143
144
|
createNativeSpot: options.createNativeSpot,
|
|
144
|
-
createReceived: options.createReceived,
|
|
145
145
|
createTopicMessage: options.createTopicMessage,
|
|
146
146
|
nativeSpotNodeProvider: options.nativeSpotNodeProvider,
|
|
147
147
|
actorResolver: options.actorResolver,
|
|
@@ -152,7 +152,9 @@ class DefaultZLinkSpotManager {
|
|
|
152
152
|
admission: options.admission,
|
|
153
153
|
statefulExecutionAllowed: options.statefulExecutionAllowed,
|
|
154
154
|
leaveActor: (spotId, actor, signal, meshName) => this.actorMembership.leaveActor(spotId, actor, signal, meshName),
|
|
155
|
-
|
|
155
|
+
requestContextClose: (activation, objectGeneration, signal) => this.closeFromContext(activation, objectGeneration, signal),
|
|
156
|
+
isSpotClosing: (activation) => this.isSpotClosing(activation.meshName, activation.spotId) ||
|
|
157
|
+
this.activations.resolve(activation.meshName, activation.spotId) !== activation,
|
|
156
158
|
registerActivation: (activation) => {
|
|
157
159
|
this.activations.register(activation);
|
|
158
160
|
this.scheduleIdleSweep();
|
|
@@ -199,10 +201,6 @@ class DefaultZLinkSpotManager {
|
|
|
199
201
|
activeSpotCount(meshName) {
|
|
200
202
|
return this.activations.list(meshName).length;
|
|
201
203
|
}
|
|
202
|
-
instanceActivationConcurrency(meshName) {
|
|
203
|
-
const limit = this.options.activationConcurrencyLimitProvider?.(meshName) ?? 128;
|
|
204
|
-
return { active: this.instanceActivationGates.get(meshName)?.active ?? 0, limit };
|
|
205
|
-
}
|
|
206
204
|
resolveRelocationActivation(meshName, spotId) {
|
|
207
205
|
return this.activations.resolve(meshName, spotId);
|
|
208
206
|
}
|
|
@@ -237,12 +235,12 @@ class DefaultZLinkSpotManager {
|
|
|
237
235
|
await (0, abort_1.awaitWithAbort)(existing, signal);
|
|
238
236
|
return;
|
|
239
237
|
}
|
|
240
|
-
const release = await this.
|
|
238
|
+
const release = await this.options.activationAdmission?.acquire(meshName, signal);
|
|
241
239
|
try {
|
|
242
240
|
await this.materializeInstanceCore(meshName, instanceType, spotId, objectGeneration, readyTarget?.objectGeneration === objectGeneration, signal);
|
|
243
241
|
}
|
|
244
242
|
finally {
|
|
245
|
-
release();
|
|
243
|
+
release?.();
|
|
246
244
|
}
|
|
247
245
|
}
|
|
248
246
|
async materializeInstanceCore(meshName, instanceType, spotId, objectGeneration, requiresReadyTarget, signal) {
|
|
@@ -260,11 +258,16 @@ class DefaultZLinkSpotManager {
|
|
|
260
258
|
// explicit Instance intent arriving at that boundary must wait for the
|
|
261
259
|
// old resources to be released before materializing the replacement.
|
|
262
260
|
// This is lifecycle convergence; it does not resubmit application work.
|
|
263
|
-
const
|
|
261
|
+
const closeOperation = this.closeOperations.get(key);
|
|
262
|
+
const pendingClose = closeOperation?.ready;
|
|
264
263
|
if (pendingClose !== undefined) {
|
|
265
264
|
await (0, abort_1.awaitWithAbort)(pendingClose, signal);
|
|
266
265
|
continue;
|
|
267
266
|
}
|
|
267
|
+
if (closeOperation?.committed === true) {
|
|
268
|
+
await (0, abort_1.awaitWithAbort)(this.closeWithReason(meshName, spotId), signal);
|
|
269
|
+
continue;
|
|
270
|
+
}
|
|
268
271
|
const closing = this.activations.closingOperation(meshName, spotId);
|
|
269
272
|
if (closing !== undefined) {
|
|
270
273
|
await (0, abort_1.awaitWithAbort)(closing.ready, signal);
|
|
@@ -340,58 +343,6 @@ class DefaultZLinkSpotManager {
|
|
|
340
343
|
return;
|
|
341
344
|
}
|
|
342
345
|
}
|
|
343
|
-
async acquireInstanceActivation(meshName, signal) {
|
|
344
|
-
let gate = this.instanceActivationGates.get(meshName);
|
|
345
|
-
if (gate === undefined) {
|
|
346
|
-
gate = {
|
|
347
|
-
meshName,
|
|
348
|
-
limit: this.options.activationConcurrencyLimitProvider?.(meshName) ?? 128,
|
|
349
|
-
active: 0,
|
|
350
|
-
waiters: [],
|
|
351
|
-
waiterHead: 0
|
|
352
|
-
};
|
|
353
|
-
this.instanceActivationGates.set(meshName, gate);
|
|
354
|
-
}
|
|
355
|
-
if (signal?.aborted === true)
|
|
356
|
-
throw signal.reason;
|
|
357
|
-
if (gate.active < gate.limit) {
|
|
358
|
-
gate.active += 1;
|
|
359
|
-
this.options.onInstanceActivationConcurrencyChanged?.(meshName);
|
|
360
|
-
return () => this.releaseInstanceActivation(gate);
|
|
361
|
-
}
|
|
362
|
-
return new Promise((resolve, reject) => {
|
|
363
|
-
const waiter = { resolve, reject, signal, abort: undefined };
|
|
364
|
-
const slot = gate.waiters.length;
|
|
365
|
-
waiter.abort = () => {
|
|
366
|
-
if (gate.waiters[slot] === waiter)
|
|
367
|
-
gate.waiters[slot] = undefined;
|
|
368
|
-
reject(signal?.reason);
|
|
369
|
-
};
|
|
370
|
-
signal?.addEventListener('abort', waiter.abort, { once: true });
|
|
371
|
-
gate.waiters.push(waiter);
|
|
372
|
-
});
|
|
373
|
-
}
|
|
374
|
-
releaseInstanceActivation(gate) {
|
|
375
|
-
while (gate.waiterHead < gate.waiters.length) {
|
|
376
|
-
const waiter = gate.waiters[gate.waiterHead];
|
|
377
|
-
gate.waiters[gate.waiterHead] = undefined;
|
|
378
|
-
gate.waiterHead += 1;
|
|
379
|
-
if (gate.waiterHead >= gate.waiters.length) {
|
|
380
|
-
gate.waiters.length = 0;
|
|
381
|
-
gate.waiterHead = 0;
|
|
382
|
-
}
|
|
383
|
-
if (waiter === undefined)
|
|
384
|
-
continue;
|
|
385
|
-
if (waiter.abort !== undefined)
|
|
386
|
-
waiter.signal?.removeEventListener('abort', waiter.abort);
|
|
387
|
-
waiter.resolve(() => this.releaseInstanceActivation(gate));
|
|
388
|
-
return;
|
|
389
|
-
}
|
|
390
|
-
gate.waiters.length = 0;
|
|
391
|
-
gate.waiterHead = 0;
|
|
392
|
-
gate.active -= 1;
|
|
393
|
-
this.options.onInstanceActivationConcurrencyChanged?.(gate.meshName);
|
|
394
|
-
}
|
|
395
346
|
isInstanceMaterialized(meshName, instanceType, spotId) {
|
|
396
347
|
const activation = this.activations.resolve(meshName, spotId);
|
|
397
348
|
return (activation !== undefined &&
|
|
@@ -401,10 +352,15 @@ class DefaultZLinkSpotManager {
|
|
|
401
352
|
const prefix = instanceMaterializationPrefix(meshName, spotId);
|
|
402
353
|
return (this.pendingInstanceMaterializationsByPrefix.get(prefix)?.size ?? 0) > 0;
|
|
403
354
|
}
|
|
404
|
-
|
|
355
|
+
isSpotClosing(meshName, spotId) {
|
|
405
356
|
const key = `${meshName}\0${String(spotId)}`;
|
|
406
|
-
return
|
|
407
|
-
|
|
357
|
+
return this.closeOperations.get(key)?.committed === true;
|
|
358
|
+
}
|
|
359
|
+
pendingSpotCloseDecision(meshName, spotId) {
|
|
360
|
+
return this.closeOperations.get(`${meshName}\0${String(spotId)}`)?.authorityDecision;
|
|
361
|
+
}
|
|
362
|
+
isInstanceClosing(meshName, spotId) {
|
|
363
|
+
return this.closeOperations.has(`${meshName}\0${String(spotId)}`);
|
|
408
364
|
}
|
|
409
365
|
async discardInstance(meshName, spotId) {
|
|
410
366
|
const activation = this.activations.resolve(meshName, spotId);
|
|
@@ -443,7 +399,7 @@ class DefaultZLinkSpotManager {
|
|
|
443
399
|
}
|
|
444
400
|
this.pendingInstanceTerminals.delete(key);
|
|
445
401
|
this.pendingInstanceTerminalGenerations.delete(key);
|
|
446
|
-
const pendingClose = this.
|
|
402
|
+
const pendingClose = this.closeOperations.get(key)?.ready;
|
|
447
403
|
if (pendingClose !== undefined) {
|
|
448
404
|
this.deferInstanceAuthorityRelease(key, objectGeneration);
|
|
449
405
|
await pendingClose;
|
|
@@ -539,32 +495,16 @@ class DefaultZLinkSpotManager {
|
|
|
539
495
|
!activation.beginIdleEviction()) {
|
|
540
496
|
continue;
|
|
541
497
|
}
|
|
542
|
-
let durableClosing;
|
|
543
|
-
try {
|
|
544
|
-
durableClosing = await (this.options.beginInstanceIdleClosingAuthority?.(activation.meshName, activation.spotId) ?? Promise.resolve({ restoreReady: async () => undefined }));
|
|
545
|
-
}
|
|
546
|
-
catch (error) {
|
|
547
|
-
activation.abortIdleEviction();
|
|
548
|
-
throw error;
|
|
549
|
-
}
|
|
550
|
-
if (durableClosing === undefined) {
|
|
551
|
-
activation.abortIdleEviction();
|
|
552
|
-
continue;
|
|
553
|
-
}
|
|
554
498
|
const close = this.closeWithReason(activation.meshName, activation.spotId, undefined, contracts_1.ZLinkSpotCloseReason.IdleEvicted);
|
|
555
499
|
const run = async () => {
|
|
556
500
|
try {
|
|
557
501
|
const closed = await close;
|
|
558
|
-
if (!closed)
|
|
559
|
-
await durableClosing.restoreReady();
|
|
502
|
+
if (!closed)
|
|
560
503
|
activation.abortIdleEviction();
|
|
561
|
-
}
|
|
562
504
|
}
|
|
563
505
|
catch (error) {
|
|
564
|
-
if (
|
|
565
|
-
|
|
566
|
-
}
|
|
567
|
-
activation.abortIdleEviction();
|
|
506
|
+
if (!this.isSpotClosing(activation.meshName, activation.spotId))
|
|
507
|
+
activation.abortIdleEviction();
|
|
568
508
|
throw error;
|
|
569
509
|
}
|
|
570
510
|
};
|
|
@@ -603,6 +543,7 @@ class DefaultZLinkSpotManager {
|
|
|
603
543
|
(0, abort_1.throwIfAborted)(args.signal);
|
|
604
544
|
const operation = this.activations.getOrBegin(meshName, spotType, spotId, async () => {
|
|
605
545
|
this.options.admission?.requireRequest('SPOT create', meshName);
|
|
546
|
+
const release = await this.options.activationAdmission?.acquire(meshName, args.signal);
|
|
606
547
|
const ownedRequest = args.request === undefined
|
|
607
548
|
? runtime_message_1.ZLinkBufferMessage.from(Buffer.alloc(0))
|
|
608
549
|
: (0, payload_codec_1.encodeFrameworkPayloadMessage)(args.request, this.options.messageSerializers);
|
|
@@ -611,6 +552,7 @@ class DefaultZLinkSpotManager {
|
|
|
611
552
|
}
|
|
612
553
|
finally {
|
|
613
554
|
ownedRequest.close();
|
|
555
|
+
release?.();
|
|
614
556
|
}
|
|
615
557
|
});
|
|
616
558
|
return await (0, abort_1.awaitWithAbort)(operation.ready, args.signal);
|
|
@@ -639,99 +581,109 @@ class DefaultZLinkSpotManager {
|
|
|
639
581
|
async close(meshName, spotId, signal) {
|
|
640
582
|
return await this.closeWithReason(meshName, spotId, signal, contracts_1.ZLinkSpotCloseReason.ExplicitClose);
|
|
641
583
|
}
|
|
642
|
-
async
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
const pendingActivation = this.activations.resolve(meshName, spotId);
|
|
652
|
-
if (pendingActivation?.serial.isCurrentTurn === true)
|
|
653
|
-
return true;
|
|
654
|
-
return await pendingClose;
|
|
584
|
+
async closeUserWithAuthority(meshName, spotId, beginAuthority, signal) {
|
|
585
|
+
return await this.closeWithReason(meshName, spotId, signal, contracts_1.ZLinkSpotCloseReason.ExplicitClose, undefined, beginAuthority);
|
|
586
|
+
}
|
|
587
|
+
closeFromContext(activation, objectGeneration, signal) {
|
|
588
|
+
const { meshName, spotId } = activation;
|
|
589
|
+
const operation = this.closeOperations.get(`${meshName}\0${String(spotId)}`);
|
|
590
|
+
const current = operation?.activation ?? this.activations.resolve(meshName, spotId);
|
|
591
|
+
if (current === undefined) {
|
|
592
|
+
return Promise.resolve(false);
|
|
655
593
|
}
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
return false;
|
|
594
|
+
if (current !== activation || current.objectGeneration !== objectGeneration) {
|
|
595
|
+
return Promise.reject((0, framework_errors_internal_1.createInternalFrameworkException)(framework_errors_internal_1.ZLinkFrameworkInternalErrorKind.InvalidOperation, `Spot '${String(spotId)}' generation is stale.`));
|
|
659
596
|
}
|
|
660
|
-
const
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
const
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
597
|
+
const beginUserAuthority = activation.domain.kind === 'user' && this.options.beginUserClosingAuthority !== undefined
|
|
598
|
+
? (onCommitted) => this.options.beginUserClosingAuthority(meshName, spotId, objectGeneration, onCommitted)
|
|
599
|
+
: undefined;
|
|
600
|
+
return this.closeWithReason(meshName, spotId, signal, contracts_1.ZLinkSpotCloseReason.ExplicitClose, undefined, beginUserAuthority);
|
|
601
|
+
}
|
|
602
|
+
async closeWithReason(meshName, spotId, signal, reason = contracts_1.ZLinkSpotCloseReason.ExplicitClose, deadline, beginUserAuthority) {
|
|
603
|
+
requireMeshName(meshName);
|
|
604
|
+
const key = `${meshName}\0${String(spotId)}`;
|
|
605
|
+
let operation = this.closeOperations.get(key);
|
|
606
|
+
if (operation === undefined) {
|
|
607
|
+
const activation = this.activations.resolve(meshName, spotId);
|
|
608
|
+
if (activation === undefined)
|
|
609
|
+
return false;
|
|
610
|
+
if (activation.domain.kind === 'user' &&
|
|
611
|
+
reason === contracts_1.ZLinkSpotCloseReason.ExplicitClose &&
|
|
612
|
+
beginUserAuthority === undefined) {
|
|
613
|
+
throw (0, framework_errors_internal_1.createInternalFrameworkException)(framework_errors_internal_1.ZLinkFrameworkInternalErrorKind.InvalidOperation, `User Spot '${String(spotId)}' Close requires its authority owner.`);
|
|
614
|
+
}
|
|
615
|
+
const beginAuthority = beginUserAuthority ??
|
|
616
|
+
(activation.domain.kind === 'instance' &&
|
|
617
|
+
reason === contracts_1.ZLinkSpotCloseReason.ExplicitClose &&
|
|
618
|
+
this.options.beginInstanceClosingAuthority !== undefined
|
|
619
|
+
? (onCommitted) => this.options.beginInstanceClosingAuthority(meshName, spotId, onCommitted)
|
|
620
|
+
: activation.domain.kind === 'instance' &&
|
|
621
|
+
reason === contracts_1.ZLinkSpotCloseReason.IdleEvicted &&
|
|
622
|
+
this.options.beginInstanceIdleClosingAuthority !== undefined
|
|
623
|
+
? (onCommitted) => this.options.beginInstanceIdleClosingAuthority(meshName, spotId, onCommitted)
|
|
624
|
+
: async (onCommitted) => {
|
|
625
|
+
onCommitted();
|
|
626
|
+
return { release: async () => undefined };
|
|
627
|
+
});
|
|
628
|
+
operation = {
|
|
629
|
+
activation,
|
|
630
|
+
reason,
|
|
631
|
+
beginAuthority,
|
|
632
|
+
committed: false
|
|
633
|
+
};
|
|
634
|
+
this.closeOperations.set(key, operation);
|
|
635
|
+
}
|
|
636
|
+
if (operation.ready === undefined) {
|
|
637
|
+
const active = operation;
|
|
638
|
+
const run = active.activation.serial.executeLifecycleOperation(() => this.runCloseOperation(meshName, spotId, active, signal, deadline));
|
|
639
|
+
active.ready = run.finally(() => {
|
|
640
|
+
active.ready = undefined;
|
|
641
|
+
if (this.closeOperations.get(key) === active) {
|
|
642
|
+
this.closeOperations.delete(key);
|
|
701
643
|
}
|
|
702
644
|
});
|
|
703
|
-
this.pendingInstanceCloses.set(key, trackedClosePromise);
|
|
704
|
-
if (currentTurn) {
|
|
705
|
-
// The current turn must return before its terminal completion can
|
|
706
|
-
// release the activation recovery fence and allow the durable close
|
|
707
|
-
// CAS. The registered close gate prevents a second admission while
|
|
708
|
-
// that detached close finishes.
|
|
709
|
-
this.options.detachedTaskRunner?.runDetached(`instance spot close ${String(spotId)}`, async () => {
|
|
710
|
-
await trackedClosePromise;
|
|
711
|
-
});
|
|
712
|
-
if (this.options.detachedTaskRunner === undefined) {
|
|
713
|
-
void trackedClosePromise.catch(() => undefined);
|
|
714
|
-
}
|
|
715
|
-
return true;
|
|
716
|
-
}
|
|
717
|
-
return await trackedClosePromise;
|
|
718
645
|
}
|
|
719
|
-
|
|
720
|
-
|
|
646
|
+
return await operation.ready;
|
|
647
|
+
}
|
|
648
|
+
async runCloseOperation(meshName, spotId, operation, signal, deadline) {
|
|
649
|
+
const began = await this.beginCloseAuthority(meshName, spotId, operation, signal);
|
|
650
|
+
if (!began)
|
|
721
651
|
return false;
|
|
652
|
+
const seal = operation.activation.sealExecution(true);
|
|
653
|
+
await this.activationLifecycle.sealForClose(operation.activation, seal);
|
|
654
|
+
const closingFailure = await this.activationLifecycle.cleanupClosedActivation(operation.activation, operation.reason, deadline);
|
|
655
|
+
await operation.authority?.release();
|
|
656
|
+
// The incarnation has no further lifecycle item once its authority is
|
|
657
|
+
// released, so its lifecycle lane admission closes with this Close.
|
|
658
|
+
operation.activation.serial.closeAdmission();
|
|
659
|
+
this.activations.finishClose(meshName, spotId);
|
|
660
|
+
this.closeOperations.delete(`${meshName}\0${String(spotId)}`);
|
|
661
|
+
// An OnClosing failure never changes a Close result; host shutdown alone
|
|
662
|
+
// reports it as its teardown outcome after cleanup has finished.
|
|
663
|
+
if (closingFailure !== undefined && operation.reason === contracts_1.ZLinkSpotCloseReason.HostShutdown) {
|
|
664
|
+
throw closingFailure;
|
|
722
665
|
}
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
666
|
+
return true;
|
|
667
|
+
}
|
|
668
|
+
async beginCloseAuthority(meshName, spotId, operation, signal) {
|
|
669
|
+
await this.options.instanceSpotApplicationQuiescenceProvider?.(meshName, spotId, signal);
|
|
670
|
+
if (!operation.activation.canClose(operation.reason))
|
|
671
|
+
return false;
|
|
672
|
+
if (operation.activation.executionBarrier.isSealed) {
|
|
673
|
+
throw (0, framework_errors_internal_1.createInternalFrameworkException)(framework_errors_internal_1.ZLinkFrameworkInternalErrorKind.SpotMoving, `Spot '${String(spotId)}' is sealed for relocation.`, true);
|
|
674
|
+
}
|
|
675
|
+
const authorityPromise = Promise.resolve().then(() => operation.beginAuthority(() => {
|
|
676
|
+
operation.committed = true;
|
|
677
|
+
}));
|
|
678
|
+
operation.authorityDecision = authorityPromise.then(() => undefined, () => undefined);
|
|
679
|
+
const authority = await authorityPromise;
|
|
680
|
+
if (authority === undefined)
|
|
681
|
+
return false;
|
|
682
|
+
operation.authority = authority;
|
|
683
|
+
if (!this.isSpotClosing(meshName, spotId)) {
|
|
684
|
+
throw new Error(`Spot '${String(spotId)}' Closing authority did not confirm its commit.`);
|
|
733
685
|
}
|
|
734
|
-
return
|
|
686
|
+
return true;
|
|
735
687
|
}
|
|
736
688
|
async executeOnSpot(spotType, spotId, operation, signal) {
|
|
737
689
|
(0, abort_1.throwIfAborted)(signal);
|
|
@@ -750,9 +702,6 @@ class DefaultZLinkSpotManager {
|
|
|
750
702
|
hasActiveSpot(spotId) {
|
|
751
703
|
return this.activations.resolveUnique(spotId) !== undefined;
|
|
752
704
|
}
|
|
753
|
-
canCloseUserSpot(meshName, spotId) {
|
|
754
|
-
return this.activations.canClose(meshName, spotId);
|
|
755
|
-
}
|
|
756
705
|
beginUserSpotPublication(meshName, spotId) {
|
|
757
706
|
this.activations.stage(meshName, spotId);
|
|
758
707
|
}
|
|
@@ -884,7 +833,7 @@ class DefaultZLinkSpotManager {
|
|
|
884
833
|
requireMeshSpotReply(record.reply((0, channel_envelope_1.encodeChannelReplyParts)(envelope.header, response, codecs)));
|
|
885
834
|
}
|
|
886
835
|
catch (error) {
|
|
887
|
-
requireMeshSpotReply(record.reply((0, channel_envelope_1.encodeChannelErrorReplyParts)(envelope.header, error
|
|
836
|
+
requireMeshSpotReply(record.reply((0, channel_envelope_1.encodeChannelErrorReplyParts)(envelope.header, error)));
|
|
888
837
|
}
|
|
889
838
|
}
|
|
890
839
|
async ensureInstanceApplicationActivation(meshName, spotId) {
|
|
@@ -975,7 +924,7 @@ class DefaultZLinkSpotManager {
|
|
|
975
924
|
action: ZLinkDispatchOptions_1.ZLinkRuntimeDispatchErrorAction.ReplyError,
|
|
976
925
|
error
|
|
977
926
|
});
|
|
978
|
-
requireMeshSpotReply(record.reply((0, channel_envelope_1.encodeChannelErrorReplyParts)(envelope.header, error
|
|
927
|
+
requireMeshSpotReply(record.reply((0, channel_envelope_1.encodeChannelErrorReplyParts)(envelope.header, error)));
|
|
979
928
|
}
|
|
980
929
|
});
|
|
981
930
|
}
|
|
@@ -1074,6 +1023,29 @@ class DefaultZLinkSpotManager {
|
|
|
1074
1023
|
}
|
|
1075
1024
|
}
|
|
1076
1025
|
async dispatchMeshActorJoin(meshName, owner, record) {
|
|
1026
|
+
const spotId = owner.spotId;
|
|
1027
|
+
const activation = spotId === null ? undefined : this.activations.resolve(meshName, spotId);
|
|
1028
|
+
if (activation?.domain.kind === 'user') {
|
|
1029
|
+
await activation.serial.executeLifecycleOperation(async () => {
|
|
1030
|
+
if (this.isSpotClosing(meshName, activation.spotId) ||
|
|
1031
|
+
this.activations.resolve(meshName, activation.spotId) !== activation) {
|
|
1032
|
+
const rejection = (0, framework_errors_internal_1.createInternalFrameworkException)(framework_errors_internal_1.ZLinkFrameworkInternalErrorKind.RequestRejected, `User Spot '${String(spotId)}' is closing.`);
|
|
1033
|
+
if (record.replyFailure !== undefined) {
|
|
1034
|
+
const terminal = (0, framework_errors_internal_1.internalFrameworkWireReply)(rejection);
|
|
1035
|
+
requireMeshSpotReply(record.replyFailure(terminal.terminalResult, terminal.failureCode));
|
|
1036
|
+
}
|
|
1037
|
+
else {
|
|
1038
|
+
requireMeshSpotReply(record.replyActorJoin(1, []));
|
|
1039
|
+
}
|
|
1040
|
+
return;
|
|
1041
|
+
}
|
|
1042
|
+
await this.dispatchMeshActorJoinCore(meshName, owner, record);
|
|
1043
|
+
});
|
|
1044
|
+
return;
|
|
1045
|
+
}
|
|
1046
|
+
await this.dispatchMeshActorJoinCore(meshName, owner, record);
|
|
1047
|
+
}
|
|
1048
|
+
async dispatchMeshActorJoinCore(meshName, owner, record) {
|
|
1077
1049
|
const spotId = owner.spotId;
|
|
1078
1050
|
const control = record.kindData;
|
|
1079
1051
|
if (control?.kind !== 'actorControl') {
|
|
@@ -1157,7 +1129,7 @@ class DefaultZLinkSpotManager {
|
|
|
1157
1129
|
let ownedCallbackRequest;
|
|
1158
1130
|
let materialized = false;
|
|
1159
1131
|
let reply;
|
|
1160
|
-
let
|
|
1132
|
+
let deferredJoinCompletion;
|
|
1161
1133
|
let preparedTransferState;
|
|
1162
1134
|
let admissionOutcome;
|
|
1163
1135
|
let accepted = false;
|
|
@@ -1286,13 +1258,13 @@ class DefaultZLinkSpotManager {
|
|
|
1286
1258
|
if (this.options.dispatchEntryActorJoin !== undefined &&
|
|
1287
1259
|
transferRequest.completionOperationId !== undefined &&
|
|
1288
1260
|
this.options.actorTransferRuntime !== undefined) {
|
|
1289
|
-
|
|
1290
|
-
|
|
1261
|
+
deferredJoinCompletion =
|
|
1262
|
+
this.options.actorTransferRuntime.prepareDeferredJoinAccepted(actorId, transferRequest.completionOperationId, actorRef, Buffer.alloc(0));
|
|
1291
1263
|
}
|
|
1292
1264
|
admissionOutcome = {
|
|
1293
1265
|
accepted: this.options.dispatchEntryActorJoin !== undefined,
|
|
1294
1266
|
actorRef,
|
|
1295
|
-
...(
|
|
1267
|
+
...(deferredJoinCompletion === undefined ? {} : { deferredJoinCompletion })
|
|
1296
1268
|
};
|
|
1297
1269
|
}
|
|
1298
1270
|
else if (activation === undefined) {
|
|
@@ -1313,8 +1285,8 @@ class DefaultZLinkSpotManager {
|
|
|
1313
1285
|
if (response.accepted &&
|
|
1314
1286
|
transferRequest.completionOperationId !== undefined &&
|
|
1315
1287
|
this.options.actorTransferRuntime !== undefined) {
|
|
1316
|
-
|
|
1317
|
-
|
|
1288
|
+
deferredJoinCompletion =
|
|
1289
|
+
this.options.actorTransferRuntime.prepareDeferredJoinAccepted(actorId, transferRequest.completionOperationId, actorRef, encodedReply?.data() ?? Buffer.alloc(0), encodedReply === undefined
|
|
1318
1290
|
? undefined
|
|
1319
1291
|
: (0, payload_codec_1.frameworkPayloadContentType)(encodedReply));
|
|
1320
1292
|
this.options.runtimeEventPublisher?.publish({
|
|
@@ -1327,7 +1299,7 @@ class DefaultZLinkSpotManager {
|
|
|
1327
1299
|
admissionOutcome = {
|
|
1328
1300
|
accepted: response.accepted,
|
|
1329
1301
|
actorRef,
|
|
1330
|
-
...(
|
|
1302
|
+
...(deferredJoinCompletion === undefined ? {} : { deferredJoinCompletion }),
|
|
1331
1303
|
...(encodedReply === undefined
|
|
1332
1304
|
? {}
|
|
1333
1305
|
: {
|
|
@@ -1366,7 +1338,7 @@ class DefaultZLinkSpotManager {
|
|
|
1366
1338
|
if ('error' in admissionOutcome) {
|
|
1367
1339
|
throw admissionOutcome.error;
|
|
1368
1340
|
}
|
|
1369
|
-
|
|
1341
|
+
deferredJoinCompletion = admissionOutcome.deferredJoinCompletion;
|
|
1370
1342
|
}
|
|
1371
1343
|
if (actor === undefined &&
|
|
1372
1344
|
transferRequest !== undefined &&
|
|
@@ -1436,7 +1408,7 @@ class DefaultZLinkSpotManager {
|
|
|
1436
1408
|
if (accepted &&
|
|
1437
1409
|
transferRequest?.completionOperationId !== undefined &&
|
|
1438
1410
|
this.options.actorTransferRuntime !== undefined) {
|
|
1439
|
-
|
|
1411
|
+
deferredJoinCompletion = this.options.actorTransferRuntime.prepareDeferredJoinAccepted(actorId, transferRequest.completionOperationId, actorRef, reply?.data() ?? Buffer.alloc(0), reply === undefined ? undefined : (0, payload_codec_1.frameworkPayloadContentType)(reply));
|
|
1440
1412
|
this.options.runtimeEventPublisher?.publish({
|
|
1441
1413
|
sourceName: 'zlink.framework.actor-handoff',
|
|
1442
1414
|
timestamp: new Date(),
|
|
@@ -1481,7 +1453,7 @@ class DefaultZLinkSpotManager {
|
|
|
1481
1453
|
// A lightweight Core actor-join notification can create the Actor
|
|
1482
1454
|
// before the formal transfer request reaches this branch. Preserve
|
|
1483
1455
|
// the full relocation fence in that race so a later Session bind
|
|
1484
|
-
// refresh cannot erase the seal
|
|
1456
|
+
// refresh cannot erase the seal.
|
|
1485
1457
|
this.options.actorTransferRuntime.rememberRoutedActorTransferTarget(actorId, transferRequest.remoteBoundSessionTarget);
|
|
1486
1458
|
}
|
|
1487
1459
|
if (accepted &&
|
|
@@ -1494,7 +1466,7 @@ class DefaultZLinkSpotManager {
|
|
|
1494
1466
|
spotId,
|
|
1495
1467
|
transferId: transferRequest.transferId,
|
|
1496
1468
|
handoffBacklog: transferRequest.handoffBacklog,
|
|
1497
|
-
|
|
1469
|
+
deferredJoinCompletion
|
|
1498
1470
|
});
|
|
1499
1471
|
if (isRemoteCommit && admissionRecord !== undefined) {
|
|
1500
1472
|
this.formalRemoteActorAdmissions.markCommitted(transferRequest.transferId, actor);
|
|
@@ -1583,9 +1555,6 @@ class DefaultZLinkSpotManager {
|
|
|
1583
1555
|
if (control.canonicalActorJoin !== undefined) {
|
|
1584
1556
|
this.formalRemoteActorAdmissions.fail(control.canonicalActorJoin.handoffId, error);
|
|
1585
1557
|
}
|
|
1586
|
-
if (deferredJoinRoot !== undefined && targetCommitPublished !== true) {
|
|
1587
|
-
await this.options.actorTransferRuntime?.discardDeferredJoinAccepted(deferredJoinRoot);
|
|
1588
|
-
}
|
|
1589
1558
|
if (targetCommitPublished !== true) {
|
|
1590
1559
|
this.formalRemoteTransfers.delete(actorId);
|
|
1591
1560
|
}
|
|
@@ -1602,6 +1571,33 @@ class DefaultZLinkSpotManager {
|
|
|
1602
1571
|
}
|
|
1603
1572
|
}
|
|
1604
1573
|
async dispatchMeshSpotControl(meshName, owner, record) {
|
|
1574
|
+
const spotId = owner.spotId;
|
|
1575
|
+
const activation = spotId === null ? undefined : this.activations.resolve(meshName, spotId);
|
|
1576
|
+
if (activation?.domain.kind === 'user') {
|
|
1577
|
+
const transfer = { terminal: undefined };
|
|
1578
|
+
const operation = activation.serial.executeLifecycleOperation(async () => {
|
|
1579
|
+
await this.dispatchMeshSpotControlCore(meshName, owner, record, (terminal) => {
|
|
1580
|
+
transfer.terminal = terminal;
|
|
1581
|
+
});
|
|
1582
|
+
await transfer.terminal;
|
|
1583
|
+
});
|
|
1584
|
+
const control = record.kindData;
|
|
1585
|
+
const actorId = control?.kind === 'actorControl' ? control.currentActor?.actorId : undefined;
|
|
1586
|
+
if (control?.kind === 'actorControl' &&
|
|
1587
|
+
control.lifecycleKind === service_runtime_contracts_1.ActorLifecycleKind.Joined &&
|
|
1588
|
+
actorId !== undefined &&
|
|
1589
|
+
this.formalRemoteTransfers.get(actorId) !== undefined) {
|
|
1590
|
+
this.options.detachedTaskRunner?.runDetached(`actor transfer target commit ${actorId}`, async () => await operation);
|
|
1591
|
+
if (this.options.detachedTaskRunner === undefined)
|
|
1592
|
+
void operation.catch(() => undefined);
|
|
1593
|
+
return;
|
|
1594
|
+
}
|
|
1595
|
+
await operation;
|
|
1596
|
+
return;
|
|
1597
|
+
}
|
|
1598
|
+
await this.dispatchMeshSpotControlCore(meshName, owner, record);
|
|
1599
|
+
}
|
|
1600
|
+
async dispatchMeshSpotControlCore(meshName, owner, record, onDetachedTerminal) {
|
|
1605
1601
|
const spotId = owner.spotId;
|
|
1606
1602
|
const control = record.kindData;
|
|
1607
1603
|
if (control?.kind !== 'actorControl') {
|
|
@@ -1664,15 +1660,15 @@ class DefaultZLinkSpotManager {
|
|
|
1664
1660
|
await activation.spot.onJoinedActor(actor);
|
|
1665
1661
|
};
|
|
1666
1662
|
const completePublicJoin = async () => {
|
|
1667
|
-
const
|
|
1668
|
-
if (
|
|
1663
|
+
const deferredJoinCompletion = pendingTransfer?.deferredJoinCompletion;
|
|
1664
|
+
if (deferredJoinCompletion !== undefined) {
|
|
1669
1665
|
const currentRef = this.options.actorTransferRuntime === undefined
|
|
1670
1666
|
? null
|
|
1671
1667
|
: control.currentActor;
|
|
1672
1668
|
if (currentRef === null) {
|
|
1673
1669
|
throw new Error(`Actor '${actor.context.actorId}' has no target ref for deferred Join completion.`);
|
|
1674
1670
|
}
|
|
1675
|
-
await this.options.actorTransferRuntime?.
|
|
1671
|
+
await this.options.actorTransferRuntime?.deliverDeferredJoinAccepted(deferredJoinCompletion, actor, currentRef, (operation) => activation.executeActor(actor.context.actorId, async () => await operation()));
|
|
1676
1672
|
}
|
|
1677
1673
|
};
|
|
1678
1674
|
const completeTargetReady = async () => {
|
|
@@ -1730,9 +1726,15 @@ class DefaultZLinkSpotManager {
|
|
|
1730
1726
|
// them only after the lifecycle turn above has been released.
|
|
1731
1727
|
await completeTargetReady();
|
|
1732
1728
|
};
|
|
1733
|
-
|
|
1734
|
-
if (
|
|
1735
|
-
|
|
1729
|
+
const terminal = resume();
|
|
1730
|
+
if (onDetachedTerminal !== undefined) {
|
|
1731
|
+
onDetachedTerminal(terminal);
|
|
1732
|
+
}
|
|
1733
|
+
else {
|
|
1734
|
+
this.options.detachedTaskRunner?.runDetached(`actor transfer target commit ${actor.context.actorId}`, async () => await terminal);
|
|
1735
|
+
if (this.options.detachedTaskRunner === undefined) {
|
|
1736
|
+
void terminal.catch(() => undefined);
|
|
1737
|
+
}
|
|
1736
1738
|
}
|
|
1737
1739
|
return;
|
|
1738
1740
|
}
|
|
@@ -1793,7 +1795,8 @@ class DefaultZLinkSpotManager {
|
|
|
1793
1795
|
await activation.serial.execute(() => activation.spot.onJoinedActor(actor));
|
|
1794
1796
|
}
|
|
1795
1797
|
await submitSourceLeave(admission.admission.actorRef.nodeRid);
|
|
1796
|
-
if (outcome.
|
|
1798
|
+
if (outcome.deferredJoinCompletion !== undefined &&
|
|
1799
|
+
this.options.actorTransferRuntime !== undefined) {
|
|
1797
1800
|
const submitMailbox = targetsEntry
|
|
1798
1801
|
? (operation) => operation()
|
|
1799
1802
|
: (operation) => {
|
|
@@ -1803,12 +1806,12 @@ class DefaultZLinkSpotManager {
|
|
|
1803
1806
|
}
|
|
1804
1807
|
return activation.executeActor(actor.context.actorId, operation);
|
|
1805
1808
|
};
|
|
1806
|
-
await this.options.actorTransferRuntime.
|
|
1809
|
+
await this.options.actorTransferRuntime.deliverDeferredJoinAccepted(outcome.deferredJoinCompletion, actor, actorRef, submitMailbox, signal);
|
|
1807
1810
|
}
|
|
1808
1811
|
this.formalRemoteActorAdmissions.markCommitted(relocationId, actor);
|
|
1809
1812
|
return true;
|
|
1810
1813
|
}
|
|
1811
|
-
async restoreCanonicalActorJoinRecovery(recovery, signal
|
|
1814
|
+
async restoreCanonicalActorJoinRecovery(recovery, signal) {
|
|
1812
1815
|
(0, abort_1.throwIfAborted)(signal);
|
|
1813
1816
|
const admission = this.formalRemoteActorAdmissions.get(recovery.request.handoffId);
|
|
1814
1817
|
if (admission === undefined) {
|
|
@@ -1850,15 +1853,14 @@ class DefaultZLinkSpotManager {
|
|
|
1850
1853
|
}
|
|
1851
1854
|
// Command 28 carries a present reply in one outer framework-multipart
|
|
1852
1855
|
// part. The accepted target admission still owns the inner typed content
|
|
1853
|
-
// type, which the
|
|
1856
|
+
// type, which the process-local completion keeps for application decode.
|
|
1854
1857
|
const admittedContentType = admittedReply.byteLength === 0 ? recovery.replyContentType : outcome.replyContentType;
|
|
1855
1858
|
const transfer = this.options.actorTransferRuntime;
|
|
1856
1859
|
if (transfer === undefined) {
|
|
1857
1860
|
throw new Error('Canonical Actor Join recovery requires the Actor transfer runtime.');
|
|
1858
1861
|
}
|
|
1859
|
-
const deferred =
|
|
1860
|
-
this.formalRemoteActorAdmissions.
|
|
1861
|
-
return deferred;
|
|
1862
|
+
const deferred = transfer.prepareDeferredJoinAccepted(recovery.request.actorId, recovery.operationId, admitted.actorRef, recovery.reply, admittedContentType);
|
|
1863
|
+
this.formalRemoteActorAdmissions.attachDeferredJoinCompletion(recovery.request.handoffId, deferred);
|
|
1862
1864
|
}
|
|
1863
1865
|
encodeMeshActorReply(requestHeaderPart, kind, payload) {
|
|
1864
1866
|
// Spec 27 §4/§7: the decode gate strips the observation-only flow pair at
|