@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
|
@@ -72,7 +72,7 @@ import { ZLinkWorkerRuntime } from '../workers';
|
|
|
72
72
|
import {
|
|
73
73
|
type ZLinkActorHandoffPrefixAdmission,
|
|
74
74
|
type ZLinkActorHandoffPrefixRecord,
|
|
75
|
-
type
|
|
75
|
+
type ZLinkDeferredJoinCompletion,
|
|
76
76
|
type ZLinkRemoteBoundSessionTarget
|
|
77
77
|
} from '../actors';
|
|
78
78
|
import type { ZLinkLocationLifecycle } from '../locations';
|
|
@@ -130,7 +130,7 @@ export {
|
|
|
130
130
|
} from './spot-handler-registry';
|
|
131
131
|
export { ZLinkRuntimeSpotPublisherTransport } from './spot-publisher-transport';
|
|
132
132
|
import { ZLinkSpotActivationRegistry } from './spot-activation-registry';
|
|
133
|
-
import {
|
|
133
|
+
import type { ZLinkSpotActivation } from './spot-activation-state';
|
|
134
134
|
import { ZLinkSpotActivationLifecycle, type ZLinkNativeSpotAuthority } from './spot-activation';
|
|
135
135
|
import { ZLinkSpotActorMembership, type ZLinkActorJoinRollback } from './spot-actor-membership';
|
|
136
136
|
import { ZLinkFormalRemoteActorTransferRegistry } from './formal-remote-actor-transfer-registry';
|
|
@@ -145,6 +145,7 @@ import type {
|
|
|
145
145
|
ZLinkSpotBoundSessionRuntime
|
|
146
146
|
} from './spot-runtime-ports';
|
|
147
147
|
import type { ZLinkRuntimeAdmissionGate } from '../admission';
|
|
148
|
+
import type { ZLinkActivationAdmission } from '../activation-admission';
|
|
148
149
|
import type { ZLinkDetachedTaskRunner } from './spot-actor-join-dispatch';
|
|
149
150
|
import type { ZLinkLocalSpotCreateResult } from './spot-manager-internal-contracts';
|
|
150
151
|
export type { ZLinkLocalSpotCreateResult } from './spot-manager-internal-contracts';
|
|
@@ -227,6 +228,7 @@ export interface ZLinkSpotManagerOptions {
|
|
|
227
228
|
readonly channelMeshNameForChannel?: (channelName: string) => string | undefined;
|
|
228
229
|
readonly providerResolver?: ZLinkProviderResolver;
|
|
229
230
|
readonly dispatchErrors?: ZLinkDispatchErrorReporter;
|
|
231
|
+
readonly closeErrorSink?: import('../diagnostics/dispatch-error-port').ZLinkDispatchErrorSink;
|
|
230
232
|
readonly runtimeEventPublisher?: ZLinkRuntimeEventPublisher;
|
|
231
233
|
readonly workerRuntime?: ZLinkWorkerRuntime;
|
|
232
234
|
readonly messageSerializers?: ReadonlyMap<string, ZLinkMessageSerializer>;
|
|
@@ -238,12 +240,21 @@ export interface ZLinkSpotManagerOptions {
|
|
|
238
240
|
) => Promise<void>;
|
|
239
241
|
readonly beginInstanceIdleClosingAuthority?: (
|
|
240
242
|
meshName: string,
|
|
241
|
-
spotId: RoutingId
|
|
242
|
-
|
|
243
|
+
spotId: RoutingId,
|
|
244
|
+
onCommitted: () => void
|
|
245
|
+
) => Promise<{ release(): Promise<void> } | undefined>;
|
|
243
246
|
readonly beginInstanceClosingAuthority?: (
|
|
244
247
|
meshName: string,
|
|
245
|
-
spotId: RoutingId
|
|
246
|
-
|
|
248
|
+
spotId: RoutingId,
|
|
249
|
+
onCommitted: () => void
|
|
250
|
+
) => Promise<{ release(): Promise<void> } | undefined>;
|
|
251
|
+
/** Moves a local User Spot incarnation's authority to Closing for a context Close. */
|
|
252
|
+
readonly beginUserClosingAuthority?: (
|
|
253
|
+
meshName: string,
|
|
254
|
+
spotId: RoutingId,
|
|
255
|
+
objectGeneration: bigint,
|
|
256
|
+
onCommitted: () => void
|
|
257
|
+
) => Promise<{ release(): Promise<void> } | undefined>;
|
|
247
258
|
readonly instanceSpotApplicationTargetProvider?: (
|
|
248
259
|
meshName: string,
|
|
249
260
|
spotId: RoutingId
|
|
@@ -261,7 +272,6 @@ export interface ZLinkSpotManagerOptions {
|
|
|
261
272
|
spotId: RoutingId,
|
|
262
273
|
authority?: ZLinkNativeSpotAuthority
|
|
263
274
|
) => ZLinkBackendSpot | undefined;
|
|
264
|
-
readonly createReceived?: () => import('../backend').ZLinkBackendReceived;
|
|
265
275
|
readonly createTopicMessage?: () => import('../backend').ZLinkBackendTopicMessage;
|
|
266
276
|
readonly nativeSpotNodeProvider?: (meshName: string) => ZLinkBackendSpotNode | undefined;
|
|
267
277
|
readonly actorResolver?: (actorId: string) => ZLinkActor | undefined;
|
|
@@ -281,8 +291,19 @@ export interface ZLinkSpotManagerOptions {
|
|
|
281
291
|
readonly metrics?: import('../diagnostics').ZLinkRuntimeMetrics;
|
|
282
292
|
readonly admission?: ZLinkRuntimeAdmissionGate;
|
|
283
293
|
readonly statefulExecutionAllowed?: () => boolean;
|
|
284
|
-
readonly
|
|
285
|
-
|
|
294
|
+
readonly activationAdmission?: ZLinkActivationAdmission;
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
interface ZLinkTargetSpotCloseOperation {
|
|
298
|
+
readonly activation: ZLinkSpotActivation;
|
|
299
|
+
readonly reason: ZLinkSpotCloseReason;
|
|
300
|
+
readonly beginAuthority: (
|
|
301
|
+
onCommitted: () => void
|
|
302
|
+
) => Promise<{ release(): Promise<void> } | undefined>;
|
|
303
|
+
committed: boolean;
|
|
304
|
+
authority?: { release(): Promise<void> };
|
|
305
|
+
authorityDecision?: Promise<void>;
|
|
306
|
+
ready?: Promise<boolean>;
|
|
286
307
|
}
|
|
287
308
|
|
|
288
309
|
export class DefaultZLinkSpotManager {
|
|
@@ -306,27 +327,7 @@ export class DefaultZLinkSpotManager {
|
|
|
306
327
|
string,
|
|
307
328
|
Map<string, Promise<ZLinkSpotActivation>>
|
|
308
329
|
>();
|
|
309
|
-
private readonly
|
|
310
|
-
string,
|
|
311
|
-
{
|
|
312
|
-
readonly meshName: string;
|
|
313
|
-
readonly limit: number;
|
|
314
|
-
active: number;
|
|
315
|
-
// Tombstone slots + head cursor keep abort O(1) and admit O(1) amortized
|
|
316
|
-
// instead of indexOf/splice + shift scans under a cancellation storm.
|
|
317
|
-
readonly waiters: Array<
|
|
318
|
-
| {
|
|
319
|
-
resolve: (release: () => void) => void;
|
|
320
|
-
reject: (error: unknown) => void;
|
|
321
|
-
signal?: AbortSignal;
|
|
322
|
-
abort?: () => void;
|
|
323
|
-
}
|
|
324
|
-
| undefined
|
|
325
|
-
>;
|
|
326
|
-
waiterHead: number;
|
|
327
|
-
}
|
|
328
|
-
>();
|
|
329
|
-
private readonly pendingInstanceCloses = new Map<string, Promise<boolean>>();
|
|
330
|
+
private readonly closeOperations = new Map<string, ZLinkTargetSpotCloseOperation>();
|
|
330
331
|
private readonly pendingInstanceTerminals = new Map<string, number>();
|
|
331
332
|
private readonly pendingInstanceTerminalGenerations = new Map<string, Map<string, number>>();
|
|
332
333
|
private readonly deferredInstanceAuthorityReleases = new Map<string, Set<bigint>>();
|
|
@@ -337,7 +338,9 @@ export class DefaultZLinkSpotManager {
|
|
|
337
338
|
private readonly options: ZLinkSpotManagerOptions,
|
|
338
339
|
timerClock?: import('./spot-timer').ZLinkTimerClock
|
|
339
340
|
) {
|
|
340
|
-
this.activations = new ZLinkSpotActivationRegistry(options.metrics)
|
|
341
|
+
this.activations = new ZLinkSpotActivationRegistry(options.metrics, (meshName, spotId) =>
|
|
342
|
+
this.isSpotClosing(meshName, spotId)
|
|
343
|
+
);
|
|
341
344
|
this.factories = new Set(options.spotFactories);
|
|
342
345
|
this.workerRuntime = options.workerRuntime ?? new ZLinkWorkerRuntime();
|
|
343
346
|
this.locationClaim = new ZLinkSpotLocationClaim({
|
|
@@ -356,6 +359,9 @@ export class DefaultZLinkSpotManager {
|
|
|
356
359
|
dispatchErrors: options.dispatchErrors
|
|
357
360
|
});
|
|
358
361
|
this.actorMembership = new ZLinkSpotActorMembership({
|
|
362
|
+
isSpotClosing: (activation) =>
|
|
363
|
+
this.isSpotClosing(activation.meshName, activation.spotId) ||
|
|
364
|
+
this.activations.resolve(activation.meshName, activation.spotId) !== activation,
|
|
359
365
|
resolveActivation: (spotId, meshName) =>
|
|
360
366
|
meshName === undefined
|
|
361
367
|
? this.activations.resolveUnique(spotId)
|
|
@@ -392,12 +398,12 @@ export class DefaultZLinkSpotManager {
|
|
|
392
398
|
spotRouterChannelIdForMesh: options.spotRouterChannelIdForMesh,
|
|
393
399
|
providerResolver: options.providerResolver,
|
|
394
400
|
dispatchErrors: options.dispatchErrors,
|
|
401
|
+
closeErrorSink: options.closeErrorSink,
|
|
395
402
|
runtimeEventPublisher: options.runtimeEventPublisher,
|
|
396
403
|
workerRuntime: this.workerRuntime,
|
|
397
404
|
messageSerializers: options.messageSerializers,
|
|
398
405
|
locationClaim: this.locationClaim,
|
|
399
406
|
createNativeSpot: options.createNativeSpot,
|
|
400
|
-
createReceived: options.createReceived,
|
|
401
407
|
createTopicMessage: options.createTopicMessage,
|
|
402
408
|
nativeSpotNodeProvider: options.nativeSpotNodeProvider,
|
|
403
409
|
actorResolver: options.actorResolver,
|
|
@@ -409,8 +415,11 @@ export class DefaultZLinkSpotManager {
|
|
|
409
415
|
statefulExecutionAllowed: options.statefulExecutionAllowed,
|
|
410
416
|
leaveActor: (spotId, actor, signal, meshName) =>
|
|
411
417
|
this.actorMembership.leaveActor(spotId, actor, signal, meshName),
|
|
412
|
-
|
|
413
|
-
this.
|
|
418
|
+
requestContextClose: (activation, objectGeneration, signal) =>
|
|
419
|
+
this.closeFromContext(activation, objectGeneration, signal),
|
|
420
|
+
isSpotClosing: (activation) =>
|
|
421
|
+
this.isSpotClosing(activation.meshName, activation.spotId) ||
|
|
422
|
+
this.activations.resolve(activation.meshName, activation.spotId) !== activation,
|
|
414
423
|
registerActivation: (activation) => {
|
|
415
424
|
this.activations.register(activation);
|
|
416
425
|
this.scheduleIdleSweep();
|
|
@@ -470,14 +479,6 @@ export class DefaultZLinkSpotManager {
|
|
|
470
479
|
return this.activations.list(meshName).length;
|
|
471
480
|
}
|
|
472
481
|
|
|
473
|
-
instanceActivationConcurrency(meshName: string): {
|
|
474
|
-
readonly active: number;
|
|
475
|
-
readonly limit: number;
|
|
476
|
-
} {
|
|
477
|
-
const limit = this.options.activationConcurrencyLimitProvider?.(meshName) ?? 128;
|
|
478
|
-
return { active: this.instanceActivationGates.get(meshName)?.active ?? 0, limit };
|
|
479
|
-
}
|
|
480
|
-
|
|
481
482
|
resolveRelocationActivation(
|
|
482
483
|
meshName: string,
|
|
483
484
|
spotId: RoutingId
|
|
@@ -548,7 +549,7 @@ export class DefaultZLinkSpotManager {
|
|
|
548
549
|
await awaitWithAbort(existing, signal);
|
|
549
550
|
return;
|
|
550
551
|
}
|
|
551
|
-
const release = await this.
|
|
552
|
+
const release = await this.options.activationAdmission?.acquire(meshName, signal);
|
|
552
553
|
try {
|
|
553
554
|
await this.materializeInstanceCore(
|
|
554
555
|
meshName,
|
|
@@ -559,7 +560,7 @@ export class DefaultZLinkSpotManager {
|
|
|
559
560
|
signal
|
|
560
561
|
);
|
|
561
562
|
} finally {
|
|
562
|
-
release();
|
|
563
|
+
release?.();
|
|
563
564
|
}
|
|
564
565
|
}
|
|
565
566
|
|
|
@@ -590,11 +591,16 @@ export class DefaultZLinkSpotManager {
|
|
|
590
591
|
// explicit Instance intent arriving at that boundary must wait for the
|
|
591
592
|
// old resources to be released before materializing the replacement.
|
|
592
593
|
// This is lifecycle convergence; it does not resubmit application work.
|
|
593
|
-
const
|
|
594
|
+
const closeOperation = this.closeOperations.get(key);
|
|
595
|
+
const pendingClose = closeOperation?.ready;
|
|
594
596
|
if (pendingClose !== undefined) {
|
|
595
597
|
await awaitWithAbort(pendingClose, signal);
|
|
596
598
|
continue;
|
|
597
599
|
}
|
|
600
|
+
if (closeOperation?.committed === true) {
|
|
601
|
+
await awaitWithAbort(this.closeWithReason(meshName, spotId), signal);
|
|
602
|
+
continue;
|
|
603
|
+
}
|
|
598
604
|
const closing = this.activations.closingOperation(meshName, spotId);
|
|
599
605
|
if (closing !== undefined) {
|
|
600
606
|
await awaitWithAbort(closing.ready, signal);
|
|
@@ -687,73 +693,6 @@ export class DefaultZLinkSpotManager {
|
|
|
687
693
|
}
|
|
688
694
|
}
|
|
689
695
|
|
|
690
|
-
private async acquireInstanceActivation(
|
|
691
|
-
meshName: string,
|
|
692
|
-
signal?: AbortSignal
|
|
693
|
-
): Promise<() => void> {
|
|
694
|
-
let gate = this.instanceActivationGates.get(meshName);
|
|
695
|
-
if (gate === undefined) {
|
|
696
|
-
gate = {
|
|
697
|
-
meshName,
|
|
698
|
-
limit: this.options.activationConcurrencyLimitProvider?.(meshName) ?? 128,
|
|
699
|
-
active: 0,
|
|
700
|
-
waiters: [],
|
|
701
|
-
waiterHead: 0
|
|
702
|
-
};
|
|
703
|
-
this.instanceActivationGates.set(meshName, gate);
|
|
704
|
-
}
|
|
705
|
-
if (signal?.aborted === true) throw signal.reason;
|
|
706
|
-
if (gate.active < gate.limit) {
|
|
707
|
-
gate.active += 1;
|
|
708
|
-
this.options.onInstanceActivationConcurrencyChanged?.(meshName);
|
|
709
|
-
return () => this.releaseInstanceActivation(gate!);
|
|
710
|
-
}
|
|
711
|
-
return new Promise<() => void>((resolve, reject) => {
|
|
712
|
-
const waiter = { resolve, reject, signal, abort: undefined as (() => void) | undefined };
|
|
713
|
-
const slot = gate!.waiters.length;
|
|
714
|
-
waiter.abort = () => {
|
|
715
|
-
if (gate!.waiters[slot] === waiter) gate!.waiters[slot] = undefined;
|
|
716
|
-
reject(signal?.reason);
|
|
717
|
-
};
|
|
718
|
-
signal?.addEventListener('abort', waiter.abort, { once: true });
|
|
719
|
-
gate!.waiters.push(waiter);
|
|
720
|
-
});
|
|
721
|
-
}
|
|
722
|
-
|
|
723
|
-
private releaseInstanceActivation(gate: {
|
|
724
|
-
readonly meshName: string;
|
|
725
|
-
readonly limit: number;
|
|
726
|
-
active: number;
|
|
727
|
-
readonly waiters: Array<
|
|
728
|
-
| {
|
|
729
|
-
resolve: (release: () => void) => void;
|
|
730
|
-
reject: (error: unknown) => void;
|
|
731
|
-
signal?: AbortSignal;
|
|
732
|
-
abort?: () => void;
|
|
733
|
-
}
|
|
734
|
-
| undefined
|
|
735
|
-
>;
|
|
736
|
-
waiterHead: number;
|
|
737
|
-
}): void {
|
|
738
|
-
while (gate.waiterHead < gate.waiters.length) {
|
|
739
|
-
const waiter = gate.waiters[gate.waiterHead];
|
|
740
|
-
gate.waiters[gate.waiterHead] = undefined;
|
|
741
|
-
gate.waiterHead += 1;
|
|
742
|
-
if (gate.waiterHead >= gate.waiters.length) {
|
|
743
|
-
gate.waiters.length = 0;
|
|
744
|
-
gate.waiterHead = 0;
|
|
745
|
-
}
|
|
746
|
-
if (waiter === undefined) continue;
|
|
747
|
-
if (waiter.abort !== undefined) waiter.signal?.removeEventListener('abort', waiter.abort);
|
|
748
|
-
waiter.resolve(() => this.releaseInstanceActivation(gate));
|
|
749
|
-
return;
|
|
750
|
-
}
|
|
751
|
-
gate.waiters.length = 0;
|
|
752
|
-
gate.waiterHead = 0;
|
|
753
|
-
gate.active -= 1;
|
|
754
|
-
this.options.onInstanceActivationConcurrencyChanged?.(gate.meshName);
|
|
755
|
-
}
|
|
756
|
-
|
|
757
696
|
isInstanceMaterialized(meshName: string, instanceType: string, spotId: RoutingId): boolean {
|
|
758
697
|
const activation = this.activations.resolve(meshName, spotId);
|
|
759
698
|
return (
|
|
@@ -767,12 +706,17 @@ export class DefaultZLinkSpotManager {
|
|
|
767
706
|
return (this.pendingInstanceMaterializationsByPrefix.get(prefix)?.size ?? 0) > 0;
|
|
768
707
|
}
|
|
769
708
|
|
|
770
|
-
|
|
709
|
+
isSpotClosing(meshName: string, spotId: RoutingId): boolean {
|
|
771
710
|
const key = `${meshName}\0${String(spotId)}`;
|
|
772
|
-
return (
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
711
|
+
return this.closeOperations.get(key)?.committed === true;
|
|
712
|
+
}
|
|
713
|
+
|
|
714
|
+
pendingSpotCloseDecision(meshName: string, spotId: RoutingId): Promise<void> | undefined {
|
|
715
|
+
return this.closeOperations.get(`${meshName}\0${String(spotId)}`)?.authorityDecision;
|
|
716
|
+
}
|
|
717
|
+
|
|
718
|
+
isInstanceClosing(meshName: string, spotId: RoutingId): boolean {
|
|
719
|
+
return this.closeOperations.has(`${meshName}\0${String(spotId)}`);
|
|
776
720
|
}
|
|
777
721
|
|
|
778
722
|
async discardInstance(meshName: string, spotId: RoutingId): Promise<void> {
|
|
@@ -835,7 +779,7 @@ export class DefaultZLinkSpotManager {
|
|
|
835
779
|
}
|
|
836
780
|
this.pendingInstanceTerminals.delete(key);
|
|
837
781
|
this.pendingInstanceTerminalGenerations.delete(key);
|
|
838
|
-
const pendingClose = this.
|
|
782
|
+
const pendingClose = this.closeOperations.get(key)?.ready;
|
|
839
783
|
if (pendingClose !== undefined) {
|
|
840
784
|
this.deferInstanceAuthorityRelease(key, objectGeneration);
|
|
841
785
|
await pendingClose;
|
|
@@ -950,20 +894,6 @@ export class DefaultZLinkSpotManager {
|
|
|
950
894
|
) {
|
|
951
895
|
continue;
|
|
952
896
|
}
|
|
953
|
-
let durableClosing: { restoreReady(): Promise<void> } | undefined;
|
|
954
|
-
try {
|
|
955
|
-
durableClosing = await (this.options.beginInstanceIdleClosingAuthority?.(
|
|
956
|
-
activation.meshName,
|
|
957
|
-
activation.spotId
|
|
958
|
-
) ?? Promise.resolve({ restoreReady: async () => undefined }));
|
|
959
|
-
} catch (error) {
|
|
960
|
-
activation.abortIdleEviction();
|
|
961
|
-
throw error;
|
|
962
|
-
}
|
|
963
|
-
if (durableClosing === undefined) {
|
|
964
|
-
activation.abortIdleEviction();
|
|
965
|
-
continue;
|
|
966
|
-
}
|
|
967
897
|
const close = this.closeWithReason(
|
|
968
898
|
activation.meshName,
|
|
969
899
|
activation.spotId,
|
|
@@ -973,15 +903,10 @@ export class DefaultZLinkSpotManager {
|
|
|
973
903
|
const run = async () => {
|
|
974
904
|
try {
|
|
975
905
|
const closed = await close;
|
|
976
|
-
if (!closed)
|
|
977
|
-
await durableClosing.restoreReady();
|
|
978
|
-
activation.abortIdleEviction();
|
|
979
|
-
}
|
|
906
|
+
if (!closed) activation.abortIdleEviction();
|
|
980
907
|
} catch (error) {
|
|
981
|
-
if (
|
|
982
|
-
|
|
983
|
-
}
|
|
984
|
-
activation.abortIdleEviction();
|
|
908
|
+
if (!this.isSpotClosing(activation.meshName, activation.spotId))
|
|
909
|
+
activation.abortIdleEviction();
|
|
985
910
|
throw error;
|
|
986
911
|
}
|
|
987
912
|
};
|
|
@@ -1087,6 +1012,7 @@ export class DefaultZLinkSpotManager {
|
|
|
1087
1012
|
throwIfAborted(args.signal);
|
|
1088
1013
|
const operation = this.activations.getOrBegin(meshName, spotType, spotId, async () => {
|
|
1089
1014
|
this.options.admission?.requireRequest('SPOT create', meshName);
|
|
1015
|
+
const release = await this.options.activationAdmission?.acquire(meshName, args.signal);
|
|
1090
1016
|
const ownedRequest =
|
|
1091
1017
|
args.request === undefined
|
|
1092
1018
|
? RuntimeMessage.from(Buffer.alloc(0))
|
|
@@ -1102,6 +1028,7 @@ export class DefaultZLinkSpotManager {
|
|
|
1102
1028
|
);
|
|
1103
1029
|
} finally {
|
|
1104
1030
|
ownedRequest.close();
|
|
1031
|
+
release?.();
|
|
1105
1032
|
}
|
|
1106
1033
|
});
|
|
1107
1034
|
return await awaitWithAbort(operation.ready, args.signal);
|
|
@@ -1143,120 +1070,182 @@ export class DefaultZLinkSpotManager {
|
|
|
1143
1070
|
return await this.closeWithReason(meshName, spotId, signal, ZLinkSpotCloseReason.ExplicitClose);
|
|
1144
1071
|
}
|
|
1145
1072
|
|
|
1073
|
+
async closeUserWithAuthority(
|
|
1074
|
+
meshName: string,
|
|
1075
|
+
spotId: RoutingId,
|
|
1076
|
+
beginAuthority: (onCommitted: () => void) => Promise<{ release(): Promise<void> }>,
|
|
1077
|
+
signal?: AbortSignal
|
|
1078
|
+
): Promise<boolean> {
|
|
1079
|
+
return await this.closeWithReason(
|
|
1080
|
+
meshName,
|
|
1081
|
+
spotId,
|
|
1082
|
+
signal,
|
|
1083
|
+
ZLinkSpotCloseReason.ExplicitClose,
|
|
1084
|
+
undefined,
|
|
1085
|
+
beginAuthority
|
|
1086
|
+
);
|
|
1087
|
+
}
|
|
1088
|
+
|
|
1089
|
+
private closeFromContext(
|
|
1090
|
+
activation: ZLinkSpotActivation,
|
|
1091
|
+
objectGeneration: bigint,
|
|
1092
|
+
signal?: AbortSignal
|
|
1093
|
+
): Promise<boolean> {
|
|
1094
|
+
const { meshName, spotId } = activation;
|
|
1095
|
+
const operation = this.closeOperations.get(`${meshName}\0${String(spotId)}`);
|
|
1096
|
+
const current = operation?.activation ?? this.activations.resolve(meshName, spotId);
|
|
1097
|
+
if (current === undefined) {
|
|
1098
|
+
return Promise.resolve(false);
|
|
1099
|
+
}
|
|
1100
|
+
if (current !== activation || current.objectGeneration !== objectGeneration) {
|
|
1101
|
+
return Promise.reject(
|
|
1102
|
+
createInternalFrameworkException(
|
|
1103
|
+
ZLinkFrameworkInternalErrorKind.InvalidOperation,
|
|
1104
|
+
`Spot '${String(spotId)}' generation is stale.`
|
|
1105
|
+
)
|
|
1106
|
+
);
|
|
1107
|
+
}
|
|
1108
|
+
const beginUserAuthority =
|
|
1109
|
+
activation.domain.kind === 'user' && this.options.beginUserClosingAuthority !== undefined
|
|
1110
|
+
? (onCommitted: () => void) =>
|
|
1111
|
+
this.options.beginUserClosingAuthority!(meshName, spotId, objectGeneration, onCommitted)
|
|
1112
|
+
: undefined;
|
|
1113
|
+
return this.closeWithReason(
|
|
1114
|
+
meshName,
|
|
1115
|
+
spotId,
|
|
1116
|
+
signal,
|
|
1117
|
+
ZLinkSpotCloseReason.ExplicitClose,
|
|
1118
|
+
undefined,
|
|
1119
|
+
beginUserAuthority
|
|
1120
|
+
);
|
|
1121
|
+
}
|
|
1122
|
+
|
|
1146
1123
|
private async closeWithReason(
|
|
1147
1124
|
meshName: string,
|
|
1148
1125
|
spotId: RoutingId,
|
|
1149
1126
|
signal?: AbortSignal,
|
|
1150
1127
|
reason = ZLinkSpotCloseReason.ExplicitClose,
|
|
1151
|
-
deadline?: Date
|
|
1128
|
+
deadline?: Date,
|
|
1129
|
+
beginUserAuthority?: (
|
|
1130
|
+
onCommitted: () => void
|
|
1131
|
+
) => Promise<{ release(): Promise<void> } | undefined>
|
|
1152
1132
|
): Promise<boolean> {
|
|
1153
1133
|
requireMeshName(meshName);
|
|
1154
1134
|
const key = `${meshName}\0${String(spotId)}`;
|
|
1155
|
-
|
|
1156
|
-
if (
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1135
|
+
let operation = this.closeOperations.get(key);
|
|
1136
|
+
if (operation === undefined) {
|
|
1137
|
+
const activation = this.activations.resolve(meshName, spotId);
|
|
1138
|
+
if (activation === undefined) return false;
|
|
1139
|
+
if (
|
|
1140
|
+
activation.domain.kind === 'user' &&
|
|
1141
|
+
reason === ZLinkSpotCloseReason.ExplicitClose &&
|
|
1142
|
+
beginUserAuthority === undefined
|
|
1143
|
+
) {
|
|
1144
|
+
throw createInternalFrameworkException(
|
|
1145
|
+
ZLinkFrameworkInternalErrorKind.InvalidOperation,
|
|
1146
|
+
`User Spot '${String(spotId)}' Close requires its authority owner.`
|
|
1147
|
+
);
|
|
1148
|
+
}
|
|
1149
|
+
const beginAuthority =
|
|
1150
|
+
beginUserAuthority ??
|
|
1151
|
+
(activation.domain.kind === 'instance' &&
|
|
1152
|
+
reason === ZLinkSpotCloseReason.ExplicitClose &&
|
|
1153
|
+
this.options.beginInstanceClosingAuthority !== undefined
|
|
1154
|
+
? (onCommitted) =>
|
|
1155
|
+
this.options.beginInstanceClosingAuthority!(meshName, spotId, onCommitted)
|
|
1156
|
+
: activation.domain.kind === 'instance' &&
|
|
1157
|
+
reason === ZLinkSpotCloseReason.IdleEvicted &&
|
|
1158
|
+
this.options.beginInstanceIdleClosingAuthority !== undefined
|
|
1159
|
+
? (onCommitted) =>
|
|
1160
|
+
this.options.beginInstanceIdleClosingAuthority!(meshName, spotId, onCommitted)
|
|
1161
|
+
: async (onCommitted) => {
|
|
1162
|
+
onCommitted();
|
|
1163
|
+
return { release: async () => undefined };
|
|
1164
|
+
});
|
|
1165
|
+
operation = {
|
|
1166
|
+
activation,
|
|
1167
|
+
reason,
|
|
1168
|
+
beginAuthority,
|
|
1169
|
+
committed: false
|
|
1170
|
+
};
|
|
1171
|
+
this.closeOperations.set(key, operation);
|
|
1168
1172
|
}
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
const operation = this.activations.startClose(
|
|
1174
|
-
meshName,
|
|
1175
|
-
spotId,
|
|
1176
|
-
(target) => this.activationLifecycle.closeAfterSeal(target, seal, signal, reason, deadline),
|
|
1177
|
-
(target) => this.activationLifecycle.resourcesReleased(target),
|
|
1178
|
-
reason
|
|
1173
|
+
if (operation.ready === undefined) {
|
|
1174
|
+
const active = operation;
|
|
1175
|
+
const run = active.activation.serial.executeLifecycleOperation(() =>
|
|
1176
|
+
this.runCloseOperation(meshName, spotId, active, signal, deadline)
|
|
1179
1177
|
);
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
};
|
|
1185
|
-
|
|
1186
|
-
if (isInstance) {
|
|
1187
|
-
const beginAuthorityClose =
|
|
1188
|
-
reason === ZLinkSpotCloseReason.ExplicitClose
|
|
1189
|
-
? this.options.beginInstanceClosingAuthority
|
|
1190
|
-
: undefined;
|
|
1191
|
-
// Register the close gate before waiting for the current application
|
|
1192
|
-
// and activation-authority terminal completions. A close requested from
|
|
1193
|
-
// a handler cannot publish Closing until that handler's durable inbox
|
|
1194
|
-
// completion has removed the recovery fence.
|
|
1195
|
-
const trackedClosePromise = (async () => {
|
|
1196
|
-
const waitForApplication = this.options.instanceSpotApplicationQuiescenceProvider?.(
|
|
1197
|
-
meshName,
|
|
1198
|
-
spotId,
|
|
1199
|
-
signal
|
|
1200
|
-
);
|
|
1201
|
-
if (waitForApplication !== undefined) {
|
|
1202
|
-
await waitForApplication;
|
|
1203
|
-
}
|
|
1204
|
-
const closingAuthority =
|
|
1205
|
-
beginAuthorityClose === undefined
|
|
1206
|
-
? undefined
|
|
1207
|
-
: await beginAuthorityClose(meshName, spotId);
|
|
1208
|
-
if (beginAuthorityClose !== undefined && closingAuthority === undefined) {
|
|
1209
|
-
return false;
|
|
1210
|
-
}
|
|
1211
|
-
const operation = beginClose();
|
|
1212
|
-
if (operation === undefined) {
|
|
1213
|
-
await closingAuthority?.restoreReady();
|
|
1214
|
-
return false;
|
|
1215
|
-
}
|
|
1216
|
-
const closed = await operation.ready;
|
|
1217
|
-
if (!closed) await closingAuthority?.restoreReady();
|
|
1218
|
-
return closed;
|
|
1219
|
-
})().finally(() => {
|
|
1220
|
-
if (this.pendingInstanceCloses.get(key) === trackedClosePromise) {
|
|
1221
|
-
this.pendingInstanceCloses.delete(key);
|
|
1178
|
+
active.ready = run.finally(() => {
|
|
1179
|
+
active.ready = undefined;
|
|
1180
|
+
if (this.closeOperations.get(key) === active) {
|
|
1181
|
+
this.closeOperations.delete(key);
|
|
1222
1182
|
}
|
|
1223
1183
|
});
|
|
1224
|
-
this.pendingInstanceCloses.set(key, trackedClosePromise);
|
|
1225
|
-
if (currentTurn) {
|
|
1226
|
-
// The current turn must return before its terminal completion can
|
|
1227
|
-
// release the activation recovery fence and allow the durable close
|
|
1228
|
-
// CAS. The registered close gate prevents a second admission while
|
|
1229
|
-
// that detached close finishes.
|
|
1230
|
-
this.options.detachedTaskRunner?.runDetached(
|
|
1231
|
-
`instance spot close ${String(spotId)}`,
|
|
1232
|
-
async () => {
|
|
1233
|
-
await trackedClosePromise;
|
|
1234
|
-
}
|
|
1235
|
-
);
|
|
1236
|
-
if (this.options.detachedTaskRunner === undefined) {
|
|
1237
|
-
void trackedClosePromise.catch(() => undefined);
|
|
1238
|
-
}
|
|
1239
|
-
return true;
|
|
1240
|
-
}
|
|
1241
|
-
return await trackedClosePromise;
|
|
1242
1184
|
}
|
|
1185
|
+
return await operation.ready!;
|
|
1186
|
+
}
|
|
1243
1187
|
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1188
|
+
private async runCloseOperation(
|
|
1189
|
+
meshName: string,
|
|
1190
|
+
spotId: RoutingId,
|
|
1191
|
+
operation: ZLinkTargetSpotCloseOperation,
|
|
1192
|
+
signal?: AbortSignal,
|
|
1193
|
+
deadline?: Date
|
|
1194
|
+
): Promise<boolean> {
|
|
1195
|
+
const began = await this.beginCloseAuthority(meshName, spotId, operation, signal);
|
|
1196
|
+
if (!began) return false;
|
|
1197
|
+
const seal = operation.activation.sealExecution(true);
|
|
1198
|
+
await this.activationLifecycle.sealForClose(operation.activation, seal);
|
|
1199
|
+
const closingFailure = await this.activationLifecycle.cleanupClosedActivation(
|
|
1200
|
+
operation.activation,
|
|
1201
|
+
operation.reason,
|
|
1202
|
+
deadline
|
|
1203
|
+
);
|
|
1204
|
+
await operation.authority?.release();
|
|
1205
|
+
// The incarnation has no further lifecycle item once its authority is
|
|
1206
|
+
// released, so its lifecycle lane admission closes with this Close.
|
|
1207
|
+
operation.activation.serial.closeAdmission();
|
|
1208
|
+
this.activations.finishClose(meshName, spotId);
|
|
1209
|
+
this.closeOperations.delete(`${meshName}\0${String(spotId)}`);
|
|
1210
|
+
// An OnClosing failure never changes a Close result; host shutdown alone
|
|
1211
|
+
// reports it as its teardown outcome after cleanup has finished.
|
|
1212
|
+
if (closingFailure !== undefined && operation.reason === ZLinkSpotCloseReason.HostShutdown) {
|
|
1213
|
+
throw closingFailure;
|
|
1247
1214
|
}
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1215
|
+
return true;
|
|
1216
|
+
}
|
|
1217
|
+
|
|
1218
|
+
private async beginCloseAuthority(
|
|
1219
|
+
meshName: string,
|
|
1220
|
+
spotId: RoutingId,
|
|
1221
|
+
operation: ZLinkTargetSpotCloseOperation,
|
|
1222
|
+
signal?: AbortSignal
|
|
1223
|
+
): Promise<boolean> {
|
|
1224
|
+
await this.options.instanceSpotApplicationQuiescenceProvider?.(meshName, spotId, signal);
|
|
1225
|
+
if (!operation.activation.canClose(operation.reason)) return false;
|
|
1226
|
+
if (operation.activation.executionBarrier.isSealed) {
|
|
1227
|
+
throw createInternalFrameworkException(
|
|
1228
|
+
ZLinkFrameworkInternalErrorKind.SpotMoving,
|
|
1229
|
+
`Spot '${String(spotId)}' is sealed for relocation.`,
|
|
1230
|
+
true
|
|
1231
|
+
);
|
|
1232
|
+
}
|
|
1233
|
+
const authorityPromise = Promise.resolve().then(() =>
|
|
1234
|
+
operation.beginAuthority(() => {
|
|
1235
|
+
operation.committed = true;
|
|
1236
|
+
})
|
|
1237
|
+
);
|
|
1238
|
+
operation.authorityDecision = authorityPromise.then(
|
|
1239
|
+
() => undefined,
|
|
1240
|
+
() => undefined
|
|
1241
|
+
);
|
|
1242
|
+
const authority = await authorityPromise;
|
|
1243
|
+
if (authority === undefined) return false;
|
|
1244
|
+
operation.authority = authority;
|
|
1245
|
+
if (!this.isSpotClosing(meshName, spotId)) {
|
|
1246
|
+
throw new Error(`Spot '${String(spotId)}' Closing authority did not confirm its commit.`);
|
|
1258
1247
|
}
|
|
1259
|
-
return
|
|
1248
|
+
return true;
|
|
1260
1249
|
}
|
|
1261
1250
|
|
|
1262
1251
|
async executeOnSpot<TSpot extends ZLinkSpot, TResult>(
|
|
@@ -1286,10 +1275,6 @@ export class DefaultZLinkSpotManager {
|
|
|
1286
1275
|
return this.activations.resolveUnique(spotId) !== undefined;
|
|
1287
1276
|
}
|
|
1288
1277
|
|
|
1289
|
-
canCloseUserSpot(meshName: string, spotId: RoutingId): boolean {
|
|
1290
|
-
return this.activations.canClose(meshName, spotId);
|
|
1291
|
-
}
|
|
1292
|
-
|
|
1293
1278
|
beginUserSpotPublication(meshName: string, spotId: RoutingId): void {
|
|
1294
1279
|
this.activations.stage(meshName, spotId);
|
|
1295
1280
|
}
|
|
@@ -1562,14 +1547,7 @@ export class DefaultZLinkSpotManager {
|
|
|
1562
1547
|
record.reply(encodeChannelReplyParts(envelope.header, response, codecs))
|
|
1563
1548
|
);
|
|
1564
1549
|
} catch (error) {
|
|
1565
|
-
requireMeshSpotReply(
|
|
1566
|
-
record.reply(
|
|
1567
|
-
encodeChannelErrorReplyParts(
|
|
1568
|
-
envelope.header,
|
|
1569
|
-
error instanceof Error ? error.message : String(error)
|
|
1570
|
-
)
|
|
1571
|
-
)
|
|
1572
|
-
);
|
|
1550
|
+
requireMeshSpotReply(record.reply(encodeChannelErrorReplyParts(envelope.header, error)));
|
|
1573
1551
|
}
|
|
1574
1552
|
}
|
|
1575
1553
|
|
|
@@ -1761,14 +1739,7 @@ export class DefaultZLinkSpotManager {
|
|
|
1761
1739
|
action: ZLinkDispatchErrorAction.ReplyError,
|
|
1762
1740
|
error
|
|
1763
1741
|
});
|
|
1764
|
-
requireMeshSpotReply(
|
|
1765
|
-
record.reply(
|
|
1766
|
-
encodeChannelErrorReplyParts(
|
|
1767
|
-
envelope.header,
|
|
1768
|
-
error instanceof Error ? error.message : String(error)
|
|
1769
|
-
)
|
|
1770
|
-
)
|
|
1771
|
-
);
|
|
1742
|
+
requireMeshSpotReply(record.reply(encodeChannelErrorReplyParts(envelope.header, error)));
|
|
1772
1743
|
}
|
|
1773
1744
|
});
|
|
1774
1745
|
}
|
|
@@ -1932,6 +1903,40 @@ export class DefaultZLinkSpotManager {
|
|
|
1932
1903
|
meshName: string,
|
|
1933
1904
|
owner: ReadyRecord,
|
|
1934
1905
|
record: ReceiveRecord
|
|
1906
|
+
): Promise<void> {
|
|
1907
|
+
const spotId = owner.spotId as unknown as RoutingId | null;
|
|
1908
|
+
const activation = spotId === null ? undefined : this.activations.resolve(meshName, spotId);
|
|
1909
|
+
if (activation?.domain.kind === 'user') {
|
|
1910
|
+
await activation.serial.executeLifecycleOperation(async () => {
|
|
1911
|
+
if (
|
|
1912
|
+
this.isSpotClosing(meshName, activation.spotId) ||
|
|
1913
|
+
this.activations.resolve(meshName, activation.spotId) !== activation
|
|
1914
|
+
) {
|
|
1915
|
+
const rejection = createInternalFrameworkException(
|
|
1916
|
+
ZLinkFrameworkInternalErrorKind.RequestRejected,
|
|
1917
|
+
`User Spot '${String(spotId)}' is closing.`
|
|
1918
|
+
);
|
|
1919
|
+
if (record.replyFailure !== undefined) {
|
|
1920
|
+
const terminal = internalFrameworkWireReply(rejection);
|
|
1921
|
+
requireMeshSpotReply(
|
|
1922
|
+
record.replyFailure(terminal.terminalResult, terminal.failureCode)
|
|
1923
|
+
);
|
|
1924
|
+
} else {
|
|
1925
|
+
requireMeshSpotReply(record.replyActorJoin(1, []));
|
|
1926
|
+
}
|
|
1927
|
+
return;
|
|
1928
|
+
}
|
|
1929
|
+
await this.dispatchMeshActorJoinCore(meshName, owner, record);
|
|
1930
|
+
});
|
|
1931
|
+
return;
|
|
1932
|
+
}
|
|
1933
|
+
await this.dispatchMeshActorJoinCore(meshName, owner, record);
|
|
1934
|
+
}
|
|
1935
|
+
|
|
1936
|
+
private async dispatchMeshActorJoinCore(
|
|
1937
|
+
meshName: string,
|
|
1938
|
+
owner: ReadyRecord,
|
|
1939
|
+
record: ReceiveRecord
|
|
1935
1940
|
): Promise<void> {
|
|
1936
1941
|
const spotId = owner.spotId as unknown as RoutingId | null;
|
|
1937
1942
|
const control = record.kindData;
|
|
@@ -2027,7 +2032,7 @@ export class DefaultZLinkSpotManager {
|
|
|
2027
2032
|
let ownedCallbackRequest: Message | undefined;
|
|
2028
2033
|
let materialized = false;
|
|
2029
2034
|
let reply: Message | undefined;
|
|
2030
|
-
let
|
|
2035
|
+
let deferredJoinCompletion: ZLinkDeferredJoinCompletion | undefined;
|
|
2031
2036
|
let preparedTransferState: Message | undefined;
|
|
2032
2037
|
let admissionOutcome: ZLinkFormalRemoteActorAdmissionResult | undefined;
|
|
2033
2038
|
let accepted = false;
|
|
@@ -2176,8 +2181,8 @@ export class DefaultZLinkSpotManager {
|
|
|
2176
2181
|
transferRequest.completionOperationId !== undefined &&
|
|
2177
2182
|
this.options.actorTransferRuntime !== undefined
|
|
2178
2183
|
) {
|
|
2179
|
-
|
|
2180
|
-
|
|
2184
|
+
deferredJoinCompletion =
|
|
2185
|
+
this.options.actorTransferRuntime.prepareDeferredJoinAccepted(
|
|
2181
2186
|
actorId,
|
|
2182
2187
|
transferRequest.completionOperationId,
|
|
2183
2188
|
actorRef,
|
|
@@ -2187,7 +2192,7 @@ export class DefaultZLinkSpotManager {
|
|
|
2187
2192
|
admissionOutcome = {
|
|
2188
2193
|
accepted: this.options.dispatchEntryActorJoin !== undefined,
|
|
2189
2194
|
actorRef,
|
|
2190
|
-
...(
|
|
2195
|
+
...(deferredJoinCompletion === undefined ? {} : { deferredJoinCompletion })
|
|
2191
2196
|
};
|
|
2192
2197
|
} else if (activation === undefined) {
|
|
2193
2198
|
admissionOutcome = { accepted: false, actorRef };
|
|
@@ -2220,8 +2225,8 @@ export class DefaultZLinkSpotManager {
|
|
|
2220
2225
|
transferRequest.completionOperationId !== undefined &&
|
|
2221
2226
|
this.options.actorTransferRuntime !== undefined
|
|
2222
2227
|
) {
|
|
2223
|
-
|
|
2224
|
-
|
|
2228
|
+
deferredJoinCompletion =
|
|
2229
|
+
this.options.actorTransferRuntime.prepareDeferredJoinAccepted(
|
|
2225
2230
|
actorId,
|
|
2226
2231
|
transferRequest.completionOperationId,
|
|
2227
2232
|
actorRef,
|
|
@@ -2240,7 +2245,7 @@ export class DefaultZLinkSpotManager {
|
|
|
2240
2245
|
admissionOutcome = {
|
|
2241
2246
|
accepted: response.accepted,
|
|
2242
2247
|
actorRef,
|
|
2243
|
-
...(
|
|
2248
|
+
...(deferredJoinCompletion === undefined ? {} : { deferredJoinCompletion }),
|
|
2244
2249
|
...(encodedReply === undefined
|
|
2245
2250
|
? {}
|
|
2246
2251
|
: {
|
|
@@ -2277,7 +2282,7 @@ export class DefaultZLinkSpotManager {
|
|
|
2277
2282
|
if ('error' in admissionOutcome) {
|
|
2278
2283
|
throw admissionOutcome.error;
|
|
2279
2284
|
}
|
|
2280
|
-
|
|
2285
|
+
deferredJoinCompletion = admissionOutcome.deferredJoinCompletion;
|
|
2281
2286
|
}
|
|
2282
2287
|
if (
|
|
2283
2288
|
actor === undefined &&
|
|
@@ -2361,7 +2366,7 @@ export class DefaultZLinkSpotManager {
|
|
|
2361
2366
|
transferRequest?.completionOperationId !== undefined &&
|
|
2362
2367
|
this.options.actorTransferRuntime !== undefined
|
|
2363
2368
|
) {
|
|
2364
|
-
|
|
2369
|
+
deferredJoinCompletion = this.options.actorTransferRuntime.prepareDeferredJoinAccepted(
|
|
2365
2370
|
actorId,
|
|
2366
2371
|
transferRequest.completionOperationId,
|
|
2367
2372
|
actorRef,
|
|
@@ -2433,7 +2438,7 @@ export class DefaultZLinkSpotManager {
|
|
|
2433
2438
|
// A lightweight Core actor-join notification can create the Actor
|
|
2434
2439
|
// before the formal transfer request reaches this branch. Preserve
|
|
2435
2440
|
// the full relocation fence in that race so a later Session bind
|
|
2436
|
-
// refresh cannot erase the seal
|
|
2441
|
+
// refresh cannot erase the seal.
|
|
2437
2442
|
this.options.actorTransferRuntime.rememberRoutedActorTransferTarget(
|
|
2438
2443
|
actorId,
|
|
2439
2444
|
transferRequest.remoteBoundSessionTarget
|
|
@@ -2451,7 +2456,7 @@ export class DefaultZLinkSpotManager {
|
|
|
2451
2456
|
spotId,
|
|
2452
2457
|
transferId: transferRequest.transferId,
|
|
2453
2458
|
handoffBacklog: transferRequest.handoffBacklog,
|
|
2454
|
-
|
|
2459
|
+
deferredJoinCompletion
|
|
2455
2460
|
});
|
|
2456
2461
|
if (isRemoteCommit && admissionRecord !== undefined) {
|
|
2457
2462
|
this.formalRemoteActorAdmissions.markCommitted(transferRequest.transferId, actor);
|
|
@@ -2558,9 +2563,6 @@ export class DefaultZLinkSpotManager {
|
|
|
2558
2563
|
if (control.canonicalActorJoin !== undefined) {
|
|
2559
2564
|
this.formalRemoteActorAdmissions.fail(control.canonicalActorJoin.handoffId, error);
|
|
2560
2565
|
}
|
|
2561
|
-
if (deferredJoinRoot !== undefined && targetCommitPublished !== true) {
|
|
2562
|
-
await this.options.actorTransferRuntime?.discardDeferredJoinAccepted(deferredJoinRoot);
|
|
2563
|
-
}
|
|
2564
2566
|
if (targetCommitPublished !== true) {
|
|
2565
2567
|
this.formalRemoteTransfers.delete(actorId);
|
|
2566
2568
|
}
|
|
@@ -2580,6 +2582,43 @@ export class DefaultZLinkSpotManager {
|
|
|
2580
2582
|
meshName: string,
|
|
2581
2583
|
owner: ReadyRecord,
|
|
2582
2584
|
record: ReceiveRecord
|
|
2585
|
+
): Promise<void> {
|
|
2586
|
+
const spotId = owner.spotId as unknown as RoutingId | null;
|
|
2587
|
+
const activation = spotId === null ? undefined : this.activations.resolve(meshName, spotId);
|
|
2588
|
+
if (activation?.domain.kind === 'user') {
|
|
2589
|
+
const transfer = { terminal: undefined as Promise<void> | undefined };
|
|
2590
|
+
const operation = activation.serial.executeLifecycleOperation(async () => {
|
|
2591
|
+
await this.dispatchMeshSpotControlCore(meshName, owner, record, (terminal) => {
|
|
2592
|
+
transfer.terminal = terminal;
|
|
2593
|
+
});
|
|
2594
|
+
await transfer.terminal;
|
|
2595
|
+
});
|
|
2596
|
+
const control = record.kindData;
|
|
2597
|
+
const actorId = control?.kind === 'actorControl' ? control.currentActor?.actorId : undefined;
|
|
2598
|
+
if (
|
|
2599
|
+
control?.kind === 'actorControl' &&
|
|
2600
|
+
control.lifecycleKind === ActorLifecycleKind.Joined &&
|
|
2601
|
+
actorId !== undefined &&
|
|
2602
|
+
this.formalRemoteTransfers.get(actorId) !== undefined
|
|
2603
|
+
) {
|
|
2604
|
+
this.options.detachedTaskRunner?.runDetached(
|
|
2605
|
+
`actor transfer target commit ${actorId}`,
|
|
2606
|
+
async () => await operation
|
|
2607
|
+
);
|
|
2608
|
+
if (this.options.detachedTaskRunner === undefined) void operation.catch(() => undefined);
|
|
2609
|
+
return;
|
|
2610
|
+
}
|
|
2611
|
+
await operation;
|
|
2612
|
+
return;
|
|
2613
|
+
}
|
|
2614
|
+
await this.dispatchMeshSpotControlCore(meshName, owner, record);
|
|
2615
|
+
}
|
|
2616
|
+
|
|
2617
|
+
private async dispatchMeshSpotControlCore(
|
|
2618
|
+
meshName: string,
|
|
2619
|
+
owner: ReadyRecord,
|
|
2620
|
+
record: ReceiveRecord,
|
|
2621
|
+
onDetachedTerminal?: (terminal: Promise<void>) => void
|
|
2583
2622
|
): Promise<void> {
|
|
2584
2623
|
const spotId = owner.spotId as unknown as RoutingId | null;
|
|
2585
2624
|
const control = record.kindData;
|
|
@@ -2664,8 +2703,8 @@ export class DefaultZLinkSpotManager {
|
|
|
2664
2703
|
await activation.spot.onJoinedActor(actor);
|
|
2665
2704
|
};
|
|
2666
2705
|
const completePublicJoin = async (): Promise<void> => {
|
|
2667
|
-
const
|
|
2668
|
-
if (
|
|
2706
|
+
const deferredJoinCompletion = pendingTransfer?.deferredJoinCompletion;
|
|
2707
|
+
if (deferredJoinCompletion !== undefined) {
|
|
2669
2708
|
const currentRef =
|
|
2670
2709
|
this.options.actorTransferRuntime === undefined
|
|
2671
2710
|
? null
|
|
@@ -2675,8 +2714,8 @@ export class DefaultZLinkSpotManager {
|
|
|
2675
2714
|
`Actor '${actor.context.actorId}' has no target ref for deferred Join completion.`
|
|
2676
2715
|
);
|
|
2677
2716
|
}
|
|
2678
|
-
await this.options.actorTransferRuntime?.
|
|
2679
|
-
|
|
2717
|
+
await this.options.actorTransferRuntime?.deliverDeferredJoinAccepted(
|
|
2718
|
+
deferredJoinCompletion,
|
|
2680
2719
|
actor,
|
|
2681
2720
|
currentRef,
|
|
2682
2721
|
(operation) =>
|
|
@@ -2760,12 +2799,17 @@ export class DefaultZLinkSpotManager {
|
|
|
2760
2799
|
// them only after the lifecycle turn above has been released.
|
|
2761
2800
|
await completeTargetReady();
|
|
2762
2801
|
};
|
|
2763
|
-
|
|
2764
|
-
|
|
2765
|
-
|
|
2766
|
-
|
|
2767
|
-
|
|
2768
|
-
|
|
2802
|
+
const terminal = resume();
|
|
2803
|
+
if (onDetachedTerminal !== undefined) {
|
|
2804
|
+
onDetachedTerminal(terminal);
|
|
2805
|
+
} else {
|
|
2806
|
+
this.options.detachedTaskRunner?.runDetached(
|
|
2807
|
+
`actor transfer target commit ${actor.context.actorId}`,
|
|
2808
|
+
async () => await terminal
|
|
2809
|
+
);
|
|
2810
|
+
if (this.options.detachedTaskRunner === undefined) {
|
|
2811
|
+
void terminal.catch(() => undefined);
|
|
2812
|
+
}
|
|
2769
2813
|
}
|
|
2770
2814
|
return;
|
|
2771
2815
|
}
|
|
@@ -2842,7 +2886,10 @@ export class DefaultZLinkSpotManager {
|
|
|
2842
2886
|
await activation.serial.execute(() => activation.spot.onJoinedActor(actor));
|
|
2843
2887
|
}
|
|
2844
2888
|
await submitSourceLeave(admission.admission.actorRef.nodeRid);
|
|
2845
|
-
if (
|
|
2889
|
+
if (
|
|
2890
|
+
outcome.deferredJoinCompletion !== undefined &&
|
|
2891
|
+
this.options.actorTransferRuntime !== undefined
|
|
2892
|
+
) {
|
|
2846
2893
|
const submitMailbox = targetsEntry
|
|
2847
2894
|
? <T>(operation: () => Promise<T>): Promise<T> => operation()
|
|
2848
2895
|
: <T>(operation: () => Promise<T>): Promise<T> => {
|
|
@@ -2852,8 +2899,8 @@ export class DefaultZLinkSpotManager {
|
|
|
2852
2899
|
}
|
|
2853
2900
|
return activation.executeActor(actor.context.actorId, operation);
|
|
2854
2901
|
};
|
|
2855
|
-
await this.options.actorTransferRuntime.
|
|
2856
|
-
outcome.
|
|
2902
|
+
await this.options.actorTransferRuntime.deliverDeferredJoinAccepted(
|
|
2903
|
+
outcome.deferredJoinCompletion,
|
|
2857
2904
|
actor,
|
|
2858
2905
|
actorRef,
|
|
2859
2906
|
submitMailbox,
|
|
@@ -2866,9 +2913,8 @@ export class DefaultZLinkSpotManager {
|
|
|
2866
2913
|
|
|
2867
2914
|
async restoreCanonicalActorJoinRecovery(
|
|
2868
2915
|
recovery: CanonicalActorJoinRecovery,
|
|
2869
|
-
signal?: AbortSignal
|
|
2870
|
-
|
|
2871
|
-
): Promise<ZLinkDeferredJoinAcceptedRoot | undefined> {
|
|
2916
|
+
signal?: AbortSignal
|
|
2917
|
+
): Promise<void> {
|
|
2872
2918
|
throwIfAborted(signal);
|
|
2873
2919
|
const admission = this.formalRemoteActorAdmissions.get(recovery.request.handoffId);
|
|
2874
2920
|
if (admission === undefined) {
|
|
@@ -2930,24 +2976,24 @@ export class DefaultZLinkSpotManager {
|
|
|
2930
2976
|
}
|
|
2931
2977
|
// Command 28 carries a present reply in one outer framework-multipart
|
|
2932
2978
|
// part. The accepted target admission still owns the inner typed content
|
|
2933
|
-
// type, which the
|
|
2979
|
+
// type, which the process-local completion keeps for application decode.
|
|
2934
2980
|
const admittedContentType =
|
|
2935
2981
|
admittedReply.byteLength === 0 ? recovery.replyContentType : outcome.replyContentType;
|
|
2936
2982
|
const transfer = this.options.actorTransferRuntime;
|
|
2937
2983
|
if (transfer === undefined) {
|
|
2938
2984
|
throw new Error('Canonical Actor Join recovery requires the Actor transfer runtime.');
|
|
2939
2985
|
}
|
|
2940
|
-
const deferred =
|
|
2986
|
+
const deferred = transfer.prepareDeferredJoinAccepted(
|
|
2941
2987
|
recovery.request.actorId,
|
|
2942
2988
|
recovery.operationId,
|
|
2943
2989
|
admitted.actorRef,
|
|
2944
2990
|
recovery.reply,
|
|
2945
|
-
admittedContentType
|
|
2946
|
-
|
|
2947
|
-
|
|
2991
|
+
admittedContentType
|
|
2992
|
+
);
|
|
2993
|
+
this.formalRemoteActorAdmissions.attachDeferredJoinCompletion(
|
|
2994
|
+
recovery.request.handoffId,
|
|
2995
|
+
deferred
|
|
2948
2996
|
);
|
|
2949
|
-
this.formalRemoteActorAdmissions.attachDeferredJoinRoot(recovery.request.handoffId, deferred);
|
|
2950
|
-
return deferred;
|
|
2951
2997
|
}
|
|
2952
2998
|
|
|
2953
2999
|
private encodeMeshActorReply(
|