@zlink-systems/framework 0.10.0 → 0.12.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/EndpointNotation.d.ts +5 -4
- package/dist/contracts/Configuration/EndpointNotation.js +5 -4
- package/dist/contracts/Configuration/InternalDefaults.d.ts +0 -1
- package/dist/contracts/Configuration/InternalDefaults.js +1 -2
- package/dist/contracts/Configuration/RegistrationNormalizers.js +1 -2
- package/dist/contracts/Configuration/RegistrationTypes.d.ts +2 -5
- package/dist/contracts/Configuration/RegistrationValidators.js +0 -1
- package/dist/contracts/Errors/ZLinkFrameworkException.d.ts +6 -7
- package/dist/contracts/Errors/ZLinkFrameworkException.js +6 -7
- package/dist/runtime/actors/actor-client.js +1 -1
- package/dist/runtime/actors/actor-mailbox.js +1 -5
- package/dist/runtime/backend/contracts/index.d.ts +2 -0
- package/dist/runtime/backend/mesh-completion-table.d.ts +1 -3
- package/dist/runtime/backend/mesh-completion-table.js +11 -15
- package/dist/runtime/backend/mesh-dispatch-pump.d.ts +11 -4
- package/dist/runtime/backend/mesh-dispatch-pump.js +201 -134
- package/dist/runtime/backend/node/node-backend-adapter-factory.d.ts +3 -4
- package/dist/runtime/backend/node/node-backend-adapter-factory.js +51 -37
- package/dist/runtime/backend/node/node-backend-adapter-support.d.ts +2 -2
- package/dist/runtime/backend/node/node-backend-adapter-support.js +2 -2
- package/dist/runtime/backend/node/node-dealer-channel-client-transport.js +2 -2
- package/dist/runtime/backend/node/node-event-loop-poller.d.ts +16 -0
- package/dist/runtime/backend/node/node-event-loop-poller.js +49 -0
- package/dist/runtime/backend/node/node-raw-binding-port.js +24 -41
- package/dist/runtime/backend/node/node-raw-mesh-backend.d.ts +8 -8
- package/dist/runtime/backend/node/node-raw-mesh-backend.js +100 -107
- package/dist/runtime/backend/node/node-socket-backend-adapter.d.ts +3 -2
- package/dist/runtime/backend/node/node-socket-backend-adapter.js +18 -67
- package/dist/runtime/backend/raw-binding-port.d.ts +1 -0
- package/dist/runtime/backend/runtime-values.d.ts +6 -1
- package/dist/runtime/backend/runtime-values.js +6 -0
- package/dist/runtime/channels/channel-dispatchers.js +2 -2
- package/dist/runtime/channels/channel-envelope.js +324 -121
- package/dist/runtime/channels/channel-multipart.d.ts +8 -1
- package/dist/runtime/channels/channel-outbound-operations.js +0 -2
- package/dist/runtime/channels/channel-receive-loops.d.ts +1 -3
- package/dist/runtime/channels/channel-receive-loops.js +25 -65
- package/dist/runtime/channels/channel-socket-registry.js +14 -1
- package/dist/runtime/channels/channel-transports.d.ts +2 -1
- package/dist/runtime/channels/channel-transports.js +12 -10
- package/dist/runtime/channels/client-server-location-runtime.js +15 -3
- package/dist/runtime/execution/serial-execution-queue.d.ts +5 -18
- package/dist/runtime/execution/serial-execution-queue.js +16 -80
- package/dist/runtime/foundation/event-loop-resources.d.ts +0 -3
- package/dist/runtime/foundation/event-loop-resources.js +2 -11
- package/dist/runtime/foundation/operation-registry.d.ts +2 -8
- package/dist/runtime/foundation/operation-registry.js +3 -21
- package/dist/runtime/foundation/raw-service-mesh-runtime.d.ts +19 -7
- package/dist/runtime/foundation/raw-service-mesh-runtime.js +56 -10
- package/dist/runtime/foundation/service-mailbox.d.ts +1 -7
- package/dist/runtime/foundation/service-mailbox.js +3 -2
- package/dist/runtime/foundation/service-runtime-contracts.d.ts +2 -1
- package/dist/runtime/foundation/service-stateful-registry.d.ts +1 -1
- package/dist/runtime/foundation/service-stateful-registry.js +2 -2
- package/dist/runtime/foundation/service-stateful-runtime.js +14 -14
- package/dist/runtime/framework-errors-internal.d.ts +4 -4
- package/dist/runtime/framework-errors-internal.js +8 -10
- package/dist/runtime/host/actor-placement-coordinator.js +1 -1
- package/dist/runtime/host/index.js +1 -1
- package/dist/runtime/host/service-relocation-host-runtime.js +0 -4
- package/dist/runtime/host/spot-address-transport.js +1 -1
- package/dist/runtime/host/user-spot-creation-coordinator.js +1 -1
- package/dist/runtime/locations/location-store-repository.d.ts +1 -0
- package/dist/runtime/locations/location-store-repository.js +64 -75
- package/dist/runtime/spots/spot-node-runtime-manager.d.ts +0 -12
- package/dist/runtime/spots/spot-node-runtime-manager.js +6 -166
- package/dist/runtime/spots/spot-serial-turn-executor.js +1 -4
- package/dist/runtime/spots/spot-timer.d.ts +3 -0
- package/dist/runtime/spots/spot-timer.js +87 -18
- package/dist/runtime/streams/session-serial-executor.js +1 -3
- package/dist/runtime/streams/stream-session-runtime.d.ts +2 -2
- package/dist/runtime/streams/stream-session-runtime.js +13 -19
- package/dist/runtime/workers/index.d.ts +0 -1
- package/dist/runtime/workers/index.js +1 -9
- package/package.json +9 -3
- package/src/contracts/Configuration/EndpointNotation.ts +5 -4
- package/src/contracts/Configuration/InternalDefaults.ts +0 -1
- package/src/contracts/Configuration/RegistrationNormalizers.ts +2 -4
- package/src/contracts/Configuration/RegistrationTypes.ts +2 -5
- package/src/contracts/Configuration/RegistrationValidators.ts +0 -1
- package/src/contracts/Errors/ZLinkFrameworkException.ts +6 -7
- package/src/runtime/actors/actor-client.ts +1 -1
- package/src/runtime/actors/actor-mailbox.ts +1 -12
- package/src/runtime/backend/contracts/index.ts +2 -0
- package/src/runtime/backend/mesh-completion-table.ts +12 -23
- package/src/runtime/backend/mesh-dispatch-pump.ts +206 -138
- package/src/runtime/backend/node/node-backend-adapter-factory.ts +66 -35
- package/src/runtime/backend/node/node-backend-adapter-support.ts +4 -4
- package/src/runtime/backend/node/node-dealer-channel-client-transport.ts +2 -2
- package/src/runtime/backend/node/node-event-loop-poller.ts +55 -0
- package/src/runtime/backend/node/node-raw-binding-port.ts +30 -45
- package/src/runtime/backend/node/node-raw-mesh-backend.ts +97 -110
- package/src/runtime/backend/node/node-socket-backend-adapter.ts +23 -69
- package/src/runtime/backend/raw-binding-port.ts +1 -0
- package/src/runtime/backend/runtime-values.ts +13 -1
- package/src/runtime/channels/channel-dispatchers.ts +2 -2
- package/src/runtime/channels/channel-envelope.ts +379 -109
- package/src/runtime/channels/channel-multipart.ts +9 -1
- package/src/runtime/channels/channel-outbound-operations.ts +0 -1
- package/src/runtime/channels/channel-receive-loops.ts +24 -75
- package/src/runtime/channels/channel-socket-registry.ts +17 -1
- package/src/runtime/channels/channel-transports.ts +20 -10
- package/src/runtime/channels/client-server-location-runtime.ts +16 -2
- package/src/runtime/execution/serial-execution-queue.ts +16 -108
- package/src/runtime/foundation/event-loop-resources.ts +2 -11
- package/src/runtime/foundation/operation-registry.ts +2 -22
- package/src/runtime/foundation/raw-service-mesh-runtime.ts +74 -19
- package/src/runtime/foundation/service-mailbox.ts +3 -13
- package/src/runtime/foundation/service-runtime-contracts.ts +2 -1
- package/src/runtime/foundation/service-stateful-registry.ts +2 -2
- package/src/runtime/foundation/service-stateful-runtime.ts +14 -14
- package/src/runtime/framework-errors-internal.ts +8 -10
- package/src/runtime/host/actor-placement-coordinator.ts +1 -1
- package/src/runtime/host/index.ts +2 -1
- package/src/runtime/host/service-relocation-host-runtime.ts +0 -4
- package/src/runtime/host/spot-address-transport.ts +1 -1
- package/src/runtime/host/user-spot-creation-coordinator.ts +1 -1
- package/src/runtime/locations/location-store-repository.ts +118 -80
- package/src/runtime/spots/spot-node-runtime-manager.ts +13 -233
- package/src/runtime/spots/spot-serial-turn-executor.ts +1 -8
- package/src/runtime/spots/spot-timer.ts +109 -18
- package/src/runtime/streams/session-serial-executor.ts +1 -7
- package/src/runtime/streams/stream-session-runtime.ts +13 -17
- package/src/runtime/workers/index.ts +2 -17
|
@@ -3464,10 +3464,6 @@ function relocationFailedFailureCode(error, objectKind) {
|
|
|
3464
3464
|
return service_wire_constants_generated_1.ServiceWireFrameworkErrorCode.requestRejected;
|
|
3465
3465
|
case contracts_1.ZLinkFrameworkErrorKind.ProtocolError:
|
|
3466
3466
|
return service_wire_constants_generated_1.ServiceWireFrameworkErrorCode.requestProtocolError;
|
|
3467
|
-
// No dedicated "capacity exceeded" wire code exists; a full queue is
|
|
3468
|
-
// the closest capacity-shaped signal.
|
|
3469
|
-
case contracts_1.ZLinkFrameworkErrorKind.CapacityExceeded:
|
|
3470
|
-
return service_wire_constants_generated_1.ServiceWireFrameworkErrorCode.workerQueueFull;
|
|
3471
3467
|
// No dedicated "deadline exceeded" wire code exists; a worker timeout
|
|
3472
3468
|
// is the closest timeout-shaped signal.
|
|
3473
3469
|
case contracts_1.ZLinkFrameworkErrorKind.DeadlineExceeded:
|
|
@@ -417,7 +417,7 @@ function missingInstanceRequestFailure(result, nativeErrno) {
|
|
|
417
417
|
? framework_errors_internal_1.ZLinkFrameworkInternalErrorKind.RuntimeShutdown
|
|
418
418
|
: result === runtime_values_1.RequestResult.Backpressured
|
|
419
419
|
// Spec 32-framework-error-model:104-108 — the bounded admission
|
|
420
|
-
// terminal is target placement capacity:
|
|
420
|
+
// terminal is target placement capacity: Unavailable.
|
|
421
421
|
? framework_errors_internal_1.ZLinkFrameworkInternalErrorKind.PlacementCapacityExhausted
|
|
422
422
|
: result === runtime_values_1.RequestResult.NotConnected
|
|
423
423
|
? framework_errors_internal_1.ZLinkFrameworkInternalErrorKind.RouteNotConnected
|
|
@@ -712,7 +712,7 @@ function remoteUserSpotFailure(terminalResult, failureCode, message) {
|
|
|
712
712
|
// Remote operation-table saturation Busy(108)+None is Unavailable,
|
|
713
713
|
// InvalidState(111)+None is InvalidOperation, every fine code follows the
|
|
714
714
|
// shared table, and only placement admission Backpressured(113) stays
|
|
715
|
-
//
|
|
715
|
+
// Unavailable.
|
|
716
716
|
return (0, framework_errors_internal_1.wireReplyFailureException)(terminalResult, failureCode, `${message} terminalResult=${terminalResult}, failureCode=${failureCode}.`);
|
|
717
717
|
}
|
|
718
718
|
function createDeadline(timeoutMs, parent) {
|
|
@@ -56,6 +56,7 @@ export declare class ZLinkLocationStoreRepository extends ZLinkInMemoryLocationS
|
|
|
56
56
|
private removeOwnedAuthorities;
|
|
57
57
|
private removeOwnerCleanupBatch;
|
|
58
58
|
private updateDescriptor;
|
|
59
|
+
private writeDescriptorWithReconciliation;
|
|
59
60
|
private removeDescriptor;
|
|
60
61
|
private listDescriptors;
|
|
61
62
|
private updateOwnedLocation;
|
|
@@ -23,6 +23,7 @@ const MAX_CREATION_TERMINAL_BYTES = 1024 * 1024;
|
|
|
23
23
|
const CREATION_TERMINAL_RETENTION_MS = 5 * 60 * 1000;
|
|
24
24
|
const AGGREGATE_COMMIT_RETRY_WINDOW_MS = 5_000;
|
|
25
25
|
const MAX_AGGREGATE_COMMIT_CONFLICT_RETRIES = 64;
|
|
26
|
+
const MAX_DESCRIPTOR_WRITE_RETRIES = 3;
|
|
26
27
|
const MAX_OWNER_CLEANUP_BATCH_ROWS = 2_047;
|
|
27
28
|
/**
|
|
28
29
|
* Maps framework domain records to the minimal provider SPI.
|
|
@@ -1225,62 +1226,7 @@ class ZLinkLocationStoreRepository extends in_memory_location_store_1.ZLinkInMem
|
|
|
1225
1226
|
return result.kind === 'applied' ? 'released' : 'stale';
|
|
1226
1227
|
}
|
|
1227
1228
|
async updateMeshNode(descriptor, intent, signal) {
|
|
1228
|
-
|
|
1229
|
-
const rowKey = meshKey(descriptor.meshName, descriptor.rid);
|
|
1230
|
-
const [lease, current] = await Promise.all([
|
|
1231
|
-
this.provider.read(leaseKey, signal),
|
|
1232
|
-
this.provider.read(rowKey, signal)
|
|
1233
|
-
]);
|
|
1234
|
-
if (lease.kind === 'missing')
|
|
1235
|
-
return rejected(lease.storeNow);
|
|
1236
|
-
if (liveOwnerLeaseGeneration(lease) !== descriptor.leaseGeneration) {
|
|
1237
|
-
return rejected(lease.value.storeNow);
|
|
1238
|
-
}
|
|
1239
|
-
let generation = 1n;
|
|
1240
|
-
let rowCondition = { kind: 'missing', key: rowKey };
|
|
1241
|
-
if (current.kind === 'found') {
|
|
1242
|
-
const record = decodeCanonicalDescriptorRecord(current.value.bytes);
|
|
1243
|
-
const stored = reviveMeshDescriptor(record.descriptor);
|
|
1244
|
-
generation = descriptorStoreGeneration(record, current.value.version.value);
|
|
1245
|
-
if (sameMeshDescriptor(stored, descriptor)) {
|
|
1246
|
-
return { status: Locations_1.ZLinkLocationWriteStatus.Stored, generation, updatedAt: current.value.storeNow };
|
|
1247
|
-
}
|
|
1248
|
-
const currentLease = await this.provider.read(ownerKey(stored.ownerId), signal);
|
|
1249
|
-
const currentLeaseGeneration = liveOwnerLeaseGeneration(currentLease);
|
|
1250
|
-
const takeover = canTakeOverStoredLocation(intent, stored.ownerId, stored.leaseGeneration, descriptor.ownerId, descriptor.leaseGeneration, currentLeaseGeneration);
|
|
1251
|
-
const renew = intent === 2
|
|
1252
|
-
&& stored.ownerId === descriptor.ownerId
|
|
1253
|
-
&& stored.leaseGeneration === descriptor.leaseGeneration
|
|
1254
|
-
&& stored.lifecycleGeneration === descriptor.lifecycleGeneration
|
|
1255
|
-
&& descriptor.descriptorRevision > stored.descriptorRevision;
|
|
1256
|
-
if (!takeover && !renew) {
|
|
1257
|
-
return {
|
|
1258
|
-
status: Locations_1.ZLinkLocationWriteStatus.IgnoredStale,
|
|
1259
|
-
generation,
|
|
1260
|
-
updatedAt: current.value.storeNow
|
|
1261
|
-
};
|
|
1262
|
-
}
|
|
1263
|
-
if (takeover)
|
|
1264
|
-
generation += 1n;
|
|
1265
|
-
rowCondition = { kind: 'version', key: rowKey, expected: current.value.version };
|
|
1266
|
-
}
|
|
1267
|
-
else if (intent === 2) {
|
|
1268
|
-
return rejected(lease.value.storeNow);
|
|
1269
|
-
}
|
|
1270
|
-
const result = await this.provider.write({
|
|
1271
|
-
conditions: [
|
|
1272
|
-
{ kind: 'version', key: leaseKey, expected: lease.value.version },
|
|
1273
|
-
rowCondition
|
|
1274
|
-
],
|
|
1275
|
-
mutations: [{
|
|
1276
|
-
kind: 'put',
|
|
1277
|
-
key: rowKey,
|
|
1278
|
-
bytes: encodeCanonicalDescriptorRecord(generation, persistMeshDescriptor(descriptor))
|
|
1279
|
-
}]
|
|
1280
|
-
}, signal);
|
|
1281
|
-
if (result.kind === 'conflict')
|
|
1282
|
-
return rejected(result.storeNow);
|
|
1283
|
-
return { status: Locations_1.ZLinkLocationWriteStatus.Stored, generation, updatedAt: result.storeNow };
|
|
1229
|
+
return this.updateDescriptor(meshKey(descriptor.meshName, descriptor.rid), descriptor, intent, reviveMeshDescriptor, sameMeshDescriptor, canRenewMesh, signal);
|
|
1284
1230
|
}
|
|
1285
1231
|
async removeMeshNode(key, owner, signal) {
|
|
1286
1232
|
const rowKey = meshKey(key.meshName, key.rid);
|
|
@@ -1656,11 +1602,10 @@ class ZLinkLocationStoreRepository extends in_memory_location_store_1.ZLinkInMem
|
|
|
1656
1602
|
]);
|
|
1657
1603
|
if (lease.kind === 'missing')
|
|
1658
1604
|
return rejected(lease.storeNow);
|
|
1659
|
-
if (
|
|
1605
|
+
if (!matchesLiveOwnerLease(lease, descriptor.ownerId, descriptor.leaseGeneration)) {
|
|
1660
1606
|
return rejected(lease.value.storeNow);
|
|
1661
1607
|
}
|
|
1662
1608
|
let generation = 1n;
|
|
1663
|
-
let rowCondition = { kind: 'missing', key: rowKey };
|
|
1664
1609
|
if (current.kind === 'found') {
|
|
1665
1610
|
const record = decodeCanonicalDescriptorRecord(current.value.bytes);
|
|
1666
1611
|
const stored = revive(record.descriptor);
|
|
@@ -1681,25 +1626,44 @@ class ZLinkLocationStoreRepository extends in_memory_location_store_1.ZLinkInMem
|
|
|
1681
1626
|
}
|
|
1682
1627
|
if (takeover)
|
|
1683
1628
|
generation += 1n;
|
|
1684
|
-
rowCondition = { kind: 'version', key: rowKey, expected: current.value.version };
|
|
1685
1629
|
}
|
|
1686
1630
|
else if (intent === 2) {
|
|
1687
1631
|
return rejected(lease.value.storeNow);
|
|
1688
1632
|
}
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
|
|
1633
|
+
return this.writeDescriptorWithReconciliation(leaseKey, descriptor.ownerId, descriptor.leaseGeneration, lease, rowKey, current, encodeCanonicalDescriptorRecord(generation, descriptor), generation, signal);
|
|
1634
|
+
}
|
|
1635
|
+
async writeDescriptorWithReconciliation(leaseKey, ownerId, leaseGeneration, liveLease, rowKey, predecessor, encodedDescriptor, generation, signal) {
|
|
1636
|
+
let currentLease = liveLease;
|
|
1637
|
+
let currentRow = predecessor;
|
|
1638
|
+
for (let attempt = 0; attempt <= MAX_DESCRIPTOR_WRITE_RETRIES; attempt += 1) {
|
|
1639
|
+
const rowCondition = currentRow.kind === 'found'
|
|
1640
|
+
? { kind: 'version', key: rowKey, expected: currentRow.value.version }
|
|
1641
|
+
: { kind: 'missing', key: rowKey };
|
|
1642
|
+
const result = await this.provider.write({
|
|
1643
|
+
conditions: [
|
|
1644
|
+
{ kind: 'version', key: leaseKey, expected: currentLease.value.version },
|
|
1645
|
+
rowCondition
|
|
1646
|
+
],
|
|
1647
|
+
mutations: [{ kind: 'put', key: rowKey, bytes: encodedDescriptor }]
|
|
1648
|
+
}, signal);
|
|
1649
|
+
if (result.kind === 'applied') {
|
|
1650
|
+
return { status: Locations_1.ZLinkLocationWriteStatus.Stored, generation, updatedAt: result.storeNow };
|
|
1651
|
+
}
|
|
1652
|
+
if (attempt === MAX_DESCRIPTOR_WRITE_RETRIES)
|
|
1653
|
+
return ignoredStale(result.storeNow);
|
|
1654
|
+
const [refreshedLease, refreshedRow] = await Promise.all([
|
|
1655
|
+
this.provider.read(leaseKey, signal),
|
|
1656
|
+
this.provider.read(rowKey, signal)
|
|
1657
|
+
]);
|
|
1658
|
+
if (refreshedLease.kind === 'missing'
|
|
1659
|
+
|| !matchesLiveOwnerLease(refreshedLease, ownerId, leaseGeneration)
|
|
1660
|
+
|| !sameDescriptorPredecessor(predecessor, refreshedRow)) {
|
|
1661
|
+
return ignoredStale(result.storeNow);
|
|
1662
|
+
}
|
|
1663
|
+
currentLease = refreshedLease;
|
|
1664
|
+
currentRow = refreshedRow;
|
|
1665
|
+
}
|
|
1666
|
+
throw new Error('Descriptor write retry loop exhausted unexpectedly.');
|
|
1703
1667
|
}
|
|
1704
1668
|
async removeDescriptor(rowKey, owner, revive, signal) {
|
|
1705
1669
|
const current = await this.provider.read(rowKey, signal);
|
|
@@ -2933,10 +2897,24 @@ function sameCreationTarget(snapshot, target) {
|
|
|
2933
2897
|
&& snapshot.ownerLeaseGeneration === target.owner.leaseGeneration;
|
|
2934
2898
|
}
|
|
2935
2899
|
function sameLiveOwner(lease, snapshot) {
|
|
2936
|
-
if (
|
|
2900
|
+
if (lease.kind === 'missing')
|
|
2901
|
+
return false;
|
|
2902
|
+
return matchesLiveOwnerLease(lease, snapshot.ownerId, snapshot.ownerLeaseGeneration);
|
|
2903
|
+
}
|
|
2904
|
+
function matchesLiveOwnerLease(lease, ownerId, leaseGeneration) {
|
|
2905
|
+
if (lease.value.expiresAt === undefined
|
|
2906
|
+
|| lease.value.expiresAt.getTime() <= lease.value.storeNow.getTime()) {
|
|
2937
2907
|
return false;
|
|
2908
|
+
}
|
|
2938
2909
|
const owner = decodeOwnerRecord(lease.value.bytes);
|
|
2939
|
-
return owner.ownerId ===
|
|
2910
|
+
return owner.ownerId === ownerId
|
|
2911
|
+
&& BigInt(owner.leaseGeneration) === leaseGeneration;
|
|
2912
|
+
}
|
|
2913
|
+
function sameDescriptorPredecessor(expected, current) {
|
|
2914
|
+
if (expected.kind === 'missing' || current.kind === 'missing') {
|
|
2915
|
+
return expected.kind === current.kind;
|
|
2916
|
+
}
|
|
2917
|
+
return Buffer.from(expected.value.bytes).equals(Buffer.from(current.value.bytes));
|
|
2940
2918
|
}
|
|
2941
2919
|
function liveOwnerLeaseGeneration(lease) {
|
|
2942
2920
|
if (lease.kind === 'missing'
|
|
@@ -3118,6 +3096,10 @@ function sameClientServerDescriptor(left, right) {
|
|
|
3118
3096
|
function sameFanoutDescriptor(left, right) {
|
|
3119
3097
|
return descriptorFingerprint(left, ['updatedAt']) === descriptorFingerprint(right, ['updatedAt']);
|
|
3120
3098
|
}
|
|
3099
|
+
function canRenewMesh(current, next) {
|
|
3100
|
+
return sameOwnerGeneration(current, next)
|
|
3101
|
+
&& next.descriptorRevision > current.descriptorRevision;
|
|
3102
|
+
}
|
|
3121
3103
|
function canRenewClientServer(current, next) {
|
|
3122
3104
|
return sameOwnerGeneration(current, next)
|
|
3123
3105
|
&& next.descriptorRevision > current.descriptorRevision
|
|
@@ -3188,6 +3170,13 @@ function rejected(updatedAt) {
|
|
|
3188
3170
|
updatedAt
|
|
3189
3171
|
};
|
|
3190
3172
|
}
|
|
3173
|
+
function ignoredStale(updatedAt) {
|
|
3174
|
+
return {
|
|
3175
|
+
status: Locations_1.ZLinkLocationWriteStatus.IgnoredStale,
|
|
3176
|
+
generation: 0n,
|
|
3177
|
+
updatedAt
|
|
3178
|
+
};
|
|
3179
|
+
}
|
|
3191
3180
|
function requireOwnerInput(ownerId, leaseTtlMs) {
|
|
3192
3181
|
if (Buffer.byteLength(ownerId, 'utf8') < 1 || ownerId.includes('\0')) {
|
|
3193
3182
|
throw new TypeError('Owner ID must be non-empty UTF-8 without NUL.');
|
|
@@ -59,8 +59,6 @@ export declare class ZLinkSpotNodeRuntimeManager {
|
|
|
59
59
|
private readonly entryActivations;
|
|
60
60
|
private readonly entryActivationStarts;
|
|
61
61
|
private readonly publishers;
|
|
62
|
-
private readonly activePublishes;
|
|
63
|
-
private readonly publishSlotWaiters;
|
|
64
62
|
private disposed;
|
|
65
63
|
private readonly autoConnectLoops;
|
|
66
64
|
private readonly publishedMeshNodeDescriptors;
|
|
@@ -123,15 +121,5 @@ export declare class ZLinkSpotNodeRuntimeManager {
|
|
|
123
121
|
private executePublish;
|
|
124
122
|
tryPublish(meshName: string, channelName: string, topic: string, packetName: string | undefined, event: Message, metadata?: ReadonlyMap<string, string>): ZLinkSubmitResult;
|
|
125
123
|
private publishWithFlags;
|
|
126
|
-
private acquirePublishSlot;
|
|
127
|
-
private publishTimedOut;
|
|
128
|
-
private releasePublishSlot;
|
|
129
|
-
private settlePublishSlotWaiter;
|
|
130
|
-
private rejectPublishSlotWaiter;
|
|
131
|
-
private removePublishSlotWaiter;
|
|
132
|
-
private cleanupPublishSlotWaiter;
|
|
133
|
-
private rejectPublishSlotWaiters;
|
|
134
|
-
private takePublishSlotWaiter;
|
|
135
|
-
private compactPublishSlotWaiters;
|
|
136
124
|
}
|
|
137
125
|
export declare function createFrameworkEntrySpotId(prefix: string): string;
|
|
@@ -34,8 +34,6 @@ class ZLinkSpotNodeRuntimeManager {
|
|
|
34
34
|
entryActivations = new Map();
|
|
35
35
|
entryActivationStarts = new Map();
|
|
36
36
|
publishers = new Map();
|
|
37
|
-
activePublishes = new Set();
|
|
38
|
-
publishSlotWaiters = new Map();
|
|
39
37
|
disposed = false;
|
|
40
38
|
autoConnectLoops = [];
|
|
41
39
|
publishedMeshNodeDescriptors = new Map();
|
|
@@ -579,7 +577,6 @@ class ZLinkSpotNodeRuntimeManager {
|
|
|
579
577
|
this.meshPumps.clear();
|
|
580
578
|
const publishers = [...this.publishers.values()];
|
|
581
579
|
this.publishers.clear();
|
|
582
|
-
this.rejectPublishSlotWaiters(runtimeShutdownError());
|
|
583
580
|
const errors = [];
|
|
584
581
|
const settle = async (operations) => {
|
|
585
582
|
const results = await Promise.allSettled(operations);
|
|
@@ -802,35 +799,13 @@ class ZLinkSpotNodeRuntimeManager {
|
|
|
802
799
|
if (publisher === undefined) {
|
|
803
800
|
throw new configuration_1.ZLinkConfigurationException(`RouteMesh '${meshName}' publisher is not started.`);
|
|
804
801
|
}
|
|
805
|
-
|
|
806
|
-
.get(meshName)?.publisherConfig?.sendTimeoutMs ?? 1000;
|
|
807
|
-
const slot = this.acquirePublishSlot(meshName, sendTimeoutMs, signal);
|
|
808
|
-
if (slot === false) {
|
|
809
|
-
// The bounded executor-admission tokens are exhausted. Do not retain the
|
|
810
|
-
// payload, cancellation state, or a timer for this hard-overload call.
|
|
811
|
-
return Promise.resolve(this.publishTimedOut());
|
|
812
|
-
}
|
|
813
|
-
if (slot === true) {
|
|
814
|
-
return this.executePublish(publisher, meshName, channelName, topic, packetName, event, metadata);
|
|
815
|
-
}
|
|
816
|
-
return slot.then((acquired) => acquired
|
|
817
|
-
? this.executePublish(publisher, meshName, channelName, topic, packetName, event, metadata)
|
|
818
|
-
: this.publishTimedOut());
|
|
802
|
+
return this.executePublish(publisher, channelName, topic, packetName, event, metadata);
|
|
819
803
|
}
|
|
820
|
-
async executePublish(publisher,
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
try {
|
|
826
|
-
const parts = (0, flow_context_1.runWithOutboundFlow)(this.options.dispatchErrors?.flow.flowCreationEnabled() ?? true, () => (0, channel_envelope_1.encodeChannelPublishEnvelopeParts)(channelName, topic, packetName, event, undefined, this.options.dispatchErrors?.flow.flowCreationEnabled() ?? true, metadata));
|
|
827
|
-
const processing = publisher.publishAsync(channelName, topic, parts, undefined, undefined);
|
|
828
|
-
void Promise.resolve(processing).catch(() => undefined);
|
|
829
|
-
return Promise.resolve({ status: submission_result_1.ZLinkSubmitStatus.Submitted });
|
|
830
|
-
}
|
|
831
|
-
finally {
|
|
832
|
-
this.releasePublishSlot(meshName);
|
|
833
|
-
}
|
|
804
|
+
async executePublish(publisher, channelName, topic, packetName, event, metadata) {
|
|
805
|
+
const parts = (0, flow_context_1.runWithOutboundFlow)(this.options.dispatchErrors?.flow.flowCreationEnabled() ?? true, () => (0, channel_envelope_1.encodeChannelPublishEnvelopeParts)(channelName, topic, packetName, event, undefined, this.options.dispatchErrors?.flow.flowCreationEnabled() ?? true, metadata));
|
|
806
|
+
const processing = publisher.publishAsync(channelName, topic, parts, undefined, undefined);
|
|
807
|
+
void Promise.resolve(processing).catch(() => undefined);
|
|
808
|
+
return Promise.resolve({ status: submission_result_1.ZLinkSubmitStatus.Submitted });
|
|
834
809
|
}
|
|
835
810
|
tryPublish(meshName, channelName, topic, packetName, event, metadata = EMPTY_SPOT_METADATA) {
|
|
836
811
|
return this.publishWithFlags(meshName, channelName, topic, packetName, event, ZLINK_SEND_DONT_WAIT, metadata);
|
|
@@ -855,141 +830,6 @@ class ZLinkSpotNodeRuntimeManager {
|
|
|
855
830
|
throw error;
|
|
856
831
|
}
|
|
857
832
|
}
|
|
858
|
-
acquirePublishSlot(meshName, timeoutMs, signal) {
|
|
859
|
-
if (!this.activePublishes.has(meshName)) {
|
|
860
|
-
this.activePublishes.add(meshName);
|
|
861
|
-
return true;
|
|
862
|
-
}
|
|
863
|
-
const waiterCapacity = Math.max(1, this.options.registration.spotNodes
|
|
864
|
-
.get(meshName)?.publisherConfig?.sendHighWaterMark ?? 1);
|
|
865
|
-
const queue = this.publishSlotWaiters.get(meshName) ?? {
|
|
866
|
-
waiters: [],
|
|
867
|
-
head: 0,
|
|
868
|
-
count: 0
|
|
869
|
-
};
|
|
870
|
-
if (queue.count >= waiterCapacity) {
|
|
871
|
-
// This call has no bounded executor-admission token. Fail without
|
|
872
|
-
// retaining its payload in a pending work queue.
|
|
873
|
-
return false;
|
|
874
|
-
}
|
|
875
|
-
return new Promise((resolve, reject) => {
|
|
876
|
-
const waiter = {
|
|
877
|
-
resolve,
|
|
878
|
-
reject,
|
|
879
|
-
signal,
|
|
880
|
-
settled: false
|
|
881
|
-
};
|
|
882
|
-
if (timeoutMs !== -1) {
|
|
883
|
-
waiter.deadlineMs = performance.now() + Math.max(0, timeoutMs);
|
|
884
|
-
}
|
|
885
|
-
queue.waiters.push(waiter);
|
|
886
|
-
queue.count += 1;
|
|
887
|
-
this.publishSlotWaiters.set(meshName, queue);
|
|
888
|
-
if (timeoutMs !== -1) {
|
|
889
|
-
waiter.timeout = setTimeout(() => this.settlePublishSlotWaiter(meshName, waiter, false), Math.max(0, timeoutMs));
|
|
890
|
-
}
|
|
891
|
-
if (signal !== undefined) {
|
|
892
|
-
waiter.abortHandler = () => this.rejectPublishSlotWaiter(meshName, waiter, signal.reason ?? (0, abort_1.createAbortError)());
|
|
893
|
-
signal.addEventListener('abort', waiter.abortHandler, { once: true });
|
|
894
|
-
}
|
|
895
|
-
});
|
|
896
|
-
}
|
|
897
|
-
publishTimedOut() {
|
|
898
|
-
return { status: submission_result_1.ZLinkSubmitStatus.TimedOut };
|
|
899
|
-
}
|
|
900
|
-
releasePublishSlot(meshName) {
|
|
901
|
-
const queue = this.publishSlotWaiters.get(meshName);
|
|
902
|
-
while (queue !== undefined && queue.count > 0) {
|
|
903
|
-
const waiter = this.takePublishSlotWaiter(queue);
|
|
904
|
-
if (waiter === undefined)
|
|
905
|
-
continue;
|
|
906
|
-
if (waiter.settled)
|
|
907
|
-
continue;
|
|
908
|
-
if (waiter.deadlineMs !== undefined && performance.now() >= waiter.deadlineMs) {
|
|
909
|
-
this.cleanupPublishSlotWaiter(waiter);
|
|
910
|
-
waiter.settled = true;
|
|
911
|
-
waiter.resolve(false);
|
|
912
|
-
continue;
|
|
913
|
-
}
|
|
914
|
-
this.cleanupPublishSlotWaiter(waiter);
|
|
915
|
-
waiter.settled = true;
|
|
916
|
-
waiter.resolve(true);
|
|
917
|
-
if (queue.count === 0)
|
|
918
|
-
this.publishSlotWaiters.delete(meshName);
|
|
919
|
-
return;
|
|
920
|
-
}
|
|
921
|
-
this.publishSlotWaiters.delete(meshName);
|
|
922
|
-
this.activePublishes.delete(meshName);
|
|
923
|
-
}
|
|
924
|
-
settlePublishSlotWaiter(meshName, waiter, acquired) {
|
|
925
|
-
if (waiter.settled)
|
|
926
|
-
return;
|
|
927
|
-
waiter.settled = true;
|
|
928
|
-
this.removePublishSlotWaiter(meshName, waiter);
|
|
929
|
-
this.cleanupPublishSlotWaiter(waiter);
|
|
930
|
-
waiter.resolve(acquired);
|
|
931
|
-
}
|
|
932
|
-
rejectPublishSlotWaiter(meshName, waiter, error) {
|
|
933
|
-
if (waiter.settled)
|
|
934
|
-
return;
|
|
935
|
-
waiter.settled = true;
|
|
936
|
-
this.removePublishSlotWaiter(meshName, waiter);
|
|
937
|
-
this.cleanupPublishSlotWaiter(waiter);
|
|
938
|
-
waiter.reject(error);
|
|
939
|
-
}
|
|
940
|
-
removePublishSlotWaiter(meshName, waiter) {
|
|
941
|
-
const queue = this.publishSlotWaiters.get(meshName);
|
|
942
|
-
if (queue === undefined)
|
|
943
|
-
return;
|
|
944
|
-
const index = queue.waiters.indexOf(waiter, queue.head);
|
|
945
|
-
if (index >= 0) {
|
|
946
|
-
queue.waiters[index] = undefined;
|
|
947
|
-
queue.count -= 1;
|
|
948
|
-
this.compactPublishSlotWaiters(queue);
|
|
949
|
-
}
|
|
950
|
-
if (queue.count === 0)
|
|
951
|
-
this.publishSlotWaiters.delete(meshName);
|
|
952
|
-
}
|
|
953
|
-
cleanupPublishSlotWaiter(waiter) {
|
|
954
|
-
if (waiter.timeout !== undefined)
|
|
955
|
-
clearTimeout(waiter.timeout);
|
|
956
|
-
if (waiter.abortHandler !== undefined) {
|
|
957
|
-
waiter.signal?.removeEventListener('abort', waiter.abortHandler);
|
|
958
|
-
}
|
|
959
|
-
}
|
|
960
|
-
rejectPublishSlotWaiters(error) {
|
|
961
|
-
for (const [meshName, queue] of this.publishSlotWaiters) {
|
|
962
|
-
let waiter;
|
|
963
|
-
while ((waiter = this.takePublishSlotWaiter(queue)) !== undefined) {
|
|
964
|
-
this.rejectPublishSlotWaiter(meshName, waiter, error);
|
|
965
|
-
}
|
|
966
|
-
this.publishSlotWaiters.delete(meshName);
|
|
967
|
-
}
|
|
968
|
-
this.activePublishes.clear();
|
|
969
|
-
}
|
|
970
|
-
takePublishSlotWaiter(queue) {
|
|
971
|
-
while (queue.head < queue.waiters.length && queue.waiters[queue.head] === undefined) {
|
|
972
|
-
queue.head += 1;
|
|
973
|
-
}
|
|
974
|
-
const waiter = queue.waiters[queue.head];
|
|
975
|
-
if (waiter === undefined)
|
|
976
|
-
return undefined;
|
|
977
|
-
queue.waiters[queue.head] = undefined;
|
|
978
|
-
queue.head += 1;
|
|
979
|
-
queue.count -= 1;
|
|
980
|
-
this.compactPublishSlotWaiters(queue);
|
|
981
|
-
return waiter;
|
|
982
|
-
}
|
|
983
|
-
compactPublishSlotWaiters(queue) {
|
|
984
|
-
if (queue.count === 0) {
|
|
985
|
-
queue.waiters.length = 0;
|
|
986
|
-
queue.head = 0;
|
|
987
|
-
}
|
|
988
|
-
else if (queue.head >= 1024 && queue.head * 2 >= queue.waiters.length) {
|
|
989
|
-
queue.waiters.splice(0, queue.head);
|
|
990
|
-
queue.head = 0;
|
|
991
|
-
}
|
|
992
|
-
}
|
|
993
833
|
}
|
|
994
834
|
exports.ZLinkSpotNodeRuntimeManager = ZLinkSpotNodeRuntimeManager;
|
|
995
835
|
function runtimeShutdownError() {
|
|
@@ -18,10 +18,7 @@ class ZLinkSpotSerialTurnExecutor {
|
|
|
18
18
|
constructor(yieldAllowed = true, sourceSpotId, schedulerOptions) {
|
|
19
19
|
this.yieldAllowed = yieldAllowed;
|
|
20
20
|
this.sourceSpotId = sourceSpotId;
|
|
21
|
-
this.scheduler = new serial_execution_queue_1.ZLinkSerialExecutionQueue((record) => this.runQueuedRecord(record),
|
|
22
|
-
...schedulerOptions,
|
|
23
|
-
capacityError: schedulerOptions?.capacityError ?? (() => (0, framework_errors_internal_1.createInternalFrameworkException)(framework_errors_internal_1.ZLinkFrameworkInternalErrorKind.WorkerQueueFull, 'Spot execution queue capacity was exceeded.'))
|
|
24
|
-
});
|
|
21
|
+
this.scheduler = new serial_execution_queue_1.ZLinkSerialExecutionQueue((record) => this.runQueuedRecord(record), schedulerOptions);
|
|
25
22
|
}
|
|
26
23
|
get isExecuting() {
|
|
27
24
|
return this.depth > 0;
|
|
@@ -74,6 +74,8 @@ export declare class ZLinkManagedTimer implements ZLinkTimer {
|
|
|
74
74
|
private lastScheduledIndex;
|
|
75
75
|
private timeout;
|
|
76
76
|
private running;
|
|
77
|
+
private dispatchFailure;
|
|
78
|
+
private finalization;
|
|
77
79
|
constructor(name: string, periodMs: number, options: Required<ZLinkTimerOptions>, onTick: (tick: ZLinkTimerTick) => Promise<void>, onFailure?: ZLinkTimerFailureReporter | undefined, shouldWaitForRunningOnCancel?: () => boolean, clock?: ZLinkTimerClock);
|
|
78
80
|
get isDisposed(): boolean;
|
|
79
81
|
cancel(_signal?: AbortSignal): Promise<void>;
|
|
@@ -83,6 +85,7 @@ export declare class ZLinkManagedTimer implements ZLinkTimer {
|
|
|
83
85
|
private scheduleNext;
|
|
84
86
|
private fire;
|
|
85
87
|
private cancelCore;
|
|
88
|
+
private completeFinalization;
|
|
86
89
|
private prepareCaptureCore;
|
|
87
90
|
private prepareFireCore;
|
|
88
91
|
private completeFireCore;
|