@zlink-systems/framework 0.30.0 → 0.30.1

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 (245) hide show
  1. package/LICENSE +150 -68
  2. package/dist/.tsbuildinfo +1 -1
  3. package/dist/contracts/Actors/ZLinkActorClient.d.ts +2 -1
  4. package/dist/contracts/Channels/Calls.d.ts +2 -1
  5. package/dist/contracts/Common/ZLinkMessageMetadata.js +11 -5
  6. package/dist/contracts/Handlers/Attributes.d.ts +5 -13
  7. package/dist/contracts/Handlers/Attributes.js +7 -11
  8. package/dist/contracts/Handlers/JsonContract.d.ts +2 -46
  9. package/dist/contracts/Handlers/JsonContract.js +4 -153
  10. package/dist/contracts/Spots/Contracts.d.ts +2 -1
  11. package/dist/nest-integration.d.ts +1 -1
  12. package/dist/nest-integration.js +2 -1
  13. package/dist/runtime/actors/actor-client.d.ts +1 -1
  14. package/dist/runtime/actors/actor-client.js +14 -12
  15. package/dist/runtime/actors/actor-handoff.d.ts +1 -1
  16. package/dist/runtime/actors/actor-handoff.js +7 -4
  17. package/dist/runtime/actors/actor-join-relocation.d.ts +1 -0
  18. package/dist/runtime/actors/actor-local-native-join.js +9 -12
  19. package/dist/runtime/actors/actor-remote-wire.js +15 -0
  20. package/dist/runtime/actors/actor-routed-join-transport.d.ts +6 -2
  21. package/dist/runtime/actors/actor-routed-json-request.d.ts +2 -0
  22. package/dist/runtime/actors/index.d.ts +2 -1
  23. package/dist/runtime/actors/index.js +18 -6
  24. package/dist/runtime/actors/spot-actor-dispatch.js +2 -2
  25. package/dist/runtime/admission.d.ts +1 -1
  26. package/dist/runtime/admission.js +15 -5
  27. package/dist/runtime/application-jobs/application-ingress-record-owner.d.ts +6 -8
  28. package/dist/runtime/application-jobs/application-ingress-record-owner.js +39 -22
  29. package/dist/runtime/application-jobs/application-job-queue-scope.d.ts +2 -1
  30. package/dist/runtime/application-jobs/application-job-queue-scope.js +37 -22
  31. package/dist/runtime/application-jobs/contracts.d.ts +10 -1
  32. package/dist/runtime/backend/contracts/index.d.ts +18 -9
  33. package/dist/runtime/backend/mesh-completion-table.d.ts +9 -1
  34. package/dist/runtime/backend/mesh-completion-table.js +149 -49
  35. package/dist/runtime/backend/mesh-dispatch-pump.d.ts +3 -0
  36. package/dist/runtime/backend/mesh-dispatch-pump.js +32 -11
  37. package/dist/runtime/backend/node/node-backend-adapter-support.d.ts +2 -2
  38. package/dist/runtime/backend/node/node-backend-adapter-support.js +16 -9
  39. package/dist/runtime/backend/node/node-dealer-channel-client-transport.d.ts +1 -1
  40. package/dist/runtime/backend/node/node-dealer-channel-client-transport.js +5 -2
  41. package/dist/runtime/backend/node/node-raw-binding-port.js +42 -22
  42. package/dist/runtime/backend/node/node-raw-mesh-backend.d.ts +13 -5
  43. package/dist/runtime/backend/node/node-raw-mesh-backend.js +69 -51
  44. package/dist/runtime/backend/node/node-socket-backend-adapter.js +6 -6
  45. package/dist/runtime/backend/raw-binding-port.d.ts +2 -2
  46. package/dist/runtime/backend/runtime-message.d.ts +1 -0
  47. package/dist/runtime/backend/runtime-message.js +5 -0
  48. package/dist/runtime/backend/runtime-values.d.ts +1 -0
  49. package/dist/runtime/backend/runtime-values.js +2 -1
  50. package/dist/runtime/channels/channel-clients.d.ts +1 -0
  51. package/dist/runtime/channels/channel-clients.js +58 -21
  52. package/dist/runtime/channels/channel-dispatch-pipeline.d.ts +3 -2
  53. package/dist/runtime/channels/channel-dispatch-pipeline.js +20 -11
  54. package/dist/runtime/channels/channel-dispatch-services.d.ts +1 -0
  55. package/dist/runtime/channels/channel-dispatch-services.js +45 -0
  56. package/dist/runtime/channels/channel-dispatchers.d.ts +1 -1
  57. package/dist/runtime/channels/channel-dispatchers.js +27 -26
  58. package/dist/runtime/channels/channel-envelope-inspection.d.ts +1 -2
  59. package/dist/runtime/channels/channel-envelope-inspection.js +1 -16
  60. package/dist/runtime/channels/channel-envelope.d.ts +1 -0
  61. package/dist/runtime/channels/channel-envelope.js +83 -8
  62. package/dist/runtime/channels/channel-outbound-operations.d.ts +2 -2
  63. package/dist/runtime/channels/channel-outbound-operations.js +8 -8
  64. package/dist/runtime/channels/channel-runtime-manager.d.ts +6 -6
  65. package/dist/runtime/channels/channel-runtime-manager.js +12 -12
  66. package/dist/runtime/channels/channel-transports.d.ts +18 -15
  67. package/dist/runtime/channels/channel-transports.js +48 -31
  68. package/dist/runtime/channels/local-spot-route-transport.d.ts +1 -1
  69. package/dist/runtime/channels/local-spot-route-transport.js +2 -1
  70. package/dist/runtime/channels/router-socket-spot-route-transport.d.ts +2 -2
  71. package/dist/runtime/channels/router-socket-spot-route-transport.js +4 -4
  72. package/dist/runtime/channels/source-spot-router.d.ts +2 -2
  73. package/dist/runtime/channels/source-spot-router.js +4 -4
  74. package/dist/runtime/channels/spot-node-route-transport.d.ts +2 -2
  75. package/dist/runtime/channels/spot-node-route-transport.js +4 -4
  76. package/dist/runtime/channels/spot-route-bridge-transport.d.ts +2 -2
  77. package/dist/runtime/channels/spot-route-bridge-transport.js +4 -4
  78. package/dist/runtime/channels/spot-route-dispatch-strategy.d.ts +5 -4
  79. package/dist/runtime/channels/spot-route-dispatch-strategy.js +18 -18
  80. package/dist/runtime/execution/serial-execution-queue.d.ts +1 -0
  81. package/dist/runtime/execution/serial-execution-queue.js +1 -0
  82. package/dist/runtime/foundation/actor-join-recovery-codec.js +2 -2
  83. package/dist/runtime/foundation/durable-service-request.d.ts +14 -0
  84. package/dist/runtime/foundation/durable-service-request.js +98 -0
  85. package/dist/runtime/foundation/operation-identity.d.ts +1 -0
  86. package/dist/runtime/foundation/operation-identity.js +5 -1
  87. package/dist/runtime/foundation/raw-service-mesh-runtime.d.ts +22 -5
  88. package/dist/runtime/foundation/raw-service-mesh-runtime.js +356 -232
  89. package/dist/runtime/foundation/service-relocation-object-owner.d.ts +1 -0
  90. package/dist/runtime/foundation/service-relocation-object-owner.js +1 -0
  91. package/dist/runtime/foundation/service-relocation-runtime.d.ts +2 -0
  92. package/dist/runtime/foundation/service-relocation-runtime.js +13 -1
  93. package/dist/runtime/foundation/service-runtime-contracts.d.ts +2 -0
  94. package/dist/runtime/foundation/service-stateful-runtime.d.ts +4 -4
  95. package/dist/runtime/foundation/service-stateful-runtime.js +44 -103
  96. package/dist/runtime/foundation/service-stateful-wire-codec.d.ts +0 -5
  97. package/dist/runtime/foundation/service-topology-registry.d.ts +12 -2
  98. package/dist/runtime/foundation/service-topology-registry.js +61 -27
  99. package/dist/runtime/foundation/service-wire-m6a-codec.d.ts +3 -3
  100. package/dist/runtime/foundation/service-wire-m6a-codec.js +36 -38
  101. package/dist/runtime/handlers/handler-instance-scope.d.ts +8 -0
  102. package/dist/runtime/handlers/handler-instance-scope.js +54 -11
  103. package/dist/runtime/host/actor-runtime-options-factory.js +2 -2
  104. package/dist/runtime/host/application-job-queue.d.ts +19 -7
  105. package/dist/runtime/host/application-job-queue.js +150 -42
  106. package/dist/runtime/host/entry-actor-runtime.d.ts +1 -0
  107. package/dist/runtime/host/entry-actor-runtime.js +3 -0
  108. package/dist/runtime/host/index.d.ts +7 -1
  109. package/dist/runtime/host/index.js +142 -118
  110. package/dist/runtime/host/remote-bound-session-relay.js +2 -18
  111. package/dist/runtime/host/route-mesh-runtime.js +1 -1
  112. package/dist/runtime/host/service-relocation-control.d.ts +1 -0
  113. package/dist/runtime/host/service-relocation-control.js +10 -4
  114. package/dist/runtime/host/service-relocation-host-runtime.d.ts +6 -8
  115. package/dist/runtime/host/service-relocation-host-runtime.js +213 -241
  116. package/dist/runtime/host/spot-address-transport.js +3 -2
  117. package/dist/runtime/host/spot-runtime-options-factory.js +1 -0
  118. package/dist/runtime/locations/actor-location-claims.d.ts +2 -2
  119. package/dist/runtime/locations/actor-location-claims.js +34 -19
  120. package/dist/runtime/locations/lifecycle.d.ts +1 -2
  121. package/dist/runtime/locations/lifecycle.js +2 -5
  122. package/dist/runtime/locations/runtime.d.ts +1 -1
  123. package/dist/runtime/locations/runtime.js +24 -23
  124. package/dist/runtime/messaging/framework-json-v1.d.ts +4 -6
  125. package/dist/runtime/messaging/framework-json-v1.js +38 -294
  126. package/dist/runtime/messaging/packet-name.d.ts +1 -1
  127. package/dist/runtime/messaging/packet-name.js +8 -24
  128. package/dist/runtime/messaging/request-result.d.ts +2 -0
  129. package/dist/runtime/messaging/request-result.js +54 -0
  130. package/dist/runtime/messaging/submission-result.d.ts +1 -0
  131. package/dist/runtime/messaging/submission-result.js +5 -2
  132. package/dist/runtime/protocol/service_wire_codec.generated.d.ts +15 -0
  133. package/dist/runtime/protocol/service_wire_codec.generated.js +144 -0
  134. package/dist/runtime/protocol/service_wire_pilot_codec.generated.d.ts +9 -0
  135. package/dist/runtime/protocol/service_wire_pilot_codec.generated.js +14 -1
  136. package/dist/runtime/spots/formal-remote-actor-admission-registry.d.ts +7 -2
  137. package/dist/runtime/spots/formal-remote-actor-admission-registry.js +33 -19
  138. package/dist/runtime/spots/index.d.ts +3 -0
  139. package/dist/runtime/spots/index.js +9 -2
  140. package/dist/runtime/spots/spot-activation.d.ts +1 -0
  141. package/dist/runtime/spots/spot-activation.js +17 -8
  142. package/dist/runtime/spots/spot-entry-activation.js +6 -2
  143. package/dist/runtime/spots/spot-handler-registry.d.ts +3 -1
  144. package/dist/runtime/spots/spot-handler-registry.js +18 -8
  145. package/dist/runtime/spots/spot-node-autoconnect.js +4 -3
  146. package/dist/runtime/spots/spot-outbound.d.ts +3 -0
  147. package/dist/runtime/spots/spot-outbound.js +24 -15
  148. package/dist/runtime/spots/spot-routed-spot-packet-dispatch.d.ts +1 -0
  149. package/dist/runtime/spots/spot-routed-spot-packet-dispatch.js +1 -1
  150. package/dist/runtime/spots/spot-runtime-ports.d.ts +1 -0
  151. package/dist/runtime/spots/spot-subscription-dispatch.js +0 -3
  152. package/dist/runtime/spots/spot-timer.js +1 -0
  153. package/dist/runtime/streams/stream-session-runtime.d.ts +1 -1
  154. package/dist/runtime/streams/stream-session-runtime.js +13 -27
  155. package/package.json +2 -2
  156. package/src/contracts/Actors/ZLinkActorClient.ts +2 -1
  157. package/src/contracts/Channels/Calls.ts +2 -1
  158. package/src/contracts/Common/ZLinkMessageMetadata.ts +13 -8
  159. package/src/contracts/Handlers/Attributes.ts +14 -21
  160. package/src/contracts/Handlers/JsonContract.ts +8 -216
  161. package/src/contracts/Spots/Contracts.ts +2 -1
  162. package/src/nest-integration.ts +1 -0
  163. package/src/runtime/actors/actor-client.ts +40 -16
  164. package/src/runtime/actors/actor-handoff.ts +9 -4
  165. package/src/runtime/actors/actor-join-relocation.ts +1 -0
  166. package/src/runtime/actors/actor-local-native-join.ts +17 -26
  167. package/src/runtime/actors/actor-remote-wire.ts +17 -0
  168. package/src/runtime/actors/actor-routed-join-transport.ts +14 -4
  169. package/src/runtime/actors/actor-routed-json-request.ts +10 -2
  170. package/src/runtime/actors/index.ts +19 -5
  171. package/src/runtime/actors/spot-actor-dispatch.ts +4 -2
  172. package/src/runtime/admission.ts +18 -5
  173. package/src/runtime/application-jobs/application-ingress-record-owner.ts +41 -25
  174. package/src/runtime/application-jobs/application-job-queue-scope.ts +51 -22
  175. package/src/runtime/application-jobs/contracts.ts +14 -1
  176. package/src/runtime/backend/contracts/index.ts +53 -14
  177. package/src/runtime/backend/mesh-completion-table.ts +156 -57
  178. package/src/runtime/backend/mesh-dispatch-pump.ts +40 -10
  179. package/src/runtime/backend/node/node-backend-adapter-support.ts +17 -8
  180. package/src/runtime/backend/node/node-dealer-channel-client-transport.ts +12 -2
  181. package/src/runtime/backend/node/node-raw-binding-port.ts +57 -30
  182. package/src/runtime/backend/node/node-raw-mesh-backend.ts +128 -65
  183. package/src/runtime/backend/node/node-socket-backend-adapter.ts +21 -6
  184. package/src/runtime/backend/raw-binding-port.ts +7 -2
  185. package/src/runtime/backend/runtime-message.ts +6 -0
  186. package/src/runtime/backend/runtime-values.ts +1 -0
  187. package/src/runtime/channels/channel-clients.ts +90 -41
  188. package/src/runtime/channels/channel-dispatch-pipeline.ts +69 -34
  189. package/src/runtime/channels/channel-dispatch-services.ts +69 -1
  190. package/src/runtime/channels/channel-dispatchers.ts +29 -27
  191. package/src/runtime/channels/channel-envelope-inspection.ts +2 -16
  192. package/src/runtime/channels/channel-envelope.ts +133 -8
  193. package/src/runtime/channels/channel-outbound-operations.ts +22 -8
  194. package/src/runtime/channels/channel-runtime-manager.ts +29 -12
  195. package/src/runtime/channels/channel-transports.ts +128 -60
  196. package/src/runtime/channels/local-spot-route-transport.ts +3 -1
  197. package/src/runtime/channels/router-socket-spot-route-transport.ts +13 -4
  198. package/src/runtime/channels/source-spot-router.ts +8 -4
  199. package/src/runtime/channels/spot-node-route-transport.ts +8 -4
  200. package/src/runtime/channels/spot-route-bridge-transport.ts +6 -4
  201. package/src/runtime/channels/spot-route-dispatch-strategy.ts +47 -18
  202. package/src/runtime/execution/serial-execution-queue.ts +2 -0
  203. package/src/runtime/foundation/actor-join-recovery-codec.ts +2 -2
  204. package/src/runtime/foundation/durable-service-request.ts +137 -0
  205. package/src/runtime/foundation/operation-identity.ts +5 -1
  206. package/src/runtime/foundation/raw-service-mesh-runtime.ts +484 -293
  207. package/src/runtime/foundation/service-relocation-object-owner.ts +2 -0
  208. package/src/runtime/foundation/service-relocation-runtime.ts +18 -1
  209. package/src/runtime/foundation/service-runtime-contracts.ts +7 -1
  210. package/src/runtime/foundation/service-stateful-runtime.ts +67 -125
  211. package/src/runtime/foundation/service-stateful-wire-codec.ts +0 -5
  212. package/src/runtime/foundation/service-topology-registry.ts +91 -36
  213. package/src/runtime/foundation/service-wire-m6a-codec.ts +57 -38
  214. package/src/runtime/handlers/handler-instance-scope.ts +67 -16
  215. package/src/runtime/host/actor-runtime-options-factory.ts +13 -2
  216. package/src/runtime/host/application-job-queue.ts +175 -41
  217. package/src/runtime/host/entry-actor-runtime.ts +4 -0
  218. package/src/runtime/host/index.ts +201 -156
  219. package/src/runtime/host/remote-bound-session-relay.ts +2 -23
  220. package/src/runtime/host/route-mesh-runtime.ts +1 -1
  221. package/src/runtime/host/service-relocation-control.ts +11 -5
  222. package/src/runtime/host/service-relocation-host-runtime.ts +315 -291
  223. package/src/runtime/host/spot-address-transport.ts +4 -2
  224. package/src/runtime/host/spot-runtime-options-factory.ts +2 -0
  225. package/src/runtime/locations/actor-location-claims.ts +52 -30
  226. package/src/runtime/locations/lifecycle.ts +8 -26
  227. package/src/runtime/locations/runtime.ts +28 -24
  228. package/src/runtime/messaging/framework-json-v1.ts +5 -325
  229. package/src/runtime/messaging/packet-name.ts +5 -25
  230. package/src/runtime/messaging/request-result.ts +58 -0
  231. package/src/runtime/messaging/submission-result.ts +5 -1
  232. package/src/runtime/protocol/service_wire_codec.generated.ts +131 -1
  233. package/src/runtime/protocol/service_wire_pilot_codec.generated.ts +4 -4
  234. package/src/runtime/spots/formal-remote-actor-admission-registry.ts +43 -23
  235. package/src/runtime/spots/index.ts +14 -2
  236. package/src/runtime/spots/spot-activation.ts +28 -10
  237. package/src/runtime/spots/spot-entry-activation.ts +9 -2
  238. package/src/runtime/spots/spot-handler-registry.ts +41 -8
  239. package/src/runtime/spots/spot-node-autoconnect.ts +6 -2
  240. package/src/runtime/spots/spot-outbound.ts +36 -16
  241. package/src/runtime/spots/spot-routed-spot-packet-dispatch.ts +2 -1
  242. package/src/runtime/spots/spot-runtime-ports.ts +1 -0
  243. package/src/runtime/spots/spot-subscription-dispatch.ts +0 -3
  244. package/src/runtime/spots/spot-timer.ts +5 -1
  245. package/src/runtime/streams/stream-session-runtime.ts +12 -29
@@ -1,3 +1,7 @@
1
+ import {
2
+ readFrameworkPacketJsonContract,
3
+ normalizePacketName
4
+ } from '@zlink-systems/stream-wire/internal/json';
1
5
  import { readZLinkDecoratorMetadata } from '../../contracts/Handlers/Attributes';
2
6
  import type { ZLinkPacketJsonContract } from '../../contracts/Handlers/JsonContract';
3
7
  import { ZLinkConfigurationException } from '../configuration';
@@ -42,23 +46,7 @@ export function resolveFrameworkPacketJsonContract(
42
46
  return readFrameworkPacketJsonContract(constructor, explicitPacketName);
43
47
  }
44
48
 
45
- export function readFrameworkPacketJsonContract(
46
- type: object,
47
- explicitPacketName?: string
48
- ): ZLinkPacketJsonContract | undefined {
49
- const expectedPacketName = normalizePacketName(explicitPacketName);
50
- for (const metadata of readZLinkDecoratorMetadata(type)) {
51
- if (
52
- metadata.kind === 'packet' &&
53
- metadata.jsonContract !== undefined &&
54
- (expectedPacketName === undefined ||
55
- normalizePacketName(metadata.packetName) === expectedPacketName)
56
- ) {
57
- return metadata.jsonContract;
58
- }
59
- }
60
- return undefined;
61
- }
49
+ export { readFrameworkPacketJsonContract } from '@zlink-systems/stream-wire/internal/json';
62
50
 
63
51
  function tryDecoratorPacketName(payload: unknown): string | undefined {
64
52
  if (typeof payload !== 'object' || payload === null) {
@@ -86,11 +74,3 @@ function tryConstructorPacketName(payload: unknown): string | undefined {
86
74
  }
87
75
  return normalizePacketName(name);
88
76
  }
89
-
90
- function normalizePacketName(value: unknown): string | undefined {
91
- if (typeof value !== 'string') {
92
- return undefined;
93
- }
94
- const trimmed = value.trim();
95
- return trimmed.length > 0 ? trimmed : undefined;
96
- }
@@ -0,0 +1,58 @@
1
+ import type { ZLinkRequest } from '../../contracts/Handlers/Attributes';
2
+
3
+ const completedAdmission = Promise.resolve();
4
+ const ignoreAdmissionFailure = (): void => {};
5
+
6
+ export function createZLinkRequest<TReply>(
7
+ start: (onAdmitted: () => void) => Promise<TReply>,
8
+ deliverReply?: (reply: Promise<TReply>) => Promise<TReply>
9
+ ): ZLinkRequest<TReply> {
10
+ let admitted: Promise<void> | undefined;
11
+ let resolveAdmission: (() => void) | undefined;
12
+ let rejectAdmission: ((error: unknown) => void) | undefined;
13
+ const confirmAdmission = (): void => {
14
+ admitted ??= completedAdmission;
15
+ resolveAdmission?.();
16
+ };
17
+ const failAdmission = (error: unknown): void => {
18
+ if (admitted === undefined) {
19
+ admitted = Promise.reject(error);
20
+ // Existing callers may observe only the reply Promise. Observing the
21
+ // rejection here leaves the public admission Promise rejected.
22
+ void admitted.catch(ignoreAdmissionFailure);
23
+ } else {
24
+ rejectAdmission?.(error);
25
+ }
26
+ };
27
+ const observeAdmission = (): Promise<void> => {
28
+ if (admitted === undefined) {
29
+ admitted = new Promise<void>((resolve, reject) => {
30
+ resolveAdmission = resolve;
31
+ rejectAdmission = reject;
32
+ });
33
+ void admitted.catch(ignoreAdmissionFailure);
34
+ }
35
+ return admitted;
36
+ };
37
+ let pending: Promise<TReply>;
38
+ try {
39
+ pending = start(confirmAdmission);
40
+ } catch (error) {
41
+ pending = Promise.reject(error);
42
+ }
43
+ const observed = pending.then(
44
+ (value) => {
45
+ // A successful reply proves admission even without an observation callback.
46
+ confirmAdmission();
47
+ return value;
48
+ },
49
+ (error: unknown) => {
50
+ failAdmission(error);
51
+ throw error;
52
+ }
53
+ );
54
+ const reply = deliverReply?.(observed) ?? observed;
55
+ return Object.defineProperty(reply, 'admitted', {
56
+ get: observeAdmission
57
+ }) as ZLinkRequest<TReply>;
58
+ }
@@ -18,6 +18,10 @@ export interface ZLinkSubmitResult {
18
18
  readonly status: ZLinkSubmitStatus;
19
19
  }
20
20
 
21
+ export const submittedResult: ZLinkSubmitResult = Object.freeze({
22
+ status: ZLinkSubmitStatus.Submitted
23
+ });
24
+
21
25
  /** Projects typed submit failure; capacity refusal has no admission wait token. */
22
26
  export function submitToRequestResult(result: number, phase: 'submit' | 'completion'): number {
23
27
  switch (result) {
@@ -54,7 +58,7 @@ export function classifySubmitResult(
54
58
  const terminal = submitToRequestResult(result, phase);
55
59
  switch (terminal) {
56
60
  case RequestResult.Ok:
57
- return { status: ZLinkSubmitStatus.Submitted };
61
+ return submittedResult;
58
62
  case RequestResult.TimedOut:
59
63
  return { status: ZLinkSubmitStatus.TimedOut };
60
64
  case RequestResult.NotFound:
@@ -7584,7 +7584,127 @@ function writeRelocationPendingTimerTickVector(input: RelocationPendingTimerTick
7584
7584
  export function decodeRelocationPendingTimerTickVector(bytes: Uint8Array, context: ServiceWireDecoderContext): RelocationPendingTimerTickVector { const reader = new Reader(bytes); const value = readRelocationPendingTimerTickVector(reader, context, {}, 0); reader.done("relocation-pending-timer-tick-vector"); return value; }
7585
7585
  export function encodeRelocationPendingTimerTickVector(value: RelocationPendingTimerTickVector, context: ServiceWireDecoderContext): Uint8Array { const writer = new Writer(); writeRelocationPendingTimerTickVector(value, writer, context, {}, 0); return writer.result(); }
7586
7586
 
7587
- export type RelocationEnvelopeV1 = { readonly relocation: RelocationId; readonly object: RelocationObjectIdentity; readonly applicationVersion: ApplicationVersion; readonly applicationStates: RelocationParticipantApplicationStateVector; readonly savedWork: SavedWorkVector; readonly timerRegistrations: RelocationTimerRegistrationVector; readonly pendingTimerTicks: RelocationPendingTimerTickVector };
7587
+ export type RelocationSessionBinding = { readonly participantId: NonzeroU64; readonly sessionOwnerNodeRid: Rid; readonly sessionOwnerNodeGeneration: NonzeroU64; readonly sessionOwnerId: Text8; readonly sessionOwnerLeaseGeneration: NonzeroU64; readonly sessionRid: Rid; readonly bindingGeneration: NonzeroU64 };
7588
+
7589
+ function readRelocationSessionBinding(reader: Reader, context: ServiceWireDecoderContext, enclosing: any, flags: number): RelocationSessionBinding {
7590
+ void context; void enclosing; void flags;
7591
+ const value: any = {};
7592
+ value["participantId"] = readNonzeroU64(reader, context, value, flags);
7593
+
7594
+
7595
+ value["sessionOwnerNodeRid"] = readRid(reader, context, value, flags);
7596
+
7597
+
7598
+ value["sessionOwnerNodeGeneration"] = readNonzeroU64(reader, context, value, flags);
7599
+
7600
+
7601
+ value["sessionOwnerId"] = readText8(reader, context, value, flags);
7602
+
7603
+
7604
+ value["sessionOwnerLeaseGeneration"] = readNonzeroU64(reader, context, value, flags);
7605
+
7606
+
7607
+ value["sessionRid"] = readRid(reader, context, value, flags);
7608
+
7609
+
7610
+ value["bindingGeneration"] = readNonzeroU64(reader, context, value, flags);
7611
+
7612
+
7613
+
7614
+
7615
+ return value;
7616
+ }
7617
+ function* readIncrementalRelocationSessionBinding(reader: IncrementalInput, context: ServiceWireDecoderContext, enclosing: any, flags: number): Generator<void, RelocationSessionBinding, void> {
7618
+ void context; void enclosing; void flags;
7619
+ const value: any = {};
7620
+ value["participantId"] = yield* readIncrementalNonzeroU64(reader, context, value, flags);
7621
+
7622
+
7623
+ value["sessionOwnerNodeRid"] = yield* readIncrementalRid(reader, context, value, flags);
7624
+
7625
+
7626
+ value["sessionOwnerNodeGeneration"] = yield* readIncrementalNonzeroU64(reader, context, value, flags);
7627
+
7628
+
7629
+ value["sessionOwnerId"] = yield* readIncrementalText8(reader, context, value, flags);
7630
+
7631
+
7632
+ value["sessionOwnerLeaseGeneration"] = yield* readIncrementalNonzeroU64(reader, context, value, flags);
7633
+
7634
+
7635
+ value["sessionRid"] = yield* readIncrementalRid(reader, context, value, flags);
7636
+
7637
+
7638
+ value["bindingGeneration"] = yield* readIncrementalNonzeroU64(reader, context, value, flags);
7639
+
7640
+
7641
+
7642
+
7643
+ return value;
7644
+ }
7645
+ function writeRelocationSessionBinding(input: RelocationSessionBinding, writer: Writer, context: ServiceWireDecoderContext, enclosing: any, flags: number): void {
7646
+ void context; void enclosing; void flags; const value: any = input;
7647
+
7648
+
7649
+ if (value["participantId"] === undefined) fail("participantId required");
7650
+
7651
+
7652
+ writeNonzeroU64(numeric(value["participantId"]), writer, context, value, flags);
7653
+ if (value["sessionOwnerNodeRid"] === undefined) fail("sessionOwnerNodeRid required");
7654
+
7655
+
7656
+ writeRid(value["sessionOwnerNodeRid"], writer, context, value, flags);
7657
+ if (value["sessionOwnerNodeGeneration"] === undefined) fail("sessionOwnerNodeGeneration required");
7658
+
7659
+
7660
+ writeNonzeroU64(numeric(value["sessionOwnerNodeGeneration"]), writer, context, value, flags);
7661
+ if (value["sessionOwnerId"] === undefined) fail("sessionOwnerId required");
7662
+
7663
+
7664
+ writeText8(value["sessionOwnerId"], writer, context, value, flags);
7665
+ if (value["sessionOwnerLeaseGeneration"] === undefined) fail("sessionOwnerLeaseGeneration required");
7666
+
7667
+
7668
+ writeNonzeroU64(numeric(value["sessionOwnerLeaseGeneration"]), writer, context, value, flags);
7669
+ if (value["sessionRid"] === undefined) fail("sessionRid required");
7670
+
7671
+
7672
+ writeRid(value["sessionRid"], writer, context, value, flags);
7673
+ if (value["bindingGeneration"] === undefined) fail("bindingGeneration required");
7674
+
7675
+
7676
+ writeNonzeroU64(numeric(value["bindingGeneration"]), writer, context, value, flags);
7677
+ }
7678
+ export function decodeRelocationSessionBinding(bytes: Uint8Array, context: ServiceWireDecoderContext): RelocationSessionBinding { const reader = new Reader(bytes); const value = readRelocationSessionBinding(reader, context, {}, 0); reader.done("relocation-session-binding"); return value; }
7679
+ export function encodeRelocationSessionBinding(value: RelocationSessionBinding, context: ServiceWireDecoderContext): Uint8Array { const writer = new Writer(); writeRelocationSessionBinding(value, writer, context, {}, 0); return writer.result(); }
7680
+
7681
+ export type RelocationSessionBindingVector = readonly RelocationSessionBinding[];
7682
+
7683
+ function readRelocationSessionBindingVector(reader: Reader, context: ServiceWireDecoderContext, enclosing: any, flags: number): RelocationSessionBindingVector {
7684
+ void context; void enclosing; void flags;
7685
+ const count = Number(readU32(reader, context, enclosing, flags)); if (count > 1024) fail("relocation-session-binding-vector count"); const value: any = Array.from({ length: count }, () => readRelocationSessionBinding(reader, context, enclosing, flags));
7686
+ try { for (let index = 1; index < value.length; ++index) if (compareResults([compareBigint(numeric(value[index - 1]["participantId"]), numeric(value[index]["participantId"]))]) >= 0) fail("relocation-session-binding-vector sorted"); } catch (error) { if (error instanceof ServiceWireProtocolError || error instanceof ServiceWireCapacityError) throw error; if (error instanceof RangeError) capacityFail("relocation-session-binding-vector constraint capacity"); throw error; }
7687
+
7688
+ return value;
7689
+ }
7690
+ function* readIncrementalRelocationSessionBindingVector(reader: IncrementalInput, context: ServiceWireDecoderContext, enclosing: any, flags: number): Generator<void, RelocationSessionBindingVector, void> {
7691
+ void context; void enclosing; void flags;
7692
+ const count = Number(yield* readIncrementalU32(reader, context, enclosing, flags)); if (count > 1024) fail("relocation-session-binding-vector count"); const value: any[] = []; for (let index = 0; index < count; ++index) { const item = yield* readIncrementalRelocationSessionBinding(reader, context, enclosing, flags); try { value.push(item); } catch { capacityFail("relocation-session-binding-vector capacity"); } }
7693
+ try { for (let index = 1; index < value.length; ++index) if (compareResults([compareBigint(numeric(value[index - 1]["participantId"]), numeric(value[index]["participantId"]))]) >= 0) fail("relocation-session-binding-vector sorted"); } catch (error) { if (error instanceof ServiceWireProtocolError || error instanceof ServiceWireCapacityError) throw error; if (error instanceof RangeError) capacityFail("relocation-session-binding-vector constraint capacity"); throw error; }
7694
+
7695
+ return value;
7696
+ }
7697
+ function writeRelocationSessionBindingVector(input: RelocationSessionBindingVector, writer: Writer, context: ServiceWireDecoderContext, enclosing: any, flags: number): void {
7698
+ void context; void enclosing; void flags; const value: any = input;
7699
+ if (!Array.isArray(value) || value.length > 1024) fail("relocation-session-binding-vector count");
7700
+ try { for (let index = 1; index < value.length; ++index) if (compareResults([compareBigint(numeric(value[index - 1]["participantId"]), numeric(value[index]["participantId"]))]) >= 0) fail("relocation-session-binding-vector sorted"); } catch (error) { if (error instanceof ServiceWireProtocolError || error instanceof ServiceWireCapacityError) throw error; if (error instanceof RangeError) capacityFail("relocation-session-binding-vector constraint capacity"); throw error; }
7701
+
7702
+ writeU32(value.length, writer, context, enclosing, flags); for (const item of value) writeRelocationSessionBinding(item, writer, context, enclosing, flags);
7703
+ }
7704
+ export function decodeRelocationSessionBindingVector(bytes: Uint8Array, context: ServiceWireDecoderContext): RelocationSessionBindingVector { const reader = new Reader(bytes); const value = readRelocationSessionBindingVector(reader, context, {}, 0); reader.done("relocation-session-binding-vector"); return value; }
7705
+ export function encodeRelocationSessionBindingVector(value: RelocationSessionBindingVector, context: ServiceWireDecoderContext): Uint8Array { const writer = new Writer(); writeRelocationSessionBindingVector(value, writer, context, {}, 0); return writer.result(); }
7706
+
7707
+ export type RelocationEnvelopeV1 = { readonly relocation: RelocationId; readonly object: RelocationObjectIdentity; readonly applicationVersion: ApplicationVersion; readonly applicationStates: RelocationParticipantApplicationStateVector; readonly savedWork: SavedWorkVector; readonly timerRegistrations: RelocationTimerRegistrationVector; readonly pendingTimerTicks: RelocationPendingTimerTickVector; readonly sessionBindings: RelocationSessionBindingVector };
7588
7708
 
7589
7709
  function readRelocationEnvelopeV1(reader: Reader, context: ServiceWireDecoderContext, enclosing: any, flags: number): RelocationEnvelopeV1 {
7590
7710
  void context; void enclosing; void flags;
@@ -7610,6 +7730,9 @@ function readRelocationEnvelopeV1(reader: Reader, context: ServiceWireDecoderCon
7610
7730
  value["pendingTimerTicks"] = readRelocationPendingTimerTickVector(reader, context, value, flags);
7611
7731
 
7612
7732
 
7733
+ value["sessionBindings"] = readRelocationSessionBindingVector(reader, context, value, flags);
7734
+
7735
+
7613
7736
 
7614
7737
 
7615
7738
  return value;
@@ -7638,6 +7761,9 @@ function* readIncrementalRelocationEnvelopeV1(reader: IncrementalInput, context:
7638
7761
  value["pendingTimerTicks"] = yield* readIncrementalRelocationPendingTimerTickVector(reader, context, value, flags);
7639
7762
 
7640
7763
 
7764
+ value["sessionBindings"] = yield* readIncrementalRelocationSessionBindingVector(reader, context, value, flags);
7765
+
7766
+
7641
7767
 
7642
7768
 
7643
7769
  return value;
@@ -7674,6 +7800,10 @@ function writeRelocationEnvelopeV1(input: RelocationEnvelopeV1, writer: Writer,
7674
7800
 
7675
7801
 
7676
7802
  writeRelocationPendingTimerTickVector(value["pendingTimerTicks"], writer, context, value, flags);
7803
+ if (value["sessionBindings"] === undefined) fail("sessionBindings required");
7804
+
7805
+
7806
+ writeRelocationSessionBindingVector(value["sessionBindings"], writer, context, value, flags);
7677
7807
  }
7678
7808
  export function decodeRelocationEnvelopeV1(bytes: Uint8Array, context: ServiceWireDecoderContext): RelocationEnvelopeV1 { const reader = new Reader(bytes); const value = readRelocationEnvelopeV1(reader, context, {}, 0); reader.done("relocation-envelope-v1"); return value; }
7679
7809
  export function encodeRelocationEnvelopeV1(value: RelocationEnvelopeV1, context: ServiceWireDecoderContext): Uint8Array { const writer = new Writer(); writeRelocationEnvelopeV1(value, writer, context, {}, 0); return writer.result(); }
@@ -1,4 +1,4 @@
1
- // <auto-generated> DO NOT EDIT. schema-sha256: 818fcd2f767793be8b5f626e5ac688807e671e546af2b11786e6fbaa02010ba5
1
+ // <auto-generated> DO NOT EDIT. schema-sha256: c9a343a64d205ce666d1e866df72538c11b3b52cf4bff41562e46d4aeaf20df6
2
2
  export interface ServiceWireRouteFence { readonly id: string; readonly generation: bigint; readonly targetNodeRid: Uint8Array; readonly targetNodeGeneration: bigint; readonly expectedAuthorityOwnerGeneration: bigint; readonly expectedOwnerLeaseGeneration: bigint; }
3
3
  export interface ApplicationPayloadEnvelopeV1 { readonly packetName: string; readonly contentType: string; readonly payload: Uint8Array; }
4
4
  export interface ActorJoin28 { readonly correlation: bigint; readonly actor: ServiceWireRouteFence; readonly entry: boolean; readonly targetSpot: ServiceWireRouteFence; readonly payload?: ApplicationPayloadEnvelopeV1; }
@@ -19,7 +19,7 @@ export interface ServiceWireRouteFence { readonly id: string; readonly generatio
19
19
  export function encodeActorJoin28(value: ActorJoin28): readonly Uint8Array[] { const out=[90,77,1,28,0]; if(value.correlation===0n) throw new RangeError("correlation"); u64(out,value.correlation); fence(out,value.actor); out.push(value.entry?1:0); fence(out,value.targetSpot); return value.payload===undefined?[Uint8Array.from(out)]:[Uint8Array.from(out),encodePayload(value.payload)]; }
20
20
  export function decodeActorJoin28(frames: readonly Uint8Array[]): ActorJoin28 { if(frames.length<1||frames.length>2)throw new RangeError("actorJoin frames");const bytes=frames[0]!; const at={value:0}; if(bytes.length<5 || bytes[at.value++]!==90 || bytes[at.value++]!==77 || bytes[at.value++]!==1 || bytes[at.value++]!==28 || bytes[at.value++]!==0) throw new RangeError("actorJoin header"); const correlation=read64(bytes,at); const actor=readFence(bytes,at); const entry=bytes[at.value++]; const targetSpot=readFence(bytes,at); if(correlation===0n || entry>1 || at.value!==bytes.length) throw new RangeError("actorJoin body"); const payload=frames.length===2?decodePayload(frames[1]!):undefined; return payload===undefined?{ correlation, actor, entry:entry===1, targetSpot }:{ correlation, actor, entry:entry===1, targetSpot,payload }; }
21
21
  export type RelocationObjectIdentity = { readonly objectKind:"actor";readonly actorId:string;readonly objectGeneration:bigint;readonly expectedAuthorityOwnerGeneration:bigint; }|{ readonly objectKind:"userSpot";readonly spotId:string;readonly objectGeneration:bigint;readonly expectedAuthorityOwnerGeneration:bigint; }|{ readonly objectKind:"instanceSpot";readonly instanceType:string;readonly spotId:string;readonly objectGeneration:bigint; };
22
- export interface RelocationEnvelopeV1 { readonly relocationHigh: bigint; readonly relocationLow: bigint; readonly object: RelocationObjectIdentity; readonly applicationVersion: bigint; readonly applicationStates: readonly { readonly participantId: bigint; readonly hasState: boolean; readonly payload: Uint8Array; }[]; readonly savedWork: readonly { readonly participantId: bigint; readonly order: bigint; readonly frozenRecord: Uint8Array; }[]; readonly timerRegistrations: readonly { readonly participantId: bigint; readonly name: string; readonly handlerType: string; readonly periodMilliseconds: bigint; readonly overrunPolicy: 1|2|3; readonly maxCatchUpTicks: bigint; readonly stopOnUnhandledException: boolean; readonly lastCompletedDeliveryIndex: bigint; readonly lastCompletedScheduledIndex: bigint; readonly nextScheduledAtUnixMilliseconds: bigint; }[]; readonly pendingTimerTicks: readonly { readonly participantId: bigint; readonly order: bigint; readonly timerName: string; readonly deliveryIndex: bigint; readonly scheduledIndex: bigint; readonly scheduledAtUnixMilliseconds: bigint; readonly skippedTicks: bigint; }[]; }
22
+ export interface RelocationEnvelopeV1 { readonly relocationHigh: bigint; readonly relocationLow: bigint; readonly object: RelocationObjectIdentity; readonly applicationVersion: bigint; readonly applicationStates: readonly { readonly participantId: bigint; readonly hasState: boolean; readonly payload: Uint8Array; }[]; readonly savedWork: readonly { readonly participantId: bigint; readonly order: bigint; readonly frozenRecord: Uint8Array; }[]; readonly timerRegistrations: readonly { readonly participantId: bigint; readonly name: string; readonly handlerType: string; readonly periodMilliseconds: bigint; readonly overrunPolicy: 1|2|3; readonly maxCatchUpTicks: bigint; readonly stopOnUnhandledException: boolean; readonly lastCompletedDeliveryIndex: bigint; readonly lastCompletedScheduledIndex: bigint; readonly nextScheduledAtUnixMilliseconds: bigint; }[]; readonly pendingTimerTicks: readonly { readonly participantId: bigint; readonly order: bigint; readonly timerName: string; readonly deliveryIndex: bigint; readonly scheduledIndex: bigint; readonly scheduledAtUnixMilliseconds: bigint; readonly skippedTicks: bigint; }[]; readonly sessionBindings: readonly {readonly participantId:bigint;readonly sessionOwnerNodeRid:Uint8Array;readonly sessionOwnerNodeGeneration:bigint;readonly sessionOwnerId:string;readonly sessionOwnerLeaseGeneration:bigint;readonly sessionRid:Uint8Array;readonly bindingGeneration:bigint;}[]; }
23
23
  export interface RelocationDataChunkV1 { readonly order:number;readonly data:Uint8Array; }
24
24
  export interface RelocationChunkEntryV1 { readonly order:number;readonly reference:string;readonly length:bigint;readonly checksumCrc32c:number; }
25
25
  export interface RelocationManifestV1 { readonly logicalFormatVersion:1;readonly totalLength:bigint;readonly totalChecksumCrc32c:number;readonly inventoryDigestSha256:Uint8Array;readonly chunks:readonly RelocationChunkEntryV1[]; }
@@ -51,8 +51,8 @@ function skipFrozenRecord(bytes:Uint8Array,at:{value:number}):void{const kind=re
51
51
  function compareUtf8(a:string,b:string):number{const x=text.encode(a),y=text.encode(b),n=Math.min(x.length,y.length);for(let i=0;i<n;i++)if(x[i]!==y[i])return x[i]!-y[i]!;return x.length-y.length;}
52
52
  function writeRelocationObject(out:number[],value:RelocationObjectIdentity):void{const kind=value.objectKind==="actor"?1:value.objectKind==="userSpot"?2:3;out.push(kind);body16(out,b=>{if(value.objectKind==="actor"){text8(b,value.actorId);if(value.objectGeneration===0n||value.expectedAuthorityOwnerGeneration===0n)throw new RangeError("object");u64(b,value.objectGeneration);u64(b,value.expectedAuthorityOwnerGeneration);}else if(value.objectKind==="userSpot"){text8(b,value.spotId);if(value.objectGeneration===0n||value.expectedAuthorityOwnerGeneration===0n)throw new RangeError("object");u64(b,value.objectGeneration);u64(b,value.expectedAuthorityOwnerGeneration);}else{text8(b,value.instanceType);text8(b,value.spotId);if(value.objectGeneration===0n)throw new RangeError("object");u64(b,value.objectGeneration);}});}
53
53
  function readRelocationObject(bytes:Uint8Array,at:{value:number}):RelocationObjectIdentity{const kind=read8(bytes,at),end=boundedEnd(bytes,at,read16(bytes,at),"relocation object");let value:RelocationObjectIdentity;if(kind===1)value={objectKind:"actor",actorId:readText8(bytes,at),objectGeneration:nonzero64(bytes,at,"object generation"),expectedAuthorityOwnerGeneration:nonzero64(bytes,at,"authority generation")};else if(kind===2)value={objectKind:"userSpot",spotId:readText8(bytes,at),objectGeneration:nonzero64(bytes,at,"object generation"),expectedAuthorityOwnerGeneration:nonzero64(bytes,at,"authority generation")};else if(kind===3)value={objectKind:"instanceSpot",instanceType:readText8(bytes,at),spotId:readText8(bytes,at),objectGeneration:nonzero64(bytes,at,"object generation")};else throw new RangeError("object kind");exactEnd(at,end,"relocation object");return value;}
54
- export function encodeRelocationEnvelopeV1(value:RelocationEnvelopeV1):Uint8Array{const out:number[]=[];if(value.relocationHigh===0n&&value.relocationLow===0n)throw new RangeError("relocation");u64(out,value.relocationHigh);u64(out,value.relocationLow);writeRelocationObject(out,value.object);if(value.applicationVersion<0n||value.applicationVersion>9223372036854775807n)throw new RangeError("application version");u64(out,value.applicationVersion);sorted(value.applicationStates,(a,b)=>a.participantId<b.participantId?-1:a.participantId>b.participantId?1:0,"applicationStates");if(value.applicationStates.length===0)throw new RangeError("applicationStates");u32(out,value.applicationStates.length);for(const s of value.applicationStates){if(s.participantId===0n)throw new RangeError("participant");u64(out,s.participantId);out.push(s.hasState?1:0);body64(out,b=>{if(s.hasState)bytes64(b,s.payload);else if(s.payload.length!==0)throw new RangeError("absent state payload");});}sorted(value.savedWork,(a,b)=>a.participantId===b.participantId?(a.order<b.order?-1:a.order>b.order?1:0):(a.participantId<b.participantId?-1:1),"savedWork");u32(out,value.savedWork.length);for(const w of value.savedWork){if(w.participantId===0n||w.order===0n)throw new RangeError("saved work");const at={value:0};skipFrozenRecord(w.frozenRecord,at);exactEnd(at,w.frozenRecord.length,"frozen record");u64(out,w.participantId);u64(out,w.order);appendBytes(out,w.frozenRecord);}sorted(value.timerRegistrations,(a,b)=>a.participantId===b.participantId?compareUtf8(a.name,b.name):a.participantId<b.participantId?-1:1,"timerRegistrations");u32(out,value.timerRegistrations.length);for(const t of value.timerRegistrations){if(t.participantId===0n||t.periodMilliseconds===0n||t.maxCatchUpTicks===0n||t.overrunPolicy<1||t.overrunPolicy>3)throw new RangeError("timer");u64(out,t.participantId);text8(out,t.name);text8(out,t.handlerType);u64(out,t.periodMilliseconds);out.push(t.overrunPolicy);u64(out,t.maxCatchUpTicks);out.push(t.stopOnUnhandledException?1:0);u64(out,t.lastCompletedDeliveryIndex);u64(out,t.lastCompletedScheduledIndex);u64(out,t.nextScheduledAtUnixMilliseconds);}sorted(value.pendingTimerTicks,(a,b)=>a.participantId===b.participantId?(a.order<b.order?-1:a.order>b.order?1:0):(a.participantId<b.participantId?-1:1),"pendingTimerTicks");u32(out,value.pendingTimerTicks.length);for(const p of value.pendingTimerTicks){if(p.participantId===0n||p.order===0n||p.deliveryIndex===0n||p.scheduledIndex===0n)throw new RangeError("pending timer");u64(out,p.participantId);u64(out,p.order);text8(out,p.timerName);u64(out,p.deliveryIndex);u64(out,p.scheduledIndex);u64(out,p.scheduledAtUnixMilliseconds);u64(out,p.skippedTicks);}if(out.length>274877906944)throw new RangeError("relocation logical bytes");return Uint8Array.from(out);}
55
- export function decodeRelocationEnvelopeV1(chunks:readonly Uint8Array[]):RelocationEnvelopeV1{const n=chunks.reduce((s,c)=>s+c.length,0);if(n>274877906944)throw new RangeError("relocation logical bytes");const bytes=new Uint8Array(n);let offset=0;for(const c of chunks){bytes.set(c,offset);offset+=c.length;}const at={value:0},relocationHigh=read64(bytes,at),relocationLow=read64(bytes,at);if(relocationHigh===0n&&relocationLow===0n)throw new RangeError("relocation");const object=readRelocationObject(bytes,at),applicationVersion=read64(bytes,at);if(applicationVersion>9223372036854775807n)throw new RangeError("application version");const applicationStates:RelocationEnvelopeV1["applicationStates"][number][]=[];const stateCount=read32(bytes,at);if(stateCount===0)throw new RangeError("applicationStates");for(let i=0,count=stateCount;i<count;i++){const participantId=nonzero64(bytes,at,"participant"),has=read8(bytes,at),end=boundedEnd(bytes,at,Number(read64(bytes,at)),"application state");if(has>1)throw new RangeError("application state");let payload=new Uint8Array();if(has===1)payload=take(bytes,at,Number(read64(bytes,at)),"state payload");exactEnd(at,end,"application state");applicationStates.push({participantId,hasState:has===1,payload});}const participants=new Set(applicationStates.map((s)=>s.participantId));const savedWork:RelocationEnvelopeV1["savedWork"][number][]=[];for(let i=0,count=read32(bytes,at);i<count;i++){const participantId=nonzero64(bytes,at,"participant");if(!participants.has(participantId))throw new RangeError("saved work participant");const order=nonzero64(bytes,at,"order"),start=at.value;skipFrozenRecord(bytes,at);savedWork.push({participantId,order,frozenRecord:bytes.slice(start,at.value)});}const timerRegistrations:RelocationEnvelopeV1["timerRegistrations"][number][]=[],registeredTimerNames=new Map<bigint,Set<string>>();for(let i=0,count=read32(bytes,at);i<count;i++){const participantId=nonzero64(bytes,at,"participant");if(!participants.has(participantId))throw new RangeError("timer participant");const name=readText8(bytes,at),handlerType=readText8(bytes,at),periodMilliseconds=nonzero64(bytes,at,"period"),overrunPolicy=read8(bytes,at);if(overrunPolicy<1||overrunPolicy>3)throw new RangeError("overrun policy");const maxCatchUpTicks=nonzero64(bytes,at,"catch-up"),stop=read8(bytes,at);if(stop>1)throw new RangeError("stop flag");let names=registeredTimerNames.get(participantId);if(names===undefined){names=new Set<string>();registeredTimerNames.set(participantId,names);}names.add(name);timerRegistrations.push({participantId,name,handlerType,periodMilliseconds,overrunPolicy:overrunPolicy as 1|2|3,maxCatchUpTicks,stopOnUnhandledException:stop===1,lastCompletedDeliveryIndex:read64(bytes,at),lastCompletedScheduledIndex:read64(bytes,at),nextScheduledAtUnixMilliseconds:read64(bytes,at)});}const pendingTimerTicks:RelocationEnvelopeV1["pendingTimerTicks"][number][]=[];for(let i=0,count=read32(bytes,at);i<count;i++){const participantId=nonzero64(bytes,at,"participant");if(!participants.has(participantId))throw new RangeError("pending timer participant");const order=nonzero64(bytes,at,"order"),timerName=readText8(bytes,at);if(registeredTimerNames.get(participantId)?.has(timerName)!==true)throw new RangeError("pending timer registration");pendingTimerTicks.push({participantId,order,timerName,deliveryIndex:nonzero64(bytes,at,"delivery"),scheduledIndex:nonzero64(bytes,at,"scheduled"),scheduledAtUnixMilliseconds:read64(bytes,at),skippedTicks:read64(bytes,at)});}exactEnd(at,bytes.length,"relocation envelope");sorted(applicationStates,(a,b)=>a.participantId<b.participantId?-1:a.participantId>b.participantId?1:0,"applicationStates");sorted(savedWork,(a,b)=>a.participantId===b.participantId?(a.order<b.order?-1:a.order>b.order?1:0):(a.participantId<b.participantId?-1:1),"savedWork");sorted(timerRegistrations,(a,b)=>a.participantId===b.participantId?compareUtf8(a.name,b.name):a.participantId<b.participantId?-1:1,"timerRegistrations");sorted(pendingTimerTicks,(a,b)=>a.participantId===b.participantId?(a.order<b.order?-1:a.order>b.order?1:0):(a.participantId<b.participantId?-1:1),"pendingTimerTicks");return{relocationHigh,relocationLow,object,applicationVersion,applicationStates,savedWork,timerRegistrations,pendingTimerTicks};}
54
+ export function encodeRelocationEnvelopeV1(value:RelocationEnvelopeV1):Uint8Array{const out:number[]=[];if(value.relocationHigh===0n&&value.relocationLow===0n)throw new RangeError("relocation");u64(out,value.relocationHigh);u64(out,value.relocationLow);writeRelocationObject(out,value.object);if(value.applicationVersion<0n||value.applicationVersion>9223372036854775807n)throw new RangeError("application version");u64(out,value.applicationVersion);sorted(value.applicationStates,(a,b)=>a.participantId<b.participantId?-1:a.participantId>b.participantId?1:0,"applicationStates");if(value.applicationStates.length===0)throw new RangeError("applicationStates");u32(out,value.applicationStates.length);for(const s of value.applicationStates){if(s.participantId===0n)throw new RangeError("participant");u64(out,s.participantId);out.push(s.hasState?1:0);body64(out,b=>{if(s.hasState)bytes64(b,s.payload);else if(s.payload.length!==0)throw new RangeError("absent state payload");});}sorted(value.savedWork,(a,b)=>a.participantId===b.participantId?(a.order<b.order?-1:a.order>b.order?1:0):(a.participantId<b.participantId?-1:1),"savedWork");u32(out,value.savedWork.length);for(const w of value.savedWork){if(w.participantId===0n||w.order===0n)throw new RangeError("saved work");const at={value:0};skipFrozenRecord(w.frozenRecord,at);exactEnd(at,w.frozenRecord.length,"frozen record");u64(out,w.participantId);u64(out,w.order);appendBytes(out,w.frozenRecord);}sorted(value.timerRegistrations,(a,b)=>a.participantId===b.participantId?compareUtf8(a.name,b.name):a.participantId<b.participantId?-1:1,"timerRegistrations");u32(out,value.timerRegistrations.length);for(const t of value.timerRegistrations){if(t.participantId===0n||t.periodMilliseconds===0n||t.maxCatchUpTicks===0n||t.overrunPolicy<1||t.overrunPolicy>3)throw new RangeError("timer");u64(out,t.participantId);text8(out,t.name);text8(out,t.handlerType);u64(out,t.periodMilliseconds);out.push(t.overrunPolicy);u64(out,t.maxCatchUpTicks);out.push(t.stopOnUnhandledException?1:0);u64(out,t.lastCompletedDeliveryIndex);u64(out,t.lastCompletedScheduledIndex);u64(out,t.nextScheduledAtUnixMilliseconds);}sorted(value.pendingTimerTicks,(a,b)=>a.participantId===b.participantId?(a.order<b.order?-1:a.order>b.order?1:0):(a.participantId<b.participantId?-1:1),"pendingTimerTicks");u32(out,value.pendingTimerTicks.length);for(const p of value.pendingTimerTicks){if(p.participantId===0n||p.order===0n||p.deliveryIndex===0n||p.scheduledIndex===0n)throw new RangeError("pending timer");u64(out,p.participantId);u64(out,p.order);text8(out,p.timerName);u64(out,p.deliveryIndex);u64(out,p.scheduledIndex);u64(out,p.scheduledAtUnixMilliseconds);u64(out,p.skippedTicks);}sorted(value.sessionBindings,(a,b)=>a.participantId<b.participantId?-1:a.participantId>b.participantId?1:0,"sessionBindings");if(value.sessionBindings.length>1024)throw new RangeError("bindings count");u32(out,value.sessionBindings.length);for(const b of value.sessionBindings){if(b.participantId===0n||b.sessionOwnerNodeGeneration===0n||b.sessionOwnerLeaseGeneration===0n||b.bindingGeneration===0n)throw new RangeError("binding");u64(out,b.participantId);rid(out,b.sessionOwnerNodeRid);u64(out,b.sessionOwnerNodeGeneration);text8(out,b.sessionOwnerId);u64(out,b.sessionOwnerLeaseGeneration);rid(out,b.sessionRid);u64(out,b.bindingGeneration);}if(out.length>274877906944)throw new RangeError("relocation logical bytes");return Uint8Array.from(out);}
55
+ export function decodeRelocationEnvelopeV1(chunks:readonly Uint8Array[]):RelocationEnvelopeV1{const n=chunks.reduce((s,c)=>s+c.length,0);if(n>274877906944)throw new RangeError("relocation logical bytes");const bytes=new Uint8Array(n);let offset=0;for(const c of chunks){bytes.set(c,offset);offset+=c.length;}const at={value:0},relocationHigh=read64(bytes,at),relocationLow=read64(bytes,at);if(relocationHigh===0n&&relocationLow===0n)throw new RangeError("relocation");const object=readRelocationObject(bytes,at),applicationVersion=read64(bytes,at);if(applicationVersion>9223372036854775807n)throw new RangeError("application version");const applicationStates:RelocationEnvelopeV1["applicationStates"][number][]=[];const stateCount=read32(bytes,at);if(stateCount===0)throw new RangeError("applicationStates");for(let i=0,count=stateCount;i<count;i++){const participantId=nonzero64(bytes,at,"participant"),has=read8(bytes,at),end=boundedEnd(bytes,at,Number(read64(bytes,at)),"application state");if(has>1)throw new RangeError("application state");let payload=new Uint8Array();if(has===1)payload=take(bytes,at,Number(read64(bytes,at)),"state payload");exactEnd(at,end,"application state");applicationStates.push({participantId,hasState:has===1,payload});}const participants=new Set(applicationStates.map((s)=>s.participantId));const savedWork:RelocationEnvelopeV1["savedWork"][number][]=[];for(let i=0,count=read32(bytes,at);i<count;i++){const participantId=nonzero64(bytes,at,"participant");if(!participants.has(participantId))throw new RangeError("saved work participant");const order=nonzero64(bytes,at,"order"),start=at.value;skipFrozenRecord(bytes,at);savedWork.push({participantId,order,frozenRecord:bytes.slice(start,at.value)});}const timerRegistrations:RelocationEnvelopeV1["timerRegistrations"][number][]=[],registeredTimerNames=new Map<bigint,Set<string>>();for(let i=0,count=read32(bytes,at);i<count;i++){const participantId=nonzero64(bytes,at,"participant");if(!participants.has(participantId))throw new RangeError("timer participant");const name=readText8(bytes,at),handlerType=readText8(bytes,at),periodMilliseconds=nonzero64(bytes,at,"period"),overrunPolicy=read8(bytes,at);if(overrunPolicy<1||overrunPolicy>3)throw new RangeError("overrun policy");const maxCatchUpTicks=nonzero64(bytes,at,"catch-up"),stop=read8(bytes,at);if(stop>1)throw new RangeError("stop flag");let names=registeredTimerNames.get(participantId);if(names===undefined){names=new Set<string>();registeredTimerNames.set(participantId,names);}names.add(name);timerRegistrations.push({participantId,name,handlerType,periodMilliseconds,overrunPolicy:overrunPolicy as 1|2|3,maxCatchUpTicks,stopOnUnhandledException:stop===1,lastCompletedDeliveryIndex:read64(bytes,at),lastCompletedScheduledIndex:read64(bytes,at),nextScheduledAtUnixMilliseconds:read64(bytes,at)});}const pendingTimerTicks:RelocationEnvelopeV1["pendingTimerTicks"][number][]=[];for(let i=0,count=read32(bytes,at);i<count;i++){const participantId=nonzero64(bytes,at,"participant");if(!participants.has(participantId))throw new RangeError("pending timer participant");const order=nonzero64(bytes,at,"order"),timerName=readText8(bytes,at);if(registeredTimerNames.get(participantId)?.has(timerName)!==true)throw new RangeError("pending timer registration");pendingTimerTicks.push({participantId,order,timerName,deliveryIndex:nonzero64(bytes,at,"delivery"),scheduledIndex:nonzero64(bytes,at,"scheduled"),scheduledAtUnixMilliseconds:read64(bytes,at),skippedTicks:read64(bytes,at)});}const sessionBindings:RelocationEnvelopeV1["sessionBindings"][number][]=[];const bindingCount=read32(bytes,at);if(bindingCount>1024)throw new RangeError("bindings count");for(let n=0;n<bindingCount;n++)sessionBindings.push({participantId:nonzero64(bytes,at,"participant"),sessionOwnerNodeRid:readRid(bytes,at),sessionOwnerNodeGeneration:nonzero64(bytes,at,"session node"),sessionOwnerId:readText8(bytes,at),sessionOwnerLeaseGeneration:nonzero64(bytes,at,"session lease"),sessionRid:readRid(bytes,at),bindingGeneration:nonzero64(bytes,at,"binding")});sorted(sessionBindings,(a,b)=>a.participantId<b.participantId?-1:a.participantId>b.participantId?1:0,"sessionBindings");exactEnd(at,bytes.length,"relocation envelope");sorted(applicationStates,(a,b)=>a.participantId<b.participantId?-1:a.participantId>b.participantId?1:0,"applicationStates");sorted(savedWork,(a,b)=>a.participantId===b.participantId?(a.order<b.order?-1:a.order>b.order?1:0):(a.participantId<b.participantId?-1:1),"savedWork");sorted(timerRegistrations,(a,b)=>a.participantId===b.participantId?compareUtf8(a.name,b.name):a.participantId<b.participantId?-1:1,"timerRegistrations");sorted(pendingTimerTicks,(a,b)=>a.participantId===b.participantId?(a.order<b.order?-1:a.order>b.order?1:0):(a.participantId<b.participantId?-1:1),"pendingTimerTicks");return{relocationHigh,relocationLow,object,applicationVersion,applicationStates,savedWork,timerRegistrations,pendingTimerTicks,sessionBindings};}
56
56
  function crc32c(bytes:Uint8Array):number{let crc=0xffffffff;for(const octet of bytes){crc^=octet;for(let bit=0;bit<8;bit++)crc=(crc>>>1)^((crc&1)!==0?0x82f63b78:0);}return(~crc)>>>0;}
57
57
  function encodeDurable(magic:readonly number[],body:readonly number[],maximum:number):Uint8Array{const out=[...magic,1,0,0];u32(out,body.length);appendBytes(out,body);if(out.length+4>maximum)throw new RangeError("durable format bytes");u32(out,crc32c(Uint8Array.from(out)));return Uint8Array.from(out);}
58
58
  function decodeDurable(bytes:Uint8Array,magic:readonly number[],maximum:number):Uint8Array{if(bytes.length>maximum||bytes.length<15||magic.some((v,i)=>bytes[i]!==v)||bytes[4]!==1||bytes[5]!==0||bytes[6]!==0)throw new RangeError("durable header");const at={value:7},length=read32(bytes,at),end=boundedEnd(bytes,at,length,"durable body");if(end+4!==bytes.length)throw new RangeError("durable length");const body=bytes.slice(at.value,end);at.value=end;const expected=read32(bytes,at);if(crc32c(bytes.slice(0,end))!==expected)throw new RangeError("durable checksum");return body;}
@@ -33,7 +33,14 @@ function objectKey(actorId: string, objectGeneration: bigint): string {
33
33
  }
34
34
 
35
35
  export type ZLinkFormalRemoteActorAdmissionState =
36
- 'provisional' | 'admitting' | 'admitted' | 'rejected' | 'committed' | 'aborted' | 'failed';
36
+ | 'provisional'
37
+ | 'admitting'
38
+ | 'admitted'
39
+ | 'restoring'
40
+ | 'rejected'
41
+ | 'committed'
42
+ | 'aborted'
43
+ | 'failed';
37
44
 
38
45
  export interface ZLinkFormalRemoteActorAdmission {
39
46
  readonly actorId: string;
@@ -78,7 +85,7 @@ export interface ZLinkFormalRemoteActorAdmissionRecord {
78
85
  }
79
86
 
80
87
  interface ZLinkFormalRemoteActorAdmissionEntry extends ZLinkFormalRemoteActorAdmissionRecord {
81
- readonly timer: ReturnType<typeof setTimeout>;
88
+ timer: ReturnType<typeof setTimeout>;
82
89
  readonly resolveResult: (result: ZLinkFormalRemoteActorAdmissionResult) => void;
83
90
  admission: ZLinkFormalRemoteActorAdmission;
84
91
  state: ZLinkFormalRemoteActorAdmissionState;
@@ -107,6 +114,35 @@ export class ZLinkFormalRemoteActorAdmissionRegistry {
107
114
  return this.admissions.get(transferId);
108
115
  }
109
116
 
117
+ /** PREPARE transfers prepared resources to the target attempt until its terminal. */
118
+ beginRestore(transferId: string): void {
119
+ const entry = this.admissions.get(transferId);
120
+ if (entry === undefined || (entry.state !== 'admitted' && entry.state !== 'restoring')) {
121
+ throw new Error(`Remote actor admission '${transferId}' is not ready to restore.`);
122
+ }
123
+ clearTimeout(entry.timer);
124
+ entry.state = 'restoring';
125
+ }
126
+
127
+ /** Retains successful commit replay; unsuccessful attempts release their resources now. */
128
+ finishRestore(transferId: string): void {
129
+ const entry = this.admissions.get(transferId);
130
+ if (entry === undefined) return;
131
+ if (entry.state === 'committed') {
132
+ clearTimeout(entry.timer);
133
+ entry.timer = this.scheduleExpiry(transferId);
134
+ } else {
135
+ this.abort(transferId);
136
+ this.delete(transferId);
137
+ }
138
+ }
139
+
140
+ private scheduleExpiry(transferId: string): ReturnType<typeof setTimeout> {
141
+ const timer = setTimeout(() => this.delete(transferId), ADMISSION_RETENTION_MS);
142
+ timer.unref();
143
+ return timer;
144
+ }
145
+
110
146
  begin(input: ZLinkFormalRemoteActorAdmission): {
111
147
  readonly record: ZLinkFormalRemoteActorAdmissionEntry;
112
148
  readonly created: boolean;
@@ -182,10 +218,7 @@ export class ZLinkFormalRemoteActorAdmissionRegistry {
182
218
  const resultTask = new Promise<ZLinkFormalRemoteActorAdmissionResult>((resolve) => {
183
219
  resolveResult = resolve;
184
220
  });
185
- const timer = setTimeout(() => {
186
- this.delete(input.transferId);
187
- }, ADMISSION_RETENTION_MS);
188
- timer.unref();
221
+ const timer = this.scheduleExpiry(input.transferId);
189
222
  const entry = {
190
223
  admission: input,
191
224
  state,
@@ -309,7 +342,7 @@ export class ZLinkFormalRemoteActorAdmissionRegistry {
309
342
  markCommitted(transferId: string, actor: ZLinkActor): void {
310
343
  const entry = this.admissions.get(transferId);
311
344
  if (entry === undefined) return;
312
- if (entry.state !== 'admitted' && entry.state !== 'committed') {
345
+ if (entry.state !== 'admitted' && entry.state !== 'restoring' && entry.state !== 'committed') {
313
346
  throw new Error(`Remote actor admission '${transferId}' is not ready to commit.`);
314
347
  }
315
348
  entry.state = 'committed';
@@ -320,7 +353,7 @@ export class ZLinkFormalRemoteActorAdmissionRegistry {
320
353
  const entry = this.admissions.get(transferId);
321
354
  if (
322
355
  entry === undefined ||
323
- entry.state !== 'admitted' ||
356
+ (entry.state !== 'admitted' && entry.state !== 'restoring') ||
324
357
  entry.result === undefined ||
325
358
  'error' in entry.result ||
326
359
  !entry.result.accepted
@@ -354,7 +387,7 @@ export class ZLinkFormalRemoteActorAdmissionRegistry {
354
387
  */
355
388
  delete(transferId: string): void {
356
389
  const pending = this.admissions.get(transferId);
357
- if (pending === undefined) return;
390
+ if (pending === undefined || pending.state === 'restoring') return;
358
391
  clearTimeout(pending.timer);
359
392
  this.admissions.delete(transferId);
360
393
  this.failParked(pending);
@@ -369,20 +402,7 @@ function sameAdmission(
369
402
  left: ZLinkFormalRemoteActorAdmission,
370
403
  right: ZLinkFormalRemoteActorAdmission
371
404
  ): boolean {
372
- return (
373
- left.actorId === right.actorId &&
374
- left.actorType === right.actorType &&
375
- String(left.spotId) === String(right.spotId) &&
376
- left.targetSpotGeneration === right.targetSpotGeneration &&
377
- left.expectedMembershipEpoch === right.expectedMembershipEpoch &&
378
- left.requestFingerprint === right.requestFingerprint &&
379
- sameOperationId(left.completionOperationId, right.completionOperationId) &&
380
- String(left.sourceSpotId ?? '') === String(right.sourceSpotId ?? '') &&
381
- String(left.sourceActorNodeRid ?? '') === String(right.sourceActorNodeRid ?? '') &&
382
- left.actorRef.actorId === right.actorRef.actorId &&
383
- String(left.actorRef.nodeRid) === String(right.actorRef.nodeRid) &&
384
- left.actorRef.objectGeneration === right.actorRef.objectGeneration
385
- );
405
+ return left.actorType === right.actorType && sameProvisionalAdmission(left, right);
386
406
  }
387
407
 
388
408
  function sameProvisionalAdmission(
@@ -215,6 +215,7 @@ export interface ZLinkSpotManagerOptions {
215
215
  operation: () => Promise<T>
216
216
  ) => Promise<T>;
217
217
  readonly actorCountProvider?: (spotId: RoutingId) => number;
218
+ readonly releaseActorMembers?: (meshName: string, spotId: RoutingId) => Promise<void>;
218
219
  readonly userSpotExecutionMode?: (
219
220
  meshName: string,
220
221
  spotType: Type<ZLinkSpot>
@@ -408,6 +409,7 @@ export class DefaultZLinkSpotManager {
408
409
  nodeRid: options.nodeRid,
409
410
  nodeRidProvider: options.nodeRidProvider,
410
411
  actorCountProvider: options.actorCountProvider,
412
+ releaseActorMembers: options.releaseActorMembers,
411
413
  userSpotExecutionMode: options.userSpotExecutionMode,
412
414
  userSpotRelocationCoordinationMode: options.userSpotRelocationCoordinationMode,
413
415
  channelClient: options.channelClient,
@@ -1620,6 +1622,7 @@ export class DefaultZLinkSpotManager {
1620
1622
  readonly workOptions?: import('../execution/serial-execution-queue').ZLinkSerialWorkOptions;
1621
1623
  readonly admissionTimeoutMs?: number;
1622
1624
  readonly signal?: AbortSignal;
1625
+ readonly onAdmitted?: () => void;
1623
1626
  }
1624
1627
  ): Promise<TReply> {
1625
1628
  return await this.routedSpotPackets.request<TReply>(spotId, packetName, request, context);
@@ -3075,7 +3078,7 @@ export class DefaultZLinkSpotManager {
3075
3078
  }
3076
3079
  const outcome = admission.result ?? (await admission.resultTask);
3077
3080
  if ('error' in outcome) throw outcome.error;
3078
- if (!outcome.accepted || admission.state !== 'admitted') {
3081
+ if (!outcome.accepted || (admission.state !== 'admitted' && admission.state !== 'restoring')) {
3079
3082
  throw new Error(`Actor Join relocation '${relocationId}' has no accepted admission.`);
3080
3083
  }
3081
3084
  const entrySpotId = this.options.entryNodeRidProvider?.() ?? this.options.entryNodeRid;
@@ -3135,6 +3138,11 @@ export class DefaultZLinkSpotManager {
3135
3138
  return true;
3136
3139
  }
3137
3140
 
3141
+ beginActorJoinRelocation(relocationId: string): () => void {
3142
+ this.formalRemoteActorAdmissions.beginRestore(relocationId);
3143
+ return () => this.formalRemoteActorAdmissions.finishRestore(relocationId);
3144
+ }
3145
+
3138
3146
  async restoreCanonicalActorJoinRecovery(
3139
3147
  recovery: CanonicalActorJoinRecovery,
3140
3148
  signal?: AbortSignal
@@ -3147,7 +3155,11 @@ export class DefaultZLinkSpotManager {
3147
3155
  );
3148
3156
  }
3149
3157
  const outcome = admission.result ?? (await admission.resultTask);
3150
- if ('error' in outcome || !outcome.accepted || admission.state !== 'admitted') {
3158
+ if (
3159
+ 'error' in outcome ||
3160
+ !outcome.accepted ||
3161
+ (admission.state !== 'admitted' && admission.state !== 'restoring')
3162
+ ) {
3151
3163
  throw new Error(
3152
3164
  `Actor Join recovery '${recovery.request.handoffId}' has no accepted admission.`
3153
3165
  );
@@ -101,6 +101,7 @@ export interface ZLinkSpotActivationLifecycleOptions {
101
101
  readonly nodeRid?: RoutingId;
102
102
  readonly nodeRidProvider?: (meshName: string) => RoutingId | undefined;
103
103
  readonly actorCountProvider?: (spotId: RoutingId) => number;
104
+ readonly releaseActorMembers?: (meshName: string, spotId: RoutingId) => Promise<void>;
104
105
  readonly userSpotExecutionMode?: (
105
106
  meshName: string,
106
107
  spotType: Type<ZLinkSpot>
@@ -215,7 +216,10 @@ export class ZLinkSpotActivationLifecycle {
215
216
  );
216
217
  const serialExecutor = new ZLinkSpotSerialExecutor(serial, executionMode, spotId);
217
218
  const actorHandlers = new ZLinkSpotActorHandlerRegistryRuntime();
218
- const handlers = new DefaultZLinkSpotHandlerRegistry(actorHandlers);
219
+ const handlers = new DefaultZLinkSpotHandlerRegistry(
220
+ actorHandlers,
221
+ this.options.providerResolver
222
+ );
219
223
  applySpotHandlerRegistrations(
220
224
  handlers,
221
225
  implementation as unknown as Type<ZLinkSpot>,
@@ -381,7 +385,10 @@ export class ZLinkSpotActivationLifecycle {
381
385
  spotId
382
386
  );
383
387
  const actorHandlers = new ZLinkSpotActorHandlerRegistryRuntime();
384
- const handlers = new DefaultZLinkSpotHandlerRegistry(actorHandlers);
388
+ const handlers = new DefaultZLinkSpotHandlerRegistry(
389
+ actorHandlers,
390
+ this.options.providerResolver
391
+ );
385
392
  const instanceHandlers = new DefaultZLinkInstanceSpotHandlerRegistry(handlers);
386
393
  applySpotHandlerRegistrations(handlers, implementation as unknown as Type<ZLinkSpot>, {
387
394
  packetHandlers: this.options.spotPacketHandlers
@@ -533,7 +540,10 @@ export class ZLinkSpotActivationLifecycle {
533
540
  );
534
541
  const serialExecutor = new ZLinkSpotSerialExecutor(serial, executionMode, spotId);
535
542
  const actorHandlers = new ZLinkSpotActorHandlerRegistryRuntime();
536
- const handlers = new DefaultZLinkSpotHandlerRegistry(actorHandlers);
543
+ const handlers = new DefaultZLinkSpotHandlerRegistry(
544
+ actorHandlers,
545
+ this.options.providerResolver
546
+ );
537
547
  applySpotHandlerRegistrations(handlers, spotType, {
538
548
  actorSendHandlers: this.options.spotActorSendHandlers,
539
549
  actorRequestHandlers: this.options.spotActorRequestHandlers,
@@ -1049,10 +1059,12 @@ export class ZLinkSpotActivationLifecycle {
1049
1059
  } catch (error) {
1050
1060
  // An OnClosing failure is diagnostic and cleanup continues. It is
1051
1061
  // returned so host shutdown can classify its teardown outcome.
1052
- this.options.closeErrorSink?.reportRuntimeTaskException(
1053
- `spot ${String(activation.spotId)} onClosing`,
1054
- error
1055
- );
1062
+ if (reason !== ZLinkSpotCloseReason.HostShutdown) {
1063
+ this.options.closeErrorSink?.reportRuntimeTaskException(
1064
+ `spot ${String(activation.spotId)} onClosing`,
1065
+ error
1066
+ );
1067
+ }
1056
1068
  closingFailure = error;
1057
1069
  }
1058
1070
  }
@@ -1093,7 +1105,12 @@ export class ZLinkSpotActivationLifecycle {
1093
1105
  }
1094
1106
  if (!state.nativeDisposed) {
1095
1107
  await cleanup(
1096
- () => activation.nativeSpot?.dispose(),
1108
+ async () => {
1109
+ if (reason === ZLinkSpotCloseReason.HostShutdown) {
1110
+ await this.options.releaseActorMembers?.(locationMeshName, activation.spotId);
1111
+ }
1112
+ await activation.nativeSpot?.dispose();
1113
+ },
1097
1114
  () => {
1098
1115
  state.nativeDisposed = true;
1099
1116
  }
@@ -1121,8 +1138,9 @@ export class ZLinkSpotActivationLifecycle {
1121
1138
  }
1122
1139
  );
1123
1140
  }
1124
- if (errors.length === 1) throw errors[0];
1125
- if (errors.length > 1) {
1141
+ if (errors.length > 0) {
1142
+ if (closingFailure !== undefined) errors.unshift(closingFailure);
1143
+ if (errors.length === 1) throw errors[0];
1126
1144
  throw new AggregateError(errors, `Spot '${activation.spotId}' cleanup failed.`);
1127
1145
  }
1128
1146
  return closingFailure;