@zlink-systems/framework 0.28.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/Configuration/Builders.d.ts +2 -0
- 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 -0
- package/dist/runtime/actors/actor-mailbox.d.ts +2 -2
- package/dist/runtime/actors/actor-mailbox.js +2 -2
- package/dist/runtime/backend/node/node-raw-mesh-backend.js +1 -3
- 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/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/instance-activation-authority.d.ts +0 -1
- package/dist/runtime/host/instance-activation-authority.js +46 -97
- package/dist/runtime/host/spot-address-transport.js +1 -1
- 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 +92 -49
- 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/index.d.ts +0 -1
- package/dist/runtime/streams/index.js +4 -3
- package/dist/runtime/streams/protocol.js +0 -9
- package/dist/runtime/streams/session-context.d.ts +0 -4
- package/dist/runtime/streams/session-context.js +0 -26
- 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/Configuration/Builders.ts +2 -0
- package/src/contracts/Configuration/InternalDefaults.ts +4 -0
- package/src/contracts/Configuration/RegistrationBuilders.ts +13 -0
- package/src/contracts/Configuration/RegistrationNormalizers.ts +25 -0
- package/src/contracts/Configuration/RegistrationTypes.ts +3 -0
- package/src/runtime/actors/actor-mailbox.ts +7 -2
- package/src/runtime/backend/node/node-raw-mesh-backend.ts +1 -7
- package/src/runtime/execution/serial-execution-queue.ts +117 -29
- package/src/runtime/foundation/operation-registry.ts +16 -9
- 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/instance-activation-authority.ts +58 -125
- package/src/runtime/host/spot-address-transport.ts +1 -1
- 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 +123 -64
- package/src/runtime/protocol/service_wire_pilot_codec.generated.ts +1 -1
- 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/index.ts +3 -1
- package/src/runtime/streams/protocol.ts +0 -13
- package/src/runtime/streams/session-context.ts +0 -32
- 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
|
@@ -11,7 +11,6 @@ const relocation_blob_1 = require("../locations/relocation-blob");
|
|
|
11
11
|
const service_instance_activation_recovery_codec_1 = require("../foundation/service-instance-activation-recovery-codec");
|
|
12
12
|
const CREATION_REQUEST_RETENTION_MS = 24 * 60 * 60 * 1_000;
|
|
13
13
|
const MAX_CREATION_REQUEST_BYTES = 1024 * 1024;
|
|
14
|
-
const ACTIVATION_JOIN_POLL_INTERVAL_MS = 10;
|
|
15
14
|
class ZLinkInstanceActivationAuthority {
|
|
16
15
|
options;
|
|
17
16
|
pending = new Map();
|
|
@@ -48,68 +47,64 @@ class ZLinkInstanceActivationAuthority {
|
|
|
48
47
|
}
|
|
49
48
|
let reserved;
|
|
50
49
|
try {
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
50
|
+
reserved = await this.options.store.reserve({
|
|
51
|
+
key: { kind: 'instance_spot', globalId: target.targetSpotId },
|
|
52
|
+
intent: {
|
|
53
|
+
stableType: target.stableType,
|
|
54
|
+
requestContentReference: stored.reference.value,
|
|
55
|
+
requestSha256: requestHash,
|
|
56
|
+
requestEncodedSize: BigInt(requestBytes.byteLength)
|
|
57
|
+
},
|
|
58
|
+
target: {
|
|
59
|
+
meshName: this.options.meshName,
|
|
60
|
+
nodeRid: target.targetNodeRid,
|
|
61
|
+
nodeLifecycleGeneration: target.targetNodeGeneration,
|
|
62
|
+
owner
|
|
63
|
+
},
|
|
64
|
+
creatingPayload: (0, service_authority_payload_codec_1.encodeServiceInstanceAuthorityPayload)({
|
|
65
|
+
state: 'coldActivating',
|
|
66
|
+
stableType: target.stableType,
|
|
67
|
+
spotId: target.targetSpotId,
|
|
68
|
+
ownerId: owner.ownerId,
|
|
69
|
+
ownerLeaseGeneration: owner.leaseGeneration,
|
|
70
|
+
ownerMeshName: this.options.meshName,
|
|
71
|
+
ownerNodeRid: target.targetNodeRid,
|
|
72
|
+
ownerNodeGeneration: target.targetNodeGeneration
|
|
73
|
+
}),
|
|
74
|
+
capacity: {
|
|
75
|
+
actors: 0,
|
|
76
|
+
spots: 1,
|
|
77
|
+
spotType: {
|
|
78
|
+
objectKind: 'instance_spot',
|
|
68
79
|
stableType: target.stableType,
|
|
69
|
-
|
|
70
|
-
ownerId: owner.ownerId,
|
|
71
|
-
ownerLeaseGeneration: owner.leaseGeneration,
|
|
72
|
-
ownerMeshName: this.options.meshName,
|
|
73
|
-
ownerNodeRid: target.targetNodeRid,
|
|
74
|
-
ownerNodeGeneration: target.targetNodeGeneration
|
|
75
|
-
}),
|
|
76
|
-
capacity: {
|
|
77
|
-
actors: 0,
|
|
78
|
-
spots: 1,
|
|
79
|
-
spotType: {
|
|
80
|
-
objectKind: 'instance_spot',
|
|
81
|
-
stableType: target.stableType,
|
|
82
|
-
count: 1
|
|
83
|
-
}
|
|
80
|
+
count: 1
|
|
84
81
|
}
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
break;
|
|
88
|
-
this.options.metrics?.recordInstanceSpotClaimConflict(this.options.meshName, target.stableType, 'already_exists');
|
|
89
|
-
await this.deleteOrphan(stored.reference);
|
|
90
|
-
return readyExisting(reserved.current, target);
|
|
91
|
-
}
|
|
82
|
+
}
|
|
83
|
+
}, undefined, activation.deadlineUnixMs);
|
|
92
84
|
}
|
|
93
85
|
catch (error) {
|
|
94
86
|
await this.deleteOrphan(stored.reference);
|
|
95
87
|
throw error;
|
|
96
88
|
}
|
|
97
|
-
if (reserved.kind === 'conflict' &&
|
|
98
|
-
reserved.current.kind === 'snapshot' &&
|
|
99
|
-
reserved.current.allocation.objectKind === 'instance_spot' &&
|
|
100
|
-
reserved.current.allocation.stableType === target.stableType &&
|
|
101
|
-
reserved.current.allocation.state === 'reserved') {
|
|
102
|
-
this.options.metrics?.recordInstanceSpotClaimConflict(this.options.meshName, target.stableType, 'activation_in_progress');
|
|
103
|
-
await this.deleteOrphan(stored.reference);
|
|
104
|
-
return await this.awaitConcurrentActivation(target, activation.deadlineUnixMs);
|
|
105
|
-
}
|
|
106
89
|
if (reserved.kind !== 'reserved') {
|
|
107
|
-
|
|
90
|
+
const conflictReason = reserved.kind === 'alreadyExists'
|
|
91
|
+
? 'already_exists'
|
|
92
|
+
: reserved.kind === 'conflict' &&
|
|
93
|
+
reserved.current.kind === 'snapshot' &&
|
|
94
|
+
reserved.current.allocation.objectKind === 'instance_spot' &&
|
|
95
|
+
reserved.current.allocation.stableType === target.stableType &&
|
|
96
|
+
reserved.current.allocation.state === 'reserved'
|
|
97
|
+
? 'activation_in_progress'
|
|
98
|
+
: reserved.kind;
|
|
99
|
+
this.options.metrics?.recordInstanceSpotClaimConflict(this.options.meshName, target.stableType, conflictReason);
|
|
108
100
|
await this.deleteOrphan(stored.reference);
|
|
101
|
+
if (reserved.kind === 'typeMismatch') {
|
|
102
|
+
throw (0, framework_errors_internal_1.createInternalFrameworkException)(framework_errors_internal_1.ZLinkFrameworkInternalErrorKind.SpotTypeMismatch, `Instance activation reservation failed: ${reserved.kind}.`);
|
|
103
|
+
}
|
|
109
104
|
if (reserved.kind === 'placementCapacityExhausted') {
|
|
110
105
|
throw (0, framework_errors_internal_1.createInternalFrameworkException)(framework_errors_internal_1.ZLinkFrameworkInternalErrorKind.PlacementCapacityExhausted, `Instance Spot placement capacity is exhausted for '${String(target.targetSpotId)}'.`);
|
|
111
106
|
}
|
|
112
|
-
throw new
|
|
107
|
+
throw new contracts_1.ZLinkFrameworkException(contracts_1.ZLinkFrameworkErrorKind.Unavailable, `Instance activation reservation failed: ${reserved.kind}.`);
|
|
113
108
|
}
|
|
114
109
|
const reservation = {
|
|
115
110
|
attempt: reserved.creating.objectGeneration,
|
|
@@ -334,27 +329,6 @@ class ZLinkInstanceActivationAuthority {
|
|
|
334
329
|
// best-effort deletion fails.
|
|
335
330
|
}
|
|
336
331
|
}
|
|
337
|
-
async awaitConcurrentActivation(target, deadlineUnixMs) {
|
|
338
|
-
const key = authorityKey(target.targetSpotId);
|
|
339
|
-
const deadlineMs = performance.now() + Number(deadlineUnixMs - BigInt(Date.now()));
|
|
340
|
-
while (performance.now() <= deadlineMs) {
|
|
341
|
-
const current = await this.options.store.readAuthority(key);
|
|
342
|
-
if (current.kind === 'snapshot') {
|
|
343
|
-
if (current.allocation.objectKind !== 'instance_spot' ||
|
|
344
|
-
current.allocation.stableType !== target.stableType) {
|
|
345
|
-
throw new Error('Concurrent Instance activation resolved to a different Spot type.');
|
|
346
|
-
}
|
|
347
|
-
if (current.allocation.state === 'active') {
|
|
348
|
-
return readyExisting(current, target);
|
|
349
|
-
}
|
|
350
|
-
}
|
|
351
|
-
else {
|
|
352
|
-
throw new Error('Concurrent Instance activation ended before the Ready barrier.');
|
|
353
|
-
}
|
|
354
|
-
await waitForActivationJoin(deadlineMs);
|
|
355
|
-
}
|
|
356
|
-
throw new Error(`Concurrent Instance activation for '${target.targetSpotId}' did not reach Ready before deadline.`);
|
|
357
|
-
}
|
|
358
332
|
requirePending(reservation) {
|
|
359
333
|
const pending = this.pending.get(reservation.token);
|
|
360
334
|
if (pending === undefined || pending.creating.objectGeneration !== reservation.attempt) {
|
|
@@ -402,31 +376,6 @@ function readyRead(snapshot, target) {
|
|
|
402
376
|
}
|
|
403
377
|
return { kind: 'ready', route: routeFromSnapshot(snapshot), authority: snapshot };
|
|
404
378
|
}
|
|
405
|
-
function readyExisting(snapshot, target) {
|
|
406
|
-
const decoded = (0, service_authority_payload_codec_1.decodeServiceReadySpotAuthority)(snapshot.payload) ??
|
|
407
|
-
(0, service_authority_payload_codec_1.decodeServiceClosingSpotAuthority)(snapshot.payload);
|
|
408
|
-
if (decoded?.kind !== 'instance_spot' ||
|
|
409
|
-
decoded.stableType !== target.stableType ||
|
|
410
|
-
decoded.spotId !== target.targetSpotId ||
|
|
411
|
-
snapshot.allocation.objectKind !== 'instance_spot' ||
|
|
412
|
-
snapshot.allocation.state !== 'active' ||
|
|
413
|
-
decoded.ownerId !== snapshot.ownerId ||
|
|
414
|
-
decoded.ownerLeaseGeneration !== snapshot.ownerLeaseGeneration ||
|
|
415
|
-
decoded.ownerMeshName !== snapshot.allocation.descriptor.meshName ||
|
|
416
|
-
decoded.ownerNodeGeneration !== snapshot.allocation.descriptorLifecycleGeneration ||
|
|
417
|
-
!(0, routing_id_1.routingIdsEqual)(decoded.ownerNodeRid, snapshot.allocation.descriptor.rid)) {
|
|
418
|
-
throw new Error('Existing Instance authority is not a matching Ready allocation.');
|
|
419
|
-
}
|
|
420
|
-
return { kind: 'ready', route: routeFromSnapshot(snapshot), authority: snapshot };
|
|
421
|
-
}
|
|
422
|
-
async function waitForActivationJoin(deadlineMs) {
|
|
423
|
-
const remaining = deadlineMs - performance.now();
|
|
424
|
-
if (remaining <= 0)
|
|
425
|
-
return;
|
|
426
|
-
await new Promise((resolve) => {
|
|
427
|
-
setTimeout(resolve, Math.min(ACTIVATION_JOIN_POLL_INTERVAL_MS, remaining));
|
|
428
|
-
});
|
|
429
|
-
}
|
|
430
379
|
function requireCommitIdentity(target, reservation, creating, spot, meshName) {
|
|
431
380
|
if (creating.allocation.state !== 'reserved' ||
|
|
432
381
|
creating.allocation.objectKind !== 'instance_spot' ||
|
|
@@ -254,7 +254,7 @@ class ZLinkHostSpotAddressTransport {
|
|
|
254
254
|
if (stableType === undefined) {
|
|
255
255
|
if (distinctTypes.length === 0)
|
|
256
256
|
return { kind: 'unsupported' };
|
|
257
|
-
throw (0, framework_errors_internal_1.createInternalFrameworkException)(framework_errors_internal_1.ZLinkFrameworkInternalErrorKind.
|
|
257
|
+
throw (0, framework_errors_internal_1.createInternalFrameworkException)(framework_errors_internal_1.ZLinkFrameworkInternalErrorKind.InvalidOperation, 'Instance Spot type is required when multiple types are registered.');
|
|
258
258
|
}
|
|
259
259
|
if (canInspectPlacementTypes && !distinctTypes.includes(stableType)) {
|
|
260
260
|
return { kind: 'unsupported' };
|
|
@@ -28,6 +28,7 @@ export declare class ZLinkStatefulAuthorityRouteRuntime {
|
|
|
28
28
|
reconcile(signal?: AbortSignal, requireComplete?: boolean): Promise<void>;
|
|
29
29
|
private recoverInstanceActivation;
|
|
30
30
|
private recoverPendingInstanceActivation;
|
|
31
|
+
private clearRecoveryRoot;
|
|
31
32
|
private readRecoveryEnvelope;
|
|
32
33
|
private run;
|
|
33
34
|
private readCompleteSnapshot;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.ZLinkStatefulAuthorityRouteRuntime = void 0;
|
|
4
|
+
const authority_key_codec_1 = require("../locations/authority-key-codec");
|
|
4
5
|
const node_crypto_1 = require("node:crypto");
|
|
5
6
|
const relocation_blob_1 = require("../locations/relocation-blob");
|
|
6
7
|
const routing_id_1 = require("../routing-id");
|
|
@@ -65,11 +66,19 @@ class ZLinkStatefulAuthorityRouteRuntime {
|
|
|
65
66
|
const previous = this.appliedByMesh.get(meshName) ?? new Map();
|
|
66
67
|
const status = sink.status();
|
|
67
68
|
for (const pending of snapshot.pending) {
|
|
68
|
-
if (pending.targetMeshName
|
|
69
|
-
|
|
69
|
+
if (pending.targetMeshName !== meshName)
|
|
70
|
+
continue;
|
|
71
|
+
if ((0, routing_id_1.routingIdsEqual)(status.routingId, pending.targetNodeRid) &&
|
|
70
72
|
status.lifecycleGeneration === pending.targetNodeGeneration) {
|
|
71
73
|
await this.recoverPendingInstanceActivation(sink, pending, signal);
|
|
72
74
|
}
|
|
75
|
+
else {
|
|
76
|
+
const release = this.options.creationStore?.releaseEndedReservation;
|
|
77
|
+
if (release === undefined)
|
|
78
|
+
throw new Error('Reservation lifecycle recovery requires a Location repository.');
|
|
79
|
+
if (await release.call(this.options.creationStore, (0, authority_key_codec_1.encodeAuthorityKey)('instance_spot', pending.spotId), pending.pending.storeVersion, signal))
|
|
80
|
+
await this.clearRecoveryRoot(pending.pending.requestReference, signal);
|
|
81
|
+
}
|
|
73
82
|
}
|
|
74
83
|
for (const [key, route] of current) {
|
|
75
84
|
if (route.meshName !== meshName)
|
|
@@ -207,19 +216,18 @@ class ZLinkStatefulAuthorityRouteRuntime {
|
|
|
207
216
|
}
|
|
208
217
|
}, signal);
|
|
209
218
|
if (aborted.kind === 'aborted' || aborted.kind === 'alreadyAborted') {
|
|
210
|
-
|
|
211
|
-
await this.options.relocationStore?.delete((0, relocation_blob_1.relocationBlobReference)(recovery.pending.requestReference));
|
|
212
|
-
}
|
|
213
|
-
catch {
|
|
214
|
-
// The authority no longer publishes this root. Retention owns a
|
|
215
|
-
// failed best-effort orphan cleanup.
|
|
216
|
-
}
|
|
219
|
+
await this.clearRecoveryRoot(recovery.pending.requestReference, signal);
|
|
217
220
|
}
|
|
218
221
|
return;
|
|
219
222
|
}
|
|
220
223
|
if ((await sink.recoverPendingInstanceActivation(envelope, recovery.pending, null)) === false)
|
|
221
224
|
return;
|
|
222
225
|
}
|
|
226
|
+
async clearRecoveryRoot(reference, signal) {
|
|
227
|
+
if (this.options.relocationStore === undefined)
|
|
228
|
+
throw new Error('Instance activation recovery requires a Relocation Store.');
|
|
229
|
+
await this.options.relocationStore.delete((0, relocation_blob_1.relocationBlobReference)(reference), signal);
|
|
230
|
+
}
|
|
223
231
|
async readRecoveryEnvelope(recovery, signal) {
|
|
224
232
|
const relocationStore = this.options.relocationStore;
|
|
225
233
|
if (relocationStore === undefined) {
|
|
@@ -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.
|
|
814
|
-
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)) {
|
|
888
|
+
if (!(await this.releaseEndedReservation(encodedAuthorityKey, current.value.version.value, signal)))
|
|
832
889
|
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([
|
|
@@ -2942,10 +2977,9 @@ function sameCreationTarget(snapshot, target) {
|
|
|
2942
2977
|
snapshot.ownerId === target.owner.ownerId &&
|
|
2943
2978
|
snapshot.ownerLeaseGeneration === target.owner.leaseGeneration);
|
|
2944
2979
|
}
|
|
2945
|
-
const
|
|
2946
|
-
function
|
|
2947
|
-
return (payload
|
|
2948
|
-
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;
|
|
2949
2983
|
}
|
|
2950
2984
|
function sameLiveOwner(lease, snapshot) {
|
|
2951
2985
|
if (lease.kind === 'missing')
|
|
@@ -3239,3 +3273,12 @@ function throwIfOperationExpired(signal, deadlineUnixMs) {
|
|
|
3239
3273
|
throw new DOMException('Operation deadline exceeded.', 'TimeoutError');
|
|
3240
3274
|
}
|
|
3241
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
|
+
}
|
|
@@ -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
|
}
|
|
@@ -16,7 +16,6 @@ import { ZLinkStreamCodec, ZLinkStreamMessageKind, type ZLinkStreamFrameHeader,
|
|
|
16
16
|
import { DefaultZLinkSessionActor, DefaultZLinkSessionContext } from './session-context';
|
|
17
17
|
import type { ZLinkActorRouteCommitOptions, ZLinkSessionBindingConfirmationOptions, ZLinkSessionBindingIdentity } from './stream-binding-runtime-ports';
|
|
18
18
|
import { ZLinkStreamSessionNodeRuntime as ZLinkStreamSessionNodeRuntimeCore, ZLinkStreamSessionRuntime as ZLinkStreamSessionRuntimeCore, type ZLinkStreamSessionNodeRuntimeOptions as ZLinkStreamSessionNodeRuntimeCoreOptions, type ZLinkStreamSessionRuntimeOptions as ZLinkStreamSessionRuntimeCoreOptions } from './stream-session-runtime';
|
|
19
|
-
export { ZLinkPendingSessionRequest } from './session-requests';
|
|
20
19
|
export { ZLinkActorSessionLifecycleCoordinator } from './actor-session-lifecycle-coordinator';
|
|
21
20
|
export { ZLinkActorSessionBindingRegistry } from './actor-session-binding-registry';
|
|
22
21
|
export { zlinkStreamLz4CompressionCodec } from './stream-frame-factory';
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.ZLinkStreamBindingRuntime = exports.ZLinkStreamSessionNodeRuntime = exports.ZLinkStreamSessionRuntime = exports.ZLinkStreamRuntimeManager = exports.DefaultZLinkSessionContext = exports.DefaultZLinkSessionActor = exports.DefaultZLinkBoundSessionFactory = exports.DefaultZLinkBoundSession = exports.ZLinkManagedStream = exports.zlinkStreamLz4CompressionCodec = exports.ZLinkActorSessionBindingRegistry = exports.ZLinkActorSessionLifecycleCoordinator =
|
|
3
|
+
exports.ZLinkStreamBindingRuntime = exports.ZLinkStreamSessionNodeRuntime = exports.ZLinkStreamSessionRuntime = exports.ZLinkStreamRuntimeManager = exports.DefaultZLinkSessionContext = exports.DefaultZLinkSessionActor = exports.DefaultZLinkBoundSessionFactory = exports.DefaultZLinkBoundSession = exports.ZLinkManagedStream = exports.zlinkStreamLz4CompressionCodec = exports.ZLinkActorSessionBindingRegistry = exports.ZLinkActorSessionLifecycleCoordinator = void 0;
|
|
4
4
|
const InternalDefaults_1 = require("../../contracts/Configuration/InternalDefaults");
|
|
5
5
|
const Options_1 = require("../../contracts/Locations/Options");
|
|
6
6
|
const configuration_1 = require("../configuration");
|
|
@@ -20,8 +20,6 @@ const stream_frame_factory_1 = require("./stream-frame-factory");
|
|
|
20
20
|
const stream_message_utils_1 = require("./stream-message-utils");
|
|
21
21
|
const stream_session_runtime_1 = require("./stream-session-runtime");
|
|
22
22
|
const DEFAULT_STREAM_SERVICE_SHUTDOWN_TIMEOUT_MS = 1000;
|
|
23
|
-
var session_requests_1 = require("./session-requests");
|
|
24
|
-
Object.defineProperty(exports, "ZLinkPendingSessionRequest", { enumerable: true, get: function () { return session_requests_1.ZLinkPendingSessionRequest; } });
|
|
25
23
|
var actor_session_lifecycle_coordinator_2 = require("./actor-session-lifecycle-coordinator");
|
|
26
24
|
Object.defineProperty(exports, "ZLinkActorSessionLifecycleCoordinator", { enumerable: true, get: function () { return actor_session_lifecycle_coordinator_2.ZLinkActorSessionLifecycleCoordinator; } });
|
|
27
25
|
var actor_session_binding_registry_2 = require("./actor-session-binding-registry");
|
|
@@ -116,6 +114,9 @@ class ZLinkStreamRuntimeManager {
|
|
|
116
114
|
const readablePoller = streamAdapter.createReadablePoller(socket);
|
|
117
115
|
const runtime = new stream_session_runtime_1.ZLinkStreamSessionNodeRuntime({
|
|
118
116
|
nodeName,
|
|
117
|
+
heartbeatIntervalMs: streamNode.heartbeatIntervalMs,
|
|
118
|
+
heartbeatTimeoutMs: streamNode.heartbeatTimeoutMs,
|
|
119
|
+
idleTimeoutMs: streamNode.idleTimeoutMs,
|
|
119
120
|
socket,
|
|
120
121
|
createPacket: () => streamAdapter.createStreamPacket(),
|
|
121
122
|
readablePoller,
|