@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
@@ -8,10 +8,14 @@ import {
8
8
  } from './service-topology-registry';
9
9
  import {
10
10
  SERVICE_WIRE_PREFIX_SIZE,
11
+ SERVICE_WIRE_TEXT8_MAX_BYTES,
12
+ canonicalServiceWireTextLength,
11
13
  decodeCanonicalServiceWireText,
12
14
  encodeCanonicalServiceWireText
13
15
  } from './service-wire-binary-primitives';
14
16
  import {
17
+ SERVICE_FRAMEWORK_MULTIPART_CONTENT_TYPE,
18
+ SERVICE_FRAMEWORK_MULTIPART_PACKET_NAME,
15
19
  SERVICE_WIRE_MAGIC,
16
20
  SERVICE_WIRE_MAJOR,
17
21
  SERVICE_WIRE_REQUIRED_CAPABILITY,
@@ -32,6 +36,10 @@ export const APPLICATION_PAYLOAD_MINIMUM_FIELD_BYTES =
32
36
  APPLICATION_PAYLOAD_LENGTH_FIELD_BYTES;
33
37
  const MAX_U32 = UINT32_MAX;
34
38
  const MAX_U64 = UINT64_MAX;
39
+ // The framework multipart frame always carries these two schema constants;
40
+ // decoding compares their bytes in place instead of decoding text.
41
+ const MULTIPART_PACKET_NAME_BYTES = Buffer.from(SERVICE_FRAMEWORK_MULTIPART_PACKET_NAME);
42
+ const MULTIPART_CONTENT_TYPE_BYTES = Buffer.from(SERVICE_FRAMEWORK_MULTIPART_CONTENT_TYPE);
35
43
  export const M6A_SERVICE_WIRE_MAGIC = SERVICE_WIRE_MAGIC;
36
44
  export const M6A_SERVICE_WIRE_MAJOR = SERVICE_WIRE_MAJOR;
37
45
  export const M6A_SERVICE_WIRE_REQUIRED_CAPABILITY = SERVICE_WIRE_REQUIRED_CAPABILITY;
@@ -67,11 +75,10 @@ export function encodeNodeSendHeader(): Buffer {
67
75
  }
68
76
 
69
77
  export function encodeNodeRequestHeader(correlation: bigint): Buffer {
70
- return withU64(prefix(M6aServiceWireCommand.nodeRequest), correlation, 'correlation');
78
+ return withU64(M6aServiceWireCommand.nodeRequest, correlation, 0);
71
79
  }
72
80
 
73
- export function decodeNodeRequestHeader(frame: Uint8Array): bigint {
74
- const header = decodeHeader(frame);
81
+ export function decodeNodeRequestHeader(frame: Uint8Array, header = decodeHeader(frame)): bigint {
75
82
  if (
76
83
  header.command !== M6aServiceWireCommand.nodeRequest ||
77
84
  header.flags !== 0 ||
@@ -83,11 +90,13 @@ export function decodeNodeRequestHeader(frame: Uint8Array): bigint {
83
90
  }
84
91
 
85
92
  export function encodeChannelSendHeader(channelName: string): Buffer {
86
- return concat(prefix(M6aServiceWireCommand.channelSend), encodeText8(channelName, 'channelName'));
93
+ const length = channelNameLength(channelName);
94
+ const result = frame(M6aServiceWireCommand.channelSend, 1 + length);
95
+ writeText8(result, PREFIX_SIZE, channelName, length);
96
+ return result;
87
97
  }
88
98
 
89
- export function decodeChannelSendHeader(frame: Uint8Array): string {
90
- const header = decodeHeader(frame);
99
+ export function decodeChannelSendHeader(frame: Uint8Array, header = decodeHeader(frame)): string {
91
100
  if (header.command !== M6aServiceWireCommand.channelSend || header.flags !== 0) {
92
101
  fail('Invalid channelSend header.');
93
102
  }
@@ -98,17 +107,28 @@ export function decodeChannelSendHeader(frame: Uint8Array): string {
98
107
  }
99
108
 
100
109
  export function encodeChannelRequestHeader(correlation: bigint, channelName: string): Buffer {
101
- return concat(
102
- withU64(prefix(M6aServiceWireCommand.channelRequest), correlation, 'correlation'),
103
- encodeText8(channelName, 'channelName')
110
+ const length = channelNameLength(channelName);
111
+ const result = withU64(M6aServiceWireCommand.channelRequest, correlation, 1 + length);
112
+ writeText8(result, PREFIX_SIZE + 8, channelName, length);
113
+ return result;
114
+ }
115
+
116
+ function channelNameLength(channelName: string): number {
117
+ return canonicalServiceWireTextLength(
118
+ channelName,
119
+ 'channelName',
120
+ SERVICE_WIRE_TEXT8_MAX_BYTES,
121
+ fail
104
122
  );
105
123
  }
106
124
 
107
- export function decodeChannelRequestHeader(frame: Uint8Array): {
125
+ export function decodeChannelRequestHeader(
126
+ frame: Uint8Array,
127
+ header = decodeHeader(frame)
128
+ ): {
108
129
  readonly correlation: bigint;
109
130
  readonly channelName: string;
110
131
  } {
111
- const header = decodeHeader(frame);
112
132
  if (header.command !== M6aServiceWireCommand.channelRequest || header.flags !== 0) {
113
133
  fail('Invalid channelRequest header.');
114
134
  }
@@ -123,7 +143,7 @@ export function encodeReplyHeader(
123
143
  correlation: bigint,
124
144
  terminalResult = 0,
125
145
  failureCode = 0,
126
- tail: Uint8Array = Buffer.alloc(0)
146
+ tail?: Uint8Array
127
147
  ): Buffer {
128
148
  validateReplyFields(correlation, terminalResult, failureCode);
129
149
  // service-wire-v1.schema.json: reply(20).tail -> `request-specific-tail`,
@@ -132,12 +152,11 @@ export function encodeReplyHeader(
132
152
  // length on the wire; an empty tail yields exactly 21 bytes. (Contrast
133
153
  // `actor-join-reply-tail`, which does declare `bodyLengthType: u16` and
134
154
  // therefore carries its own inner length prefix.)
135
- const result = Buffer.alloc(PREFIX_SIZE + 16 + tail.byteLength);
136
- prefix(M6aServiceWireCommand.reply).copy(result);
155
+ const result = frame(M6aServiceWireCommand.reply, 16 + (tail?.byteLength ?? 0));
137
156
  result.writeBigUInt64BE(correlation, PREFIX_SIZE);
138
157
  result.writeUInt32BE(terminalResult, PREFIX_SIZE + 8);
139
158
  result.writeUInt32BE(failureCode, PREFIX_SIZE + 12);
140
- Buffer.from(tail).copy(result, PREFIX_SIZE + 16);
159
+ if (tail !== undefined) result.set(tail, PREFIX_SIZE + 16);
141
160
  return result;
142
161
  }
143
162
 
@@ -158,31 +177,20 @@ export function decodeReplyHeader(frame: Uint8Array): ServiceReplyHeader {
158
177
  correlation: bytes.readBigUInt64BE(PREFIX_SIZE),
159
178
  terminalResult: bytes.readUInt32BE(PREFIX_SIZE + 8),
160
179
  failureCode: bytes.readUInt32BE(PREFIX_SIZE + 12),
161
- tail: Buffer.from(bytes.subarray(PREFIX_SIZE + 16))
180
+ // A view of the frame: the caller validates the tail before the frame is released.
181
+ tail: bytes.subarray(PREFIX_SIZE + 16)
162
182
  };
163
183
  validateReplyFields(result.correlation, result.terminalResult, result.failureCode);
164
184
  return result;
165
185
  }
166
186
 
167
187
  export function encodeApplicationPayload(payload: ServiceApplicationPayload): Buffer {
168
- const packetName = encodeText8(payload.packetName, 'packetName');
169
- const contentType = encodeText8(payload.contentType, 'contentType');
170
- if (payload.payload.byteLength > MAX_U32) fail('Application payload exceeds u32.');
171
- const bodyLength =
172
- packetName.byteLength + contentType.byteLength + 4 + payload.payload.byteLength;
173
- if (bodyLength > MAX_U32) fail('Application payload body exceeds u32.');
174
- const result = Buffer.alloc(5 + bodyLength);
175
- result[0] = APPLICATION_PAYLOAD_VERSION;
176
- result.writeUInt32BE(bodyLength, 1);
177
- let offset = 5;
178
- offset += packetName.copy(result, offset);
179
- offset += contentType.copy(result, offset);
180
- result.writeUInt32BE(payload.payload.byteLength, offset);
181
- offset += 4;
182
- Buffer.from(payload.payload.buffer, payload.payload.byteOffset, payload.payload.byteLength).copy(
183
- result,
184
- offset
188
+ const result = allocateApplicationPayload(
189
+ payload.packetName,
190
+ payload.contentType,
191
+ payload.payload.byteLength
185
192
  );
193
+ result.set(payload.payload, result.byteLength - payload.payload.byteLength);
186
194
  return result;
187
195
  }
188
196
 
@@ -198,35 +206,57 @@ export function encodeMultipartApplicationPayload(
198
206
  ): Buffer {
199
207
  if (parts.length === 0) fail('Multipart payload must contain at least one part.');
200
208
  if (parts.length > MAX_U32) fail('Multipart part count exceeds u32.');
201
- const packetNameBytes = encodeText8(packetName, 'packetName');
202
- const contentTypeBytes = encodeText8(contentType, 'contentType');
203
209
  let multipartLength = 4;
204
210
  for (const part of parts) {
205
211
  if (part.byteLength > MAX_U32) fail('Multipart part exceeds u32.');
206
212
  multipartLength += 4 + part.byteLength;
207
213
  if (multipartLength > MAX_U32) fail('Multipart payload exceeds u32.');
208
214
  }
209
- const bodyLength = packetNameBytes.byteLength + contentTypeBytes.byteLength + 4 + multipartLength;
210
- if (bodyLength > MAX_U32) fail('Application payload body exceeds u32.');
211
- const result = Buffer.alloc(5 + bodyLength);
212
- result[0] = APPLICATION_PAYLOAD_VERSION;
213
- result.writeUInt32BE(bodyLength, 1);
214
- let offset = 5;
215
- offset += packetNameBytes.copy(result, offset);
216
- offset += contentTypeBytes.copy(result, offset);
217
- result.writeUInt32BE(multipartLength, offset);
218
- offset += 4;
215
+ const result = allocateApplicationPayload(packetName, contentType, multipartLength);
216
+ let offset = result.byteLength - multipartLength;
219
217
  result.writeUInt32BE(parts.length, offset);
220
218
  offset += 4;
221
219
  for (const part of parts) {
222
220
  result.writeUInt32BE(part.byteLength, offset);
223
221
  offset += 4;
224
- Buffer.from(part.buffer, part.byteOffset, part.byteLength).copy(result, offset);
222
+ result.set(part, offset);
225
223
  offset += part.byteLength;
226
224
  }
227
225
  return result;
228
226
  }
229
227
 
228
+ function allocateApplicationPayload(
229
+ packetName: string,
230
+ contentType: string,
231
+ payloadLength: number
232
+ ): Buffer {
233
+ const packetNameLength = canonicalServiceWireTextLength(
234
+ packetName,
235
+ 'packetName',
236
+ SERVICE_WIRE_TEXT8_MAX_BYTES,
237
+ fail
238
+ );
239
+ const contentTypeLength = canonicalServiceWireTextLength(
240
+ contentType,
241
+ 'contentType',
242
+ SERVICE_WIRE_TEXT8_MAX_BYTES,
243
+ fail
244
+ );
245
+ if (payloadLength > MAX_U32) fail('Application payload exceeds u32.');
246
+ const frameLength =
247
+ APPLICATION_PAYLOAD_MINIMUM_FIELD_BYTES + packetNameLength + contentTypeLength + payloadLength;
248
+ const prefixLength = 1 + APPLICATION_PAYLOAD_LENGTH_FIELD_BYTES;
249
+ const bodyLength = frameLength - prefixLength;
250
+ if (bodyLength > MAX_U32) fail('Application payload body exceeds u32.');
251
+ const result = Buffer.alloc(frameLength);
252
+ result[0] = APPLICATION_PAYLOAD_VERSION;
253
+ result.writeUInt32BE(bodyLength, 1);
254
+ let offset = writeText8(result, prefixLength, packetName, packetNameLength);
255
+ offset = writeText8(result, offset, contentType, contentTypeLength);
256
+ result.writeUInt32BE(payloadLength, offset);
257
+ return result;
258
+ }
259
+
230
260
  export function decodeApplicationPayload(frame: Uint8Array): ServiceApplicationPayload {
231
261
  const decoded = decodeApplicationPayloadView(frame);
232
262
  return {
@@ -241,18 +271,127 @@ export function decodeApplicationPayload(frame: Uint8Array): ServiceApplicationP
241
271
  * they must hand the multipart bytes to another runtime-owned queue.
242
272
  */
243
273
  export function decodeApplicationPayloadView(frame: Uint8Array): ServiceApplicationPayload {
244
- const reader = new Reader(frame);
245
- if (reader.u8('version') !== APPLICATION_PAYLOAD_VERSION)
246
- fail('Invalid application payload version.');
247
- const bodyLength = reader.u32('bodyLength');
248
- if (bodyLength !== reader.remaining) fail('Application payload body length mismatch.');
274
+ const reader = applicationPayloadReader(frame);
249
275
  const packetName = reader.text8('packetName');
250
276
  const contentType = reader.text8('contentType');
251
- const payloadLength = reader.u32('payloadLength');
252
- if (payloadLength !== reader.remaining) fail('Application payload length mismatch.');
253
- const payload = reader.view(payloadLength, 'payload');
254
- reader.end();
255
- return { packetName, contentType, payload };
277
+ return { packetName, contentType, payload: applicationPayloadView(reader) };
278
+ }
279
+
280
+ /**
281
+ * Decodes the framework multipart application frame, whose packet name and
282
+ * content type are the schema's multipart constants, and returns a view of its
283
+ * multipart payload without decoding either text field.
284
+ */
285
+ export function decodeMultipartApplicationPayloadView(
286
+ frame: Uint8Array
287
+ ): ServiceApplicationPayload {
288
+ const bytes = asBuffer(frame);
289
+ const offset = multipartApplicationPayloadOffset(bytes);
290
+ return {
291
+ packetName: SERVICE_FRAMEWORK_MULTIPART_PACKET_NAME,
292
+ contentType: SERVICE_FRAMEWORK_MULTIPART_CONTENT_TYPE,
293
+ payload: bytes.subarray(offset)
294
+ };
295
+ }
296
+
297
+ /** Materializes final message parts directly over the retained application frame. */
298
+ export function decodeMultipartApplicationParts<T>(
299
+ frame: Uint8Array,
300
+ materialize: (part: Buffer) => T,
301
+ release?: (part: T) => void
302
+ ): T[] {
303
+ const bytes = asBuffer(frame);
304
+ return decodeMultipartParts(
305
+ bytes,
306
+ materialize,
307
+ release,
308
+ multipartApplicationPayloadOffset(bytes)
309
+ );
310
+ }
311
+
312
+ function multipartApplicationPayloadOffset(bytes: Buffer): number {
313
+ let offset = applicationPayloadBodyOffset(bytes);
314
+ offset = expectText8At(bytes, offset, MULTIPART_PACKET_NAME_BYTES, 'packetName');
315
+ offset = expectText8At(bytes, offset, MULTIPART_CONTENT_TYPE_BYTES, 'contentType');
316
+ return applicationPayloadDataOffset(bytes, offset);
317
+ }
318
+
319
+ function expectText8At(bytes: Buffer, offset: number, expected: Buffer, field: string): number {
320
+ if (bytes.length <= offset) fail(`Truncated ${field}.length.`);
321
+ const length = bytes[offset++]!;
322
+ if (bytes.length - offset < length) fail(`Truncated ${field}.`);
323
+ if (length !== expected.length || expected.compare(bytes, offset, offset + length) !== 0) {
324
+ fail(`Unexpected ${field}.`);
325
+ }
326
+ return offset + length;
327
+ }
328
+
329
+ function applicationPayloadBodyOffset(bytes: Buffer): number {
330
+ if (bytes.length === 0) fail('Truncated version.');
331
+ if (bytes[0] !== APPLICATION_PAYLOAD_VERSION) fail('Invalid application payload version.');
332
+ const offset = 1 + APPLICATION_PAYLOAD_LENGTH_FIELD_BYTES;
333
+ if (bytes.length < offset) fail('Truncated bodyLength.');
334
+ if (bytes.readUInt32BE(1) !== bytes.length - offset)
335
+ fail('Application payload body length mismatch.');
336
+ return offset;
337
+ }
338
+
339
+ function applicationPayloadDataOffset(bytes: Buffer, offset: number): number {
340
+ if (bytes.length - offset < APPLICATION_PAYLOAD_LENGTH_FIELD_BYTES)
341
+ fail('Truncated payloadLength.');
342
+ const length = bytes.readUInt32BE(offset);
343
+ offset += APPLICATION_PAYLOAD_LENGTH_FIELD_BYTES;
344
+ if (length !== bytes.length - offset) fail('Application payload length mismatch.');
345
+ return offset;
346
+ }
347
+
348
+ function applicationPayloadReader(frame: Uint8Array): Reader {
349
+ const bytes = asBuffer(frame);
350
+ return new Reader(bytes, applicationPayloadBodyOffset(bytes));
351
+ }
352
+
353
+ function applicationPayloadView(reader: Reader): Buffer {
354
+ return reader.buffer.subarray(applicationPayloadDataOffset(reader.buffer, reader.offset));
355
+ }
356
+
357
+ export function decodeMultipartParts<T>(
358
+ payload: Uint8Array,
359
+ materialize: (part: Buffer) => T,
360
+ release?: (part: T) => void,
361
+ offset = 0
362
+ ): T[] {
363
+ const bytes = asBuffer(payload);
364
+ if (bytes.length - offset < 4) throw new ServiceWireProtocolError('Truncated multipart payload.');
365
+ const count = bytes.readUInt32BE(offset);
366
+ if (count === 0 || count > Math.floor((bytes.length - offset - 4) / 4)) {
367
+ throw new ServiceWireProtocolError('Invalid multipart part count.');
368
+ }
369
+ const result = new Array<T>(count);
370
+ offset += 4;
371
+ let index = 0;
372
+ try {
373
+ for (; index < count; index++) {
374
+ if (bytes.length - offset < 4) {
375
+ throw new ServiceWireProtocolError('Truncated multipart part length.');
376
+ }
377
+ const length = bytes.readUInt32BE(offset);
378
+ offset += 4;
379
+ if (bytes.length - offset < length) {
380
+ throw new ServiceWireProtocolError('Truncated multipart part.');
381
+ }
382
+ result[index] = materialize(bytes.subarray(offset, offset + length));
383
+ offset += length;
384
+ }
385
+ if (offset !== bytes.length) {
386
+ throw new ServiceWireProtocolError('Multipart payload has trailing bytes.');
387
+ }
388
+ return result;
389
+ } catch (error) {
390
+ if (release !== undefined) {
391
+ for (let retained = 0; retained < index; retained++) release(result[retained]!);
392
+ }
393
+ throw error;
394
+ }
256
395
  }
257
396
 
258
397
  /**
@@ -262,11 +401,7 @@ export function decodeApplicationPayloadView(frame: Uint8Array): ServiceApplicat
262
401
  * message is admitted to an execution queue.
263
402
  */
264
403
  export function validateApplicationPayloadFrame(frame: Uint8Array): void {
265
- const reader = new Reader(frame);
266
- if (reader.u8('version') !== APPLICATION_PAYLOAD_VERSION)
267
- fail('Invalid application payload version.');
268
- const bodyLength = reader.u32('bodyLength');
269
- if (bodyLength !== reader.remaining) fail('Application payload body length mismatch.');
404
+ const reader = applicationPayloadReader(frame);
270
405
  reader.text8('packetName');
271
406
  reader.text8('contentType');
272
407
  const payloadLength = reader.u32('payloadLength');
@@ -450,19 +585,37 @@ export function decodeHeader(frame: Uint8Array): ServiceWireHeader {
450
585
  return { command: frame[3]!, flags: frame[4]! };
451
586
  }
452
587
 
588
+ /** Allocates a whole service wire record once and writes its prefix; the caller fills the body. */
589
+ function frame(command: number, bodyLength: number): Buffer {
590
+ const result = Buffer.allocUnsafe(PREFIX_SIZE + bodyLength);
591
+ result[0] = M6A_SERVICE_WIRE_MAGIC[0];
592
+ result[1] = M6A_SERVICE_WIRE_MAGIC[1];
593
+ result[2] = M6A_SERVICE_WIRE_MAJOR;
594
+ result[3] = command;
595
+ result[4] = 0;
596
+ return result;
597
+ }
598
+
453
599
  function prefix(command: number): Buffer {
454
- return Buffer.from([
455
- M6A_SERVICE_WIRE_MAGIC[0],
456
- M6A_SERVICE_WIRE_MAGIC[1],
457
- M6A_SERVICE_WIRE_MAJOR,
458
- command,
459
- 0
460
- ]);
600
+ return frame(command, 0);
461
601
  }
462
602
 
463
- function withU64(head: Buffer, value: bigint, field: string): Buffer {
464
- if (value <= 0n || value > MAX_U64) fail(`${field} must be a non-zero u64.`);
465
- return concat(head, encodeU64(value));
603
+ /** A record whose body starts with the non-zero u64 correlation, followed by `restLength` bytes. */
604
+ function withU64(command: number, correlation: bigint, restLength: number): Buffer {
605
+ if (correlation <= 0n || correlation > MAX_U64) fail('correlation must be a non-zero u64.');
606
+ const result = frame(command, 8 + restLength);
607
+ result.writeBigUInt64BE(correlation, PREFIX_SIZE);
608
+ return result;
609
+ }
610
+
611
+ /**
612
+ * Writes a validated text8 field — the byte length from
613
+ * canonicalServiceWireTextLength, then the UTF-8 text — and returns the next offset.
614
+ */
615
+ function writeText8(target: Buffer, offset: number, value: string, length: number): number {
616
+ target[offset] = length;
617
+ target.write(value, offset + 1, length, 'utf8');
618
+ return offset + 1 + length;
466
619
  }
467
620
 
468
621
  function encodeU16(value: number): Buffer {
@@ -487,7 +640,7 @@ function encodeU64(value: bigint): Buffer {
487
640
  }
488
641
 
489
642
  function encodeText8(value: string, field: string): Buffer {
490
- const bytes = encodeCanonicalServiceWireText(value, field, 0xff, fail);
643
+ const bytes = encodeCanonicalServiceWireText(value, field, SERVICE_WIRE_TEXT8_MAX_BYTES, fail);
491
644
  return concat(Buffer.of(bytes.byteLength), bytes);
492
645
  }
493
646
 
@@ -501,7 +654,7 @@ function tlv(id: number, value: Buffer): Buffer {
501
654
  }
502
655
 
503
656
  function concat(...parts: readonly Uint8Array[]): Buffer {
504
- return Buffer.concat(parts.map((part) => Buffer.from(part)));
657
+ return Buffer.concat(parts);
505
658
  }
506
659
 
507
660
  function readNonZeroU64(bytes: Buffer, offset: number, field: string): bigint {
@@ -511,7 +664,9 @@ function readNonZeroU64(bytes: Buffer, offset: number, field: string): bigint {
511
664
  }
512
665
 
513
666
  function asBuffer(value: Uint8Array): Buffer {
514
- return Buffer.from(value.buffer, value.byteOffset, value.byteLength);
667
+ return Buffer.isBuffer(value)
668
+ ? value
669
+ : Buffer.from(value.buffer, value.byteOffset, value.byteLength);
515
670
  }
516
671
 
517
672
  function validateAdmissionCommand(command: number): void {
@@ -633,13 +788,13 @@ class Reader {
633
788
  text8(field: string): string {
634
789
  const length = this.u8(`${field}.length`);
635
790
  if (length === 0) fail(`${field} must be non-empty.`);
636
- return decodeText(this.bytes(length, field), field);
791
+ return decodeText(this.view(length, field), field);
637
792
  }
638
793
 
639
794
  text16(field: string): string {
640
795
  const length = this.u16(`${field}.length`);
641
796
  if (length === 0 || length > SERVICE_ROUTE_TEXT_MAX_BYTES) fail(`${field} has invalid length.`);
642
- return decodeText(this.bytes(length, field), field);
797
+ return decodeText(this.view(length, field), field);
643
798
  }
644
799
 
645
800
  bytes(length: number, field: string): Buffer {
@@ -9,13 +9,10 @@ export interface ZLinkHandlerInstanceScope {
9
9
  }
10
10
 
11
11
  interface ZLinkHandlerInstanceScopeFactory {
12
+ prepare?(type: Type): void | (() => unknown);
12
13
  create(context?: ZLinkMessageContext): ZLinkHandlerInstanceScope;
13
14
  }
14
15
 
15
- interface ActiveHandlerScope {
16
- readonly scope: ZLinkHandlerInstanceScope;
17
- }
18
-
19
16
  interface Deferred<T> {
20
17
  readonly promise: Promise<T>;
21
18
  readonly resolve: (value: T) => void;
@@ -29,12 +26,37 @@ interface LifecycleScopeDisposal {
29
26
  }
30
27
 
31
28
  const HANDLER_SCOPE_FACTORY = Symbol.for('@zlink-systems/framework.handler-instance-scope-factory');
32
- const activeHandlerScope = new AsyncLocalStorage<ActiveHandlerScope>();
29
+ const activeHandlerScope = new AsyncLocalStorage<ZLinkHandlerInstanceScope>();
33
30
  const activeLifecycleScope = new AsyncLocalStorage<LifecycleHandlerInstanceScope>();
34
31
  const detachedLifecycleResource = new AsyncResource('zlink:handler-instance-scope');
35
32
  const dispatchScopes = new WeakMap<object, ZLinkHandlerInstanceScope>();
36
33
  const lifecycleScopes = new WeakMap<object, LifecycleHandlerInstanceScope>();
37
34
 
35
+ export function registerHandlerInstanceScopeFactory(
36
+ providerResolver: ZLinkProviderResolver,
37
+ factory: ZLinkHandlerInstanceScopeFactory
38
+ ): void {
39
+ Object.defineProperty(providerResolver, HANDLER_SCOPE_FACTORY, {
40
+ value: factory,
41
+ enumerable: false
42
+ });
43
+ }
44
+
45
+ export function prepareHandlerInstance<T>(
46
+ providerResolver: ZLinkProviderResolver | undefined,
47
+ type: Type<T>
48
+ ): (() => T) | undefined {
49
+ if (providerResolver === undefined) return () => new type();
50
+ const factory = (providerResolver as unknown as Record<PropertyKey, unknown>)[
51
+ HANDLER_SCOPE_FACTORY
52
+ ];
53
+ if (isHandlerInstanceScopeFactory(factory)) {
54
+ const activate = factory.prepare?.(type);
55
+ if (activate !== undefined) return activate as () => T;
56
+ }
57
+ return undefined;
58
+ }
59
+
38
60
  export async function runInHandlerInstanceScope<T>(
39
61
  providerResolver: ZLinkProviderResolver | undefined,
40
62
  context: ZLinkMessageContext | undefined,
@@ -42,7 +64,7 @@ export async function runInHandlerInstanceScope<T>(
42
64
  ): Promise<T> {
43
65
  const active = activeHandlerScope.getStore();
44
66
  if (active !== undefined) {
45
- return callback(active.scope);
67
+ return callback(active);
46
68
  }
47
69
  if (context !== undefined) {
48
70
  const existing = dispatchScopes.get(context);
@@ -56,7 +78,7 @@ export async function runInHandlerInstanceScope<T>(
56
78
  dispatchScopes.set(context, scope);
57
79
  }
58
80
  try {
59
- return await activeHandlerScope.run({ scope }, () => callback(scope));
81
+ return await activeHandlerScope.run(scope, () => callback(scope));
60
82
  } finally {
61
83
  if (context !== undefined && dispatchScopes.get(context) === scope) {
62
84
  dispatchScopes.delete(context);
@@ -144,14 +166,15 @@ class DefaultHandlerInstanceScope implements ZLinkHandlerInstanceScope {
144
166
  if (existing !== undefined) return existing;
145
167
  const activation = createDeferred<unknown>();
146
168
  this.instances.set(type, activation.promise);
147
- void this.activate(type, activation);
169
+ this.activate(type, activation);
148
170
  return activation.promise as Promise<T>;
149
171
  }
150
172
 
151
173
  async dispose(): Promise<void> {
152
174
  if (this.disposed) return;
153
175
  this.disposed = true;
154
- await Promise.allSettled(this.instances.values());
176
+ if (this.owned.length !== this.instances.size)
177
+ await Promise.allSettled(this.instances.values());
155
178
  try {
156
179
  await disposeOwnedInstances(this.owned);
157
180
  } finally {
@@ -159,21 +182,43 @@ class DefaultHandlerInstanceScope implements ZLinkHandlerInstanceScope {
159
182
  this.instances.clear();
160
183
  }
161
184
  }
162
- private async activate<T>(type: Type<T>, activation: Deferred<unknown>): Promise<void> {
163
- let instance: T;
185
+ private activate<T>(type: Type<T>, activation: Deferred<unknown>): void {
164
186
  try {
165
187
  const created = this.providerResolver?.create?.(type);
166
- instance = created === undefined ? new type() : await created;
188
+ if (created === undefined) {
189
+ this.completeActivation(new type(), activation);
190
+ } else {
191
+ void this.activatePending(created, activation);
192
+ }
167
193
  } catch (error) {
168
194
  activation.reject(error);
169
- return;
170
195
  }
196
+ }
171
197
 
198
+ private async activatePending<T>(
199
+ created: T | Promise<T>,
200
+ activation: Deferred<unknown>
201
+ ): Promise<void> {
202
+ try {
203
+ this.completeActivation(await created, activation);
204
+ } catch (error) {
205
+ activation.reject(error);
206
+ }
207
+ }
208
+
209
+ private completeActivation(instance: unknown, activation: Deferred<unknown>): void {
172
210
  if (!this.disposed) {
173
211
  this.owned.push(instance);
174
212
  activation.resolve(instance);
175
213
  return;
176
214
  }
215
+ void this.disposeLateActivation(instance, activation);
216
+ }
217
+
218
+ private async disposeLateActivation(
219
+ instance: unknown,
220
+ activation: Deferred<unknown>
221
+ ): Promise<void> {
177
222
  try {
178
223
  await disposeOwnedInstance(instance);
179
224
  activation.reject(new Error('Handler instance scope was disposed during activation.'));
@@ -306,6 +351,11 @@ function startOutsideLifecycleInvocation<T>(work: () => T): T {
306
351
  }
307
352
 
308
353
  export async function disposeOwnedInstance(instance: unknown): Promise<void> {
354
+ const cleanup = handlerInstanceCleanup(instance);
355
+ if (cleanup !== undefined) await cleanup.call(instance);
356
+ }
357
+
358
+ export function handlerInstanceCleanup(instance: unknown): (() => unknown) | undefined {
309
359
  if (instance === null || instance === undefined) return;
310
360
  const value = instance as {
311
361
  dispose?: () => unknown;
@@ -313,12 +363,13 @@ export async function disposeOwnedInstance(instance: unknown): Promise<void> {
313
363
  onModuleDestroy?: () => unknown;
314
364
  };
315
365
  if (typeof value.dispose === 'function') {
316
- await value.dispose();
366
+ return value.dispose;
317
367
  } else if (typeof value.close === 'function') {
318
- await value.close();
368
+ return value.close;
319
369
  } else if (typeof value.onModuleDestroy === 'function') {
320
- await value.onModuleDestroy();
370
+ return value.onModuleDestroy;
321
371
  }
372
+ return undefined;
322
373
  }
323
374
 
324
375
  export async function disposeOwnedInstances(instances: readonly unknown[]): Promise<void> {