@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.
Files changed (125) hide show
  1. package/dist/.tsbuildinfo +1 -1
  2. package/dist/contracts/Configuration/EndpointNotation.d.ts +5 -4
  3. package/dist/contracts/Configuration/EndpointNotation.js +5 -4
  4. package/dist/contracts/Configuration/InternalDefaults.d.ts +0 -1
  5. package/dist/contracts/Configuration/InternalDefaults.js +1 -2
  6. package/dist/contracts/Configuration/RegistrationNormalizers.js +1 -2
  7. package/dist/contracts/Configuration/RegistrationTypes.d.ts +2 -5
  8. package/dist/contracts/Configuration/RegistrationValidators.js +0 -1
  9. package/dist/contracts/Errors/ZLinkFrameworkException.d.ts +6 -7
  10. package/dist/contracts/Errors/ZLinkFrameworkException.js +6 -7
  11. package/dist/runtime/actors/actor-client.js +1 -1
  12. package/dist/runtime/actors/actor-mailbox.js +1 -5
  13. package/dist/runtime/backend/contracts/index.d.ts +2 -0
  14. package/dist/runtime/backend/mesh-completion-table.d.ts +1 -3
  15. package/dist/runtime/backend/mesh-completion-table.js +11 -15
  16. package/dist/runtime/backend/mesh-dispatch-pump.d.ts +11 -4
  17. package/dist/runtime/backend/mesh-dispatch-pump.js +201 -134
  18. package/dist/runtime/backend/node/node-backend-adapter-factory.d.ts +3 -4
  19. package/dist/runtime/backend/node/node-backend-adapter-factory.js +51 -37
  20. package/dist/runtime/backend/node/node-backend-adapter-support.d.ts +2 -2
  21. package/dist/runtime/backend/node/node-backend-adapter-support.js +2 -2
  22. package/dist/runtime/backend/node/node-dealer-channel-client-transport.js +2 -2
  23. package/dist/runtime/backend/node/node-event-loop-poller.d.ts +16 -0
  24. package/dist/runtime/backend/node/node-event-loop-poller.js +49 -0
  25. package/dist/runtime/backend/node/node-raw-binding-port.js +24 -41
  26. package/dist/runtime/backend/node/node-raw-mesh-backend.d.ts +8 -8
  27. package/dist/runtime/backend/node/node-raw-mesh-backend.js +100 -107
  28. package/dist/runtime/backend/node/node-socket-backend-adapter.d.ts +3 -2
  29. package/dist/runtime/backend/node/node-socket-backend-adapter.js +18 -67
  30. package/dist/runtime/backend/raw-binding-port.d.ts +1 -0
  31. package/dist/runtime/backend/runtime-values.d.ts +6 -1
  32. package/dist/runtime/backend/runtime-values.js +6 -0
  33. package/dist/runtime/channels/channel-dispatchers.js +2 -2
  34. package/dist/runtime/channels/channel-envelope.js +324 -121
  35. package/dist/runtime/channels/channel-multipart.d.ts +8 -1
  36. package/dist/runtime/channels/channel-outbound-operations.js +0 -2
  37. package/dist/runtime/channels/channel-receive-loops.d.ts +1 -3
  38. package/dist/runtime/channels/channel-receive-loops.js +25 -65
  39. package/dist/runtime/channels/channel-socket-registry.js +14 -1
  40. package/dist/runtime/channels/channel-transports.d.ts +2 -1
  41. package/dist/runtime/channels/channel-transports.js +12 -10
  42. package/dist/runtime/channels/client-server-location-runtime.js +15 -3
  43. package/dist/runtime/execution/serial-execution-queue.d.ts +5 -18
  44. package/dist/runtime/execution/serial-execution-queue.js +16 -80
  45. package/dist/runtime/foundation/event-loop-resources.d.ts +0 -3
  46. package/dist/runtime/foundation/event-loop-resources.js +2 -11
  47. package/dist/runtime/foundation/operation-registry.d.ts +2 -8
  48. package/dist/runtime/foundation/operation-registry.js +3 -21
  49. package/dist/runtime/foundation/raw-service-mesh-runtime.d.ts +19 -7
  50. package/dist/runtime/foundation/raw-service-mesh-runtime.js +56 -10
  51. package/dist/runtime/foundation/service-mailbox.d.ts +1 -7
  52. package/dist/runtime/foundation/service-mailbox.js +3 -2
  53. package/dist/runtime/foundation/service-runtime-contracts.d.ts +2 -1
  54. package/dist/runtime/foundation/service-stateful-registry.d.ts +1 -1
  55. package/dist/runtime/foundation/service-stateful-registry.js +2 -2
  56. package/dist/runtime/foundation/service-stateful-runtime.js +14 -14
  57. package/dist/runtime/framework-errors-internal.d.ts +4 -4
  58. package/dist/runtime/framework-errors-internal.js +8 -10
  59. package/dist/runtime/host/actor-placement-coordinator.js +1 -1
  60. package/dist/runtime/host/index.js +1 -1
  61. package/dist/runtime/host/service-relocation-host-runtime.js +0 -4
  62. package/dist/runtime/host/spot-address-transport.js +1 -1
  63. package/dist/runtime/host/user-spot-creation-coordinator.js +1 -1
  64. package/dist/runtime/locations/location-store-repository.d.ts +1 -0
  65. package/dist/runtime/locations/location-store-repository.js +64 -75
  66. package/dist/runtime/spots/spot-node-runtime-manager.d.ts +0 -12
  67. package/dist/runtime/spots/spot-node-runtime-manager.js +6 -166
  68. package/dist/runtime/spots/spot-serial-turn-executor.js +1 -4
  69. package/dist/runtime/spots/spot-timer.d.ts +3 -0
  70. package/dist/runtime/spots/spot-timer.js +87 -18
  71. package/dist/runtime/streams/session-serial-executor.js +1 -3
  72. package/dist/runtime/streams/stream-session-runtime.d.ts +2 -2
  73. package/dist/runtime/streams/stream-session-runtime.js +13 -19
  74. package/dist/runtime/workers/index.d.ts +0 -1
  75. package/dist/runtime/workers/index.js +1 -9
  76. package/package.json +9 -3
  77. package/src/contracts/Configuration/EndpointNotation.ts +5 -4
  78. package/src/contracts/Configuration/InternalDefaults.ts +0 -1
  79. package/src/contracts/Configuration/RegistrationNormalizers.ts +2 -4
  80. package/src/contracts/Configuration/RegistrationTypes.ts +2 -5
  81. package/src/contracts/Configuration/RegistrationValidators.ts +0 -1
  82. package/src/contracts/Errors/ZLinkFrameworkException.ts +6 -7
  83. package/src/runtime/actors/actor-client.ts +1 -1
  84. package/src/runtime/actors/actor-mailbox.ts +1 -12
  85. package/src/runtime/backend/contracts/index.ts +2 -0
  86. package/src/runtime/backend/mesh-completion-table.ts +12 -23
  87. package/src/runtime/backend/mesh-dispatch-pump.ts +206 -138
  88. package/src/runtime/backend/node/node-backend-adapter-factory.ts +66 -35
  89. package/src/runtime/backend/node/node-backend-adapter-support.ts +4 -4
  90. package/src/runtime/backend/node/node-dealer-channel-client-transport.ts +2 -2
  91. package/src/runtime/backend/node/node-event-loop-poller.ts +55 -0
  92. package/src/runtime/backend/node/node-raw-binding-port.ts +30 -45
  93. package/src/runtime/backend/node/node-raw-mesh-backend.ts +97 -110
  94. package/src/runtime/backend/node/node-socket-backend-adapter.ts +23 -69
  95. package/src/runtime/backend/raw-binding-port.ts +1 -0
  96. package/src/runtime/backend/runtime-values.ts +13 -1
  97. package/src/runtime/channels/channel-dispatchers.ts +2 -2
  98. package/src/runtime/channels/channel-envelope.ts +379 -109
  99. package/src/runtime/channels/channel-multipart.ts +9 -1
  100. package/src/runtime/channels/channel-outbound-operations.ts +0 -1
  101. package/src/runtime/channels/channel-receive-loops.ts +24 -75
  102. package/src/runtime/channels/channel-socket-registry.ts +17 -1
  103. package/src/runtime/channels/channel-transports.ts +20 -10
  104. package/src/runtime/channels/client-server-location-runtime.ts +16 -2
  105. package/src/runtime/execution/serial-execution-queue.ts +16 -108
  106. package/src/runtime/foundation/event-loop-resources.ts +2 -11
  107. package/src/runtime/foundation/operation-registry.ts +2 -22
  108. package/src/runtime/foundation/raw-service-mesh-runtime.ts +74 -19
  109. package/src/runtime/foundation/service-mailbox.ts +3 -13
  110. package/src/runtime/foundation/service-runtime-contracts.ts +2 -1
  111. package/src/runtime/foundation/service-stateful-registry.ts +2 -2
  112. package/src/runtime/foundation/service-stateful-runtime.ts +14 -14
  113. package/src/runtime/framework-errors-internal.ts +8 -10
  114. package/src/runtime/host/actor-placement-coordinator.ts +1 -1
  115. package/src/runtime/host/index.ts +2 -1
  116. package/src/runtime/host/service-relocation-host-runtime.ts +0 -4
  117. package/src/runtime/host/spot-address-transport.ts +1 -1
  118. package/src/runtime/host/user-spot-creation-coordinator.ts +1 -1
  119. package/src/runtime/locations/location-store-repository.ts +118 -80
  120. package/src/runtime/spots/spot-node-runtime-manager.ts +13 -233
  121. package/src/runtime/spots/spot-serial-turn-executor.ts +1 -8
  122. package/src/runtime/spots/spot-timer.ts +109 -18
  123. package/src/runtime/streams/session-serial-executor.ts +1 -7
  124. package/src/runtime/streams/stream-session-runtime.ts +13 -17
  125. 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: CapacityExceeded.
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
- // CapacityExceeded.
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
- const leaseKey = ownerKey(descriptor.ownerId);
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 (liveOwnerLeaseGeneration(lease) !== descriptor.leaseGeneration) {
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
- const result = await this.provider.write({
1690
- conditions: [
1691
- { kind: 'version', key: leaseKey, expected: lease.value.version },
1692
- rowCondition
1693
- ],
1694
- mutations: [{
1695
- kind: 'put',
1696
- key: rowKey,
1697
- bytes: encodeCanonicalDescriptorRecord(generation, descriptor)
1698
- }]
1699
- }, signal);
1700
- if (result.kind === 'conflict')
1701
- return rejected(result.storeNow);
1702
- return { status: Locations_1.ZLinkLocationWriteStatus.Stored, generation, updatedAt: result.storeNow };
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 (liveOwnerLeaseGeneration(lease) !== snapshot.ownerLeaseGeneration)
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 === snapshot.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
- const sendTimeoutMs = this.options.registration.spotNodes
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, meshName, channelName, topic, packetName, event, metadata) {
821
- // The slot is the source-local admission boundary. Once publishAsync takes
822
- // the owned frames, target processing cannot change the caller terminal.
823
- // Call-scoped flow (spec 27 §4): the fanout envelope flow pair does not
824
- // outlive this publish call.
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;