@zlink-systems/framework 0.27.0 → 0.29.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/Actors/ZLinkActorClient.d.ts +1 -1
- package/dist/contracts/Channels/Calls.d.ts +1 -1
- package/dist/contracts/Configuration/Builders.d.ts +2 -1
- package/dist/contracts/Configuration/Configs.d.ts +0 -1
- package/dist/contracts/Configuration/InternalDefaults.d.ts +3 -0
- package/dist/contracts/Configuration/InternalDefaults.js +4 -1
- package/dist/contracts/Configuration/RegistrationBuilders.js +9 -0
- package/dist/contracts/Configuration/RegistrationNormalizers.d.ts +1 -0
- package/dist/contracts/Configuration/RegistrationNormalizers.js +16 -0
- package/dist/contracts/Configuration/RegistrationTypes.d.ts +3 -5
- package/dist/contracts/Configuration/RegistrationValidators.js +0 -2
- package/dist/contracts/Spots/Contracts.d.ts +1 -1
- package/dist/contracts/Streams/BoundSessionContracts.d.ts +1 -1
- package/dist/contracts/Streams/IZLinkSession.d.ts +2 -3
- package/dist/contracts/Streams/IZLinkSessionActor.d.ts +2 -2
- package/dist/runtime/actors/actor-client.js +7 -10
- package/dist/runtime/actors/actor-mailbox.d.ts +2 -2
- package/dist/runtime/actors/actor-mailbox.js +2 -2
- package/dist/runtime/actors/actor-request-deadline.d.ts +1 -3
- package/dist/runtime/actors/actor-request-deadline.js +4 -29
- package/dist/runtime/actors/actor-routed-join-transport.d.ts +2 -3
- package/dist/runtime/backend/contracts/index.d.ts +1 -4
- package/dist/runtime/backend/node/node-backend-adapter-support.d.ts +2 -0
- package/dist/runtime/backend/node/node-backend-adapter-support.js +35 -4
- package/dist/runtime/backend/node/node-dealer-channel-client-transport.d.ts +1 -1
- package/dist/runtime/backend/node/node-dealer-channel-client-transport.js +1 -2
- package/dist/runtime/backend/node/node-raw-binding-port.js +10 -27
- package/dist/runtime/backend/node/node-raw-mesh-backend.js +1 -3
- package/dist/runtime/backend/node/node-socket-backend-adapter.js +1 -1
- package/dist/runtime/channels/channel-clients.js +8 -10
- package/dist/runtime/channels/channel-envelope.d.ts +1 -1
- package/dist/runtime/channels/channel-envelope.js +4 -10
- package/dist/runtime/channels/channel-outbound-operations.d.ts +2 -2
- package/dist/runtime/channels/channel-outbound-operations.js +20 -36
- package/dist/runtime/channels/channel-runtime-manager.d.ts +4 -4
- package/dist/runtime/channels/channel-runtime-manager.js +8 -8
- package/dist/runtime/channels/channel-socket-options.js +0 -10
- package/dist/runtime/channels/channel-socket-registry.d.ts +1 -1
- package/dist/runtime/channels/channel-socket-registry.js +3 -14
- package/dist/runtime/channels/channel-transports.d.ts +10 -14
- package/dist/runtime/channels/channel-transports.js +11 -14
- package/dist/runtime/channels/local-spot-route-transport.d.ts +1 -1
- package/dist/runtime/channels/local-spot-route-transport.js +1 -3
- package/dist/runtime/channels/router-socket-spot-route-transport.d.ts +1 -1
- package/dist/runtime/channels/router-socket-spot-route-transport.js +2 -2
- package/dist/runtime/channels/source-spot-router.d.ts +1 -1
- package/dist/runtime/channels/source-spot-router.js +2 -4
- package/dist/runtime/channels/spot-node-route-transport.d.ts +1 -1
- package/dist/runtime/channels/spot-node-route-transport.js +2 -3
- package/dist/runtime/channels/spot-route-bridge-transport.d.ts +1 -1
- package/dist/runtime/channels/spot-route-bridge-transport.js +2 -2
- package/dist/runtime/channels/spot-route-dispatch-strategy.d.ts +2 -4
- package/dist/runtime/channels/spot-route-dispatch-strategy.js +11 -12
- package/dist/runtime/execution/serial-execution-queue.d.ts +12 -3
- package/dist/runtime/execution/serial-execution-queue.js +116 -28
- package/dist/runtime/foundation/operation-registry.d.ts +3 -2
- package/dist/runtime/foundation/operation-registry.js +5 -1
- package/dist/runtime/foundation/raw-service-mesh-runtime.js +17 -11
- package/dist/runtime/foundation/service-authority-payload-codec.d.ts +0 -2
- package/dist/runtime/foundation/service-authority-payload-codec.js +0 -43
- package/dist/runtime/foundation/service-stateful-registry.d.ts +4 -3
- package/dist/runtime/foundation/service-stateful-registry.js +5 -2
- package/dist/runtime/foundation/service-stateful-runtime.d.ts +1 -8
- package/dist/runtime/foundation/service-stateful-runtime.js +78 -126
- package/dist/runtime/foundation/service-stateful-wire-codec.d.ts +0 -11
- package/dist/runtime/foundation/service-stateful-wire-codec.js +1 -23
- package/dist/runtime/foundation/service-topology-registry.d.ts +5 -0
- package/dist/runtime/foundation/service-topology-registry.js +16 -17
- package/dist/runtime/host/actor-packet-relay.d.ts +2 -2
- package/dist/runtime/host/actor-packet-relay.js +8 -10
- package/dist/runtime/host/index.js +1 -15
- package/dist/runtime/host/instance-activation-authority.d.ts +0 -1
- package/dist/runtime/host/instance-activation-authority.js +46 -97
- package/dist/runtime/host/remote-bound-session-relay.js +8 -8
- package/dist/runtime/host/spot-address-transport.d.ts +1 -9
- package/dist/runtime/host/spot-address-transport.js +47 -87
- package/dist/runtime/host/stateful-authority-route-runtime.d.ts +1 -0
- package/dist/runtime/host/stateful-authority-route-runtime.js +17 -9
- package/dist/runtime/locations/domain-store-contract.d.ts +1 -0
- package/dist/runtime/locations/in-memory-authority-store.d.ts +2 -0
- package/dist/runtime/locations/in-memory-authority-store.js +22 -8
- package/dist/runtime/locations/in-memory-location-store.d.ts +1 -0
- package/dist/runtime/locations/in-memory-location-store.js +3 -0
- package/dist/runtime/locations/internal-store-contracts.d.ts +1 -1
- package/dist/runtime/locations/location-store-repository.d.ts +1 -0
- package/dist/runtime/locations/location-store-repository.js +98 -53
- package/dist/runtime/messaging/request-deadline.d.ts +3 -0
- package/dist/runtime/messaging/request-deadline.js +39 -0
- package/dist/runtime/messaging/submission-result.d.ts +2 -1
- package/dist/runtime/messaging/submission-result.js +11 -4
- package/dist/runtime/spots/spot-outbound.d.ts +3 -5
- package/dist/runtime/spots/spot-outbound.js +12 -15
- package/dist/runtime/spots/spot-serial-executor.js +4 -1
- package/dist/runtime/spots/spot-serial-turn-executor.d.ts +3 -0
- package/dist/runtime/spots/spot-serial-turn-executor.js +5 -0
- package/dist/runtime/streams/bound-actor-relay-sender.d.ts +2 -2
- package/dist/runtime/streams/bound-actor-relay-sender.js +14 -14
- package/dist/runtime/streams/bound-session-service.js +1 -1
- package/dist/runtime/streams/index.d.ts +2 -3
- package/dist/runtime/streams/index.js +6 -5
- package/dist/runtime/streams/managed-stream.d.ts +2 -2
- package/dist/runtime/streams/managed-stream.js +3 -5
- package/dist/runtime/streams/native-fallback-bound-session.js +13 -16
- package/dist/runtime/streams/protocol.js +0 -9
- package/dist/runtime/streams/session-calls.d.ts +5 -7
- package/dist/runtime/streams/session-calls.js +6 -23
- package/dist/runtime/streams/session-context.d.ts +4 -8
- package/dist/runtime/streams/session-context.js +3 -32
- package/dist/runtime/streams/session-serial-executor.d.ts +0 -1
- package/dist/runtime/streams/session-serial-executor.js +0 -3
- package/dist/runtime/streams/stream-message-utils.d.ts +0 -1
- package/dist/runtime/streams/stream-message-utils.js +0 -20
- package/dist/runtime/streams/stream-session-runtime.d.ts +6 -3
- package/dist/runtime/streams/stream-session-runtime.js +40 -85
- package/package.json +3 -3
- package/src/contracts/Actors/ZLinkActorClient.ts +1 -1
- package/src/contracts/Channels/Calls.ts +1 -1
- package/src/contracts/Configuration/Builders.ts +2 -1
- package/src/contracts/Configuration/Configs.ts +0 -1
- package/src/contracts/Configuration/InternalDefaults.ts +4 -0
- package/src/contracts/Configuration/RegistrationBuilders.ts +13 -3
- package/src/contracts/Configuration/RegistrationNormalizers.ts +25 -0
- package/src/contracts/Configuration/RegistrationTypes.ts +3 -5
- package/src/contracts/Configuration/RegistrationValidators.ts +0 -4
- package/src/contracts/Spots/Contracts.ts +1 -1
- package/src/contracts/Streams/BoundSessionContracts.ts +1 -1
- package/src/contracts/Streams/IZLinkSession.ts +2 -3
- package/src/contracts/Streams/IZLinkSessionActor.ts +2 -6
- package/src/runtime/actors/actor-client.ts +9 -15
- package/src/runtime/actors/actor-mailbox.ts +7 -2
- package/src/runtime/actors/actor-request-deadline.ts +4 -49
- package/src/runtime/actors/actor-routed-join-transport.ts +3 -5
- package/src/runtime/backend/contracts/index.ts +1 -8
- package/src/runtime/backend/node/node-backend-adapter-support.ts +45 -5
- package/src/runtime/backend/node/node-dealer-channel-client-transport.ts +0 -2
- package/src/runtime/backend/node/node-raw-binding-port.ts +15 -41
- package/src/runtime/backend/node/node-raw-mesh-backend.ts +1 -7
- package/src/runtime/backend/node/node-socket-backend-adapter.ts +1 -1
- package/src/runtime/channels/channel-clients.ts +9 -19
- package/src/runtime/channels/channel-envelope.ts +16 -28
- package/src/runtime/channels/channel-outbound-operations.ts +36 -38
- package/src/runtime/channels/channel-runtime-manager.ts +6 -28
- package/src/runtime/channels/channel-socket-options.ts +0 -13
- package/src/runtime/channels/channel-socket-registry.ts +3 -17
- package/src/runtime/channels/channel-transports.ts +7 -33
- package/src/runtime/channels/local-spot-route-transport.ts +1 -5
- package/src/runtime/channels/router-socket-spot-route-transport.ts +2 -6
- package/src/runtime/channels/source-spot-router.ts +2 -9
- package/src/runtime/channels/spot-node-route-transport.ts +2 -7
- package/src/runtime/channels/spot-route-bridge-transport.ts +5 -12
- package/src/runtime/channels/spot-route-dispatch-strategy.ts +11 -30
- package/src/runtime/execution/serial-execution-queue.ts +117 -29
- package/src/runtime/foundation/operation-registry.ts +16 -9
- package/src/runtime/foundation/raw-service-mesh-runtime.ts +17 -14
- package/src/runtime/foundation/service-authority-payload-codec.ts +0 -46
- package/src/runtime/foundation/service-stateful-registry.ts +10 -5
- package/src/runtime/foundation/service-stateful-runtime.ts +103 -181
- package/src/runtime/foundation/service-stateful-wire-codec.ts +0 -25
- package/src/runtime/foundation/service-topology-registry.ts +30 -20
- package/src/runtime/host/actor-packet-relay.ts +8 -15
- package/src/runtime/host/index.ts +2 -26
- package/src/runtime/host/instance-activation-authority.ts +58 -125
- package/src/runtime/host/remote-bound-session-relay.ts +8 -16
- package/src/runtime/host/spot-address-transport.ts +107 -166
- package/src/runtime/host/stateful-authority-route-runtime.ts +22 -9
- package/src/runtime/locations/domain-store-contract.ts +5 -0
- package/src/runtime/locations/in-memory-authority-store.ts +42 -8
- package/src/runtime/locations/in-memory-location-store.ts +8 -0
- package/src/runtime/locations/internal-store-contracts.ts +1 -0
- package/src/runtime/locations/location-store-repository.ts +130 -68
- package/src/runtime/messaging/request-deadline.ts +58 -0
- package/src/runtime/messaging/submission-result.ts +18 -4
- package/src/runtime/protocol/service_wire_pilot_codec.generated.ts +1 -1
- package/src/runtime/spots/spot-outbound.ts +14 -24
- package/src/runtime/spots/spot-serial-executor.ts +4 -1
- package/src/runtime/spots/spot-serial-turn-executor.ts +10 -0
- package/src/runtime/streams/bound-actor-relay-sender.ts +12 -26
- package/src/runtime/streams/bound-session-service.ts +1 -1
- package/src/runtime/streams/index.ts +5 -5
- package/src/runtime/streams/managed-stream.ts +3 -13
- package/src/runtime/streams/native-fallback-bound-session.ts +13 -25
- package/src/runtime/streams/protocol.ts +0 -13
- package/src/runtime/streams/session-calls.ts +8 -34
- package/src/runtime/streams/session-context.ts +6 -47
- package/src/runtime/streams/session-serial-executor.ts +0 -8
- package/src/runtime/streams/stream-message-utils.ts +1 -27
- package/src/runtime/streams/stream-session-runtime.ts +54 -97
- package/dist/runtime/streams/session-requests.d.ts +0 -25
- package/dist/runtime/streams/session-requests.js +0 -101
- package/src/runtime/streams/session-requests.ts +0 -110
|
@@ -25,6 +25,7 @@ export interface ZLinkDomainLocationStore {
|
|
|
25
25
|
reserve(request: ZLinkObjectReserveRequest, signal?: AbortSignal, deadlineUnixMs?: bigint): Promise<ZLinkObjectReserveResult>;
|
|
26
26
|
commit(request: ZLinkObjectCommitRequest, signal?: AbortSignal, deadlineUnixMs?: bigint): Promise<ZLinkObjectCommitResult>;
|
|
27
27
|
completeCreation(request: ZLinkObjectCreationCompleteRequest, signal?: AbortSignal): Promise<ZLinkObjectCreationCompleteResult>;
|
|
28
|
+
releaseEndedReservation?(key: ZLinkAuthorityKey, expectedStoreVersion: string, signal?: AbortSignal): Promise<boolean>;
|
|
28
29
|
abort(request: ZLinkObjectAbortRequest, signal?: AbortSignal, deadlineUnixMs?: bigint): Promise<ZLinkObjectAbortResult>;
|
|
29
30
|
prepareAggregate(request: ZLinkAggregatePrepareRequest, signal?: AbortSignal): Promise<ZLinkAggregatePrepareResult>;
|
|
30
31
|
commitAggregate(fence: ZLinkAggregateFence, signal?: AbortSignal): Promise<ZLinkAggregateCommitResult>;
|
|
@@ -26,6 +26,8 @@ export declare class ZLinkInMemoryAuthorityStore {
|
|
|
26
26
|
compareExchangeAuthority(key: ZLinkAuthorityKey, expectedStoreVersion: ZLinkAuthorityStoreVersion, mutation: ZLinkAuthorityMutation, signal?: AbortSignal): Promise<ZLinkAuthorityCompareExchangeResult>;
|
|
27
27
|
listAuthorities(prefix: string, cursor: ZLinkAuthorityScanCursor | undefined, limit: number, signal?: AbortSignal): Promise<ZLinkAuthorityScanResult>;
|
|
28
28
|
removeAllByOwner(owner: ZLinkLocationOwnerToken, signal?: AbortSignal): Promise<bigint>;
|
|
29
|
+
releaseEndedReservation(key: ZLinkAuthorityKey, expectedStoreVersion: string, signal?: AbortSignal): Promise<boolean>;
|
|
30
|
+
private tryReleaseEndedReservation;
|
|
29
31
|
reserve(request: ZLinkObjectReserveRequest, signal?: AbortSignal): Promise<ZLinkObjectReserveResult>;
|
|
30
32
|
commit(request: ZLinkObjectCommitRequest, signal?: AbortSignal): Promise<ZLinkObjectCommitResult>;
|
|
31
33
|
completeCreation(request: ZLinkObjectCreationCompleteRequest, signal?: AbortSignal): Promise<ZLinkObjectCreationCompleteResult>;
|
|
@@ -171,6 +171,27 @@ class ZLinkInMemoryAuthorityStore {
|
|
|
171
171
|
this.scanRevision++;
|
|
172
172
|
return BigInt(removed);
|
|
173
173
|
}
|
|
174
|
+
async releaseEndedReservation(key, expectedStoreVersion, signal) {
|
|
175
|
+
signal?.throwIfAborted();
|
|
176
|
+
return this.tryReleaseEndedReservation(key, expectedStoreVersion);
|
|
177
|
+
}
|
|
178
|
+
tryReleaseEndedReservation(key, expectedStoreVersion) {
|
|
179
|
+
const current = this.rows.get(key.value);
|
|
180
|
+
if (current === undefined ||
|
|
181
|
+
current.snapshot.storeVersion.value !== expectedStoreVersion ||
|
|
182
|
+
current.snapshot.allocation.state !== 'reserved' ||
|
|
183
|
+
current.creation === undefined ||
|
|
184
|
+
this.validation.isTargetLive(current.snapshot.allocation.descriptor, current.snapshot.allocation.descriptorLifecycleGeneration, {
|
|
185
|
+
ownerId: current.snapshot.ownerId,
|
|
186
|
+
leaseGeneration: current.snapshot.ownerLeaseGeneration
|
|
187
|
+
}))
|
|
188
|
+
return false;
|
|
189
|
+
this.adjustCapacity(this.pendingCapacity, current.snapshot.allocation, -1);
|
|
190
|
+
this.rows.delete(key.value);
|
|
191
|
+
this.creationTerminals.set(current.creation.reservationId, 'aborted');
|
|
192
|
+
this.scanRevision++;
|
|
193
|
+
return true;
|
|
194
|
+
}
|
|
174
195
|
async reserve(request, signal) {
|
|
175
196
|
signal?.throwIfAborted();
|
|
176
197
|
validateReserve(request);
|
|
@@ -187,15 +208,8 @@ class ZLinkInMemoryAuthorityStore {
|
|
|
187
208
|
if (current.snapshot.allocation.state === 'active') {
|
|
188
209
|
return { kind: 'alreadyExists', current: this.snapshot(current.snapshot) };
|
|
189
210
|
}
|
|
190
|
-
|
|
191
|
-
// Reclaim it so the key does not stay blocked forever.
|
|
192
|
-
if (this.isOwnerLive(current.snapshot) || current.creation === undefined) {
|
|
211
|
+
if (!this.tryReleaseEndedReservation((0, authority_key_codec_1.encodeAuthorityKey)(request.key.kind, request.key.globalId), current.snapshot.storeVersion.value))
|
|
193
212
|
return { kind: 'conflict', current: this.read(key) };
|
|
194
|
-
}
|
|
195
|
-
this.adjustCapacity(this.pendingCapacity, current.snapshot.allocation, -1);
|
|
196
|
-
this.rows.delete(key);
|
|
197
|
-
this.creationTerminals.set(current.creation.reservationId, 'aborted');
|
|
198
|
-
this.scanRevision++;
|
|
199
213
|
}
|
|
200
214
|
const target = creationTarget(request);
|
|
201
215
|
if (!this.validation.isTargetLive(target.descriptor, target.lifecycleGeneration, target.owner)) {
|
|
@@ -25,6 +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
29
|
abort(request: ZLinkObjectAbortRequest, signal?: AbortSignal): Promise<ZLinkObjectAbortResult>;
|
|
29
30
|
prepareAggregate(request: ZLinkAggregatePrepareRequest, signal?: AbortSignal): Promise<ZLinkAggregatePrepareResult>;
|
|
30
31
|
commitAggregate(fence: ZLinkAggregateFence, signal?: AbortSignal): Promise<ZLinkAggregateCommitResult>;
|
|
@@ -86,6 +86,9 @@ class ZLinkInMemoryLocationStore {
|
|
|
86
86
|
async readCreationTerminal(operation, signal) {
|
|
87
87
|
return this.authority.readCreationTerminal(operation, signal);
|
|
88
88
|
}
|
|
89
|
+
async releaseEndedReservation(key, expectedStoreVersion, signal) {
|
|
90
|
+
return this.authority.releaseEndedReservation(key, expectedStoreVersion, signal);
|
|
91
|
+
}
|
|
89
92
|
async abort(request, signal) {
|
|
90
93
|
return this.authority.abort(request, signal);
|
|
91
94
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { ZLinkActorLocation, ZLinkActorLocationFilter, ZLinkActorLocationKey, ZLinkLocationOwnerToken, ZLinkLocationPage, ZLinkLocationWriteIntent, ZLinkLocationWriteResult, ZLinkLocationWriteStatus, ZLinkPageRequest, ZLinkPeerLocation, ZLinkPeerLocationFilter, ZLinkPeerLocationKey, ZLinkRouteLocation, ZLinkRouteLocationFilter, ZLinkRouteLocationKey, ZLinkSpotLocation, ZLinkSpotLocationFilter, ZLinkSpotLocationKey } from './internal-location-contracts';
|
|
2
2
|
import type { ZLinkDomainLocationStore } from './domain-store-contract';
|
|
3
3
|
export type ZLinkAuthorityStore = Pick<ZLinkDomainLocationStore, 'readAuthority' | 'compareExchangeAuthority' | 'listAuthorities'>;
|
|
4
|
-
export type ZLinkObjectCreationStore = Pick<ZLinkDomainLocationStore, 'readCreationTerminal' | 'reserve' | 'commit' | 'completeCreation' | 'abort' | 'prepareAggregate' | 'commitAggregate' | 'abortAggregate'>;
|
|
4
|
+
export type ZLinkObjectCreationStore = Pick<ZLinkDomainLocationStore, 'readCreationTerminal' | 'reserve' | 'commit' | 'completeCreation' | 'abort' | 'releaseEndedReservation' | 'prepareAggregate' | 'commitAggregate' | 'abortAggregate'>;
|
|
5
5
|
export type ZLinkOwnerLeaseStore = Pick<ZLinkDomainLocationStore, 'claimOwnerLease' | 'readOwnerLease' | 'renewOwnerLease' | 'releaseOwnerLease'>;
|
|
6
6
|
export type ZLinkMeshNodeLocationStore = Pick<ZLinkDomainLocationStore, 'updateMeshNode' | 'removeMeshNode' | 'listMeshNodes'>;
|
|
7
7
|
export type ZLinkClientServerLocationStore = Pick<ZLinkDomainLocationStore, 'updateClientServer' | 'removeClientServer' | 'listClientServers'>;
|
|
@@ -20,6 +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
24
|
reserve(request: ZLinkObjectReserveRequest, signal?: AbortSignal, deadlineUnixMs?: bigint): Promise<ZLinkObjectReserveResult>;
|
|
24
25
|
commit(request: ZLinkObjectCommitRequest, signal?: AbortSignal, deadlineUnixMs?: bigint): Promise<ZLinkObjectCommitResult>;
|
|
25
26
|
abort(request: ZLinkObjectAbortRequest, signal?: AbortSignal, deadlineUnixMs?: bigint): Promise<ZLinkObjectAbortResult>;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.ZLinkLocationStoreRepository = void 0;
|
|
4
|
+
const service_relocation_runtime_1 = require("../foundation/service-relocation-runtime");
|
|
4
5
|
const stream_wire_1 = require("@zlink-systems/stream-wire");
|
|
5
6
|
const node_crypto_1 = require("node:crypto");
|
|
6
7
|
const Options_1 = require("../../contracts/Locations/Options");
|
|
@@ -46,7 +47,33 @@ class ZLinkLocationStoreRepository extends in_memory_location_store_1.ZLinkInMem
|
|
|
46
47
|
constructor(provider, nowProvider = () => new Date()) {
|
|
47
48
|
super(nowProvider);
|
|
48
49
|
this.nowProvider = nowProvider;
|
|
49
|
-
|
|
50
|
+
// Classify only failures of the opaque SPI, before interpreting its records.
|
|
51
|
+
this.provider = {
|
|
52
|
+
async read(key, signal) {
|
|
53
|
+
try {
|
|
54
|
+
return await provider.read(key, signal);
|
|
55
|
+
}
|
|
56
|
+
catch (error) {
|
|
57
|
+
throw locationStoreProviderFailure(error, signal);
|
|
58
|
+
}
|
|
59
|
+
},
|
|
60
|
+
async write(request, signal) {
|
|
61
|
+
try {
|
|
62
|
+
return await provider.write(request, signal);
|
|
63
|
+
}
|
|
64
|
+
catch (error) {
|
|
65
|
+
throw locationStoreProviderFailure(error, signal);
|
|
66
|
+
}
|
|
67
|
+
},
|
|
68
|
+
async scan(request, signal) {
|
|
69
|
+
try {
|
|
70
|
+
return await provider.scan(request, signal);
|
|
71
|
+
}
|
|
72
|
+
catch (error) {
|
|
73
|
+
throw locationStoreProviderFailure(error, signal);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
};
|
|
50
77
|
this.aggregateInventory = new aggregate_inventory_store_1.ZLinkAggregateInventoryStore(this.provider);
|
|
51
78
|
}
|
|
52
79
|
async readAuthority(key, signal) {
|
|
@@ -787,6 +814,57 @@ class ZLinkLocationStoreRepository extends in_memory_location_store_1.ZLinkInMem
|
|
|
787
814
|
return { kind: 'aborted' };
|
|
788
815
|
}
|
|
789
816
|
}
|
|
817
|
+
async releaseEndedReservation(key, expectedStoreVersion, signal) {
|
|
818
|
+
const rowKey = authorityKey(key.value);
|
|
819
|
+
const current = await this.provider.read(rowKey, signal);
|
|
820
|
+
if (current.kind === 'missing' || current.value.version.value !== expectedStoreVersion)
|
|
821
|
+
return false;
|
|
822
|
+
const record = decodeAuthorityRecord(current.value.bytes);
|
|
823
|
+
const snapshot = record.snapshot;
|
|
824
|
+
if (snapshot.allocation.state !== 'reserved' ||
|
|
825
|
+
snapshot.pendingCreation === undefined ||
|
|
826
|
+
record.aggregate !== undefined ||
|
|
827
|
+
hasRelocationAuthority(snapshot.payload))
|
|
828
|
+
return false;
|
|
829
|
+
const leaseKey = ownerKey(snapshot.ownerId);
|
|
830
|
+
const descriptorKey = meshKey(snapshot.allocation.descriptor.meshName, snapshot.allocation.descriptor.rid);
|
|
831
|
+
const capacityRowKey = capacityKey(snapshot.allocation.descriptor.meshName, String(snapshot.allocation.descriptor.rid));
|
|
832
|
+
const [lease, descriptor, capacity] = await Promise.all([
|
|
833
|
+
this.provider.read(leaseKey, signal),
|
|
834
|
+
this.provider.read(descriptorKey, signal),
|
|
835
|
+
this.provider.read(capacityRowKey, signal)
|
|
836
|
+
]);
|
|
837
|
+
if (lease.kind === 'found' && lease.value.expiresAt === undefined)
|
|
838
|
+
throw new Error('Location Store owner lease record is invalid.');
|
|
839
|
+
if (sameLiveOwner(lease, snapshot) &&
|
|
840
|
+
descriptor.kind === 'found' &&
|
|
841
|
+
reviveMeshDescriptor(decodeCanonicalDescriptorRecord(descriptor.value.bytes).descriptor).lifecycleGeneration === snapshot.allocation.descriptorLifecycleGeneration)
|
|
842
|
+
return false;
|
|
843
|
+
const mutations = [
|
|
844
|
+
{ kind: 'delete', key: rowKey }
|
|
845
|
+
];
|
|
846
|
+
if (capacity.kind === 'found') {
|
|
847
|
+
const stored = decodeJson(capacity.value.bytes);
|
|
848
|
+
mutations.push({
|
|
849
|
+
kind: 'put',
|
|
850
|
+
key: capacityRowKey,
|
|
851
|
+
bytes: encodeJson({
|
|
852
|
+
active: stored.active,
|
|
853
|
+
pending: subtractCapacity(stored.pending, snapshot.allocation.capacity)
|
|
854
|
+
})
|
|
855
|
+
});
|
|
856
|
+
}
|
|
857
|
+
const result = await this.provider.write({
|
|
858
|
+
conditions: [
|
|
859
|
+
{ kind: 'version', key: rowKey, expected: current.value.version },
|
|
860
|
+
conditionFor(leaseKey, lease),
|
|
861
|
+
conditionFor(descriptorKey, descriptor),
|
|
862
|
+
conditionFor(capacityRowKey, capacity)
|
|
863
|
+
],
|
|
864
|
+
mutations
|
|
865
|
+
}, signal);
|
|
866
|
+
return result.kind === 'applied';
|
|
867
|
+
}
|
|
790
868
|
async reserve(request, signal, deadlineUnixMs) {
|
|
791
869
|
const encodedAuthorityKey = (0, authority_key_codec_1.encodeAuthorityKey)(request.key.kind, request.key.globalId);
|
|
792
870
|
const reservationId = (0, node_crypto_1.randomUUID)();
|
|
@@ -807,51 +885,8 @@ class ZLinkLocationStoreRepository extends in_memory_location_store_1.ZLinkInMem
|
|
|
807
885
|
if (snapshot.allocation.state === 'active') {
|
|
808
886
|
return { kind: 'alreadyExists', current: snapshot };
|
|
809
887
|
}
|
|
810
|
-
if (
|
|
811
|
-
isCanonicalAuthorityPayload(record.snapshot.payload)) {
|
|
812
|
-
// A relocation record carries its own recovery protocol. Reserve
|
|
813
|
-
// may reclaim only an unfinished plain creation.
|
|
888
|
+
if (!(await this.releaseEndedReservation(encodedAuthorityKey, current.value.version.value, signal)))
|
|
814
889
|
return { kind: 'conflict', current: snapshot };
|
|
815
|
-
}
|
|
816
|
-
// The row is Reserved by another owner. An unfinished creation
|
|
817
|
-
// whose owner lease ended is cancellable, so reclaim it and retry
|
|
818
|
-
// instead of blocking the key forever.
|
|
819
|
-
const staleOwnerKey = ownerKey(snapshot.ownerId);
|
|
820
|
-
const staleCapacityKey = capacityKey(snapshot.allocation.descriptor.meshName, String(snapshot.allocation.descriptor.rid));
|
|
821
|
-
const [staleOwnerRead, staleCapacityRead] = await Promise.all([
|
|
822
|
-
this.provider.read(staleOwnerKey, signal),
|
|
823
|
-
this.provider.read(staleCapacityKey, signal)
|
|
824
|
-
]);
|
|
825
|
-
if (staleOwnerRead.kind === 'found' && staleOwnerRead.value.expiresAt === undefined) {
|
|
826
|
-
// A lease is always written with a positive TTL, so a missing
|
|
827
|
-
// expiry is a corrupt record. Reclaiming deletes authority state,
|
|
828
|
-
// so refuse rather than read the absence as expiry.
|
|
829
|
-
throw new Error('Location Store owner lease record is invalid.');
|
|
830
|
-
}
|
|
831
|
-
if (sameLiveOwner(staleOwnerRead, record.snapshot)) {
|
|
832
|
-
return { kind: 'conflict', current: snapshot };
|
|
833
|
-
}
|
|
834
|
-
const staleCapacity = staleCapacityRead.kind === 'missing'
|
|
835
|
-
? emptyCapacityRecord()
|
|
836
|
-
: decodeJson(staleCapacityRead.value.bytes);
|
|
837
|
-
await this.provider.write({
|
|
838
|
-
conditions: [
|
|
839
|
-
{ kind: 'version', key: rowKey, expected: current.value.version },
|
|
840
|
-
versionCondition(staleOwnerKey, staleOwnerRead),
|
|
841
|
-
conditionFor(staleCapacityKey, staleCapacityRead)
|
|
842
|
-
],
|
|
843
|
-
mutations: [
|
|
844
|
-
{ kind: 'delete', key: rowKey },
|
|
845
|
-
{
|
|
846
|
-
kind: 'put',
|
|
847
|
-
key: staleCapacityKey,
|
|
848
|
-
bytes: encodeJson({
|
|
849
|
-
active: staleCapacity.active,
|
|
850
|
-
pending: subtractCapacity(staleCapacity.pending, record.snapshot.allocation.capacity)
|
|
851
|
-
})
|
|
852
|
-
}
|
|
853
|
-
]
|
|
854
|
-
}, signal);
|
|
855
890
|
continue;
|
|
856
891
|
}
|
|
857
892
|
const [descriptorRead, leaseRead] = await Promise.all([
|
|
@@ -859,7 +894,7 @@ class ZLinkLocationStoreRepository extends in_memory_location_store_1.ZLinkInMem
|
|
|
859
894
|
this.provider.read(leaseKey, signal)
|
|
860
895
|
]);
|
|
861
896
|
const descriptor = liveTargetDescriptor(descriptorRead, leaseRead, request.target);
|
|
862
|
-
if (descriptor === undefined) {
|
|
897
|
+
if (descriptor === undefined || descriptor.state !== contracts_1.ZLinkFrameworkRuntimeState.Serving) {
|
|
863
898
|
return { kind: 'conflict', current: { kind: 'missing', storeNow: current.storeNow } };
|
|
864
899
|
}
|
|
865
900
|
const [capacityRead, objectGenerationRead, authorityOwnerGenerationRead] = await Promise.all([
|
|
@@ -1042,9 +1077,11 @@ class ZLinkLocationStoreRepository extends in_memory_location_store_1.ZLinkInMem
|
|
|
1042
1077
|
!sameCreationTarget(record.snapshot, request.target)) {
|
|
1043
1078
|
return { kind: 'stale' };
|
|
1044
1079
|
}
|
|
1080
|
+
const descriptorKey = meshKey(request.target.meshName, request.target.nodeRid);
|
|
1045
1081
|
const leaseKey = ownerKey(request.target.owner.ownerId);
|
|
1046
1082
|
const capacityRowKey = capacityKey(request.target.meshName, String(request.target.nodeRid));
|
|
1047
|
-
const [leaseRead, capacityRead] = await Promise.all([
|
|
1083
|
+
const [descriptorRead, leaseRead, capacityRead] = await Promise.all([
|
|
1084
|
+
this.provider.read(descriptorKey, signal),
|
|
1048
1085
|
this.provider.read(leaseKey, signal),
|
|
1049
1086
|
this.provider.read(capacityRowKey, signal)
|
|
1050
1087
|
]);
|
|
@@ -1054,7 +1091,7 @@ class ZLinkLocationStoreRepository extends in_memory_location_store_1.ZLinkInMem
|
|
|
1054
1091
|
// rather than read the absence as expiry.
|
|
1055
1092
|
throw new Error('Location Store owner lease record is invalid.');
|
|
1056
1093
|
}
|
|
1057
|
-
if (
|
|
1094
|
+
if (liveTargetDescriptor(descriptorRead, leaseRead, request.target) === undefined)
|
|
1058
1095
|
return { kind: 'stale' };
|
|
1059
1096
|
const capacity = capacityRead.kind === 'missing'
|
|
1060
1097
|
? emptyCapacityRecord()
|
|
@@ -1062,6 +1099,7 @@ class ZLinkLocationStoreRepository extends in_memory_location_store_1.ZLinkInMem
|
|
|
1062
1099
|
const result = await this.provider.write({
|
|
1063
1100
|
conditions: [
|
|
1064
1101
|
{ kind: 'version', key: rowKey, expected: current.value.version },
|
|
1102
|
+
versionCondition(descriptorKey, descriptorRead),
|
|
1065
1103
|
leaseValueCondition(leaseKey, {
|
|
1066
1104
|
ownerId: record.snapshot.ownerId,
|
|
1067
1105
|
leaseGeneration: record.snapshot.ownerLeaseGeneration
|
|
@@ -2843,7 +2881,6 @@ function liveTargetDescriptor(descriptorRead, leaseRead, target) {
|
|
|
2843
2881
|
descriptor.ownerId === target.owner.ownerId &&
|
|
2844
2882
|
descriptor.leaseGeneration === target.owner.leaseGeneration &&
|
|
2845
2883
|
descriptor.objectRole === contracts_1.ZLinkObjectRole.Server &&
|
|
2846
|
-
descriptor.state === contracts_1.ZLinkFrameworkRuntimeState.Serving &&
|
|
2847
2884
|
lease.ownerId === target.owner.ownerId &&
|
|
2848
2885
|
BigInt(lease.leaseGeneration) === target.owner.leaseGeneration &&
|
|
2849
2886
|
leaseRead.value.expiresAt !== undefined &&
|
|
@@ -2940,10 +2977,9 @@ function sameCreationTarget(snapshot, target) {
|
|
|
2940
2977
|
snapshot.ownerId === target.owner.ownerId &&
|
|
2941
2978
|
snapshot.ownerLeaseGeneration === target.owner.leaseGeneration);
|
|
2942
2979
|
}
|
|
2943
|
-
const
|
|
2944
|
-
function
|
|
2945
|
-
return (payload
|
|
2946
|
-
Buffer.from(payload.buffer, payload.byteOffset, CANONICAL_AUTHORITY_MAGIC.byteLength).equals(CANONICAL_AUTHORITY_MAGIC));
|
|
2980
|
+
const relocationAuthorityCodec = new service_relocation_runtime_1.ServiceRelocationAuthorityPayloadCodec();
|
|
2981
|
+
function hasRelocationAuthority(payload) {
|
|
2982
|
+
return relocationAuthorityCodec.read(payload) !== undefined;
|
|
2947
2983
|
}
|
|
2948
2984
|
function sameLiveOwner(lease, snapshot) {
|
|
2949
2985
|
if (lease.kind === 'missing')
|
|
@@ -3237,3 +3273,12 @@ function throwIfOperationExpired(signal, deadlineUnixMs) {
|
|
|
3237
3273
|
throw new DOMException('Operation deadline exceeded.', 'TimeoutError');
|
|
3238
3274
|
}
|
|
3239
3275
|
}
|
|
3276
|
+
// Store SPI §6: preserve caller failures and classify provider failures once.
|
|
3277
|
+
function locationStoreProviderFailure(error, signal) {
|
|
3278
|
+
if (error instanceof contracts_1.ZLinkFrameworkException ||
|
|
3279
|
+
error instanceof TypeError ||
|
|
3280
|
+
error instanceof RangeError ||
|
|
3281
|
+
signal?.aborted === true)
|
|
3282
|
+
return error;
|
|
3283
|
+
return new contracts_1.ZLinkFrameworkException(contracts_1.ZLinkFrameworkErrorKind.Unavailable, 'Location Store provider is unavailable.', error);
|
|
3284
|
+
}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export declare function remainingRequestTimeout(operation: string, deadlineMs: number | undefined): number | undefined;
|
|
2
|
+
/** Bounds caller waiting across outbound admission and reply; late completions stay observed. */
|
|
3
|
+
export declare function waitRequestReply<T>(reply: Promise<T>, operation: string, deadlineMs: number | undefined, signal?: AbortSignal, endWait?: () => void, discardLateReply?: (reply: T) => void): Promise<T>;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.remainingRequestTimeout = remainingRequestTimeout;
|
|
4
|
+
exports.waitRequestReply = waitRequestReply;
|
|
5
|
+
const abort_1 = require("../abort");
|
|
6
|
+
const framework_errors_internal_1 = require("../framework-errors-internal");
|
|
7
|
+
function remainingRequestTimeout(operation, deadlineMs) {
|
|
8
|
+
if (deadlineMs === undefined)
|
|
9
|
+
return undefined;
|
|
10
|
+
const remaining = deadlineMs - performance.now();
|
|
11
|
+
if (remaining <= 0) {
|
|
12
|
+
throw (0, framework_errors_internal_1.createInternalFrameworkException)(framework_errors_internal_1.ZLinkFrameworkInternalErrorKind.DeadlineExceeded, `${operation} exceeded its deadline.`);
|
|
13
|
+
}
|
|
14
|
+
return Math.max(1, Math.ceil(remaining));
|
|
15
|
+
}
|
|
16
|
+
/** Bounds caller waiting across outbound admission and reply; late completions stay observed. */
|
|
17
|
+
async function waitRequestReply(reply, operation, deadlineMs, signal, endWait, discardLateReply) {
|
|
18
|
+
let timer;
|
|
19
|
+
let waiting = reply;
|
|
20
|
+
if (deadlineMs !== undefined) {
|
|
21
|
+
const timeout = new Promise((_resolve, reject) => {
|
|
22
|
+
const remaining = remainingRequestTimeout(operation, deadlineMs);
|
|
23
|
+
timer = setTimeout(() => reject((0, framework_errors_internal_1.createInternalFrameworkException)(framework_errors_internal_1.ZLinkFrameworkInternalErrorKind.DeadlineExceeded, `${operation} exceeded its deadline.`)), remaining);
|
|
24
|
+
});
|
|
25
|
+
waiting = Promise.race([reply, timeout]);
|
|
26
|
+
}
|
|
27
|
+
try {
|
|
28
|
+
return await (0, abort_1.awaitWithAbort)(waiting, signal);
|
|
29
|
+
}
|
|
30
|
+
catch (error) {
|
|
31
|
+
endWait?.();
|
|
32
|
+
if (discardLateReply !== undefined)
|
|
33
|
+
void reply.then(discardLateReply, () => undefined);
|
|
34
|
+
throw error;
|
|
35
|
+
}
|
|
36
|
+
finally {
|
|
37
|
+
clearTimeout(timer);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
@@ -10,9 +10,10 @@ export declare enum ZLinkSubmitStatus {
|
|
|
10
10
|
export interface ZLinkSubmitResult {
|
|
11
11
|
readonly status: ZLinkSubmitStatus;
|
|
12
12
|
}
|
|
13
|
-
/** Projects
|
|
13
|
+
/** Projects immediate refusal and pending admission failure from their Core phase. */
|
|
14
14
|
export declare function submitToRequestResult(result: number, phase: 'submit' | 'completion'): number;
|
|
15
15
|
export declare function classifySubmitResult(result: number, operation: string, phase?: 'submit' | 'completion'): ZLinkSubmitResult;
|
|
16
16
|
export declare function requireOneWayCompletion(result: ZLinkSubmitResult, operation: string, notFoundKind?: ZLinkFrameworkInternalErrorKind): void;
|
|
17
17
|
export declare function requirePublishCompletion(result: ZLinkSubmitResult, operation: string): void;
|
|
18
|
+
export declare function requireClassicFanoutCompletion(result: ZLinkSubmitResult, operation: string): void;
|
|
18
19
|
export declare function throwAlreadySubmitted(operation: string): never;
|
|
@@ -5,6 +5,7 @@ exports.submitToRequestResult = submitToRequestResult;
|
|
|
5
5
|
exports.classifySubmitResult = classifySubmitResult;
|
|
6
6
|
exports.requireOneWayCompletion = requireOneWayCompletion;
|
|
7
7
|
exports.requirePublishCompletion = requirePublishCompletion;
|
|
8
|
+
exports.requireClassicFanoutCompletion = requireClassicFanoutCompletion;
|
|
8
9
|
exports.throwAlreadySubmitted = throwAlreadySubmitted;
|
|
9
10
|
const framework_errors_internal_1 = require("../framework-errors-internal");
|
|
10
11
|
const contracts_1 = require("../../contracts");
|
|
@@ -18,7 +19,7 @@ var ZLinkSubmitStatus;
|
|
|
18
19
|
ZLinkSubmitStatus["RouteNotConnected"] = "routeNotConnected";
|
|
19
20
|
ZLinkSubmitStatus["Shutdown"] = "shutdown";
|
|
20
21
|
})(ZLinkSubmitStatus || (exports.ZLinkSubmitStatus = ZLinkSubmitStatus = {}));
|
|
21
|
-
/** Projects
|
|
22
|
+
/** Projects immediate refusal and pending admission failure from their Core phase. */
|
|
22
23
|
function submitToRequestResult(result, phase) {
|
|
23
24
|
switch (result) {
|
|
24
25
|
case runtime_values_1.SubmitResult.Ok:
|
|
@@ -28,7 +29,7 @@ function submitToRequestResult(result, phase) {
|
|
|
28
29
|
case runtime_values_1.SubmitResult.NotConnected:
|
|
29
30
|
return runtime_values_1.RequestResult.NotConnected;
|
|
30
31
|
case runtime_values_1.SubmitResult.NotFound:
|
|
31
|
-
return runtime_values_1.RequestResult.NotFound;
|
|
32
|
+
return phase === 'submit' ? runtime_values_1.RequestResult.NotFound : runtime_values_1.RequestResult.NotConnected;
|
|
32
33
|
case runtime_values_1.SubmitResult.NotAdmitted:
|
|
33
34
|
return runtime_values_1.RequestResult.Rejected;
|
|
34
35
|
case runtime_values_1.SubmitResult.InvalidHandle:
|
|
@@ -45,7 +46,7 @@ function submitToRequestResult(result, phase) {
|
|
|
45
46
|
return runtime_values_1.RequestResult.InternalError;
|
|
46
47
|
}
|
|
47
48
|
}
|
|
48
|
-
function classifySubmitResult(result, operation, phase = '
|
|
49
|
+
function classifySubmitResult(result, operation, phase = 'submit') {
|
|
49
50
|
const terminal = submitToRequestResult(result, phase);
|
|
50
51
|
switch (terminal) {
|
|
51
52
|
case runtime_values_1.RequestResult.Ok:
|
|
@@ -67,8 +68,9 @@ function requireOneWayCompletion(result, operation, notFoundKind = framework_err
|
|
|
67
68
|
case ZLinkSubmitStatus.Submitted:
|
|
68
69
|
return;
|
|
69
70
|
case ZLinkSubmitStatus.TimedOut:
|
|
70
|
-
case ZLinkSubmitStatus.Backpressured:
|
|
71
71
|
throw (0, framework_errors_internal_1.createInternalFrameworkException)(framework_errors_internal_1.ZLinkFrameworkInternalErrorKind.DeadlineExceeded, `${operation} did not obtain admission before its deadline.`, true);
|
|
72
|
+
case ZLinkSubmitStatus.Backpressured:
|
|
73
|
+
throw (0, framework_errors_internal_1.createInternalFrameworkException)(framework_errors_internal_1.ZLinkFrameworkInternalErrorKind.RouteNotConnected, `${operation} has no admission wait token.`, true);
|
|
72
74
|
case ZLinkSubmitStatus.TargetNotFound:
|
|
73
75
|
throw (0, framework_errors_internal_1.createInternalFrameworkException)(notFoundKind, `${operation} target was not found.`);
|
|
74
76
|
case ZLinkSubmitStatus.RouteNotConnected:
|
|
@@ -80,6 +82,11 @@ function requireOneWayCompletion(result, operation, notFoundKind = framework_err
|
|
|
80
82
|
function requirePublishCompletion(result, operation) {
|
|
81
83
|
requireOneWayCompletion(result, operation);
|
|
82
84
|
}
|
|
85
|
+
function requireClassicFanoutCompletion(result, operation) {
|
|
86
|
+
requireOneWayCompletion(result.status === ZLinkSubmitStatus.Backpressured
|
|
87
|
+
? { status: ZLinkSubmitStatus.TimedOut }
|
|
88
|
+
: result, operation);
|
|
89
|
+
}
|
|
83
90
|
function throwAlreadySubmitted(operation) {
|
|
84
91
|
throw (0, framework_errors_internal_1.createInternalFrameworkException)(framework_errors_internal_1.ZLinkFrameworkInternalErrorKind.AlreadySubmitted, `${operation} has already been submitted.`);
|
|
85
92
|
}
|
|
@@ -48,7 +48,7 @@ export interface ZLinkSpotAddressCallOptions {
|
|
|
48
48
|
* activation. Public callers never handle an owner or generation fence.
|
|
49
49
|
*/
|
|
50
50
|
export interface ZLinkSpotAddressTransport {
|
|
51
|
-
sendToSpotAddress(spotId: RoutingId, message: unknown, options: ZLinkSpotAddressCallOptions): Promise<ZLinkSubmitResult>;
|
|
51
|
+
sendToSpotAddress(spotId: RoutingId, message: unknown, options: Omit<ZLinkSpotAddressCallOptions, 'timeoutMs' | 'signal'>): Promise<ZLinkSubmitResult>;
|
|
52
52
|
requestToSpotAddress<TReply = unknown>(spotId: RoutingId, request: unknown, options: ZLinkSpotAddressCallOptions): Promise<TReply>;
|
|
53
53
|
}
|
|
54
54
|
export interface ZLinkSpotRoutedTransport {
|
|
@@ -60,13 +60,11 @@ export interface ZLinkSpotRoutedTransport {
|
|
|
60
60
|
export interface ZLinkSpotRoutedSendOptions {
|
|
61
61
|
readonly instanceSpot?: boolean;
|
|
62
62
|
readonly packetName?: string;
|
|
63
|
-
/** Internal end-to-end budget remaining for route admission. */
|
|
64
|
-
readonly timeoutMs?: number;
|
|
65
|
-
readonly signal?: AbortSignal;
|
|
66
63
|
readonly metadata?: ReadonlyMap<string, string>;
|
|
67
64
|
}
|
|
68
65
|
export interface ZLinkSpotRoutedRequestOptions extends ZLinkSpotRoutedSendOptions {
|
|
69
66
|
readonly timeoutMs?: number;
|
|
67
|
+
readonly signal?: AbortSignal;
|
|
70
68
|
}
|
|
71
69
|
export interface ZLinkSpotHandleCallOptions {
|
|
72
70
|
readonly metadata?: ReadonlyMap<string, string>;
|
|
@@ -75,5 +73,5 @@ export interface ZLinkSpotHandleCallOptions {
|
|
|
75
73
|
readonly spotRouterChannelIdForMesh?: (meshName: string) => string;
|
|
76
74
|
readonly sourceSpot?: ZLinkBackendSpot;
|
|
77
75
|
}
|
|
78
|
-
export declare function sendToSpotHandle(transport: ZLinkSpotRoutedTransport, spot: SpotHandle, message: unknown, options?: ZLinkSpotHandleCallOptions): Promise<ZLinkSubmitResult>;
|
|
76
|
+
export declare function sendToSpotHandle(transport: ZLinkSpotRoutedTransport, spot: SpotHandle, message: unknown, options?: Omit<ZLinkSpotHandleCallOptions, 'timeoutMs' | 'signal'>): Promise<ZLinkSubmitResult>;
|
|
79
77
|
export declare function requestToSpotHandle<TReply = unknown>(transport: ZLinkSpotRoutedTransport, spot: SpotHandle, request: unknown, options?: ZLinkSpotHandleCallOptions): Promise<TReply>;
|
|
@@ -103,10 +103,10 @@ function createAddressedSpotSendCall(serial, transport, spotId, message, sourceS
|
|
|
103
103
|
options.initialMeshName = requireAddressValue(meshName, 'Mesh name', CoreTypes_1.ZLINK_MAX_MESH_NAME_BYTES);
|
|
104
104
|
return this;
|
|
105
105
|
},
|
|
106
|
-
async submit(
|
|
106
|
+
async submit() {
|
|
107
107
|
markSubmitted(options);
|
|
108
108
|
const pending = startRequestOnSerial(serial, () => ({
|
|
109
|
-
pending: transport.sendToSpotAddress(spotId, message, freezeAddressCallOptions(options,
|
|
109
|
+
pending: transport.sendToSpotAddress(spotId, message, freezeAddressCallOptions(options, sourceSpotProvider?.()))
|
|
110
110
|
}));
|
|
111
111
|
const result = await (serial.isCurrentTurn ? pending : (0, workers_1.deliverOnSerial)(serial, pending));
|
|
112
112
|
(0, submission_result_1.requireOneWayCompletion)(result, 'Spot send', framework_errors_internal_1.ZLinkFrameworkInternalErrorKind.SpotRouteNotFound);
|
|
@@ -119,7 +119,11 @@ function createAddressedSpotRequestCall(serial, transport, spotId, request, sour
|
|
|
119
119
|
markSubmitted(options);
|
|
120
120
|
rejectSameSpotAsyncRequest(serial, spotId, waitPolicy);
|
|
121
121
|
return startRequestOnSerial(serial, () => ({
|
|
122
|
-
pending: transport.requestToSpotAddress(spotId, request,
|
|
122
|
+
pending: transport.requestToSpotAddress(spotId, request, {
|
|
123
|
+
...freezeAddressCallOptions(options, sourceSpotProvider?.()),
|
|
124
|
+
timeoutMs: options.timeoutMs,
|
|
125
|
+
signal
|
|
126
|
+
})
|
|
123
127
|
}));
|
|
124
128
|
};
|
|
125
129
|
return {
|
|
@@ -200,14 +204,12 @@ function markSubmitted(options) {
|
|
|
200
204
|
}
|
|
201
205
|
options.submitted = true;
|
|
202
206
|
}
|
|
203
|
-
function freezeAddressCallOptions(options,
|
|
207
|
+
function freezeAddressCallOptions(options, sourceSpot) {
|
|
204
208
|
return {
|
|
205
209
|
...(options.metadataPresent ? { metadata: new Map(options.metadata) } : {}),
|
|
206
210
|
instanceSpot: options.instanceSpot,
|
|
207
211
|
instanceSpotType: options.instanceSpotType,
|
|
208
212
|
initialMeshName: options.initialMeshName,
|
|
209
|
-
timeoutMs: options.timeoutMs,
|
|
210
|
-
signal,
|
|
211
213
|
sourceSpot
|
|
212
214
|
};
|
|
213
215
|
}
|
|
@@ -227,8 +229,8 @@ function wrapSendCall(serial, inner) {
|
|
|
227
229
|
inner.metadata(key);
|
|
228
230
|
return this;
|
|
229
231
|
},
|
|
230
|
-
async submit(
|
|
231
|
-
const result = await runInternalTransportStart(serial, () => inner.submit(
|
|
232
|
+
async submit() {
|
|
233
|
+
const result = await runInternalTransportStart(serial, () => inner.submit());
|
|
232
234
|
return result;
|
|
233
235
|
}
|
|
234
236
|
};
|
|
@@ -302,11 +304,10 @@ function wrapRoutedSpotSendCall(serial, transport, spot, message, spotRouterChan
|
|
|
302
304
|
}
|
|
303
305
|
return this;
|
|
304
306
|
},
|
|
305
|
-
async submit(
|
|
307
|
+
async submit() {
|
|
306
308
|
const pending = startRequestOnSerial(serial, () => ({
|
|
307
309
|
pending: sendToSpotHandle(transport, spot, message, {
|
|
308
310
|
metadata,
|
|
309
|
-
signal,
|
|
310
311
|
spotRouterChannelIdForMesh,
|
|
311
312
|
sourceSpot: sourceSpotProvider?.()
|
|
312
313
|
})
|
|
@@ -376,19 +377,15 @@ async function sendToSpotHandle(transport, spot, message, options = {}) {
|
|
|
376
377
|
if (options.sourceSpot !== undefined && transport.sendFromSpotToSpot !== undefined) {
|
|
377
378
|
return transport.sendFromSpotToSpot(options.sourceSpot, target, message, {
|
|
378
379
|
packetName,
|
|
379
|
-
timeoutMs: options.timeoutMs,
|
|
380
|
-
signal: options.signal,
|
|
381
380
|
metadata: options.metadata
|
|
382
381
|
});
|
|
383
382
|
}
|
|
384
383
|
return transport.sendToSpot(target, message, {
|
|
385
384
|
packetName,
|
|
386
|
-
timeoutMs: options.timeoutMs,
|
|
387
|
-
signal: options.signal,
|
|
388
385
|
metadata: options.metadata
|
|
389
386
|
});
|
|
390
387
|
};
|
|
391
|
-
return sendResolved(await requireSpotRef(spot
|
|
388
|
+
return sendResolved(await requireSpotRef(spot));
|
|
392
389
|
}
|
|
393
390
|
async function requestToSpotHandle(transport, spot, request, options = {}) {
|
|
394
391
|
const packetName = (0, packet_name_1.resolveFrameworkPacketName)(request, undefined, 'SPOT');
|
|
@@ -96,7 +96,10 @@ class ZLinkSpotSerialExecutor {
|
|
|
96
96
|
this.throwIfClosing();
|
|
97
97
|
let executor = this.actorExecutors.get(actorId);
|
|
98
98
|
if (executor === undefined) {
|
|
99
|
-
executor =
|
|
99
|
+
executor =
|
|
100
|
+
this.executionMode === contracts_1.ZLinkUserSpotExecutionMode.SpotWide
|
|
101
|
+
? this.spotSerial.createActorExecutor(actorId, this.sourceSpotId, this.actorOptions)
|
|
102
|
+
: new actors_1.ZLinkActorSerialExecutor(actorId, this.sourceSpotId, this.actorOptions);
|
|
100
103
|
this.actorExecutors.set(actorId, executor);
|
|
101
104
|
}
|
|
102
105
|
return executor;
|
|
@@ -3,6 +3,7 @@ import type { SpotId } from '../../contracts';
|
|
|
3
3
|
import type { ZLinkFrameworkException } from '../../contracts/Errors/ZLinkFrameworkException';
|
|
4
4
|
import { type ZLinkSerialSchedulerOptions, type ZLinkSerialWorkOptions, type ZLinkSerialWorkRecord } from '../execution/serial-execution-queue';
|
|
5
5
|
import type { ZLinkSerialLifecycleContext } from '../execution/serial-execution-queue';
|
|
6
|
+
import { ZLinkActorSerialExecutor } from '../actors/actor-mailbox';
|
|
6
7
|
export type ZLinkSpotApplicationTurnContext = ZLinkExecutionBarrierClaim & {
|
|
7
8
|
readonly replay?: (failure?: unknown) => Promise<unknown> | unknown;
|
|
8
9
|
};
|
|
@@ -19,6 +20,8 @@ export declare class ZLinkSpotSerialTurnExecutor {
|
|
|
19
20
|
activeTurnId: number;
|
|
20
21
|
constructor(yieldAllowed?: boolean, sourceSpotId?: SpotId | undefined, schedulerOptions?: ZLinkSerialSchedulerOptions);
|
|
21
22
|
get isExecuting(): boolean;
|
|
23
|
+
/** Creates a passive Actor mailbox consumed by this Spot's scheduler. */
|
|
24
|
+
createActorExecutor(actorId: string, sourceSpotId: unknown, options?: ZLinkSerialSchedulerOptions): ZLinkActorSerialExecutor;
|
|
22
25
|
get isCurrentTurn(): boolean;
|
|
23
26
|
get hasPendingWork(): boolean;
|
|
24
27
|
get lastActivityAt(): number;
|
|
@@ -4,6 +4,7 @@ exports.ZLinkSpotSerialTurnExecutor = void 0;
|
|
|
4
4
|
const execution_1 = require("../execution");
|
|
5
5
|
const framework_errors_internal_1 = require("../framework-errors-internal");
|
|
6
6
|
const serial_execution_queue_1 = require("../execution/serial-execution-queue");
|
|
7
|
+
const actor_mailbox_1 = require("../actors/actor-mailbox");
|
|
7
8
|
const application_job_queue_scope_1 = require("../application-jobs/application-job-queue-scope");
|
|
8
9
|
class ZLinkSpotSerialTurnExecutor {
|
|
9
10
|
yieldAllowed;
|
|
@@ -24,6 +25,10 @@ class ZLinkSpotSerialTurnExecutor {
|
|
|
24
25
|
get isExecuting() {
|
|
25
26
|
return this.depth > 0;
|
|
26
27
|
}
|
|
28
|
+
/** Creates a passive Actor mailbox consumed by this Spot's scheduler. */
|
|
29
|
+
createActorExecutor(actorId, sourceSpotId, options) {
|
|
30
|
+
return new actor_mailbox_1.ZLinkActorSerialExecutor(actorId, sourceSpotId, options, this.scheduler);
|
|
31
|
+
}
|
|
27
32
|
get isCurrentTurn() {
|
|
28
33
|
return this.depth > 0 && (0, execution_1.isCurrentZLinkSpotSerialTurn)(this);
|
|
29
34
|
}
|
|
@@ -12,7 +12,7 @@ export interface ZLinkBoundActorRelaySenderOptions {
|
|
|
12
12
|
readonly dispatchErrors?: ZLinkDispatchErrorReporter;
|
|
13
13
|
readonly actorBindTimeoutMs?: number;
|
|
14
14
|
readonly messageSerializers?: ReadonlyMap<string, ZLinkMessageSerializer>;
|
|
15
|
-
readonly relay?: (actor: ZLinkSessionActor, header: ZLinkStreamFrameHeader, payload: Message
|
|
15
|
+
readonly relay?: (actor: ZLinkSessionActor, header: ZLinkStreamFrameHeader, payload: Message) => Promise<boolean>;
|
|
16
16
|
readonly notifyDisconnected?: (actor: ZLinkSessionActor, signal?: AbortSignal) => Promise<void>;
|
|
17
17
|
}
|
|
18
18
|
export declare class ZLinkBoundActorRelaySender {
|
|
@@ -21,7 +21,7 @@ export declare class ZLinkBoundActorRelaySender {
|
|
|
21
21
|
private readonly options;
|
|
22
22
|
private readonly lifecycle;
|
|
23
23
|
constructor(routes: ZLinkActorSessionBindingRegistry<DefaultZLinkSessionContext, DefaultZLinkSessionActor>, frameMessages: ZLinkStreamFrameMessageFactory, options?: ZLinkBoundActorRelaySenderOptions, lifecycle?: ZLinkActorSessionLifecycleCoordinator);
|
|
24
|
-
relay(actor: DefaultZLinkSessionActor, payload: ZLinkMessage,
|
|
24
|
+
relay(actor: DefaultZLinkSessionActor, payload: ZLinkMessage, dispatchHeader?: ZLinkStreamFrameHeader): Promise<ZLinkSubmitResult>;
|
|
25
25
|
private traceHeldDrop;
|
|
26
26
|
private relayAcceptedFrame;
|
|
27
27
|
private currentHeader;
|