@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
@@ -22,11 +22,14 @@ export interface ZLinkSpotRuntimeOptionsFactoryOptions {
22
22
  readonly actorManager: () => DefaultZLinkActorManager | undefined;
23
23
  readonly locationLifecycle: () => ZLinkLocationLifecycle | undefined;
24
24
  readonly releaseInstanceAuthority: (meshName: string, spotId: string, objectGeneration: bigint) => Promise<void>;
25
- readonly beginInstanceIdleClosingAuthority: (meshName: string, spotId: string) => Promise<{
26
- restoreReady(): Promise<void>;
25
+ readonly beginInstanceIdleClosingAuthority: (meshName: string, spotId: string, onCommitted: () => void) => Promise<{
26
+ release(): Promise<void>;
27
27
  } | undefined>;
28
- readonly beginInstanceClosingAuthority: (meshName: string, spotId: string) => Promise<{
29
- restoreReady(): Promise<void>;
28
+ readonly beginInstanceClosingAuthority: (meshName: string, spotId: string, onCommitted: () => void) => Promise<{
29
+ release(): Promise<void>;
30
+ } | undefined>;
31
+ readonly beginUserClosingAuthority: (meshName: string, spotId: string, objectGeneration: bigint, onCommitted: () => void) => Promise<{
32
+ release(): Promise<void>;
30
33
  } | undefined>;
31
34
  readonly createLocationSpotRouteResolver: () => ZLinkSpotRouteResolver | undefined;
32
35
  readonly boundSessionRelay: ZLinkBoundSessionRelay;
@@ -55,8 +55,9 @@ class ZLinkSpotRuntimeOptionsFactory {
55
55
  detachedTaskRunner: this.options.detachedTaskRunner,
56
56
  locationLifecycle: this.options.locationLifecycle(),
57
57
  releaseInstanceAuthority: (meshName, spotId, objectGeneration) => this.options.releaseInstanceAuthority(meshName, String(spotId), objectGeneration),
58
- beginInstanceIdleClosingAuthority: (meshName, spotId) => this.options.beginInstanceIdleClosingAuthority(meshName, String(spotId)),
59
- beginInstanceClosingAuthority: (meshName, spotId) => this.options.beginInstanceClosingAuthority(meshName, String(spotId)),
58
+ beginInstanceIdleClosingAuthority: (meshName, spotId, onCommitted) => this.options.beginInstanceIdleClosingAuthority(meshName, String(spotId), onCommitted),
59
+ beginInstanceClosingAuthority: (meshName, spotId, onCommitted) => this.options.beginInstanceClosingAuthority(meshName, String(spotId), onCommitted),
60
+ beginUserClosingAuthority: (meshName, spotId, objectGeneration, onCommitted) => this.options.beginUserClosingAuthority(meshName, String(spotId), objectGeneration, onCommitted),
60
61
  instanceSpotApplicationTargetProvider: (meshName, spotId) => this.options
61
62
  .spotNodeRuntime()
62
63
  ?.meshNode(meshName)
@@ -85,12 +86,6 @@ class ZLinkSpotRuntimeOptionsFactory {
85
86
  }
86
87
  };
87
88
  },
88
- createReceived: () => {
89
- const runtime = this.options.spotNodeRuntime();
90
- if (runtime === undefined)
91
- throw new Error('Spot backend runtime is not initialized.');
92
- return runtime.createReceived();
93
- },
94
89
  createTopicMessage: () => {
95
90
  const runtime = this.options.spotNodeRuntime();
96
91
  if (runtime === undefined)
@@ -152,6 +147,7 @@ class ZLinkSpotRuntimeOptionsFactory {
152
147
  metrics: this.options.metrics,
153
148
  admission: this.options.admission,
154
149
  statefulExecutionAllowed: this.options.statefulExecutionAllowed,
150
+ closeErrorSink: this.options.runtimeOrPreStartErrorSink,
155
151
  dispatchErrors: this.options.dispatchErrorReporter(this.options.runtimeOrPreStartErrorSink)
156
152
  };
157
153
  }
@@ -78,7 +78,7 @@ class ZLinkStatefulAuthorityRouteRuntime {
78
78
  const expectedSpotRoute = previousRoute?.spotRoute ?? null;
79
79
  const expectedInstanceRoute = previousRoute?.kind === 'instance_spot' ? previousRoute.instanceRoute : null;
80
80
  sink.rememberSpotRoute(route.spotRoute, expectedSpotRoute);
81
- if (route.kind === 'instance_spot') {
81
+ if (route.kind === 'instance_spot' && !route.closing) {
82
82
  const status = sink.status();
83
83
  if ((0, routing_id_1.routingIdsEqual)(status.routingId, route.instanceRoute.targetNodeRid) &&
84
84
  status.lifecycleGeneration === route.instanceRoute.targetNodeGeneration) {
@@ -346,7 +346,9 @@ function pendingInstanceActivation(snapshot) {
346
346
  }
347
347
  function authorityRoute(snapshot) {
348
348
  const allocation = snapshot.allocation;
349
- const decoded = (0, service_authority_payload_codec_1.decodeServiceReadySpotAuthority)((0, service_relocation_runtime_1.serviceRelocationAuthorityApplicationPayload)(snapshot.payload));
349
+ const payload = (0, service_relocation_runtime_1.serviceRelocationAuthorityApplicationPayload)(snapshot.payload);
350
+ const ready = (0, service_authority_payload_codec_1.decodeServiceReadySpotAuthority)(payload);
351
+ const decoded = ready ?? (0, service_authority_payload_codec_1.decodeServiceClosingSpotAuthority)(payload);
350
352
  if (allocation.state !== 'active' ||
351
353
  allocation.objectKind === 'actor' ||
352
354
  allocation.descriptor.meshName.length === 0 ||
@@ -372,6 +374,7 @@ function authorityRoute(snapshot) {
372
374
  };
373
375
  return {
374
376
  kind: allocation.objectKind,
377
+ closing: ready === undefined,
375
378
  stableType: allocation.stableType,
376
379
  meshName: allocation.descriptor.meshName,
377
380
  spotRoute,
@@ -397,6 +400,7 @@ function sameAppliedRoute(left, right) {
397
400
  if (right === undefined)
398
401
  return false;
399
402
  return (left.kind === right.kind &&
403
+ left.closing === right.closing &&
400
404
  left.stableType === right.stableType &&
401
405
  left.meshName === right.meshName &&
402
406
  left.instanceRoute.targetNodeRid === right.instanceRoute.targetNodeRid &&
@@ -53,15 +53,23 @@ export declare class ZLinkUserSpotCreationCoordinator {
53
53
  readonly nodeRid: RoutingId;
54
54
  readonly isLocal: boolean;
55
55
  }, authority: ZLinkAuthoritySnapshot, signal: AbortSignal) => Promise<ZLinkLocalSpotCreateResult>, discard?: (signal?: AbortSignal) => Promise<void>): Promise<ZLinkUserSpotCreationResult>;
56
- close(spot: SpotRef, closeOwner: (current: SpotRef, snapshot: ZLinkAuthoritySnapshot) => Promise<boolean>, signal?: AbortSignal, ownerPresent?: (current: SpotRef) => boolean, ownerCanClose?: (current: SpotRef) => boolean): Promise<boolean>;
56
+ close(spot: SpotRef, closeOwner: (current: SpotRef, beginAuthority: (onCommitted: () => void) => Promise<{
57
+ release(): Promise<void>;
58
+ }>) => Promise<boolean>, signal?: AbortSignal): Promise<boolean>;
59
+ /** Commits Closing for the owner's own incarnation when its context requests Close. */
60
+ beginOwnerClose(spot: SpotRef, onCommitted: () => void): Promise<{
61
+ release(): Promise<void>;
62
+ } | undefined>;
57
63
  resolveCloseTarget(spot: SpotRef, signal?: AbortSignal): Promise<ZLinkUserSpotCloseTarget | undefined>;
58
64
  handleRemoteCreate(record: ServiceUserSpotCreateRecord, materialize: (requestPayload: Uint8Array, authority: ZLinkAuthoritySnapshot, signal: AbortSignal) => Promise<ZLinkLocalSpotCreateResult>, discard?: (signal?: AbortSignal) => Promise<void>, signal?: AbortSignal): Promise<ZLinkUserSpotCreationResult>;
59
65
  private handleLocalCreate;
60
66
  private materializeRemoteCreate;
61
- handleRemoteClose(record: ServiceUserSpotCloseRecord, closeOwner: (spot: SpotRef, signal?: AbortSignal) => Promise<boolean>, signal?: AbortSignal): Promise<boolean>;
67
+ handleRemoteClose(record: ServiceUserSpotCloseRecord, closeOwner: (spot: SpotRef, beginAuthority: (onCommitted: () => void) => Promise<{
68
+ release(): Promise<void>;
69
+ }>, signal?: AbortSignal) => Promise<boolean>, signal?: AbortSignal, canResume?: (spot: SpotRef) => boolean): Promise<boolean>;
70
+ private commitCloseAuthority;
62
71
  forgetReadyRoute(spotId: RoutingId, snapshot: ZLinkAuthoritySnapshot): void;
63
72
  private beginClosing;
64
- private restoreReady;
65
73
  private awaitReady;
66
74
  private remoteCreate;
67
75
  }
@@ -192,60 +192,35 @@ class ZLinkUserSpotCreationCoordinator {
192
192
  deadline.close();
193
193
  }
194
194
  }
195
- async close(spot, closeOwner, signal, ownerPresent, ownerCanClose) {
195
+ async close(spot, closeOwner, signal) {
196
196
  const resolved = await this.resolveCloseTarget(spot, signal);
197
197
  if (resolved === undefined)
198
198
  return false;
199
199
  const { spot: currentRef, snapshot: current } = resolved;
200
200
  const key = (0, authority_key_codec_1.encodeAuthorityKey)('user_spot', String(spot.spotId));
201
- if (ownerPresent?.(currentRef) === false) {
202
- throw (0, framework_errors_internal_1.createInternalFrameworkException)(framework_errors_internal_1.ZLinkFrameworkInternalErrorKind.SpotMoving, `User Spot '${String(spot.spotId)}' is missing from its authority owner.`, true);
203
- }
204
- if (ownerCanClose?.(currentRef) === false)
205
- return false;
206
- const closing = await this.beginClosing(key, current, String(spot.spotId), signal);
207
- let closed;
208
- try {
209
- closed = await closeOwner(currentRef, closing);
210
- }
211
- catch (error) {
212
- await this.restoreReady(key, closing, String(spot.spotId), signal);
213
- throw error;
214
- }
215
- if (!closed) {
216
- await this.restoreReady(key, closing, String(spot.spotId), signal);
217
- return false;
218
- }
219
- const deleted = await this.options.store.compareExchangeAuthority(key, closing.storeVersion, { kind: 'delete' }, signal);
220
- if (deleted.kind === 'deleted') {
221
- this.forgetReadyRoute(currentRef.spotId, current);
222
- return true;
223
- }
224
- if (deleted.kind === 'conflict') {
225
- throw (0, framework_errors_internal_1.createInternalFrameworkException)(framework_errors_internal_1.ZLinkFrameworkInternalErrorKind.SpotMoving, `User Spot '${String(spot.spotId)}' authority changed while closing.`, true);
226
- }
227
- throw (0, framework_errors_internal_1.createInternalFrameworkException)(framework_errors_internal_1.ZLinkFrameworkInternalErrorKind.SpotGenerationStale, `User Spot '${String(spot.spotId)}' generation cannot be closed.`);
201
+ return await closeOwner(currentRef, async (onCommitted) => this.commitCloseAuthority(key, current, String(spot.spotId), onCommitted));
202
+ }
203
+ /** Commits Closing for the owner's own incarnation when its context requests Close. */
204
+ async beginOwnerClose(spot, onCommitted) {
205
+ const resolved = await this.resolveCloseTarget(spot);
206
+ if (resolved === undefined)
207
+ return undefined;
208
+ const spotId = String(spot.spotId);
209
+ return await this.commitCloseAuthority((0, authority_key_codec_1.encodeAuthorityKey)('user_spot', spotId), resolved.snapshot, spotId, onCommitted);
228
210
  }
229
211
  async resolveCloseTarget(spot, signal) {
230
212
  const key = (0, authority_key_codec_1.encodeAuthorityKey)('user_spot', String(spot.spotId));
231
213
  const current = await this.options.store.readAuthority(key, signal);
232
214
  if (current.kind === 'missing')
233
215
  return undefined;
234
- if (current.objectGeneration !== spot.objectGeneration) {
235
- throw (0, framework_errors_internal_1.createInternalFrameworkException)(framework_errors_internal_1.ZLinkFrameworkInternalErrorKind.SpotGenerationStale, `User Spot '${String(spot.spotId)}' generation is stale.`);
236
- }
237
- const currentRef = spotRef(current, {
238
- meshName: current.allocation.descriptor.meshName,
239
- spotId: spot.spotId,
240
- stableType: current.allocation.stableType,
241
- requestPayload: Buffer.alloc(0),
242
- timeoutMs: 1
243
- });
244
- if (String(current.allocation.descriptor.rid) !== String(spot.nodeRid) ||
245
- current.allocation.descriptor.meshName !== spot.meshName) {
246
- throw (0, framework_errors_internal_1.createInternalFrameworkException)(framework_errors_internal_1.ZLinkFrameworkInternalErrorKind.SpotGenerationStale, `User Spot '${String(spot.spotId)}' owner route is stale.`);
247
- }
248
- return { spot: currentRef, snapshot: current };
216
+ return {
217
+ spot: requireCloseTarget(current, String(spot.spotId), {
218
+ objectGeneration: spot.objectGeneration,
219
+ nodeRid: String(spot.nodeRid),
220
+ meshName: spot.meshName
221
+ }),
222
+ snapshot: current
223
+ };
249
224
  }
250
225
  async handleRemoteCreate(record, materialize, discard, signal) {
251
226
  const key = `${record.spotId}\0${record.reservation.reservationId}`;
@@ -430,52 +405,50 @@ class ZLinkUserSpotCreationCoordinator {
430
405
  throw error;
431
406
  }
432
407
  }
433
- async handleRemoteClose(record, closeOwner, signal) {
408
+ async handleRemoteClose(record, closeOwner, signal, canResume) {
434
409
  const key = (0, authority_key_codec_1.encodeAuthorityKey)('user_spot', record.target.spotId);
435
410
  const current = await this.options.store.readAuthority(key, signal);
436
411
  if (current.kind === 'missing')
437
412
  return false;
438
- if (current.objectGeneration !== record.target.objectGeneration) {
439
- throw (0, framework_errors_internal_1.createInternalFrameworkException)(framework_errors_internal_1.ZLinkFrameworkInternalErrorKind.SpotGenerationStale, `User Spot '${record.target.spotId}' generation is stale.`);
440
- }
441
- if (current.authorityOwnerGeneration !== record.target.authorityOwnerGeneration ||
442
- current.storeVersion.value !== record.target.expectedStoreVersion ||
443
- String(current.allocation.descriptor.rid) !== record.target.targetNodeRid ||
444
- current.allocation.descriptorLifecycleGeneration !== record.target.targetNodeGeneration ||
445
- current.allocation.objectKind !== 'user_spot' ||
446
- current.allocation.state !== 'active') {
447
- throw (0, framework_errors_internal_1.createInternalFrameworkException)(framework_errors_internal_1.ZLinkFrameworkInternalErrorKind.SpotMoving, `User Spot '${record.target.spotId}' close authority is moving.`, true);
448
- }
449
- const spot = {
413
+ const candidate = {
450
414
  spotId: record.target.spotId,
451
415
  objectGeneration: current.objectGeneration,
452
416
  meshName: current.allocation.descriptor.meshName,
453
417
  nodeRid: current.allocation.descriptor.rid
454
418
  };
455
- const closing = await this.beginClosing(key, current, record.target.spotId, signal);
456
- let closed;
457
- try {
458
- closed = await closeOwner(spot, signal);
459
- }
460
- catch (error) {
461
- await this.restoreReady(key, closing, record.target.spotId, signal);
462
- throw error;
463
- }
464
- if (!closed) {
465
- await this.restoreReady(key, closing, record.target.spotId, signal);
466
- return false;
467
- }
468
- const deleted = await this.options.store.compareExchangeAuthority(key, closing.storeVersion, { kind: 'delete' }, signal);
469
- if (deleted.kind === 'deleted') {
470
- this.forgetReadyRoute(record.target.spotId, current);
471
- return true;
472
- }
473
- throw (0, framework_errors_internal_1.createInternalFrameworkException)(framework_errors_internal_1.ZLinkFrameworkInternalErrorKind.SpotMoving, `User Spot '${record.target.spotId}' authority changed while closing.`, true);
419
+ // A Closing committed by this owner is resumed, so its store version has
420
+ // advanced past the one the source observed.
421
+ const resuming = canResume?.(candidate) === true &&
422
+ (0, service_authority_payload_codec_1.decodeServiceClosingSpotAuthority)(current.payload)?.kind === 'user_spot';
423
+ const spot = requireCloseTarget(current, record.target.spotId, {
424
+ objectGeneration: record.target.objectGeneration,
425
+ nodeRid: record.target.targetNodeRid,
426
+ nodeGeneration: record.target.targetNodeGeneration,
427
+ authorityOwnerGeneration: record.target.authorityOwnerGeneration,
428
+ storeVersion: resuming ? undefined : record.target.expectedStoreVersion
429
+ });
430
+ return await closeOwner(spot, async (onCommitted) => this.commitCloseAuthority(key, current, record.target.spotId, onCommitted), signal);
431
+ }
432
+ async commitCloseAuthority(key, current, spotId, onCommitted) {
433
+ const closing = await this.beginClosing(key, current, spotId);
434
+ const authority = {
435
+ release: async () => {
436
+ this.forgetReadyRoute(spotId, current);
437
+ const deleted = await this.options.store.compareExchangeAuthority(key, closing.storeVersion, {
438
+ kind: 'delete'
439
+ });
440
+ if (deleted.kind !== 'deleted') {
441
+ throw (0, framework_errors_internal_1.createInternalFrameworkException)(framework_errors_internal_1.ZLinkFrameworkInternalErrorKind.SpotMoving, `User Spot '${spotId}' authority changed while closing.`, true);
442
+ }
443
+ }
444
+ };
445
+ onCommitted();
446
+ return authority;
474
447
  }
475
448
  forgetReadyRoute(spotId, snapshot) {
476
449
  this.options.forgetReadyRoute?.(snapshot.allocation.descriptor.meshName, readySpotRoute(spotId, snapshot));
477
450
  }
478
- async beginClosing(key, current, spotId, signal) {
451
+ async beginClosing(key, current, spotId) {
479
452
  const ready = (0, service_authority_payload_codec_1.decodeServiceReadySpotAuthority)(current.payload);
480
453
  if (ready?.kind !== 'user_spot' ||
481
454
  ready.spotId !== spotId ||
@@ -486,23 +459,13 @@ class ZLinkUserSpotCreationCoordinator {
486
459
  kind: 'put',
487
460
  payload: userSpotAuthorityPayload(current, spotId, 'closing'),
488
461
  generationTransition: 'preserve'
489
- }, signal);
462
+ }, undefined);
490
463
  if (closing.kind === 'stored') {
491
464
  const { kind: _kind, ...snapshot } = closing;
492
465
  return { kind: 'snapshot', ...snapshot };
493
466
  }
494
467
  throw (0, framework_errors_internal_1.createInternalFrameworkException)(framework_errors_internal_1.ZLinkFrameworkInternalErrorKind.SpotMoving, `User Spot authority changed while entering Closing.`, true);
495
468
  }
496
- async restoreReady(key, closing, spotId, signal) {
497
- const restored = await this.options.store.compareExchangeAuthority(key, closing.storeVersion, {
498
- kind: 'put',
499
- payload: userSpotAuthorityPayload(closing, spotId, 'ready'),
500
- generationTransition: 'preserve'
501
- }, signal);
502
- if (restored.kind !== 'stored') {
503
- throw (0, framework_errors_internal_1.createInternalFrameworkException)(framework_errors_internal_1.ZLinkFrameworkInternalErrorKind.SpotMoving, 'User Spot Ready authority could not be restored after close was declined.', true);
504
- }
505
- }
506
469
  async awaitReady(request, signal) {
507
470
  const key = (0, authority_key_codec_1.encodeAuthorityKey)('user_spot', String(request.spotId));
508
471
  for (;;) {
@@ -588,6 +551,41 @@ function readySpotRoute(spotId, snapshot) {
588
551
  storeVersion: snapshot.storeVersion.value
589
552
  };
590
553
  }
554
+ /**
555
+ * The single classifier of a Close target (§7, §9): another ObjectGeneration is
556
+ * SpotGenerationStale; any owner fence difference or an authority that is not
557
+ * in a Framework-owned Ready or Closing state is SpotMoving.
558
+ */
559
+ function requireCloseTarget(current, spotId, fence) {
560
+ if (current.objectGeneration !== fence.objectGeneration) {
561
+ throw (0, framework_errors_internal_1.createInternalFrameworkException)(framework_errors_internal_1.ZLinkFrameworkInternalErrorKind.SpotGenerationStale, `User Spot '${spotId}' generation is stale.`);
562
+ }
563
+ // A committed Closing stays the close target: its owner resumes that Close.
564
+ const decoded = (0, service_authority_payload_codec_1.decodeServiceReadySpotAuthority)(current.payload) ??
565
+ (0, service_authority_payload_codec_1.decodeServiceClosingSpotAuthority)(current.payload);
566
+ const allocation = current.allocation;
567
+ if (decoded?.kind !== 'user_spot' ||
568
+ decoded.spotId !== spotId ||
569
+ decoded.ownerId !== current.ownerId ||
570
+ decoded.ownerLeaseGeneration !== current.ownerLeaseGeneration ||
571
+ allocation.objectKind !== 'user_spot' ||
572
+ allocation.state !== 'active' ||
573
+ String(allocation.descriptor.rid) !== fence.nodeRid ||
574
+ (fence.meshName !== undefined && allocation.descriptor.meshName !== fence.meshName) ||
575
+ (fence.nodeGeneration !== undefined &&
576
+ allocation.descriptorLifecycleGeneration !== fence.nodeGeneration) ||
577
+ (fence.authorityOwnerGeneration !== undefined &&
578
+ current.authorityOwnerGeneration !== fence.authorityOwnerGeneration) ||
579
+ (fence.storeVersion !== undefined && current.storeVersion.value !== fence.storeVersion)) {
580
+ throw (0, framework_errors_internal_1.createInternalFrameworkException)(framework_errors_internal_1.ZLinkFrameworkInternalErrorKind.SpotMoving, `User Spot '${spotId}' owner fence changed or the Spot is moving.`, true);
581
+ }
582
+ return {
583
+ spotId: spotId,
584
+ objectGeneration: current.objectGeneration,
585
+ meshName: allocation.descriptor.meshName,
586
+ nodeRid: allocation.descriptor.rid
587
+ };
588
+ }
591
589
  function spotRef(snapshot, request, allowPending = false) {
592
590
  const decoded = (0, service_authority_payload_codec_1.decodeServiceReadySpotAuthority)(snapshot.payload);
593
591
  if (allowPending
@@ -52,11 +52,9 @@ class ZLinkInMemoryProviderLocationStore {
52
52
  this.values.delete(mutation.key.value);
53
53
  continue;
54
54
  }
55
- requireValue(mutation.bytes, mutation.retentionMs);
55
+ const retentionMs = requireValue(mutation.bytes, mutation.retentionMs);
56
56
  const version = storeVersion((++this.nextVersion).toString());
57
- const expiresAt = mutation.retentionMs === undefined
58
- ? undefined
59
- : new Date(storeNow.getTime() + mutation.retentionMs);
57
+ const expiresAt = retentionMs === undefined ? undefined : new Date(storeNow.getTime() + retentionMs);
60
58
  this.values.set(mutation.key.value, {
61
59
  bytes: mutation.bytes.slice(),
62
60
  version,
@@ -169,9 +167,13 @@ function requireValue(bytes, retentionMs) {
169
167
  if (bytes.byteLength > 1024 * 1024) {
170
168
  throw new RangeError('Location Store value exceeds 1 MiB.');
171
169
  }
172
- if (retentionMs !== undefined && (!Number.isSafeInteger(retentionMs) || retentionMs < 1)) {
173
- throw new RangeError('Location Store retention must be a positive safe integer.');
170
+ if (retentionMs !== undefined &&
171
+ (!Number.isFinite(retentionMs) ||
172
+ retentionMs <= 0 ||
173
+ !Number.isSafeInteger(Math.ceil(retentionMs)))) {
174
+ throw new RangeError('Location Store retention must round to a positive safe integer.');
174
175
  }
176
+ return retentionMs === undefined ? undefined : Math.ceil(retentionMs);
175
177
  }
176
178
  function requireKey(value) {
177
179
  const bytes = Buffer.byteLength(value, 'utf8');
@@ -31,7 +31,7 @@ export declare class ZLinkLocationLifecycle {
31
31
  private retryActorRelease;
32
32
  claimSpot(meshName: string, spotId: RoutingId, spotType: string, nodeRid: RoutingId, spotKind: ZLinkSpotKind, spotGeneration: bigint, ownerNodeGeneration: bigint, deactivate?: () => Promise<void>): Promise<ZLinkLocationWriteStatus>;
33
33
  releaseSpot(meshName: string, spotId: RoutingId, expectedObjectGeneration?: bigint): Promise<void>;
34
- beginInstanceSpotClosing(meshName: string, spotId: RoutingId): Promise<ZLinkInstanceClosingAuthority | undefined>;
34
+ beginInstanceSpotClosing(meshName: string, spotId: RoutingId, onCommitted: () => void): Promise<ZLinkInstanceClosingAuthority | undefined>;
35
35
  trackInstanceSpot(input: ZLinkTrackedInstanceAuthority): void;
36
36
  reclaimOwnerRows(): Promise<void>;
37
37
  bindActorSessionRoute(sessionRid: RoutingId, actorId: string, ownerNodeRid: RoutingId): Promise<void>;
@@ -81,8 +81,8 @@ class ZLinkLocationLifecycle {
81
81
  async releaseSpot(meshName, spotId, expectedObjectGeneration) {
82
82
  await this.spotClaims.release(meshName, spotId, expectedObjectGeneration);
83
83
  }
84
- async beginInstanceSpotClosing(meshName, spotId) {
85
- return await this.spotClaims.beginInstanceClosing(meshName, spotId);
84
+ async beginInstanceSpotClosing(meshName, spotId, onCommitted) {
85
+ return await this.spotClaims.beginInstanceClosing(meshName, spotId, onCommitted);
86
86
  }
87
87
  trackInstanceSpot(input) {
88
88
  this.spotClaims.trackInstanceAuthority(input);
@@ -582,7 +582,10 @@ class ZLinkAuthoritySpotRouteResolver {
582
582
  return prepared.cached;
583
583
  const current = await this.store.readAuthority((0, authority_key_codec_1.encodeAuthorityKey)('user_spot', key), signal);
584
584
  if (current.kind === 'snapshot' && current.allocation.state === 'active') {
585
- const decoded = (0, service_authority_payload_codec_1.decodeServiceReadySpotAuthority)((0, service_relocation_runtime_1.serviceRelocationAuthorityApplicationPayload)(current.payload));
585
+ const authorityPayload = (0, service_relocation_runtime_1.serviceRelocationAuthorityApplicationPayload)(current.payload);
586
+ const ready = (0, service_authority_payload_codec_1.decodeServiceReadySpotAuthority)(authorityPayload);
587
+ const closing = (0, service_authority_payload_codec_1.decodeServiceClosingSpotAuthority)(authorityPayload);
588
+ const decoded = ready ?? closing;
586
589
  if (decoded !== undefined &&
587
590
  decoded.spotId === String(spotId) &&
588
591
  decoded.ownerId === current.ownerId &&
@@ -610,7 +613,9 @@ class ZLinkAuthoritySpotRouteResolver {
610
613
  authorityStoreVersion: current.storeVersion.value,
611
614
  targetNodeState: await this.targetNodeStateResolver?.(decoded.ownerMeshName, decoded.ownerNodeRid, current.allocation.descriptorLifecycleGeneration, signal)
612
615
  };
613
- await this.lane.run(() => this.cacheResolutionCore(key, prepared.epoch, target, remainingLeaseMs, current.storeVersion.value));
616
+ if (ready !== undefined) {
617
+ await this.lane.run(() => this.cacheResolutionCore(key, prepared.epoch, target, remainingLeaseMs, current.storeVersion.value));
618
+ }
614
619
  return target;
615
620
  }
616
621
  }
@@ -13,7 +13,7 @@ export declare class ZLinkSpotLocationClaims {
13
13
  claim(meshName: string, spotId: RoutingId, spotType: string, nodeRid: RoutingId, spotKind: ZLinkSpotKind, spotGeneration: bigint, ownerNodeGeneration: bigint, deactivate?: () => Promise<void>): Promise<ZLinkLocationWriteStatus>;
14
14
  trackInstanceAuthority(input: ZLinkTrackedInstanceAuthority): void;
15
15
  release(meshName: string, spotId: RoutingId, expectedObjectGeneration?: bigint): Promise<void>;
16
- beginInstanceClosing(meshName: string, spotId: RoutingId): Promise<ZLinkInstanceClosingAuthority | undefined>;
16
+ beginInstanceClosing(meshName: string, spotId: RoutingId, onCommitted: () => void): Promise<ZLinkInstanceClosingAuthority | undefined>;
17
17
  onOwnershipLost(event: ZLinkOwnershipLostEvent): void;
18
18
  reclaimOwnerRows(): Promise<void>;
19
19
  private releaseAuthority;
@@ -32,5 +32,5 @@ export interface ZLinkTrackedInstanceAuthority {
32
32
  readonly deactivate?: () => Promise<void>;
33
33
  }
34
34
  export interface ZLinkInstanceClosingAuthority {
35
- restoreReady(): Promise<void>;
35
+ release(): Promise<void>;
36
36
  }
@@ -82,7 +82,7 @@ class ZLinkSpotLocationClaims {
82
82
  }
83
83
  this.invalidateSpotRoute?.(tracked.spotId);
84
84
  }
85
- async beginInstanceClosing(meshName, spotId) {
85
+ async beginInstanceClosing(meshName, spotId, onCommitted) {
86
86
  const canonical = key_codec_1.ZLinkLocationKeyCodec.encodeSpotKey({ meshName, spotId });
87
87
  const tracked = this.spots.get(canonical);
88
88
  const store = this.authorityStore;
@@ -116,33 +116,9 @@ class ZLinkSpotLocationClaims {
116
116
  return undefined;
117
117
  }
118
118
  tracked.storeVersion = result.storeVersion.value;
119
- this.invalidateSpotRoute?.(tracked.spotId);
120
- let restored = false;
119
+ onCommitted();
121
120
  return {
122
- restoreReady: async () => {
123
- if (restored)
124
- return;
125
- const restore = await store.compareExchangeAuthority(key, result.storeVersion, {
126
- kind: 'put',
127
- generationTransition: 'preserve',
128
- payload: (0, service_relocation_runtime_1.replaceServiceRelocationAuthorityApplicationPayload)(current.payload, (0, service_authority_payload_codec_1.encodeServiceInstanceAuthorityPayload)({
129
- state: 'ready',
130
- stableType: decoded.stableType,
131
- spotId: decoded.spotId,
132
- ownerId: decoded.ownerId,
133
- ownerLeaseGeneration: decoded.ownerLeaseGeneration,
134
- ownerMeshName: decoded.ownerMeshName,
135
- ownerNodeRid: decoded.ownerNodeRid,
136
- ownerNodeGeneration: decoded.ownerNodeGeneration
137
- }))
138
- });
139
- if (restore.kind !== 'stored') {
140
- throw (0, framework_errors_internal_1.createInternalFrameworkException)(framework_errors_internal_1.ZLinkFrameworkInternalErrorKind.SpotMoving, `Instance Spot '${String(spotId)}' Ready authority could not be restored after idle eviction was declined.`, true);
141
- }
142
- restored = true;
143
- tracked.storeVersion = restore.storeVersion.value;
144
- this.invalidateSpotRoute?.(tracked.spotId);
145
- }
121
+ release: async () => undefined
146
122
  };
147
123
  }
148
124
  onOwnershipLost(event) {
@@ -343,6 +343,7 @@ export type SessionRelocationRouteUpdate = {
343
343
  readonly targetAuthorityOwnerGeneration: NonzeroU64;
344
344
  readonly targetNodeRid: Rid;
345
345
  readonly targetNodeGeneration: NonzeroU64;
346
+ readonly targetOwnerLeaseGeneration: NonzeroU64;
346
347
  } | {
347
348
  readonly action: "abort";
348
349
  readonly currentAuthorityOwnerGeneration: NonzeroU64;
@@ -3701,6 +3701,7 @@ function readSessionRelocationRouteUpdate(reader, context, enclosing, flags) {
3701
3701
  value["targetAuthorityOwnerGeneration"] = readNonzeroU64(body, context, value, flags);
3702
3702
  value["targetNodeRid"] = readRid(body, context, value, flags);
3703
3703
  value["targetNodeGeneration"] = readNonzeroU64(body, context, value, flags);
3704
+ value["targetOwnerLeaseGeneration"] = readNonzeroU64(body, context, value, flags);
3704
3705
  }
3705
3706
  else if (same(value["action"], "abort")) {
3706
3707
  value["currentAuthorityOwnerGeneration"] = readNonzeroU64(body, context, value, flags);
@@ -3732,9 +3733,12 @@ function writeSessionRelocationRouteUpdate(input, writer, context, enclosing, fl
3732
3733
  if (value["targetNodeGeneration"] === undefined)
3733
3734
  fail("targetNodeGeneration required");
3734
3735
  writeNonzeroU64(numeric(value["targetNodeGeneration"]), body, context, value, flags);
3736
+ if (value["targetOwnerLeaseGeneration"] === undefined)
3737
+ fail("targetOwnerLeaseGeneration required");
3738
+ writeNonzeroU64(numeric(value["targetOwnerLeaseGeneration"]), body, context, value, flags);
3735
3739
  }
3736
3740
  else if (same(value["action"], "abort")) {
3737
- if (value["previousAuthorityOwnerGeneration"] !== undefined || value["targetAuthorityOwnerGeneration"] !== undefined || value["targetNodeRid"] !== undefined || value["targetNodeGeneration"] !== undefined)
3741
+ if (value["previousAuthorityOwnerGeneration"] !== undefined || value["targetAuthorityOwnerGeneration"] !== undefined || value["targetNodeRid"] !== undefined || value["targetNodeGeneration"] !== undefined || value["targetOwnerLeaseGeneration"] !== undefined)
3738
3742
  fail("session-relocation-route-update discriminator agreement");
3739
3743
  if (value["currentAuthorityOwnerGeneration"] === undefined)
3740
3744
  fail("currentAuthorityOwnerGeneration required");
@@ -200,6 +200,7 @@ export type ServiceWireSessionRouteUpdate = {
200
200
  readonly targetAuthorityOwnerGeneration: bigint;
201
201
  readonly targetNodeRid: Uint8Array;
202
202
  readonly targetNodeGeneration: bigint;
203
+ readonly targetOwnerLeaseGeneration: bigint;
203
204
  } | {
204
205
  readonly action: "abort";
205
206
  readonly currentAuthorityOwnerGeneration: bigint;
@@ -522,12 +522,13 @@ function b3ValidTerminal(result, failure, payload) { const boundary = [101, 103,
522
522
  } if (b3FailureResults.get(failure) !== result)
523
523
  throw new RangeError("typed failure"); }
524
524
  function b3WriteRoute(out, v) { out.push(v.action === "commit" ? 1 : 2); body16(out, b => { if (v.action === "commit") {
525
- if (v.previousAuthorityOwnerGeneration === 0n || v.targetAuthorityOwnerGeneration === 0n || v.targetNodeGeneration === 0n)
525
+ if (v.previousAuthorityOwnerGeneration === 0n || v.targetAuthorityOwnerGeneration === 0n || v.targetNodeGeneration === 0n || v.targetOwnerLeaseGeneration === 0n)
526
526
  throw new RangeError("route commit");
527
527
  u64(b, v.previousAuthorityOwnerGeneration);
528
528
  u64(b, v.targetAuthorityOwnerGeneration);
529
529
  rid(b, v.targetNodeRid);
530
530
  u64(b, v.targetNodeGeneration);
531
+ u64(b, v.targetOwnerLeaseGeneration);
531
532
  }
532
533
  else {
533
534
  if (v.currentAuthorityOwnerGeneration === 0n)
@@ -535,7 +536,7 @@ else {
535
536
  u64(b, v.currentAuthorityOwnerGeneration);
536
537
  } }); }
537
538
  function b3ReadRoute(bytes, at) { const action = read8(bytes, at), end = boundedEnd(bytes, at, read16(bytes, at), "session route"); let value; if (action === 1)
538
- value = { action: "commit", previousAuthorityOwnerGeneration: nonzero64(bytes, at, "previous authority"), targetAuthorityOwnerGeneration: nonzero64(bytes, at, "target authority"), targetNodeRid: readRid(bytes, at), targetNodeGeneration: nonzero64(bytes, at, "target node") };
539
+ value = { action: "commit", previousAuthorityOwnerGeneration: nonzero64(bytes, at, "previous authority"), targetAuthorityOwnerGeneration: nonzero64(bytes, at, "target authority"), targetNodeRid: readRid(bytes, at), targetNodeGeneration: nonzero64(bytes, at, "target node"), targetOwnerLeaseGeneration: nonzero64(bytes, at, "target lease") };
539
540
  else if (action === 2)
540
541
  value = { action: "abort", currentAuthorityOwnerGeneration: nonzero64(bytes, at, "current authority") };
541
542
  else
@@ -1,6 +1,6 @@
1
1
  import type { ActorRef, RoutingId, ZLinkActor, ZLinkActorJoinOperationId } from '../../contracts';
2
2
  import type { ZLinkRemoteBoundSessionTarget } from '../actors/actor-runtime-state';
3
- import type { ZLinkDeferredJoinAcceptedRoot } from '../actors/deferred-join-accepted-journal';
3
+ import type { ZLinkDeferredJoinCompletion } from '../actors/deferred-join-completion';
4
4
  import type { ZLinkActorRequestTerminal } from './spot-actor-packet-dispatch';
5
5
  /**
6
6
  * One production-ingress arrival parked at the target between admission
@@ -40,7 +40,7 @@ export interface ZLinkFormalRemoteActorAdmissionOutcome {
40
40
  readonly actorRef: ActorRef;
41
41
  readonly reply?: Buffer;
42
42
  readonly replyContentType?: string;
43
- readonly deferredJoinRoot?: ZLinkDeferredJoinAcceptedRoot;
43
+ readonly deferredJoinCompletion?: ZLinkDeferredJoinCompletion;
44
44
  }
45
45
  export interface ZLinkFormalRemoteActorAdmissionFailure {
46
46
  readonly error: unknown;
@@ -111,7 +111,7 @@ export declare class ZLinkFormalRemoteActorAdmissionRegistry {
111
111
  complete(transferId: string, outcome: ZLinkFormalRemoteActorAdmissionOutcome): void;
112
112
  fail(transferId: string, error: unknown): void;
113
113
  markCommitted(transferId: string, actor: ZLinkActor): void;
114
- attachDeferredJoinRoot(transferId: string, root: ZLinkDeferredJoinAcceptedRoot): void;
114
+ attachDeferredJoinCompletion(transferId: string, root: ZLinkDeferredJoinCompletion): void;
115
115
  abort(transferId: string): void;
116
116
  /**
117
117
  * Releases the admission for {@code transferId} — normal retention
@@ -161,9 +161,9 @@ class ZLinkFormalRemoteActorAdmissionRegistry {
161
161
  ...(outcome.replyContentType === undefined
162
162
  ? {}
163
163
  : { replyContentType: outcome.replyContentType }),
164
- ...(outcome.deferredJoinRoot === undefined
164
+ ...(outcome.deferredJoinCompletion === undefined
165
165
  ? {}
166
- : { deferredJoinRoot: outcome.deferredJoinRoot })
166
+ : { deferredJoinCompletion: outcome.deferredJoinCompletion })
167
167
  };
168
168
  entry.resolveResult(entry.result);
169
169
  if (!outcome.accepted) {
@@ -192,7 +192,7 @@ class ZLinkFormalRemoteActorAdmissionRegistry {
192
192
  entry.state = 'committed';
193
193
  entry.actor = actor;
194
194
  }
195
- attachDeferredJoinRoot(transferId, root) {
195
+ attachDeferredJoinCompletion(transferId, root) {
196
196
  const entry = this.admissions.get(transferId);
197
197
  if (entry === undefined ||
198
198
  entry.state !== 'admitted' ||
@@ -201,7 +201,7 @@ class ZLinkFormalRemoteActorAdmissionRegistry {
201
201
  !entry.result.accepted) {
202
202
  throw new Error(`Remote actor admission '${transferId}' cannot attach deferred recovery.`);
203
203
  }
204
- entry.result = { ...entry.result, deferredJoinRoot: root };
204
+ entry.result = { ...entry.result, deferredJoinCompletion: root };
205
205
  }
206
206
  abort(transferId) {
207
207
  const entry = this.admissions.get(transferId);