@zlink-systems/framework 0.29.1 → 0.30.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/Configuration/Builders.d.ts +1 -2
- package/dist/contracts/Configuration/Configs.d.ts +0 -5
- package/dist/contracts/Configuration/RegistrationBuilders.js +6 -4
- package/dist/contracts/Configuration/RegistrationTypes.d.ts +1 -6
- package/dist/contracts/Configuration/RegistrationValidators.js +4 -4
- package/dist/contracts/Configuration/index.d.ts +1 -1
- package/dist/internal.d.ts +1 -0
- package/dist/internal.js +3 -1
- package/dist/runtime/actors/actor-handoff.d.ts +3 -2
- package/dist/runtime/actors/actor-handoff.js +9 -4
- package/dist/runtime/application-jobs/application-ingress-record-owner.d.ts +3 -1
- package/dist/runtime/application-jobs/application-ingress-record-owner.js +6 -1
- package/dist/runtime/application-jobs/application-job-queue-scope.d.ts +3 -1
- package/dist/runtime/application-jobs/application-job-queue-scope.js +5 -0
- package/dist/runtime/application-jobs/contracts.d.ts +5 -1
- package/dist/runtime/backend/contracts/index.d.ts +10 -19
- package/dist/runtime/backend/mesh-completion-table.d.ts +6 -4
- package/dist/runtime/backend/mesh-completion-table.js +28 -18
- package/dist/runtime/backend/mesh-dispatch-pump.js +21 -25
- package/dist/runtime/backend/node/node-backend-adapter-factory.js +6 -1
- package/dist/runtime/backend/node/node-backend-adapter-support.d.ts +3 -3
- package/dist/runtime/backend/node/node-backend-adapter-support.js +24 -29
- package/dist/runtime/backend/node/node-mesh-backend-adapter.d.ts +1 -9
- package/dist/runtime/backend/node/node-mesh-backend-adapter.js +1 -1
- package/dist/runtime/backend/node/node-raw-binding-port.js +11 -6
- package/dist/runtime/backend/node/node-raw-mesh-backend.d.ts +10 -12
- package/dist/runtime/backend/node/node-raw-mesh-backend.js +64 -98
- package/dist/runtime/backend/node/node-socket-backend-adapter.js +10 -5
- package/dist/runtime/backend/raw-binding-port.d.ts +9 -2
- package/dist/runtime/channels/channel-receive-loops.js +3 -3
- package/dist/runtime/channels/channel-runtime-lifecycle.js +2 -1
- package/dist/runtime/channels/channel-socket-registry.d.ts +10 -3
- package/dist/runtime/channels/channel-socket-registry.js +59 -82
- package/dist/runtime/diagnostics/message-flow.d.ts +1 -0
- package/dist/runtime/diagnostics/message-flow.js +3 -3
- package/dist/runtime/foundation/raw-service-mesh-runtime.d.ts +15 -1
- package/dist/runtime/foundation/raw-service-mesh-runtime.js +193 -64
- package/dist/runtime/foundation/service-liveness-registry.d.ts +20 -8
- package/dist/runtime/foundation/service-liveness-registry.js +57 -44
- package/dist/runtime/foundation/service-mailbox.d.ts +3 -0
- package/dist/runtime/foundation/service-mailbox.js +2 -1
- package/dist/runtime/foundation/service-stateful-runtime.d.ts +7 -6
- package/dist/runtime/foundation/service-stateful-runtime.js +34 -23
- package/dist/runtime/foundation/service-stateful-wire-codec.d.ts +5 -2
- package/dist/runtime/foundation/service-stateful-wire-codec.js +43 -61
- package/dist/runtime/foundation/service-topology-registry.d.ts +5 -3
- package/dist/runtime/foundation/service-topology-registry.js +9 -4
- package/dist/runtime/host/actor-packet-relay.js +7 -7
- package/dist/runtime/host/actor-runtime-options-factory.js +1 -1
- package/dist/runtime/host/application-job-queue.d.ts +11 -4
- package/dist/runtime/host/application-job-queue.js +66 -10
- package/dist/runtime/host/entry-actor-runtime.js +1 -1
- package/dist/runtime/host/index.js +15 -11
- package/dist/runtime/host/instance-activation-authority.d.ts +2 -1
- package/dist/runtime/host/instance-activation-authority.js +89 -25
- package/dist/runtime/host/service-relocation-host-runtime.js +2 -2
- package/dist/runtime/host/spot-address-transport.d.ts +1 -0
- package/dist/runtime/host/spot-address-transport.js +25 -12
- package/dist/runtime/host/spot-runtime-options-factory.js +2 -2
- package/dist/runtime/host/user-spot-creation-coordinator.d.ts +1 -0
- package/dist/runtime/host/user-spot-creation-coordinator.js +1 -0
- package/dist/runtime/locations/domain-store-contract.d.ts +2 -2
- package/dist/runtime/locations/in-memory-authority-store.d.ts +4 -2
- package/dist/runtime/locations/in-memory-authority-store.js +80 -8
- package/dist/runtime/locations/in-memory-location-store.d.ts +2 -2
- package/dist/runtime/locations/in-memory-location-store.js +19 -3
- package/dist/runtime/locations/internal-location-contracts.d.ts +3 -0
- package/dist/runtime/locations/location-store-repository.d.ts +3 -2
- package/dist/runtime/locations/location-store-repository.js +165 -22
- package/dist/runtime/locations/resolvers.d.ts +2 -1
- package/dist/runtime/locations/resolvers.js +10 -1
- package/dist/runtime/messaging/submission-result.d.ts +1 -1
- package/dist/runtime/messaging/submission-result.js +2 -2
- package/dist/runtime/spots/formal-remote-actor-admission-registry.d.ts +2 -0
- package/dist/runtime/spots/index.d.ts +4 -3
- package/dist/runtime/spots/index.js +14 -14
- package/dist/runtime/spots/spot-activation.d.ts +2 -1
- package/dist/runtime/spots/spot-activation.js +4 -4
- package/dist/runtime/spots/spot-actor-admission-coordinator.d.ts +2 -1
- package/dist/runtime/spots/spot-actor-admission-coordinator.js +11 -10
- package/dist/runtime/spots/spot-actor-packet-dispatch.d.ts +4 -1
- package/dist/runtime/spots/spot-actor-packet-dispatch.js +7 -5
- package/dist/runtime/spots/spot-actor-packet-drain.js +2 -0
- package/dist/runtime/spots/spot-actor-packet-relay-dispatch.js +1 -0
- package/dist/runtime/spots/spot-entry-activation.js +3 -1
- package/dist/runtime/spots/spot-node-runtime-manager.d.ts +2 -1
- package/dist/runtime/spots/spot-node-runtime-manager.js +4 -11
- package/dist/runtime/spots/spot-routing-internal.d.ts +6 -0
- package/dist/runtime/spots/spot-runtime-ports.d.ts +2 -1
- package/dist/runtime/streams/stream-session-runtime.js +1 -1
- package/package.json +3 -3
- package/src/contracts/Configuration/Builders.ts +1 -2
- package/src/contracts/Configuration/Configs.ts +0 -6
- package/src/contracts/Configuration/RegistrationBuilders.ts +8 -12
- package/src/contracts/Configuration/RegistrationTypes.ts +1 -6
- package/src/contracts/Configuration/RegistrationValidators.ts +9 -10
- package/src/contracts/Configuration/index.ts +1 -6
- package/src/internal.ts +1 -0
- package/src/runtime/actors/actor-handoff.ts +13 -4
- package/src/runtime/application-jobs/application-ingress-record-owner.ts +12 -2
- package/src/runtime/application-jobs/application-job-queue-scope.ts +6 -1
- package/src/runtime/application-jobs/contracts.ts +14 -1
- package/src/runtime/backend/contracts/index.ts +10 -18
- package/src/runtime/backend/mesh-completion-table.ts +36 -19
- package/src/runtime/backend/mesh-dispatch-pump.ts +19 -22
- package/src/runtime/backend/node/node-backend-adapter-factory.ts +12 -5
- package/src/runtime/backend/node/node-backend-adapter-support.ts +31 -29
- package/src/runtime/backend/node/node-mesh-backend-adapter.ts +3 -10
- package/src/runtime/backend/node/node-raw-binding-port.ts +19 -10
- package/src/runtime/backend/node/node-raw-mesh-backend.ts +81 -111
- package/src/runtime/backend/node/node-socket-backend-adapter.ts +12 -8
- package/src/runtime/backend/raw-binding-port.ts +12 -2
- package/src/runtime/channels/channel-receive-loops.ts +3 -3
- package/src/runtime/channels/channel-runtime-lifecycle.ts +7 -1
- package/src/runtime/channels/channel-socket-registry.ts +84 -130
- package/src/runtime/diagnostics/message-flow.ts +1 -1
- package/src/runtime/foundation/raw-service-mesh-runtime.ts +268 -70
- package/src/runtime/foundation/service-liveness-registry.ts +68 -59
- package/src/runtime/foundation/service-mailbox.ts +7 -1
- package/src/runtime/foundation/service-stateful-runtime.ts +61 -35
- package/src/runtime/foundation/service-stateful-wire-codec.ts +55 -79
- package/src/runtime/foundation/service-topology-registry.ts +13 -7
- package/src/runtime/host/actor-packet-relay.ts +7 -0
- package/src/runtime/host/actor-runtime-options-factory.ts +1 -0
- package/src/runtime/host/application-job-queue.ts +77 -10
- package/src/runtime/host/entry-actor-runtime.ts +1 -0
- package/src/runtime/host/index.ts +24 -5
- package/src/runtime/host/instance-activation-authority.ts +132 -27
- package/src/runtime/host/service-relocation-host-runtime.ts +2 -0
- package/src/runtime/host/spot-address-transport.ts +45 -22
- package/src/runtime/host/spot-runtime-options-factory.ts +2 -0
- package/src/runtime/host/user-spot-creation-coordinator.ts +8 -0
- package/src/runtime/locations/domain-store-contract.ts +6 -2
- package/src/runtime/locations/in-memory-authority-store.ts +113 -9
- package/src/runtime/locations/in-memory-location-store.ts +25 -3
- package/src/runtime/locations/internal-location-contracts.ts +4 -0
- package/src/runtime/locations/location-store-repository.ts +220 -15
- package/src/runtime/locations/resolvers.ts +25 -2
- package/src/runtime/messaging/submission-result.ts +2 -2
- package/src/runtime/spots/formal-remote-actor-admission-registry.ts +2 -0
- package/src/runtime/spots/index.ts +16 -0
- package/src/runtime/spots/spot-activation.ts +5 -0
- package/src/runtime/spots/spot-actor-admission-coordinator.ts +13 -0
- package/src/runtime/spots/spot-actor-packet-dispatch.ts +10 -0
- package/src/runtime/spots/spot-actor-packet-drain.ts +2 -0
- package/src/runtime/spots/spot-actor-packet-relay-dispatch.ts +1 -0
- package/src/runtime/spots/spot-entry-activation.ts +3 -0
- package/src/runtime/spots/spot-node-runtime-manager.ts +7 -12
- package/src/runtime/spots/spot-routing-internal.ts +14 -0
- package/src/runtime/spots/spot-runtime-ports.ts +2 -0
- package/src/runtime/streams/stream-session-runtime.ts +1 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { ZLinkLocationOwnerToken, ZLinkLocationPage, ZLinkLocationWriteIntent, ZLinkLocationWriteResult, ZLinkLocationWriteStatus, ZLinkMeshNodeDescriptor, ZLinkMeshNodeDescriptorKey, ZLinkClientServerServerDescriptor, ZLinkClientServerServerDescriptorKey, ZLinkFanoutPublisherDescriptor, ZLinkFanoutPublisherDescriptorKey, ZLinkOwnerLeaseClaimResult, ZLinkOwnerLeaseReadResult, ZLinkOwnerLeaseReleaseResult, ZLinkOwnerLeaseRenewResult, ZLinkPageRequest } from '../../contracts/Locations/Models';
|
|
2
2
|
import type { ZLinkAggregateAbortResult, ZLinkAggregateCommitResult, ZLinkAggregateFence, ZLinkAggregatePrepareRequest, ZLinkAggregatePrepareResult, ZLinkAuthorityCompareExchangeResult, ZLinkAuthorityKey, ZLinkAuthorityMutation, ZLinkAuthorityReadResult, ZLinkAuthorityScanCursor, ZLinkAuthorityScanResult, ZLinkAuthorityStoreVersion, ZLinkCreationOperationIdentity, ZLinkCreationTerminalReadResult, ZLinkObjectAbortRequest, ZLinkObjectAbortResult, ZLinkObjectCommitRequest, ZLinkObjectCommitResult, ZLinkObjectCreationCompleteRequest, ZLinkObjectCreationCompleteResult, ZLinkObjectReserveResult } from '../../contracts/Locations/Authority';
|
|
3
|
-
import type { ZLinkObjectReserveRequest } from './internal-location-contracts';
|
|
3
|
+
import type { ZLinkObjectReserveRequest, ZLinkEndedOwnerReleaseIntent } from './internal-location-contracts';
|
|
4
4
|
/**
|
|
5
5
|
* Framework-private domain repository. Provider implementations never
|
|
6
6
|
* implement this interface; the framework maps it to the opaque Store SPI.
|
|
@@ -26,7 +26,7 @@ export interface ZLinkDomainLocationStore {
|
|
|
26
26
|
reserve(request: ZLinkObjectReserveRequest, signal?: AbortSignal, deadlineUnixMs?: bigint): Promise<ZLinkObjectReserveResult>;
|
|
27
27
|
commit(request: ZLinkObjectCommitRequest, signal?: AbortSignal, deadlineUnixMs?: bigint): Promise<ZLinkObjectCommitResult>;
|
|
28
28
|
completeCreation(request: ZLinkObjectCreationCompleteRequest, signal?: AbortSignal): Promise<ZLinkObjectCreationCompleteResult>;
|
|
29
|
-
releaseEndedReservation?(key: ZLinkAuthorityKey, expectedStoreVersion: string, signal?: AbortSignal): Promise<boolean>;
|
|
29
|
+
releaseEndedReservation?(key: ZLinkAuthorityKey, expectedStoreVersion: string, signal?: AbortSignal, request?: ZLinkEndedOwnerReleaseIntent): Promise<boolean>;
|
|
30
30
|
abort(request: ZLinkObjectAbortRequest, signal?: AbortSignal, deadlineUnixMs?: bigint): Promise<ZLinkObjectAbortResult>;
|
|
31
31
|
prepareAggregate(request: ZLinkAggregatePrepareRequest, signal?: AbortSignal): Promise<ZLinkAggregatePrepareResult>;
|
|
32
32
|
commitAggregate(fence: ZLinkAggregateFence, signal?: AbortSignal): Promise<ZLinkAggregateCommitResult>;
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import type { ZLinkAggregateAbortResult, ZLinkAggregateCommitResult, ZLinkAggregateFence, ZLinkAggregatePrepareRequest, ZLinkAggregatePrepareResult, ZLinkAuthorityCompareExchangeResult, ZLinkAuthorityKey, ZLinkAuthorityMutation, ZLinkAuthorityReadResult, ZLinkAuthorityScanCursor, ZLinkAuthorityScanResult, ZLinkAuthorityStoreVersion, ZLinkCapacityVector, ZLinkLocationOwnerToken, ZLinkMeshNodeDescriptorKey, ZLinkObjectAbortRequest, ZLinkObjectAbortResult, ZLinkObjectCommitRequest, ZLinkObjectCommitResult, ZLinkObjectCreationCompleteRequest, ZLinkObjectCreationCompleteResult, ZLinkObjectReserveRequest, ZLinkObjectReserveResult, ZLinkCreationOperationIdentity, ZLinkCreationTerminalReadResult } from './internal-location-contracts';
|
|
1
|
+
import type { ZLinkAggregateAbortResult, ZLinkAggregateCommitResult, ZLinkAggregateFence, ZLinkAggregatePrepareRequest, ZLinkAggregatePrepareResult, ZLinkAuthorityCompareExchangeResult, ZLinkAuthorityKey, ZLinkAuthorityMutation, ZLinkAuthorityReadResult, ZLinkAuthorityScanCursor, ZLinkAuthorityScanResult, ZLinkAuthorityStoreVersion, ZLinkCapacityVector, ZLinkLocationOwnerToken, ZLinkMeshNodeDescriptorKey, ZLinkObjectAbortRequest, ZLinkObjectAbortResult, ZLinkObjectCommitRequest, ZLinkObjectCommitResult, ZLinkObjectCreationCompleteRequest, ZLinkObjectCreationCompleteResult, ZLinkEndedOwnerReleaseIntent, ZLinkObjectReserveRequest, ZLinkObjectReserveResult, ZLinkCreationOperationIdentity, ZLinkCreationTerminalReadResult } from './internal-location-contracts';
|
|
2
2
|
export interface ZLinkInMemoryAuthorityValidation {
|
|
3
3
|
isOwnerLive(owner: ZLinkLocationOwnerToken): boolean;
|
|
4
4
|
isTargetLive(descriptor: ZLinkMeshNodeDescriptorKey, lifecycleGeneration: bigint, owner: ZLinkLocationOwnerToken): boolean;
|
|
5
5
|
placementCapacityAvailable?(descriptor: ZLinkMeshNodeDescriptorKey, requested: ZLinkCapacityVector, currentReserved: ZLinkCapacityVector, currentActive: ZLinkCapacityVector): boolean;
|
|
6
6
|
identityClaimed?(authorityKey: string): boolean;
|
|
7
|
+
hasSpotMembers?(spotId: string, objectGeneration: bigint): boolean;
|
|
7
8
|
}
|
|
8
9
|
/**
|
|
9
10
|
* In-memory reference provider for the provider-owned authority state machine.
|
|
@@ -27,7 +28,8 @@ export declare class ZLinkInMemoryAuthorityStore {
|
|
|
27
28
|
compareExchangeAuthority(key: ZLinkAuthorityKey, expectedStoreVersion: ZLinkAuthorityStoreVersion, mutation: ZLinkAuthorityMutation, signal?: AbortSignal): Promise<ZLinkAuthorityCompareExchangeResult>;
|
|
28
29
|
listAuthorities(prefix: string, cursor: ZLinkAuthorityScanCursor | undefined, limit: number, signal?: AbortSignal): Promise<ZLinkAuthorityScanResult>;
|
|
29
30
|
removeAllByOwner(owner: ZLinkLocationOwnerToken, signal?: AbortSignal): Promise<bigint>;
|
|
30
|
-
releaseEndedReservation(key: ZLinkAuthorityKey, expectedStoreVersion: string, signal?: AbortSignal): Promise<boolean>;
|
|
31
|
+
releaseEndedReservation(key: ZLinkAuthorityKey, expectedStoreVersion: string, signal?: AbortSignal, request?: ZLinkEndedOwnerReleaseIntent): Promise<boolean>;
|
|
32
|
+
acceptsUserSpotMembership(spotId: string, objectGeneration: bigint): boolean;
|
|
31
33
|
private tryReleaseEndedReservation;
|
|
32
34
|
reserve(request: ZLinkObjectReserveRequest, signal?: AbortSignal): Promise<ZLinkObjectReserveResult>;
|
|
33
35
|
commit(request: ZLinkObjectCommitRequest, signal?: AbortSignal): Promise<ZLinkObjectCommitResult>;
|
|
@@ -11,6 +11,9 @@ const actor_join_recovery_codec_1 = require("../foundation/actor-join-recovery-c
|
|
|
11
11
|
const authority_key_codec_1 = require("./authority-key-codec");
|
|
12
12
|
const opaque_record_key_1 = require("./opaque-record-key");
|
|
13
13
|
const service_relocation_runtime_1 = require("../foundation/service-relocation-runtime");
|
|
14
|
+
const service_authority_payload_codec_1 = require("../foundation/service-authority-payload-codec");
|
|
15
|
+
const actor_authority_payload_codec_1 = require("../actors/actor-authority-payload-codec");
|
|
16
|
+
const contracts_2 = require("../../contracts");
|
|
14
17
|
const MAX_GENERATION = 0x7fffffffffffffffn;
|
|
15
18
|
const CREATION_TERMINAL_RETENTION_MS = 5 * 60 * 1000;
|
|
16
19
|
const MAX_U64 = stream_wire_1.UINT64_MAX;
|
|
@@ -108,6 +111,18 @@ class ZLinkInMemoryAuthorityStore {
|
|
|
108
111
|
if (!this.isOwnerLive(row.snapshot)) {
|
|
109
112
|
return { kind: 'conflict', current: this.read(keyValue) };
|
|
110
113
|
}
|
|
114
|
+
const actor = row.snapshot.allocation.objectKind === 'actor'
|
|
115
|
+
? (0, actor_authority_payload_codec_1.decodeActorAuthorityPayload)((0, service_relocation_runtime_1.serviceRelocationAuthorityApplicationPayload)(mutation.payload))
|
|
116
|
+
: undefined;
|
|
117
|
+
const previousActor = actor === undefined
|
|
118
|
+
? undefined
|
|
119
|
+
: (0, actor_authority_payload_codec_1.decodeActorAuthorityPayload)((0, service_relocation_runtime_1.serviceRelocationAuthorityApplicationPayload)(row.snapshot.payload));
|
|
120
|
+
if (actor?.currentSpotKind === contracts_2.ZLinkSpotKind.User &&
|
|
121
|
+
(previousActor?.currentSpotKind !== contracts_2.ZLinkSpotKind.User ||
|
|
122
|
+
previousActor.currentSpotId !== actor.currentSpotId ||
|
|
123
|
+
previousActor.currentSpotGeneration !== actor.currentSpotGeneration) &&
|
|
124
|
+
!this.acceptsUserSpotMembership(actor.currentSpotId, actor.currentSpotGeneration))
|
|
125
|
+
return { kind: 'conflict', current: this.read(keyValue) };
|
|
111
126
|
if (mutation.generationTransition === 'reincarnate' &&
|
|
112
127
|
(this.objectGeneration >= MAX_GENERATION || this.ownerGeneration >= MAX_GENERATION)) {
|
|
113
128
|
return { kind: 'generationExhausted' };
|
|
@@ -174,33 +189,67 @@ class ZLinkInMemoryAuthorityStore {
|
|
|
174
189
|
this.scanRevision++;
|
|
175
190
|
return BigInt(removed);
|
|
176
191
|
}
|
|
177
|
-
async releaseEndedReservation(key, expectedStoreVersion, signal) {
|
|
192
|
+
async releaseEndedReservation(key, expectedStoreVersion, signal, request) {
|
|
178
193
|
signal?.throwIfAborted();
|
|
179
|
-
return this.tryReleaseEndedReservation(key, expectedStoreVersion);
|
|
194
|
+
return this.tryReleaseEndedReservation(key, expectedStoreVersion, request);
|
|
195
|
+
}
|
|
196
|
+
acceptsUserSpotMembership(spotId, objectGeneration) {
|
|
197
|
+
const row = this.rows.get((0, authority_key_codec_1.encodeAuthorityKey)('user_spot', spotId).value);
|
|
198
|
+
return (row !== undefined &&
|
|
199
|
+
row.snapshot.allocation.objectKind === 'user_spot' &&
|
|
200
|
+
row.snapshot.allocation.state === 'active' &&
|
|
201
|
+
row.snapshot.objectGeneration === objectGeneration &&
|
|
202
|
+
(0, service_authority_payload_codec_1.decodeServiceReadySpotAuthority)(row.snapshot.payload)?.kind === 'user_spot' &&
|
|
203
|
+
this.isOwnerLive(row.snapshot));
|
|
180
204
|
}
|
|
181
205
|
tryReleaseEndedReservation(key, expectedStoreVersion, request) {
|
|
182
206
|
const current = this.rows.get(key.value);
|
|
183
207
|
if (current === undefined ||
|
|
184
208
|
current.snapshot.storeVersion.value !== expectedStoreVersion ||
|
|
185
209
|
(current.snapshot.allocation.state === 'active'
|
|
186
|
-
? request
|
|
210
|
+
? request === undefined
|
|
187
211
|
: current.creation === undefined))
|
|
188
212
|
return false;
|
|
189
213
|
if (current.snapshot.allocation.state === 'active') {
|
|
214
|
+
let unavailable = false;
|
|
190
215
|
for (const aggregate of this.aggregates.values()) {
|
|
191
216
|
if (aggregate.state === 'prepared' &&
|
|
192
217
|
aggregate.request.participants.some((participant) => participant.authorityKey.value === key.value))
|
|
193
|
-
|
|
218
|
+
unavailable = true;
|
|
194
219
|
}
|
|
195
|
-
|
|
196
|
-
return false;
|
|
220
|
+
unavailable ||= relocationAuthorityCodec.read(current.snapshot.payload) !== undefined;
|
|
197
221
|
if (this.validation.isOwnerLive({
|
|
198
222
|
ownerId: current.snapshot.ownerId,
|
|
199
223
|
leaseGeneration: current.snapshot.ownerLeaseGeneration
|
|
200
224
|
}))
|
|
201
225
|
return false;
|
|
202
|
-
|
|
203
|
-
|
|
226
|
+
const spot = current.snapshot.allocation.objectKind === 'actor'
|
|
227
|
+
? undefined
|
|
228
|
+
: (0, service_authority_payload_codec_1.decodeServiceReadySpotAuthority)(current.snapshot.payload);
|
|
229
|
+
if (current.snapshot.allocation.objectKind !== 'actor') {
|
|
230
|
+
unavailable ||=
|
|
231
|
+
spot === undefined ||
|
|
232
|
+
spot.kind !== request?.key.kind ||
|
|
233
|
+
spot.stableType !== request.intent.stableType ||
|
|
234
|
+
spot.spotId !== request.key.globalId ||
|
|
235
|
+
spot.activationRecovery !== undefined;
|
|
236
|
+
if (spot?.kind === 'user_spot') {
|
|
237
|
+
unavailable ||=
|
|
238
|
+
this.validation.hasSpotMembers?.(spot.spotId, current.snapshot.objectGeneration) ===
|
|
239
|
+
true;
|
|
240
|
+
for (const row of this.rows.values()) {
|
|
241
|
+
if (row.snapshot.allocation.objectKind !== 'actor')
|
|
242
|
+
continue;
|
|
243
|
+
const actor = (0, actor_authority_payload_codec_1.decodeActorAuthorityPayload)((0, service_relocation_runtime_1.serviceRelocationAuthorityApplicationPayload)(row.snapshot.payload));
|
|
244
|
+
unavailable ||=
|
|
245
|
+
actor?.currentSpotKind === contracts_2.ZLinkSpotKind.User &&
|
|
246
|
+
actor.currentSpotId === spot.spotId &&
|
|
247
|
+
actor.currentSpotGeneration === current.snapshot.objectGeneration;
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
if (unavailable || request?.actorRelocationPolicy !== 'disabled')
|
|
252
|
+
throw new contracts_1.ZLinkFrameworkException(contracts_1.ZLinkFrameworkErrorKind.Unavailable, 'Object owner lease is unavailable.');
|
|
204
253
|
}
|
|
205
254
|
else if (this.validation.isTargetLive(current.snapshot.allocation.descriptor, current.snapshot.allocation.descriptorLifecycleGeneration, {
|
|
206
255
|
ownerId: current.snapshot.ownerId,
|
|
@@ -357,6 +406,12 @@ class ZLinkInMemoryAuthorityStore {
|
|
|
357
406
|
if (!this.creationTerminalAvailable(terminalRecord)) {
|
|
358
407
|
return { kind: 'stale' };
|
|
359
408
|
}
|
|
409
|
+
const actor = request.completion.kind === 'created'
|
|
410
|
+
? (0, actor_authority_payload_codec_1.decodeActorAuthorityPayload)((0, service_relocation_runtime_1.serviceRelocationAuthorityApplicationPayload)(request.completion.readyPayload))
|
|
411
|
+
: undefined;
|
|
412
|
+
if (actor?.currentSpotKind === contracts_2.ZLinkSpotKind.User &&
|
|
413
|
+
!this.acceptsUserSpotMembership(actor.currentSpotId, actor.currentSpotGeneration))
|
|
414
|
+
return { kind: 'stale' };
|
|
360
415
|
const nextVersion = this.tryNextStoreVersion();
|
|
361
416
|
if (nextVersion === undefined)
|
|
362
417
|
return { kind: 'generationExhausted' };
|
|
@@ -500,6 +555,23 @@ class ZLinkInMemoryAuthorityStore {
|
|
|
500
555
|
row.snapshot.storeVersion.value !== participant.expectedStoreVersion.value) {
|
|
501
556
|
return { kind: 'stale' };
|
|
502
557
|
}
|
|
558
|
+
const actor = row.snapshot.allocation.objectKind === 'actor'
|
|
559
|
+
? (0, actor_authority_payload_codec_1.decodeActorAuthorityPayload)((0, service_relocation_runtime_1.serviceRelocationAuthorityApplicationPayload)(participant.authorityPayload))
|
|
560
|
+
: undefined;
|
|
561
|
+
if (actor?.currentSpotKind === contracts_2.ZLinkSpotKind.User) {
|
|
562
|
+
const participantSpot = aggregate.request.participants.find((candidate) => candidate.authorityKey.value ===
|
|
563
|
+
(0, authority_key_codec_1.encodeAuthorityKey)('user_spot', actor.currentSpotId).value);
|
|
564
|
+
if (participantSpot === undefined) {
|
|
565
|
+
if (!this.acceptsUserSpotMembership(actor.currentSpotId, actor.currentSpotGeneration))
|
|
566
|
+
return { kind: 'stale' };
|
|
567
|
+
}
|
|
568
|
+
else {
|
|
569
|
+
const spot = this.rows.get(participantSpot.authorityKey.value);
|
|
570
|
+
if (spot?.snapshot.allocation.objectKind !== 'user_spot' ||
|
|
571
|
+
spot.snapshot.objectGeneration !== actor.currentSpotGeneration)
|
|
572
|
+
return { kind: 'stale' };
|
|
573
|
+
}
|
|
574
|
+
}
|
|
503
575
|
if (participant.ownerTransition === 'newOwner') {
|
|
504
576
|
if (!this.validation.isTargetLive(aggregate.request.targetDescriptor, aggregate.request.targetDescriptorLifecycleGeneration, aggregate.request.targetOwner)) {
|
|
505
577
|
return { kind: 'stale' };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { ZLinkActorTransferPrepareRequest, ZLinkActorTransferRecord, ZLinkActorTransferWriteResult } from '../../contracts/Locations/ActorTransfer';
|
|
2
2
|
import type { ZLinkDomainLocationStore } from './domain-store-contract';
|
|
3
|
-
import { ZLinkLocationWriteIntent, ZLinkLocationWriteStatus, type ZLinkActorLocation, type ZLinkActorLocationFilter, type ZLinkActorLocationKey, type ZLinkAggregateAbortResult, type ZLinkAggregateCommitResult, type ZLinkAggregateFence, type ZLinkAggregatePrepareRequest, type ZLinkAggregatePrepareResult, type ZLinkAuthorityCompareExchangeResult, type ZLinkAuthorityKey, type ZLinkAuthorityMutation, type ZLinkAuthorityReadResult, type ZLinkAuthorityScanCursor, type ZLinkAuthorityScanResult, type ZLinkAuthorityStoreVersion, type ZLinkClientServerServerDescriptor, type ZLinkClientServerServerDescriptorKey, type ZLinkCreationOperationIdentity, type ZLinkCreationTerminalReadResult, type ZLinkFanoutPublisherDescriptor, type ZLinkFanoutPublisherDescriptorKey, type ZLinkLocationChangeStampScope, type ZLinkLocationOwnerToken, type ZLinkLocationPage, type ZLinkLocationWriteResult, type ZLinkMeshNodeDescriptor, type ZLinkMeshNodeDescriptorKey, type ZLinkObjectAbortRequest, type ZLinkObjectAbortResult, type ZLinkObjectCommitRequest, type ZLinkObjectCommitResult, type ZLinkObjectCreationCompleteRequest, type ZLinkObjectCreationCompleteResult, type ZLinkObjectReserveRequest, type ZLinkObjectReserveResult, type ZLinkOwnerLeaseClaimResult, type ZLinkOwnerLeaseReadResult, type ZLinkOwnerLeaseReleaseResult, type ZLinkOwnerLeaseRenewResult, type ZLinkPageRequest, type ZLinkPeerLocation, type ZLinkPeerLocationFilter, type ZLinkPeerLocationKey, type ZLinkRouteLocation, type ZLinkRouteLocationFilter, type ZLinkRouteLocationKey, type ZLinkSpotLocation, type ZLinkSpotLocationFilter, type ZLinkSpotLocationKey } from './internal-location-contracts';
|
|
3
|
+
import { ZLinkLocationWriteIntent, ZLinkLocationWriteStatus, type ZLinkActorLocation, type ZLinkActorLocationFilter, type ZLinkActorLocationKey, type ZLinkAggregateAbortResult, type ZLinkAggregateCommitResult, type ZLinkAggregateFence, type ZLinkAggregatePrepareRequest, type ZLinkAggregatePrepareResult, type ZLinkAuthorityCompareExchangeResult, type ZLinkAuthorityKey, type ZLinkAuthorityMutation, type ZLinkAuthorityReadResult, type ZLinkAuthorityScanCursor, type ZLinkAuthorityScanResult, type ZLinkAuthorityStoreVersion, type ZLinkClientServerServerDescriptor, type ZLinkClientServerServerDescriptorKey, type ZLinkCreationOperationIdentity, type ZLinkCreationTerminalReadResult, type ZLinkFanoutPublisherDescriptor, type ZLinkFanoutPublisherDescriptorKey, type ZLinkLocationChangeStampScope, type ZLinkLocationOwnerToken, type ZLinkLocationPage, type ZLinkLocationWriteResult, type ZLinkMeshNodeDescriptor, type ZLinkMeshNodeDescriptorKey, type ZLinkObjectAbortRequest, type ZLinkObjectAbortResult, type ZLinkObjectCommitRequest, type ZLinkObjectCommitResult, type ZLinkObjectCreationCompleteRequest, type ZLinkObjectCreationCompleteResult, type ZLinkEndedOwnerReleaseIntent, type ZLinkObjectReserveRequest, type ZLinkObjectReserveResult, type ZLinkOwnerLeaseClaimResult, type ZLinkOwnerLeaseReadResult, type ZLinkOwnerLeaseReleaseResult, type ZLinkOwnerLeaseRenewResult, type ZLinkPageRequest, type ZLinkPeerLocation, type ZLinkPeerLocationFilter, type ZLinkPeerLocationKey, type ZLinkRouteLocation, type ZLinkRouteLocationFilter, type ZLinkRouteLocationKey, type ZLinkSpotLocation, type ZLinkSpotLocationFilter, type ZLinkSpotLocationKey } from './internal-location-contracts';
|
|
4
4
|
import type { ZLinkFanoutLocationStore } from './internal-store-contracts';
|
|
5
5
|
export declare class ZLinkInMemoryLocationStore implements ZLinkDomainLocationStore, ZLinkFanoutLocationStore {
|
|
6
6
|
private readonly now;
|
|
@@ -25,7 +25,7 @@ export declare class ZLinkInMemoryLocationStore implements ZLinkDomainLocationSt
|
|
|
25
25
|
commit(request: ZLinkObjectCommitRequest, signal?: AbortSignal): Promise<ZLinkObjectCommitResult>;
|
|
26
26
|
completeCreation(request: ZLinkObjectCreationCompleteRequest, signal?: AbortSignal): Promise<ZLinkObjectCreationCompleteResult>;
|
|
27
27
|
readCreationTerminal(operation: ZLinkCreationOperationIdentity, signal?: AbortSignal): Promise<ZLinkCreationTerminalReadResult>;
|
|
28
|
-
releaseEndedReservation(key: ZLinkAuthorityKey, expectedStoreVersion: string, signal?: AbortSignal): Promise<boolean>;
|
|
28
|
+
releaseEndedReservation(key: ZLinkAuthorityKey, expectedStoreVersion: string, signal?: AbortSignal, request?: ZLinkEndedOwnerReleaseIntent): Promise<boolean>;
|
|
29
29
|
abort(request: ZLinkObjectAbortRequest, signal?: AbortSignal): Promise<ZLinkObjectAbortResult>;
|
|
30
30
|
prepareAggregate(request: ZLinkAggregatePrepareRequest, signal?: AbortSignal): Promise<ZLinkAggregatePrepareResult>;
|
|
31
31
|
commitAggregate(fence: ZLinkAggregateFence, signal?: AbortSignal): Promise<ZLinkAggregateCommitResult>;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.ZLinkInMemoryLocationStore = void 0;
|
|
4
|
+
const contracts_1 = require("../../contracts");
|
|
4
5
|
const CoreTypes_1 = require("../../contracts/Common/CoreTypes");
|
|
5
6
|
const RegistrationBuilderPolicy_1 = require("../../contracts/Configuration/RegistrationBuilderPolicy");
|
|
6
7
|
const location_store_integration_1 = require("../../location-store-integration");
|
|
@@ -62,7 +63,16 @@ class ZLinkInMemoryLocationStore {
|
|
|
62
63
|
spotType.count <=
|
|
63
64
|
typeCapacity.limit))));
|
|
64
65
|
},
|
|
65
|
-
identityClaimed: (authorityKey) => this.entrySpotClaims.has(authorityKey)
|
|
66
|
+
identityClaimed: (authorityKey) => this.entrySpotClaims.has(authorityKey),
|
|
67
|
+
hasSpotMembers: (spotId, objectGeneration) => {
|
|
68
|
+
for (const actor of this.actors.rows.values()) {
|
|
69
|
+
if (actor.spotKind === contracts_1.ZLinkSpotKind.User &&
|
|
70
|
+
String(actor.spotId) === spotId &&
|
|
71
|
+
actor.spotGeneration === objectGeneration)
|
|
72
|
+
return true;
|
|
73
|
+
}
|
|
74
|
+
return false;
|
|
75
|
+
}
|
|
66
76
|
}, now);
|
|
67
77
|
}
|
|
68
78
|
async readAuthority(key, signal) {
|
|
@@ -86,8 +96,8 @@ class ZLinkInMemoryLocationStore {
|
|
|
86
96
|
async readCreationTerminal(operation, signal) {
|
|
87
97
|
return this.authority.readCreationTerminal(operation, signal);
|
|
88
98
|
}
|
|
89
|
-
async releaseEndedReservation(key, expectedStoreVersion, signal) {
|
|
90
|
-
return this.authority.releaseEndedReservation(key, expectedStoreVersion, signal);
|
|
99
|
+
async releaseEndedReservation(key, expectedStoreVersion, signal, request) {
|
|
100
|
+
return this.authority.releaseEndedReservation(key, expectedStoreVersion, signal, request);
|
|
91
101
|
}
|
|
92
102
|
async abort(request, signal) {
|
|
93
103
|
return this.authority.abort(request, signal);
|
|
@@ -389,6 +399,12 @@ class ZLinkInMemoryLocationStore {
|
|
|
389
399
|
});
|
|
390
400
|
const updatedAt = this.now();
|
|
391
401
|
const current = this.actors.rows.get(key);
|
|
402
|
+
if (actor.spotKind === contracts_1.ZLinkSpotKind.User &&
|
|
403
|
+
(current?.spotKind !== contracts_1.ZLinkSpotKind.User ||
|
|
404
|
+
String(current.spotId) !== String(actor.spotId) ||
|
|
405
|
+
current.spotGeneration !== actor.spotGeneration) &&
|
|
406
|
+
!this.authority.acceptsUserSpotMembership(String(actor.spotId), actor.spotGeneration))
|
|
407
|
+
return rejectedConflict();
|
|
392
408
|
if (intent === internal_location_contracts_1.ZLinkLocationWriteIntent.NewClaim &&
|
|
393
409
|
current !== undefined &&
|
|
394
410
|
this.liveOwnerLease(current.ownerId, updatedAt) !== undefined) {
|
|
@@ -4,6 +4,9 @@ import type { ZLinkRelocationConfiguration } from '../../contracts/Configuration
|
|
|
4
4
|
export interface ZLinkObjectReserveRequest extends ReserveRequest {
|
|
5
5
|
readonly actorRelocationPolicy?: ZLinkRelocationConfiguration<unknown>['kind'];
|
|
6
6
|
}
|
|
7
|
+
export type ZLinkEndedOwnerReleaseIntent = Pick<ZLinkObjectReserveRequest, 'key' | 'actorRelocationPolicy'> & {
|
|
8
|
+
readonly intent: Pick<ZLinkObjectReserveRequest['intent'], 'stableType'>;
|
|
9
|
+
};
|
|
7
10
|
export type * from '../../contracts/Locations/Authority';
|
|
8
11
|
export type { ZLinkActorLocation, ZLinkPeerLocation, ZLinkRouteLocation, ZLinkSpotLocation } from '../../contracts/Locations/Rows';
|
|
9
12
|
export type { ZLinkActorLocationFilter, ZLinkActorLocationKey, ZLinkLocationKey, ZLinkPeerLocationFilter, ZLinkPeerLocationKey, ZLinkRouteLocationFilter, ZLinkRouteLocationKey, ZLinkSpotLocationFilter, ZLinkSpotLocationKey } from '../../contracts/Locations/Keys';
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type ZLinkClientServerServerDescriptor, type ZLinkClientServerServerDescriptorKey, type ZLinkFanoutPublisherDescriptor, type ZLinkFanoutPublisherDescriptorKey, type ZLinkLocationPage, type ZLinkLocationStore, type ZLinkMeshNodeDescriptor, type ZLinkMeshNodeDescriptorKey, type ZLinkPageRequest } from '../../contracts';
|
|
2
2
|
import { ZLinkInMemoryLocationStore } from './in-memory-location-store';
|
|
3
|
-
import { type ZLinkActorLocation, type ZLinkActorLocationFilter, type ZLinkActorLocationKey, type ZLinkAggregateAbortResult, type ZLinkAggregateCommitResult, type ZLinkAggregateFence, type ZLinkAggregatePrepareRequest, type ZLinkAggregatePrepareResult, type ZLinkAuthorityCompareExchangeResult, type ZLinkAuthorityKey, type ZLinkAuthorityMutation, type ZLinkAuthorityReadResult, type ZLinkAuthorityScanCursor, type ZLinkAuthorityScanResult, type ZLinkAuthorityStoreVersion, type ZLinkCreationOperationIdentity, type ZLinkCreationTerminalReadResult, type ZLinkLocationOwnerToken, type ZLinkLocationWriteResult, type ZLinkLocationWriteStatus, type ZLinkObjectAbortRequest, type ZLinkObjectAbortResult, type ZLinkObjectCommitRequest, type ZLinkObjectCommitResult, type ZLinkObjectCreationCompleteRequest, type ZLinkObjectCreationCompleteResult, type ZLinkObjectReserveRequest, type ZLinkObjectReserveResult, type ZLinkOwnerLeaseClaimResult, type ZLinkOwnerLeaseReadResult, type ZLinkOwnerLeaseReleaseResult, type ZLinkOwnerLeaseRenewResult, type ZLinkRouteLocation, type ZLinkRouteLocationFilter, type ZLinkRouteLocationKey, type ZLinkSpotLocation, type ZLinkSpotLocationFilter, type ZLinkSpotLocationKey, ZLinkLocationWriteIntent } from './internal-location-contracts';
|
|
3
|
+
import { type ZLinkActorLocation, type ZLinkActorLocationFilter, type ZLinkActorLocationKey, type ZLinkAggregateAbortResult, type ZLinkAggregateCommitResult, type ZLinkAggregateFence, type ZLinkAggregatePrepareRequest, type ZLinkAggregatePrepareResult, type ZLinkAuthorityCompareExchangeResult, type ZLinkAuthorityKey, type ZLinkAuthorityMutation, type ZLinkAuthorityReadResult, type ZLinkAuthorityScanCursor, type ZLinkAuthorityScanResult, type ZLinkAuthorityStoreVersion, type ZLinkCreationOperationIdentity, type ZLinkCreationTerminalReadResult, type ZLinkLocationOwnerToken, type ZLinkLocationWriteResult, type ZLinkLocationWriteStatus, type ZLinkObjectAbortRequest, type ZLinkObjectAbortResult, type ZLinkObjectCommitRequest, type ZLinkObjectCommitResult, type ZLinkObjectCreationCompleteRequest, type ZLinkObjectCreationCompleteResult, type ZLinkEndedOwnerReleaseIntent, type ZLinkObjectReserveRequest, type ZLinkObjectReserveResult, type ZLinkOwnerLeaseClaimResult, type ZLinkOwnerLeaseReadResult, type ZLinkOwnerLeaseReleaseResult, type ZLinkOwnerLeaseRenewResult, type ZLinkRouteLocation, type ZLinkRouteLocationFilter, type ZLinkRouteLocationKey, type ZLinkSpotLocation, type ZLinkSpotLocationFilter, type ZLinkSpotLocationKey, ZLinkLocationWriteIntent } from './internal-location-contracts';
|
|
4
4
|
/**
|
|
5
5
|
* Maps framework domain records to the minimal provider SPI.
|
|
6
6
|
*
|
|
@@ -20,7 +20,7 @@ export declare class ZLinkLocationStoreRepository extends ZLinkInMemoryLocationS
|
|
|
20
20
|
commitAggregate(fence: ZLinkAggregateFence, signal?: AbortSignal): Promise<ZLinkAggregateCommitResult>;
|
|
21
21
|
private commitAggregateCore;
|
|
22
22
|
abortAggregate(fence: ZLinkAggregateFence, signal?: AbortSignal): Promise<ZLinkAggregateAbortResult>;
|
|
23
|
-
releaseEndedReservation(key: ZLinkAuthorityKey, expectedStoreVersion: string, signal?: AbortSignal): Promise<boolean>;
|
|
23
|
+
releaseEndedReservation(key: ZLinkAuthorityKey, expectedStoreVersion: string, signal?: AbortSignal, request?: ZLinkEndedOwnerReleaseIntent): Promise<boolean>;
|
|
24
24
|
private tryReleaseEndedReservation;
|
|
25
25
|
reserve(request: ZLinkObjectReserveRequest, signal?: AbortSignal, deadlineUnixMs?: bigint): Promise<ZLinkObjectReserveResult>;
|
|
26
26
|
commit(request: ZLinkObjectCommitRequest, signal?: AbortSignal, deadlineUnixMs?: bigint): Promise<ZLinkObjectCommitResult>;
|
|
@@ -59,6 +59,7 @@ export declare class ZLinkLocationStoreRepository extends ZLinkInMemoryLocationS
|
|
|
59
59
|
private writeDescriptorWithReconciliation;
|
|
60
60
|
private removeDescriptor;
|
|
61
61
|
private listDescriptors;
|
|
62
|
+
private userSpotMembershipConditions;
|
|
62
63
|
private updateOwnedLocation;
|
|
63
64
|
private removeOwnedLocation;
|
|
64
65
|
private readOwnedLocation;
|
|
@@ -2,10 +2,13 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.ZLinkLocationStoreRepository = void 0;
|
|
4
4
|
const service_relocation_runtime_1 = require("../foundation/service-relocation-runtime");
|
|
5
|
+
const service_authority_payload_codec_1 = require("../foundation/service-authority-payload-codec");
|
|
6
|
+
const actor_authority_payload_codec_1 = require("../actors/actor-authority-payload-codec");
|
|
7
|
+
const contracts_1 = require("../../contracts");
|
|
5
8
|
const stream_wire_1 = require("@zlink-systems/stream-wire");
|
|
6
9
|
const node_crypto_1 = require("node:crypto");
|
|
7
10
|
const Options_1 = require("../../contracts/Locations/Options");
|
|
8
|
-
const
|
|
11
|
+
const contracts_2 = require("../../contracts");
|
|
9
12
|
const CoreTypes_1 = require("../../contracts/Common/CoreTypes");
|
|
10
13
|
const InternalDefaults_1 = require("../../contracts/Configuration/InternalDefaults");
|
|
11
14
|
const RegistrationBuilderPolicy_1 = require("../../contracts/Configuration/RegistrationBuilderPolicy");
|
|
@@ -215,9 +218,27 @@ class ZLinkLocationStoreRepository extends in_memory_location_store_1.ZLinkInMem
|
|
|
215
218
|
payload: Buffer.from(mutation.payload)
|
|
216
219
|
}
|
|
217
220
|
};
|
|
221
|
+
const actor = mutation.kind !== 'delete' && record.snapshot.allocation.objectKind === 'actor'
|
|
222
|
+
? (0, actor_authority_payload_codec_1.decodeActorAuthorityPayload)((0, service_relocation_runtime_1.serviceRelocationAuthorityApplicationPayload)(mutation.payload))
|
|
223
|
+
: undefined;
|
|
224
|
+
const previousActor = actor === undefined
|
|
225
|
+
? undefined
|
|
226
|
+
: (0, actor_authority_payload_codec_1.decodeActorAuthorityPayload)((0, service_relocation_runtime_1.serviceRelocationAuthorityApplicationPayload)(record.snapshot.payload));
|
|
227
|
+
const membershipConditions = actor?.currentSpotKind === contracts_1.ZLinkSpotKind.User &&
|
|
228
|
+
(previousActor?.currentSpotKind !== contracts_1.ZLinkSpotKind.User ||
|
|
229
|
+
previousActor.currentSpotId !== actor.currentSpotId ||
|
|
230
|
+
previousActor.currentSpotGeneration !== actor.currentSpotGeneration)
|
|
231
|
+
? await this.userSpotMembershipConditions(actor.currentSpotId, actor.currentSpotGeneration, signal, {
|
|
232
|
+
ownerId: record.snapshot.ownerId,
|
|
233
|
+
leaseGeneration: record.snapshot.ownerLeaseGeneration
|
|
234
|
+
})
|
|
235
|
+
: [];
|
|
236
|
+
if (membershipConditions === undefined)
|
|
237
|
+
return { kind: 'conflict', current: snapshot };
|
|
218
238
|
const result = await this.provider.write({
|
|
219
239
|
conditions: [
|
|
220
240
|
{ kind: 'version', key: rowKey, expected: current.value.version },
|
|
241
|
+
...membershipConditions,
|
|
221
242
|
...(mutation.kind === 'restore'
|
|
222
243
|
? []
|
|
223
244
|
: [
|
|
@@ -654,7 +675,7 @@ class ZLinkLocationStoreRepository extends in_memory_location_store_1.ZLinkInMem
|
|
|
654
675
|
sha256Hex(membership) !== entry.membershipMutationSha256) {
|
|
655
676
|
throw new Error('Aggregate participant staging checksum does not match inventory.');
|
|
656
677
|
}
|
|
657
|
-
authorityRows.push({ key: rowKeyForParticipant, current, record, entry });
|
|
678
|
+
authorityRows.push({ key: rowKeyForParticipant, current, record, entry, payload });
|
|
658
679
|
}
|
|
659
680
|
const targetDescriptorKey = meshKey(aggregate.targetDescriptor.meshName, aggregate.targetDescriptor.rid);
|
|
660
681
|
const targetLeaseKey = ownerKey(aggregate.targetOwner.ownerId);
|
|
@@ -717,11 +738,34 @@ class ZLinkLocationStoreRepository extends in_memory_location_store_1.ZLinkInMem
|
|
|
717
738
|
bytes: encodeJson(capacity)
|
|
718
739
|
});
|
|
719
740
|
}
|
|
741
|
+
const membershipConditions = [];
|
|
742
|
+
for (const row of authorityRows) {
|
|
743
|
+
if (row.record.snapshot.allocation.objectKind !== 'actor')
|
|
744
|
+
continue;
|
|
745
|
+
const actor = (0, actor_authority_payload_codec_1.decodeActorAuthorityPayload)((0, service_relocation_runtime_1.serviceRelocationAuthorityApplicationPayload)(row.payload));
|
|
746
|
+
if (actor?.currentSpotKind !== contracts_1.ZLinkSpotKind.User)
|
|
747
|
+
continue;
|
|
748
|
+
const spotKey = (0, authority_key_codec_1.encodeAuthorityKey)('user_spot', actor.currentSpotId);
|
|
749
|
+
const participantSpot = authorityRows.find((candidate) => candidate.entry.authorityKey === spotKey.value);
|
|
750
|
+
if (participantSpot !== undefined) {
|
|
751
|
+
if (participantSpot.record.snapshot.allocation.objectKind !== 'user_spot' ||
|
|
752
|
+
participantSpot.record.snapshot.objectGeneration !== actor.currentSpotGeneration)
|
|
753
|
+
return { kind: 'stale' };
|
|
754
|
+
continue;
|
|
755
|
+
}
|
|
756
|
+
if (membershipConditions.some((condition) => condition.key.value === authorityKey(spotKey.value).value))
|
|
757
|
+
continue;
|
|
758
|
+
const conditions = await this.userSpotMembershipConditions(actor.currentSpotId, actor.currentSpotGeneration, signal, aggregate.targetOwner);
|
|
759
|
+
if (conditions === undefined)
|
|
760
|
+
return { kind: 'stale' };
|
|
761
|
+
membershipConditions.push(...conditions.filter((condition) => !membershipConditions.some((existing) => existing.key.value === condition.key.value)));
|
|
762
|
+
}
|
|
720
763
|
const published = await this.provider.write({
|
|
721
764
|
conditions: [
|
|
722
765
|
{ kind: 'version', key: rowKey, expected: aggregateRead.value.version },
|
|
723
766
|
versionCondition(targetDescriptorKey, descriptorRead),
|
|
724
767
|
leaseValueCondition(targetLeaseKey, aggregate.targetOwner),
|
|
768
|
+
...membershipConditions,
|
|
725
769
|
...[...capacityReads.entries()].map(([value, read]) => ({
|
|
726
770
|
kind: 'version',
|
|
727
771
|
key: capacityKeys.get(value),
|
|
@@ -814,8 +858,9 @@ class ZLinkLocationStoreRepository extends in_memory_location_store_1.ZLinkInMem
|
|
|
814
858
|
return { kind: 'aborted' };
|
|
815
859
|
}
|
|
816
860
|
}
|
|
817
|
-
async releaseEndedReservation(key, expectedStoreVersion, signal) {
|
|
818
|
-
return ((await this.tryReleaseEndedReservation(key, expectedStoreVersion, signal)) ===
|
|
861
|
+
async releaseEndedReservation(key, expectedStoreVersion, signal, request) {
|
|
862
|
+
return ((await this.tryReleaseEndedReservation(key, expectedStoreVersion, signal, request)) ===
|
|
863
|
+
'reclaimed');
|
|
819
864
|
}
|
|
820
865
|
async tryReleaseEndedReservation(key, expectedStoreVersion, signal, request) {
|
|
821
866
|
const rowKey = authorityKey(key.value);
|
|
@@ -824,11 +869,9 @@ class ZLinkLocationStoreRepository extends in_memory_location_store_1.ZLinkInMem
|
|
|
824
869
|
return 'conflict';
|
|
825
870
|
const record = decodeAuthorityRecord(current.value.bytes);
|
|
826
871
|
const snapshot = record.snapshot;
|
|
827
|
-
if (
|
|
828
|
-
? request
|
|
829
|
-
: snapshot.pendingCreation === undefined)
|
|
830
|
-
record.aggregate !== undefined ||
|
|
831
|
-
hasRelocationAuthority(snapshot.payload))
|
|
872
|
+
if (snapshot.allocation.state === 'active'
|
|
873
|
+
? request === undefined
|
|
874
|
+
: snapshot.pendingCreation === undefined)
|
|
832
875
|
return 'notReclaimable';
|
|
833
876
|
const leaseKey = ownerKey(snapshot.ownerId);
|
|
834
877
|
const descriptorKey = meshKey(snapshot.allocation.descriptor.meshName, snapshot.allocation.descriptor.rid);
|
|
@@ -844,13 +887,62 @@ class ZLinkLocationStoreRepository extends in_memory_location_store_1.ZLinkInMem
|
|
|
844
887
|
if (snapshot.allocation.state === 'active') {
|
|
845
888
|
if (ownerLive)
|
|
846
889
|
return 'notReclaimable';
|
|
847
|
-
|
|
848
|
-
|
|
890
|
+
let unavailable = record.aggregate !== undefined || hasRelocationAuthority(snapshot.payload);
|
|
891
|
+
if (snapshot.allocation.objectKind !== 'actor') {
|
|
892
|
+
const spot = (0, service_authority_payload_codec_1.decodeServiceReadySpotAuthority)(snapshot.payload);
|
|
893
|
+
unavailable ||=
|
|
894
|
+
spot === undefined ||
|
|
895
|
+
spot.kind !== request?.key.kind ||
|
|
896
|
+
spot.stableType !== request.intent.stableType ||
|
|
897
|
+
spot.spotId !== request.key.globalId ||
|
|
898
|
+
spot.activationRecovery !== undefined;
|
|
899
|
+
if (spot?.kind === 'user_spot') {
|
|
900
|
+
// The snapshot starts only after the old owner's lease was found invalid.
|
|
901
|
+
for (const prefix of [`${PREFIX}actor:`, `${AUTHORITY_PREIMAGE_PREFIX}actor\0`]) {
|
|
902
|
+
membershipSnapshot: for (;;) {
|
|
903
|
+
let snapshotHasMember = false;
|
|
904
|
+
let cursor;
|
|
905
|
+
do {
|
|
906
|
+
const page = await this.provider.scan({ prefix, cursor, limit: Stores_1.ZLINK_PROVIDER_MAX_PAGE_SIZE }, signal);
|
|
907
|
+
if (page.kind === 'expired')
|
|
908
|
+
continue membershipSnapshot;
|
|
909
|
+
for (const item of page.value.items) {
|
|
910
|
+
if (prefix === `${PREFIX}actor:`) {
|
|
911
|
+
const actor = normalizeActor(decodeJson(item.value.bytes).descriptor);
|
|
912
|
+
snapshotHasMember ||=
|
|
913
|
+
actor.spotKind === contracts_1.ZLinkSpotKind.User &&
|
|
914
|
+
String(actor.spotId) === spot.spotId &&
|
|
915
|
+
actor.spotGeneration === snapshot.objectGeneration;
|
|
916
|
+
}
|
|
917
|
+
else {
|
|
918
|
+
const authority = decodeAuthorityRecord(item.value.bytes).snapshot;
|
|
919
|
+
if (authority.allocation.objectKind !== 'actor')
|
|
920
|
+
continue;
|
|
921
|
+
const actor = (0, actor_authority_payload_codec_1.decodeActorAuthorityPayload)((0, service_relocation_runtime_1.serviceRelocationAuthorityApplicationPayload)(authority.payload));
|
|
922
|
+
snapshotHasMember ||=
|
|
923
|
+
actor?.currentSpotKind === contracts_1.ZLinkSpotKind.User &&
|
|
924
|
+
actor.currentSpotId === spot.spotId &&
|
|
925
|
+
actor.currentSpotGeneration === snapshot.objectGeneration;
|
|
926
|
+
}
|
|
927
|
+
}
|
|
928
|
+
cursor = page.value.nextCursor;
|
|
929
|
+
} while (cursor !== undefined);
|
|
930
|
+
unavailable ||= snapshotHasMember;
|
|
931
|
+
break;
|
|
932
|
+
}
|
|
933
|
+
}
|
|
934
|
+
}
|
|
935
|
+
}
|
|
936
|
+
if (unavailable || request?.actorRelocationPolicy !== 'disabled')
|
|
937
|
+
throw new contracts_2.ZLinkFrameworkException(contracts_2.ZLinkFrameworkErrorKind.Unavailable, 'Object owner lease is unavailable.');
|
|
849
938
|
}
|
|
850
939
|
else if (ownerLive &&
|
|
851
940
|
descriptor.kind === 'found' &&
|
|
852
941
|
reviveMeshDescriptor(decodeCanonicalDescriptorRecord(descriptor.value.bytes).descriptor).lifecycleGeneration === snapshot.allocation.descriptorLifecycleGeneration)
|
|
853
942
|
return 'notReclaimable';
|
|
943
|
+
if (snapshot.allocation.state !== 'active' &&
|
|
944
|
+
(record.aggregate !== undefined || hasRelocationAuthority(snapshot.payload)))
|
|
945
|
+
return 'notReclaimable';
|
|
854
946
|
const mutations = [
|
|
855
947
|
{ kind: 'delete', key: rowKey }
|
|
856
948
|
];
|
|
@@ -871,8 +963,8 @@ class ZLinkLocationStoreRepository extends in_memory_location_store_1.ZLinkInMem
|
|
|
871
963
|
});
|
|
872
964
|
}
|
|
873
965
|
catch (error) {
|
|
874
|
-
if (!(error instanceof
|
|
875
|
-
error.kind !==
|
|
966
|
+
if (!(error instanceof contracts_2.ZLinkFrameworkException) ||
|
|
967
|
+
error.kind !== contracts_2.ZLinkFrameworkErrorKind.DataLost)
|
|
876
968
|
throw error;
|
|
877
969
|
const observed = await this.provider.read(rowKey, signal);
|
|
878
970
|
if (observed.kind === 'missing' ||
|
|
@@ -927,7 +1019,7 @@ class ZLinkLocationStoreRepository extends in_memory_location_store_1.ZLinkInMem
|
|
|
927
1019
|
this.provider.read(leaseKey, signal)
|
|
928
1020
|
]);
|
|
929
1021
|
const descriptor = liveTargetDescriptor(descriptorRead, leaseRead, request.target);
|
|
930
|
-
if (descriptor === undefined || descriptor.state !==
|
|
1022
|
+
if (descriptor === undefined || descriptor.state !== contracts_2.ZLinkFrameworkRuntimeState.Serving) {
|
|
931
1023
|
return { kind: 'conflict', current: { kind: 'missing', storeNow: current.storeNow } };
|
|
932
1024
|
}
|
|
933
1025
|
const [capacityRead, objectGenerationRead, authorityOwnerGenerationRead] = await Promise.all([
|
|
@@ -1204,6 +1296,14 @@ class ZLinkLocationStoreRepository extends in_memory_location_store_1.ZLinkInMem
|
|
|
1204
1296
|
if (retentionMs <= 0) {
|
|
1205
1297
|
throw new RangeError('Creation terminal expiry must be the live operation deadline plus five minutes.');
|
|
1206
1298
|
}
|
|
1299
|
+
const actor = request.completion.kind === 'created'
|
|
1300
|
+
? (0, actor_authority_payload_codec_1.decodeActorAuthorityPayload)((0, service_relocation_runtime_1.serviceRelocationAuthorityApplicationPayload)(request.completion.readyPayload))
|
|
1301
|
+
: undefined;
|
|
1302
|
+
const membershipConditions = actor?.currentSpotKind === contracts_1.ZLinkSpotKind.User
|
|
1303
|
+
? await this.userSpotMembershipConditions(actor.currentSpotId, actor.currentSpotGeneration, signal, request.target.owner)
|
|
1304
|
+
: [];
|
|
1305
|
+
if (membershipConditions === undefined)
|
|
1306
|
+
return { kind: 'stale' };
|
|
1207
1307
|
const mutations = request.completion.kind === 'created'
|
|
1208
1308
|
? [
|
|
1209
1309
|
{
|
|
@@ -1243,6 +1343,7 @@ class ZLinkLocationStoreRepository extends in_memory_location_store_1.ZLinkInMem
|
|
|
1243
1343
|
conditions: [
|
|
1244
1344
|
{ kind: 'version', key: rowKey, expected: current.value.version },
|
|
1245
1345
|
{ kind: 'missing', key: terminalRowKey },
|
|
1346
|
+
...membershipConditions,
|
|
1246
1347
|
versionCondition(descriptorKey, descriptorRead),
|
|
1247
1348
|
leaseValueCondition(leaseKey, request.target.owner),
|
|
1248
1349
|
conditionFor(capacityRowKey, capacityRead)
|
|
@@ -1505,7 +1606,7 @@ class ZLinkLocationStoreRepository extends in_memory_location_store_1.ZLinkInMem
|
|
|
1505
1606
|
return this.listOwnedLocations(`${PREFIX}spot:`, page, normalizeSpot, (value) => matchesSpot(value, filter), signal);
|
|
1506
1607
|
}
|
|
1507
1608
|
async updateActor(location, intent, signal) {
|
|
1508
|
-
return this.updateOwnedLocation(actorKey(location.meshName, location.actorId), normalizeActor(location), intent, signal);
|
|
1609
|
+
return this.updateOwnedLocation(actorKey(location.meshName, location.actorId), normalizeActor(location), intent, signal, location);
|
|
1509
1610
|
}
|
|
1510
1611
|
async removeActor(key, owner, signal) {
|
|
1511
1612
|
return this.removeOwnedLocation(actorKey(key.meshName, key.actorId), owner, signal);
|
|
@@ -1874,7 +1975,37 @@ class ZLinkLocationStoreRepository extends in_memory_location_store_1.ZLinkInMem
|
|
|
1874
1975
|
continuationToken: result.value.nextCursor?.value
|
|
1875
1976
|
};
|
|
1876
1977
|
}
|
|
1877
|
-
async
|
|
1978
|
+
async userSpotMembershipConditions(spotId, objectGeneration, signal, conditionedOwner) {
|
|
1979
|
+
const key = authorityKey((0, authority_key_codec_1.encodeAuthorityKey)('user_spot', spotId).value);
|
|
1980
|
+
const read = await this.provider.read(key, signal);
|
|
1981
|
+
if (read.kind === 'missing')
|
|
1982
|
+
return undefined;
|
|
1983
|
+
const record = decodeAuthorityRecord(read.value.bytes);
|
|
1984
|
+
const snapshot = record.snapshot;
|
|
1985
|
+
if (record.aggregate !== undefined ||
|
|
1986
|
+
snapshot.allocation.objectKind !== 'user_spot' ||
|
|
1987
|
+
snapshot.allocation.state !== 'active' ||
|
|
1988
|
+
snapshot.objectGeneration !== objectGeneration ||
|
|
1989
|
+
(0, service_authority_payload_codec_1.decodeServiceReadySpotAuthority)(snapshot.payload)?.kind !== 'user_spot')
|
|
1990
|
+
return undefined;
|
|
1991
|
+
const leaseKey = ownerKey(snapshot.ownerId);
|
|
1992
|
+
const lease = await this.provider.read(leaseKey, signal);
|
|
1993
|
+
if (!sameLiveOwner(lease, snapshot))
|
|
1994
|
+
return undefined;
|
|
1995
|
+
return [
|
|
1996
|
+
{ kind: 'version', key, expected: read.value.version },
|
|
1997
|
+
...(conditionedOwner?.ownerId === snapshot.ownerId &&
|
|
1998
|
+
conditionedOwner.leaseGeneration === snapshot.ownerLeaseGeneration
|
|
1999
|
+
? []
|
|
2000
|
+
: [
|
|
2001
|
+
leaseValueCondition(leaseKey, {
|
|
2002
|
+
ownerId: snapshot.ownerId,
|
|
2003
|
+
leaseGeneration: snapshot.ownerLeaseGeneration
|
|
2004
|
+
})
|
|
2005
|
+
])
|
|
2006
|
+
];
|
|
2007
|
+
}
|
|
2008
|
+
async updateOwnedLocation(rowKey, location, intent, signal, membership) {
|
|
1878
2009
|
const leaseKey = ownerKey(location.ownerId);
|
|
1879
2010
|
const [lease, current] = await Promise.all([
|
|
1880
2011
|
this.provider.read(leaseKey, signal),
|
|
@@ -1919,13 +2050,25 @@ class ZLinkLocationStoreRepository extends in_memory_location_store_1.ZLinkInMem
|
|
|
1919
2050
|
else if (intent === 2) {
|
|
1920
2051
|
return rejected(lease.value.storeNow);
|
|
1921
2052
|
}
|
|
2053
|
+
const previousMembership = current.kind === 'found' && membership !== undefined
|
|
2054
|
+
? decodeJson(current.value.bytes).descriptor
|
|
2055
|
+
: undefined;
|
|
2056
|
+
const membershipConditions = membership?.spotKind === contracts_1.ZLinkSpotKind.User &&
|
|
2057
|
+
(previousMembership?.spotKind !== contracts_1.ZLinkSpotKind.User ||
|
|
2058
|
+
String(previousMembership.spotId) !== String(membership.spotId) ||
|
|
2059
|
+
BigInt(previousMembership.spotGeneration) !== membership.spotGeneration)
|
|
2060
|
+
? await this.userSpotMembershipConditions(String(membership.spotId), membership.spotGeneration, signal, { ownerId: location.ownerId, leaseGeneration: locationOwnerGeneration(location) })
|
|
2061
|
+
: [];
|
|
2062
|
+
if (membershipConditions === undefined)
|
|
2063
|
+
return rejected(lease.value.storeNow);
|
|
1922
2064
|
const result = await this.provider.write({
|
|
1923
2065
|
conditions: [
|
|
1924
2066
|
leaseValueCondition(leaseKey, {
|
|
1925
2067
|
ownerId: location.ownerId,
|
|
1926
2068
|
leaseGeneration: locationOwnerGeneration(location)
|
|
1927
2069
|
}),
|
|
1928
|
-
rowCondition
|
|
2070
|
+
rowCondition,
|
|
2071
|
+
...membershipConditions
|
|
1929
2072
|
],
|
|
1930
2073
|
mutations: [
|
|
1931
2074
|
{
|
|
@@ -2913,7 +3056,7 @@ function liveTargetDescriptor(descriptorRead, leaseRead, target) {
|
|
|
2913
3056
|
descriptor.lifecycleGeneration === target.nodeLifecycleGeneration &&
|
|
2914
3057
|
descriptor.ownerId === target.owner.ownerId &&
|
|
2915
3058
|
descriptor.leaseGeneration === target.owner.leaseGeneration &&
|
|
2916
|
-
descriptor.objectRole ===
|
|
3059
|
+
descriptor.objectRole === contracts_2.ZLinkObjectRole.Server &&
|
|
2917
3060
|
lease.ownerId === target.owner.ownerId &&
|
|
2918
3061
|
BigInt(lease.leaseGeneration) === target.owner.leaseGeneration &&
|
|
2919
3062
|
leaseRead.value.expiresAt !== undefined &&
|
|
@@ -2974,7 +3117,7 @@ function adjustCapacity(usage, delta, direction) {
|
|
|
2974
3117
|
const key = capacityTypeKey(delta.spotType);
|
|
2975
3118
|
const next = (spotTypes[key] ?? 0) + direction * delta.spotType.count;
|
|
2976
3119
|
if (next < 0)
|
|
2977
|
-
throw new
|
|
3120
|
+
throw new contracts_2.ZLinkFrameworkException(contracts_2.ZLinkFrameworkErrorKind.DataLost, 'Provider capacity counter underflow.');
|
|
2978
3121
|
if (next === 0)
|
|
2979
3122
|
delete spotTypes[key];
|
|
2980
3123
|
else
|
|
@@ -2983,7 +3126,7 @@ function adjustCapacity(usage, delta, direction) {
|
|
|
2983
3126
|
const actors = usage.actors + direction * delta.actors;
|
|
2984
3127
|
const spots = usage.spots + direction * delta.spots;
|
|
2985
3128
|
if (actors < 0 || spots < 0)
|
|
2986
|
-
throw new
|
|
3129
|
+
throw new contracts_2.ZLinkFrameworkException(contracts_2.ZLinkFrameworkErrorKind.DataLost, 'Provider capacity counter underflow.');
|
|
2987
3130
|
return { actors, spots, spotTypes };
|
|
2988
3131
|
}
|
|
2989
3132
|
function capacityTypeKey(value) {
|
|
@@ -3308,10 +3451,10 @@ function throwIfOperationExpired(signal, deadlineUnixMs) {
|
|
|
3308
3451
|
}
|
|
3309
3452
|
// Store SPI §6: preserve caller failures and classify provider failures once.
|
|
3310
3453
|
function locationStoreProviderFailure(error, signal) {
|
|
3311
|
-
if (error instanceof
|
|
3454
|
+
if (error instanceof contracts_2.ZLinkFrameworkException ||
|
|
3312
3455
|
error instanceof TypeError ||
|
|
3313
3456
|
error instanceof RangeError ||
|
|
3314
3457
|
signal?.aborted === true)
|
|
3315
3458
|
return error;
|
|
3316
|
-
return new
|
|
3459
|
+
return new contracts_2.ZLinkFrameworkException(contracts_2.ZLinkFrameworkErrorKind.Unavailable, 'Location Store provider is unavailable.', error);
|
|
3317
3460
|
}
|