@zlink-systems/framework 0.25.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
@@ -4,6 +4,7 @@ exports.ZLinkActorTransferRuntime = void 0;
4
4
  exports.committedActorOwnerFence = committedActorOwnerFence;
5
5
  const node_crypto_1 = require("node:crypto");
6
6
  const contracts_1 = require("../../contracts");
7
+ const runtime_message_1 = require("../backend/runtime-message");
7
8
  const authority_key_codec_1 = require("../locations/authority-key-codec");
8
9
  const actors_1 = require("../actors");
9
10
  const actor_retry_delay_1 = require("../actors/actor-retry-delay");
@@ -56,19 +57,21 @@ class ZLinkActorTransferRuntime {
56
57
  options;
57
58
  sourceDepartureTasks = new Map();
58
59
  coreSourceLeaves = new Map();
60
+ // Spot Actor membership sections 4-5: Join completion idempotency is
61
+ // process-local. These maps end with the process; nothing is replayed.
59
62
  activeDeferredJoinTerminals = new Map();
60
63
  deferredJoinTerminals = new bounded_replay_map_1.BoundedReplayMap(DEFERRED_JOIN_TERMINAL_CAPACITY);
61
64
  constructor(options) {
62
65
  this.options = options;
63
66
  }
64
- beginDeferredActorHandoff(actor, state, operationId) {
67
+ beginDeferredActorHandoff(actor, state) {
65
68
  const actorId = actor.context.actorId;
66
- this.options.actorHandoff.beginProvisional(actorId, operationId, requireSourceObjectGeneration(actorId, state));
69
+ this.options.actorHandoff.beginProvisional(actorId, requireSourceObjectGeneration(actorId, state));
67
70
  }
68
- promoteDeferredActorHandoff(actor, _state, operationId) {
69
- this.options.actorHandoff.promoteProvisional(actor.context.actorId, operationId);
71
+ promoteDeferredActorHandoff(actor, _state) {
72
+ this.options.actorHandoff.promoteProvisional(actor.context.actorId);
70
73
  }
71
- async completeDeferredActorHandoff(actor, target, _targetActorRef, operationId) {
74
+ async completeDeferredActorHandoff(actor, target, _targetActorRef) {
72
75
  const actorId = actor.context.actorId;
73
76
  if (!this.options.actorHandoff.isProvisional(actorId))
74
77
  return;
@@ -76,91 +79,69 @@ class ZLinkActorTransferRuntime {
76
79
  if (manager === undefined) {
77
80
  throw new Error(`Actor '${actorId}' same-node Join has no local Spot manager.`);
78
81
  }
79
- const admitted = this.options.actorHandoff.admitDeferredPrefix(actorId, operationId, (drain) => manager.admitRoutedActorPacketPrefix(target.spotId, actorId, drain), this.options.prepareApplicationJob);
82
+ const admitted = this.options.actorHandoff.admitDeferredPrefix(actorId, (drain) => manager.admitRoutedActorPacketPrefix(target.spotId, actorId, drain), this.options.prepareApplicationJob);
80
83
  void this.observeHandoffReplay(admitted.terminal);
81
84
  }
82
- async cancelDeferredActorHandoff(actor, _state, operationId) {
83
- const admitted = this.admitDeferredSourcePrefix(actor, _state, operationId);
85
+ async cancelDeferredActorHandoff(actor, state) {
86
+ const admitted = this.admitDeferredSourcePrefix(actor, state);
84
87
  void this.observeHandoffReplay(admitted.terminal);
85
88
  }
86
- async prepareDeferredJoinAccepted(actorId, operationId, actorRef, rawReply, replyContentType, signal, canonicalInventoryDigest) {
87
- return await this.requireDeferredJoinJournal().prepare(actorId, operationId, actorRef, rawReply, replyContentType, signal, canonicalInventoryDigest);
89
+ prepareDeferredJoinAccepted(actorId, operationId, actorRef, rawReply, replyContentType) {
90
+ return (0, actors_1.createDeferredJoinCompletion)(actorId, operationId, actorRef, rawReply, replyContentType);
88
91
  }
89
- async isDeferredJoinAcceptedRootPublication(reference, checksumCrc32c, expected, signal) {
90
- const relocation = this.options.relocationStore();
91
- return relocation === undefined
92
- ? false
93
- : await (0, actors_1.isDeferredJoinAcceptedRootPublication)(relocation, reference, checksumCrc32c, expected, signal);
94
- }
95
- async discardDeferredJoinAccepted(root, signal) {
96
- await this.requireDeferredJoinJournal().discardPrepared(root, signal);
97
- }
98
- markDeferredJoinAcceptedCommitted(root, actorRef, signal) {
99
- return this.requireDeferredJoinJournal().markCommitted(root, actorRef, signal);
100
- }
101
- async commitAndDeliverDeferredJoinAccepted(root, actor, actorRef, submitMailbox, signal) {
102
- const terminalKey = deferredJoinTerminalKey(root);
103
- const terminal = this.deferredJoinTerminals.get(terminalKey);
104
- if (terminal !== undefined) {
92
+ /**
93
+ * Runs the Accepted completion callback once in the target Actor mailbox.
94
+ * A repeated delivery of the same OperationId in this process observes the
95
+ * first terminal (completion idempotency only).
96
+ */
97
+ async deliverDeferredJoinAccepted(completion, actor, actorRef, submitMailbox, signal) {
98
+ const terminalKey = deferredJoinTerminalKey(completion);
99
+ if (this.deferredJoinTerminals.get(terminalKey) !== undefined) {
105
100
  this.deferredJoinTerminals.touch(terminalKey);
106
- return terminal;
101
+ return;
107
102
  }
108
103
  const active = this.activeDeferredJoinTerminals.get(terminalKey);
109
104
  if (active !== undefined)
110
105
  return await waitForOperation(active, signal);
111
- const completion = this.commitAndDeliverDeferredJoinAcceptedCore(root, actor, actorRef, submitMailbox);
112
- this.activeDeferredJoinTerminals.set(terminalKey, completion);
113
- void completion.then((completed) => {
114
- this.deferredJoinTerminals.remember(terminalKey, completed);
115
- if (this.activeDeferredJoinTerminals.get(terminalKey) === completion) {
106
+ const delivery = this.deliverDeferredJoinAcceptedCore(completion, actor, actorRef, submitMailbox);
107
+ this.activeDeferredJoinTerminals.set(terminalKey, delivery);
108
+ void delivery.then(() => {
109
+ this.deferredJoinTerminals.remember(terminalKey, true);
110
+ if (this.activeDeferredJoinTerminals.get(terminalKey) === delivery) {
116
111
  this.activeDeferredJoinTerminals.delete(terminalKey);
117
112
  }
118
113
  }, () => {
119
- if (this.activeDeferredJoinTerminals.get(terminalKey) === completion) {
114
+ if (this.activeDeferredJoinTerminals.get(terminalKey) === delivery) {
120
115
  this.activeDeferredJoinTerminals.delete(terminalKey);
121
116
  }
122
117
  });
123
- return await waitForOperation(completion, signal);
118
+ return await waitForOperation(delivery, signal);
124
119
  }
125
- async commitAndDeliverDeferredJoinAcceptedCore(root, actor, actorRef, submitMailbox) {
120
+ async deliverDeferredJoinAcceptedCore(completion, actor, actorRef, submitMailbox) {
126
121
  const targetActorRef = this.options
127
122
  .actorManager()
128
123
  ?.getState(actor.context.actorId)?.nativeActorRef;
129
124
  const currentActorRef = targetActorRef === undefined
130
125
  ? actorRef
131
126
  : (0, actors_1.toFrameworkActorRef)(targetActorRef, actor.context.meshName);
132
- let current = root.cursor === 'prepared'
133
- ? await this.requireDeferredJoinJournal().markCommitted(root, currentActorRef)
134
- : root;
135
- if (current.cursor === 'delivered')
136
- return current;
137
- let lastError;
138
- for (let attempt = 0; attempt < 3; attempt++) {
139
- try {
140
- current = await this.requireDeferredJoinJournal().deliver(current, actor, currentActorRef, submitMailbox);
141
- return current;
142
- }
143
- catch (error) {
144
- lastError = error;
145
- if (attempt < 2) {
146
- await new Promise((resolve) => {
147
- const timer = setTimeout(resolve, 10 << attempt);
148
- timer.unref();
149
- });
150
- current =
151
- (await this.requireDeferredJoinJournal().recover(currentActorRef.actorId)) ?? current;
152
- }
153
- }
154
- }
155
- throw lastError;
156
- }
157
- requireDeferredJoinJournal() {
158
- const authority = this.options.authorityStore();
159
- const relocation = this.options.relocationStore();
160
- if (authority === undefined || relocation === undefined) {
161
- throw new Error('Cross-node deferred Actor Join requires Location and Relocation Stores.');
162
- }
163
- return new actors_1.ZLinkDeferredJoinAcceptedJournal(authority, relocation, this.options.messageSerializers);
127
+ if (completion.actor.actorId !== currentActorRef.actorId ||
128
+ completion.actor.objectGeneration !== currentActorRef.objectGeneration) {
129
+ throw new Error('Deferred Join completion generation fence is stale ' +
130
+ `(completion ${completion.actor.actorId}/${completion.actor.objectGeneration}, ` +
131
+ `actor ${currentActorRef.actorId}/${currentActorRef.objectGeneration}).`);
132
+ }
133
+ await submitMailbox(async () => {
134
+ await actor.onJoinCompleted?.({
135
+ status: 'accepted',
136
+ operationId: completion.operationId,
137
+ actor: currentActorRef,
138
+ reply: completion.rawReply.byteLength === 0
139
+ ? undefined
140
+ : completion.replyContentType === undefined
141
+ ? contracts_1.ZLinkMessage.fromEncoded(contracts_1.ZLinkEncodedPayload.from(completion.rawReply))
142
+ : (0, payload_codec_1.wrapFrameworkPayloadMessage)(runtime_message_1.ZLinkBufferMessage.from(completion.rawReply), this.options.messageSerializers, completion.replyContentType, undefined, 'reply')
143
+ });
144
+ });
164
145
  }
165
146
  async prepareSourceActorLeave(actor, sourceSpotId, signal) {
166
147
  if (sourceSpotId !== undefined) {
@@ -182,10 +163,9 @@ class ZLinkActorTransferRuntime {
182
163
  }
183
164
  await this.options.restoreEntrySpotActorJoined(actor, signal);
184
165
  }
185
- async beginSourceActorMove(actor, state, deferredOperationId) {
186
- if (deferredOperationId !== undefined &&
187
- this.options.actorHandoff.isProvisional(actor.context.actorId)) {
188
- this.promoteDeferredActorHandoff(actor, state, deferredOperationId);
166
+ async beginSourceActorMove(actor, state, deferredJoin = false) {
167
+ if (deferredJoin && this.options.actorHandoff.isProvisional(actor.context.actorId)) {
168
+ this.promoteDeferredActorHandoff(actor, state);
189
169
  }
190
170
  state.beginMove();
191
171
  if (!this.options.actorHandoff.isActive(actor.context.actorId)) {
@@ -205,18 +185,18 @@ class ZLinkActorTransferRuntime {
205
185
  }
206
186
  }
207
187
  catch (error) {
208
- if (deferredOperationId === undefined) {
188
+ if (!deferredJoin) {
209
189
  this.options.actorHandoff.cancel(actor.context.actorId);
210
190
  }
211
191
  else {
212
- const admitted = this.admitDeferredSourcePrefix(actor, state, deferredOperationId);
192
+ const admitted = this.admitDeferredSourcePrefix(actor, state);
213
193
  void this.observeHandoffReplay(admitted.terminal);
214
194
  }
215
195
  state.endMove();
216
196
  throw error;
217
197
  }
218
198
  }
219
- async cancelSourceActorMove(actor, state, deferredOperationId, replayStart = Promise.resolve()) {
199
+ async cancelSourceActorMove(actor, state, deferredJoin = false, replayStart = Promise.resolve()) {
220
200
  try {
221
201
  if (state.spotId !== undefined) {
222
202
  await this.options.spotManager()?.cancelActorTransfer(state.spotId, actor.context.actorId);
@@ -224,12 +204,12 @@ class ZLinkActorTransferRuntime {
224
204
  }
225
205
  finally {
226
206
  try {
227
- if (deferredOperationId === undefined) {
207
+ if (!deferredJoin) {
228
208
  const admitted = this.admitCanceledSourcePrefix(actor, state, replayStart);
229
209
  void this.observeHandoffReplay(admitted.terminal);
230
210
  }
231
211
  else {
232
- const admitted = this.admitDeferredSourcePrefix(actor, state, deferredOperationId, replayStart);
212
+ const admitted = this.admitDeferredSourcePrefix(actor, state, replayStart);
233
213
  void this.observeHandoffReplay(admitted.terminal);
234
214
  }
235
215
  }
@@ -249,13 +229,13 @@ class ZLinkActorTransferRuntime {
249
229
  }
250
230
  return this.options.actorHandoff.admitCanceledPrefix(actor.context.actorId, queue, this.options.prepareApplicationJob, replayStart);
251
231
  }
252
- admitDeferredSourcePrefix(actor, state, operationId, replayStart = Promise.resolve()) {
232
+ admitDeferredSourcePrefix(actor, state, replayStart = Promise.resolve()) {
253
233
  const queue = this.sourceHandoffPrefixQueue(actor, state);
254
234
  if (queue === undefined) {
255
235
  this.options.actorHandoff.cancel(actor.context.actorId);
256
236
  return { terminal: Promise.resolve() };
257
237
  }
258
- return this.options.actorHandoff.admitDeferredPrefix(actor.context.actorId, operationId, queue, this.options.prepareApplicationJob, replayStart);
238
+ return this.options.actorHandoff.admitDeferredPrefix(actor.context.actorId, queue, this.options.prepareApplicationJob, replayStart);
259
239
  }
260
240
  async observeHandoffReplay(release) {
261
241
  try {
@@ -281,8 +261,8 @@ class ZLinkActorTransferRuntime {
281
261
  }
282
262
  return (drain) => manager.admitRoutedActorPacketPrefix(sourceSpotId, actor.context.actorId, drain);
283
263
  }
284
- async prepareSource(actor, state, signal, lifecycleAuthority = 'framework', deferredOperationId, relocation) {
285
- await this.beginSourceActorMove(actor, state, deferredOperationId);
264
+ async prepareSource(actor, state, signal, lifecycleAuthority = 'framework', deferredJoin = false, relocation) {
265
+ await this.beginSourceActorMove(actor, state, deferredJoin);
286
266
  const relocationMetric = state.meshName === undefined
287
267
  ? undefined
288
268
  : this.options.metrics?.startRelocation(state.meshName, 'actor', this.options.actorTransferRegistry.policy(state.actorType));
@@ -386,7 +366,7 @@ class ZLinkActorTransferRuntime {
386
366
  this.coreSourceLeaves.delete(actor.context.actorId);
387
367
  const replayGate = createHandoffReplayGate();
388
368
  try {
389
- await this.cancelSourceActorMove(actor, state, deferredOperationId, replayGate.start);
369
+ await this.cancelSourceActorMove(actor, state, deferredJoin, replayGate.start);
390
370
  await this.restoreSourceActor(actor, sourceSpotId);
391
371
  if (sealId !== undefined) {
392
372
  await this.observeBoundSessionSealAbort(actor, state);
@@ -402,7 +382,7 @@ class ZLinkActorTransferRuntime {
402
382
  relocationMetric?.complete('failed');
403
383
  const replayGate = createHandoffReplayGate();
404
384
  try {
405
- await this.cancelSourceActorMove(actor, state, deferredOperationId, replayGate.start);
385
+ await this.cancelSourceActorMove(actor, state, deferredJoin, replayGate.start);
406
386
  if (sourceLeaveStarted)
407
387
  await this.restoreSourceActor(actor, sourceSpotId);
408
388
  if (sealId !== undefined) {
@@ -465,6 +445,12 @@ class ZLinkActorTransferRuntime {
465
445
  terminal = 'committed';
466
446
  }
467
447
  },
448
+ discard: (reason) => {
449
+ if (terminal !== 'prepared')
450
+ return;
451
+ terminal = 'rolledBack';
452
+ this.options.actorHandoff.failPending(actor.context.actorId, reason);
453
+ },
468
454
  rollback: async () => {
469
455
  if (terminal !== 'prepared')
470
456
  return;
@@ -1201,7 +1187,8 @@ class ZLinkActorTransferRuntime {
1201
1187
  previousAuthorityOwnerGeneration: target.previousAuthorityOwnerGeneration,
1202
1188
  targetAuthorityOwnerGeneration: ownershipGeneration,
1203
1189
  targetNodeRid: String(actorRef.nodeRid),
1204
- targetNodeGeneration: authority.allocation.descriptorLifecycleGeneration
1190
+ targetNodeGeneration: authority.allocation.descriptorLifecycleGeneration,
1191
+ targetOwnerLeaseGeneration: authority.ownerLeaseGeneration
1205
1192
  }
1206
1193
  }, this.options.shutdownSignal?.());
1207
1194
  return;
@@ -1214,9 +1201,9 @@ function relocationDebug(marker, detail) {
1214
1201
  return;
1215
1202
  console.error('[zlink.runtime.relocation]', marker, detail);
1216
1203
  }
1217
- function deferredJoinTerminalKey(root) {
1218
- return (`${root.actor.actorId}:${root.actor.objectGeneration.toString()}:` +
1219
- (0, operation_identity_1.operationIdentityKey)(root.operationId));
1204
+ function deferredJoinTerminalKey(completion) {
1205
+ return (`${completion.actor.actorId}:${completion.actor.objectGeneration.toString()}:` +
1206
+ (0, operation_identity_1.operationIdentityKey)(completion.operationId));
1220
1207
  }
1221
1208
  function waitForOperation(operation, signal) {
1222
1209
  if (signal === undefined)
@@ -1,6 +1,6 @@
1
1
  import type { ZLinkBackendContext, ZLinkBackendMeshNode } from '../backend';
2
2
  import type { ZLinkFrameworkRegistration } from '../configuration';
3
- import type { ZLinkMeshNodeDescriptor, ZLinkClientServerRuntime, ZLinkFanoutRuntime, ZLinkFrameworkRuntime, ZLinkFrameworkLifecycleOptions, ZLinkFrameworkRelocationOptions, ZLinkFrameworkRelocationResult, ZLinkObservedStatus, ZLinkFrameworkRuntimeStatus, ZLinkFrameworkTerminationResult, ZLinkRouteMeshRuntime } from '../../contracts';
3
+ import type { ZLinkMeshNodeDescriptor, ZLinkClientServerRuntime, ZLinkFanoutRuntime, ZLinkFrameworkRuntime, ZLinkListenerKind, ZLinkListenerStatus, ZLinkFrameworkLifecycleOptions, ZLinkFrameworkRelocationOptions, ZLinkFrameworkRelocationResult, ZLinkObservedStatus, ZLinkFrameworkRuntimeStatus, ZLinkFrameworkTerminationResult, ZLinkRouteMeshRuntime } from '../../contracts';
4
4
  import type { ZLinkProviderResolver } from '../../contracts/Common/ZLinkProviderResolver';
5
5
  import type { ZLinkRuntimeEventPublisher } from '../diagnostics';
6
6
  import type { ZLinkMessageFlowControl, ZLinkMessageFlowLogMode } from '../../contracts';
@@ -61,6 +61,7 @@ export declare class ZLinkFrameworkRuntimeHost implements ZLinkFrameworkRuntimeL
61
61
  private actorManager?;
62
62
  private actorPlacement?;
63
63
  private spotManager?;
64
+ private userSpotCoordinator?;
64
65
  private ownerLeaseRecoveryRuntime?;
65
66
  private ownerLeaseRecoveryHandler?;
66
67
  private registerUserSpotHandlers?;
@@ -71,6 +72,7 @@ export declare class ZLinkFrameworkRuntimeHost implements ZLinkFrameworkRuntimeL
71
72
  private readonly capacityStatus;
72
73
  private readonly metricRegistrations;
73
74
  private readonly admission;
75
+ private readonly activationAdmission;
74
76
  private cachedLocationSpotRouteResolver?;
75
77
  private actorClientLocationResolver?;
76
78
  private readonly messageFlowModeCell;
@@ -94,6 +96,8 @@ export declare class ZLinkFrameworkRuntimeHost implements ZLinkFrameworkRuntimeL
94
96
  constructor(options: ZLinkFrameworkRuntimeHostOptions, internalOptions?: unknown);
95
97
  get isStarted(): boolean;
96
98
  get status(): ZLinkFrameworkRuntimeStatus;
99
+ private listenerRecords;
100
+ getListenerStatus(kind: ZLinkListenerKind, name: string): ZLinkListenerStatus;
97
101
  observe(signal?: AbortSignal): AsyncIterable<ZLinkObservedStatus<ZLinkFrameworkRuntimeStatus>>;
98
102
  resetCapacityMetrics(): void;
99
103
  relocate(options: ZLinkFrameworkRelocationOptions): Promise<ZLinkFrameworkRelocationResult>;
@@ -150,7 +154,7 @@ export declare class ZLinkFrameworkRuntimeHost implements ZLinkFrameworkRuntimeL
150
154
  private registerInstanceApplicationLifecycle;
151
155
  setActorManager(actorManager: DefaultZLinkActorManager): void;
152
156
  setSpotManager(spotManager: DefaultZLinkSpotManager): void;
153
- createActorManagerOptions(): Pick<ZLinkActorManagerOptions, 'joinCoordinator' | 'actorMeshNameProvider' | 'actorLeaveSpot' | 'messageSerializers' | 'nativeActorNode' | 'nativeActorNodeProvider' | 'actorCreatedNodeRidProvider' | 'actorRefResolver' | 'actorCreatedNotifier' | 'actorDestroyedCleanup' | 'locationLifecycle' | 'boundSessionFactory' | 'shutdownSignal' | 'admission' | 'placementCreate'>;
157
+ createActorManagerOptions(): Pick<ZLinkActorManagerOptions, 'joinCoordinator' | 'actorMeshNameProvider' | 'actorLeaveSpot' | 'messageSerializers' | 'nativeActorNode' | 'nativeActorNodeProvider' | 'actorCreatedNodeRidProvider' | 'actorRefResolver' | 'actorCreatedNotifier' | 'actorDestroyedCleanup' | 'locationLifecycle' | 'boundSessionFactory' | 'shutdownSignal' | 'admission' | 'activationAdmission' | 'placementCreate'>;
154
158
  createActorClientOptions(): ConstructorParameters<typeof DefaultZLinkActorClient>[0];
155
159
  createLocationHandleResolver(): ZLinkStoreLocationResolvers | undefined;
156
160
  createSpotManagerOptions(): Partial<ZLinkSpotManagerOptions>;
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.ZLinkUserSpotCreationCoordinator = exports.ZLinkHostSpotAddressTransport = exports.ZLinkRelocationStateIncompatibleError = exports.ZLinkRouteMeshRuntimeCoordinator = exports.ZLinkRetiringRollbackError = exports.transferIdString = exports.ZLinkActorTransferAuthorityRuntime = exports.ZLinkFrameworkRuntimeHost = void 0;
4
4
  exports.hasUnsupportedManualTopology = hasUnsupportedManualTopology;
5
5
  exports.hasExactPeerReadiness = hasExactPeerReadiness;
6
+ const listener_records_1 = require("../foundation/listener-records");
6
7
  const framework_errors_internal_1 = require("../framework-errors-internal");
7
8
  const node_crypto_1 = require("node:crypto");
8
9
  const runtime_message_1 = require("../backend/runtime-message");
@@ -46,7 +47,9 @@ const channel_runtime_options_factory_1 = require("./channel-runtime-options-fac
46
47
  const spot_node_runtime_options_factory_1 = require("./spot-node-runtime-options-factory");
47
48
  const runtime_shutdown_1 = require("./runtime-shutdown");
48
49
  const admission_1 = require("../admission");
50
+ const activation_admission_1 = require("../activation-admission");
49
51
  const route_mesh_runtime_1 = require("./route-mesh-runtime");
52
+ const service_relocation_coordinator_1 = require("../foundation/service-relocation-coordinator");
50
53
  const ConfigurationException_1 = require("../../contracts/Configuration/ConfigurationException");
51
54
  const stateful_authority_route_runtime_1 = require("./stateful-authority-route-runtime");
52
55
  const instance_activation_authority_1 = require("./instance-activation-authority");
@@ -95,6 +98,7 @@ class ZLinkFrameworkRuntimeHost {
95
98
  actorManager;
96
99
  actorPlacement;
97
100
  spotManager;
101
+ userSpotCoordinator;
98
102
  ownerLeaseRecoveryRuntime;
99
103
  ownerLeaseRecoveryHandler;
100
104
  registerUserSpotHandlers;
@@ -105,6 +109,11 @@ class ZLinkFrameworkRuntimeHost {
105
109
  capacityStatus;
106
110
  metricRegistrations = [];
107
111
  admission = new admission_1.ZLinkRuntimeAdmissionGate(() => this.ownerAdmissionOpen());
112
+ activationAdmission = new activation_admission_1.ZLinkActivationAdmission((meshName) => this.options.registration.spotNodes.get(meshName)?.activationConcurrencyLimit ?? 128, (meshName) => {
113
+ void this.spotNodeRuntime
114
+ ?.publishMeshNodeState(this.runtimeState, this.executionState?.abortController.signal, meshName)
115
+ .catch(() => undefined);
116
+ });
108
117
  cachedLocationSpotRouteResolver;
109
118
  actorClientLocationResolver;
110
119
  // Shared, runtime-mutable message-flow mode cell — installed once so
@@ -441,7 +450,6 @@ class ZLinkFrameworkRuntimeHost {
441
450
  actorTransferRegistry: this.actorTransferRegistry,
442
451
  authorityStore: () => this.locationOwner.currentStores?.locationStore,
443
452
  currentOwner: () => this.locationOwner.currentRuntime?.currentOwnerToken,
444
- relocationStore: () => this.options.registration.locations.relocationStoreInstance,
445
453
  liveDescriptors: (meshName, signal) => {
446
454
  const runtime = this.locationOwner.currentRuntime;
447
455
  if (runtime === undefined) {
@@ -527,7 +535,8 @@ class ZLinkFrameworkRuntimeHost {
527
535
  invalidateActorRoute: (actorId) => this.actorClientLocationResolver?.invalidateActorRoute(actorId),
528
536
  reconcileStatefulAuthorityRoutes: (signal) => this.statefulAuthorityRoutes?.reconcile(signal) ?? Promise.resolve(),
529
537
  runtimeEventPublisher: this.runtimeEventPublisher,
530
- metrics: this.metrics
538
+ metrics: this.metrics,
539
+ activationAdmission: this.activationAdmission
531
540
  });
532
541
  this.actorTransferAuthorityRuntime = new actor_transfer_authority_runtime_1.ZLinkActorTransferAuthorityRuntime({
533
542
  store: () => this.locationOwner.actorTransferStore(),
@@ -561,6 +570,7 @@ class ZLinkFrameworkRuntimeHost {
561
570
  },
562
571
  hostState: () => this.runtimeState,
563
572
  admission: this.admission,
573
+ activationAdmission: this.activationAdmission,
564
574
  publishRetiring: (meshName, signal) => this.publishMeshRetiring(meshName, signal),
565
575
  rollbackRetiring: (meshName, signal) => this.publishMeshServing(meshName, signal),
566
576
  publishDraining: (meshName, signal) => this.publishMeshDraining(meshName, signal),
@@ -590,6 +600,15 @@ class ZLinkFrameworkRuntimeHost {
590
600
  observedAt: new Date()
591
601
  };
592
602
  }
603
+ // Bound listener records of the current runtime generation.
604
+ listenerRecords = new listener_records_1.ZLinkListenerRecords();
605
+ getListenerStatus(kind, name) {
606
+ const endpoint = this.listenerRecords.endpoint(kind, name);
607
+ if (endpoint === undefined || endpoint.length === 0) {
608
+ throw new ConfigurationException_1.ZLinkConfigurationException(`Listener '${kind}:${name}' is not configured or has not bound.`);
609
+ }
610
+ return { kind, name, endpoint, observedAt: new Date() };
611
+ }
593
612
  observe(signal) {
594
613
  const queue = new runtime_observation_queue_1.RuntimeEventQueue(undefined, signal);
595
614
  this.runtimeObservers.add(queue);
@@ -704,6 +723,11 @@ class ZLinkFrameworkRuntimeHost {
704
723
  this.setRuntimeState(contracts_1.ZLinkFrameworkRuntimeState.Relocating);
705
724
  const drained = await this.routeMeshCoordinator.relocateHost(remainingDeadlineMs(), stopStartingSignal);
706
725
  if (drained.kind === 'forceStopped') {
726
+ // Settled authority on both sides or an expired source owner lease
727
+ // ends the host in Error (spec 30 §13).
728
+ if (drained.error instanceof service_relocation_coordinator_1.ServiceRelocationAuthorityError) {
729
+ return this.completeRelocation(blockedRelocation(mode, effectiveTargetApplicationVersion, contracts_1.ZLinkFrameworkRelocationReason.RelocationFailed));
730
+ }
707
731
  return this.resetBlockedRelocation(blockedRelocation(mode, effectiveTargetApplicationVersion, stopStartingSignal.aborted
708
732
  ? contracts_1.ZLinkFrameworkRelocationReason.ShutdownRequested
709
733
  : drained.error instanceof service_relocation_host_runtime_1.ZLinkRelocationStateIncompatibleError
@@ -947,6 +971,8 @@ class ZLinkFrameworkRuntimeHost {
947
971
  }
948
972
  this.setRuntimeState(contracts_1.ZLinkFrameworkRuntimeState.Preparing);
949
973
  this.lifecycleSink?.push('framework:start');
974
+ const listenerRecords = new listener_records_1.ZLinkListenerRecords();
975
+ this.listenerRecords = listenerRecords;
950
976
  const channelAdapter = this.backendAdapterFactory.createChannelAdapter();
951
977
  const context = channelAdapter.createContext();
952
978
  const coreHwm = this.options.registration.coreHwm;
@@ -964,10 +990,13 @@ class ZLinkFrameworkRuntimeHost {
964
990
  this.messageFlowModeCell.mode =
965
991
  this.options.registration.dispatch?.diagnostics.messageFlow ?? 'errors';
966
992
  const dispatchErrors = this.createDispatchErrorReporter(this.executionState.errorSink);
967
- channelRuntime = new channels_1.ZLinkChannelRuntimeManager(this.options.registration, channelAdapter, context, this.options.providerResolver, this.createChannelRuntimeOptions());
993
+ channelRuntime = new channels_1.ZLinkChannelRuntimeManager(this.options.registration, channelAdapter, context, this.options.providerResolver, { ...this.createChannelRuntimeOptions(), listenerRecords });
968
994
  this.channelRuntime = channelRuntime;
969
995
  channelRuntime.prepareMeshDispatch(this.executionState.taskRunner);
970
- spotNodeRuntime = new spots_1.ZLinkSpotNodeRuntimeManager(this.createSpotNodeRuntimeOptions(context, dispatchErrors));
996
+ spotNodeRuntime = new spots_1.ZLinkSpotNodeRuntimeManager({
997
+ ...this.createSpotNodeRuntimeOptions(context, dispatchErrors),
998
+ listenerRecords
999
+ });
971
1000
  await spotNodeRuntime.start();
972
1001
  this.spotNodeRuntime = spotNodeRuntime;
973
1002
  this.registerUserSpotHandlers?.(spotNodeRuntime);
@@ -991,6 +1020,7 @@ class ZLinkFrameworkRuntimeHost {
991
1020
  }
992
1021
  }
993
1022
  streamRuntime = new streams_1.ZLinkStreamRuntimeManager({
1023
+ listenerRecords,
994
1024
  registration: this.options.registration,
995
1025
  backendAdapterFactory: this.backendAdapterFactory,
996
1026
  context,
@@ -1076,7 +1106,7 @@ class ZLinkFrameworkRuntimeHost {
1076
1106
  reserved: capacity.reserved,
1077
1107
  limit: capacity.limit
1078
1108
  })),
1079
- activation: descriptor?.activationConcurrency ?? { active: 0, limit: 0 },
1109
+ activation: this.activationAdmission.current(meshName),
1080
1110
  instanceSpots: []
1081
1111
  });
1082
1112
  }
@@ -1112,6 +1142,7 @@ class ZLinkFrameworkRuntimeHost {
1112
1142
  serviceRelocation: this.serviceRelocation,
1113
1143
  ownedStores: registeredRuntimeStores(this.options.registration)
1114
1144
  });
1145
+ this.listenerRecords.clear();
1115
1146
  this.lifecycleSink?.push('framework:stopped');
1116
1147
  if (this.shutdownOperation === undefined) {
1117
1148
  this.setRuntimeState(contracts_1.ZLinkFrameworkRuntimeState.Stopped);
@@ -1180,6 +1211,11 @@ class ZLinkFrameworkRuntimeHost {
1180
1211
  const activationNode = node;
1181
1212
  const spotManager = this.spotManager;
1182
1213
  if (spotManager !== undefined) {
1214
+ activationNode.setSpotAdmissionProvider?.({
1215
+ isClosing: (spotId) => spotManager.isSpotClosing(meshName, spotId),
1216
+ awaitCloseDecision: (spotId) => spotManager.pendingSpotCloseDecision(meshName, spotId),
1217
+ runtimeState: () => this.runtimeState
1218
+ });
1183
1219
  this.registerInstanceApplicationLifecycle(meshName, activationNode, spotManager);
1184
1220
  }
1185
1221
  activationNode.registerAsyncInstanceActivationAuthority?.(new instance_activation_authority_1.ZLinkInstanceActivationAuthority({
@@ -1366,6 +1402,12 @@ class ZLinkFrameworkRuntimeHost {
1366
1402
  setSpotManager(spotManager) {
1367
1403
  this.spotManager = spotManager;
1368
1404
  for (const [meshName, node] of this.spotNodeRuntime?.meshNodesByName ?? []) {
1405
+ const admissionNode = node;
1406
+ admissionNode.setSpotAdmissionProvider?.({
1407
+ isClosing: (spotId) => spotManager.isSpotClosing(meshName, spotId),
1408
+ awaitCloseDecision: (spotId) => spotManager.pendingSpotCloseDecision(meshName, spotId),
1409
+ runtimeState: () => this.runtimeState
1410
+ });
1369
1411
  this.registerInstanceApplicationLifecycle(meshName, node, spotManager);
1370
1412
  }
1371
1413
  }
@@ -1373,6 +1415,7 @@ class ZLinkFrameworkRuntimeHost {
1373
1415
  this.ensureLocationRuntime();
1374
1416
  return {
1375
1417
  ...this.actorRuntimeOptionsFactory().createActorManagerOptions(),
1418
+ activationAdmission: this.activationAdmission,
1376
1419
  placementCreate: async (actorId, actorType, createOnly, call, signal) => {
1377
1420
  const placement = this.actorPlacement;
1378
1421
  if (placement === undefined) {
@@ -1416,10 +1459,16 @@ class ZLinkFrameworkRuntimeHost {
1416
1459
  ?.meshNode(meshName)
1417
1460
  ?.completeClosedInstance?.(spotId, objectGeneration);
1418
1461
  },
1419
- beginInstanceIdleClosingAuthority: (meshName, spotId) => this.locationOwner.currentLifecycle?.beginInstanceSpotClosing(meshName, spotId) ??
1420
- Promise.resolve(undefined),
1421
- beginInstanceClosingAuthority: (meshName, spotId) => this.locationOwner.currentLifecycle?.beginInstanceSpotClosing(meshName, spotId) ??
1422
- Promise.resolve(undefined),
1462
+ beginInstanceIdleClosingAuthority: (meshName, spotId, onCommitted) => this.locationOwner.currentLifecycle?.beginInstanceSpotClosing(meshName, spotId, onCommitted) ?? Promise.resolve(undefined),
1463
+ beginInstanceClosingAuthority: (meshName, spotId, onCommitted) => this.locationOwner.currentLifecycle?.beginInstanceSpotClosing(meshName, spotId, onCommitted) ?? Promise.resolve(undefined),
1464
+ beginUserClosingAuthority: async (meshName, spotId, objectGeneration, onCommitted) => {
1465
+ const coordinator = this.userSpotCoordinator;
1466
+ const nodeRid = this.spotNodeRuntime?.meshNode(meshName)?.status().routingId;
1467
+ if (coordinator === undefined || nodeRid === undefined) {
1468
+ throw new ConfigurationException_1.ZLinkConfigurationException('User Spot context Close requires its authority coordinator.');
1469
+ }
1470
+ return await coordinator.beginOwnerClose({ spotId: spotId, objectGeneration, meshName, nodeRid }, onCommitted);
1471
+ },
1423
1472
  createLocationSpotRouteResolver: () => this.createLocationSpotRouteResolver(),
1424
1473
  boundSessionRelay: this.boundSessionRelay,
1425
1474
  actorHandoff: this.actorHandoff,
@@ -1430,12 +1479,7 @@ class ZLinkFrameworkRuntimeHost {
1430
1479
  admission: this.admission,
1431
1480
  statefulExecutionAllowed: () => this.ownerAdmissionOpen()
1432
1481
  }).create(this.actorTransferRuntime),
1433
- activationConcurrencyLimitProvider: (meshName) => this.options.registration.spotNodes.get(meshName)?.activationConcurrencyLimit ?? 128,
1434
- onInstanceActivationConcurrencyChanged: (meshName) => {
1435
- void this.spotNodeRuntime
1436
- ?.publishMeshNodeState(this.runtimeState, this.executionState?.abortController.signal, meshName)
1437
- .catch(() => undefined);
1438
- }
1482
+ activationAdmission: this.activationAdmission
1439
1483
  };
1440
1484
  }
1441
1485
  createPublicSpotManager(local) {
@@ -1511,7 +1555,7 @@ class ZLinkFrameworkRuntimeHost {
1511
1555
  };
1512
1556
  }
1513
1557
  });
1514
- const coordinator = new user_spot_creation_coordinator_1.ZLinkUserSpotCreationCoordinator({
1558
+ const coordinator = (this.userSpotCoordinator = new user_spot_creation_coordinator_1.ZLinkUserSpotCreationCoordinator({
1515
1559
  store: locationStore,
1516
1560
  publishReadyRoute: (meshName, route) => {
1517
1561
  this.cachedLocationSpotRouteResolver?.invalidate?.(route.spot.spotId);
@@ -1589,7 +1633,7 @@ class ZLinkFrameworkRuntimeHost {
1589
1633
  localStatus.lifecycleGeneration === selected.lifecycleGeneration
1590
1634
  };
1591
1635
  }
1592
- });
1636
+ }));
1593
1637
  const factories = new Map([...this.options.registration.spotNodes].map(([meshName, node]) => [
1594
1638
  meshName,
1595
1639
  new Map(Object.entries(node.spotFactoryRegistrations ?? {}))
@@ -1725,25 +1769,12 @@ class ZLinkFrameworkRuntimeHost {
1725
1769
  }, signal);
1726
1770
  },
1727
1771
  close: async (record, signal) => {
1728
- if (!local.hasActiveSpot(record.target.spotId)) {
1729
- throw (0, framework_errors_internal_1.createInternalFrameworkException)(framework_errors_internal_1.ZLinkFrameworkInternalErrorKind.SpotMoving, `User Spot '${record.target.spotId}' is not materialized on its authority owner.`, true);
1730
- }
1731
- if (!local.canCloseUserSpot(meshName, record.target.spotId)) {
1732
- return {
1733
- terminalResult: runtime_values_1.RequestResult.Ok,
1734
- failureCode: 0,
1735
- tail: {
1736
- kind: 'userSpotClose',
1737
- closed: false
1738
- }
1739
- };
1740
- }
1741
1772
  return {
1742
1773
  terminalResult: runtime_values_1.RequestResult.Ok,
1743
1774
  failureCode: 0,
1744
1775
  tail: {
1745
1776
  kind: 'userSpotClose',
1746
- closed: await coordinator.handleRemoteClose(record, (spot, closeSignal) => local.close(spot.meshName, spot.spotId, closeSignal), signal)
1777
+ closed: await coordinator.handleRemoteClose(record, (spot, beginAuthority, closeSignal) => local.closeUserWithAuthority(spot.meshName, spot.spotId, beginAuthority, closeSignal), signal, (spot) => local.isSpotClosing(spot.meshName, spot.spotId))
1747
1778
  }
1748
1779
  };
1749
1780
  }
@@ -1905,12 +1936,7 @@ class ZLinkFrameworkRuntimeHost {
1905
1936
  });
1906
1937
  },
1907
1938
  meshRecordDispatcher: (meshName, owner, record) => this.dispatchMeshRecord(meshName, owner, record, this.executionState?.abortController.signal),
1908
- instanceActivationConcurrencyProvider: (meshName) => {
1909
- return (this.spotManager?.instanceActivationConcurrency(meshName) ?? {
1910
- active: 0,
1911
- limit: this.options.registration.spotNodes.get(meshName)?.activationConcurrencyLimit ?? 128
1912
- });
1913
- }
1939
+ activationConcurrency: (meshName) => this.activationAdmission.current(meshName)
1914
1940
  };
1915
1941
  }
1916
1942
  async dispatchMeshRecord(meshName, owner, record, signal) {
@@ -338,7 +338,7 @@ class ZLinkRemoteBoundSessionRelay {
338
338
  const owner = (0, actor_session_binding_runtime_owner_1.actorSessionBindingRuntimeOwner)(runtime);
339
339
  const fingerprint = (0, service_stateful_wire_codec_1.encodeSessionRelocationRoute)(value).toString('base64');
340
340
  if (value.route.action === 'abort') {
341
- await owner.applyRelocation(value.actor.actorId, key, fingerprint, 'abort', async () => {
341
+ await owner.applyRelocation(value.actor.actorId, key, fingerprint, async () => {
342
342
  if (!(await runtime.abortActorRouteSeal(value.actor.actorId, key))) {
343
343
  throw new bound_session_wire_1.ZLinkRemoteBoundSessionFenceError(`Actor '${value.actor.actorId}' command 44 abort lost its Session seal.`);
344
344
  }
@@ -357,9 +357,10 @@ class ZLinkRemoteBoundSessionRelay {
357
357
  nodeRid: (0, routing_id_1.decodeRoutingId)(committedRoute.targetNodeRid, undefined),
358
358
  bindingGeneration: value.session.bindingGeneration,
359
359
  ownershipGeneration: committedRoute.targetAuthorityOwnerGeneration,
360
- ownerNodeGeneration: committedRoute.targetNodeGeneration
360
+ ownerNodeGeneration: committedRoute.targetNodeGeneration,
361
+ ownerLeaseGeneration: committedRoute.targetOwnerLeaseGeneration
361
362
  };
362
- await owner.applyRelocation(value.actor.actorId, key, fingerprint, 'commit', async () => {
363
+ await owner.applyRelocation(value.actor.actorId, key, fingerprint, async () => {
363
364
  await runtime.commitActorRoute(targetActorRef, undefined, {
364
365
  confirmRemoteSessionBinding: 'send',
365
366
  releaseSeal: { sealId: key }
@@ -9,6 +9,7 @@ type ZLinkMeshDrainResult = {
9
9
  };
10
10
  import type { ZLinkBackendMeshNode } from '../backend';
11
11
  import type { ZLinkRuntimeAdmissionGate } from '../admission';
12
+ import type { ZLinkActivationAdmission } from '../activation-admission';
12
13
  import type { ZLinkSpotNodeOptions } from '../configuration';
13
14
  import { type ZLinkMeshNodeDescriptor } from '../../contracts';
14
15
  export interface ZLinkRouteMeshRuntimeCoordinatorOptions {
@@ -20,6 +21,7 @@ export interface ZLinkRouteMeshRuntimeCoordinatorOptions {
20
21
  readonly isLocationStoreHealthy?: () => boolean;
21
22
  readonly hostState?: () => ZLinkFrameworkRuntimeState;
22
23
  readonly admission: ZLinkRuntimeAdmissionGate;
24
+ readonly activationAdmission?: ZLinkActivationAdmission;
23
25
  readonly publishRetiring: (meshName: string, signal: AbortSignal) => Promise<void>;
24
26
  readonly rollbackRetiring: (meshName: string, signal: AbortSignal) => Promise<void>;
25
27
  readonly publishDraining: (meshName: string, signal: AbortSignal) => Promise<void>;