reactor-effect-client 0.7.1 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (514) hide show
  1. package/NOTICE +7 -2
  2. package/README.md +103 -141
  3. package/dist/Coordinator.d.ts +382 -0
  4. package/dist/Coordinator.d.ts.map +1 -0
  5. package/dist/Coordinator.js +732 -0
  6. package/dist/Coordinator.js.map +1 -0
  7. package/dist/H3.d.ts +159 -0
  8. package/dist/H3.d.ts.map +1 -0
  9. package/dist/H3.js +21 -0
  10. package/dist/H3.js.map +1 -0
  11. package/dist/H3Source.d.ts +93 -0
  12. package/dist/H3Source.d.ts.map +1 -0
  13. package/dist/H3Source.js +401 -0
  14. package/dist/H3Source.js.map +1 -0
  15. package/dist/LocalSource.d.ts +68 -0
  16. package/dist/LocalSource.d.ts.map +1 -0
  17. package/dist/LocalSource.js +354 -0
  18. package/dist/LocalSource.js.map +1 -0
  19. package/dist/Media.d.ts +106 -0
  20. package/dist/Media.d.ts.map +1 -0
  21. package/dist/Media.js +16 -0
  22. package/dist/Media.js.map +1 -0
  23. package/dist/Peer.d.ts +134 -0
  24. package/dist/Peer.d.ts.map +1 -0
  25. package/dist/Peer.js +57 -0
  26. package/dist/Peer.js.map +1 -0
  27. package/dist/Playout.d.ts +724 -0
  28. package/dist/Playout.d.ts.map +1 -0
  29. package/dist/Playout.js +28 -0
  30. package/dist/Playout.js.map +1 -0
  31. package/dist/Reactor.d.ts +135 -0
  32. package/dist/Reactor.d.ts.map +1 -0
  33. package/dist/Reactor.js +158 -0
  34. package/dist/Reactor.js.map +1 -0
  35. package/dist/ReactorError.d.ts +331 -0
  36. package/dist/ReactorError.d.ts.map +1 -0
  37. package/dist/ReactorError.js +316 -0
  38. package/dist/ReactorError.js.map +1 -0
  39. package/dist/ReactorTest.d.ts +383 -0
  40. package/dist/ReactorTest.d.ts.map +1 -0
  41. package/dist/ReactorTest.js +317 -0
  42. package/dist/ReactorTest.js.map +1 -0
  43. package/dist/Session.d.ts +314 -0
  44. package/dist/Session.d.ts.map +1 -0
  45. package/dist/Session.js +51 -0
  46. package/dist/Session.js.map +1 -0
  47. package/dist/index.d.ts +12 -22
  48. package/dist/index.d.ts.map +1 -1
  49. package/dist/index.js +12 -11
  50. package/dist/index.js.map +1 -1
  51. package/dist/internal/correlator.d.ts +46 -0
  52. package/dist/internal/correlator.d.ts.map +1 -0
  53. package/dist/internal/correlator.js +150 -0
  54. package/dist/internal/correlator.js.map +1 -0
  55. package/dist/internal/deadline.d.ts +24 -0
  56. package/dist/internal/deadline.d.ts.map +1 -0
  57. package/dist/internal/deadline.js +44 -0
  58. package/dist/internal/deadline.js.map +1 -0
  59. package/dist/{h3/_internal/contracts.d.ts → internal/h3/commands.d.ts} +39 -33
  60. package/dist/internal/h3/commands.d.ts.map +1 -0
  61. package/dist/internal/h3/commands.js +128 -0
  62. package/dist/internal/h3/commands.js.map +1 -0
  63. package/dist/{h3 → internal/h3}/messages.d.ts +16 -11
  64. package/dist/internal/h3/messages.d.ts.map +1 -0
  65. package/dist/{h3 → internal/h3}/messages.js +19 -31
  66. package/dist/internal/h3/messages.js.map +1 -0
  67. package/dist/internal/h3/operations.d.ts +145 -0
  68. package/dist/internal/h3/operations.d.ts.map +1 -0
  69. package/dist/internal/h3/operations.js +284 -0
  70. package/dist/internal/h3/operations.js.map +1 -0
  71. package/dist/{h3 → internal/h3}/profile.d.ts +63 -65
  72. package/dist/internal/h3/profile.d.ts.map +1 -0
  73. package/dist/{h3 → internal/h3}/profile.js +39 -39
  74. package/dist/internal/h3/profile.js.map +1 -0
  75. package/dist/internal/h3/provider.d.ts +14 -0
  76. package/dist/internal/h3/provider.d.ts.map +1 -0
  77. package/dist/internal/h3/provider.js +672 -0
  78. package/dist/internal/h3/provider.js.map +1 -0
  79. package/dist/internal/h3/references.d.ts +68 -0
  80. package/dist/internal/h3/references.d.ts.map +1 -0
  81. package/dist/internal/h3/references.js +339 -0
  82. package/dist/internal/h3/references.js.map +1 -0
  83. package/dist/internal/h3/request.d.ts +56 -0
  84. package/dist/internal/h3/request.d.ts.map +1 -0
  85. package/dist/internal/h3/request.js +70 -0
  86. package/dist/internal/h3/request.js.map +1 -0
  87. package/dist/internal/h3/state.d.ts +120 -0
  88. package/dist/internal/h3/state.d.ts.map +1 -0
  89. package/dist/internal/h3/state.js +270 -0
  90. package/dist/internal/h3/state.js.map +1 -0
  91. package/dist/{Submission.d.ts → internal/h3/submission.d.ts} +1 -3
  92. package/dist/internal/h3/submission.d.ts.map +1 -0
  93. package/dist/{Submission.js → internal/h3/submission.js} +1 -9
  94. package/dist/internal/h3/submission.js.map +1 -0
  95. package/dist/internal/hub.d.ts +32 -0
  96. package/dist/internal/hub.d.ts.map +1 -0
  97. package/dist/internal/hub.js +92 -0
  98. package/dist/internal/hub.js.map +1 -0
  99. package/dist/internal/playout/errors.d.ts +51 -0
  100. package/dist/internal/playout/errors.d.ts.map +1 -0
  101. package/dist/internal/playout/errors.js +40 -0
  102. package/dist/internal/playout/errors.js.map +1 -0
  103. package/dist/internal/playout/policy.d.ts +559 -0
  104. package/dist/internal/playout/policy.d.ts.map +1 -0
  105. package/dist/internal/playout/policy.js +2338 -0
  106. package/dist/internal/playout/policy.js.map +1 -0
  107. package/dist/internal/playout/runtime.d.ts +28 -0
  108. package/dist/internal/playout/runtime.d.ts.map +1 -0
  109. package/dist/internal/playout/runtime.js +766 -0
  110. package/dist/internal/playout/runtime.js.map +1 -0
  111. package/dist/internal/playout/tag.d.ts +14 -0
  112. package/dist/internal/playout/tag.d.ts.map +1 -0
  113. package/dist/internal/playout/tag.js +43 -0
  114. package/dist/internal/playout/tag.js.map +1 -0
  115. package/dist/internal/proto/reactor_wire/v1/common_pb.d.ts +55 -0
  116. package/dist/internal/proto/reactor_wire/v1/common_pb.d.ts.map +1 -0
  117. package/dist/internal/proto/reactor_wire/v1/common_pb.js +42 -0
  118. package/dist/internal/proto/reactor_wire/v1/common_pb.js.map +1 -0
  119. package/dist/internal/proto/reactor_wire/v1/control_pb.d.ts +160 -0
  120. package/dist/internal/proto/reactor_wire/v1/control_pb.d.ts.map +1 -0
  121. package/dist/internal/proto/reactor_wire/v1/control_pb.js +21 -0
  122. package/dist/internal/proto/reactor_wire/v1/control_pb.js.map +1 -0
  123. package/dist/internal/proto/reactor_wire/v1/data_pb.d.ts +89 -0
  124. package/dist/internal/proto/reactor_wire/v1/data_pb.d.ts.map +1 -0
  125. package/dist/internal/proto/reactor_wire/v1/data_pb.js +20 -0
  126. package/dist/internal/proto/reactor_wire/v1/data_pb.js.map +1 -0
  127. package/dist/internal/proto/reactor_wire/v1/model_pb.d.ts +85 -0
  128. package/dist/internal/proto/reactor_wire/v1/model_pb.d.ts.map +1 -0
  129. package/dist/internal/proto/reactor_wire/v1/model_pb.js +24 -0
  130. package/dist/internal/proto/reactor_wire/v1/model_pb.js.map +1 -0
  131. package/dist/internal/proto/reactor_wire/v1/platform_pb.d.ts +190 -0
  132. package/dist/internal/proto/reactor_wire/v1/platform_pb.d.ts.map +1 -0
  133. package/dist/internal/proto/reactor_wire/v1/platform_pb.js +54 -0
  134. package/dist/internal/proto/reactor_wire/v1/platform_pb.js.map +1 -0
  135. package/dist/internal/proto/reactor_wire/v1/track_pb.d.ts +88 -0
  136. package/dist/internal/proto/reactor_wire/v1/track_pb.d.ts.map +1 -0
  137. package/dist/internal/proto/reactor_wire/v1/track_pb.js +33 -0
  138. package/dist/internal/proto/reactor_wire/v1/track_pb.js.map +1 -0
  139. package/dist/internal/queue.d.ts +4 -0
  140. package/dist/internal/queue.d.ts.map +1 -0
  141. package/dist/{_internal → internal}/queue.js +0 -9
  142. package/dist/internal/queue.js.map +1 -0
  143. package/dist/internal/reactorTest/coordinator.d.ts +5 -0
  144. package/dist/internal/reactorTest/coordinator.d.ts.map +1 -0
  145. package/dist/internal/reactorTest/coordinator.js +178 -0
  146. package/dist/internal/reactorTest/coordinator.js.map +1 -0
  147. package/dist/internal/reactorTest/faults.d.ts +172 -0
  148. package/dist/internal/reactorTest/faults.d.ts.map +1 -0
  149. package/dist/internal/reactorTest/faults.js +23 -0
  150. package/dist/internal/reactorTest/faults.js.map +1 -0
  151. package/dist/internal/reactorTest/h3.d.ts +431 -0
  152. package/dist/internal/reactorTest/h3.d.ts.map +1 -0
  153. package/dist/internal/reactorTest/h3.js +625 -0
  154. package/dist/internal/reactorTest/h3.js.map +1 -0
  155. package/dist/internal/reactorTest/media.d.ts +22 -0
  156. package/dist/internal/reactorTest/media.d.ts.map +1 -0
  157. package/dist/internal/reactorTest/media.js +34 -0
  158. package/dist/internal/reactorTest/media.js.map +1 -0
  159. package/dist/internal/reactorTest/peer.d.ts +318 -0
  160. package/dist/internal/reactorTest/peer.d.ts.map +1 -0
  161. package/dist/internal/reactorTest/peer.js +206 -0
  162. package/dist/internal/reactorTest/peer.js.map +1 -0
  163. package/dist/internal/reactorTest/playout.d.ts +34 -0
  164. package/dist/internal/reactorTest/playout.d.ts.map +1 -0
  165. package/dist/internal/reactorTest/playout.js +340 -0
  166. package/dist/internal/reactorTest/playout.js.map +1 -0
  167. package/dist/internal/reactorTest/references.d.ts +25 -0
  168. package/dist/internal/reactorTest/references.d.ts.map +1 -0
  169. package/dist/{testing/Png.js → internal/reactorTest/references.js} +50 -12
  170. package/dist/internal/reactorTest/references.js.map +1 -0
  171. package/dist/internal/reactorTest/sessions.d.ts +364 -0
  172. package/dist/internal/reactorTest/sessions.d.ts.map +1 -0
  173. package/dist/internal/reactorTest/sessions.js +592 -0
  174. package/dist/internal/reactorTest/sessions.js.map +1 -0
  175. package/dist/internal/reactorTest/timing.d.ts +13 -0
  176. package/dist/internal/reactorTest/timing.d.ts.map +1 -0
  177. package/dist/internal/reactorTest/timing.js +20 -0
  178. package/dist/internal/reactorTest/timing.js.map +1 -0
  179. package/dist/internal/recording.d.ts +52 -0
  180. package/dist/internal/recording.d.ts.map +1 -0
  181. package/dist/internal/recording.js +141 -0
  182. package/dist/internal/recording.js.map +1 -0
  183. package/dist/internal/session/connect.d.ts +34 -0
  184. package/dist/internal/session/connect.d.ts.map +1 -0
  185. package/dist/internal/session/connect.js +502 -0
  186. package/dist/internal/session/connect.js.map +1 -0
  187. package/dist/internal/session/generation.d.ts +35 -0
  188. package/dist/internal/session/generation.d.ts.map +1 -0
  189. package/dist/internal/session/generation.js +185 -0
  190. package/dist/internal/session/generation.js.map +1 -0
  191. package/dist/internal/session/ice.d.ts +23 -0
  192. package/dist/internal/session/ice.d.ts.map +1 -0
  193. package/dist/internal/session/ice.js +57 -0
  194. package/dist/internal/session/ice.js.map +1 -0
  195. package/dist/internal/session/inbound.d.ts +50 -0
  196. package/dist/internal/session/inbound.d.ts.map +1 -0
  197. package/dist/internal/session/inbound.js +202 -0
  198. package/dist/internal/session/inbound.js.map +1 -0
  199. package/dist/internal/session/model.d.ts +163 -0
  200. package/dist/internal/session/model.d.ts.map +1 -0
  201. package/dist/internal/session/model.js +78 -0
  202. package/dist/internal/session/model.js.map +1 -0
  203. package/dist/internal/session/requests.d.ts +71 -0
  204. package/dist/internal/session/requests.d.ts.map +1 -0
  205. package/dist/internal/session/requests.js +240 -0
  206. package/dist/internal/session/requests.js.map +1 -0
  207. package/dist/internal/session/tracks.d.ts +21 -0
  208. package/dist/internal/session/tracks.d.ts.map +1 -0
  209. package/dist/internal/session/tracks.js +166 -0
  210. package/dist/internal/session/tracks.js.map +1 -0
  211. package/dist/internal/session/upload.d.ts +21 -0
  212. package/dist/internal/session/upload.d.ts.map +1 -0
  213. package/dist/internal/session/upload.js +68 -0
  214. package/dist/internal/session/upload.js.map +1 -0
  215. package/dist/internal/session.d.ts +66 -0
  216. package/dist/internal/session.d.ts.map +1 -0
  217. package/dist/internal/session.js +280 -0
  218. package/dist/internal/session.js.map +1 -0
  219. package/dist/{stats.d.ts → internal/stats.d.ts} +30 -16
  220. package/dist/internal/stats.d.ts.map +1 -0
  221. package/dist/internal/stats.js +201 -0
  222. package/dist/internal/stats.js.map +1 -0
  223. package/dist/internal/token.d.ts +22 -0
  224. package/dist/internal/token.d.ts.map +1 -0
  225. package/dist/internal/token.js +65 -0
  226. package/dist/internal/token.js.map +1 -0
  227. package/dist/internal/wire.d.ts +37 -0
  228. package/dist/internal/wire.d.ts.map +1 -0
  229. package/dist/internal/wire.js +49 -0
  230. package/dist/internal/wire.js.map +1 -0
  231. package/notices/bufbuild-protobuf-LICENSE +201 -0
  232. package/package.json +17 -38
  233. package/dist/FetchHttp.d.ts +0 -9
  234. package/dist/FetchHttp.d.ts.map +0 -1
  235. package/dist/FetchHttp.js +0 -63
  236. package/dist/FetchHttp.js.map +0 -1
  237. package/dist/PeerFactory.d.ts +0 -26
  238. package/dist/PeerFactory.d.ts.map +0 -1
  239. package/dist/PeerFactory.js +0 -4
  240. package/dist/PeerFactory.js.map +0 -1
  241. package/dist/PeerTypes.d.ts +0 -64
  242. package/dist/PeerTypes.d.ts.map +0 -1
  243. package/dist/PeerTypes.js +0 -2
  244. package/dist/PeerTypes.js.map +0 -1
  245. package/dist/Sequence.d.ts +0 -85
  246. package/dist/Sequence.d.ts.map +0 -1
  247. package/dist/Sequence.js +0 -210
  248. package/dist/Sequence.js.map +0 -1
  249. package/dist/SessionTypes.d.ts +0 -312
  250. package/dist/SessionTypes.d.ts.map +0 -1
  251. package/dist/SessionTypes.js +0 -19
  252. package/dist/SessionTypes.js.map +0 -1
  253. package/dist/Submission.d.ts.map +0 -1
  254. package/dist/Submission.js.map +0 -1
  255. package/dist/_internal/queue.d.ts +0 -6
  256. package/dist/_internal/queue.d.ts.map +0 -1
  257. package/dist/_internal/queue.js.map +0 -1
  258. package/dist/bytes.d.ts +0 -6
  259. package/dist/bytes.d.ts.map +0 -1
  260. package/dist/bytes.js +0 -32
  261. package/dist/bytes.js.map +0 -1
  262. package/dist/contract.d.ts +0 -149
  263. package/dist/contract.d.ts.map +0 -1
  264. package/dist/contract.js +0 -119
  265. package/dist/contract.js.map +0 -1
  266. package/dist/coordinator/_internal/client.d.ts +0 -215
  267. package/dist/coordinator/_internal/client.d.ts.map +0 -1
  268. package/dist/coordinator/_internal/client.js +0 -563
  269. package/dist/coordinator/_internal/client.js.map +0 -1
  270. package/dist/coordinator/_internal/recording.d.ts +0 -31
  271. package/dist/coordinator/_internal/recording.d.ts.map +0 -1
  272. package/dist/coordinator/_internal/recording.js +0 -123
  273. package/dist/coordinator/_internal/recording.js.map +0 -1
  274. package/dist/coordinator/_internal/response.d.ts +0 -15
  275. package/dist/coordinator/_internal/response.d.ts.map +0 -1
  276. package/dist/coordinator/_internal/response.js +0 -55
  277. package/dist/coordinator/_internal/response.js.map +0 -1
  278. package/dist/coordinator/_internal/schemas.d.ts +0 -73
  279. package/dist/coordinator/_internal/schemas.d.ts.map +0 -1
  280. package/dist/coordinator/_internal/schemas.js +0 -200
  281. package/dist/coordinator/_internal/schemas.js.map +0 -1
  282. package/dist/coordinator/index.d.ts +0 -40
  283. package/dist/coordinator/index.d.ts.map +0 -1
  284. package/dist/coordinator/index.js +0 -21
  285. package/dist/coordinator/index.js.map +0 -1
  286. package/dist/correlation.d.ts +0 -47
  287. package/dist/correlation.d.ts.map +0 -1
  288. package/dist/correlation.js +0 -131
  289. package/dist/correlation.js.map +0 -1
  290. package/dist/duration.d.ts +0 -27
  291. package/dist/duration.d.ts.map +0 -1
  292. package/dist/duration.js +0 -47
  293. package/dist/duration.js.map +0 -1
  294. package/dist/errors.d.ts +0 -1303
  295. package/dist/errors.d.ts.map +0 -1
  296. package/dist/errors.js +0 -745
  297. package/dist/errors.js.map +0 -1
  298. package/dist/h3/_internal/client.d.ts +0 -9
  299. package/dist/h3/_internal/client.d.ts.map +0 -1
  300. package/dist/h3/_internal/client.js +0 -652
  301. package/dist/h3/_internal/client.js.map +0 -1
  302. package/dist/h3/_internal/contracts.d.ts.map +0 -1
  303. package/dist/h3/_internal/contracts.js +0 -123
  304. package/dist/h3/_internal/contracts.js.map +0 -1
  305. package/dist/h3/_internal/deployment.d.ts +0 -8
  306. package/dist/h3/_internal/deployment.d.ts.map +0 -1
  307. package/dist/h3/_internal/deployment.js +0 -149
  308. package/dist/h3/_internal/deployment.js.map +0 -1
  309. package/dist/h3/_internal/evidence.d.ts +0 -17
  310. package/dist/h3/_internal/evidence.d.ts.map +0 -1
  311. package/dist/h3/_internal/evidence.js +0 -48
  312. package/dist/h3/_internal/evidence.js.map +0 -1
  313. package/dist/h3/_internal/operations.d.ts +0 -58
  314. package/dist/h3/_internal/operations.d.ts.map +0 -1
  315. package/dist/h3/_internal/operations.js +0 -268
  316. package/dist/h3/_internal/operations.js.map +0 -1
  317. package/dist/h3/_internal/references.d.ts +0 -24
  318. package/dist/h3/_internal/references.d.ts.map +0 -1
  319. package/dist/h3/_internal/references.js +0 -309
  320. package/dist/h3/_internal/references.js.map +0 -1
  321. package/dist/h3/_internal/request.d.ts +0 -21
  322. package/dist/h3/_internal/request.d.ts.map +0 -1
  323. package/dist/h3/_internal/request.js +0 -97
  324. package/dist/h3/_internal/request.js.map +0 -1
  325. package/dist/h3/_internal/retained.d.ts +0 -22
  326. package/dist/h3/_internal/retained.d.ts.map +0 -1
  327. package/dist/h3/_internal/retained.js +0 -89
  328. package/dist/h3/_internal/retained.js.map +0 -1
  329. package/dist/h3/_internal/state.d.ts +0 -44
  330. package/dist/h3/_internal/state.d.ts.map +0 -1
  331. package/dist/h3/_internal/state.js +0 -283
  332. package/dist/h3/_internal/state.js.map +0 -1
  333. package/dist/h3/index.d.ts +0 -10
  334. package/dist/h3/index.d.ts.map +0 -1
  335. package/dist/h3/index.js +0 -7
  336. package/dist/h3/index.js.map +0 -1
  337. package/dist/h3/messages.d.ts.map +0 -1
  338. package/dist/h3/messages.js.map +0 -1
  339. package/dist/h3/profile.d.ts.map +0 -1
  340. package/dist/h3/profile.js.map +0 -1
  341. package/dist/h3/types.d.ts +0 -291
  342. package/dist/h3/types.d.ts.map +0 -1
  343. package/dist/h3/types.js +0 -2
  344. package/dist/h3/types.js.map +0 -1
  345. package/dist/host.d.ts +0 -26
  346. package/dist/host.d.ts.map +0 -1
  347. package/dist/host.js +0 -20
  348. package/dist/host.js.map +0 -1
  349. package/dist/json.d.ts +0 -25
  350. package/dist/json.d.ts.map +0 -1
  351. package/dist/json.js +0 -143
  352. package/dist/json.js.map +0 -1
  353. package/dist/media-stream.d.ts +0 -10
  354. package/dist/media-stream.d.ts.map +0 -1
  355. package/dist/media-stream.js +0 -18
  356. package/dist/media-stream.js.map +0 -1
  357. package/dist/observation.d.ts +0 -38
  358. package/dist/observation.d.ts.map +0 -1
  359. package/dist/observation.js +0 -113
  360. package/dist/observation.js.map +0 -1
  361. package/dist/orchestration/elapsed.d.ts +0 -9
  362. package/dist/orchestration/elapsed.d.ts.map +0 -1
  363. package/dist/orchestration/elapsed.js +0 -8
  364. package/dist/orchestration/elapsed.js.map +0 -1
  365. package/dist/orchestration/h3-source.d.ts +0 -58
  366. package/dist/orchestration/h3-source.d.ts.map +0 -1
  367. package/dist/orchestration/h3-source.js +0 -362
  368. package/dist/orchestration/h3-source.js.map +0 -1
  369. package/dist/orchestration/index.d.ts +0 -17
  370. package/dist/orchestration/index.d.ts.map +0 -1
  371. package/dist/orchestration/index.js +0 -12
  372. package/dist/orchestration/index.js.map +0 -1
  373. package/dist/orchestration/media-buffer.d.ts +0 -32
  374. package/dist/orchestration/media-buffer.d.ts.map +0 -1
  375. package/dist/orchestration/media-buffer.js +0 -94
  376. package/dist/orchestration/media-buffer.js.map +0 -1
  377. package/dist/orchestration/open-h3.d.ts +0 -101
  378. package/dist/orchestration/open-h3.d.ts.map +0 -1
  379. package/dist/orchestration/open-h3.js +0 -127
  380. package/dist/orchestration/open-h3.js.map +0 -1
  381. package/dist/orchestration/queries.d.ts +0 -10
  382. package/dist/orchestration/queries.d.ts.map +0 -1
  383. package/dist/orchestration/queries.js +0 -43
  384. package/dist/orchestration/queries.js.map +0 -1
  385. package/dist/orchestration/references.d.ts +0 -18
  386. package/dist/orchestration/references.d.ts.map +0 -1
  387. package/dist/orchestration/references.js +0 -79
  388. package/dist/orchestration/references.js.map +0 -1
  389. package/dist/orchestration/renewal-state.d.ts +0 -84
  390. package/dist/orchestration/renewal-state.d.ts.map +0 -1
  391. package/dist/orchestration/renewal-state.js +0 -95
  392. package/dist/orchestration/renewal-state.js.map +0 -1
  393. package/dist/orchestration/renewal.d.ts +0 -103
  394. package/dist/orchestration/renewal.d.ts.map +0 -1
  395. package/dist/orchestration/renewal.js +0 -1099
  396. package/dist/orchestration/renewal.js.map +0 -1
  397. package/dist/orchestration/request.d.ts +0 -65
  398. package/dist/orchestration/request.d.ts.map +0 -1
  399. package/dist/orchestration/request.js +0 -134
  400. package/dist/orchestration/request.js.map +0 -1
  401. package/dist/orchestration/retention.d.ts +0 -100
  402. package/dist/orchestration/retention.d.ts.map +0 -1
  403. package/dist/orchestration/retention.js +0 -134
  404. package/dist/orchestration/retention.js.map +0 -1
  405. package/dist/orchestration/routing.d.ts +0 -21
  406. package/dist/orchestration/routing.d.ts.map +0 -1
  407. package/dist/orchestration/routing.js +0 -93
  408. package/dist/orchestration/routing.js.map +0 -1
  409. package/dist/orchestration/scheduler-key.d.ts +0 -14
  410. package/dist/orchestration/scheduler-key.d.ts.map +0 -1
  411. package/dist/orchestration/scheduler-key.js +0 -62
  412. package/dist/orchestration/scheduler-key.js.map +0 -1
  413. package/dist/orchestration/scheduler-policy.d.ts +0 -246
  414. package/dist/orchestration/scheduler-policy.d.ts.map +0 -1
  415. package/dist/orchestration/scheduler-policy.js +0 -668
  416. package/dist/orchestration/scheduler-policy.js.map +0 -1
  417. package/dist/orchestration/scheduler.d.ts +0 -393
  418. package/dist/orchestration/scheduler.d.ts.map +0 -1
  419. package/dist/orchestration/scheduler.js +0 -2621
  420. package/dist/orchestration/scheduler.js.map +0 -1
  421. package/dist/orchestration/source-slot.d.ts +0 -124
  422. package/dist/orchestration/source-slot.d.ts.map +0 -1
  423. package/dist/orchestration/source-slot.js +0 -348
  424. package/dist/orchestration/source-slot.js.map +0 -1
  425. package/dist/orchestration/types.d.ts +0 -1462
  426. package/dist/orchestration/types.d.ts.map +0 -1
  427. package/dist/orchestration/types.js +0 -135
  428. package/dist/orchestration/types.js.map +0 -1
  429. package/dist/protobuf.d.ts +0 -63
  430. package/dist/protobuf.d.ts.map +0 -1
  431. package/dist/protobuf.js +0 -252
  432. package/dist/protobuf.js.map +0 -1
  433. package/dist/session/_internal/acquire.d.ts +0 -21
  434. package/dist/session/_internal/acquire.d.ts.map +0 -1
  435. package/dist/session/_internal/acquire.js +0 -168
  436. package/dist/session/_internal/acquire.js.map +0 -1
  437. package/dist/session/_internal/cleanup.d.ts +0 -19
  438. package/dist/session/_internal/cleanup.d.ts.map +0 -1
  439. package/dist/session/_internal/cleanup.js +0 -102
  440. package/dist/session/_internal/cleanup.js.map +0 -1
  441. package/dist/session/_internal/lifecycle.d.ts +0 -67
  442. package/dist/session/_internal/lifecycle.d.ts.map +0 -1
  443. package/dist/session/_internal/lifecycle.js +0 -142
  444. package/dist/session/_internal/lifecycle.js.map +0 -1
  445. package/dist/session/_internal/remote.d.ts +0 -28
  446. package/dist/session/_internal/remote.d.ts.map +0 -1
  447. package/dist/session/_internal/remote.js +0 -71
  448. package/dist/session/_internal/remote.js.map +0 -1
  449. package/dist/session/_internal/uploads.d.ts +0 -7
  450. package/dist/session/_internal/uploads.d.ts.map +0 -1
  451. package/dist/session/_internal/uploads.js +0 -31
  452. package/dist/session/_internal/uploads.js.map +0 -1
  453. package/dist/session/commands.d.ts +0 -2
  454. package/dist/session/commands.d.ts.map +0 -1
  455. package/dist/session/commands.js +0 -2
  456. package/dist/session/commands.js.map +0 -1
  457. package/dist/session/files.d.ts +0 -21
  458. package/dist/session/files.d.ts.map +0 -1
  459. package/dist/session/files.js +0 -49
  460. package/dist/session/files.js.map +0 -1
  461. package/dist/session/index.d.ts +0 -84
  462. package/dist/session/index.d.ts.map +0 -1
  463. package/dist/session/index.js +0 -16
  464. package/dist/session/index.js.map +0 -1
  465. package/dist/session/media.d.ts +0 -114
  466. package/dist/session/media.d.ts.map +0 -1
  467. package/dist/session/media.js +0 -2
  468. package/dist/session/media.js.map +0 -1
  469. package/dist/session/recorder.d.ts +0 -24
  470. package/dist/session/recorder.d.ts.map +0 -1
  471. package/dist/session/recorder.js +0 -19
  472. package/dist/session/recorder.js.map +0 -1
  473. package/dist/session.d.ts +0 -105
  474. package/dist/session.d.ts.map +0 -1
  475. package/dist/session.js +0 -976
  476. package/dist/session.js.map +0 -1
  477. package/dist/simulation/_internal/source.d.ts +0 -12
  478. package/dist/simulation/_internal/source.d.ts.map +0 -1
  479. package/dist/simulation/_internal/source.js +0 -513
  480. package/dist/simulation/_internal/source.js.map +0 -1
  481. package/dist/simulation/index.d.ts +0 -13
  482. package/dist/simulation/index.d.ts.map +0 -1
  483. package/dist/simulation/index.js +0 -12
  484. package/dist/simulation/index.js.map +0 -1
  485. package/dist/simulation/types.d.ts +0 -39
  486. package/dist/simulation/types.d.ts.map +0 -1
  487. package/dist/simulation/types.js +0 -2
  488. package/dist/simulation/types.js.map +0 -1
  489. package/dist/stats.d.ts.map +0 -1
  490. package/dist/stats.js +0 -205
  491. package/dist/stats.js.map +0 -1
  492. package/dist/testing/Faults.d.ts +0 -4
  493. package/dist/testing/Faults.d.ts.map +0 -1
  494. package/dist/testing/Faults.js +0 -7
  495. package/dist/testing/Faults.js.map +0 -1
  496. package/dist/testing/Png.d.ts +0 -3
  497. package/dist/testing/Png.d.ts.map +0 -1
  498. package/dist/testing/Png.js.map +0 -1
  499. package/dist/testing/Wav.d.ts +0 -14
  500. package/dist/testing/Wav.d.ts.map +0 -1
  501. package/dist/testing/Wav.js +0 -37
  502. package/dist/testing/Wav.js.map +0 -1
  503. package/dist/testing/index.d.ts +0 -5
  504. package/dist/testing/index.d.ts.map +0 -1
  505. package/dist/testing/index.js +0 -4
  506. package/dist/testing/index.js.map +0 -1
  507. package/dist/wire.d.ts +0 -7
  508. package/dist/wire.d.ts.map +0 -1
  509. package/dist/wire.generated.d.ts +0 -305
  510. package/dist/wire.generated.d.ts.map +0 -1
  511. package/dist/wire.generated.js +0 -1257
  512. package/dist/wire.generated.js.map +0 -1
  513. package/dist/wire.js +0 -5
  514. package/dist/wire.js.map +0 -1
package/dist/session.js DELETED
@@ -1,976 +0,0 @@
1
- import * as Effect from "effect/Effect";
2
- import * as Deferred from "effect/Deferred";
3
- import * as Fiber from "effect/Fiber";
4
- import * as Scope from "effect/Scope";
5
- import * as Exit from "effect/Exit";
6
- import * as Queue from "effect/Queue";
7
- import * as Cause from "effect/Cause";
8
- import * as Clock from "effect/Clock";
9
- import * as Duration from "effect/Duration";
10
- import * as Stream from "effect/Stream";
11
- import { take as takeQueue } from "./_internal/queue.js";
12
- import { duration } from "./duration.js";
13
- import { parsed, parsedInput, positiveLimit, ReactorError, Remote } from "./errors.js";
14
- import { nonempty, uint32, structFromObject, objectFromStruct } from "./json.js";
15
- import { CoordinatorClient, terminationAttributes } from "./coordinator/_internal/client.js";
16
- import { Correlator } from "./correlation.js";
17
- import { Observations } from "./observation.js";
18
- import * as W from "./wire.generated.js";
19
- import { StatsSampler } from "./stats.js";
20
- import { CommandFailure } from "./session/commands.js";
21
- import { captureUploads } from "./session/_internal/uploads.js";
22
- import { SessionLifecycle } from "./session/_internal/lifecycle.js";
23
- import { isKnownRemote, RemoteSession } from "./session/_internal/remote.js";
24
- import { cleanupSession } from "./session/_internal/cleanup.js";
25
- /** A provider error reply: its code routes, its text stays in `body` for inspection. */
26
- const remoteError = (value, context) => new ReactorError({
27
- reason: new Remote({
28
- _tag: "Remote",
29
- message: `remote command error ${value.code}`,
30
- remoteCode: value.code,
31
- body: value.message,
32
- }),
33
- context,
34
- });
35
- const pure = (body) => parsed(body);
36
- /** Mark a connect phase on the current span, as SqlClient marks a transaction's. */
37
- const phase = (name) => Effect.currentSpan.pipe(Effect.flatMap((span) => Clock.currentTimeNanos.pipe(Effect.map((now) => span.event(`reactor.connect.${name}`, now)))), Effect.ignore);
38
- const replyTimeout = (input) => duration(input, "reply timeout", { maximum: "10 minutes" });
39
- const uploadTimeout = (input) => duration(input, "upload timeout", { maximum: "10 minutes" });
40
- const withDeadline = (effect, deadline, operation) => effect.pipe(Effect.timeoutOrElse({
41
- duration: deadline,
42
- orElse: () => Effect.fail(ReactorError.fromCode("Timeout", `${operation}: deadline`)),
43
- }));
44
- /** The canonical Reactor state and wire engine for both public host exports.
45
- * Platform and peer dependencies are supplied by the configured client factory. */
46
- export class Session {
47
- options;
48
- makePeer;
49
- lifecycle = new SessionLifecycle((status) => this.emit({ _tag: "Status", status }));
50
- remote = new RemoteSession();
51
- data;
52
- control;
53
- observations = new Observations();
54
- sequence = 0n;
55
- sampler = new StatsSampler();
56
- closeGate;
57
- closeReport;
58
- received = new Set();
59
- bitrates = new Map();
60
- replyTimeout;
61
- uploadTimeout;
62
- connectTimeout;
63
- readyTimeout;
64
- heartbeat;
65
- uploadBound;
66
- http;
67
- constructor(options, makePeer, http) {
68
- this.options = options;
69
- this.makePeer = makePeer;
70
- if (options.intent._tag === "Attach") {
71
- nonempty(options.intent.sessionId, "attach sessionId");
72
- if (options.intent.connectionId !== undefined)
73
- uint32(options.intent.connectionId, "attach connectionId");
74
- }
75
- else
76
- nonempty(options.intent.model.name, "model name");
77
- this.http = http;
78
- this.replyTimeout = replyTimeout(options.replyTimeout ?? "10 seconds");
79
- this.uploadTimeout = uploadTimeout(options.uploadTimeout ?? "60 seconds");
80
- this.connectTimeout = duration(options.connectTimeout ?? "3 minutes", "connect timeout", {
81
- maximum: "10 minutes",
82
- });
83
- this.readyTimeout = duration(options.readyTimeout ?? "30 seconds", "ready timeout", {
84
- maximum: "10 minutes",
85
- });
86
- this.heartbeat = duration(options.heartbeatInterval ?? "10 seconds", "heartbeat interval", {
87
- maximum: "10 minutes",
88
- allowInfinite: true,
89
- });
90
- this.uploadBound = positiveLimit(options.maxUploadBytes ?? 16_777_216, "upload byte bound", 64 * 1024 * 1024);
91
- this.data = new Correlator("data", options.maxPending ?? 128, options.requestNamespace);
92
- this.control = new Correlator("ctrl", options.maxPending ?? 128, options.requestNamespace);
93
- }
94
- get snapshot() {
95
- const r = this.remote.current, c = this.lifecycle.connection;
96
- const details = {
97
- generation: this.lifecycle.generation,
98
- pending: Object.freeze({ data: this.data.size, control: this.control.size }),
99
- pausedLocally: Object.freeze([...(c?.paused ?? [])]),
100
- claimedTracks: Object.freeze([...(c?.claimed ?? [])]),
101
- receivedTracks: Object.freeze([...this.received]),
102
- unresolvedPublications: Object.freeze([...(c?.pendingClaims.values() ?? [])]),
103
- observationOverflows: this.observations.overflowCount,
104
- subscribers: this.observations.size,
105
- ...(this.lifecycle.lastError === undefined ? {} : { lastError: this.lifecycle.lastError }),
106
- ...(this.closeReport === undefined ? {} : { close: this.closeReport }),
107
- };
108
- if (this.lifecycle.status === "ready")
109
- return Object.freeze({ ...details, status: "ready", remote: this.currentReady().negotiated });
110
- return Object.freeze({
111
- ...details,
112
- status: this.lifecycle.status,
113
- ...(r === undefined
114
- ? {}
115
- : {
116
- remote: Object.freeze({
117
- ownership: r.ownership,
118
- ...(isKnownRemote(r)
119
- ? {
120
- sessionId: r.id,
121
- ...(r.descriptor === undefined ? {} : { descriptor: r.descriptor }),
122
- ...(r.connectionId === undefined ? {} : { connectionId: r.connectionId }),
123
- }
124
- : {}),
125
- }),
126
- }),
127
- });
128
- }
129
- events(options) {
130
- return this.observations.stream(options);
131
- }
132
- observe(options) {
133
- const self = this;
134
- return Effect.gen(function* () {
135
- const events = yield* self.observations.subscribe(options);
136
- const initial = self.snapshot;
137
- const revision = self.sequence;
138
- return {
139
- initial,
140
- revision,
141
- events: events.pipe(Stream.filter((event) => event.sequence > revision)),
142
- };
143
- });
144
- }
145
- emit(event, bytes) {
146
- this.observations.emit({ ...event, sequence: ++this.sequence, generation: this.lifecycle.generation }, bytes);
147
- }
148
- assertCurrent(c) {
149
- this.lifecycle.assertCurrent(c);
150
- }
151
- currentReady() {
152
- return this.lifecycle.currentReady();
153
- }
154
- currentRemote() {
155
- return this.remote.requireKnown();
156
- }
157
- fail(c, error) {
158
- if (c.failure !== undefined)
159
- return;
160
- c.failure = error;
161
- Deferred.doneUnsafe(c.failed, Effect.fail(error));
162
- Deferred.doneUnsafe(c.ready, Effect.fail(error));
163
- Queue.failCauseUnsafe(c.iceWake, Cause.fail(error));
164
- this.data.failGeneration(c.generation, error);
165
- this.control.failGeneration(c.generation, error);
166
- c.peer.close();
167
- for (const track of c.sending.values())
168
- track.stop();
169
- c.sending.clear();
170
- c.iceBuffer.length = 0;
171
- c.iceBytes = 0;
172
- c.claimed.clear();
173
- c.paused.clear();
174
- if (this.lifecycle.connection === c)
175
- this.received.clear();
176
- if (this.lifecycle.disconnect(c, error)) {
177
- this.emit({ _tag: "Diagnostic", error });
178
- }
179
- }
180
- guard(c, effect) {
181
- return pure(() => this.assertCurrent(c)).pipe(Effect.andThen(effect), Effect.raceFirst(Deferred.await(c.failed)), Effect.tap(() => pure(() => this.assertCurrent(c))), Effect.mapError((e) => c.failure ?? e));
182
- }
183
- onPeer(c, event) {
184
- if (!this.lifecycle.accepts(c))
185
- return;
186
- switch (event.type) {
187
- case "state":
188
- if (event.state === "failed" || event.state === "disconnected" || event.state === "closed")
189
- this.fail(c, ReactorError.fromCode("Disconnected", `peer state ${event.state}`, {
190
- generation: c.generation,
191
- }));
192
- else {
193
- c.peerConnected = event.state === "connected";
194
- c.readyGate();
195
- }
196
- break;
197
- case "channel":
198
- if (!event.open) {
199
- this.fail(c, ReactorError.fromCode("ChannelClosed", `${event.channel} channel closed`, {
200
- generation: c.generation,
201
- detail: { channel: event.channel },
202
- }));
203
- break;
204
- }
205
- if (event.channel === "control")
206
- c.controlOpen = true;
207
- else
208
- c.dataOpen = true;
209
- c.readyGate();
210
- break;
211
- case "ice":
212
- if (event.candidate === undefined)
213
- c.iceDone = true;
214
- else {
215
- c.iceBytes += event.candidate.candidate.length * 2;
216
- if (c.iceBuffer.length >= 256 || c.iceBytes > 262_144 || c.finalSent) {
217
- this.fail(c, ReactorError.fromCode("Overflow", "ICE buffer bound or candidate after final batch"));
218
- break;
219
- }
220
- c.iceBuffer.push(event.candidate);
221
- }
222
- Queue.offerUnsafe(c.iceWake, undefined);
223
- break;
224
- case "decoded":
225
- this.received.add(event.name);
226
- this.emit({ _tag: "Decoded", kind: event.kind, name: event.name, mid: event.mid });
227
- break;
228
- case "track":
229
- this.received.add(event.name);
230
- this.emit({ _tag: "Track", name: event.name, mid: event.mid });
231
- break;
232
- case "error":
233
- this.fail(c, event.error);
234
- break;
235
- case "message":
236
- this.receive(c, event.channel, event.bytes);
237
- break;
238
- }
239
- }
240
- receive(c, channel, bytes) {
241
- try {
242
- if (channel === "data") {
243
- const message = W.DataServerMessage.decode(bytes), payload = message.payload;
244
- if (payload?.case === "error") {
245
- const error = remoteError(payload.value, {
246
- requestId: message.request_id,
247
- generation: c.generation,
248
- outcome: "replied",
249
- detail: message,
250
- });
251
- this.data.settleWith(message.request_id, c.generation, (correlation) => {
252
- this.emit({ _tag: "CommandError", requestId: message.request_id, error, correlation }, bytes.length);
253
- return Effect.fail(error);
254
- });
255
- return;
256
- }
257
- const value = payload === undefined
258
- ? { kind: "ack", raw: message }
259
- : {
260
- kind: "message",
261
- type: payload.value.type,
262
- ...(payload.value.data === undefined
263
- ? {}
264
- : { data: objectFromStruct(payload.value.data) }),
265
- raw: message,
266
- };
267
- this.data.settleWith(message.request_id, c.generation, (correlation) => {
268
- const reply = Object.freeze({
269
- ...value,
270
- _tag: "Model",
271
- outcome: "replied",
272
- requestId: message.request_id,
273
- generation: c.generation,
274
- sequence: ++this.sequence,
275
- correlation,
276
- });
277
- // Publish the exact value that completes the request. Observers cannot
278
- // delay correlation; overflow terminates only that observation.
279
- this.observations.emit(reply, bytes.length);
280
- return Effect.succeed(reply);
281
- }, value.kind === "ack" ? "acknowledged" : "replied");
282
- }
283
- else {
284
- const message = W.ControlServerMessage.decode(bytes), payload = message.payload;
285
- // Unlike the data correlator, a bodyless control message is NOT an acknowledgement.
286
- if (payload === undefined) {
287
- this.emit({
288
- _tag: "Diagnostic",
289
- error: ReactorError.fromCode("Protocol", "bodyless control response does not resolve a request", { requestId: message.request_id }),
290
- }, bytes.length);
291
- return;
292
- }
293
- const result = payload.case === "error"
294
- ? Effect.fail(remoteError(payload.value, {
295
- requestId: message.request_id,
296
- outcome: "replied",
297
- detail: message,
298
- }))
299
- : Effect.succeed(payload);
300
- const claim = c.pendingClaims.get(message.request_id);
301
- if (claim !== undefined) {
302
- if (payload.case === "publish_track" && payload.value.name === claim) {
303
- // Record remote ownership even after the local publish caller stops
304
- // waiting. Attaching a source still requires that caller to continue.
305
- c.claimed.add(claim);
306
- c.pendingClaims.delete(message.request_id);
307
- }
308
- else if (payload.case === "error")
309
- c.pendingClaims.delete(message.request_id);
310
- else {
311
- this.fail(c, ReactorError.fromCode("UnexpectedReply", "publisher claim reply did not identify the requested track", {
312
- operation: "publish_track",
313
- requestId: message.request_id,
314
- outcome: "unknown",
315
- }));
316
- return;
317
- }
318
- }
319
- const correlation = this.control.settle(message.request_id, c.generation, result);
320
- if (payload.case !== "error" || correlation !== "matched")
321
- this.emit({ _tag: "Control", message, correlation }, bytes.length);
322
- }
323
- }
324
- catch (cause) {
325
- // Decoding rejects a malformed reply with a ReactorError; anything else it
326
- // throws is a bug and propagates to the peer rather than becoming typed.
327
- if (!ReactorError.is(cause))
328
- throw cause;
329
- this.emit({ _tag: "Diagnostic", error: cause }, bytes.length);
330
- }
331
- }
332
- flushIce(c) {
333
- const self = this;
334
- return Effect.gen(function* () {
335
- self.assertCurrent(c);
336
- if (c.connectionId === undefined)
337
- return;
338
- while (c.iceBuffer.length > 0 || (c.iceDone && !c.finalSent)) {
339
- const candidates = c.iceBuffer.splice(0);
340
- c.iceBytes = 0;
341
- const isFinal = c.iceDone && !c.finalSent;
342
- yield* self.guard(c, self.http.ice(self.currentRemote().id, c.connectionId, candidates, isFinal));
343
- if (isFinal)
344
- c.finalSent = true;
345
- }
346
- });
347
- }
348
- background(c, body) {
349
- return Effect.forkIn(body.pipe(Effect.raceFirst(Deferred.await(c.failed)), Effect.catchCause((cause) => Effect.sync(() => {
350
- const failure = Cause.findError(cause);
351
- this.fail(c, failure._tag === "Success" && ReactorError.is(failure.success)
352
- ? failure.success
353
- : ReactorError.fromCode("Protocol", "session task failed", {
354
- detail: cause,
355
- generation: c.generation,
356
- }));
357
- }))), c.scope).pipe(Effect.asVoid);
358
- }
359
- begin(reconnect) {
360
- const self = this;
361
- return Effect.gen(function* () {
362
- const previous = self.lifecycle.connection;
363
- const c = yield* pure(() => {
364
- const connection = self.lifecycle.begin(reconnect, self.remote.isKnown, () => self.makePeer());
365
- self.sampler.reset();
366
- self.received.clear();
367
- self.lifecycle.transition("connecting");
368
- return connection;
369
- });
370
- yield* Scope.addFinalizer(c.scope, Effect.gen(function* () {
371
- if (c.failure === undefined)
372
- self.fail(c, ReactorError.fromCode("Aborted", "connection scope closed", {
373
- generation: c.generation,
374
- }));
375
- if (c.peer.shutdown !== undefined)
376
- yield* c.peer.shutdown.pipe(Effect.orDie);
377
- }));
378
- if (previous !== undefined) {
379
- self.fail(previous, ReactorError.fromCode("Disconnected", "connection retired for reconnect"));
380
- yield* Scope.close(previous.scope, Exit.void);
381
- }
382
- return c;
383
- }).pipe(Effect.uninterruptible);
384
- }
385
- /** Allocate or identify one remote session, without opening a peer connection. */
386
- allocate() {
387
- return this.remote.allocate(this.options, this.http, this.lifecycle);
388
- }
389
- get id() {
390
- return this.remote.id;
391
- }
392
- get rawMedia() {
393
- return this.lifecycle.connection?.peer.rawMedia;
394
- }
395
- readyState() {
396
- return pure(() => {
397
- const connection = this.currentReady();
398
- return Object.freeze({
399
- status: "ready",
400
- generation: connection.generation,
401
- remote: connection.negotiated,
402
- });
403
- });
404
- }
405
- mediaGeneration() {
406
- return pure(() => {
407
- const connection = this.currentReady();
408
- const media = connection.peer.rawMedia;
409
- if (media === undefined)
410
- throw ReactorError.fromCode("UnsupportedCapability", "peer has no decoded media capability", { outcome: "not-submitted" });
411
- const owned = (source) => Stream.transformPull(source, (pull) => Effect.succeed(pure(() => this.assertCurrent(connection)).pipe(Effect.andThen(pull), Effect.raceFirst(Deferred.await(connection.failed)), Effect.tap(() => pure(() => this.assertCurrent(connection))))));
412
- return Object.freeze({
413
- generation: connection.generation,
414
- tracks: connection.negotiated.descriptor.capabilities.tracks,
415
- retired: Deferred.await(connection.failed),
416
- video: (name) => owned(media.video(name)),
417
- audio: (name) => owned(media.audio(name)),
418
- snapshot: media.snapshot,
419
- });
420
- });
421
- }
422
- trackGeneration() {
423
- return pure(() => {
424
- const connection = this.currentReady();
425
- if (connection.peer.nativeTracks !== true) {
426
- throw ReactorError.fromCode("UnsupportedCapability", "peer has no browser track capability", { outcome: "not-submitted" });
427
- }
428
- return Object.freeze({
429
- generation: connection.generation,
430
- tracks: connection.negotiated.descriptor.capabilities.tracks,
431
- retired: Deferred.await(connection.failed),
432
- track: (name) => this.track(name, connection),
433
- publish: (name, source) => this.publish(name, source, connection),
434
- unpublish: (name) => this.unpublish(name, connection),
435
- setTrackActive: (name, active) => this.setTrackActive(name, active, connection),
436
- setMaxBitrate: (name, bits) => this.setMaxBitrate(name, bits, connection),
437
- });
438
- });
439
- }
440
- /** Internal initial acquisition. Reconnect is a distinct operation and never replays a model command. */
441
- start() {
442
- return this.connectAttempt(false);
443
- }
444
- reconnect() {
445
- return this.connectAttempt(true);
446
- }
447
- connectAttempt(reconnect) {
448
- const self = this;
449
- return Effect.gen(function* () {
450
- const c = yield* self.begin(reconnect);
451
- yield* Effect.annotateCurrentSpan("reactor.connection.generation", c.generation);
452
- const work = Effect.gen(function* () {
453
- if (!reconnect)
454
- yield* self.guard(c, self.allocate());
455
- self.assertCurrent(c);
456
- self.lifecycle.transition("waiting");
457
- const remote = self.currentRemote();
458
- yield* Effect.annotateCurrentSpan("reactor.session.id", remote.id);
459
- const descriptor = yield* self.guard(c, self.http.ready(remote.id, reconnect ? undefined : remote.descriptor));
460
- remote.descriptor = descriptor;
461
- yield* phase("described");
462
- const capabilities = descriptor.capabilities, transport = descriptor.selected_transport;
463
- if (capabilities === undefined || transport === undefined)
464
- return yield* ReactorError.fromCode("Protocol", "missing ready capabilities/transport");
465
- if (transport.protocol !== "webrtc" || transport.version !== "1.0")
466
- return yield* ReactorError.fromCode("VersionMismatch", `unsupported transport ${transport.protocol}/${transport.version}`);
467
- const readyDescriptor = Object.freeze({
468
- ...descriptor,
469
- capabilities,
470
- selected_transport: transport,
471
- });
472
- const servers = yield* self.guard(c, self.http.iceServers(remote.id));
473
- const prepared = yield* self.guard(c, Scope.provide(c.peer.prepare(servers, capabilities.tracks, (event) => self.onPeer(c, event)), c.scope));
474
- c.mapping = prepared.mapping;
475
- yield* phase("prepared");
476
- const previousId = remote.connectionId;
477
- const cid = previousId ?? (yield* self.guard(c, self.http.register(remote.id)));
478
- c.connectionId = cid;
479
- remote.connectionId = cid;
480
- yield* phase("registered");
481
- // Source order: registration -> buffered ICE (including empty final) -> offer -> poll answer.
482
- yield* self.flushIce(c);
483
- yield* self.background(c, Effect.gen(function* () {
484
- while (true) {
485
- yield* takeQueue(c.iceWake);
486
- yield* self.flushIce(c);
487
- }
488
- }));
489
- yield* self.guard(c, self.http.offer(remote.id, cid, prepared.sdp, prepared.mapping, reconnect && previousId !== undefined));
490
- yield* phase("offered");
491
- const answer = yield* self.guard(c, self.http.answer(remote.id, cid));
492
- if (answer.connection_id !== undefined) {
493
- c.connectionId = answer.connection_id;
494
- remote.connectionId = answer.connection_id;
495
- }
496
- yield* self.guard(c, c.peer.answer(answer.sdp_answer));
497
- yield* phase("answered");
498
- yield* withDeadline(self.guard(c, Deferred.await(c.ready)), self.readyTimeout, "peer and both channels ready");
499
- self.assertCurrent(c);
500
- yield* phase("ready");
501
- self.lifecycle.ready(c, Object.freeze({
502
- ownership: remote.ownership,
503
- sessionId: remote.id,
504
- descriptor: readyDescriptor,
505
- connectionId: c.connectionId,
506
- }));
507
- // Each connection subscribes to its own receive-only tracks, an attached
508
- // one as much as the one that created the session: hosted Reactor holds
509
- // a connection's media until that connection resumes them. A data-only
510
- // peer has no tracks to resume.
511
- if ((self.options.autoResumeTracks ?? true) && c.peer.mediaSupported !== false)
512
- for (const track of capabilities.tracks)
513
- if (track.direction === "recvonly") {
514
- const outcome = yield* Effect.result(self.setTrackActive(track.name, true));
515
- if (outcome._tag === "Failure")
516
- self.emit({ _tag: "Diagnostic", error: outcome.failure });
517
- }
518
- for (const [name, bitrate] of self.bitrates) {
519
- const outcome = yield* Effect.result(self.guard(c, c.peer.maxBitrate(name, bitrate)));
520
- if (outcome._tag === "Failure")
521
- self.emit({ _tag: "Diagnostic", error: outcome.failure });
522
- }
523
- if (Duration.isFinite(self.heartbeat))
524
- yield* self.background(c, Effect.gen(function* () {
525
- while (true) {
526
- yield* self.ping();
527
- yield* Effect.sleep(self.heartbeat);
528
- }
529
- }));
530
- });
531
- yield* withDeadline(work, self.connectTimeout, reconnect ? "reconnect" : "connect").pipe(Effect.onExit((exit) => Exit.isFailure(exit)
532
- ? Effect.gen(function* () {
533
- self.remote.allocationLost();
534
- const error = Cause.findError(exit.cause);
535
- self.fail(c, error._tag === "Success" && ReactorError.is(error.success)
536
- ? error.success
537
- : ReactorError.fromCode("Aborted", "connection attempt interrupted"));
538
- yield* Scope.close(c.scope, Exit.void);
539
- })
540
- : Effect.void));
541
- }).pipe(
542
- // A caller-boundary span with an event per phase; the caller can cancel it.
543
- Effect.withSpan(reconnect ? "reactor.session.reconnect" : "reactor.session.connect", { kind: "client" }, { captureStackTrace: false }));
544
- }
545
- request(c, correlator, operation, encode, channel, deadline, publication) {
546
- const self = this;
547
- return Effect.uninterruptibleMask((restore) => Effect.gen(function* () {
548
- const pending = yield* pure(() => {
549
- self.assertCurrent(c);
550
- return correlator.register(c.generation, operation);
551
- });
552
- if (publication !== undefined)
553
- c.pendingClaims.set(pending.id, publication);
554
- const encoded = yield* Effect.result(pure(() => encode(pending.id)));
555
- if (encoded._tag === "Failure") {
556
- correlator.cancel(pending);
557
- c.pendingClaims.delete(pending.id);
558
- return yield* new ReactorError({
559
- reason: encoded.failure.reason,
560
- context: {
561
- ...encoded.failure.context,
562
- operation,
563
- requestId: pending.id,
564
- generation: c.generation,
565
- outcome: "not-submitted",
566
- },
567
- });
568
- }
569
- const failure = (error) => new ReactorError({
570
- reason: error.reason,
571
- context: {
572
- ...error.context,
573
- operation,
574
- requestId: pending.id,
575
- generation: c.generation,
576
- outcome: error.context.outcome ?? (pending.submitted ? "unknown" : "not-submitted"),
577
- },
578
- });
579
- const sending = pure(() => {
580
- self.assertCurrent(c);
581
- // The record already exists when a synchronous peer reply arrives.
582
- pending.submitted = true;
583
- }).pipe(Effect.andThen(Effect.suspend(() => c.peer.send(channel, encoded.success))), Effect.catch((error) => Effect.sync(() => {
584
- if (!correlator.has(pending))
585
- return;
586
- if (error.context.outcome === "not-submitted") {
587
- correlator.cancel(pending);
588
- c.pendingClaims.delete(pending.id);
589
- }
590
- Deferred.doneUnsafe(pending.deferred, Effect.fail(failure(error)));
591
- })));
592
- const execution = Effect.scoped(Effect.gen(function* () {
593
- // The application reply can precede the transport's acknowledgement.
594
- // Ending the reply wait joins this sender's local ACK waiter, while the
595
- // native backend remains responsible for any foreign operation slot.
596
- yield* Effect.forkIn(sending, yield* Effect.scope, { startImmediately: true });
597
- return yield* Deferred.await(pending.deferred);
598
- })).pipe(Effect.interruptible, (effect) => withDeadline(effect, deadline, operation), Effect.mapError(failure), Effect.onExit((exit) => Effect.sync(() => {
599
- if (!pending.submitted) {
600
- correlator.cancel(pending);
601
- c.pendingClaims.delete(pending.id);
602
- }
603
- else if (Exit.isFailure(exit))
604
- pending.waiting = false;
605
- // Unresolved submitted records remain bounded by maxPending. A late
606
- // reply or retiring this generation releases the slot; a timeout does not.
607
- })),
608
- // The span covers the owned execution, not the caller's wait: the wire has no
609
- // cancel, so it ends with the request's own outcome even after the caller stops
610
- // waiting. It records identity and dispatch evidence only; failure messages are
611
- // library-written, so its Exit carries no input, reply or provider text.
612
- Effect.onExit((exit) => {
613
- const error = Exit.findError(exit);
614
- return Effect.annotateCurrentSpan(Exit.isSuccess(exit)
615
- ? { "reactor.command.outcome": "replied" }
616
- : error._tag === "Success"
617
- ? {
618
- "reactor.command.outcome": error.success.context.outcome,
619
- "error.type": error.success.reason._tag,
620
- }
621
- : // No typed failure: the connection scope closed, or a defect.
622
- { "reactor.command.outcome": pending.submitted ? "unknown" : "not-submitted" });
623
- }), Effect.withSpan(channel === "data" ? "reactor.session.command" : "reactor.session.control", {
624
- kind: "client",
625
- attributes: {
626
- "reactor.operation": operation,
627
- "reactor.request.id": pending.id,
628
- "reactor.connection.generation": c.generation,
629
- },
630
- }, { captureStackTrace: false }));
631
- const owner = yield* Effect.forkIn(execution, c.scope, { startImmediately: true });
632
- return yield* restore(Fiber.join(owner));
633
- }));
634
- }
635
- command(type, data, options = {}) {
636
- return pure(() => this.currentReady()).pipe(
637
- // The caller's name, data, uploads and deadline: a rejection is InvalidInput.
638
- Effect.flatMap((c) => parsedInput(() => ({
639
- c,
640
- deadline: options.replyTimeout === undefined
641
- ? this.replyTimeout
642
- : replyTimeout(options.replyTimeout),
643
- payload: {
644
- type: nonempty(type, "command type"),
645
- data: structFromObject(data),
646
- uploads: captureUploads(options.uploads ?? new Map()),
647
- },
648
- }), type)), Effect.mapError((error) => CommandFailure.from(error, {
649
- ...error.context,
650
- operation: type,
651
- outcome: "not-submitted",
652
- })), Effect.flatMap(({ c, deadline, payload }) => this.request(c, this.data, type, (id) => W.DataClientMessage.encode({
653
- request_id: id,
654
- kind: 1,
655
- payload: { case: "command", value: payload },
656
- }), "data", deadline).pipe(Effect.mapError((error) => {
657
- const { outcome, requestId, generation } = error.context;
658
- if (outcome === "unknown" || outcome === "replied") {
659
- if (requestId === undefined || generation === undefined)
660
- throw new Error("dispatched command lost its attribution");
661
- const context = {
662
- ...error.context,
663
- operation: type,
664
- outcome,
665
- requestId,
666
- generation,
667
- };
668
- return CommandFailure.from(error, context);
669
- }
670
- return CommandFailure.from(error, {
671
- ...error.context,
672
- operation: type,
673
- outcome: "not-submitted",
674
- });
675
- }))));
676
- }
677
- controlRequest(operation, payload, expected) {
678
- return pure(() => {
679
- const connection = expected ?? this.currentReady();
680
- this.assertCurrent(connection);
681
- return connection;
682
- }).pipe(Effect.flatMap((c) => this.request(c, this.control, operation, (id) => W.ControlClientMessage.encode({ request_id: id, kind: 1, payload }), "control", this.replyTimeout, payload.case === "publish_track" ? payload.value.name : undefined)));
683
- }
684
- notification(c, payload) {
685
- return pure(() => {
686
- this.assertCurrent(c);
687
- return W.ControlClientMessage.encode({ request_id: "", kind: 3, payload });
688
- }).pipe(Effect.flatMap((bytes) => this.guard(c, c.peer.send("control", bytes))), (effect) => withDeadline(effect, this.replyTimeout, "control notification"));
689
- }
690
- ping() {
691
- return pure(() => this.currentReady()).pipe(Effect.flatMap((c) => this.notification(c, { case: "ping", value: {} })));
692
- }
693
- schema() {
694
- return this.controlRequest("request_schema", { case: "request_schema", value: {} }).pipe(Effect.flatMap((reply) => pure(() => {
695
- if (reply.case !== "model_schema")
696
- throw ReactorError.fromCode("UnexpectedReply", `schema reply was ${reply.case}`, {
697
- outcome: "replied",
698
- });
699
- return {
700
- raw: reply.value,
701
- ...(reply.value.openapi === undefined
702
- ? {}
703
- : { openapi: objectFromStruct(reply.value.openapi) }),
704
- };
705
- })));
706
- }
707
- clip(payload) {
708
- return this.controlRequest(payload.case, payload).pipe(Effect.flatMap((reply) => pure(() => {
709
- if (reply.case === "clip_failed")
710
- throw new ReactorError({
711
- reason: new Remote({
712
- // The one regex classification of provider free text, a deliberate exception:
713
- // ClipFailed carries only a reason string, and a caller must tell a disabled
714
- // recorder from other clip failures. Add no others; drop this once the wire
715
- // carries a code.
716
- _tag: /recorder disabled|encoder crashed/i.test(reply.value.reason)
717
- ? "RecorderDisabled"
718
- : "Remote",
719
- message: "clip failed",
720
- body: reply.value.reason,
721
- }),
722
- context: { outcome: "replied" },
723
- });
724
- if (reply.case !== "clip_ready")
725
- throw ReactorError.fromCode("UnexpectedReply", `clip reply was ${reply.case}`, {
726
- outcome: "replied",
727
- });
728
- let playlist;
729
- try {
730
- playlist = new URL(reply.value.playlist_url, `${this.http.apiUrl}/`);
731
- }
732
- catch (cause) {
733
- throw ReactorError.fromCode("Protocol", "clip playlist URL is malformed", {
734
- outcome: "replied",
735
- detail: cause,
736
- });
737
- }
738
- return { ...reply.value, playlist_url: playlist.href };
739
- })));
740
- }
741
- requestClip(seconds) {
742
- return pure(() => {
743
- if (!Number.isFinite(seconds) || seconds <= 0)
744
- throw ReactorError.fromCode("Protocol", "clip duration must be finite and positive");
745
- }).pipe(Effect.andThen(this.clip({ case: "request_clip", value: { duration_seconds: seconds } })));
746
- }
747
- recording() {
748
- return this.clip({ case: "request_recording", value: {} });
749
- }
750
- namedTrack(name, connection) {
751
- if (connection.peer.mediaSupported === false)
752
- throw ReactorError.fromCode("UnsupportedCapability", "This peer is data-only; track/media operations are unavailable", { outcome: "not-submitted" });
753
- const track = connection.negotiated.descriptor.capabilities.tracks.find((t) => t.name === name);
754
- if (track === undefined)
755
- throw ReactorError.fromCode("InvalidState", `unknown track: ${name}`);
756
- return track;
757
- }
758
- trackOperation(name, body, expected) {
759
- return Effect.acquireUseRelease(pure(() => {
760
- const c = expected ?? this.currentReady();
761
- this.assertCurrent(c);
762
- const track = this.namedTrack(name, c);
763
- if (c.trackBusy.has(name))
764
- throw ReactorError.fromCode("InvalidState", `another track operation is in flight: ${name}`);
765
- c.trackBusy.add(name);
766
- return { c, track };
767
- }), ({ c, track }) => this.guard(c, body(c, track)), ({ c }) => Effect.sync(() => {
768
- c.trackBusy.delete(name);
769
- }));
770
- }
771
- setTrackActive(name, active, expected) {
772
- return this.trackOperation(name, (c) => c.peer.direction(name, active).pipe(Effect.andThen(pure(() => {
773
- if (active)
774
- c.paused.delete(name);
775
- else
776
- c.paused.add(name);
777
- })), Effect.andThen(this.notification(c, active
778
- ? { case: "resume_track", value: { name } }
779
- : { case: "pause_track", value: { name } }))), expected);
780
- }
781
- /** Native replaceTrack cannot be cancelled. Atomic local ownership transfer is
782
- * masked; only the bounded native wait is interruptible. An abandoned wait retires
783
- * this generation, preventing late replacement from racing another sender operation. */
784
- replaceSender(c, name, source) {
785
- const self = this;
786
- return Effect.uninterruptibleMask((restore) => Effect.gen(function* () {
787
- const clone = yield* pure(() => {
788
- self.assertCurrent(c);
789
- return source === null ? null : source.clone();
790
- });
791
- let invoked = false, deadline = false;
792
- const mutation = pure(() => {
793
- self.assertCurrent(c);
794
- invoked = true;
795
- }).pipe(Effect.andThen(Effect.suspend(() => c.peer.replace(name, clone))), Effect.timeoutOrElse({
796
- duration: self.replyTimeout,
797
- orElse: () => {
798
- deadline = true;
799
- return Effect.fail(ReactorError.fromCode("Timeout", "sender replacement deadline; local generation retired", { operation: name, outcome: "unknown" }));
800
- },
801
- }));
802
- yield* restore(mutation).pipe(Effect.onExit((exit) => Exit.isFailure(exit)
803
- ? Effect.sync(() => {
804
- clone?.stop();
805
- if (invoked && (deadline || Cause.hasInterrupts(exit.cause)))
806
- self.fail(c, ReactorError.fromCode(deadline ? "Timeout" : "Disconnected", "native sender replacement abandoned; reconnect explicitly before reusing publication", { operation: name, outcome: "unknown" }));
807
- })
808
- : Effect.void));
809
- // No interruptible boundary between successful mutation and recording its owner.
810
- // If another task retired the generation, do not resurrect a sending clone.
811
- yield* pure(() => {
812
- try {
813
- self.assertCurrent(c);
814
- c.sending.get(name)?.stop();
815
- if (clone === null)
816
- c.sending.delete(name);
817
- else
818
- c.sending.set(name, clone);
819
- }
820
- catch (error) {
821
- clone?.stop();
822
- throw error;
823
- }
824
- });
825
- }));
826
- }
827
- /** Claims the publisher slot, then attaches a session-owned clone. Caller retains its source track. */
828
- publish(name, source, expected) {
829
- const self = this;
830
- return this.trackOperation(name, (c, track) => Effect.gen(function* () {
831
- if (c.peer.nativeTracks === false)
832
- return yield* ReactorError.fromCode("UnsupportedCapability", "this peer does not accept browser media tracks", { outcome: "not-submitted" });
833
- if (track.direction !== "sendonly" ||
834
- source.kind !== track.kind ||
835
- source.readyState !== "live")
836
- return yield* ReactorError.fromCode("InvalidState", "publish requires a live matching input track");
837
- if (!c.claimed.has(name)) {
838
- const reply = yield* self.controlRequest("publish_track", { case: "publish_track", value: { name } }, c);
839
- if (reply.case !== "publish_track" || reply.value.name !== name)
840
- return yield* ReactorError.fromCode("UnexpectedReply", "publisher claim reply mismatch", { outcome: "replied" });
841
- c.claimed.add(name);
842
- }
843
- yield* self.replaceSender(c, name, source);
844
- }), expected);
845
- }
846
- unpublish(name, expected) {
847
- return this.trackOperation(name, (c) => c.peer.nativeTracks === false
848
- ? Effect.fail(ReactorError.fromCode("UnsupportedCapability", "this peer does not expose browser track publication", { outcome: "not-submitted" }))
849
- : this.replaceSender(c, name, null).pipe(Effect.andThen(this.notification(c, { case: "unpublish_track", value: { name } })), Effect.tap(() => Effect.sync(() => {
850
- c.claimed.delete(name);
851
- }))), expected);
852
- }
853
- track(name, expected) {
854
- return Effect.acquireRelease(pure(() => {
855
- const c = expected ?? this.currentReady();
856
- this.assertCurrent(c);
857
- if (c.peer.nativeTracks === false)
858
- throw ReactorError.fromCode("UnsupportedCapability", "this peer exposes owned decoded frames instead of browser tracks", { outcome: "not-submitted" });
859
- return { peer: c.peer, track: c.peer.lease(name) };
860
- }), ({ peer, track }) => Effect.sync(() => peer.release(track))).pipe(Effect.map(({ track }) => track));
861
- }
862
- setMaxBitrate(name, bitsPerSecond, expected) {
863
- return this.trackOperation(name, (c) => c.peer.maxBitrate(name, bitsPerSecond).pipe(Effect.tap(() => Effect.sync(() => {
864
- this.bitrates.set(name, bitsPerSecond);
865
- }))), expected);
866
- }
867
- stats() {
868
- const self = this;
869
- return Effect.gen(function* () {
870
- const connection = yield* pure(() => self.currentReady());
871
- const raw = yield* self.guard(connection, connection.peer.stats);
872
- // Elapsed sampling time belongs to this Effect boundary, not the pure sampler.
873
- const atNanos = yield* Clock.monotonicTimeNanos;
874
- const atMs = Number(atNanos) / 1_000_000;
875
- return yield* pure(() => self.sampler.sample(raw, connection.generation, atMs));
876
- });
877
- }
878
- rawStats() {
879
- return pure(() => this.currentReady()).pipe(Effect.flatMap((c) => this.guard(c, c.peer.stats)));
880
- }
881
- upload(name, mimeType, bytes, options = {}) {
882
- const self = this;
883
- return Effect.suspend(() => {
884
- let progress = {
885
- allocation: "not-requested",
886
- transfer: "not-requested",
887
- notification: "not-submitted",
888
- };
889
- const operation = Effect.gen(function* () {
890
- const { c, remote, copy } = yield* pure(() => {
891
- const c = self.currentReady(), remote = self.currentRemote();
892
- nonempty(name, "upload name");
893
- nonempty(mimeType, "upload MIME type");
894
- positiveLimit(bytes.byteLength, "upload size", self.uploadBound);
895
- return { c, remote, copy: new Uint8Array(bytes) };
896
- });
897
- progress = { ...progress, allocation: "unknown" };
898
- const allocation = yield* self.guard(c, self.http.allocateUpload(remote.id, name, mimeType, copy.length));
899
- const file = {
900
- upload_id: allocation.presigned_id,
901
- name,
902
- mime_type: mimeType,
903
- size: BigInt(copy.length),
904
- };
905
- progress = { ...progress, allocation: "confirmed", file, transfer: "unknown" };
906
- yield* self.guard(c, self.http.putUpload(allocation, copy, mimeType));
907
- progress = { ...progress, transfer: "confirmed" };
908
- progress = { ...progress, notification: "unknown" };
909
- yield* self.notification(c, { case: "file_uploaded", value: file }).pipe(Effect.tapError((error) => Effect.sync(() => {
910
- if (error.context.outcome === "not-submitted")
911
- progress = { ...progress, notification: "not-submitted" };
912
- })));
913
- progress = { ...progress, notification: "submitted" };
914
- return { file, transfer: "confirmed", notification: "submitted" };
915
- });
916
- return pure(() => options.uploadTimeout === undefined
917
- ? self.uploadTimeout
918
- : uploadTimeout(options.uploadTimeout)).pipe(Effect.flatMap((deadline) => withDeadline(operation, deadline, "upload")), Effect.mapError((e) => ReactorError.fromCode("Upload", e.message, {
919
- ...e.context,
920
- operation: "upload",
921
- detail: { cause: e, progress: { ...progress } },
922
- })), Effect.ensuring(Effect.sync(() => self.emit({ _tag: "Upload", progress: Object.freeze({ ...progress }) }))));
923
- }).pipe(
924
- // The MIME type and size only: never the name or the bytes.
925
- Effect.withSpan("reactor.session.upload", {
926
- kind: "client",
927
- attributes: {
928
- "reactor.upload.mime_type": mimeType,
929
- "reactor.upload.size": bytes.byteLength,
930
- },
931
- }, { captureStackTrace: false }));
932
- }
933
- /** Idempotent close. Owned-session termination is attempted once; response is not terminal proof. */
934
- close() {
935
- const self = this;
936
- return Effect.uninterruptible(Effect.suspend(() => {
937
- if (self.closeGate !== undefined)
938
- return Deferred.await(self.closeGate);
939
- const gate = Deferred.makeUnsafe();
940
- self.closeGate = gate;
941
- return Effect.gen(function* () {
942
- self.lifecycle.transition("closing");
943
- Deferred.doneUnsafe(self.lifecycle.closing, Effect.fail(ReactorError.fromCode("Closed", "session closing")));
944
- const report = yield* cleanupSession({
945
- connection: self.lifecycle.connection,
946
- scope: self.lifecycle.scope,
947
- remote: self.remote,
948
- http: self.http,
949
- replyTimeout: self.replyTimeout,
950
- retire: (connection, error) => self.fail(connection, error),
951
- });
952
- self.closeReport = report;
953
- self.lifecycle.transition("closed");
954
- self.observations.end();
955
- Deferred.doneUnsafe(gate, Effect.succeed(report));
956
- // Consumer callbacks cannot undo or stall cleanup.
957
- yield* Effect.ignore(Effect.try(() => self.options.onClose?.(report)));
958
- yield* Effect.annotateCurrentSpan({
959
- "reactor.close.local_closed": report.localClosed,
960
- "reactor.close.allocation": report.allocation,
961
- ...terminationAttributes(report.remote),
962
- });
963
- return report;
964
- }).pipe(
965
- // Only the close that runs cleanup is traced; a later close awaits its report.
966
- Effect.withSpan("reactor.session.close", {
967
- kind: "client",
968
- attributes: self.remote.id === undefined ? {} : { "reactor.session.id": self.remote.id },
969
- }, { captureStackTrace: false }));
970
- }));
971
- }
972
- isKnownTerminal() {
973
- return this.remote.isKnownTerminal();
974
- }
975
- }
976
- //# sourceMappingURL=session.js.map