@zlink-systems/framework 0.24.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
|
@@ -22,11 +22,14 @@ export interface ZLinkSpotRuntimeOptionsFactoryOptions {
|
|
|
22
22
|
readonly actorManager: () => DefaultZLinkActorManager | undefined;
|
|
23
23
|
readonly locationLifecycle: () => ZLinkLocationLifecycle | undefined;
|
|
24
24
|
readonly releaseInstanceAuthority: (meshName: string, spotId: string, objectGeneration: bigint) => Promise<void>;
|
|
25
|
-
readonly beginInstanceIdleClosingAuthority: (meshName: string, spotId: string) => Promise<{
|
|
26
|
-
|
|
25
|
+
readonly beginInstanceIdleClosingAuthority: (meshName: string, spotId: string, onCommitted: () => void) => Promise<{
|
|
26
|
+
release(): Promise<void>;
|
|
27
27
|
} | undefined>;
|
|
28
|
-
readonly beginInstanceClosingAuthority: (meshName: string, spotId: string) => Promise<{
|
|
29
|
-
|
|
28
|
+
readonly beginInstanceClosingAuthority: (meshName: string, spotId: string, onCommitted: () => void) => Promise<{
|
|
29
|
+
release(): Promise<void>;
|
|
30
|
+
} | undefined>;
|
|
31
|
+
readonly beginUserClosingAuthority: (meshName: string, spotId: string, objectGeneration: bigint, onCommitted: () => void) => Promise<{
|
|
32
|
+
release(): Promise<void>;
|
|
30
33
|
} | undefined>;
|
|
31
34
|
readonly createLocationSpotRouteResolver: () => ZLinkSpotRouteResolver | undefined;
|
|
32
35
|
readonly boundSessionRelay: ZLinkBoundSessionRelay;
|
|
@@ -55,8 +55,9 @@ class ZLinkSpotRuntimeOptionsFactory {
|
|
|
55
55
|
detachedTaskRunner: this.options.detachedTaskRunner,
|
|
56
56
|
locationLifecycle: this.options.locationLifecycle(),
|
|
57
57
|
releaseInstanceAuthority: (meshName, spotId, objectGeneration) => this.options.releaseInstanceAuthority(meshName, String(spotId), objectGeneration),
|
|
58
|
-
beginInstanceIdleClosingAuthority: (meshName, spotId) => this.options.beginInstanceIdleClosingAuthority(meshName, String(spotId)),
|
|
59
|
-
beginInstanceClosingAuthority: (meshName, spotId) => this.options.beginInstanceClosingAuthority(meshName, String(spotId)),
|
|
58
|
+
beginInstanceIdleClosingAuthority: (meshName, spotId, onCommitted) => this.options.beginInstanceIdleClosingAuthority(meshName, String(spotId), onCommitted),
|
|
59
|
+
beginInstanceClosingAuthority: (meshName, spotId, onCommitted) => this.options.beginInstanceClosingAuthority(meshName, String(spotId), onCommitted),
|
|
60
|
+
beginUserClosingAuthority: (meshName, spotId, objectGeneration, onCommitted) => this.options.beginUserClosingAuthority(meshName, String(spotId), objectGeneration, onCommitted),
|
|
60
61
|
instanceSpotApplicationTargetProvider: (meshName, spotId) => this.options
|
|
61
62
|
.spotNodeRuntime()
|
|
62
63
|
?.meshNode(meshName)
|
|
@@ -85,12 +86,6 @@ class ZLinkSpotRuntimeOptionsFactory {
|
|
|
85
86
|
}
|
|
86
87
|
};
|
|
87
88
|
},
|
|
88
|
-
createReceived: () => {
|
|
89
|
-
const runtime = this.options.spotNodeRuntime();
|
|
90
|
-
if (runtime === undefined)
|
|
91
|
-
throw new Error('Spot backend runtime is not initialized.');
|
|
92
|
-
return runtime.createReceived();
|
|
93
|
-
},
|
|
94
89
|
createTopicMessage: () => {
|
|
95
90
|
const runtime = this.options.spotNodeRuntime();
|
|
96
91
|
if (runtime === undefined)
|
|
@@ -152,6 +147,7 @@ class ZLinkSpotRuntimeOptionsFactory {
|
|
|
152
147
|
metrics: this.options.metrics,
|
|
153
148
|
admission: this.options.admission,
|
|
154
149
|
statefulExecutionAllowed: this.options.statefulExecutionAllowed,
|
|
150
|
+
closeErrorSink: this.options.runtimeOrPreStartErrorSink,
|
|
155
151
|
dispatchErrors: this.options.dispatchErrorReporter(this.options.runtimeOrPreStartErrorSink)
|
|
156
152
|
};
|
|
157
153
|
}
|
|
@@ -78,7 +78,7 @@ class ZLinkStatefulAuthorityRouteRuntime {
|
|
|
78
78
|
const expectedSpotRoute = previousRoute?.spotRoute ?? null;
|
|
79
79
|
const expectedInstanceRoute = previousRoute?.kind === 'instance_spot' ? previousRoute.instanceRoute : null;
|
|
80
80
|
sink.rememberSpotRoute(route.spotRoute, expectedSpotRoute);
|
|
81
|
-
if (route.kind === 'instance_spot') {
|
|
81
|
+
if (route.kind === 'instance_spot' && !route.closing) {
|
|
82
82
|
const status = sink.status();
|
|
83
83
|
if ((0, routing_id_1.routingIdsEqual)(status.routingId, route.instanceRoute.targetNodeRid) &&
|
|
84
84
|
status.lifecycleGeneration === route.instanceRoute.targetNodeGeneration) {
|
|
@@ -346,7 +346,9 @@ function pendingInstanceActivation(snapshot) {
|
|
|
346
346
|
}
|
|
347
347
|
function authorityRoute(snapshot) {
|
|
348
348
|
const allocation = snapshot.allocation;
|
|
349
|
-
const
|
|
349
|
+
const payload = (0, service_relocation_runtime_1.serviceRelocationAuthorityApplicationPayload)(snapshot.payload);
|
|
350
|
+
const ready = (0, service_authority_payload_codec_1.decodeServiceReadySpotAuthority)(payload);
|
|
351
|
+
const decoded = ready ?? (0, service_authority_payload_codec_1.decodeServiceClosingSpotAuthority)(payload);
|
|
350
352
|
if (allocation.state !== 'active' ||
|
|
351
353
|
allocation.objectKind === 'actor' ||
|
|
352
354
|
allocation.descriptor.meshName.length === 0 ||
|
|
@@ -372,6 +374,7 @@ function authorityRoute(snapshot) {
|
|
|
372
374
|
};
|
|
373
375
|
return {
|
|
374
376
|
kind: allocation.objectKind,
|
|
377
|
+
closing: ready === undefined,
|
|
375
378
|
stableType: allocation.stableType,
|
|
376
379
|
meshName: allocation.descriptor.meshName,
|
|
377
380
|
spotRoute,
|
|
@@ -397,6 +400,7 @@ function sameAppliedRoute(left, right) {
|
|
|
397
400
|
if (right === undefined)
|
|
398
401
|
return false;
|
|
399
402
|
return (left.kind === right.kind &&
|
|
403
|
+
left.closing === right.closing &&
|
|
400
404
|
left.stableType === right.stableType &&
|
|
401
405
|
left.meshName === right.meshName &&
|
|
402
406
|
left.instanceRoute.targetNodeRid === right.instanceRoute.targetNodeRid &&
|
|
@@ -53,15 +53,23 @@ export declare class ZLinkUserSpotCreationCoordinator {
|
|
|
53
53
|
readonly nodeRid: RoutingId;
|
|
54
54
|
readonly isLocal: boolean;
|
|
55
55
|
}, authority: ZLinkAuthoritySnapshot, signal: AbortSignal) => Promise<ZLinkLocalSpotCreateResult>, discard?: (signal?: AbortSignal) => Promise<void>): Promise<ZLinkUserSpotCreationResult>;
|
|
56
|
-
close(spot: SpotRef, closeOwner: (current: SpotRef,
|
|
56
|
+
close(spot: SpotRef, closeOwner: (current: SpotRef, beginAuthority: (onCommitted: () => void) => Promise<{
|
|
57
|
+
release(): Promise<void>;
|
|
58
|
+
}>) => Promise<boolean>, signal?: AbortSignal): Promise<boolean>;
|
|
59
|
+
/** Commits Closing for the owner's own incarnation when its context requests Close. */
|
|
60
|
+
beginOwnerClose(spot: SpotRef, onCommitted: () => void): Promise<{
|
|
61
|
+
release(): Promise<void>;
|
|
62
|
+
} | undefined>;
|
|
57
63
|
resolveCloseTarget(spot: SpotRef, signal?: AbortSignal): Promise<ZLinkUserSpotCloseTarget | undefined>;
|
|
58
64
|
handleRemoteCreate(record: ServiceUserSpotCreateRecord, materialize: (requestPayload: Uint8Array, authority: ZLinkAuthoritySnapshot, signal: AbortSignal) => Promise<ZLinkLocalSpotCreateResult>, discard?: (signal?: AbortSignal) => Promise<void>, signal?: AbortSignal): Promise<ZLinkUserSpotCreationResult>;
|
|
59
65
|
private handleLocalCreate;
|
|
60
66
|
private materializeRemoteCreate;
|
|
61
|
-
handleRemoteClose(record: ServiceUserSpotCloseRecord, closeOwner: (spot: SpotRef,
|
|
67
|
+
handleRemoteClose(record: ServiceUserSpotCloseRecord, closeOwner: (spot: SpotRef, beginAuthority: (onCommitted: () => void) => Promise<{
|
|
68
|
+
release(): Promise<void>;
|
|
69
|
+
}>, signal?: AbortSignal) => Promise<boolean>, signal?: AbortSignal, canResume?: (spot: SpotRef) => boolean): Promise<boolean>;
|
|
70
|
+
private commitCloseAuthority;
|
|
62
71
|
forgetReadyRoute(spotId: RoutingId, snapshot: ZLinkAuthoritySnapshot): void;
|
|
63
72
|
private beginClosing;
|
|
64
|
-
private restoreReady;
|
|
65
73
|
private awaitReady;
|
|
66
74
|
private remoteCreate;
|
|
67
75
|
}
|
|
@@ -192,60 +192,35 @@ class ZLinkUserSpotCreationCoordinator {
|
|
|
192
192
|
deadline.close();
|
|
193
193
|
}
|
|
194
194
|
}
|
|
195
|
-
async close(spot, closeOwner, signal
|
|
195
|
+
async close(spot, closeOwner, signal) {
|
|
196
196
|
const resolved = await this.resolveCloseTarget(spot, signal);
|
|
197
197
|
if (resolved === undefined)
|
|
198
198
|
return false;
|
|
199
199
|
const { spot: currentRef, snapshot: current } = resolved;
|
|
200
200
|
const key = (0, authority_key_codec_1.encodeAuthorityKey)('user_spot', String(spot.spotId));
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
}
|
|
211
|
-
catch (error) {
|
|
212
|
-
await this.restoreReady(key, closing, String(spot.spotId), signal);
|
|
213
|
-
throw error;
|
|
214
|
-
}
|
|
215
|
-
if (!closed) {
|
|
216
|
-
await this.restoreReady(key, closing, String(spot.spotId), signal);
|
|
217
|
-
return false;
|
|
218
|
-
}
|
|
219
|
-
const deleted = await this.options.store.compareExchangeAuthority(key, closing.storeVersion, { kind: 'delete' }, signal);
|
|
220
|
-
if (deleted.kind === 'deleted') {
|
|
221
|
-
this.forgetReadyRoute(currentRef.spotId, current);
|
|
222
|
-
return true;
|
|
223
|
-
}
|
|
224
|
-
if (deleted.kind === 'conflict') {
|
|
225
|
-
throw (0, framework_errors_internal_1.createInternalFrameworkException)(framework_errors_internal_1.ZLinkFrameworkInternalErrorKind.SpotMoving, `User Spot '${String(spot.spotId)}' authority changed while closing.`, true);
|
|
226
|
-
}
|
|
227
|
-
throw (0, framework_errors_internal_1.createInternalFrameworkException)(framework_errors_internal_1.ZLinkFrameworkInternalErrorKind.SpotGenerationStale, `User Spot '${String(spot.spotId)}' generation cannot be closed.`);
|
|
201
|
+
return await closeOwner(currentRef, async (onCommitted) => this.commitCloseAuthority(key, current, String(spot.spotId), onCommitted));
|
|
202
|
+
}
|
|
203
|
+
/** Commits Closing for the owner's own incarnation when its context requests Close. */
|
|
204
|
+
async beginOwnerClose(spot, onCommitted) {
|
|
205
|
+
const resolved = await this.resolveCloseTarget(spot);
|
|
206
|
+
if (resolved === undefined)
|
|
207
|
+
return undefined;
|
|
208
|
+
const spotId = String(spot.spotId);
|
|
209
|
+
return await this.commitCloseAuthority((0, authority_key_codec_1.encodeAuthorityKey)('user_spot', spotId), resolved.snapshot, spotId, onCommitted);
|
|
228
210
|
}
|
|
229
211
|
async resolveCloseTarget(spot, signal) {
|
|
230
212
|
const key = (0, authority_key_codec_1.encodeAuthorityKey)('user_spot', String(spot.spotId));
|
|
231
213
|
const current = await this.options.store.readAuthority(key, signal);
|
|
232
214
|
if (current.kind === 'missing')
|
|
233
215
|
return undefined;
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
timeoutMs: 1
|
|
243
|
-
});
|
|
244
|
-
if (String(current.allocation.descriptor.rid) !== String(spot.nodeRid) ||
|
|
245
|
-
current.allocation.descriptor.meshName !== spot.meshName) {
|
|
246
|
-
throw (0, framework_errors_internal_1.createInternalFrameworkException)(framework_errors_internal_1.ZLinkFrameworkInternalErrorKind.SpotGenerationStale, `User Spot '${String(spot.spotId)}' owner route is stale.`);
|
|
247
|
-
}
|
|
248
|
-
return { spot: currentRef, snapshot: current };
|
|
216
|
+
return {
|
|
217
|
+
spot: requireCloseTarget(current, String(spot.spotId), {
|
|
218
|
+
objectGeneration: spot.objectGeneration,
|
|
219
|
+
nodeRid: String(spot.nodeRid),
|
|
220
|
+
meshName: spot.meshName
|
|
221
|
+
}),
|
|
222
|
+
snapshot: current
|
|
223
|
+
};
|
|
249
224
|
}
|
|
250
225
|
async handleRemoteCreate(record, materialize, discard, signal) {
|
|
251
226
|
const key = `${record.spotId}\0${record.reservation.reservationId}`;
|
|
@@ -430,52 +405,50 @@ class ZLinkUserSpotCreationCoordinator {
|
|
|
430
405
|
throw error;
|
|
431
406
|
}
|
|
432
407
|
}
|
|
433
|
-
async handleRemoteClose(record, closeOwner, signal) {
|
|
408
|
+
async handleRemoteClose(record, closeOwner, signal, canResume) {
|
|
434
409
|
const key = (0, authority_key_codec_1.encodeAuthorityKey)('user_spot', record.target.spotId);
|
|
435
410
|
const current = await this.options.store.readAuthority(key, signal);
|
|
436
411
|
if (current.kind === 'missing')
|
|
437
412
|
return false;
|
|
438
|
-
|
|
439
|
-
throw (0, framework_errors_internal_1.createInternalFrameworkException)(framework_errors_internal_1.ZLinkFrameworkInternalErrorKind.SpotGenerationStale, `User Spot '${record.target.spotId}' generation is stale.`);
|
|
440
|
-
}
|
|
441
|
-
if (current.authorityOwnerGeneration !== record.target.authorityOwnerGeneration ||
|
|
442
|
-
current.storeVersion.value !== record.target.expectedStoreVersion ||
|
|
443
|
-
String(current.allocation.descriptor.rid) !== record.target.targetNodeRid ||
|
|
444
|
-
current.allocation.descriptorLifecycleGeneration !== record.target.targetNodeGeneration ||
|
|
445
|
-
current.allocation.objectKind !== 'user_spot' ||
|
|
446
|
-
current.allocation.state !== 'active') {
|
|
447
|
-
throw (0, framework_errors_internal_1.createInternalFrameworkException)(framework_errors_internal_1.ZLinkFrameworkInternalErrorKind.SpotMoving, `User Spot '${record.target.spotId}' close authority is moving.`, true);
|
|
448
|
-
}
|
|
449
|
-
const spot = {
|
|
413
|
+
const candidate = {
|
|
450
414
|
spotId: record.target.spotId,
|
|
451
415
|
objectGeneration: current.objectGeneration,
|
|
452
416
|
meshName: current.allocation.descriptor.meshName,
|
|
453
417
|
nodeRid: current.allocation.descriptor.rid
|
|
454
418
|
};
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
419
|
+
// A Closing committed by this owner is resumed, so its store version has
|
|
420
|
+
// advanced past the one the source observed.
|
|
421
|
+
const resuming = canResume?.(candidate) === true &&
|
|
422
|
+
(0, service_authority_payload_codec_1.decodeServiceClosingSpotAuthority)(current.payload)?.kind === 'user_spot';
|
|
423
|
+
const spot = requireCloseTarget(current, record.target.spotId, {
|
|
424
|
+
objectGeneration: record.target.objectGeneration,
|
|
425
|
+
nodeRid: record.target.targetNodeRid,
|
|
426
|
+
nodeGeneration: record.target.targetNodeGeneration,
|
|
427
|
+
authorityOwnerGeneration: record.target.authorityOwnerGeneration,
|
|
428
|
+
storeVersion: resuming ? undefined : record.target.expectedStoreVersion
|
|
429
|
+
});
|
|
430
|
+
return await closeOwner(spot, async (onCommitted) => this.commitCloseAuthority(key, current, record.target.spotId, onCommitted), signal);
|
|
431
|
+
}
|
|
432
|
+
async commitCloseAuthority(key, current, spotId, onCommitted) {
|
|
433
|
+
const closing = await this.beginClosing(key, current, spotId);
|
|
434
|
+
const authority = {
|
|
435
|
+
release: async () => {
|
|
436
|
+
this.forgetReadyRoute(spotId, current);
|
|
437
|
+
const deleted = await this.options.store.compareExchangeAuthority(key, closing.storeVersion, {
|
|
438
|
+
kind: 'delete'
|
|
439
|
+
});
|
|
440
|
+
if (deleted.kind !== 'deleted') {
|
|
441
|
+
throw (0, framework_errors_internal_1.createInternalFrameworkException)(framework_errors_internal_1.ZLinkFrameworkInternalErrorKind.SpotMoving, `User Spot '${spotId}' authority changed while closing.`, true);
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
};
|
|
445
|
+
onCommitted();
|
|
446
|
+
return authority;
|
|
474
447
|
}
|
|
475
448
|
forgetReadyRoute(spotId, snapshot) {
|
|
476
449
|
this.options.forgetReadyRoute?.(snapshot.allocation.descriptor.meshName, readySpotRoute(spotId, snapshot));
|
|
477
450
|
}
|
|
478
|
-
async beginClosing(key, current, spotId
|
|
451
|
+
async beginClosing(key, current, spotId) {
|
|
479
452
|
const ready = (0, service_authority_payload_codec_1.decodeServiceReadySpotAuthority)(current.payload);
|
|
480
453
|
if (ready?.kind !== 'user_spot' ||
|
|
481
454
|
ready.spotId !== spotId ||
|
|
@@ -486,23 +459,13 @@ class ZLinkUserSpotCreationCoordinator {
|
|
|
486
459
|
kind: 'put',
|
|
487
460
|
payload: userSpotAuthorityPayload(current, spotId, 'closing'),
|
|
488
461
|
generationTransition: 'preserve'
|
|
489
|
-
},
|
|
462
|
+
}, undefined);
|
|
490
463
|
if (closing.kind === 'stored') {
|
|
491
464
|
const { kind: _kind, ...snapshot } = closing;
|
|
492
465
|
return { kind: 'snapshot', ...snapshot };
|
|
493
466
|
}
|
|
494
467
|
throw (0, framework_errors_internal_1.createInternalFrameworkException)(framework_errors_internal_1.ZLinkFrameworkInternalErrorKind.SpotMoving, `User Spot authority changed while entering Closing.`, true);
|
|
495
468
|
}
|
|
496
|
-
async restoreReady(key, closing, spotId, signal) {
|
|
497
|
-
const restored = await this.options.store.compareExchangeAuthority(key, closing.storeVersion, {
|
|
498
|
-
kind: 'put',
|
|
499
|
-
payload: userSpotAuthorityPayload(closing, spotId, 'ready'),
|
|
500
|
-
generationTransition: 'preserve'
|
|
501
|
-
}, signal);
|
|
502
|
-
if (restored.kind !== 'stored') {
|
|
503
|
-
throw (0, framework_errors_internal_1.createInternalFrameworkException)(framework_errors_internal_1.ZLinkFrameworkInternalErrorKind.SpotMoving, 'User Spot Ready authority could not be restored after close was declined.', true);
|
|
504
|
-
}
|
|
505
|
-
}
|
|
506
469
|
async awaitReady(request, signal) {
|
|
507
470
|
const key = (0, authority_key_codec_1.encodeAuthorityKey)('user_spot', String(request.spotId));
|
|
508
471
|
for (;;) {
|
|
@@ -588,6 +551,41 @@ function readySpotRoute(spotId, snapshot) {
|
|
|
588
551
|
storeVersion: snapshot.storeVersion.value
|
|
589
552
|
};
|
|
590
553
|
}
|
|
554
|
+
/**
|
|
555
|
+
* The single classifier of a Close target (§7, §9): another ObjectGeneration is
|
|
556
|
+
* SpotGenerationStale; any owner fence difference or an authority that is not
|
|
557
|
+
* in a Framework-owned Ready or Closing state is SpotMoving.
|
|
558
|
+
*/
|
|
559
|
+
function requireCloseTarget(current, spotId, fence) {
|
|
560
|
+
if (current.objectGeneration !== fence.objectGeneration) {
|
|
561
|
+
throw (0, framework_errors_internal_1.createInternalFrameworkException)(framework_errors_internal_1.ZLinkFrameworkInternalErrorKind.SpotGenerationStale, `User Spot '${spotId}' generation is stale.`);
|
|
562
|
+
}
|
|
563
|
+
// A committed Closing stays the close target: its owner resumes that Close.
|
|
564
|
+
const decoded = (0, service_authority_payload_codec_1.decodeServiceReadySpotAuthority)(current.payload) ??
|
|
565
|
+
(0, service_authority_payload_codec_1.decodeServiceClosingSpotAuthority)(current.payload);
|
|
566
|
+
const allocation = current.allocation;
|
|
567
|
+
if (decoded?.kind !== 'user_spot' ||
|
|
568
|
+
decoded.spotId !== spotId ||
|
|
569
|
+
decoded.ownerId !== current.ownerId ||
|
|
570
|
+
decoded.ownerLeaseGeneration !== current.ownerLeaseGeneration ||
|
|
571
|
+
allocation.objectKind !== 'user_spot' ||
|
|
572
|
+
allocation.state !== 'active' ||
|
|
573
|
+
String(allocation.descriptor.rid) !== fence.nodeRid ||
|
|
574
|
+
(fence.meshName !== undefined && allocation.descriptor.meshName !== fence.meshName) ||
|
|
575
|
+
(fence.nodeGeneration !== undefined &&
|
|
576
|
+
allocation.descriptorLifecycleGeneration !== fence.nodeGeneration) ||
|
|
577
|
+
(fence.authorityOwnerGeneration !== undefined &&
|
|
578
|
+
current.authorityOwnerGeneration !== fence.authorityOwnerGeneration) ||
|
|
579
|
+
(fence.storeVersion !== undefined && current.storeVersion.value !== fence.storeVersion)) {
|
|
580
|
+
throw (0, framework_errors_internal_1.createInternalFrameworkException)(framework_errors_internal_1.ZLinkFrameworkInternalErrorKind.SpotMoving, `User Spot '${spotId}' owner fence changed or the Spot is moving.`, true);
|
|
581
|
+
}
|
|
582
|
+
return {
|
|
583
|
+
spotId: spotId,
|
|
584
|
+
objectGeneration: current.objectGeneration,
|
|
585
|
+
meshName: allocation.descriptor.meshName,
|
|
586
|
+
nodeRid: allocation.descriptor.rid
|
|
587
|
+
};
|
|
588
|
+
}
|
|
591
589
|
function spotRef(snapshot, request, allowPending = false) {
|
|
592
590
|
const decoded = (0, service_authority_payload_codec_1.decodeServiceReadySpotAuthority)(snapshot.payload);
|
|
593
591
|
if (allowPending
|
|
@@ -52,11 +52,9 @@ class ZLinkInMemoryProviderLocationStore {
|
|
|
52
52
|
this.values.delete(mutation.key.value);
|
|
53
53
|
continue;
|
|
54
54
|
}
|
|
55
|
-
requireValue(mutation.bytes, mutation.retentionMs);
|
|
55
|
+
const retentionMs = requireValue(mutation.bytes, mutation.retentionMs);
|
|
56
56
|
const version = storeVersion((++this.nextVersion).toString());
|
|
57
|
-
const expiresAt =
|
|
58
|
-
? undefined
|
|
59
|
-
: new Date(storeNow.getTime() + mutation.retentionMs);
|
|
57
|
+
const expiresAt = retentionMs === undefined ? undefined : new Date(storeNow.getTime() + retentionMs);
|
|
60
58
|
this.values.set(mutation.key.value, {
|
|
61
59
|
bytes: mutation.bytes.slice(),
|
|
62
60
|
version,
|
|
@@ -169,9 +167,13 @@ function requireValue(bytes, retentionMs) {
|
|
|
169
167
|
if (bytes.byteLength > 1024 * 1024) {
|
|
170
168
|
throw new RangeError('Location Store value exceeds 1 MiB.');
|
|
171
169
|
}
|
|
172
|
-
if (retentionMs !== undefined &&
|
|
173
|
-
|
|
170
|
+
if (retentionMs !== undefined &&
|
|
171
|
+
(!Number.isFinite(retentionMs) ||
|
|
172
|
+
retentionMs <= 0 ||
|
|
173
|
+
!Number.isSafeInteger(Math.ceil(retentionMs)))) {
|
|
174
|
+
throw new RangeError('Location Store retention must round to a positive safe integer.');
|
|
174
175
|
}
|
|
176
|
+
return retentionMs === undefined ? undefined : Math.ceil(retentionMs);
|
|
175
177
|
}
|
|
176
178
|
function requireKey(value) {
|
|
177
179
|
const bytes = Buffer.byteLength(value, 'utf8');
|
|
@@ -31,7 +31,7 @@ export declare class ZLinkLocationLifecycle {
|
|
|
31
31
|
private retryActorRelease;
|
|
32
32
|
claimSpot(meshName: string, spotId: RoutingId, spotType: string, nodeRid: RoutingId, spotKind: ZLinkSpotKind, spotGeneration: bigint, ownerNodeGeneration: bigint, deactivate?: () => Promise<void>): Promise<ZLinkLocationWriteStatus>;
|
|
33
33
|
releaseSpot(meshName: string, spotId: RoutingId, expectedObjectGeneration?: bigint): Promise<void>;
|
|
34
|
-
beginInstanceSpotClosing(meshName: string, spotId: RoutingId): Promise<ZLinkInstanceClosingAuthority | undefined>;
|
|
34
|
+
beginInstanceSpotClosing(meshName: string, spotId: RoutingId, onCommitted: () => void): Promise<ZLinkInstanceClosingAuthority | undefined>;
|
|
35
35
|
trackInstanceSpot(input: ZLinkTrackedInstanceAuthority): void;
|
|
36
36
|
reclaimOwnerRows(): Promise<void>;
|
|
37
37
|
bindActorSessionRoute(sessionRid: RoutingId, actorId: string, ownerNodeRid: RoutingId): Promise<void>;
|
|
@@ -81,8 +81,8 @@ class ZLinkLocationLifecycle {
|
|
|
81
81
|
async releaseSpot(meshName, spotId, expectedObjectGeneration) {
|
|
82
82
|
await this.spotClaims.release(meshName, spotId, expectedObjectGeneration);
|
|
83
83
|
}
|
|
84
|
-
async beginInstanceSpotClosing(meshName, spotId) {
|
|
85
|
-
return await this.spotClaims.beginInstanceClosing(meshName, spotId);
|
|
84
|
+
async beginInstanceSpotClosing(meshName, spotId, onCommitted) {
|
|
85
|
+
return await this.spotClaims.beginInstanceClosing(meshName, spotId, onCommitted);
|
|
86
86
|
}
|
|
87
87
|
trackInstanceSpot(input) {
|
|
88
88
|
this.spotClaims.trackInstanceAuthority(input);
|
|
@@ -582,7 +582,10 @@ class ZLinkAuthoritySpotRouteResolver {
|
|
|
582
582
|
return prepared.cached;
|
|
583
583
|
const current = await this.store.readAuthority((0, authority_key_codec_1.encodeAuthorityKey)('user_spot', key), signal);
|
|
584
584
|
if (current.kind === 'snapshot' && current.allocation.state === 'active') {
|
|
585
|
-
const
|
|
585
|
+
const authorityPayload = (0, service_relocation_runtime_1.serviceRelocationAuthorityApplicationPayload)(current.payload);
|
|
586
|
+
const ready = (0, service_authority_payload_codec_1.decodeServiceReadySpotAuthority)(authorityPayload);
|
|
587
|
+
const closing = (0, service_authority_payload_codec_1.decodeServiceClosingSpotAuthority)(authorityPayload);
|
|
588
|
+
const decoded = ready ?? closing;
|
|
586
589
|
if (decoded !== undefined &&
|
|
587
590
|
decoded.spotId === String(spotId) &&
|
|
588
591
|
decoded.ownerId === current.ownerId &&
|
|
@@ -610,7 +613,9 @@ class ZLinkAuthoritySpotRouteResolver {
|
|
|
610
613
|
authorityStoreVersion: current.storeVersion.value,
|
|
611
614
|
targetNodeState: await this.targetNodeStateResolver?.(decoded.ownerMeshName, decoded.ownerNodeRid, current.allocation.descriptorLifecycleGeneration, signal)
|
|
612
615
|
};
|
|
613
|
-
|
|
616
|
+
if (ready !== undefined) {
|
|
617
|
+
await this.lane.run(() => this.cacheResolutionCore(key, prepared.epoch, target, remainingLeaseMs, current.storeVersion.value));
|
|
618
|
+
}
|
|
614
619
|
return target;
|
|
615
620
|
}
|
|
616
621
|
}
|
|
@@ -13,7 +13,7 @@ export declare class ZLinkSpotLocationClaims {
|
|
|
13
13
|
claim(meshName: string, spotId: RoutingId, spotType: string, nodeRid: RoutingId, spotKind: ZLinkSpotKind, spotGeneration: bigint, ownerNodeGeneration: bigint, deactivate?: () => Promise<void>): Promise<ZLinkLocationWriteStatus>;
|
|
14
14
|
trackInstanceAuthority(input: ZLinkTrackedInstanceAuthority): void;
|
|
15
15
|
release(meshName: string, spotId: RoutingId, expectedObjectGeneration?: bigint): Promise<void>;
|
|
16
|
-
beginInstanceClosing(meshName: string, spotId: RoutingId): Promise<ZLinkInstanceClosingAuthority | undefined>;
|
|
16
|
+
beginInstanceClosing(meshName: string, spotId: RoutingId, onCommitted: () => void): Promise<ZLinkInstanceClosingAuthority | undefined>;
|
|
17
17
|
onOwnershipLost(event: ZLinkOwnershipLostEvent): void;
|
|
18
18
|
reclaimOwnerRows(): Promise<void>;
|
|
19
19
|
private releaseAuthority;
|
|
@@ -32,5 +32,5 @@ export interface ZLinkTrackedInstanceAuthority {
|
|
|
32
32
|
readonly deactivate?: () => Promise<void>;
|
|
33
33
|
}
|
|
34
34
|
export interface ZLinkInstanceClosingAuthority {
|
|
35
|
-
|
|
35
|
+
release(): Promise<void>;
|
|
36
36
|
}
|
|
@@ -82,7 +82,7 @@ class ZLinkSpotLocationClaims {
|
|
|
82
82
|
}
|
|
83
83
|
this.invalidateSpotRoute?.(tracked.spotId);
|
|
84
84
|
}
|
|
85
|
-
async beginInstanceClosing(meshName, spotId) {
|
|
85
|
+
async beginInstanceClosing(meshName, spotId, onCommitted) {
|
|
86
86
|
const canonical = key_codec_1.ZLinkLocationKeyCodec.encodeSpotKey({ meshName, spotId });
|
|
87
87
|
const tracked = this.spots.get(canonical);
|
|
88
88
|
const store = this.authorityStore;
|
|
@@ -116,33 +116,9 @@ class ZLinkSpotLocationClaims {
|
|
|
116
116
|
return undefined;
|
|
117
117
|
}
|
|
118
118
|
tracked.storeVersion = result.storeVersion.value;
|
|
119
|
-
|
|
120
|
-
let restored = false;
|
|
119
|
+
onCommitted();
|
|
121
120
|
return {
|
|
122
|
-
|
|
123
|
-
if (restored)
|
|
124
|
-
return;
|
|
125
|
-
const restore = await store.compareExchangeAuthority(key, result.storeVersion, {
|
|
126
|
-
kind: 'put',
|
|
127
|
-
generationTransition: 'preserve',
|
|
128
|
-
payload: (0, service_relocation_runtime_1.replaceServiceRelocationAuthorityApplicationPayload)(current.payload, (0, service_authority_payload_codec_1.encodeServiceInstanceAuthorityPayload)({
|
|
129
|
-
state: 'ready',
|
|
130
|
-
stableType: decoded.stableType,
|
|
131
|
-
spotId: decoded.spotId,
|
|
132
|
-
ownerId: decoded.ownerId,
|
|
133
|
-
ownerLeaseGeneration: decoded.ownerLeaseGeneration,
|
|
134
|
-
ownerMeshName: decoded.ownerMeshName,
|
|
135
|
-
ownerNodeRid: decoded.ownerNodeRid,
|
|
136
|
-
ownerNodeGeneration: decoded.ownerNodeGeneration
|
|
137
|
-
}))
|
|
138
|
-
});
|
|
139
|
-
if (restore.kind !== 'stored') {
|
|
140
|
-
throw (0, framework_errors_internal_1.createInternalFrameworkException)(framework_errors_internal_1.ZLinkFrameworkInternalErrorKind.SpotMoving, `Instance Spot '${String(spotId)}' Ready authority could not be restored after idle eviction was declined.`, true);
|
|
141
|
-
}
|
|
142
|
-
restored = true;
|
|
143
|
-
tracked.storeVersion = restore.storeVersion.value;
|
|
144
|
-
this.invalidateSpotRoute?.(tracked.spotId);
|
|
145
|
-
}
|
|
121
|
+
release: async () => undefined
|
|
146
122
|
};
|
|
147
123
|
}
|
|
148
124
|
onOwnershipLost(event) {
|
|
@@ -343,6 +343,7 @@ export type SessionRelocationRouteUpdate = {
|
|
|
343
343
|
readonly targetAuthorityOwnerGeneration: NonzeroU64;
|
|
344
344
|
readonly targetNodeRid: Rid;
|
|
345
345
|
readonly targetNodeGeneration: NonzeroU64;
|
|
346
|
+
readonly targetOwnerLeaseGeneration: NonzeroU64;
|
|
346
347
|
} | {
|
|
347
348
|
readonly action: "abort";
|
|
348
349
|
readonly currentAuthorityOwnerGeneration: NonzeroU64;
|
|
@@ -3701,6 +3701,7 @@ function readSessionRelocationRouteUpdate(reader, context, enclosing, flags) {
|
|
|
3701
3701
|
value["targetAuthorityOwnerGeneration"] = readNonzeroU64(body, context, value, flags);
|
|
3702
3702
|
value["targetNodeRid"] = readRid(body, context, value, flags);
|
|
3703
3703
|
value["targetNodeGeneration"] = readNonzeroU64(body, context, value, flags);
|
|
3704
|
+
value["targetOwnerLeaseGeneration"] = readNonzeroU64(body, context, value, flags);
|
|
3704
3705
|
}
|
|
3705
3706
|
else if (same(value["action"], "abort")) {
|
|
3706
3707
|
value["currentAuthorityOwnerGeneration"] = readNonzeroU64(body, context, value, flags);
|
|
@@ -3732,9 +3733,12 @@ function writeSessionRelocationRouteUpdate(input, writer, context, enclosing, fl
|
|
|
3732
3733
|
if (value["targetNodeGeneration"] === undefined)
|
|
3733
3734
|
fail("targetNodeGeneration required");
|
|
3734
3735
|
writeNonzeroU64(numeric(value["targetNodeGeneration"]), body, context, value, flags);
|
|
3736
|
+
if (value["targetOwnerLeaseGeneration"] === undefined)
|
|
3737
|
+
fail("targetOwnerLeaseGeneration required");
|
|
3738
|
+
writeNonzeroU64(numeric(value["targetOwnerLeaseGeneration"]), body, context, value, flags);
|
|
3735
3739
|
}
|
|
3736
3740
|
else if (same(value["action"], "abort")) {
|
|
3737
|
-
if (value["previousAuthorityOwnerGeneration"] !== undefined || value["targetAuthorityOwnerGeneration"] !== undefined || value["targetNodeRid"] !== undefined || value["targetNodeGeneration"] !== undefined)
|
|
3741
|
+
if (value["previousAuthorityOwnerGeneration"] !== undefined || value["targetAuthorityOwnerGeneration"] !== undefined || value["targetNodeRid"] !== undefined || value["targetNodeGeneration"] !== undefined || value["targetOwnerLeaseGeneration"] !== undefined)
|
|
3738
3742
|
fail("session-relocation-route-update discriminator agreement");
|
|
3739
3743
|
if (value["currentAuthorityOwnerGeneration"] === undefined)
|
|
3740
3744
|
fail("currentAuthorityOwnerGeneration required");
|
|
@@ -200,6 +200,7 @@ export type ServiceWireSessionRouteUpdate = {
|
|
|
200
200
|
readonly targetAuthorityOwnerGeneration: bigint;
|
|
201
201
|
readonly targetNodeRid: Uint8Array;
|
|
202
202
|
readonly targetNodeGeneration: bigint;
|
|
203
|
+
readonly targetOwnerLeaseGeneration: bigint;
|
|
203
204
|
} | {
|
|
204
205
|
readonly action: "abort";
|
|
205
206
|
readonly currentAuthorityOwnerGeneration: bigint;
|
|
@@ -522,12 +522,13 @@ function b3ValidTerminal(result, failure, payload) { const boundary = [101, 103,
|
|
|
522
522
|
} if (b3FailureResults.get(failure) !== result)
|
|
523
523
|
throw new RangeError("typed failure"); }
|
|
524
524
|
function b3WriteRoute(out, v) { out.push(v.action === "commit" ? 1 : 2); body16(out, b => { if (v.action === "commit") {
|
|
525
|
-
if (v.previousAuthorityOwnerGeneration === 0n || v.targetAuthorityOwnerGeneration === 0n || v.targetNodeGeneration === 0n)
|
|
525
|
+
if (v.previousAuthorityOwnerGeneration === 0n || v.targetAuthorityOwnerGeneration === 0n || v.targetNodeGeneration === 0n || v.targetOwnerLeaseGeneration === 0n)
|
|
526
526
|
throw new RangeError("route commit");
|
|
527
527
|
u64(b, v.previousAuthorityOwnerGeneration);
|
|
528
528
|
u64(b, v.targetAuthorityOwnerGeneration);
|
|
529
529
|
rid(b, v.targetNodeRid);
|
|
530
530
|
u64(b, v.targetNodeGeneration);
|
|
531
|
+
u64(b, v.targetOwnerLeaseGeneration);
|
|
531
532
|
}
|
|
532
533
|
else {
|
|
533
534
|
if (v.currentAuthorityOwnerGeneration === 0n)
|
|
@@ -535,7 +536,7 @@ else {
|
|
|
535
536
|
u64(b, v.currentAuthorityOwnerGeneration);
|
|
536
537
|
} }); }
|
|
537
538
|
function b3ReadRoute(bytes, at) { const action = read8(bytes, at), end = boundedEnd(bytes, at, read16(bytes, at), "session route"); let value; if (action === 1)
|
|
538
|
-
value = { action: "commit", previousAuthorityOwnerGeneration: nonzero64(bytes, at, "previous authority"), targetAuthorityOwnerGeneration: nonzero64(bytes, at, "target authority"), targetNodeRid: readRid(bytes, at), targetNodeGeneration: nonzero64(bytes, at, "target node") };
|
|
539
|
+
value = { action: "commit", previousAuthorityOwnerGeneration: nonzero64(bytes, at, "previous authority"), targetAuthorityOwnerGeneration: nonzero64(bytes, at, "target authority"), targetNodeRid: readRid(bytes, at), targetNodeGeneration: nonzero64(bytes, at, "target node"), targetOwnerLeaseGeneration: nonzero64(bytes, at, "target lease") };
|
|
539
540
|
else if (action === 2)
|
|
540
541
|
value = { action: "abort", currentAuthorityOwnerGeneration: nonzero64(bytes, at, "current authority") };
|
|
541
542
|
else
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { ActorRef, RoutingId, ZLinkActor, ZLinkActorJoinOperationId } from '../../contracts';
|
|
2
2
|
import type { ZLinkRemoteBoundSessionTarget } from '../actors/actor-runtime-state';
|
|
3
|
-
import type {
|
|
3
|
+
import type { ZLinkDeferredJoinCompletion } from '../actors/deferred-join-completion';
|
|
4
4
|
import type { ZLinkActorRequestTerminal } from './spot-actor-packet-dispatch';
|
|
5
5
|
/**
|
|
6
6
|
* One production-ingress arrival parked at the target between admission
|
|
@@ -40,7 +40,7 @@ export interface ZLinkFormalRemoteActorAdmissionOutcome {
|
|
|
40
40
|
readonly actorRef: ActorRef;
|
|
41
41
|
readonly reply?: Buffer;
|
|
42
42
|
readonly replyContentType?: string;
|
|
43
|
-
readonly
|
|
43
|
+
readonly deferredJoinCompletion?: ZLinkDeferredJoinCompletion;
|
|
44
44
|
}
|
|
45
45
|
export interface ZLinkFormalRemoteActorAdmissionFailure {
|
|
46
46
|
readonly error: unknown;
|
|
@@ -111,7 +111,7 @@ export declare class ZLinkFormalRemoteActorAdmissionRegistry {
|
|
|
111
111
|
complete(transferId: string, outcome: ZLinkFormalRemoteActorAdmissionOutcome): void;
|
|
112
112
|
fail(transferId: string, error: unknown): void;
|
|
113
113
|
markCommitted(transferId: string, actor: ZLinkActor): void;
|
|
114
|
-
|
|
114
|
+
attachDeferredJoinCompletion(transferId: string, root: ZLinkDeferredJoinCompletion): void;
|
|
115
115
|
abort(transferId: string): void;
|
|
116
116
|
/**
|
|
117
117
|
* Releases the admission for {@code transferId} — normal retention
|
|
@@ -161,9 +161,9 @@ class ZLinkFormalRemoteActorAdmissionRegistry {
|
|
|
161
161
|
...(outcome.replyContentType === undefined
|
|
162
162
|
? {}
|
|
163
163
|
: { replyContentType: outcome.replyContentType }),
|
|
164
|
-
...(outcome.
|
|
164
|
+
...(outcome.deferredJoinCompletion === undefined
|
|
165
165
|
? {}
|
|
166
|
-
: {
|
|
166
|
+
: { deferredJoinCompletion: outcome.deferredJoinCompletion })
|
|
167
167
|
};
|
|
168
168
|
entry.resolveResult(entry.result);
|
|
169
169
|
if (!outcome.accepted) {
|
|
@@ -192,7 +192,7 @@ class ZLinkFormalRemoteActorAdmissionRegistry {
|
|
|
192
192
|
entry.state = 'committed';
|
|
193
193
|
entry.actor = actor;
|
|
194
194
|
}
|
|
195
|
-
|
|
195
|
+
attachDeferredJoinCompletion(transferId, root) {
|
|
196
196
|
const entry = this.admissions.get(transferId);
|
|
197
197
|
if (entry === undefined ||
|
|
198
198
|
entry.state !== 'admitted' ||
|
|
@@ -201,7 +201,7 @@ class ZLinkFormalRemoteActorAdmissionRegistry {
|
|
|
201
201
|
!entry.result.accepted) {
|
|
202
202
|
throw new Error(`Remote actor admission '${transferId}' cannot attach deferred recovery.`);
|
|
203
203
|
}
|
|
204
|
-
entry.result = { ...entry.result,
|
|
204
|
+
entry.result = { ...entry.result, deferredJoinCompletion: root };
|
|
205
205
|
}
|
|
206
206
|
abort(transferId) {
|
|
207
207
|
const entry = this.admissions.get(transferId);
|