@zlink-systems/framework 0.27.0 → 0.29.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (191) hide show
  1. package/dist/.tsbuildinfo +1 -1
  2. package/dist/contracts/Actors/ZLinkActorClient.d.ts +1 -1
  3. package/dist/contracts/Channels/Calls.d.ts +1 -1
  4. package/dist/contracts/Configuration/Builders.d.ts +2 -1
  5. package/dist/contracts/Configuration/Configs.d.ts +0 -1
  6. package/dist/contracts/Configuration/InternalDefaults.d.ts +3 -0
  7. package/dist/contracts/Configuration/InternalDefaults.js +4 -1
  8. package/dist/contracts/Configuration/RegistrationBuilders.js +9 -0
  9. package/dist/contracts/Configuration/RegistrationNormalizers.d.ts +1 -0
  10. package/dist/contracts/Configuration/RegistrationNormalizers.js +16 -0
  11. package/dist/contracts/Configuration/RegistrationTypes.d.ts +3 -5
  12. package/dist/contracts/Configuration/RegistrationValidators.js +0 -2
  13. package/dist/contracts/Spots/Contracts.d.ts +1 -1
  14. package/dist/contracts/Streams/BoundSessionContracts.d.ts +1 -1
  15. package/dist/contracts/Streams/IZLinkSession.d.ts +2 -3
  16. package/dist/contracts/Streams/IZLinkSessionActor.d.ts +2 -2
  17. package/dist/runtime/actors/actor-client.js +7 -10
  18. package/dist/runtime/actors/actor-mailbox.d.ts +2 -2
  19. package/dist/runtime/actors/actor-mailbox.js +2 -2
  20. package/dist/runtime/actors/actor-request-deadline.d.ts +1 -3
  21. package/dist/runtime/actors/actor-request-deadline.js +4 -29
  22. package/dist/runtime/actors/actor-routed-join-transport.d.ts +2 -3
  23. package/dist/runtime/backend/contracts/index.d.ts +1 -4
  24. package/dist/runtime/backend/node/node-backend-adapter-support.d.ts +2 -0
  25. package/dist/runtime/backend/node/node-backend-adapter-support.js +35 -4
  26. package/dist/runtime/backend/node/node-dealer-channel-client-transport.d.ts +1 -1
  27. package/dist/runtime/backend/node/node-dealer-channel-client-transport.js +1 -2
  28. package/dist/runtime/backend/node/node-raw-binding-port.js +10 -27
  29. package/dist/runtime/backend/node/node-raw-mesh-backend.js +1 -3
  30. package/dist/runtime/backend/node/node-socket-backend-adapter.js +1 -1
  31. package/dist/runtime/channels/channel-clients.js +8 -10
  32. package/dist/runtime/channels/channel-envelope.d.ts +1 -1
  33. package/dist/runtime/channels/channel-envelope.js +4 -10
  34. package/dist/runtime/channels/channel-outbound-operations.d.ts +2 -2
  35. package/dist/runtime/channels/channel-outbound-operations.js +20 -36
  36. package/dist/runtime/channels/channel-runtime-manager.d.ts +4 -4
  37. package/dist/runtime/channels/channel-runtime-manager.js +8 -8
  38. package/dist/runtime/channels/channel-socket-options.js +0 -10
  39. package/dist/runtime/channels/channel-socket-registry.d.ts +1 -1
  40. package/dist/runtime/channels/channel-socket-registry.js +3 -14
  41. package/dist/runtime/channels/channel-transports.d.ts +10 -14
  42. package/dist/runtime/channels/channel-transports.js +11 -14
  43. package/dist/runtime/channels/local-spot-route-transport.d.ts +1 -1
  44. package/dist/runtime/channels/local-spot-route-transport.js +1 -3
  45. package/dist/runtime/channels/router-socket-spot-route-transport.d.ts +1 -1
  46. package/dist/runtime/channels/router-socket-spot-route-transport.js +2 -2
  47. package/dist/runtime/channels/source-spot-router.d.ts +1 -1
  48. package/dist/runtime/channels/source-spot-router.js +2 -4
  49. package/dist/runtime/channels/spot-node-route-transport.d.ts +1 -1
  50. package/dist/runtime/channels/spot-node-route-transport.js +2 -3
  51. package/dist/runtime/channels/spot-route-bridge-transport.d.ts +1 -1
  52. package/dist/runtime/channels/spot-route-bridge-transport.js +2 -2
  53. package/dist/runtime/channels/spot-route-dispatch-strategy.d.ts +2 -4
  54. package/dist/runtime/channels/spot-route-dispatch-strategy.js +11 -12
  55. package/dist/runtime/execution/serial-execution-queue.d.ts +12 -3
  56. package/dist/runtime/execution/serial-execution-queue.js +116 -28
  57. package/dist/runtime/foundation/operation-registry.d.ts +3 -2
  58. package/dist/runtime/foundation/operation-registry.js +5 -1
  59. package/dist/runtime/foundation/raw-service-mesh-runtime.js +17 -11
  60. package/dist/runtime/foundation/service-authority-payload-codec.d.ts +0 -2
  61. package/dist/runtime/foundation/service-authority-payload-codec.js +0 -43
  62. package/dist/runtime/foundation/service-stateful-registry.d.ts +4 -3
  63. package/dist/runtime/foundation/service-stateful-registry.js +5 -2
  64. package/dist/runtime/foundation/service-stateful-runtime.d.ts +1 -8
  65. package/dist/runtime/foundation/service-stateful-runtime.js +78 -126
  66. package/dist/runtime/foundation/service-stateful-wire-codec.d.ts +0 -11
  67. package/dist/runtime/foundation/service-stateful-wire-codec.js +1 -23
  68. package/dist/runtime/foundation/service-topology-registry.d.ts +5 -0
  69. package/dist/runtime/foundation/service-topology-registry.js +16 -17
  70. package/dist/runtime/host/actor-packet-relay.d.ts +2 -2
  71. package/dist/runtime/host/actor-packet-relay.js +8 -10
  72. package/dist/runtime/host/index.js +1 -15
  73. package/dist/runtime/host/instance-activation-authority.d.ts +0 -1
  74. package/dist/runtime/host/instance-activation-authority.js +46 -97
  75. package/dist/runtime/host/remote-bound-session-relay.js +8 -8
  76. package/dist/runtime/host/spot-address-transport.d.ts +1 -9
  77. package/dist/runtime/host/spot-address-transport.js +47 -87
  78. package/dist/runtime/host/stateful-authority-route-runtime.d.ts +1 -0
  79. package/dist/runtime/host/stateful-authority-route-runtime.js +17 -9
  80. package/dist/runtime/locations/domain-store-contract.d.ts +1 -0
  81. package/dist/runtime/locations/in-memory-authority-store.d.ts +2 -0
  82. package/dist/runtime/locations/in-memory-authority-store.js +22 -8
  83. package/dist/runtime/locations/in-memory-location-store.d.ts +1 -0
  84. package/dist/runtime/locations/in-memory-location-store.js +3 -0
  85. package/dist/runtime/locations/internal-store-contracts.d.ts +1 -1
  86. package/dist/runtime/locations/location-store-repository.d.ts +1 -0
  87. package/dist/runtime/locations/location-store-repository.js +98 -53
  88. package/dist/runtime/messaging/request-deadline.d.ts +3 -0
  89. package/dist/runtime/messaging/request-deadline.js +39 -0
  90. package/dist/runtime/messaging/submission-result.d.ts +2 -1
  91. package/dist/runtime/messaging/submission-result.js +11 -4
  92. package/dist/runtime/spots/spot-outbound.d.ts +3 -5
  93. package/dist/runtime/spots/spot-outbound.js +12 -15
  94. package/dist/runtime/spots/spot-serial-executor.js +4 -1
  95. package/dist/runtime/spots/spot-serial-turn-executor.d.ts +3 -0
  96. package/dist/runtime/spots/spot-serial-turn-executor.js +5 -0
  97. package/dist/runtime/streams/bound-actor-relay-sender.d.ts +2 -2
  98. package/dist/runtime/streams/bound-actor-relay-sender.js +14 -14
  99. package/dist/runtime/streams/bound-session-service.js +1 -1
  100. package/dist/runtime/streams/index.d.ts +2 -3
  101. package/dist/runtime/streams/index.js +6 -5
  102. package/dist/runtime/streams/managed-stream.d.ts +2 -2
  103. package/dist/runtime/streams/managed-stream.js +3 -5
  104. package/dist/runtime/streams/native-fallback-bound-session.js +13 -16
  105. package/dist/runtime/streams/protocol.js +0 -9
  106. package/dist/runtime/streams/session-calls.d.ts +5 -7
  107. package/dist/runtime/streams/session-calls.js +6 -23
  108. package/dist/runtime/streams/session-context.d.ts +4 -8
  109. package/dist/runtime/streams/session-context.js +3 -32
  110. package/dist/runtime/streams/session-serial-executor.d.ts +0 -1
  111. package/dist/runtime/streams/session-serial-executor.js +0 -3
  112. package/dist/runtime/streams/stream-message-utils.d.ts +0 -1
  113. package/dist/runtime/streams/stream-message-utils.js +0 -20
  114. package/dist/runtime/streams/stream-session-runtime.d.ts +6 -3
  115. package/dist/runtime/streams/stream-session-runtime.js +40 -85
  116. package/package.json +3 -3
  117. package/src/contracts/Actors/ZLinkActorClient.ts +1 -1
  118. package/src/contracts/Channels/Calls.ts +1 -1
  119. package/src/contracts/Configuration/Builders.ts +2 -1
  120. package/src/contracts/Configuration/Configs.ts +0 -1
  121. package/src/contracts/Configuration/InternalDefaults.ts +4 -0
  122. package/src/contracts/Configuration/RegistrationBuilders.ts +13 -3
  123. package/src/contracts/Configuration/RegistrationNormalizers.ts +25 -0
  124. package/src/contracts/Configuration/RegistrationTypes.ts +3 -5
  125. package/src/contracts/Configuration/RegistrationValidators.ts +0 -4
  126. package/src/contracts/Spots/Contracts.ts +1 -1
  127. package/src/contracts/Streams/BoundSessionContracts.ts +1 -1
  128. package/src/contracts/Streams/IZLinkSession.ts +2 -3
  129. package/src/contracts/Streams/IZLinkSessionActor.ts +2 -6
  130. package/src/runtime/actors/actor-client.ts +9 -15
  131. package/src/runtime/actors/actor-mailbox.ts +7 -2
  132. package/src/runtime/actors/actor-request-deadline.ts +4 -49
  133. package/src/runtime/actors/actor-routed-join-transport.ts +3 -5
  134. package/src/runtime/backend/contracts/index.ts +1 -8
  135. package/src/runtime/backend/node/node-backend-adapter-support.ts +45 -5
  136. package/src/runtime/backend/node/node-dealer-channel-client-transport.ts +0 -2
  137. package/src/runtime/backend/node/node-raw-binding-port.ts +15 -41
  138. package/src/runtime/backend/node/node-raw-mesh-backend.ts +1 -7
  139. package/src/runtime/backend/node/node-socket-backend-adapter.ts +1 -1
  140. package/src/runtime/channels/channel-clients.ts +9 -19
  141. package/src/runtime/channels/channel-envelope.ts +16 -28
  142. package/src/runtime/channels/channel-outbound-operations.ts +36 -38
  143. package/src/runtime/channels/channel-runtime-manager.ts +6 -28
  144. package/src/runtime/channels/channel-socket-options.ts +0 -13
  145. package/src/runtime/channels/channel-socket-registry.ts +3 -17
  146. package/src/runtime/channels/channel-transports.ts +7 -33
  147. package/src/runtime/channels/local-spot-route-transport.ts +1 -5
  148. package/src/runtime/channels/router-socket-spot-route-transport.ts +2 -6
  149. package/src/runtime/channels/source-spot-router.ts +2 -9
  150. package/src/runtime/channels/spot-node-route-transport.ts +2 -7
  151. package/src/runtime/channels/spot-route-bridge-transport.ts +5 -12
  152. package/src/runtime/channels/spot-route-dispatch-strategy.ts +11 -30
  153. package/src/runtime/execution/serial-execution-queue.ts +117 -29
  154. package/src/runtime/foundation/operation-registry.ts +16 -9
  155. package/src/runtime/foundation/raw-service-mesh-runtime.ts +17 -14
  156. package/src/runtime/foundation/service-authority-payload-codec.ts +0 -46
  157. package/src/runtime/foundation/service-stateful-registry.ts +10 -5
  158. package/src/runtime/foundation/service-stateful-runtime.ts +103 -181
  159. package/src/runtime/foundation/service-stateful-wire-codec.ts +0 -25
  160. package/src/runtime/foundation/service-topology-registry.ts +30 -20
  161. package/src/runtime/host/actor-packet-relay.ts +8 -15
  162. package/src/runtime/host/index.ts +2 -26
  163. package/src/runtime/host/instance-activation-authority.ts +58 -125
  164. package/src/runtime/host/remote-bound-session-relay.ts +8 -16
  165. package/src/runtime/host/spot-address-transport.ts +107 -166
  166. package/src/runtime/host/stateful-authority-route-runtime.ts +22 -9
  167. package/src/runtime/locations/domain-store-contract.ts +5 -0
  168. package/src/runtime/locations/in-memory-authority-store.ts +42 -8
  169. package/src/runtime/locations/in-memory-location-store.ts +8 -0
  170. package/src/runtime/locations/internal-store-contracts.ts +1 -0
  171. package/src/runtime/locations/location-store-repository.ts +130 -68
  172. package/src/runtime/messaging/request-deadline.ts +58 -0
  173. package/src/runtime/messaging/submission-result.ts +18 -4
  174. package/src/runtime/protocol/service_wire_pilot_codec.generated.ts +1 -1
  175. package/src/runtime/spots/spot-outbound.ts +14 -24
  176. package/src/runtime/spots/spot-serial-executor.ts +4 -1
  177. package/src/runtime/spots/spot-serial-turn-executor.ts +10 -0
  178. package/src/runtime/streams/bound-actor-relay-sender.ts +12 -26
  179. package/src/runtime/streams/bound-session-service.ts +1 -1
  180. package/src/runtime/streams/index.ts +5 -5
  181. package/src/runtime/streams/managed-stream.ts +3 -13
  182. package/src/runtime/streams/native-fallback-bound-session.ts +13 -25
  183. package/src/runtime/streams/protocol.ts +0 -13
  184. package/src/runtime/streams/session-calls.ts +8 -34
  185. package/src/runtime/streams/session-context.ts +6 -47
  186. package/src/runtime/streams/session-serial-executor.ts +0 -8
  187. package/src/runtime/streams/stream-message-utils.ts +1 -27
  188. package/src/runtime/streams/stream-session-runtime.ts +54 -97
  189. package/dist/runtime/streams/session-requests.d.ts +0 -25
  190. package/dist/runtime/streams/session-requests.js +0 -101
  191. package/src/runtime/streams/session-requests.ts +0 -110
@@ -55,12 +55,6 @@ export interface ZLinkHostSpotAddressTransportOptions {
55
55
  readonly completions: (meshName: string) => ZLinkMeshCompletionTable | undefined;
56
56
  readonly codecs?: ZLinkChannelEnvelopeCodecRegistry;
57
57
  readonly defaultRequestTimeoutMs: number;
58
- /** Internal one-way deadline policy; public calls do not expose this option. */
59
- readonly defaultSendTimeoutMs?: number;
60
- /** Resolves the send timeout for a configured Spot Mesh. */
61
- readonly sendTimeoutMsForMesh?: (meshName: string) => number;
62
- /** Resolves the send timeout for a resolved Spot route channel. */
63
- readonly sendTimeoutMsForRouteChannel?: (routeChannelId: string) => number;
64
58
  readonly dispatchErrors?: ZLinkDispatchErrorReporter;
65
59
  }
66
60
 
@@ -93,7 +87,7 @@ export class ZLinkHostSpotAddressTransport implements ZLinkSpotAddressTransport
93
87
  sendToSpotAddress(
94
88
  spotId: RoutingId,
95
89
  message: unknown,
96
- call: ZLinkSpotAddressCallOptions
90
+ call: Omit<ZLinkSpotAddressCallOptions, 'timeoutMs' | 'signal'>
97
91
  ): Promise<ZLinkSubmitResult> {
98
92
  // Call-scoped flow (spec 27 §4): the envelope encoders and the
99
93
  // traceInstanceAddress points share one ambient flow that does not
@@ -107,157 +101,136 @@ export class ZLinkHostSpotAddressTransport implements ZLinkSpotAddressTransport
107
101
  private async sendToSpotAddressScoped(
108
102
  spotId: RoutingId,
109
103
  message: unknown,
110
- call: ZLinkSpotAddressCallOptions
104
+ call: Omit<ZLinkSpotAddressCallOptions, 'timeoutMs' | 'signal'>
111
105
  ): Promise<ZLinkSubmitResult> {
112
- const timeoutMs = initialSendTimeoutMs(this.options, call);
113
- const deadline = createSpotAddressDeadline(timeoutMs, call.signal);
114
- try {
115
- const existing = await this.resolveExisting(spotId, deadline.signal);
116
- deadline.requireRemaining();
117
- if (existing !== undefined) {
118
- this.validateExisting(existing, call);
119
- deadline.setOwnerTimeout(this.sendTimeoutMsForRouteChannel(existing.routerChannelId));
120
- try {
121
- const result = await awaitWithAbort(
122
- this.options.routed.sendToSpot(existing, message, {
123
- instanceSpot: call.instanceSpot,
124
- timeoutMs: deadline.requireRemaining(),
125
- signal: deadline.signal,
126
- metadata: call.metadata
127
- }),
128
- deadline.signal
106
+ const activationDeadlineUnixMs = BigInt(
107
+ Math.round(Date.now() + this.options.defaultRequestTimeoutMs)
108
+ );
109
+ const existing = await this.resolveExisting(spotId);
110
+ if (existing !== undefined) {
111
+ this.validateExisting(existing, call);
112
+ try {
113
+ const result = await this.options.routed.sendToSpot(existing, message, {
114
+ instanceSpot: call.instanceSpot,
115
+ metadata: call.metadata
116
+ });
117
+ if (result.status === ZLinkSubmitStatus.Submitted) {
118
+ this.traceInstanceAddress(
119
+ ZLinkMessageFlowOutcome.Sent,
120
+ ZLinkDispatchMessageKind.Send,
121
+ spotId,
122
+ message,
123
+ existing.routerChannelId,
124
+ existing.stableType,
125
+ existing.targetNodeRid
129
126
  );
130
- if (result.status === ZLinkSubmitStatus.Submitted) {
131
- this.traceInstanceAddress(
132
- ZLinkMessageFlowOutcome.Sent,
133
- ZLinkDispatchMessageKind.Send,
134
- spotId,
135
- message,
136
- existing.routerChannelId,
137
- existing.stableType,
138
- existing.targetNodeRid
139
- );
140
- } else {
141
- this.traceInstanceAddress(
142
- submitResultFlowOutcome(result.status),
143
- ZLinkDispatchMessageKind.Send,
144
- spotId,
145
- message,
146
- existing.routerChannelId,
147
- existing.stableType,
148
- existing.targetNodeRid,
149
- submitResultReason(result.status)
150
- );
151
- }
152
- if (
153
- result.status === ZLinkSubmitStatus.TargetNotFound ||
154
- result.status === ZLinkSubmitStatus.RouteNotConnected
155
- ) {
156
- this.options.resolver()?.invalidate?.(spotId);
157
- }
158
- return result;
159
- } catch (error) {
160
- if (isSpotRouteRefreshError(error)) {
161
- this.options.resolver()?.invalidate?.(spotId);
162
- }
163
- const reason = addressedInstanceErrorReason(error);
127
+ } else {
164
128
  this.traceInstanceAddress(
165
- reason === ZLinkDispatchErrorReason.Backpressure
166
- ? ZLinkMessageFlowOutcome.Backpressured
167
- : ZLinkMessageFlowOutcome.Dropped,
129
+ submitResultFlowOutcome(result.status),
168
130
  ZLinkDispatchMessageKind.Send,
169
131
  spotId,
170
132
  message,
171
133
  existing.routerChannelId,
172
134
  existing.stableType,
173
135
  existing.targetNodeRid,
174
- reason
136
+ submitResultReason(result.status)
175
137
  );
176
- throw error;
177
138
  }
178
- }
179
- if (!call.instanceSpot) {
180
- return { status: ZLinkSubmitStatus.TargetNotFound };
181
- }
182
- const selected = this.selectMissingTarget(spotId, call);
183
- if (selected.kind === 'unsupported') {
184
- this.traceInstanceAddress(
185
- ZLinkMessageFlowOutcome.Dropped,
186
- ZLinkDispatchMessageKind.Send,
187
- spotId,
188
- message,
189
- call.initialMeshName,
190
- call.instanceSpotType,
191
- undefined,
192
- ZLinkDispatchErrorReason.StaleTarget
193
- );
194
- return { status: ZLinkSubmitStatus.TargetNotFound };
195
- }
196
- if (selected.kind === 'capacity') {
197
- const error = missingInstancePlacementCapacity(spotId, call.instanceSpotType);
139
+ if (
140
+ result.status === ZLinkSubmitStatus.TargetNotFound ||
141
+ result.status === ZLinkSubmitStatus.RouteNotConnected
142
+ ) {
143
+ this.options.resolver()?.invalidate?.(spotId);
144
+ }
145
+ return result;
146
+ } catch (error) {
147
+ if (isSpotRouteRefreshError(error)) {
148
+ this.options.resolver()?.invalidate?.(spotId);
149
+ }
150
+ const reason = addressedInstanceErrorReason(error);
198
151
  this.traceInstanceAddress(
199
- ZLinkMessageFlowOutcome.Backpressured,
152
+ reason === ZLinkDispatchErrorReason.Backpressure
153
+ ? ZLinkMessageFlowOutcome.Backpressured
154
+ : ZLinkMessageFlowOutcome.Dropped,
200
155
  ZLinkDispatchMessageKind.Send,
201
156
  spotId,
202
157
  message,
203
- call.initialMeshName,
204
- call.instanceSpotType,
205
- undefined,
206
- ZLinkDispatchErrorReason.Backpressure
158
+ existing.routerChannelId,
159
+ existing.stableType,
160
+ existing.targetNodeRid,
161
+ reason
207
162
  );
208
163
  throw error;
209
164
  }
210
- if (selected.kind === 'unavailable') {
211
- this.traceInstanceAddress(
212
- ZLinkMessageFlowOutcome.Dropped,
213
- ZLinkDispatchMessageKind.Send,
214
- spotId,
215
- message,
216
- call.initialMeshName,
217
- call.instanceSpotType,
218
- undefined,
219
- ZLinkDispatchErrorReason.StaleTarget
220
- );
221
- return { status: ZLinkSubmitStatus.RouteNotConnected };
222
- }
223
- deadline.setOwnerTimeout(this.sendTimeoutMsForMesh(selected.meshName));
224
- const encoded = this.encode(ZLinkChannelMessageKind.Command, selected.meshName, message);
225
- const sourceSpotId =
226
- call.sourceSpot === undefined ? undefined : String(call.sourceSpot.routingId);
227
- const mapped = classifySubmitResult(
228
- await awaitWithAbort(
229
- selected.node.sendToMissingInstanceSpot(
230
- selected.target,
231
- encoded,
232
- BigInt(deadline.deadlineUnixMs),
233
- sourceSpotId,
234
- call.metadata
235
- ),
236
- deadline.signal
237
- ),
238
- 'Instance Spot submission'
165
+ }
166
+ if (!call.instanceSpot) {
167
+ return { status: ZLinkSubmitStatus.TargetNotFound };
168
+ }
169
+ const selected = this.selectMissingTarget(spotId, call);
170
+ if (selected.kind === 'unsupported') {
171
+ this.traceInstanceAddress(
172
+ ZLinkMessageFlowOutcome.Dropped,
173
+ ZLinkDispatchMessageKind.Send,
174
+ spotId,
175
+ message,
176
+ call.initialMeshName,
177
+ call.instanceSpotType,
178
+ undefined,
179
+ ZLinkDispatchErrorReason.StaleTarget
239
180
  );
181
+ return { status: ZLinkSubmitStatus.TargetNotFound };
182
+ }
183
+ if (selected.kind === 'capacity') {
184
+ const error = missingInstancePlacementCapacity(spotId, call.instanceSpotType);
240
185
  this.traceInstanceAddress(
241
- submitResultFlowOutcome(mapped.status),
186
+ ZLinkMessageFlowOutcome.Backpressured,
242
187
  ZLinkDispatchMessageKind.Send,
243
188
  spotId,
244
189
  message,
245
- selected.meshName,
246
- selected.target.stableType,
247
- selected.target.targetNodeRid,
248
- mapped.status === ZLinkSubmitStatus.Submitted
249
- ? undefined
250
- : submitResultReason(mapped.status)
190
+ call.initialMeshName,
191
+ call.instanceSpotType,
192
+ undefined,
193
+ ZLinkDispatchErrorReason.Backpressure
251
194
  );
252
- return mapped;
253
- } catch (error) {
254
- if (deadline.expired()) {
255
- return { status: ZLinkSubmitStatus.TimedOut };
256
- }
257
195
  throw error;
258
- } finally {
259
- deadline.close();
260
196
  }
197
+ if (selected.kind === 'unavailable') {
198
+ this.traceInstanceAddress(
199
+ ZLinkMessageFlowOutcome.Dropped,
200
+ ZLinkDispatchMessageKind.Send,
201
+ spotId,
202
+ message,
203
+ call.initialMeshName,
204
+ call.instanceSpotType,
205
+ undefined,
206
+ ZLinkDispatchErrorReason.StaleTarget
207
+ );
208
+ return { status: ZLinkSubmitStatus.RouteNotConnected };
209
+ }
210
+ const encoded = this.encode(ZLinkChannelMessageKind.Command, selected.meshName, message);
211
+ const sourceSpotId =
212
+ call.sourceSpot === undefined ? undefined : String(call.sourceSpot.routingId);
213
+ const mapped = classifySubmitResult(
214
+ await selected.node.sendToMissingInstanceSpot(
215
+ selected.target,
216
+ encoded,
217
+ activationDeadlineUnixMs,
218
+ sourceSpotId,
219
+ call.metadata
220
+ ),
221
+ 'Instance Spot submission'
222
+ );
223
+ this.traceInstanceAddress(
224
+ submitResultFlowOutcome(mapped.status),
225
+ ZLinkDispatchMessageKind.Send,
226
+ spotId,
227
+ message,
228
+ selected.meshName,
229
+ selected.target.stableType,
230
+ selected.target.targetNodeRid,
231
+ mapped.status === ZLinkSubmitStatus.Submitted ? undefined : submitResultReason(mapped.status)
232
+ );
233
+ return mapped;
261
234
  }
262
235
 
263
236
  requestToSpotAddress<TReply = unknown>(
@@ -603,7 +576,7 @@ export class ZLinkHostSpotAddressTransport implements ZLinkSpotAddressTransport
603
576
  if (stableType === undefined) {
604
577
  if (distinctTypes.length === 0) return { kind: 'unsupported' };
605
578
  throw createInternalFrameworkException(
606
- ZLinkFrameworkInternalErrorKind.InvalidConfiguration,
579
+ ZLinkFrameworkInternalErrorKind.InvalidOperation,
607
580
  'Instance Spot type is required when multiple types are registered.'
608
581
  );
609
582
  }
@@ -642,22 +615,6 @@ export class ZLinkHostSpotAddressTransport implements ZLinkSpotAddressTransport
642
615
  return { kind: 'unavailable' };
643
616
  }
644
617
 
645
- private sendTimeoutMsForMesh(meshName: string): number {
646
- return (
647
- this.options.sendTimeoutMsForMesh?.(meshName) ??
648
- this.options.defaultSendTimeoutMs ??
649
- this.options.defaultRequestTimeoutMs
650
- );
651
- }
652
-
653
- private sendTimeoutMsForRouteChannel(routeChannelId: string): number {
654
- return (
655
- this.options.sendTimeoutMsForRouteChannel?.(routeChannelId) ??
656
- this.options.defaultSendTimeoutMs ??
657
- this.options.defaultRequestTimeoutMs
658
- );
659
- }
660
-
661
618
  private validateExisting(
662
619
  target: import('../spots/spot-routing-internal').ZLinkSpotRouteTarget,
663
620
  call: ZLinkSpotAddressCallOptions
@@ -845,21 +802,9 @@ function addressedInstanceErrorReason(error: unknown): ZLinkDispatchErrorReason
845
802
  return ZLinkDispatchErrorReason.HandlerException;
846
803
  }
847
804
 
848
- function initialSendTimeoutMs(
849
- options: ZLinkHostSpotAddressTransportOptions,
850
- call: ZLinkSpotAddressCallOptions
851
- ): number {
852
- return call.initialMeshName === undefined
853
- ? (options.defaultSendTimeoutMs ?? options.defaultRequestTimeoutMs)
854
- : (options.sendTimeoutMsForMesh?.(call.initialMeshName) ??
855
- options.defaultSendTimeoutMs ??
856
- options.defaultRequestTimeoutMs);
857
- }
858
-
859
805
  interface ZLinkSpotAddressDeadline {
860
806
  readonly deadlineUnixMs: number;
861
807
  readonly signal: AbortSignal;
862
- setOwnerTimeout(timeoutMs: number): void;
863
808
  requireRemaining(): number;
864
809
  expired(): boolean;
865
810
  close(): void;
@@ -871,7 +816,7 @@ function createSpotAddressDeadline(
871
816
  ): ZLinkSpotAddressDeadline {
872
817
  const startedAtMs = performance.now();
873
818
  const startedAtUnixMs = Date.now();
874
- let deadlineMs = startedAtMs + Math.max(0, timeoutMs);
819
+ const deadlineMs = startedAtMs + Math.max(0, timeoutMs);
875
820
  const controller = new AbortController();
876
821
  let expired = false;
877
822
  let timeout: ReturnType<typeof setTimeout> | undefined;
@@ -897,10 +842,6 @@ function createSpotAddressDeadline(
897
842
  return Math.round(startedAtUnixMs + (deadlineMs - startedAtMs));
898
843
  },
899
844
  signal: controller.signal,
900
- setOwnerTimeout(ownerTimeoutMs: number) {
901
- deadlineMs = startedAtMs + Math.max(0, ownerTimeoutMs);
902
- arm();
903
- },
904
845
  requireRemaining() {
905
846
  const remainingMs = deadlineMs - performance.now();
906
847
  if (remainingMs <= 0) {
@@ -1,3 +1,4 @@
1
+ import { encodeAuthorityKey } from '../locations/authority-key-codec';
1
2
  import { createHash } from 'node:crypto';
2
3
  import type {
3
4
  ZLinkAuthorityKey,
@@ -175,12 +176,25 @@ export class ZLinkStatefulAuthorityRouteRuntime {
175
176
 
176
177
  const status = sink.status();
177
178
  for (const pending of snapshot.pending) {
179
+ if (pending.targetMeshName !== meshName) continue;
178
180
  if (
179
- pending.targetMeshName === meshName &&
180
181
  routingIdsEqual(status.routingId, pending.targetNodeRid) &&
181
182
  status.lifecycleGeneration === pending.targetNodeGeneration
182
183
  ) {
183
184
  await this.recoverPendingInstanceActivation(sink, pending, signal);
185
+ } else {
186
+ const release = this.options.creationStore?.releaseEndedReservation;
187
+ if (release === undefined)
188
+ throw new Error('Reservation lifecycle recovery requires a Location repository.');
189
+ if (
190
+ await release.call(
191
+ this.options.creationStore,
192
+ encodeAuthorityKey('instance_spot', pending.spotId),
193
+ pending.pending.storeVersion,
194
+ signal
195
+ )
196
+ )
197
+ await this.clearRecoveryRoot(pending.pending.requestReference, signal);
184
198
  }
185
199
  }
186
200
 
@@ -386,14 +400,7 @@ export class ZLinkStatefulAuthorityRouteRuntime {
386
400
  signal
387
401
  );
388
402
  if (aborted.kind === 'aborted' || aborted.kind === 'alreadyAborted') {
389
- try {
390
- await this.options.relocationStore?.delete(
391
- relocationBlobReference(recovery.pending.requestReference)
392
- );
393
- } catch {
394
- // The authority no longer publishes this root. Retention owns a
395
- // failed best-effort orphan cleanup.
396
- }
403
+ await this.clearRecoveryRoot(recovery.pending.requestReference, signal);
397
404
  }
398
405
  return;
399
406
  }
@@ -401,6 +408,12 @@ export class ZLinkStatefulAuthorityRouteRuntime {
401
408
  return;
402
409
  }
403
410
 
411
+ private async clearRecoveryRoot(reference: string, signal?: AbortSignal): Promise<void> {
412
+ if (this.options.relocationStore === undefined)
413
+ throw new Error('Instance activation recovery requires a Relocation Store.');
414
+ await this.options.relocationStore.delete(relocationBlobReference(reference), signal);
415
+ }
416
+
404
417
  private async readRecoveryEnvelope(
405
418
  recovery: ServiceActivationRecoveryState,
406
419
  signal?: AbortSignal
@@ -140,6 +140,11 @@ export interface ZLinkDomainLocationStore {
140
140
  request: ZLinkObjectCreationCompleteRequest,
141
141
  signal?: AbortSignal
142
142
  ): Promise<ZLinkObjectCreationCompleteResult>;
143
+ releaseEndedReservation?(
144
+ key: ZLinkAuthorityKey,
145
+ expectedStoreVersion: string,
146
+ signal?: AbortSignal
147
+ ): Promise<boolean>;
143
148
  abort(
144
149
  request: ZLinkObjectAbortRequest,
145
150
  signal?: AbortSignal,
@@ -276,6 +276,42 @@ export class ZLinkInMemoryAuthorityStore {
276
276
  return BigInt(removed);
277
277
  }
278
278
 
279
+ async releaseEndedReservation(
280
+ key: ZLinkAuthorityKey,
281
+ expectedStoreVersion: string,
282
+ signal?: AbortSignal
283
+ ): Promise<boolean> {
284
+ signal?.throwIfAborted();
285
+ return this.tryReleaseEndedReservation(key, expectedStoreVersion);
286
+ }
287
+
288
+ private tryReleaseEndedReservation(
289
+ key: ZLinkAuthorityKey,
290
+ expectedStoreVersion: string
291
+ ): boolean {
292
+ const current = this.rows.get(key.value);
293
+ if (
294
+ current === undefined ||
295
+ current.snapshot.storeVersion.value !== expectedStoreVersion ||
296
+ current.snapshot.allocation.state !== 'reserved' ||
297
+ current.creation === undefined ||
298
+ this.validation.isTargetLive(
299
+ current.snapshot.allocation.descriptor,
300
+ current.snapshot.allocation.descriptorLifecycleGeneration,
301
+ {
302
+ ownerId: current.snapshot.ownerId,
303
+ leaseGeneration: current.snapshot.ownerLeaseGeneration
304
+ }
305
+ )
306
+ )
307
+ return false;
308
+ this.adjustCapacity(this.pendingCapacity, current.snapshot.allocation, -1);
309
+ this.rows.delete(key.value);
310
+ this.creationTerminals.set(current.creation.reservationId, 'aborted');
311
+ this.scanRevision++;
312
+ return true;
313
+ }
314
+
279
315
  async reserve(
280
316
  request: ZLinkObjectReserveRequest,
281
317
  signal?: AbortSignal
@@ -297,15 +333,13 @@ export class ZLinkInMemoryAuthorityStore {
297
333
  if (current.snapshot.allocation.state === 'active') {
298
334
  return { kind: 'alreadyExists', current: this.snapshot(current.snapshot) };
299
335
  }
300
- // An unfinished creation whose owner lease ended is cancellable.
301
- // Reclaim it so the key does not stay blocked forever.
302
- if (this.isOwnerLive(current.snapshot) || current.creation === undefined) {
336
+ if (
337
+ !this.tryReleaseEndedReservation(
338
+ encodeAuthorityKey(request.key.kind, request.key.globalId),
339
+ current.snapshot.storeVersion.value
340
+ )
341
+ )
303
342
  return { kind: 'conflict', current: this.read(key) };
304
- }
305
- this.adjustCapacity(this.pendingCapacity, current.snapshot.allocation, -1);
306
- this.rows.delete(key);
307
- this.creationTerminals.set(current.creation.reservationId, 'aborted');
308
- this.scanRevision++;
309
343
  }
310
344
  const target = creationTarget(request);
311
345
  if (
@@ -201,6 +201,14 @@ export class ZLinkInMemoryLocationStore
201
201
  return this.authority.readCreationTerminal(operation, signal);
202
202
  }
203
203
 
204
+ async releaseEndedReservation(
205
+ key: ZLinkAuthorityKey,
206
+ expectedStoreVersion: string,
207
+ signal?: AbortSignal
208
+ ): Promise<boolean> {
209
+ return this.authority.releaseEndedReservation(key, expectedStoreVersion, signal);
210
+ }
211
+
204
212
  async abort(
205
213
  request: ZLinkObjectAbortRequest,
206
214
  signal?: AbortSignal
@@ -32,6 +32,7 @@ export type ZLinkObjectCreationStore = Pick<
32
32
  | 'commit'
33
33
  | 'completeCreation'
34
34
  | 'abort'
35
+ | 'releaseEndedReservation'
35
36
  | 'prepareAggregate'
36
37
  | 'commitAggregate'
37
38
  | 'abortAggregate'