@zlink-systems/framework 0.30.0 → 0.30.2

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 (456) 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/ZLinkEncodedPayload.d.ts +6 -0
  6. package/dist/contracts/Common/ZLinkEncodedPayload.js +18 -3
  7. package/dist/contracts/Common/ZLinkMessageMetadata.js +11 -5
  8. package/dist/contracts/Common/encoded-payload-storage.d.ts +1 -1
  9. package/dist/contracts/Common/encoded-payload-storage.js +5 -2
  10. package/dist/contracts/Configuration/Builders.d.ts +1 -1
  11. package/dist/contracts/Configuration/RegistrationBuilderPolicy.d.ts +2 -1
  12. package/dist/contracts/Configuration/RegistrationBuilderPolicy.js +5 -1
  13. package/dist/contracts/Configuration/RegistrationBuilders.js +2 -2
  14. package/dist/contracts/Configuration/RegistrationTypes.d.ts +1 -0
  15. package/dist/contracts/Dispatch/ZLinkDispatchOptions.d.ts +2 -2
  16. package/dist/contracts/Handlers/Attributes.d.ts +5 -13
  17. package/dist/contracts/Handlers/Attributes.js +7 -11
  18. package/dist/contracts/Handlers/JsonContract.d.ts +2 -46
  19. package/dist/contracts/Handlers/JsonContract.js +4 -153
  20. package/dist/contracts/Locations/Rows.d.ts +2 -0
  21. package/dist/contracts/Spots/Contracts.d.ts +6 -1
  22. package/dist/contracts/Spots/ZLinkSpot.d.ts +3 -3
  23. package/dist/nest-integration.d.ts +1 -1
  24. package/dist/nest-integration.js +2 -1
  25. package/dist/runtime/abort.d.ts +5 -0
  26. package/dist/runtime/abort.js +10 -0
  27. package/dist/runtime/actors/actor-authority-publication.js +3 -2
  28. package/dist/runtime/actors/actor-client.d.ts +1 -2
  29. package/dist/runtime/actors/actor-client.js +52 -57
  30. package/dist/runtime/actors/actor-context.d.ts +2 -0
  31. package/dist/runtime/actors/actor-context.js +46 -9
  32. package/dist/runtime/actors/actor-handoff.d.ts +8 -4
  33. package/dist/runtime/actors/actor-handoff.js +219 -92
  34. package/dist/runtime/actors/actor-join-relocation.d.ts +3 -0
  35. package/dist/runtime/actors/actor-local-native-join.js +13 -12
  36. package/dist/runtime/actors/actor-mailbox.js +27 -1
  37. package/dist/runtime/actors/actor-remote-joiner.js +3 -1
  38. package/dist/runtime/actors/actor-remote-wire.js +15 -0
  39. package/dist/runtime/actors/actor-reply.d.ts +4 -0
  40. package/dist/runtime/actors/actor-reply.js +29 -0
  41. package/dist/runtime/actors/actor-routed-join-transport.d.ts +6 -2
  42. package/dist/runtime/actors/actor-routed-json-request.d.ts +2 -0
  43. package/dist/runtime/actors/actor-runtime-contracts.d.ts +2 -0
  44. package/dist/runtime/actors/actor-runtime-state.js +2 -20
  45. package/dist/runtime/actors/actor-source-transfer.d.ts +1 -17
  46. package/dist/runtime/actors/index.d.ts +8 -3
  47. package/dist/runtime/actors/index.js +55 -27
  48. package/dist/runtime/actors/session-disconnected-wire.d.ts +8 -0
  49. package/dist/runtime/actors/session-disconnected-wire.js +48 -0
  50. package/dist/runtime/actors/spot-actor-dispatch.js +2 -2
  51. package/dist/runtime/admission.d.ts +9 -1
  52. package/dist/runtime/admission.js +56 -23
  53. package/dist/runtime/application-jobs/application-ingress-record-owner.d.ts +6 -8
  54. package/dist/runtime/application-jobs/application-ingress-record-owner.js +39 -22
  55. package/dist/runtime/application-jobs/application-job-queue-scope.d.ts +15 -1
  56. package/dist/runtime/application-jobs/application-job-queue-scope.js +61 -20
  57. package/dist/runtime/application-jobs/contracts.d.ts +12 -1
  58. package/dist/runtime/backend/contracts/index.d.ts +37 -12
  59. package/dist/runtime/backend/mesh-actor-session-node-adapter.js +2 -2
  60. package/dist/runtime/backend/mesh-completion-table.d.ts +9 -1
  61. package/dist/runtime/backend/mesh-completion-table.js +154 -49
  62. package/dist/runtime/backend/mesh-dispatch-pump.d.ts +28 -1
  63. package/dist/runtime/backend/mesh-dispatch-pump.js +208 -101
  64. package/dist/runtime/backend/node/node-backend-adapter-support.d.ts +2 -2
  65. package/dist/runtime/backend/node/node-backend-adapter-support.js +16 -9
  66. package/dist/runtime/backend/node/node-dealer-channel-client-transport.d.ts +1 -1
  67. package/dist/runtime/backend/node/node-dealer-channel-client-transport.js +5 -2
  68. package/dist/runtime/backend/node/node-raw-binding-port.js +124 -72
  69. package/dist/runtime/backend/node/node-raw-mesh-backend.d.ts +46 -13
  70. package/dist/runtime/backend/node/node-raw-mesh-backend.js +181 -164
  71. package/dist/runtime/backend/node/node-socket-backend-adapter.d.ts +1 -1
  72. package/dist/runtime/backend/node/node-socket-backend-adapter.js +11 -11
  73. package/dist/runtime/backend/raw-binding-port.d.ts +2 -2
  74. package/dist/runtime/backend/runtime-message.d.ts +1 -0
  75. package/dist/runtime/backend/runtime-message.js +5 -0
  76. package/dist/runtime/backend/runtime-values.d.ts +1 -0
  77. package/dist/runtime/backend/runtime-values.js +2 -1
  78. package/dist/runtime/channels/channel-clients.d.ts +2 -0
  79. package/dist/runtime/channels/channel-clients.js +75 -23
  80. package/dist/runtime/channels/channel-dispatch-pipeline.d.ts +25 -5
  81. package/dist/runtime/channels/channel-dispatch-pipeline.js +111 -56
  82. package/dist/runtime/channels/channel-dispatch-services.d.ts +1 -0
  83. package/dist/runtime/channels/channel-dispatch-services.js +45 -0
  84. package/dist/runtime/channels/channel-dispatchers.d.ts +4 -3
  85. package/dist/runtime/channels/channel-dispatchers.js +62 -54
  86. package/dist/runtime/channels/channel-envelope-inspection.d.ts +1 -2
  87. package/dist/runtime/channels/channel-envelope-inspection.js +1 -16
  88. package/dist/runtime/channels/channel-envelope.d.ts +2 -0
  89. package/dist/runtime/channels/channel-envelope.js +146 -28
  90. package/dist/runtime/channels/channel-outbound-operations.d.ts +2 -2
  91. package/dist/runtime/channels/channel-outbound-operations.js +8 -8
  92. package/dist/runtime/channels/channel-runtime-lifecycle.d.ts +4 -3
  93. package/dist/runtime/channels/channel-runtime-lifecycle.js +19 -24
  94. package/dist/runtime/channels/channel-runtime-manager.d.ts +9 -8
  95. package/dist/runtime/channels/channel-runtime-manager.js +16 -16
  96. package/dist/runtime/channels/channel-transports.d.ts +18 -16
  97. package/dist/runtime/channels/channel-transports.js +77 -58
  98. package/dist/runtime/channels/client-server-location-runtime.js +5 -4
  99. package/dist/runtime/channels/dispatch-error-reporter.d.ts +2 -1
  100. package/dist/runtime/channels/dispatch-error-reporter.js +2 -1
  101. package/dist/runtime/channels/fanout-location-runtime.d.ts +1 -1
  102. package/dist/runtime/channels/fanout-location-runtime.js +3 -3
  103. package/dist/runtime/channels/local-spot-route-transport.d.ts +1 -1
  104. package/dist/runtime/channels/local-spot-route-transport.js +2 -1
  105. package/dist/runtime/channels/router-socket-spot-route-transport.d.ts +2 -2
  106. package/dist/runtime/channels/router-socket-spot-route-transport.js +4 -4
  107. package/dist/runtime/channels/source-spot-router.d.ts +2 -2
  108. package/dist/runtime/channels/source-spot-router.js +4 -4
  109. package/dist/runtime/channels/spot-node-route-transport.d.ts +2 -2
  110. package/dist/runtime/channels/spot-node-route-transport.js +4 -4
  111. package/dist/runtime/channels/spot-route-bridge-transport.d.ts +2 -2
  112. package/dist/runtime/channels/spot-route-bridge-transport.js +4 -4
  113. package/dist/runtime/channels/spot-route-dispatch-strategy.d.ts +5 -4
  114. package/dist/runtime/channels/spot-route-dispatch-strategy.js +18 -18
  115. package/dist/runtime/diagnostics/flow-context.js +19 -7
  116. package/dist/runtime/diagnostics/index.js +4 -9
  117. package/dist/runtime/diagnostics/message-flow.d.ts +8 -0
  118. package/dist/runtime/diagnostics/message-flow.js +35 -5
  119. package/dist/runtime/diagnostics/runtime-metrics.d.ts +2 -2
  120. package/dist/runtime/diagnostics/runtime-metrics.js +10 -8
  121. package/dist/runtime/execution/index.d.ts +4 -2
  122. package/dist/runtime/execution/index.js +33 -10
  123. package/dist/runtime/execution/serial-execution-queue.d.ts +5 -0
  124. package/dist/runtime/execution/serial-execution-queue.js +22 -2
  125. package/dist/runtime/execution/state-lane.d.ts +2 -0
  126. package/dist/runtime/execution/state-lane.js +5 -0
  127. package/dist/runtime/foundation/actor-join-recovery-codec.js +2 -2
  128. package/dist/runtime/foundation/durable-service-request.d.ts +14 -0
  129. package/dist/runtime/foundation/durable-service-request.js +98 -0
  130. package/dist/runtime/foundation/operation-identity.d.ts +1 -0
  131. package/dist/runtime/foundation/operation-identity.js +5 -1
  132. package/dist/runtime/foundation/operation-registry.d.ts +25 -1
  133. package/dist/runtime/foundation/operation-registry.js +86 -18
  134. package/dist/runtime/foundation/raw-service-mesh-runtime.d.ts +61 -8
  135. package/dist/runtime/foundation/raw-service-mesh-runtime.js +486 -266
  136. package/dist/runtime/foundation/service-liveness-registry.d.ts +12 -1
  137. package/dist/runtime/foundation/service-liveness-registry.js +38 -0
  138. package/dist/runtime/foundation/service-mailbox.d.ts +7 -0
  139. package/dist/runtime/foundation/service-maintenance-runtime.js +1 -6
  140. package/dist/runtime/foundation/service-relocation-object-owner.d.ts +3 -3
  141. package/dist/runtime/foundation/service-relocation-object-owner.js +48 -34
  142. package/dist/runtime/foundation/service-relocation-runtime.d.ts +2 -0
  143. package/dist/runtime/foundation/service-relocation-runtime.js +20 -4
  144. package/dist/runtime/foundation/service-runtime-contracts.d.ts +10 -1
  145. package/dist/runtime/foundation/service-session-binding-ingress-port.d.ts +2 -1
  146. package/dist/runtime/foundation/service-stateful-registry.d.ts +5 -4
  147. package/dist/runtime/foundation/service-stateful-registry.js +24 -26
  148. package/dist/runtime/foundation/service-stateful-runtime.d.ts +75 -9
  149. package/dist/runtime/foundation/service-stateful-runtime.js +486 -218
  150. package/dist/runtime/foundation/service-stateful-wire-codec.d.ts +14 -6
  151. package/dist/runtime/foundation/service-stateful-wire-codec.js +48 -27
  152. package/dist/runtime/foundation/service-topology-registry.d.ts +12 -2
  153. package/dist/runtime/foundation/service-topology-registry.js +61 -27
  154. package/dist/runtime/foundation/service-wire-binary-primitives.d.ts +6 -1
  155. package/dist/runtime/foundation/service-wire-binary-primitives.js +27 -11
  156. package/dist/runtime/foundation/service-wire-constants.generated.d.ts +1 -0
  157. package/dist/runtime/foundation/service-wire-constants.generated.js +1 -0
  158. package/dist/runtime/foundation/service-wire-m6a-codec.d.ts +13 -3
  159. package/dist/runtime/foundation/service-wire-m6a-codec.js +189 -78
  160. package/dist/runtime/handlers/handler-instance-scope.d.ts +8 -0
  161. package/dist/runtime/handlers/handler-instance-scope.js +54 -11
  162. package/dist/runtime/host/actor-packet-relay.d.ts +6 -4
  163. package/dist/runtime/host/actor-packet-relay.js +59 -72
  164. package/dist/runtime/host/actor-placement-coordinator.js +25 -8
  165. package/dist/runtime/host/actor-runtime-options-factory.js +2 -2
  166. package/dist/runtime/host/actor-transfer-runtime.d.ts +7 -31
  167. package/dist/runtime/host/actor-transfer-runtime.js +85 -331
  168. package/dist/runtime/host/application-job-queue.d.ts +40 -7
  169. package/dist/runtime/host/application-job-queue.js +137 -42
  170. package/dist/runtime/host/entry-actor-runtime.d.ts +1 -0
  171. package/dist/runtime/host/entry-actor-runtime.js +3 -0
  172. package/dist/runtime/host/index.d.ts +12 -2
  173. package/dist/runtime/host/index.js +300 -202
  174. package/dist/runtime/host/location-runtime-owner.js +2 -6
  175. package/dist/runtime/host/mesh-router-resolver.d.ts +4 -0
  176. package/dist/runtime/host/mesh-router-resolver.js +14 -6
  177. package/dist/runtime/host/remote-bound-session-relay.d.ts +2 -4
  178. package/dist/runtime/host/remote-bound-session-relay.js +73 -208
  179. package/dist/runtime/host/route-mesh-runtime.d.ts +2 -2
  180. package/dist/runtime/host/route-mesh-runtime.js +6 -4
  181. package/dist/runtime/host/runtime-shutdown.d.ts +1 -0
  182. package/dist/runtime/host/runtime-shutdown.js +3 -2
  183. package/dist/runtime/host/service-relocation-control.d.ts +1 -0
  184. package/dist/runtime/host/service-relocation-control.js +10 -4
  185. package/dist/runtime/host/service-relocation-host-runtime.d.ts +22 -14
  186. package/dist/runtime/host/service-relocation-host-runtime.js +754 -599
  187. package/dist/runtime/host/spot-address-transport.js +3 -2
  188. package/dist/runtime/host/spot-runtime-options-factory.js +16 -7
  189. package/dist/runtime/host/user-spot-creation-coordinator.js +33 -84
  190. package/dist/runtime/locations/actor-location-claims.d.ts +2 -2
  191. package/dist/runtime/locations/actor-location-claims.js +34 -19
  192. package/dist/runtime/locations/auto-connect-loop.d.ts +2 -0
  193. package/dist/runtime/locations/auto-connect-loop.js +22 -14
  194. package/dist/runtime/locations/auto-connect-reconciler.js +0 -6
  195. package/dist/runtime/locations/auto-connect-types.d.ts +0 -1
  196. package/dist/runtime/locations/descriptor-publication.d.ts +4 -0
  197. package/dist/runtime/locations/descriptor-publication.js +11 -0
  198. package/dist/runtime/locations/domain-store-contract.d.ts +1 -0
  199. package/dist/runtime/locations/in-memory-authority-store.d.ts +7 -1
  200. package/dist/runtime/locations/in-memory-authority-store.js +56 -19
  201. package/dist/runtime/locations/in-memory-location-store.js +1 -10
  202. package/dist/runtime/locations/index.d.ts +1 -0
  203. package/dist/runtime/locations/index.js +1 -0
  204. package/dist/runtime/locations/lease-tracker.js +1 -6
  205. package/dist/runtime/locations/lifecycle.d.ts +1 -2
  206. package/dist/runtime/locations/lifecycle.js +2 -5
  207. package/dist/runtime/locations/location-store-repository.d.ts +51 -1
  208. package/dist/runtime/locations/location-store-repository.js +363 -139
  209. package/dist/runtime/locations/relocation-blob.d.ts +18 -1
  210. package/dist/runtime/locations/relocation-blob.js +52 -1
  211. package/dist/runtime/locations/request-source-resolver.d.ts +37 -0
  212. package/dist/runtime/locations/request-source-resolver.js +80 -0
  213. package/dist/runtime/locations/resolvers.js +1 -1
  214. package/dist/runtime/locations/runtime.d.ts +7 -3
  215. package/dist/runtime/locations/runtime.js +61 -53
  216. package/dist/runtime/messaging/framework-json-v1.d.ts +4 -6
  217. package/dist/runtime/messaging/framework-json-v1.js +38 -294
  218. package/dist/runtime/messaging/packet-name.d.ts +1 -1
  219. package/dist/runtime/messaging/packet-name.js +8 -24
  220. package/dist/runtime/messaging/payload-codec.d.ts +7 -1
  221. package/dist/runtime/messaging/payload-codec.js +7 -6
  222. package/dist/runtime/messaging/request-result.d.ts +2 -0
  223. package/dist/runtime/messaging/request-result.js +57 -0
  224. package/dist/runtime/messaging/submission-result.d.ts +1 -0
  225. package/dist/runtime/messaging/submission-result.js +5 -2
  226. package/dist/runtime/protocol/service_wire_codec.generated.d.ts +34 -1
  227. package/dist/runtime/protocol/service_wire_codec.generated.js +229 -0
  228. package/dist/runtime/protocol/service_wire_pilot_codec.generated.d.ts +16 -1
  229. package/dist/runtime/protocol/service_wire_pilot_codec.generated.js +37 -8
  230. package/dist/runtime/spots/formal-remote-actor-admission-registry.d.ts +7 -2
  231. package/dist/runtime/spots/formal-remote-actor-admission-registry.js +36 -21
  232. package/dist/runtime/spots/index.d.ts +21 -11
  233. package/dist/runtime/spots/index.js +243 -178
  234. package/dist/runtime/spots/spot-activation-registry.d.ts +4 -2
  235. package/dist/runtime/spots/spot-activation-registry.js +21 -11
  236. package/dist/runtime/spots/spot-activation-state.d.ts +1 -1
  237. package/dist/runtime/spots/spot-activation-state.js +7 -7
  238. package/dist/runtime/spots/spot-activation.d.ts +7 -3
  239. package/dist/runtime/spots/spot-activation.js +140 -52
  240. package/dist/runtime/spots/spot-actor-admission-coordinator.d.ts +1 -0
  241. package/dist/runtime/spots/spot-actor-admission-coordinator.js +13 -22
  242. package/dist/runtime/spots/spot-actor-membership.d.ts +0 -1
  243. package/dist/runtime/spots/spot-actor-membership.js +0 -8
  244. package/dist/runtime/spots/spot-actor-packet-dispatch.js +33 -8
  245. package/dist/runtime/spots/spot-actor-packet-drain.js +5 -33
  246. package/dist/runtime/spots/spot-entry-activation.d.ts +2 -0
  247. package/dist/runtime/spots/spot-entry-activation.js +20 -11
  248. package/dist/runtime/spots/spot-handler-registry.d.ts +7 -4
  249. package/dist/runtime/spots/spot-handler-registry.js +24 -10
  250. package/dist/runtime/spots/spot-manager-internal-contracts.d.ts +2 -2
  251. package/dist/runtime/spots/spot-manager-public.js +2 -2
  252. package/dist/runtime/spots/spot-node-autoconnect.d.ts +2 -1
  253. package/dist/runtime/spots/spot-node-autoconnect.js +22 -42
  254. package/dist/runtime/spots/spot-node-runtime-manager.d.ts +19 -2
  255. package/dist/runtime/spots/spot-node-runtime-manager.js +115 -50
  256. package/dist/runtime/spots/spot-outbound.d.ts +3 -0
  257. package/dist/runtime/spots/spot-outbound.js +27 -18
  258. package/dist/runtime/spots/spot-remote-codec.js +5 -1
  259. package/dist/runtime/spots/spot-routed-spot-packet-dispatch.d.ts +1 -0
  260. package/dist/runtime/spots/spot-routed-spot-packet-dispatch.js +1 -1
  261. package/dist/runtime/spots/spot-runtime-ports.d.ts +1 -1
  262. package/dist/runtime/spots/spot-serial-executor.d.ts +10 -0
  263. package/dist/runtime/spots/spot-serial-executor.js +61 -8
  264. package/dist/runtime/spots/spot-serial-turn-executor.js +19 -2
  265. package/dist/runtime/spots/spot-subscription-dispatch.js +1 -4
  266. package/dist/runtime/spots/spot-timer.d.ts +57 -5
  267. package/dist/runtime/spots/spot-timer.js +288 -103
  268. package/dist/runtime/streams/actor-session-binding-registry.d.ts +42 -11
  269. package/dist/runtime/streams/actor-session-binding-registry.js +165 -48
  270. package/dist/runtime/streams/actor-session-binding-runtime-owner.d.ts +8 -4
  271. package/dist/runtime/streams/bound-actor-relay-sender.d.ts +2 -1
  272. package/dist/runtime/streams/bound-actor-relay-sender.js +15 -8
  273. package/dist/runtime/streams/bound-session-service.d.ts +1 -1
  274. package/dist/runtime/streams/bound-session-service.js +6 -11
  275. package/dist/runtime/streams/index.d.ts +3 -2
  276. package/dist/runtime/streams/index.js +6 -4
  277. package/dist/runtime/streams/managed-stream.js +3 -2
  278. package/dist/runtime/streams/native-fallback-bound-session.js +8 -73
  279. package/dist/runtime/streams/session-actor-coordinator.d.ts +2 -8
  280. package/dist/runtime/streams/session-actor-coordinator.js +15 -32
  281. package/dist/runtime/streams/stream-binding-runtime-ports.d.ts +3 -10
  282. package/dist/runtime/streams/stream-session-runtime.d.ts +1 -1
  283. package/dist/runtime/streams/stream-session-runtime.js +14 -31
  284. package/dist/runtime/workers/index.js +1 -1
  285. package/package.json +3 -3
  286. package/src/contracts/Actors/ZLinkActorClient.ts +2 -1
  287. package/src/contracts/Channels/Calls.ts +2 -1
  288. package/src/contracts/Common/ZLinkEncodedPayload.ts +24 -4
  289. package/src/contracts/Common/ZLinkMessageMetadata.ts +13 -8
  290. package/src/contracts/Common/encoded-payload-storage.ts +6 -3
  291. package/src/contracts/Configuration/Builders.ts +4 -1
  292. package/src/contracts/Configuration/RegistrationBuilderPolicy.ts +7 -2
  293. package/src/contracts/Configuration/RegistrationBuilders.ts +6 -2
  294. package/src/contracts/Configuration/RegistrationTypes.ts +1 -0
  295. package/src/contracts/Dispatch/ZLinkDispatchOptions.ts +2 -1
  296. package/src/contracts/Handlers/Attributes.ts +14 -21
  297. package/src/contracts/Handlers/JsonContract.ts +8 -216
  298. package/src/contracts/Locations/Rows.ts +2 -0
  299. package/src/contracts/Spots/Contracts.ts +10 -1
  300. package/src/contracts/Spots/ZLinkSpot.ts +3 -3
  301. package/src/nest-integration.ts +1 -0
  302. package/src/runtime/abort.ts +12 -0
  303. package/src/runtime/actors/actor-authority-publication.ts +3 -2
  304. package/src/runtime/actors/actor-client.ts +100 -85
  305. package/src/runtime/actors/actor-context.ts +49 -9
  306. package/src/runtime/actors/actor-handoff.ts +291 -110
  307. package/src/runtime/actors/actor-join-relocation.ts +3 -0
  308. package/src/runtime/actors/actor-local-native-join.ts +21 -26
  309. package/src/runtime/actors/actor-mailbox.ts +40 -2
  310. package/src/runtime/actors/actor-remote-joiner.ts +6 -1
  311. package/src/runtime/actors/actor-remote-wire.ts +17 -0
  312. package/src/runtime/actors/actor-reply.ts +42 -0
  313. package/src/runtime/actors/actor-routed-join-transport.ts +14 -4
  314. package/src/runtime/actors/actor-routed-json-request.ts +10 -2
  315. package/src/runtime/actors/actor-runtime-contracts.ts +2 -0
  316. package/src/runtime/actors/actor-runtime-state.ts +2 -20
  317. package/src/runtime/actors/actor-source-transfer.ts +1 -34
  318. package/src/runtime/actors/index.ts +60 -32
  319. package/src/runtime/actors/session-disconnected-wire.ts +66 -0
  320. package/src/runtime/actors/spot-actor-dispatch.ts +4 -2
  321. package/src/runtime/admission.ts +69 -21
  322. package/src/runtime/application-jobs/application-ingress-record-owner.ts +41 -25
  323. package/src/runtime/application-jobs/application-job-queue-scope.ts +83 -22
  324. package/src/runtime/application-jobs/contracts.ts +16 -1
  325. package/src/runtime/backend/contracts/index.ts +92 -18
  326. package/src/runtime/backend/mesh-actor-session-node-adapter.ts +5 -3
  327. package/src/runtime/backend/mesh-completion-table.ts +160 -57
  328. package/src/runtime/backend/mesh-dispatch-pump.ts +237 -108
  329. package/src/runtime/backend/node/node-backend-adapter-support.ts +17 -8
  330. package/src/runtime/backend/node/node-dealer-channel-client-transport.ts +12 -2
  331. package/src/runtime/backend/node/node-raw-binding-port.ts +148 -85
  332. package/src/runtime/backend/node/node-raw-mesh-backend.ts +315 -201
  333. package/src/runtime/backend/node/node-socket-backend-adapter.ts +26 -11
  334. package/src/runtime/backend/raw-binding-port.ts +7 -2
  335. package/src/runtime/backend/runtime-message.ts +6 -0
  336. package/src/runtime/backend/runtime-values.ts +1 -0
  337. package/src/runtime/channels/channel-clients.ts +132 -58
  338. package/src/runtime/channels/channel-dispatch-pipeline.ts +198 -114
  339. package/src/runtime/channels/channel-dispatch-services.ts +69 -1
  340. package/src/runtime/channels/channel-dispatchers.ts +136 -90
  341. package/src/runtime/channels/channel-envelope-inspection.ts +2 -16
  342. package/src/runtime/channels/channel-envelope.ts +225 -31
  343. package/src/runtime/channels/channel-outbound-operations.ts +22 -8
  344. package/src/runtime/channels/channel-runtime-lifecycle.ts +13 -13
  345. package/src/runtime/channels/channel-runtime-manager.ts +41 -17
  346. package/src/runtime/channels/channel-transports.ts +171 -112
  347. package/src/runtime/channels/client-server-location-runtime.ts +11 -10
  348. package/src/runtime/channels/dispatch-error-reporter.ts +4 -2
  349. package/src/runtime/channels/fanout-location-runtime.ts +17 -9
  350. package/src/runtime/channels/local-spot-route-transport.ts +3 -1
  351. package/src/runtime/channels/router-socket-spot-route-transport.ts +13 -4
  352. package/src/runtime/channels/source-spot-router.ts +8 -4
  353. package/src/runtime/channels/spot-node-route-transport.ts +8 -4
  354. package/src/runtime/channels/spot-route-bridge-transport.ts +6 -4
  355. package/src/runtime/channels/spot-route-dispatch-strategy.ts +47 -18
  356. package/src/runtime/diagnostics/flow-context.ts +20 -7
  357. package/src/runtime/diagnostics/index.ts +1 -7
  358. package/src/runtime/diagnostics/message-flow.ts +47 -9
  359. package/src/runtime/diagnostics/runtime-metrics.ts +12 -10
  360. package/src/runtime/execution/index.ts +40 -14
  361. package/src/runtime/execution/serial-execution-queue.ts +33 -4
  362. package/src/runtime/execution/state-lane.ts +7 -0
  363. package/src/runtime/foundation/actor-join-recovery-codec.ts +2 -2
  364. package/src/runtime/foundation/durable-service-request.ts +137 -0
  365. package/src/runtime/foundation/operation-identity.ts +5 -1
  366. package/src/runtime/foundation/operation-registry.ts +98 -20
  367. package/src/runtime/foundation/raw-service-mesh-runtime.ts +704 -336
  368. package/src/runtime/foundation/service-liveness-registry.ts +39 -0
  369. package/src/runtime/foundation/service-mailbox.ts +8 -0
  370. package/src/runtime/foundation/service-maintenance-runtime.ts +1 -8
  371. package/src/runtime/foundation/service-relocation-object-owner.ts +55 -36
  372. package/src/runtime/foundation/service-relocation-runtime.ts +25 -4
  373. package/src/runtime/foundation/service-runtime-contracts.ts +19 -2
  374. package/src/runtime/foundation/service-session-binding-ingress-port.ts +2 -1
  375. package/src/runtime/foundation/service-stateful-registry.ts +38 -35
  376. package/src/runtime/foundation/service-stateful-runtime.ts +732 -275
  377. package/src/runtime/foundation/service-stateful-wire-codec.ts +49 -16
  378. package/src/runtime/foundation/service-topology-registry.ts +91 -36
  379. package/src/runtime/foundation/service-wire-binary-primitives.ts +35 -12
  380. package/src/runtime/foundation/service-wire-constants.generated.ts +1 -0
  381. package/src/runtime/foundation/service-wire-m6a-codec.ts +231 -76
  382. package/src/runtime/handlers/handler-instance-scope.ts +67 -16
  383. package/src/runtime/host/actor-packet-relay.ts +113 -94
  384. package/src/runtime/host/actor-placement-coordinator.ts +31 -8
  385. package/src/runtime/host/actor-runtime-options-factory.ts +13 -2
  386. package/src/runtime/host/actor-transfer-runtime.ts +104 -430
  387. package/src/runtime/host/application-job-queue.ts +160 -41
  388. package/src/runtime/host/entry-actor-runtime.ts +4 -0
  389. package/src/runtime/host/index.ts +473 -271
  390. package/src/runtime/host/location-runtime-owner.ts +2 -6
  391. package/src/runtime/host/mesh-router-resolver.ts +13 -5
  392. package/src/runtime/host/remote-bound-session-relay.ts +88 -271
  393. package/src/runtime/host/route-mesh-runtime.ts +12 -6
  394. package/src/runtime/host/runtime-shutdown.ts +15 -4
  395. package/src/runtime/host/service-relocation-control.ts +11 -5
  396. package/src/runtime/host/service-relocation-host-runtime.ts +1092 -759
  397. package/src/runtime/host/spot-address-transport.ts +4 -2
  398. package/src/runtime/host/spot-runtime-options-factory.ts +20 -7
  399. package/src/runtime/host/user-spot-creation-coordinator.ts +41 -100
  400. package/src/runtime/locations/actor-location-claims.ts +52 -30
  401. package/src/runtime/locations/auto-connect-loop.ts +22 -14
  402. package/src/runtime/locations/auto-connect-reconciler.ts +0 -6
  403. package/src/runtime/locations/auto-connect-types.ts +0 -1
  404. package/src/runtime/locations/descriptor-publication.ts +7 -0
  405. package/src/runtime/locations/domain-store-contract.ts +5 -0
  406. package/src/runtime/locations/in-memory-authority-store.ts +85 -23
  407. package/src/runtime/locations/in-memory-location-store.ts +1 -12
  408. package/src/runtime/locations/index.ts +1 -0
  409. package/src/runtime/locations/lease-tracker.ts +2 -9
  410. package/src/runtime/locations/lifecycle.ts +8 -26
  411. package/src/runtime/locations/location-store-repository.ts +628 -152
  412. package/src/runtime/locations/relocation-blob.ts +75 -1
  413. package/src/runtime/locations/request-source-resolver.ts +138 -0
  414. package/src/runtime/locations/resolvers.ts +2 -2
  415. package/src/runtime/locations/runtime.ts +98 -64
  416. package/src/runtime/messaging/framework-json-v1.ts +5 -325
  417. package/src/runtime/messaging/packet-name.ts +5 -25
  418. package/src/runtime/messaging/payload-codec.ts +8 -11
  419. package/src/runtime/messaging/request-result.ts +62 -0
  420. package/src/runtime/messaging/submission-result.ts +5 -1
  421. package/src/runtime/protocol/service_wire_codec.generated.ts +218 -5
  422. package/src/runtime/protocol/service_wire_pilot_codec.generated.ts +16 -13
  423. package/src/runtime/spots/formal-remote-actor-admission-registry.ts +46 -25
  424. package/src/runtime/spots/index.ts +389 -283
  425. package/src/runtime/spots/spot-activation-registry.ts +25 -13
  426. package/src/runtime/spots/spot-activation-state.ts +12 -19
  427. package/src/runtime/spots/spot-activation.ts +198 -96
  428. package/src/runtime/spots/spot-actor-admission-coordinator.ts +25 -55
  429. package/src/runtime/spots/spot-actor-membership.ts +0 -15
  430. package/src/runtime/spots/spot-actor-packet-dispatch.ts +56 -11
  431. package/src/runtime/spots/spot-actor-packet-drain.ts +9 -52
  432. package/src/runtime/spots/spot-entry-activation.ts +33 -21
  433. package/src/runtime/spots/spot-handler-registry.ts +56 -12
  434. package/src/runtime/spots/spot-manager-internal-contracts.ts +2 -2
  435. package/src/runtime/spots/spot-manager-public.ts +2 -2
  436. package/src/runtime/spots/spot-node-autoconnect.ts +28 -47
  437. package/src/runtime/spots/spot-node-runtime-manager.ts +197 -67
  438. package/src/runtime/spots/spot-outbound.ts +39 -19
  439. package/src/runtime/spots/spot-remote-codec.ts +9 -2
  440. package/src/runtime/spots/spot-routed-spot-packet-dispatch.ts +2 -1
  441. package/src/runtime/spots/spot-runtime-ports.ts +1 -1
  442. package/src/runtime/spots/spot-serial-executor.ts +97 -25
  443. package/src/runtime/spots/spot-serial-turn-executor.ts +22 -3
  444. package/src/runtime/spots/spot-subscription-dispatch.ts +1 -4
  445. package/src/runtime/spots/spot-timer.ts +418 -158
  446. package/src/runtime/streams/actor-session-binding-registry.ts +236 -64
  447. package/src/runtime/streams/actor-session-binding-runtime-owner.ts +16 -8
  448. package/src/runtime/streams/bound-actor-relay-sender.ts +23 -9
  449. package/src/runtime/streams/bound-session-service.ts +7 -10
  450. package/src/runtime/streams/index.ts +12 -6
  451. package/src/runtime/streams/managed-stream.ts +4 -2
  452. package/src/runtime/streams/native-fallback-bound-session.ts +14 -103
  453. package/src/runtime/streams/session-actor-coordinator.ts +39 -88
  454. package/src/runtime/streams/stream-binding-runtime-ports.ts +3 -9
  455. package/src/runtime/streams/stream-session-runtime.ts +13 -34
  456. package/src/runtime/workers/index.ts +1 -1
@@ -18,14 +18,18 @@ import type {
18
18
  import { ZLinkTimerOverrunPolicy } from '../../contracts';
19
19
  import { validateTimerRegistration } from '../../contracts/Configuration/TimerRegistrationValidator';
20
20
  import { throwIfAborted } from '../abort';
21
+ import {
22
+ ZLinkFrameworkInternalErrorKind,
23
+ createInternalFrameworkException
24
+ } from '../framework-errors-internal';
21
25
  import { ZLinkSpotSerialTurnExecutor } from './spot-serial-turn-executor';
22
- import { resolveLifecycleHandler } from '../handlers/handler-instance-scope';
26
+ import {
27
+ prepareHandlerInstance,
28
+ resolveLifecycleHandler
29
+ } from '../handlers/handler-instance-scope';
23
30
  import { createInboundFlow, runWithFlow } from '../diagnostics/flow-context';
24
31
  import type { ZLinkExecutionBarrier } from '../execution';
25
- import { ZLinkStateLane } from '../execution/state-lane';
26
- import { AsyncResource } from 'node:async_hooks';
27
-
28
- const detachedTimerStateLaneResource = new AsyncResource('zlink:spot-timer');
32
+ import { startOutsideStateLane, ZLinkStateLane } from '../execution/state-lane';
29
33
 
30
34
  export interface ZLinkTimerClock {
31
35
  now(): number;
@@ -51,7 +55,7 @@ interface ZLinkTimerFinalization {
51
55
 
52
56
  interface ZLinkTimerFinalizationStart {
53
57
  readonly timeout: unknown;
54
- readonly running: Promise<void>;
58
+ readonly running: Promise<void> | undefined;
55
59
  }
56
60
 
57
61
  type ZLinkTimerFailureReporter = (
@@ -75,6 +79,13 @@ export interface ZLinkTimerRelocationState {
75
79
  readonly pendingTicks: readonly ZLinkTimerRelocationPendingTick[];
76
80
  }
77
81
 
82
+ export interface ZLinkManagedTimerStart {
83
+ /** Created paused; the owner starts it with `resume()`. */
84
+ readonly paused?: boolean;
85
+ /** Relocated logical schedule the timer continues from. */
86
+ readonly cursor?: ZLinkTimerRelocationState;
87
+ }
88
+
78
89
  export interface ZLinkTimerRelocationPendingTick {
79
90
  readonly deliveryIndex: bigint;
80
91
  readonly scheduledIndex: bigint;
@@ -82,18 +93,56 @@ export interface ZLinkTimerRelocationPendingTick {
82
93
  readonly skippedTicks: bigint;
83
94
  }
84
95
 
96
+ interface ZLinkTimerBinding {
97
+ readonly handler: ZLinkSpotTimerHandler<ZLinkTimerOwnerSpot>;
98
+ readonly spot: ZLinkTimerOwnerSpot;
99
+ readonly executionSerial?: ZLinkSpotSerialTurnExecutor;
100
+ readonly reportFailure?: ZLinkTimerFailureReporter;
101
+ }
102
+
103
+ interface ZLinkTimerBindingSlot {
104
+ binding: ZLinkTimerBinding | undefined;
105
+ }
106
+
107
+ interface ZLinkTimerEntry {
108
+ readonly generation: bigint;
109
+ readonly handlerType: string;
110
+ readonly timer: ZLinkManagedTimer;
111
+ readonly handle: ZLinkRegisteredTimer;
112
+ /** Restored from a relocation payload; Configure and OnInitialize reattach it. */
113
+ readonly restored: boolean;
114
+ readonly slot: ZLinkTimerBindingSlot;
115
+ }
116
+
117
+ type ZLinkTimerAddPreparation =
118
+ | { readonly kind: 'reattached'; readonly handle: ZLinkTimer }
119
+ | {
120
+ readonly kind: 'registered';
121
+ readonly previous: ZLinkTimerEntry | undefined;
122
+ readonly generation: bigint;
123
+ };
124
+
85
125
  export class ZLinkSpotTimerRegistry {
86
126
  private readonly lane = new ZLinkStateLane();
87
- private readonly timers = new Map<
88
- string,
89
- {
90
- readonly generation: bigint;
91
- readonly handlerType: string;
92
- readonly timer: ZLinkManagedTimer;
93
- }
94
- >();
127
+ private readonly timers = new Map<string, ZLinkTimerEntry>();
95
128
  private readonly generations = new Map<string, bigint>();
96
129
  private executionBarrier: ZLinkExecutionBarrier | undefined;
130
+ /** Frozen from the source capture or the target restore until abort or Ready. */
131
+ private frozen = false;
132
+ /**
133
+ * The lifecycle owner opens this window around the target's Configure and
134
+ * pre-Ready OnInitialize only (Spot timer §1). A registration captures it at
135
+ * the call, so a registration started inside the window reattaches a
136
+ * restored key even when its asynchronous part finishes after the window.
137
+ */
138
+ private initializing = false;
139
+ /**
140
+ * Handler constructors the target Spot announced with `addTimer(...)` during
141
+ * Configure. Together with `handlers.addTimerHandler(...)` they form the
142
+ * table that resolves a restored timer's handler by name.
143
+ */
144
+ private readonly configureTimerHandlers = new Set<Type>();
145
+ private relocationHandlersResolved = false;
97
146
 
98
147
  constructor(
99
148
  _metrics?: import('../diagnostics').ZLinkRuntimeMetrics,
@@ -134,60 +183,148 @@ export class ZLinkSpotTimerRegistry {
134
183
  reportFailure?: ZLinkTimerFailureReporter
135
184
  ): Promise<ZLinkTimer> {
136
185
  validateTimerRegistration(name, periodMs, options);
186
+ const initializing = this.initializing;
187
+ if (initializing && !this.relocationHandlersResolved) {
188
+ this.configureTimerHandlers.add(handlerType);
189
+ }
137
190
  throwIfAborted(signal);
191
+ prepareHandlerInstance(providerResolver, handlerType);
138
192
  const handler = await resolveLifecycleHandler(spot, handlerType, providerResolver);
139
- const prepared = await this.lane.run(() => this.prepareAddCore(name));
140
- if (prepared.previous !== undefined) await prepared.previous.timer.cancel(signal);
141
193
  const executionSerial =
142
194
  this.executeTimer === undefined
143
195
  ? (this.executionSerialForTimer?.(name, serial) ?? serial)
144
196
  : undefined;
145
197
  if (this.executionBarrier !== undefined)
146
198
  executionSerial?.setExecutionBarrier(this.executionBarrier);
147
- let callbackStarted = false;
148
- const timer = startOutsideStateLane(
149
- () =>
150
- new ZLinkManagedTimer(
151
- name,
152
- periodMs,
153
- normalizeTimerOptions(options),
154
- async (tick) => {
155
- callbackStarted = false;
156
- const timerFlow = createInboundFlow(
157
- undefined,
158
- 'Timer',
159
- this.flowCreationEnabled(),
160
- undefined
161
- );
162
- const operation = () => {
163
- const current = this.timers.get(name);
164
- if (
165
- current === undefined ||
166
- current.generation !== prepared.generation ||
167
- current.timer !== timer
168
- ) {
169
- return undefined;
170
- }
171
- if (!this.executionAllowed()) return undefined;
172
- callbackStarted = true;
173
- return runWithFlow(timerFlow, () => handler.handle(spot, tick));
174
- };
175
- if (this.executeTimer !== undefined) {
176
- await this.executeTimer(name, operation);
177
- } else {
178
- await executionSerial!.execute(operation);
179
- }
180
- },
181
- reportFailure,
182
- () => callbackStarted,
183
- this.clock
184
- )
199
+ const binding: ZLinkTimerBinding = {
200
+ handler: handler as ZLinkSpotTimerHandler<ZLinkTimerOwnerSpot>,
201
+ spot,
202
+ executionSerial,
203
+ reportFailure
204
+ };
205
+ const prepared = await this.lane.run(() =>
206
+ this.prepareAddCore(name, handlerType.name, initializing, binding)
185
207
  );
208
+ if (prepared.kind === 'reattached') return prepared.handle;
209
+ if (prepared.previous !== undefined) await prepared.previous.timer.cancel(signal);
210
+ const slot: ZLinkTimerBindingSlot = { binding };
211
+ const timer = this.createTimer(name, prepared.generation, periodMs, options, slot);
212
+ const handle = new ZLinkRegisteredTimer(this, name, prepared.generation, timer);
186
213
  const registered = await this.lane.run(() =>
187
- this.completeAddCore(name, prepared.generation, handlerType.name, timer)
214
+ this.completeAddCore(name, {
215
+ generation: prepared.generation,
216
+ handlerType: handlerType.name,
217
+ timer,
218
+ handle,
219
+ restored: false,
220
+ slot
221
+ })
188
222
  );
189
223
  if (!registered) await timer.cancel(signal);
190
- return new ZLinkRegisteredTimer(this, name, prepared.generation, timer);
224
+ return handle;
225
+ }
226
+
227
+ /**
228
+ * Stages the source payload on a fresh relocation target before Configure.
229
+ * The restored registrations keep their schedule and stay frozen until Ready.
230
+ */
231
+ stageRelocation(states: readonly ZLinkTimerRelocationState[]): void {
232
+ if (this.frozen || this.timers.size !== 0) {
233
+ throw new Error('Timer relocation can only be restored into a fresh registry.');
234
+ }
235
+ const restored = states.map((state): [string, ZLinkTimerEntry] => {
236
+ if (states.some((other) => other !== state && other.name === state.name)) {
237
+ throw new Error(`Timer '${state.name}' appears twice in relocation state.`);
238
+ }
239
+ const options = {
240
+ overrunPolicy: state.overrunPolicy,
241
+ maxCatchUpTicks: state.maxCatchUpTicks,
242
+ stopOnUnhandledException: state.stopOnUnhandledException
243
+ };
244
+ validateTimerRegistration(state.name, state.periodMs, options);
245
+ const slot: ZLinkTimerBindingSlot = { binding: undefined };
246
+ const timer = this.createTimer(state.name, 1n, state.periodMs, options, slot, state);
247
+ return [
248
+ state.name,
249
+ {
250
+ generation: 1n,
251
+ handlerType: state.handlerType,
252
+ timer,
253
+ handle: new ZLinkRegisteredTimer(this, state.name, 1n, timer),
254
+ restored: true,
255
+ slot
256
+ }
257
+ ];
258
+ });
259
+ this.frozen = true;
260
+ for (const [name, entry] of restored) {
261
+ this.generations.set(name, entry.generation);
262
+ this.timers.set(name, entry);
263
+ }
264
+ }
265
+
266
+ /** Runs one relocation-target initialization callback inside the reattach window. */
267
+ async runRelocationInitialization<T>(operation: () => Promise<T> | T): Promise<T> {
268
+ if (!this.frozen || this.initializing) {
269
+ throw new Error('Timer relocation initialization is not active.');
270
+ }
271
+ this.initializing = true;
272
+ try {
273
+ return await operation();
274
+ } finally {
275
+ this.initializing = false;
276
+ }
277
+ }
278
+
279
+ /**
280
+ * After Configure, resolves every restored timer's handler constructor by
281
+ * name among the constructors the Spot announced in Configure: `addTimer(...)`
282
+ * there or `handlers.addTimerHandler(...)`. A restored key that Configure did
283
+ * not reattach is registered with the resolved constructor so it survives
284
+ * Ready without re-registration. No match or more than one match fails the
285
+ * target restore.
286
+ */
287
+ async resolveRelocationHandlers(
288
+ declared: readonly Type[],
289
+ register: (name: string, periodMs: number, handlerType: Type) => Promise<unknown>
290
+ ): Promise<void> {
291
+ if (!this.frozen || !this.initializing || this.relocationHandlersResolved) {
292
+ throw new Error('Timer relocation handler resolution is not active.');
293
+ }
294
+ this.relocationHandlersResolved = true;
295
+ const constructors = [...new Set([...declared, ...this.configureTimerHandlers])];
296
+ const restored = await this.lane.run(() =>
297
+ [...this.timers.entries()].filter(([, entry]) => entry.restored)
298
+ );
299
+ for (const [name, entry] of restored) {
300
+ const matches = constructors.filter((type) => type.name === entry.handlerType);
301
+ if (matches.length !== 1) {
302
+ throw createInternalFrameworkException(
303
+ ZLinkFrameworkInternalErrorKind.RelocationFailed,
304
+ matches.length === 0
305
+ ? `Timer '${name}' handler '${entry.handlerType}' is not declared. Register its timer with context.addTimer(...) in configure(), or declare it with context.handlers.addTimerHandler(Handler) in configure().`
306
+ : `Timer '${name}' handler '${entry.handlerType}' is ambiguous: ${matches.length} declared constructors share the name.`
307
+ );
308
+ }
309
+ if (entry.slot.binding === undefined) {
310
+ await register(name, entry.timer.periodMs, matches[0]!);
311
+ }
312
+ }
313
+ }
314
+
315
+ /** Ready: starts the restored and newly registered timers. */
316
+ async publishRelocation(): Promise<void> {
317
+ await this.lane.run(() => {
318
+ for (const [name, entry] of this.timers) {
319
+ if (entry.slot.binding === undefined) {
320
+ throw new Error(`Restored timer '${name}' has no resolved handler at Ready.`);
321
+ }
322
+ }
323
+ this.frozen = false;
324
+ for (const entry of this.timers.values()) {
325
+ startOutsideStateLane(() => entry.timer.resume());
326
+ }
327
+ });
191
328
  }
192
329
 
193
330
  async dispose(): Promise<void> {
@@ -205,9 +342,10 @@ export class ZLinkSpotTimerRegistry {
205
342
  }
206
343
 
207
344
  async captureRelocation(): Promise<readonly ZLinkTimerRelocationState[]> {
208
- const timers = await this.lane.run(() =>
209
- [...this.timers.entries()].sort(([left], [right]) => left.localeCompare(right))
210
- );
345
+ const timers = await this.lane.run(() => {
346
+ this.frozen = true;
347
+ return [...this.timers.entries()].sort(([left], [right]) => left.localeCompare(right));
348
+ });
211
349
  const states: ZLinkTimerRelocationState[] = [];
212
350
  for (const [name, entry] of timers) {
213
351
  const state = await entry.timer.captureRelocation(entry.handlerType);
@@ -217,24 +355,14 @@ export class ZLinkSpotTimerRegistry {
217
355
  return states;
218
356
  }
219
357
 
220
- restoreRelocation(states: readonly ZLinkTimerRelocationState[]): void {
221
- const byName = new Map(states.map((state) => [state.name, state]));
222
- if (byName.size !== states.length || byName.size !== this.timers.size) {
223
- throw new Error('Timer relocation inventory does not match registered handlers.');
224
- }
225
- for (const [name, entry] of this.timers) {
226
- const state = byName.get(name);
227
- if (state === undefined) {
228
- throw new Error(`Timer '${name}' is missing from relocation state.`);
229
- }
230
- entry.timer.restoreRelocation(state, entry.handlerType);
358
+ /** Source abort: the captured timers continue from their own unchanged cursor. */
359
+ abortRelocation(): void {
360
+ this.frozen = false;
361
+ for (const entry of this.timers.values()) {
362
+ startOutsideStateLane(() => entry.timer.resume());
231
363
  }
232
364
  }
233
365
 
234
- abortRelocation(states: readonly ZLinkTimerRelocationState[]): void {
235
- this.restoreRelocation(states);
236
- }
237
-
238
366
  async commitRelocation(): Promise<void> {
239
367
  await this.dispose();
240
368
  }
@@ -250,31 +378,92 @@ export class ZLinkSpotTimerRegistry {
250
378
  await timer.cancel(signal);
251
379
  }
252
380
 
253
- private prepareAddCore(name: string): {
254
- readonly previous:
255
- | {
256
- readonly generation: bigint;
257
- readonly handlerType: string;
258
- readonly timer: ZLinkManagedTimer;
259
- }
260
- | undefined;
261
- readonly generation: bigint;
262
- } {
381
+ private createTimer(
382
+ name: string,
383
+ generation: bigint,
384
+ periodMs: number,
385
+ options: ZLinkTimerOptions | undefined,
386
+ slot: ZLinkTimerBindingSlot,
387
+ cursor?: ZLinkTimerRelocationState
388
+ ): ZLinkManagedTimer {
389
+ let callbackStarted = false;
390
+ const timer: ZLinkManagedTimer = startOutsideStateLane(
391
+ () =>
392
+ new ZLinkManagedTimer(
393
+ name,
394
+ periodMs,
395
+ normalizeTimerOptions(options),
396
+ async (tick) => {
397
+ callbackStarted = false;
398
+ const binding = slot.binding;
399
+ if (binding === undefined) return;
400
+ const timerFlow = createInboundFlow(
401
+ undefined,
402
+ 'Timer',
403
+ this.flowCreationEnabled(),
404
+ undefined
405
+ );
406
+ const operation = () => {
407
+ const current = this.timers.get(name);
408
+ if (
409
+ current === undefined ||
410
+ current.generation !== generation ||
411
+ current.timer !== timer
412
+ ) {
413
+ return undefined;
414
+ }
415
+ if (!this.executionAllowed()) return undefined;
416
+ callbackStarted = true;
417
+ return runWithFlow(timerFlow, () => binding.handler.handle(binding.spot, tick));
418
+ };
419
+ if (this.executeTimer !== undefined) {
420
+ await this.executeTimer(name, operation);
421
+ } else {
422
+ await binding.executionSerial!.execute(operation);
423
+ }
424
+ },
425
+ (tick, cause, event) => slot.binding?.reportFailure?.(tick, cause, event),
426
+ () => callbackStarted,
427
+ this.clock,
428
+ { paused: true, cursor }
429
+ )
430
+ );
431
+ return timer;
432
+ }
433
+
434
+ private prepareAddCore(
435
+ name: string,
436
+ handlerType: string,
437
+ initializing: boolean,
438
+ binding: ZLinkTimerBinding
439
+ ): ZLinkTimerAddPreparation {
440
+ if (this.frozen && !initializing) {
441
+ throw createInternalFrameworkException(
442
+ ZLinkFrameworkInternalErrorKind.InvalidOperation,
443
+ `Timer '${name}' registration is sealed for relocation.`
444
+ );
445
+ }
263
446
  const previous = this.timers.get(name);
447
+ if (initializing && previous?.restored === true) {
448
+ if (previous.handlerType !== handlerType) {
449
+ throw createInternalFrameworkException(
450
+ ZLinkFrameworkInternalErrorKind.InvalidOperation,
451
+ `Timer '${name}' was restored with handler '${previous.handlerType}', not '${handlerType}'.`
452
+ );
453
+ }
454
+ previous.slot.binding = binding;
455
+ return { kind: 'reattached', handle: previous.handle };
456
+ }
264
457
  this.timers.delete(name);
265
458
  const generation = (this.generations.get(name) ?? 0n) + 1n;
266
459
  this.generations.set(name, generation);
267
- return { previous, generation };
460
+ return { kind: 'registered', previous, generation };
268
461
  }
269
462
 
270
- private completeAddCore(
271
- name: string,
272
- generation: bigint,
273
- handlerType: string,
274
- timer: ZLinkManagedTimer
275
- ): boolean {
276
- if (this.generations.get(name) !== generation) return false;
277
- this.timers.set(name, { generation, handlerType, timer });
463
+ private completeAddCore(name: string, entry: ZLinkTimerEntry): boolean {
464
+ if (this.generations.get(name) !== entry.generation) return false;
465
+ this.timers.set(name, entry);
466
+ if (!this.frozen) startOutsideStateLane(() => entry.timer.resume());
278
467
  return true;
279
468
  }
280
469
 
@@ -322,24 +511,44 @@ export class ZLinkManagedTimer implements ZLinkTimer {
322
511
  private pausedForRelocation = false;
323
512
  private startedAtMs: number;
324
513
  private startedAtUnixMs: number;
514
+ /** DeliveryIndex and ScheduledIndex of the last completed tick. */
325
515
  private deliveryIndex = 0n;
326
516
  private lastScheduledIndex = 0n;
517
+ /**
518
+ * The selected tick whose callback has not completed (Spot timer §1). It is
519
+ * the only pending tick a relocation captures, and a restored timer delivers
520
+ * it before it selects another tick.
521
+ */
522
+ private pendingScheduledIndex: bigint | undefined;
327
523
  private timeout: unknown;
328
- private running: Promise<void> = Promise.resolve();
524
+ /** The dispatch in flight, from its timer callback until `completeFireCore`. */
525
+ private running: Promise<void> | undefined;
329
526
  private dispatchFailure: { readonly cause: unknown } | undefined;
330
527
  private finalization: ZLinkTimerFinalization | undefined;
331
528
 
332
529
  constructor(
333
530
  private readonly name: string,
334
- private readonly periodMs: number,
531
+ readonly periodMs: number,
335
532
  private readonly options: Required<ZLinkTimerOptions>,
336
533
  private readonly onTick: (tick: ZLinkTimerTick) => Promise<void>,
337
534
  private readonly onFailure?: ZLinkTimerFailureReporter,
338
535
  private readonly shouldWaitForRunningOnCancel: () => boolean = () => true,
339
- private readonly clock: ZLinkTimerClock = systemTimerClock
536
+ private readonly clock: ZLinkTimerClock = systemTimerClock,
537
+ start: ZLinkManagedTimerStart = {}
340
538
  ) {
341
- this.startedAtMs = clock.now();
342
- this.startedAtUnixMs = clock.utcNow();
539
+ const cursor = start.cursor;
540
+ if (cursor === undefined) {
541
+ this.startedAtMs = clock.now();
542
+ this.startedAtUnixMs = clock.utcNow();
543
+ } else {
544
+ validateRelocationCursor(name, periodMs, cursor);
545
+ this.startedAtUnixMs = cursor.startedAtUnixMs;
546
+ this.startedAtMs = clock.now() - Math.max(0, clock.utcNow() - cursor.startedAtUnixMs);
547
+ this.deliveryIndex = cursor.deliveryIndex;
548
+ this.lastScheduledIndex = cursor.lastScheduledIndex;
549
+ this.pendingScheduledIndex = cursor.pendingTicks[0]?.scheduledIndex;
550
+ }
551
+ this.pausedForRelocation = start.paused === true;
343
552
  this.scheduleNext();
344
553
  }
345
554
 
@@ -388,59 +597,44 @@ export class ZLinkManagedTimer implements ZLinkTimer {
388
597
  deliveryIndex: this.deliveryIndex,
389
598
  lastScheduledIndex: this.lastScheduledIndex,
390
599
  nextDueAtUnixMs: this.startedAtUnixMs + Number(this.lastScheduledIndex + 1n) * this.periodMs,
391
- pendingTicks: []
600
+ pendingTicks:
601
+ this.pendingScheduledIndex === undefined
602
+ ? []
603
+ : [this.pendingTick(this.pendingScheduledIndex)]
392
604
  }));
393
605
  }
394
606
 
395
- restoreRelocation(state: ZLinkTimerRelocationState, handlerType = ''): void {
396
- if (this.disposed) throw new Error(`Timer '${this.name}' is disposed.`);
397
- if (
398
- state.name !== this.name ||
399
- state.handlerType !== handlerType ||
400
- state.periodMs !== this.periodMs ||
401
- state.overrunPolicy !== this.options.overrunPolicy ||
402
- state.maxCatchUpTicks !== this.options.maxCatchUpTicks ||
403
- state.stopOnUnhandledException !== this.options.stopOnUnhandledException ||
404
- !Number.isSafeInteger(state.startedAtUnixMs) ||
405
- state.deliveryIndex < 0n ||
406
- state.lastScheduledIndex < 0n ||
407
- !Number.isSafeInteger(state.nextDueAtUnixMs) ||
408
- state.nextDueAtUnixMs !==
409
- state.startedAtUnixMs + Number(state.lastScheduledIndex + 1n) * state.periodMs ||
410
- state.pendingTicks.length !== 0
411
- ) {
412
- throw new Error(`Timer '${this.name}' relocation contract does not match its registration.`);
413
- }
414
- if (this.timeout !== undefined) this.clock.clearTimeout(this.timeout);
415
- this.timeout = undefined;
416
- this.startedAtUnixMs = state.startedAtUnixMs;
417
- this.startedAtMs = this.clock.now() - Math.max(0, this.clock.utcNow() - state.startedAtUnixMs);
418
- this.deliveryIndex = state.deliveryIndex;
419
- this.lastScheduledIndex = state.lastScheduledIndex;
607
+ /** Starts a timer created paused, or continues one paused by a relocation capture. */
608
+ resume(): void {
609
+ if (this.disposed || !this.pausedForRelocation) return;
420
610
  this.pausedForRelocation = false;
421
611
  this.scheduleNext();
422
612
  }
423
613
 
424
614
  private scheduleNext(): void {
425
- if (this.disposed || this.pausedForRelocation) {
615
+ // The dispatch in flight schedules the next tick when it completes.
616
+ if (this.disposed || this.pausedForRelocation || this.running !== undefined) {
426
617
  return;
427
618
  }
428
619
 
429
620
  const delayMs =
430
- this.options.overrunPolicy === ZLinkTimerOverrunPolicy.DelayNextTick
431
- ? this.periodMs
432
- : Math.max(0, Number(this.lastScheduledIndex + 1n) * this.periodMs - this.elapsedMs());
433
- this.timeout = this.clock.setTimeout(() => {
434
- this.timeout = undefined;
435
- const execution = startOutsideStateLane(() => this.fire());
436
- this.running = execution.then(
437
- () => undefined,
438
- (cause) =>
439
- this.lane.run(() => {
440
- this.dispatchFailure ??= { cause };
441
- })
442
- );
443
- }, delayMs);
621
+ this.pendingScheduledIndex !== undefined
622
+ ? 0
623
+ : this.options.overrunPolicy === ZLinkTimerOverrunPolicy.DelayNextTick
624
+ ? this.periodMs
625
+ : Math.max(0, Number(this.lastScheduledIndex + 1n) * this.periodMs - this.elapsedMs());
626
+ this.timeout = startOutsideStateLane(() =>
627
+ this.clock.setTimeout(() => {
628
+ this.timeout = undefined;
629
+ this.running = this.fire().then(
630
+ () => undefined,
631
+ (cause) =>
632
+ this.lane.run(() => {
633
+ this.dispatchFailure ??= { cause };
634
+ })
635
+ );
636
+ }, delayMs)
637
+ );
444
638
  }
445
639
 
446
640
  private async fire(): Promise<void> {
@@ -451,6 +645,11 @@ export class ZLinkManagedTimer implements ZLinkTimer {
451
645
  try {
452
646
  await this.onTick(prepared.tick);
453
647
  } catch (cause) {
648
+ // A tick whose callback had not started when a relocation captured it
649
+ // belongs to the capture: the target delivers it, so the source neither
650
+ // reports nor completes it.
651
+ const started = this.shouldWaitForRunningOnCancel();
652
+ if (!started && (await this.lane.run(() => this.pausedForRelocation))) return;
454
653
  shouldContinue = !this.options.stopOnUnhandledException;
455
654
  await this.onFailure?.(
456
655
  prepared.tick,
@@ -461,7 +660,7 @@ export class ZLinkManagedTimer implements ZLinkTimer {
461
660
  );
462
661
  }
463
662
 
464
- await this.lane.run(() => this.completeFireCore(prepared.scheduledIndex, shouldContinue));
663
+ await this.lane.run(() => this.completeFireCore(shouldContinue));
465
664
  }
466
665
 
467
666
  private cancelCore(): ZLinkTimerFinalizationStart {
@@ -470,7 +669,7 @@ export class ZLinkManagedTimer implements ZLinkTimer {
470
669
  this.timeout = undefined;
471
670
  return {
472
671
  timeout,
473
- running: this.shouldWaitForRunningOnCancel() ? this.running : Promise.resolve()
672
+ running: this.shouldWaitForRunningOnCancel() ? this.running : undefined
474
673
  };
475
674
  }
476
675
 
@@ -503,43 +702,54 @@ export class ZLinkManagedTimer implements ZLinkTimer {
503
702
  }
504
703
  }
505
704
 
506
- private prepareCaptureCore(): { readonly running: Promise<void> } {
705
+ private prepareCaptureCore(): { readonly running: Promise<void> | undefined } {
507
706
  if (this.disposed) throw new Error(`Timer '${this.name}' is disposed.`);
508
707
  this.pausedForRelocation = true;
509
708
  if (this.timeout !== undefined) {
510
709
  this.clock.clearTimeout(this.timeout);
511
710
  this.timeout = undefined;
512
711
  }
513
- return { running: this.shouldWaitForRunningOnCancel() ? this.running : Promise.resolve() };
712
+ return { running: this.shouldWaitForRunningOnCancel() ? this.running : undefined };
514
713
  }
515
714
 
516
- private prepareFireCore():
517
- { readonly tick: ZLinkTimerTick; readonly scheduledIndex: bigint } | undefined {
715
+ private prepareFireCore(): { readonly tick: ZLinkTimerTick } | undefined {
518
716
  if (this.disposed) return undefined;
519
- const scheduledIndex = this.selectScheduledIndex();
520
- const skippedTicks = scheduledIndex - this.lastScheduledIndex - 1n;
717
+ this.pendingScheduledIndex ??= this.selectScheduledIndex();
718
+ const pending = this.pendingTick(this.pendingScheduledIndex);
521
719
  const startedElapsedMs = this.elapsedMs();
522
- const scheduledElapsedMs = Number(scheduledIndex) * this.periodMs;
523
- this.deliveryIndex += 1n;
720
+ const scheduledElapsedMs = Number(pending.scheduledIndex) * this.periodMs;
524
721
  return {
525
- scheduledIndex,
526
722
  tick: {
527
723
  name: this.name,
528
- deliveryIndex: this.deliveryIndex,
529
- scheduledIndex,
724
+ deliveryIndex: pending.deliveryIndex,
725
+ scheduledIndex: pending.scheduledIndex,
530
726
  periodMs: this.periodMs,
531
- scheduledAt: new Date(this.startedAtUnixMs + scheduledElapsedMs),
727
+ scheduledAt: new Date(pending.scheduledAtUnixMs),
532
728
  startedAt: new Date(this.clock.utcNow()),
533
729
  scheduledElapsedMs,
534
730
  startedElapsedMs,
535
731
  delayMs: startedElapsedMs - scheduledElapsedMs,
536
- skippedTicks
732
+ skippedTicks: pending.skippedTicks
537
733
  }
538
734
  };
539
735
  }
540
736
 
541
- private completeFireCore(scheduledIndex: bigint, shouldContinue: boolean): void {
542
- this.lastScheduledIndex = scheduledIndex;
737
+ /** The tick info of the pending tick at `scheduledIndex` after the completed cursor. */
738
+ private pendingTick(scheduledIndex: bigint): ZLinkTimerRelocationPendingTick {
739
+ return relocationPendingTick(
740
+ this.startedAtUnixMs,
741
+ this.periodMs,
742
+ this.deliveryIndex,
743
+ this.lastScheduledIndex,
744
+ scheduledIndex
745
+ );
746
+ }
747
+
748
+ private completeFireCore(shouldContinue: boolean): void {
749
+ this.deliveryIndex += 1n;
750
+ this.lastScheduledIndex = this.pendingScheduledIndex!;
751
+ this.pendingScheduledIndex = undefined;
752
+ this.running = undefined;
543
753
  if (!shouldContinue) {
544
754
  this.disposed = true;
545
755
  return;
@@ -576,8 +786,58 @@ export class ZLinkManagedTimer implements ZLinkTimer {
576
786
  }
577
787
  }
578
788
 
579
- function startOutsideStateLane<T>(work: () => T): T {
580
- return detachedTimerStateLaneResource.runInAsyncScope(work);
789
+ function validateRelocationCursor(
790
+ name: string,
791
+ periodMs: number,
792
+ state: ZLinkTimerRelocationState
793
+ ): void {
794
+ if (
795
+ state.name !== name ||
796
+ state.periodMs !== periodMs ||
797
+ !Number.isSafeInteger(state.startedAtUnixMs) ||
798
+ state.deliveryIndex < 0n ||
799
+ state.lastScheduledIndex < 0n ||
800
+ !Number.isSafeInteger(state.nextDueAtUnixMs) ||
801
+ state.nextDueAtUnixMs !==
802
+ state.startedAtUnixMs + Number(state.lastScheduledIndex + 1n) * state.periodMs ||
803
+ state.pendingTicks.length > 1 ||
804
+ state.pendingTicks.some((pending) => {
805
+ const expected = relocationPendingTick(
806
+ state.startedAtUnixMs,
807
+ state.periodMs,
808
+ state.deliveryIndex,
809
+ state.lastScheduledIndex,
810
+ pending.scheduledIndex
811
+ );
812
+ return (
813
+ pending.scheduledIndex <= state.lastScheduledIndex ||
814
+ pending.deliveryIndex !== expected.deliveryIndex ||
815
+ pending.scheduledAtUnixMs !== expected.scheduledAtUnixMs ||
816
+ pending.skippedTicks !== expected.skippedTicks
817
+ );
818
+ })
819
+ ) {
820
+ throw new Error(`Timer '${name}' relocation state is invalid.`);
821
+ }
822
+ }
823
+
824
+ /**
825
+ * Spot timer §1: the tick info that follows the completed cursor. A timer holds
826
+ * at most one pending tick, so its DeliveryIndex is the next one.
827
+ */
828
+ function relocationPendingTick(
829
+ startedAtUnixMs: number,
830
+ periodMs: number,
831
+ deliveryIndex: bigint,
832
+ lastScheduledIndex: bigint,
833
+ scheduledIndex: bigint
834
+ ): ZLinkTimerRelocationPendingTick {
835
+ return {
836
+ deliveryIndex: deliveryIndex + 1n,
837
+ scheduledIndex,
838
+ scheduledAtUnixMs: startedAtUnixMs + Number(scheduledIndex) * periodMs,
839
+ skippedTicks: scheduledIndex - lastScheduledIndex - 1n
840
+ };
581
841
  }
582
842
 
583
843
  export function createTimerDiagnostics(