@zlink-systems/framework 0.24.0 → 0.26.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 (215) hide show
  1. package/dist/.tsbuildinfo +1 -1
  2. package/dist/contracts/Channels/IZLinkFanoutClient.d.ts +0 -6
  3. package/dist/contracts/RouteMesh/RuntimeTopology.d.ts +8 -0
  4. package/dist/internal.d.ts +1 -0
  5. package/dist/internal.js +1 -0
  6. package/dist/runtime/activation-admission.d.ts +29 -0
  7. package/dist/runtime/activation-admission.js +61 -0
  8. package/dist/runtime/actors/actor-context.js +6 -6
  9. package/dist/runtime/actors/actor-handoff.d.ts +9 -3
  10. package/dist/runtime/actors/actor-handoff.js +28 -17
  11. package/dist/runtime/actors/actor-local-native-join.js +2 -18
  12. package/dist/runtime/actors/actor-remote-joiner.d.ts +2 -2
  13. package/dist/runtime/actors/actor-remote-joiner.js +6 -8
  14. package/dist/runtime/actors/actor-runtime-contracts.d.ts +4 -2
  15. package/dist/runtime/actors/actor-source-transfer.d.ts +5 -5
  16. package/dist/runtime/actors/deferred-join-completion.d.ts +14 -0
  17. package/dist/runtime/actors/deferred-join-completion.js +20 -0
  18. package/dist/runtime/actors/index.d.ts +1 -1
  19. package/dist/runtime/actors/index.js +15 -5
  20. package/dist/runtime/admission.d.ts +5 -1
  21. package/dist/runtime/admission.js +4 -0
  22. package/dist/runtime/backend/contracts/index.d.ts +2 -10
  23. package/dist/runtime/backend/mesh-actor-session-node-adapter.js +2 -9
  24. package/dist/runtime/backend/node/node-backend-adapter-factory.d.ts +1 -2
  25. package/dist/runtime/backend/node/node-backend-adapter-factory.js +4 -18
  26. package/dist/runtime/backend/node/node-backend-adapter-support.d.ts +6 -3
  27. package/dist/runtime/backend/node/node-backend-adapter-support.js +12 -28
  28. package/dist/runtime/backend/node/node-event-loop-poller.d.ts +1 -1
  29. package/dist/runtime/backend/node/node-event-loop-poller.js +8 -2
  30. package/dist/runtime/backend/node/node-raw-binding-port.d.ts +1 -1
  31. package/dist/runtime/backend/node/node-raw-binding-port.js +11 -3
  32. package/dist/runtime/backend/node/node-raw-mesh-backend.d.ts +12 -9
  33. package/dist/runtime/backend/node/node-raw-mesh-backend.js +61 -29
  34. package/dist/runtime/backend/node/node-socket-backend-adapter.js +1 -1
  35. package/dist/runtime/backend/raw-binding-port.d.ts +12 -0
  36. package/dist/runtime/channels/channel-clients.d.ts +0 -1
  37. package/dist/runtime/channels/channel-clients.js +0 -8
  38. package/dist/runtime/channels/channel-outbound-operations.js +2 -10
  39. package/dist/runtime/channels/channel-runtime-manager.d.ts +2 -5
  40. package/dist/runtime/channels/channel-runtime-manager.js +1 -12
  41. package/dist/runtime/channels/channel-socket-registry.d.ts +17 -4
  42. package/dist/runtime/channels/channel-socket-registry.js +49 -62
  43. package/dist/runtime/channels/channel-transports.d.ts +0 -3
  44. package/dist/runtime/channels/fanout-location-runtime.js +3 -9
  45. package/dist/runtime/execution/index.d.ts +18 -8
  46. package/dist/runtime/execution/index.js +55 -29
  47. package/dist/runtime/execution/serial-execution-queue.d.ts +5 -6
  48. package/dist/runtime/execution/serial-execution-queue.js +49 -15
  49. package/dist/runtime/foundation/listener-records.d.ts +11 -0
  50. package/dist/runtime/foundation/listener-records.js +20 -0
  51. package/dist/runtime/foundation/raw-service-mesh-runtime.d.ts +10 -21
  52. package/dist/runtime/foundation/raw-service-mesh-runtime.js +66 -392
  53. package/dist/runtime/foundation/service-authority-payload-codec.d.ts +1 -0
  54. package/dist/runtime/foundation/service-authority-payload-codec.js +8 -0
  55. package/dist/runtime/foundation/service-maintenance-runtime.js +23 -2
  56. package/dist/runtime/foundation/service-relocation-coordinator.d.ts +9 -0
  57. package/dist/runtime/foundation/service-relocation-coordinator.js +14 -1
  58. package/dist/runtime/foundation/service-relocation-object-owner.d.ts +8 -0
  59. package/dist/runtime/foundation/service-relocation-object-owner.js +16 -4
  60. package/dist/runtime/foundation/service-session-binding-ingress-port.d.ts +6 -13
  61. package/dist/runtime/foundation/service-stateful-runtime.d.ts +10 -7
  62. package/dist/runtime/foundation/service-stateful-runtime.js +100 -60
  63. package/dist/runtime/foundation/service-stateful-wire-codec.d.ts +9 -4
  64. package/dist/runtime/foundation/service-stateful-wire-codec.js +153 -90
  65. package/dist/runtime/foundation/service-topology-registry.d.ts +1 -2
  66. package/dist/runtime/foundation/service-topology-registry.js +6 -30
  67. package/dist/runtime/host/actor-transfer-runtime.d.ts +17 -15
  68. package/dist/runtime/host/actor-transfer-runtime.js +73 -86
  69. package/dist/runtime/host/index.d.ts +6 -2
  70. package/dist/runtime/host/index.js +63 -37
  71. package/dist/runtime/host/remote-bound-session-relay.js +4 -3
  72. package/dist/runtime/host/route-mesh-runtime.d.ts +2 -0
  73. package/dist/runtime/host/route-mesh-runtime.js +7 -5
  74. package/dist/runtime/host/service-relocation-host-runtime.d.ts +50 -8
  75. package/dist/runtime/host/service-relocation-host-runtime.js +343 -270
  76. package/dist/runtime/host/spot-runtime-options-factory.d.ts +7 -4
  77. package/dist/runtime/host/spot-runtime-options-factory.js +4 -8
  78. package/dist/runtime/host/stateful-authority-route-runtime.js +6 -2
  79. package/dist/runtime/host/user-spot-creation-coordinator.d.ts +11 -3
  80. package/dist/runtime/host/user-spot-creation-coordinator.js +85 -87
  81. package/dist/runtime/locations/in-memory-provider-location-store.js +8 -6
  82. package/dist/runtime/locations/lifecycle.d.ts +1 -1
  83. package/dist/runtime/locations/lifecycle.js +2 -2
  84. package/dist/runtime/locations/resolvers.js +7 -2
  85. package/dist/runtime/locations/spot-location-claims.d.ts +2 -2
  86. package/dist/runtime/locations/spot-location-claims.js +3 -27
  87. package/dist/runtime/protocol/service_wire_codec.generated.d.ts +1 -0
  88. package/dist/runtime/protocol/service_wire_codec.generated.js +5 -1
  89. package/dist/runtime/protocol/service_wire_pilot_codec.generated.d.ts +1 -0
  90. package/dist/runtime/protocol/service_wire_pilot_codec.generated.js +3 -2
  91. package/dist/runtime/spots/formal-remote-actor-admission-registry.d.ts +3 -3
  92. package/dist/runtime/spots/formal-remote-actor-admission-registry.js +4 -4
  93. package/dist/runtime/spots/formal-remote-actor-transfer-registry.d.ts +3 -3
  94. package/dist/runtime/spots/index.d.ts +25 -19
  95. package/dist/runtime/spots/index.js +207 -205
  96. package/dist/runtime/spots/spot-activation-registry.d.ts +4 -2
  97. package/dist/runtime/spots/spot-activation-registry.js +34 -31
  98. package/dist/runtime/spots/spot-activation-state.d.ts +2 -11
  99. package/dist/runtime/spots/spot-activation-state.js +4 -17
  100. package/dist/runtime/spots/spot-activation.d.ts +8 -6
  101. package/dist/runtime/spots/spot-activation.js +54 -49
  102. package/dist/runtime/spots/spot-actor-admission-coordinator.d.ts +1 -1
  103. package/dist/runtime/spots/spot-actor-admission-coordinator.js +1 -1
  104. package/dist/runtime/spots/spot-actor-join-dispatch.d.ts +2 -2
  105. package/dist/runtime/spots/spot-actor-join-dispatch.js +3 -5
  106. package/dist/runtime/spots/spot-actor-lifecycle-drain.js +2 -2
  107. package/dist/runtime/spots/spot-actor-membership.d.ts +4 -0
  108. package/dist/runtime/spots/spot-actor-membership.js +26 -12
  109. package/dist/runtime/spots/spot-entry-activation.d.ts +1 -2
  110. package/dist/runtime/spots/spot-entry-activation.js +0 -1
  111. package/dist/runtime/spots/spot-manager-public.js +1 -1
  112. package/dist/runtime/spots/spot-native-actor-join-admission.d.ts +1 -1
  113. package/dist/runtime/spots/spot-native-actor-join-admission.js +2 -2
  114. package/dist/runtime/spots/spot-node-runtime-manager.d.ts +5 -5
  115. package/dist/runtime/spots/spot-node-runtime-manager.js +7 -11
  116. package/dist/runtime/spots/spot-outbound.js +1 -29
  117. package/dist/runtime/spots/spot-routed-actor-admission.d.ts +1 -0
  118. package/dist/runtime/spots/spot-routed-actor-admission.js +10 -0
  119. package/dist/runtime/spots/spot-routed-frame-dispatch.d.ts +2 -6
  120. package/dist/runtime/spots/spot-routed-frame-dispatch.js +2 -70
  121. package/dist/runtime/spots/spot-runtime-ports.d.ts +3 -5
  122. package/dist/runtime/spots/spot-serial-executor.d.ts +5 -0
  123. package/dist/runtime/spots/spot-serial-executor.js +8 -1
  124. package/dist/runtime/spots/spot-serial-turn-executor.d.ts +3 -0
  125. package/dist/runtime/spots/spot-serial-turn-executor.js +8 -4
  126. package/dist/runtime/streams/actor-session-binding-registry.d.ts +13 -15
  127. package/dist/runtime/streams/actor-session-binding-registry.js +19 -171
  128. package/dist/runtime/streams/actor-session-binding-runtime-owner.d.ts +3 -4
  129. package/dist/runtime/streams/bound-session-service.js +1 -18
  130. package/dist/runtime/streams/index.d.ts +2 -0
  131. package/dist/runtime/streams/index.js +19 -19
  132. package/dist/runtime/streams/session-serial-executor.js +2 -2
  133. package/package.json +3 -3
  134. package/src/contracts/Channels/IZLinkFanoutClient.ts +0 -7
  135. package/src/contracts/RouteMesh/RuntimeTopology.ts +10 -0
  136. package/src/internal.ts +1 -0
  137. package/src/runtime/activation-admission.ts +78 -0
  138. package/src/runtime/actors/actor-context.ts +6 -6
  139. package/src/runtime/actors/actor-handoff.ts +31 -23
  140. package/src/runtime/actors/actor-local-native-join.ts +3 -42
  141. package/src/runtime/actors/actor-remote-joiner.ts +6 -25
  142. package/src/runtime/actors/actor-runtime-contracts.ts +4 -10
  143. package/src/runtime/actors/actor-source-transfer.ts +5 -18
  144. package/src/runtime/actors/deferred-join-completion.ts +40 -0
  145. package/src/runtime/actors/index.ts +22 -9
  146. package/src/runtime/admission.ts +5 -1
  147. package/src/runtime/backend/contracts/index.ts +2 -13
  148. package/src/runtime/backend/mesh-actor-session-node-adapter.ts +2 -10
  149. package/src/runtime/backend/node/node-backend-adapter-factory.ts +5 -25
  150. package/src/runtime/backend/node/node-backend-adapter-support.ts +9 -29
  151. package/src/runtime/backend/node/node-event-loop-poller.ts +14 -2
  152. package/src/runtime/backend/node/node-raw-binding-port.ts +17 -3
  153. package/src/runtime/backend/node/node-raw-mesh-backend.ts +65 -32
  154. package/src/runtime/backend/node/node-socket-backend-adapter.ts +2 -2
  155. package/src/runtime/backend/raw-binding-port.ts +13 -0
  156. package/src/runtime/channels/channel-clients.ts +0 -11
  157. package/src/runtime/channels/channel-outbound-operations.ts +3 -11
  158. package/src/runtime/channels/channel-runtime-manager.ts +4 -15
  159. package/src/runtime/channels/channel-socket-registry.ts +69 -71
  160. package/src/runtime/channels/channel-transports.ts +0 -3
  161. package/src/runtime/channels/fanout-location-runtime.ts +4 -16
  162. package/src/runtime/execution/index.ts +68 -30
  163. package/src/runtime/execution/serial-execution-queue.ts +52 -20
  164. package/src/runtime/foundation/listener-records.ts +21 -0
  165. package/src/runtime/foundation/raw-service-mesh-runtime.ts +66 -466
  166. package/src/runtime/foundation/service-authority-payload-codec.ts +10 -0
  167. package/src/runtime/foundation/service-maintenance-runtime.ts +30 -9
  168. package/src/runtime/foundation/service-relocation-coordinator.ts +13 -0
  169. package/src/runtime/foundation/service-relocation-object-owner.ts +18 -5
  170. package/src/runtime/foundation/service-session-binding-ingress-port.ts +6 -14
  171. package/src/runtime/foundation/service-stateful-runtime.ts +151 -89
  172. package/src/runtime/foundation/service-stateful-wire-codec.ts +203 -121
  173. package/src/runtime/foundation/service-topology-registry.ts +8 -48
  174. package/src/runtime/host/actor-transfer-runtime.ts +94 -166
  175. package/src/runtime/host/index.ts +119 -54
  176. package/src/runtime/host/remote-bound-session-relay.ts +4 -3
  177. package/src/runtime/host/route-mesh-runtime.ts +9 -5
  178. package/src/runtime/host/service-relocation-host-runtime.ts +495 -376
  179. package/src/runtime/host/spot-runtime-options-factory.ts +24 -13
  180. package/src/runtime/host/stateful-authority-route-runtime.ts +8 -4
  181. package/src/runtime/host/user-spot-creation-coordinator.ts +147 -142
  182. package/src/runtime/locations/in-memory-provider-location-store.ts +11 -7
  183. package/src/runtime/locations/lifecycle.ts +3 -2
  184. package/src/runtime/locations/resolvers.ts +19 -13
  185. package/src/runtime/locations/spot-location-claims.ts +5 -34
  186. package/src/runtime/protocol/service_wire_codec.generated.ts +9 -2
  187. package/src/runtime/protocol/service_wire_pilot_codec.generated.ts +4 -4
  188. package/src/runtime/spots/formal-remote-actor-admission-registry.ts +6 -6
  189. package/src/runtime/spots/formal-remote-actor-transfer-registry.ts +3 -3
  190. package/src/runtime/spots/index.ts +341 -295
  191. package/src/runtime/spots/spot-activation-registry.ts +41 -31
  192. package/src/runtime/spots/spot-activation-state.ts +4 -16
  193. package/src/runtime/spots/spot-activation.ts +102 -80
  194. package/src/runtime/spots/spot-actor-admission-coordinator.ts +2 -2
  195. package/src/runtime/spots/spot-actor-join-dispatch.ts +6 -7
  196. package/src/runtime/spots/spot-actor-lifecycle-drain.ts +20 -18
  197. package/src/runtime/spots/spot-actor-membership.ts +81 -17
  198. package/src/runtime/spots/spot-entry-activation.ts +0 -3
  199. package/src/runtime/spots/spot-manager-public.ts +8 -4
  200. package/src/runtime/spots/spot-native-actor-join-admission.ts +2 -2
  201. package/src/runtime/spots/spot-node-runtime-manager.ts +12 -18
  202. package/src/runtime/spots/spot-outbound.ts +4 -47
  203. package/src/runtime/spots/spot-routed-actor-admission.ts +20 -0
  204. package/src/runtime/spots/spot-routed-frame-dispatch.ts +6 -76
  205. package/src/runtime/spots/spot-runtime-ports.ts +6 -17
  206. package/src/runtime/spots/spot-serial-executor.ts +9 -1
  207. package/src/runtime/spots/spot-serial-turn-executor.ts +10 -4
  208. package/src/runtime/streams/actor-session-binding-registry.ts +20 -308
  209. package/src/runtime/streams/actor-session-binding-runtime-owner.ts +2 -12
  210. package/src/runtime/streams/bound-session-service.ts +2 -36
  211. package/src/runtime/streams/index.ts +29 -27
  212. package/src/runtime/streams/session-serial-executor.ts +2 -2
  213. package/dist/runtime/actors/deferred-join-accepted-journal.d.ts +0 -47
  214. package/dist/runtime/actors/deferred-join-accepted-journal.js +0 -992
  215. package/src/runtime/actors/deferred-join-accepted-journal.ts +0 -1346
@@ -1,3 +1,4 @@
1
+ import { ZLinkListenerRecords } from '../foundation/listener-records';
1
2
  import {
2
3
  ZLinkFrameworkInternalErrorKind,
3
4
  createInternalFrameworkException,
@@ -35,6 +36,8 @@ import type {
35
36
  ZLinkClientServerRuntime,
36
37
  ZLinkFanoutRuntime,
37
38
  ZLinkFrameworkRuntime,
39
+ ZLinkListenerKind,
40
+ ZLinkListenerStatus,
38
41
  ZLinkFrameworkLifecycleOptions,
39
42
  ZLinkFrameworkRelocationOptions,
40
43
  ZLinkFrameworkRelocationResult,
@@ -163,7 +166,9 @@ import { ZLinkChannelRuntimeOptionsFactory } from './channel-runtime-options-fac
163
166
  import { ZLinkSpotNodeRuntimeOptionsFactory } from './spot-node-runtime-options-factory';
164
167
  import { rollbackRuntimeStart, stopRuntimeParts } from './runtime-shutdown';
165
168
  import { ZLinkRuntimeAdmissionGate } from '../admission';
169
+ import { ZLinkActivationAdmission } from '../activation-admission';
166
170
  import { ZLinkRetiringRollbackError, ZLinkRouteMeshRuntimeCoordinator } from './route-mesh-runtime';
171
+ import { ServiceRelocationAuthorityError } from '../foundation/service-relocation-coordinator';
167
172
  import { ZLinkConfigurationException } from '../../contracts/Configuration/ConfigurationException';
168
173
  import { ZLinkStatefulAuthorityRouteRuntime } from './stateful-authority-route-runtime';
169
174
  import { ZLinkInstanceActivationAuthority } from './instance-activation-authority';
@@ -245,6 +250,7 @@ export class ZLinkFrameworkRuntimeHost
245
250
  private actorManager?: DefaultZLinkActorManager;
246
251
  private actorPlacement?: ZLinkActorPlacementCoordinator;
247
252
  private spotManager?: DefaultZLinkSpotManager;
253
+ private userSpotCoordinator?: ZLinkUserSpotCreationCoordinator;
248
254
  private ownerLeaseRecoveryRuntime?: ZLinkLocationRuntime;
249
255
  private ownerLeaseRecoveryHandler?: () => void;
250
256
  private registerUserSpotHandlers?: (runtime: ZLinkSpotNodeRuntimeManager) => void;
@@ -256,6 +262,19 @@ export class ZLinkFrameworkRuntimeHost
256
262
  private readonly metricRegistrations: import('../diagnostics').ZLinkRuntimeMetricRegistration[] =
257
263
  [];
258
264
  private readonly admission = new ZLinkRuntimeAdmissionGate(() => this.ownerAdmissionOpen());
265
+ private readonly activationAdmission = new ZLinkActivationAdmission(
266
+ (meshName) =>
267
+ this.options.registration.spotNodes.get(meshName)?.activationConcurrencyLimit ?? 128,
268
+ (meshName) => {
269
+ void this.spotNodeRuntime
270
+ ?.publishMeshNodeState(
271
+ this.runtimeState,
272
+ this.executionState?.abortController.signal,
273
+ meshName
274
+ )
275
+ .catch(() => undefined);
276
+ }
277
+ );
259
278
  private cachedLocationSpotRouteResolver?: ZLinkSpotRouteResolver;
260
279
  private actorClientLocationResolver?: ZLinkStoreLocationResolvers;
261
280
  // Shared, runtime-mutable message-flow mode cell — installed once so
@@ -698,7 +717,6 @@ export class ZLinkFrameworkRuntimeHost
698
717
  actorTransferRegistry: this.actorTransferRegistry,
699
718
  authorityStore: () => this.locationOwner.currentStores?.locationStore,
700
719
  currentOwner: () => this.locationOwner.currentRuntime?.currentOwnerToken,
701
- relocationStore: () => this.options.registration.locations.relocationStoreInstance,
702
720
  liveDescriptors: (meshName, signal) => {
703
721
  const runtime = this.locationOwner.currentRuntime;
704
722
  if (runtime === undefined) {
@@ -795,7 +813,8 @@ export class ZLinkFrameworkRuntimeHost
795
813
  reconcileStatefulAuthorityRoutes: (signal) =>
796
814
  this.statefulAuthorityRoutes?.reconcile(signal) ?? Promise.resolve(),
797
815
  runtimeEventPublisher: this.runtimeEventPublisher,
798
- metrics: this.metrics
816
+ metrics: this.metrics,
817
+ activationAdmission: this.activationAdmission
799
818
  });
800
819
  this.actorTransferAuthorityRuntime = new ZLinkActorTransferAuthorityRuntime({
801
820
  store: () => this.locationOwner.actorTransferStore() as never,
@@ -828,6 +847,7 @@ export class ZLinkFrameworkRuntimeHost
828
847
  },
829
848
  hostState: () => this.runtimeState,
830
849
  admission: this.admission,
850
+ activationAdmission: this.activationAdmission,
831
851
  publishRetiring: (meshName, signal) => this.publishMeshRetiring(meshName, signal),
832
852
  rollbackRetiring: (meshName, signal) => this.publishMeshServing(meshName, signal),
833
853
  publishDraining: (meshName, signal) => this.publishMeshDraining(meshName, signal),
@@ -868,6 +888,19 @@ export class ZLinkFrameworkRuntimeHost
868
888
  };
869
889
  }
870
890
 
891
+ // Bound listener records of the current runtime generation.
892
+ private listenerRecords = new ZLinkListenerRecords();
893
+
894
+ getListenerStatus(kind: ZLinkListenerKind, name: string): ZLinkListenerStatus {
895
+ const endpoint = this.listenerRecords.endpoint(kind, name);
896
+ if (endpoint === undefined || endpoint.length === 0) {
897
+ throw new ZLinkConfigurationException(
898
+ `Listener '${kind}:${name}' is not configured or has not bound.`
899
+ );
900
+ }
901
+ return { kind, name, endpoint, observedAt: new Date() };
902
+ }
903
+
871
904
  observe(signal?: AbortSignal): AsyncIterable<ZLinkObservedStatus<ZLinkFrameworkRuntimeStatus>> {
872
905
  const queue = new RuntimeEventQueue<ZLinkFrameworkRuntimeStatus>(undefined, signal);
873
906
  this.runtimeObservers.add(queue);
@@ -1021,6 +1054,17 @@ export class ZLinkFrameworkRuntimeHost
1021
1054
  stopStartingSignal
1022
1055
  );
1023
1056
  if (drained.kind === 'forceStopped') {
1057
+ // Settled authority on both sides or an expired source owner lease
1058
+ // ends the host in Error (spec 30 §13).
1059
+ if (drained.error instanceof ServiceRelocationAuthorityError) {
1060
+ return this.completeRelocation(
1061
+ blockedRelocation(
1062
+ mode,
1063
+ effectiveTargetApplicationVersion,
1064
+ ZLinkFrameworkRelocationReason.RelocationFailed
1065
+ )
1066
+ );
1067
+ }
1024
1068
  return this.resetBlockedRelocation(
1025
1069
  blockedRelocation(
1026
1070
  mode,
@@ -1322,6 +1366,8 @@ export class ZLinkFrameworkRuntimeHost
1322
1366
 
1323
1367
  this.setRuntimeState(ZLinkFrameworkRuntimeState.Preparing);
1324
1368
  this.lifecycleSink?.push('framework:start');
1369
+ const listenerRecords = new ZLinkListenerRecords();
1370
+ this.listenerRecords = listenerRecords;
1325
1371
  const channelAdapter = this.backendAdapterFactory.createChannelAdapter();
1326
1372
  const context = channelAdapter.createContext();
1327
1373
  const coreHwm = this.options.registration.coreHwm;
@@ -1344,13 +1390,14 @@ export class ZLinkFrameworkRuntimeHost
1344
1390
  channelAdapter,
1345
1391
  context,
1346
1392
  this.options.providerResolver,
1347
- this.createChannelRuntimeOptions()
1393
+ { ...this.createChannelRuntimeOptions(), listenerRecords }
1348
1394
  );
1349
1395
  this.channelRuntime = channelRuntime;
1350
1396
  channelRuntime.prepareMeshDispatch(this.executionState.taskRunner);
1351
- spotNodeRuntime = new ZLinkSpotNodeRuntimeManager(
1352
- this.createSpotNodeRuntimeOptions(context, dispatchErrors)
1353
- );
1397
+ spotNodeRuntime = new ZLinkSpotNodeRuntimeManager({
1398
+ ...this.createSpotNodeRuntimeOptions(context, dispatchErrors),
1399
+ listenerRecords
1400
+ });
1354
1401
  await spotNodeRuntime.start();
1355
1402
  this.spotNodeRuntime = spotNodeRuntime;
1356
1403
  this.registerUserSpotHandlers?.(spotNodeRuntime);
@@ -1386,6 +1433,7 @@ export class ZLinkFrameworkRuntimeHost
1386
1433
  }
1387
1434
  }
1388
1435
  streamRuntime = new ZLinkStreamRuntimeManager({
1436
+ listenerRecords,
1389
1437
  registration: this.options.registration,
1390
1438
  backendAdapterFactory: this.backendAdapterFactory,
1391
1439
  context,
@@ -1477,7 +1525,7 @@ export class ZLinkFrameworkRuntimeHost
1477
1525
  reserved: capacity.reserved,
1478
1526
  limit: capacity.limit
1479
1527
  })),
1480
- activation: descriptor?.activationConcurrency ?? { active: 0, limit: 0 },
1528
+ activation: this.activationAdmission.current(meshName),
1481
1529
  instanceSpots: []
1482
1530
  });
1483
1531
  }
@@ -1515,6 +1563,7 @@ export class ZLinkFrameworkRuntimeHost
1515
1563
  serviceRelocation: this.serviceRelocation,
1516
1564
  ownedStores: registeredRuntimeStores(this.options.registration)
1517
1565
  });
1566
+ this.listenerRecords.clear();
1518
1567
  this.lifecycleSink?.push('framework:stopped');
1519
1568
  if (this.shutdownOperation === undefined) {
1520
1569
  this.setRuntimeState(ZLinkFrameworkRuntimeState.Stopped);
@@ -1608,6 +1657,11 @@ export class ZLinkFrameworkRuntimeHost
1608
1657
  ): void {
1609
1658
  for (const [meshName, node] of spotNodeRuntime.meshNodesByName) {
1610
1659
  const activationNode = node as typeof node & {
1660
+ setSpotAdmissionProvider?: (provider: {
1661
+ isClosing(spotId: string): boolean;
1662
+ awaitCloseDecision(spotId: string): Promise<void> | undefined;
1663
+ runtimeState(): ZLinkFrameworkRuntimeState;
1664
+ }) => void;
1611
1665
  registerAsyncInstanceActivationAuthority?: (
1612
1666
  authority: ServiceAsyncInstanceActivationAuthority
1613
1667
  ) => void;
@@ -1623,6 +1677,11 @@ export class ZLinkFrameworkRuntimeHost
1623
1677
  };
1624
1678
  const spotManager = this.spotManager;
1625
1679
  if (spotManager !== undefined) {
1680
+ activationNode.setSpotAdmissionProvider?.({
1681
+ isClosing: (spotId) => spotManager.isSpotClosing(meshName, spotId),
1682
+ awaitCloseDecision: (spotId) => spotManager.pendingSpotCloseDecision(meshName, spotId),
1683
+ runtimeState: () => this.runtimeState
1684
+ });
1626
1685
  this.registerInstanceApplicationLifecycle(meshName, activationNode, spotManager);
1627
1686
  }
1628
1687
  activationNode.registerAsyncInstanceActivationAuthority?.(
@@ -1906,6 +1965,19 @@ export class ZLinkFrameworkRuntimeHost
1906
1965
  setSpotManager(spotManager: DefaultZLinkSpotManager): void {
1907
1966
  this.spotManager = spotManager;
1908
1967
  for (const [meshName, node] of this.spotNodeRuntime?.meshNodesByName ?? []) {
1968
+ const admissionNode = node as typeof node & {
1969
+ setSpotAdmissionProvider?: (provider: {
1970
+ isClosing(spotId: string): boolean;
1971
+ awaitCloseDecision(spotId: string): Promise<void> | undefined;
1972
+ runtimeState(): ZLinkFrameworkRuntimeState;
1973
+ }) => void;
1974
+ };
1975
+ admissionNode.setSpotAdmissionProvider?.({
1976
+ isClosing: (spotId: string) => spotManager.isSpotClosing(meshName, spotId),
1977
+ awaitCloseDecision: (spotId: string) =>
1978
+ spotManager.pendingSpotCloseDecision(meshName, spotId),
1979
+ runtimeState: () => this.runtimeState
1980
+ });
1909
1981
  this.registerInstanceApplicationLifecycle(meshName, node, spotManager);
1910
1982
  }
1911
1983
  }
@@ -1926,11 +1998,13 @@ export class ZLinkFrameworkRuntimeHost
1926
1998
  | 'boundSessionFactory'
1927
1999
  | 'shutdownSignal'
1928
2000
  | 'admission'
2001
+ | 'activationAdmission'
1929
2002
  | 'placementCreate'
1930
2003
  > {
1931
2004
  this.ensureLocationRuntime();
1932
2005
  return {
1933
2006
  ...this.actorRuntimeOptionsFactory().createActorManagerOptions(),
2007
+ activationAdmission: this.activationAdmission,
1934
2008
  placementCreate: async (actorId, actorType, createOnly, call, signal) => {
1935
2009
  const placement = this.actorPlacement;
1936
2010
  if (placement === undefined) {
@@ -1992,12 +2066,31 @@ export class ZLinkFrameworkRuntimeHost
1992
2066
  ?.meshNode(meshName)
1993
2067
  ?.completeClosedInstance?.(spotId, objectGeneration);
1994
2068
  },
1995
- beginInstanceIdleClosingAuthority: (meshName, spotId) =>
1996
- this.locationOwner.currentLifecycle?.beginInstanceSpotClosing(meshName, spotId) ??
1997
- Promise.resolve(undefined),
1998
- beginInstanceClosingAuthority: (meshName, spotId) =>
1999
- this.locationOwner.currentLifecycle?.beginInstanceSpotClosing(meshName, spotId) ??
2000
- Promise.resolve(undefined),
2069
+ beginInstanceIdleClosingAuthority: (meshName, spotId, onCommitted) =>
2070
+ this.locationOwner.currentLifecycle?.beginInstanceSpotClosing(
2071
+ meshName,
2072
+ spotId,
2073
+ onCommitted
2074
+ ) ?? Promise.resolve(undefined),
2075
+ beginInstanceClosingAuthority: (meshName, spotId, onCommitted) =>
2076
+ this.locationOwner.currentLifecycle?.beginInstanceSpotClosing(
2077
+ meshName,
2078
+ spotId,
2079
+ onCommitted
2080
+ ) ?? Promise.resolve(undefined),
2081
+ beginUserClosingAuthority: async (meshName, spotId, objectGeneration, onCommitted) => {
2082
+ const coordinator = this.userSpotCoordinator;
2083
+ const nodeRid = this.spotNodeRuntime?.meshNode(meshName)?.status().routingId;
2084
+ if (coordinator === undefined || nodeRid === undefined) {
2085
+ throw new ZLinkConfigurationException(
2086
+ 'User Spot context Close requires its authority coordinator.'
2087
+ );
2088
+ }
2089
+ return await coordinator.beginOwnerClose(
2090
+ { spotId: spotId as never, objectGeneration, meshName, nodeRid },
2091
+ onCommitted
2092
+ );
2093
+ },
2001
2094
  createLocationSpotRouteResolver: () => this.createLocationSpotRouteResolver(),
2002
2095
  boundSessionRelay: this.boundSessionRelay,
2003
2096
  actorHandoff: this.actorHandoff,
@@ -2008,17 +2101,7 @@ export class ZLinkFrameworkRuntimeHost
2008
2101
  admission: this.admission,
2009
2102
  statefulExecutionAllowed: () => this.ownerAdmissionOpen()
2010
2103
  }).create(this.actorTransferRuntime),
2011
- activationConcurrencyLimitProvider: (meshName: string) =>
2012
- this.options.registration.spotNodes.get(meshName)?.activationConcurrencyLimit ?? 128,
2013
- onInstanceActivationConcurrencyChanged: (meshName: string) => {
2014
- void this.spotNodeRuntime
2015
- ?.publishMeshNodeState(
2016
- this.runtimeState,
2017
- this.executionState?.abortController.signal,
2018
- meshName
2019
- )
2020
- .catch(() => undefined);
2021
- }
2104
+ activationAdmission: this.activationAdmission
2022
2105
  };
2023
2106
  }
2024
2107
 
@@ -2123,7 +2206,7 @@ export class ZLinkFrameworkRuntimeHost
2123
2206
  };
2124
2207
  }
2125
2208
  });
2126
- const coordinator = new ZLinkUserSpotCreationCoordinator({
2209
+ const coordinator = (this.userSpotCoordinator = new ZLinkUserSpotCreationCoordinator({
2127
2210
  store: locationStore,
2128
2211
  publishReadyRoute: (meshName, route) => {
2129
2212
  this.cachedLocationSpotRouteResolver?.invalidate?.(route.spot.spotId);
@@ -2231,7 +2314,7 @@ export class ZLinkFrameworkRuntimeHost
2231
2314
  localStatus.lifecycleGeneration === selected.lifecycleGeneration
2232
2315
  };
2233
2316
  }
2234
- });
2317
+ }));
2235
2318
  const factories = new Map(
2236
2319
  [...this.options.registration.spotNodes].map(([meshName, node]) => [
2237
2320
  meshName,
@@ -2428,23 +2511,6 @@ export class ZLinkFrameworkRuntimeHost
2428
2511
  );
2429
2512
  },
2430
2513
  close: async (record, signal) => {
2431
- if (!local.hasActiveSpot(record.target.spotId as never)) {
2432
- throw createInternalFrameworkException(
2433
- ZLinkFrameworkInternalErrorKind.SpotMoving,
2434
- `User Spot '${record.target.spotId}' is not materialized on its authority owner.`,
2435
- true
2436
- );
2437
- }
2438
- if (!local.canCloseUserSpot(meshName, record.target.spotId as never)) {
2439
- return {
2440
- terminalResult: RequestResult.Ok,
2441
- failureCode: 0,
2442
- tail: {
2443
- kind: 'userSpotClose' as const,
2444
- closed: false
2445
- }
2446
- };
2447
- }
2448
2514
  return {
2449
2515
  terminalResult: RequestResult.Ok,
2450
2516
  failureCode: 0,
@@ -2452,8 +2518,15 @@ export class ZLinkFrameworkRuntimeHost
2452
2518
  kind: 'userSpotClose' as const,
2453
2519
  closed: await coordinator.handleRemoteClose(
2454
2520
  record,
2455
- (spot, closeSignal) => local.close(spot.meshName, spot.spotId, closeSignal),
2456
- signal
2521
+ (spot, beginAuthority, closeSignal) =>
2522
+ local.closeUserWithAuthority(
2523
+ spot.meshName,
2524
+ spot.spotId,
2525
+ beginAuthority,
2526
+ closeSignal
2527
+ ),
2528
+ signal,
2529
+ (spot) => local.isSpotClosing(spot.meshName, spot.spotId)
2457
2530
  )
2458
2531
  }
2459
2532
  };
@@ -2655,15 +2728,7 @@ export class ZLinkFrameworkRuntimeHost
2655
2728
  record,
2656
2729
  this.executionState?.abortController.signal
2657
2730
  ),
2658
- instanceActivationConcurrencyProvider: (meshName: string) => {
2659
- return (
2660
- this.spotManager?.instanceActivationConcurrency(meshName) ?? {
2661
- active: 0,
2662
- limit:
2663
- this.options.registration.spotNodes.get(meshName)?.activationConcurrencyLimit ?? 128
2664
- }
2665
- );
2666
- }
2731
+ activationConcurrency: (meshName: string) => this.activationAdmission.current(meshName)
2667
2732
  };
2668
2733
  }
2669
2734
 
@@ -528,7 +528,7 @@ export class ZLinkRemoteBoundSessionRelay {
528
528
  const owner = actorSessionBindingRuntimeOwner(runtime);
529
529
  const fingerprint = encodeSessionRelocationRoute(value).toString('base64');
530
530
  if (value.route.action === 'abort') {
531
- await owner.applyRelocation(value.actor.actorId, key, fingerprint, 'abort', async () => {
531
+ await owner.applyRelocation(value.actor.actorId, key, fingerprint, async () => {
532
532
  if (!(await runtime.abortActorRouteSeal(value.actor.actorId, key))) {
533
533
  throw new ZLinkRemoteBoundSessionFenceError(
534
534
  `Actor '${value.actor.actorId}' command 44 abort lost its Session seal.`
@@ -550,9 +550,10 @@ export class ZLinkRemoteBoundSessionRelay {
550
550
  nodeRid: decodeWireRoutingId(committedRoute.targetNodeRid, undefined),
551
551
  bindingGeneration: value.session.bindingGeneration,
552
552
  ownershipGeneration: committedRoute.targetAuthorityOwnerGeneration,
553
- ownerNodeGeneration: committedRoute.targetNodeGeneration
553
+ ownerNodeGeneration: committedRoute.targetNodeGeneration,
554
+ ownerLeaseGeneration: committedRoute.targetOwnerLeaseGeneration
554
555
  } as ActorRef;
555
- await owner.applyRelocation(value.actor.actorId, key, fingerprint, 'commit', async () => {
556
+ await owner.applyRelocation(value.actor.actorId, key, fingerprint, async () => {
556
557
  await runtime.commitActorRoute(targetActorRef, undefined, {
557
558
  confirmRemoteSessionBinding: 'send',
558
559
  releaseSeal: { sealId: key }
@@ -35,6 +35,7 @@ type ZLinkMeshDrainResult =
35
35
  };
36
36
  import type { ZLinkBackendMeshNode } from '../backend';
37
37
  import type { ZLinkRuntimeAdmissionGate } from '../admission';
38
+ import type { ZLinkActivationAdmission } from '../activation-admission';
38
39
  import type { ZLinkSpotNodeOptions } from '../configuration';
39
40
  import { ZLinkObjectRole, type ZLinkMeshNodeDescriptor } from '../../contracts';
40
41
 
@@ -47,6 +48,7 @@ export interface ZLinkRouteMeshRuntimeCoordinatorOptions {
47
48
  readonly isLocationStoreHealthy?: () => boolean;
48
49
  readonly hostState?: () => ZLinkFrameworkRuntimeState;
49
50
  readonly admission: ZLinkRuntimeAdmissionGate;
51
+ readonly activationAdmission?: ZLinkActivationAdmission;
50
52
  readonly publishRetiring: (meshName: string, signal: AbortSignal) => Promise<void>;
51
53
  readonly rollbackRetiring: (meshName: string, signal: AbortSignal) => Promise<void>;
52
54
  readonly publishDraining: (meshName: string, signal: AbortSignal) => Promise<void>;
@@ -113,18 +115,20 @@ export class ZLinkRouteMeshRuntimeCoordinator implements ZLinkRouteMeshRuntime {
113
115
  const status = node.status();
114
116
  const descriptor = this.options.meshNodeDescriptor?.(meshName);
115
117
  const localPlacementCounts = this.options.localPlacementCounts?.(meshName);
118
+ // Active counts come only from this MeshNode's activation records (runtime monitoring §5);
119
+ // before the object managers exist nothing is active on it.
116
120
  const populationCapacity =
117
- descriptor === undefined || localPlacementCounts === undefined
118
- ? descriptor?.populationCapacity
121
+ descriptor === undefined
122
+ ? undefined
119
123
  : {
120
124
  ...descriptor.populationCapacity,
121
125
  actors: {
122
126
  ...descriptor.populationCapacity.actors,
123
- active: localPlacementCounts.activeActorCount
127
+ active: localPlacementCounts?.activeActorCount ?? 0
124
128
  },
125
129
  spots: {
126
130
  ...descriptor.populationCapacity.spots,
127
- active: localPlacementCounts.activeSpotCount
131
+ active: localPlacementCounts?.activeSpotCount ?? 0
128
132
  }
129
133
  };
130
134
  const backendPeers = node.peers();
@@ -180,7 +184,7 @@ export class ZLinkRouteMeshRuntimeCoordinator implements ZLinkRouteMeshRuntime {
180
184
  const capacityAvailable =
181
185
  descriptor !== undefined &&
182
186
  populationCapacity !== undefined &&
183
- hasRemainingCapacity(descriptor.activationConcurrency) &&
187
+ (this.options.activationAdmission?.hasHeadroom(meshName) ?? true) &&
184
188
  (hasRemainingCapacity(populationCapacity.actors) ||
185
189
  hasRemainingCapacity(populationCapacity.spots));
186
190
  const placementAvailable =