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.
- package/NOTICE +7 -2
- package/README.md +103 -141
- package/dist/Coordinator.d.ts +382 -0
- package/dist/Coordinator.d.ts.map +1 -0
- package/dist/Coordinator.js +732 -0
- package/dist/Coordinator.js.map +1 -0
- package/dist/H3.d.ts +159 -0
- package/dist/H3.d.ts.map +1 -0
- package/dist/H3.js +21 -0
- package/dist/H3.js.map +1 -0
- package/dist/H3Source.d.ts +93 -0
- package/dist/H3Source.d.ts.map +1 -0
- package/dist/H3Source.js +401 -0
- package/dist/H3Source.js.map +1 -0
- package/dist/LocalSource.d.ts +68 -0
- package/dist/LocalSource.d.ts.map +1 -0
- package/dist/LocalSource.js +354 -0
- package/dist/LocalSource.js.map +1 -0
- package/dist/Media.d.ts +106 -0
- package/dist/Media.d.ts.map +1 -0
- package/dist/Media.js +16 -0
- package/dist/Media.js.map +1 -0
- package/dist/Peer.d.ts +134 -0
- package/dist/Peer.d.ts.map +1 -0
- package/dist/Peer.js +57 -0
- package/dist/Peer.js.map +1 -0
- package/dist/Playout.d.ts +724 -0
- package/dist/Playout.d.ts.map +1 -0
- package/dist/Playout.js +28 -0
- package/dist/Playout.js.map +1 -0
- package/dist/Reactor.d.ts +135 -0
- package/dist/Reactor.d.ts.map +1 -0
- package/dist/Reactor.js +158 -0
- package/dist/Reactor.js.map +1 -0
- package/dist/ReactorError.d.ts +331 -0
- package/dist/ReactorError.d.ts.map +1 -0
- package/dist/ReactorError.js +316 -0
- package/dist/ReactorError.js.map +1 -0
- package/dist/ReactorTest.d.ts +383 -0
- package/dist/ReactorTest.d.ts.map +1 -0
- package/dist/ReactorTest.js +317 -0
- package/dist/ReactorTest.js.map +1 -0
- package/dist/Session.d.ts +314 -0
- package/dist/Session.d.ts.map +1 -0
- package/dist/Session.js +51 -0
- package/dist/Session.js.map +1 -0
- package/dist/index.d.ts +12 -22
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +12 -11
- package/dist/index.js.map +1 -1
- package/dist/internal/correlator.d.ts +46 -0
- package/dist/internal/correlator.d.ts.map +1 -0
- package/dist/internal/correlator.js +150 -0
- package/dist/internal/correlator.js.map +1 -0
- package/dist/internal/deadline.d.ts +24 -0
- package/dist/internal/deadline.d.ts.map +1 -0
- package/dist/internal/deadline.js +44 -0
- package/dist/internal/deadline.js.map +1 -0
- package/dist/{h3/_internal/contracts.d.ts → internal/h3/commands.d.ts} +39 -33
- package/dist/internal/h3/commands.d.ts.map +1 -0
- package/dist/internal/h3/commands.js +128 -0
- package/dist/internal/h3/commands.js.map +1 -0
- package/dist/{h3 → internal/h3}/messages.d.ts +16 -11
- package/dist/internal/h3/messages.d.ts.map +1 -0
- package/dist/{h3 → internal/h3}/messages.js +19 -31
- package/dist/internal/h3/messages.js.map +1 -0
- package/dist/internal/h3/operations.d.ts +145 -0
- package/dist/internal/h3/operations.d.ts.map +1 -0
- package/dist/internal/h3/operations.js +284 -0
- package/dist/internal/h3/operations.js.map +1 -0
- package/dist/{h3 → internal/h3}/profile.d.ts +63 -65
- package/dist/internal/h3/profile.d.ts.map +1 -0
- package/dist/{h3 → internal/h3}/profile.js +39 -39
- package/dist/internal/h3/profile.js.map +1 -0
- package/dist/internal/h3/provider.d.ts +14 -0
- package/dist/internal/h3/provider.d.ts.map +1 -0
- package/dist/internal/h3/provider.js +672 -0
- package/dist/internal/h3/provider.js.map +1 -0
- package/dist/internal/h3/references.d.ts +68 -0
- package/dist/internal/h3/references.d.ts.map +1 -0
- package/dist/internal/h3/references.js +339 -0
- package/dist/internal/h3/references.js.map +1 -0
- package/dist/internal/h3/request.d.ts +56 -0
- package/dist/internal/h3/request.d.ts.map +1 -0
- package/dist/internal/h3/request.js +70 -0
- package/dist/internal/h3/request.js.map +1 -0
- package/dist/internal/h3/state.d.ts +120 -0
- package/dist/internal/h3/state.d.ts.map +1 -0
- package/dist/internal/h3/state.js +270 -0
- package/dist/internal/h3/state.js.map +1 -0
- package/dist/{Submission.d.ts → internal/h3/submission.d.ts} +1 -3
- package/dist/internal/h3/submission.d.ts.map +1 -0
- package/dist/{Submission.js → internal/h3/submission.js} +1 -9
- package/dist/internal/h3/submission.js.map +1 -0
- package/dist/internal/hub.d.ts +32 -0
- package/dist/internal/hub.d.ts.map +1 -0
- package/dist/internal/hub.js +92 -0
- package/dist/internal/hub.js.map +1 -0
- package/dist/internal/playout/errors.d.ts +51 -0
- package/dist/internal/playout/errors.d.ts.map +1 -0
- package/dist/internal/playout/errors.js +40 -0
- package/dist/internal/playout/errors.js.map +1 -0
- package/dist/internal/playout/policy.d.ts +559 -0
- package/dist/internal/playout/policy.d.ts.map +1 -0
- package/dist/internal/playout/policy.js +2338 -0
- package/dist/internal/playout/policy.js.map +1 -0
- package/dist/internal/playout/runtime.d.ts +28 -0
- package/dist/internal/playout/runtime.d.ts.map +1 -0
- package/dist/internal/playout/runtime.js +766 -0
- package/dist/internal/playout/runtime.js.map +1 -0
- package/dist/internal/playout/tag.d.ts +14 -0
- package/dist/internal/playout/tag.d.ts.map +1 -0
- package/dist/internal/playout/tag.js +43 -0
- package/dist/internal/playout/tag.js.map +1 -0
- package/dist/internal/proto/reactor_wire/v1/common_pb.d.ts +55 -0
- package/dist/internal/proto/reactor_wire/v1/common_pb.d.ts.map +1 -0
- package/dist/internal/proto/reactor_wire/v1/common_pb.js +42 -0
- package/dist/internal/proto/reactor_wire/v1/common_pb.js.map +1 -0
- package/dist/internal/proto/reactor_wire/v1/control_pb.d.ts +160 -0
- package/dist/internal/proto/reactor_wire/v1/control_pb.d.ts.map +1 -0
- package/dist/internal/proto/reactor_wire/v1/control_pb.js +21 -0
- package/dist/internal/proto/reactor_wire/v1/control_pb.js.map +1 -0
- package/dist/internal/proto/reactor_wire/v1/data_pb.d.ts +89 -0
- package/dist/internal/proto/reactor_wire/v1/data_pb.d.ts.map +1 -0
- package/dist/internal/proto/reactor_wire/v1/data_pb.js +20 -0
- package/dist/internal/proto/reactor_wire/v1/data_pb.js.map +1 -0
- package/dist/internal/proto/reactor_wire/v1/model_pb.d.ts +85 -0
- package/dist/internal/proto/reactor_wire/v1/model_pb.d.ts.map +1 -0
- package/dist/internal/proto/reactor_wire/v1/model_pb.js +24 -0
- package/dist/internal/proto/reactor_wire/v1/model_pb.js.map +1 -0
- package/dist/internal/proto/reactor_wire/v1/platform_pb.d.ts +190 -0
- package/dist/internal/proto/reactor_wire/v1/platform_pb.d.ts.map +1 -0
- package/dist/internal/proto/reactor_wire/v1/platform_pb.js +54 -0
- package/dist/internal/proto/reactor_wire/v1/platform_pb.js.map +1 -0
- package/dist/internal/proto/reactor_wire/v1/track_pb.d.ts +88 -0
- package/dist/internal/proto/reactor_wire/v1/track_pb.d.ts.map +1 -0
- package/dist/internal/proto/reactor_wire/v1/track_pb.js +33 -0
- package/dist/internal/proto/reactor_wire/v1/track_pb.js.map +1 -0
- package/dist/internal/queue.d.ts +4 -0
- package/dist/internal/queue.d.ts.map +1 -0
- package/dist/{_internal → internal}/queue.js +0 -9
- package/dist/internal/queue.js.map +1 -0
- package/dist/internal/reactorTest/coordinator.d.ts +5 -0
- package/dist/internal/reactorTest/coordinator.d.ts.map +1 -0
- package/dist/internal/reactorTest/coordinator.js +178 -0
- package/dist/internal/reactorTest/coordinator.js.map +1 -0
- package/dist/internal/reactorTest/faults.d.ts +172 -0
- package/dist/internal/reactorTest/faults.d.ts.map +1 -0
- package/dist/internal/reactorTest/faults.js +23 -0
- package/dist/internal/reactorTest/faults.js.map +1 -0
- package/dist/internal/reactorTest/h3.d.ts +431 -0
- package/dist/internal/reactorTest/h3.d.ts.map +1 -0
- package/dist/internal/reactorTest/h3.js +625 -0
- package/dist/internal/reactorTest/h3.js.map +1 -0
- package/dist/internal/reactorTest/media.d.ts +22 -0
- package/dist/internal/reactorTest/media.d.ts.map +1 -0
- package/dist/internal/reactorTest/media.js +34 -0
- package/dist/internal/reactorTest/media.js.map +1 -0
- package/dist/internal/reactorTest/peer.d.ts +318 -0
- package/dist/internal/reactorTest/peer.d.ts.map +1 -0
- package/dist/internal/reactorTest/peer.js +206 -0
- package/dist/internal/reactorTest/peer.js.map +1 -0
- package/dist/internal/reactorTest/playout.d.ts +34 -0
- package/dist/internal/reactorTest/playout.d.ts.map +1 -0
- package/dist/internal/reactorTest/playout.js +340 -0
- package/dist/internal/reactorTest/playout.js.map +1 -0
- package/dist/internal/reactorTest/references.d.ts +25 -0
- package/dist/internal/reactorTest/references.d.ts.map +1 -0
- package/dist/{testing/Png.js → internal/reactorTest/references.js} +50 -12
- package/dist/internal/reactorTest/references.js.map +1 -0
- package/dist/internal/reactorTest/sessions.d.ts +364 -0
- package/dist/internal/reactorTest/sessions.d.ts.map +1 -0
- package/dist/internal/reactorTest/sessions.js +592 -0
- package/dist/internal/reactorTest/sessions.js.map +1 -0
- package/dist/internal/reactorTest/timing.d.ts +13 -0
- package/dist/internal/reactorTest/timing.d.ts.map +1 -0
- package/dist/internal/reactorTest/timing.js +20 -0
- package/dist/internal/reactorTest/timing.js.map +1 -0
- package/dist/internal/recording.d.ts +52 -0
- package/dist/internal/recording.d.ts.map +1 -0
- package/dist/internal/recording.js +141 -0
- package/dist/internal/recording.js.map +1 -0
- package/dist/internal/session/connect.d.ts +34 -0
- package/dist/internal/session/connect.d.ts.map +1 -0
- package/dist/internal/session/connect.js +502 -0
- package/dist/internal/session/connect.js.map +1 -0
- package/dist/internal/session/generation.d.ts +35 -0
- package/dist/internal/session/generation.d.ts.map +1 -0
- package/dist/internal/session/generation.js +185 -0
- package/dist/internal/session/generation.js.map +1 -0
- package/dist/internal/session/ice.d.ts +23 -0
- package/dist/internal/session/ice.d.ts.map +1 -0
- package/dist/internal/session/ice.js +57 -0
- package/dist/internal/session/ice.js.map +1 -0
- package/dist/internal/session/inbound.d.ts +50 -0
- package/dist/internal/session/inbound.d.ts.map +1 -0
- package/dist/internal/session/inbound.js +202 -0
- package/dist/internal/session/inbound.js.map +1 -0
- package/dist/internal/session/model.d.ts +163 -0
- package/dist/internal/session/model.d.ts.map +1 -0
- package/dist/internal/session/model.js +78 -0
- package/dist/internal/session/model.js.map +1 -0
- package/dist/internal/session/requests.d.ts +71 -0
- package/dist/internal/session/requests.d.ts.map +1 -0
- package/dist/internal/session/requests.js +240 -0
- package/dist/internal/session/requests.js.map +1 -0
- package/dist/internal/session/tracks.d.ts +21 -0
- package/dist/internal/session/tracks.d.ts.map +1 -0
- package/dist/internal/session/tracks.js +166 -0
- package/dist/internal/session/tracks.js.map +1 -0
- package/dist/internal/session/upload.d.ts +21 -0
- package/dist/internal/session/upload.d.ts.map +1 -0
- package/dist/internal/session/upload.js +68 -0
- package/dist/internal/session/upload.js.map +1 -0
- package/dist/internal/session.d.ts +66 -0
- package/dist/internal/session.d.ts.map +1 -0
- package/dist/internal/session.js +280 -0
- package/dist/internal/session.js.map +1 -0
- package/dist/{stats.d.ts → internal/stats.d.ts} +30 -16
- package/dist/internal/stats.d.ts.map +1 -0
- package/dist/internal/stats.js +201 -0
- package/dist/internal/stats.js.map +1 -0
- package/dist/internal/token.d.ts +22 -0
- package/dist/internal/token.d.ts.map +1 -0
- package/dist/internal/token.js +65 -0
- package/dist/internal/token.js.map +1 -0
- package/dist/internal/wire.d.ts +37 -0
- package/dist/internal/wire.d.ts.map +1 -0
- package/dist/internal/wire.js +49 -0
- package/dist/internal/wire.js.map +1 -0
- package/notices/bufbuild-protobuf-LICENSE +201 -0
- package/package.json +17 -38
- package/dist/FetchHttp.d.ts +0 -9
- package/dist/FetchHttp.d.ts.map +0 -1
- package/dist/FetchHttp.js +0 -63
- package/dist/FetchHttp.js.map +0 -1
- package/dist/PeerFactory.d.ts +0 -26
- package/dist/PeerFactory.d.ts.map +0 -1
- package/dist/PeerFactory.js +0 -4
- package/dist/PeerFactory.js.map +0 -1
- package/dist/PeerTypes.d.ts +0 -64
- package/dist/PeerTypes.d.ts.map +0 -1
- package/dist/PeerTypes.js +0 -2
- package/dist/PeerTypes.js.map +0 -1
- package/dist/Sequence.d.ts +0 -85
- package/dist/Sequence.d.ts.map +0 -1
- package/dist/Sequence.js +0 -210
- package/dist/Sequence.js.map +0 -1
- package/dist/SessionTypes.d.ts +0 -312
- package/dist/SessionTypes.d.ts.map +0 -1
- package/dist/SessionTypes.js +0 -19
- package/dist/SessionTypes.js.map +0 -1
- package/dist/Submission.d.ts.map +0 -1
- package/dist/Submission.js.map +0 -1
- package/dist/_internal/queue.d.ts +0 -6
- package/dist/_internal/queue.d.ts.map +0 -1
- package/dist/_internal/queue.js.map +0 -1
- package/dist/bytes.d.ts +0 -6
- package/dist/bytes.d.ts.map +0 -1
- package/dist/bytes.js +0 -32
- package/dist/bytes.js.map +0 -1
- package/dist/contract.d.ts +0 -149
- package/dist/contract.d.ts.map +0 -1
- package/dist/contract.js +0 -119
- package/dist/contract.js.map +0 -1
- package/dist/coordinator/_internal/client.d.ts +0 -215
- package/dist/coordinator/_internal/client.d.ts.map +0 -1
- package/dist/coordinator/_internal/client.js +0 -563
- package/dist/coordinator/_internal/client.js.map +0 -1
- package/dist/coordinator/_internal/recording.d.ts +0 -31
- package/dist/coordinator/_internal/recording.d.ts.map +0 -1
- package/dist/coordinator/_internal/recording.js +0 -123
- package/dist/coordinator/_internal/recording.js.map +0 -1
- package/dist/coordinator/_internal/response.d.ts +0 -15
- package/dist/coordinator/_internal/response.d.ts.map +0 -1
- package/dist/coordinator/_internal/response.js +0 -55
- package/dist/coordinator/_internal/response.js.map +0 -1
- package/dist/coordinator/_internal/schemas.d.ts +0 -73
- package/dist/coordinator/_internal/schemas.d.ts.map +0 -1
- package/dist/coordinator/_internal/schemas.js +0 -200
- package/dist/coordinator/_internal/schemas.js.map +0 -1
- package/dist/coordinator/index.d.ts +0 -40
- package/dist/coordinator/index.d.ts.map +0 -1
- package/dist/coordinator/index.js +0 -21
- package/dist/coordinator/index.js.map +0 -1
- package/dist/correlation.d.ts +0 -47
- package/dist/correlation.d.ts.map +0 -1
- package/dist/correlation.js +0 -131
- package/dist/correlation.js.map +0 -1
- package/dist/duration.d.ts +0 -27
- package/dist/duration.d.ts.map +0 -1
- package/dist/duration.js +0 -47
- package/dist/duration.js.map +0 -1
- package/dist/errors.d.ts +0 -1303
- package/dist/errors.d.ts.map +0 -1
- package/dist/errors.js +0 -745
- package/dist/errors.js.map +0 -1
- package/dist/h3/_internal/client.d.ts +0 -9
- package/dist/h3/_internal/client.d.ts.map +0 -1
- package/dist/h3/_internal/client.js +0 -652
- package/dist/h3/_internal/client.js.map +0 -1
- package/dist/h3/_internal/contracts.d.ts.map +0 -1
- package/dist/h3/_internal/contracts.js +0 -123
- package/dist/h3/_internal/contracts.js.map +0 -1
- package/dist/h3/_internal/deployment.d.ts +0 -8
- package/dist/h3/_internal/deployment.d.ts.map +0 -1
- package/dist/h3/_internal/deployment.js +0 -149
- package/dist/h3/_internal/deployment.js.map +0 -1
- package/dist/h3/_internal/evidence.d.ts +0 -17
- package/dist/h3/_internal/evidence.d.ts.map +0 -1
- package/dist/h3/_internal/evidence.js +0 -48
- package/dist/h3/_internal/evidence.js.map +0 -1
- package/dist/h3/_internal/operations.d.ts +0 -58
- package/dist/h3/_internal/operations.d.ts.map +0 -1
- package/dist/h3/_internal/operations.js +0 -268
- package/dist/h3/_internal/operations.js.map +0 -1
- package/dist/h3/_internal/references.d.ts +0 -24
- package/dist/h3/_internal/references.d.ts.map +0 -1
- package/dist/h3/_internal/references.js +0 -309
- package/dist/h3/_internal/references.js.map +0 -1
- package/dist/h3/_internal/request.d.ts +0 -21
- package/dist/h3/_internal/request.d.ts.map +0 -1
- package/dist/h3/_internal/request.js +0 -97
- package/dist/h3/_internal/request.js.map +0 -1
- package/dist/h3/_internal/retained.d.ts +0 -22
- package/dist/h3/_internal/retained.d.ts.map +0 -1
- package/dist/h3/_internal/retained.js +0 -89
- package/dist/h3/_internal/retained.js.map +0 -1
- package/dist/h3/_internal/state.d.ts +0 -44
- package/dist/h3/_internal/state.d.ts.map +0 -1
- package/dist/h3/_internal/state.js +0 -283
- package/dist/h3/_internal/state.js.map +0 -1
- package/dist/h3/index.d.ts +0 -10
- package/dist/h3/index.d.ts.map +0 -1
- package/dist/h3/index.js +0 -7
- package/dist/h3/index.js.map +0 -1
- package/dist/h3/messages.d.ts.map +0 -1
- package/dist/h3/messages.js.map +0 -1
- package/dist/h3/profile.d.ts.map +0 -1
- package/dist/h3/profile.js.map +0 -1
- package/dist/h3/types.d.ts +0 -291
- package/dist/h3/types.d.ts.map +0 -1
- package/dist/h3/types.js +0 -2
- package/dist/h3/types.js.map +0 -1
- package/dist/host.d.ts +0 -26
- package/dist/host.d.ts.map +0 -1
- package/dist/host.js +0 -20
- package/dist/host.js.map +0 -1
- package/dist/json.d.ts +0 -25
- package/dist/json.d.ts.map +0 -1
- package/dist/json.js +0 -143
- package/dist/json.js.map +0 -1
- package/dist/media-stream.d.ts +0 -10
- package/dist/media-stream.d.ts.map +0 -1
- package/dist/media-stream.js +0 -18
- package/dist/media-stream.js.map +0 -1
- package/dist/observation.d.ts +0 -38
- package/dist/observation.d.ts.map +0 -1
- package/dist/observation.js +0 -113
- package/dist/observation.js.map +0 -1
- package/dist/orchestration/elapsed.d.ts +0 -9
- package/dist/orchestration/elapsed.d.ts.map +0 -1
- package/dist/orchestration/elapsed.js +0 -8
- package/dist/orchestration/elapsed.js.map +0 -1
- package/dist/orchestration/h3-source.d.ts +0 -58
- package/dist/orchestration/h3-source.d.ts.map +0 -1
- package/dist/orchestration/h3-source.js +0 -362
- package/dist/orchestration/h3-source.js.map +0 -1
- package/dist/orchestration/index.d.ts +0 -17
- package/dist/orchestration/index.d.ts.map +0 -1
- package/dist/orchestration/index.js +0 -12
- package/dist/orchestration/index.js.map +0 -1
- package/dist/orchestration/media-buffer.d.ts +0 -32
- package/dist/orchestration/media-buffer.d.ts.map +0 -1
- package/dist/orchestration/media-buffer.js +0 -94
- package/dist/orchestration/media-buffer.js.map +0 -1
- package/dist/orchestration/open-h3.d.ts +0 -101
- package/dist/orchestration/open-h3.d.ts.map +0 -1
- package/dist/orchestration/open-h3.js +0 -127
- package/dist/orchestration/open-h3.js.map +0 -1
- package/dist/orchestration/queries.d.ts +0 -10
- package/dist/orchestration/queries.d.ts.map +0 -1
- package/dist/orchestration/queries.js +0 -43
- package/dist/orchestration/queries.js.map +0 -1
- package/dist/orchestration/references.d.ts +0 -18
- package/dist/orchestration/references.d.ts.map +0 -1
- package/dist/orchestration/references.js +0 -79
- package/dist/orchestration/references.js.map +0 -1
- package/dist/orchestration/renewal-state.d.ts +0 -84
- package/dist/orchestration/renewal-state.d.ts.map +0 -1
- package/dist/orchestration/renewal-state.js +0 -95
- package/dist/orchestration/renewal-state.js.map +0 -1
- package/dist/orchestration/renewal.d.ts +0 -103
- package/dist/orchestration/renewal.d.ts.map +0 -1
- package/dist/orchestration/renewal.js +0 -1099
- package/dist/orchestration/renewal.js.map +0 -1
- package/dist/orchestration/request.d.ts +0 -65
- package/dist/orchestration/request.d.ts.map +0 -1
- package/dist/orchestration/request.js +0 -134
- package/dist/orchestration/request.js.map +0 -1
- package/dist/orchestration/retention.d.ts +0 -100
- package/dist/orchestration/retention.d.ts.map +0 -1
- package/dist/orchestration/retention.js +0 -134
- package/dist/orchestration/retention.js.map +0 -1
- package/dist/orchestration/routing.d.ts +0 -21
- package/dist/orchestration/routing.d.ts.map +0 -1
- package/dist/orchestration/routing.js +0 -93
- package/dist/orchestration/routing.js.map +0 -1
- package/dist/orchestration/scheduler-key.d.ts +0 -14
- package/dist/orchestration/scheduler-key.d.ts.map +0 -1
- package/dist/orchestration/scheduler-key.js +0 -62
- package/dist/orchestration/scheduler-key.js.map +0 -1
- package/dist/orchestration/scheduler-policy.d.ts +0 -246
- package/dist/orchestration/scheduler-policy.d.ts.map +0 -1
- package/dist/orchestration/scheduler-policy.js +0 -668
- package/dist/orchestration/scheduler-policy.js.map +0 -1
- package/dist/orchestration/scheduler.d.ts +0 -393
- package/dist/orchestration/scheduler.d.ts.map +0 -1
- package/dist/orchestration/scheduler.js +0 -2621
- package/dist/orchestration/scheduler.js.map +0 -1
- package/dist/orchestration/source-slot.d.ts +0 -124
- package/dist/orchestration/source-slot.d.ts.map +0 -1
- package/dist/orchestration/source-slot.js +0 -348
- package/dist/orchestration/source-slot.js.map +0 -1
- package/dist/orchestration/types.d.ts +0 -1462
- package/dist/orchestration/types.d.ts.map +0 -1
- package/dist/orchestration/types.js +0 -135
- package/dist/orchestration/types.js.map +0 -1
- package/dist/protobuf.d.ts +0 -63
- package/dist/protobuf.d.ts.map +0 -1
- package/dist/protobuf.js +0 -252
- package/dist/protobuf.js.map +0 -1
- package/dist/session/_internal/acquire.d.ts +0 -21
- package/dist/session/_internal/acquire.d.ts.map +0 -1
- package/dist/session/_internal/acquire.js +0 -168
- package/dist/session/_internal/acquire.js.map +0 -1
- package/dist/session/_internal/cleanup.d.ts +0 -19
- package/dist/session/_internal/cleanup.d.ts.map +0 -1
- package/dist/session/_internal/cleanup.js +0 -102
- package/dist/session/_internal/cleanup.js.map +0 -1
- package/dist/session/_internal/lifecycle.d.ts +0 -67
- package/dist/session/_internal/lifecycle.d.ts.map +0 -1
- package/dist/session/_internal/lifecycle.js +0 -142
- package/dist/session/_internal/lifecycle.js.map +0 -1
- package/dist/session/_internal/remote.d.ts +0 -28
- package/dist/session/_internal/remote.d.ts.map +0 -1
- package/dist/session/_internal/remote.js +0 -71
- package/dist/session/_internal/remote.js.map +0 -1
- package/dist/session/_internal/uploads.d.ts +0 -7
- package/dist/session/_internal/uploads.d.ts.map +0 -1
- package/dist/session/_internal/uploads.js +0 -31
- package/dist/session/_internal/uploads.js.map +0 -1
- package/dist/session/commands.d.ts +0 -2
- package/dist/session/commands.d.ts.map +0 -1
- package/dist/session/commands.js +0 -2
- package/dist/session/commands.js.map +0 -1
- package/dist/session/files.d.ts +0 -21
- package/dist/session/files.d.ts.map +0 -1
- package/dist/session/files.js +0 -49
- package/dist/session/files.js.map +0 -1
- package/dist/session/index.d.ts +0 -84
- package/dist/session/index.d.ts.map +0 -1
- package/dist/session/index.js +0 -16
- package/dist/session/index.js.map +0 -1
- package/dist/session/media.d.ts +0 -114
- package/dist/session/media.d.ts.map +0 -1
- package/dist/session/media.js +0 -2
- package/dist/session/media.js.map +0 -1
- package/dist/session/recorder.d.ts +0 -24
- package/dist/session/recorder.d.ts.map +0 -1
- package/dist/session/recorder.js +0 -19
- package/dist/session/recorder.js.map +0 -1
- package/dist/session.d.ts +0 -105
- package/dist/session.d.ts.map +0 -1
- package/dist/session.js +0 -976
- package/dist/session.js.map +0 -1
- package/dist/simulation/_internal/source.d.ts +0 -12
- package/dist/simulation/_internal/source.d.ts.map +0 -1
- package/dist/simulation/_internal/source.js +0 -513
- package/dist/simulation/_internal/source.js.map +0 -1
- package/dist/simulation/index.d.ts +0 -13
- package/dist/simulation/index.d.ts.map +0 -1
- package/dist/simulation/index.js +0 -12
- package/dist/simulation/index.js.map +0 -1
- package/dist/simulation/types.d.ts +0 -39
- package/dist/simulation/types.d.ts.map +0 -1
- package/dist/simulation/types.js +0 -2
- package/dist/simulation/types.js.map +0 -1
- package/dist/stats.d.ts.map +0 -1
- package/dist/stats.js +0 -205
- package/dist/stats.js.map +0 -1
- package/dist/testing/Faults.d.ts +0 -4
- package/dist/testing/Faults.d.ts.map +0 -1
- package/dist/testing/Faults.js +0 -7
- package/dist/testing/Faults.js.map +0 -1
- package/dist/testing/Png.d.ts +0 -3
- package/dist/testing/Png.d.ts.map +0 -1
- package/dist/testing/Png.js.map +0 -1
- package/dist/testing/Wav.d.ts +0 -14
- package/dist/testing/Wav.d.ts.map +0 -1
- package/dist/testing/Wav.js +0 -37
- package/dist/testing/Wav.js.map +0 -1
- package/dist/testing/index.d.ts +0 -5
- package/dist/testing/index.d.ts.map +0 -1
- package/dist/testing/index.js +0 -4
- package/dist/testing/index.js.map +0 -1
- package/dist/wire.d.ts +0 -7
- package/dist/wire.d.ts.map +0 -1
- package/dist/wire.generated.d.ts +0 -305
- package/dist/wire.generated.d.ts.map +0 -1
- package/dist/wire.generated.js +0 -1257
- package/dist/wire.generated.js.map +0 -1
- package/dist/wire.js +0 -5
- package/dist/wire.js.map +0 -1
|
@@ -0,0 +1,672 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The H3 provider over a connected session. One fiber applies the session's
|
|
3
|
+
* events to the reducer; commands wait on the state it publishes rather than
|
|
4
|
+
* on waiter registries, and every transition returns the waiters it settles.
|
|
5
|
+
*/
|
|
6
|
+
import * as Crypto from "effect/Crypto";
|
|
7
|
+
import * as Deferred from "effect/Deferred";
|
|
8
|
+
import * as Effect from "effect/Effect";
|
|
9
|
+
import * as Exit from "effect/Exit";
|
|
10
|
+
import * as Fiber from "effect/Fiber";
|
|
11
|
+
import * as Option from "effect/Option";
|
|
12
|
+
import * as Redacted from "effect/Redacted";
|
|
13
|
+
import * as Ref from "effect/Ref";
|
|
14
|
+
import * as Result from "effect/Result";
|
|
15
|
+
import * as Schema from "effect/Schema";
|
|
16
|
+
import * as Scope from "effect/Scope";
|
|
17
|
+
import * as Semaphore from "effect/Semaphore";
|
|
18
|
+
import * as Stream from "effect/Stream";
|
|
19
|
+
import * as SubscriptionRef from "effect/SubscriptionRef";
|
|
20
|
+
import { CommandFailure, ReactorError, Remote } from "../../ReactorError.js";
|
|
21
|
+
import * as Submission from "./submission.js";
|
|
22
|
+
import * as Deadline from "../deadline.js";
|
|
23
|
+
import * as Hub from "../hub.js";
|
|
24
|
+
import { Commands, deploymentContract } from "./commands.js";
|
|
25
|
+
import { decodeMessage, Payloads } from "./messages.js";
|
|
26
|
+
import * as Operations from "./operations.js";
|
|
27
|
+
import { canvases } from "./profile.js";
|
|
28
|
+
import { materialOf, validateAudioReference, validateReference } from "./references.js";
|
|
29
|
+
import { enqueueArguments, Request } from "./request.js";
|
|
30
|
+
import * as State from "./state.js";
|
|
31
|
+
/** Bounds on what the provider retains; none is an application setting. */
|
|
32
|
+
const bounds = {
|
|
33
|
+
pending: 128,
|
|
34
|
+
clips: 4096,
|
|
35
|
+
acceptances: 1024,
|
|
36
|
+
operations: 1024,
|
|
37
|
+
uploads: 256,
|
|
38
|
+
observation: 1024,
|
|
39
|
+
};
|
|
40
|
+
const localFailure = (operation, cause) => CommandFailure.from(cause, { ...cause.context, operation, outcome: "not-submitted" });
|
|
41
|
+
/** `operation` refused before anything was sent. */
|
|
42
|
+
const refused = (operation, code, message) => localFailure(operation, ReactorError.fromCode(code, message));
|
|
43
|
+
const uncertain = (operation, source, message, cause) => CommandFailure.from(cause ?? ReactorError.fromCode("UnexpectedReply", message), {
|
|
44
|
+
...cause?.context,
|
|
45
|
+
operation,
|
|
46
|
+
outcome: "unknown",
|
|
47
|
+
requestId: source.requestId,
|
|
48
|
+
generation: source.generation,
|
|
49
|
+
});
|
|
50
|
+
/** H3's refusal reason is free text with no stable codes: kept for diagnosis only. */
|
|
51
|
+
const rejected = (operation, source, reason) => CommandFailure.make({
|
|
52
|
+
reason: Remote.make({
|
|
53
|
+
_tag: "Remote",
|
|
54
|
+
message: `H3 ${operation} was refused`,
|
|
55
|
+
body: Redacted.make(reason),
|
|
56
|
+
}),
|
|
57
|
+
context: {
|
|
58
|
+
operation,
|
|
59
|
+
outcome: "replied",
|
|
60
|
+
requestId: source.requestId,
|
|
61
|
+
generation: source.generation,
|
|
62
|
+
},
|
|
63
|
+
});
|
|
64
|
+
const hex = (bytes) => Array.from(bytes, (byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
65
|
+
/** The clips a message lists: a queue's three lists, or a lifecycle message's one clip. */
|
|
66
|
+
const clipsOf = (message) => {
|
|
67
|
+
if (message.type === "queue_update")
|
|
68
|
+
return [...message.data.generation, ...message.data.playout, ...message.data.history];
|
|
69
|
+
return "clip" in message.data ? [message.data.clip] : [];
|
|
70
|
+
};
|
|
71
|
+
/** An enqueue's outcome as its span records it; an interruption records none. */
|
|
72
|
+
const outcomeOf = (exit) => {
|
|
73
|
+
if (Exit.isSuccess(exit))
|
|
74
|
+
return { "reactor.command.outcome": "replied" };
|
|
75
|
+
const error = Exit.findError(exit);
|
|
76
|
+
return error._tag === "Success"
|
|
77
|
+
? {
|
|
78
|
+
"reactor.command.outcome": error.success.context.outcome,
|
|
79
|
+
"error.type": error.success.reason._tag,
|
|
80
|
+
}
|
|
81
|
+
: {};
|
|
82
|
+
};
|
|
83
|
+
/** Whether a snapshot at `revision` already reflects `event`. */
|
|
84
|
+
const covered = (event, revision) => {
|
|
85
|
+
switch (event._tag) {
|
|
86
|
+
case "Acceptance":
|
|
87
|
+
return false;
|
|
88
|
+
case "Diagnostic":
|
|
89
|
+
return event.source !== undefined && event.source.sequence <= revision;
|
|
90
|
+
default:
|
|
91
|
+
return event.source.sequence <= revision;
|
|
92
|
+
}
|
|
93
|
+
};
|
|
94
|
+
const build = Effect.fnUntraced(function* (session, options) {
|
|
95
|
+
const scope = yield* Effect.scope;
|
|
96
|
+
const crypto = yield* Crypto.Crypto;
|
|
97
|
+
const limits = {
|
|
98
|
+
command: yield* Deadline.decode("H3 replyTimeout")(options.replyTimeout ?? "15 seconds"),
|
|
99
|
+
upload: yield* Deadline.decode("H3 uploadTimeout")(options.uploadTimeout ?? "60 seconds"),
|
|
100
|
+
setup: yield* Deadline.decode("H3 setupTimeout")(options.setupTimeout ?? "60 seconds"),
|
|
101
|
+
reconcile: yield* Deadline.decode("H3 reconcileWindow")(options.reconcileWindow ?? "5 seconds"),
|
|
102
|
+
};
|
|
103
|
+
// A provider attaches to an already connected session. It neither allocates
|
|
104
|
+
// nor connects it, and never takes ownership of its remote lifetime.
|
|
105
|
+
yield* session.ready;
|
|
106
|
+
const observation = yield* session.observe({ capacity: bounds.observation });
|
|
107
|
+
const namespace = hex(yield* crypto.randomBytes(State.namespaceBytes).pipe(Effect.mapError(() => ReactorError.fromCode("InvalidState", "Could not allocate an H3 acceptance namespace", {
|
|
108
|
+
outcome: "not-submitted",
|
|
109
|
+
}))));
|
|
110
|
+
const hub = yield* Hub.make();
|
|
111
|
+
const fatal = yield* Deferred.make();
|
|
112
|
+
const counter = yield* Ref.make(0n);
|
|
113
|
+
const uploads = yield* Ref.make(new Map());
|
|
114
|
+
const uploadGate = yield* Semaphore.make(1);
|
|
115
|
+
const state = yield* SubscriptionRef.make({
|
|
116
|
+
model: State.initial({
|
|
117
|
+
sessionId: session.id,
|
|
118
|
+
generation: observation.initial.generation,
|
|
119
|
+
revision: observation.revision,
|
|
120
|
+
maxClips: bounds.clips,
|
|
121
|
+
}),
|
|
122
|
+
closed: false,
|
|
123
|
+
fatal: undefined,
|
|
124
|
+
pending: new Map(),
|
|
125
|
+
acceptances: new Map(),
|
|
126
|
+
operations: Operations.empty(bounds.operations),
|
|
127
|
+
});
|
|
128
|
+
/** Applies a transition atomically, then settles the waiters it names, in order. */
|
|
129
|
+
const step = (transition) => SubscriptionRef.modify(state, (internal) => {
|
|
130
|
+
const [next, effects] = transition(internal);
|
|
131
|
+
return [effects, next];
|
|
132
|
+
}).pipe(Effect.flatMap((effects) => Effect.forEach(effects, (effect) => effect, { discard: true })));
|
|
133
|
+
const withPending = (internal, id, pending) => {
|
|
134
|
+
const next = new Map(internal.pending);
|
|
135
|
+
if (pending === undefined)
|
|
136
|
+
next.delete(id);
|
|
137
|
+
else
|
|
138
|
+
next.set(id, pending);
|
|
139
|
+
return { ...internal, pending: next };
|
|
140
|
+
};
|
|
141
|
+
/** Records a submission's acceptance, resolves its waiter and announces it. */
|
|
142
|
+
const record = (internal, entry, acceptance) => {
|
|
143
|
+
const acceptances = new Map(internal.acceptances);
|
|
144
|
+
if (acceptances.size >= bounds.acceptances)
|
|
145
|
+
acceptances.delete(acceptances.keys().next().value ?? "");
|
|
146
|
+
acceptances.set(entry.id, acceptance);
|
|
147
|
+
const [operations, settled] = Operations.accept({ table: internal.operations, acceptance });
|
|
148
|
+
return [
|
|
149
|
+
{
|
|
150
|
+
...withPending(internal, entry.id, { ...entry, held: undefined }),
|
|
151
|
+
acceptances,
|
|
152
|
+
operations,
|
|
153
|
+
},
|
|
154
|
+
[
|
|
155
|
+
Effect.asVoid(Deferred.succeed(entry.deferred, acceptance)),
|
|
156
|
+
...settled,
|
|
157
|
+
hub.publish({ _tag: "Acceptance", acceptance }),
|
|
158
|
+
],
|
|
159
|
+
];
|
|
160
|
+
};
|
|
161
|
+
/** Held evidence decides once the reply cannot: it was lost, or it came without correlating. */
|
|
162
|
+
const decideHeld = (internal, id) => {
|
|
163
|
+
const entry = internal.pending.get(id);
|
|
164
|
+
return entry?.held === undefined ? [internal, []] : record(internal, entry, entry.held);
|
|
165
|
+
};
|
|
166
|
+
const sequence = (internal, transitions) => {
|
|
167
|
+
let current = internal;
|
|
168
|
+
const effects = [];
|
|
169
|
+
for (const transition of transitions) {
|
|
170
|
+
const [next, more] = transition(current);
|
|
171
|
+
current = next;
|
|
172
|
+
effects.push(...more);
|
|
173
|
+
}
|
|
174
|
+
return [current, effects];
|
|
175
|
+
};
|
|
176
|
+
/**
|
|
177
|
+
* The provider fails for good. Held evidence is recorded first, so a waiter
|
|
178
|
+
* it resumes already finds the provider refusing new work.
|
|
179
|
+
*/
|
|
180
|
+
const failProvider = (error) => (internal) => {
|
|
181
|
+
if (internal.fatal !== undefined)
|
|
182
|
+
return [internal, []];
|
|
183
|
+
const failed = {
|
|
184
|
+
...internal,
|
|
185
|
+
fatal: error,
|
|
186
|
+
model: State.unavailable({ model: internal.model, cause: error }),
|
|
187
|
+
};
|
|
188
|
+
const [decided, recorded] = sequence(failed, [...failed.pending.keys()].map((id) => (current) => decideHeld(current, id)));
|
|
189
|
+
return [
|
|
190
|
+
decided,
|
|
191
|
+
[
|
|
192
|
+
...recorded,
|
|
193
|
+
Effect.asVoid(Deferred.succeed(fatal, error)),
|
|
194
|
+
...[...decided.pending.values()].map((entry) => Effect.asVoid(Deferred.fail(entry.deferred, error))),
|
|
195
|
+
hub.publish({ _tag: "Diagnostic", error }),
|
|
196
|
+
],
|
|
197
|
+
];
|
|
198
|
+
};
|
|
199
|
+
const accept = (clip, source) => (internal) => {
|
|
200
|
+
const id = State.submissionFromMetadata({ namespace, metadata: clip.metadata });
|
|
201
|
+
if (id === undefined)
|
|
202
|
+
return [internal, []];
|
|
203
|
+
const entry = internal.pending.get(id);
|
|
204
|
+
const acceptance = entry === undefined ? undefined : State.acceptanceFor({ identity: entry, clip, source });
|
|
205
|
+
if (entry === undefined || acceptance === undefined) {
|
|
206
|
+
// After the reconcile window, or in a later generation, the evidence
|
|
207
|
+
// can still resolve the operation, never the acceptances.
|
|
208
|
+
const [operations, settled] = Operations.lateEvidence({
|
|
209
|
+
table: internal.operations,
|
|
210
|
+
id,
|
|
211
|
+
clip,
|
|
212
|
+
source,
|
|
213
|
+
});
|
|
214
|
+
return [{ ...internal, operations }, settled];
|
|
215
|
+
}
|
|
216
|
+
const previous = internal.acceptances.get(id) ?? entry.held;
|
|
217
|
+
if (previous !== undefined && previous.clip.clip_id !== clip.clip_id)
|
|
218
|
+
return failProvider(ReactorError.fromCode("Protocol", "H3 acceptance identity named two clips", {
|
|
219
|
+
operation: "enqueue",
|
|
220
|
+
}))(internal);
|
|
221
|
+
if (internal.acceptances.has(id))
|
|
222
|
+
return [internal, []];
|
|
223
|
+
// Until the reply is observed it may still correlate the acceptance; the
|
|
224
|
+
// clip's facts accrue meanwhile.
|
|
225
|
+
if (acceptance.evidence.kind === "metadata" && entry.awaiting)
|
|
226
|
+
return entry.held === undefined
|
|
227
|
+
? [
|
|
228
|
+
{
|
|
229
|
+
...withPending(internal, id, { ...entry, held: acceptance }),
|
|
230
|
+
operations: Operations.identify({ table: internal.operations, acceptance }),
|
|
231
|
+
},
|
|
232
|
+
[],
|
|
233
|
+
]
|
|
234
|
+
: [internal, []];
|
|
235
|
+
return record(internal, entry, acceptance);
|
|
236
|
+
};
|
|
237
|
+
const disconnected = ReactorError.fromCode("Disconnected", "H3 acceptance crossed a transport generation", { operation: "enqueue" });
|
|
238
|
+
const reduce = (source) => (internal) => {
|
|
239
|
+
if (internal.closed || internal.fatal !== undefined)
|
|
240
|
+
return [internal, []];
|
|
241
|
+
const [disposition, admitted] = State.admit({ model: internal.model, source });
|
|
242
|
+
let current = { ...internal, model: admitted };
|
|
243
|
+
const effects = [];
|
|
244
|
+
if (admitted.generation !== internal.model.generation) {
|
|
245
|
+
effects.push(Ref.set(uploads, new Map()));
|
|
246
|
+
// No reply to an earlier generation's enqueue can correlate now.
|
|
247
|
+
for (const entry of current.pending.values())
|
|
248
|
+
if (entry.generation !== source.generation) {
|
|
249
|
+
const [decided, recorded] = decideHeld(current, entry.id);
|
|
250
|
+
current = decided;
|
|
251
|
+
effects.push(...recorded, Effect.asVoid(Deferred.fail(entry.deferred, disconnected)));
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
if (source._tag !== "Model")
|
|
255
|
+
return [current, [...effects, hub.publish({ _tag: "Session", source })]];
|
|
256
|
+
if (source.kind === "ack")
|
|
257
|
+
return [current, [...effects, hub.publish({ _tag: "Acknowledged", source })]];
|
|
258
|
+
const decoded = decodeMessage(source);
|
|
259
|
+
if (Result.isFailure(decoded)) {
|
|
260
|
+
const [failed, failure] = failProvider(decoded.failure)(current);
|
|
261
|
+
return [failed, [...effects, ...failure]];
|
|
262
|
+
}
|
|
263
|
+
const message = decoded.success;
|
|
264
|
+
let applied = disposition;
|
|
265
|
+
if (disposition === "applied") {
|
|
266
|
+
const result = State.apply({ model: current.model, message, source });
|
|
267
|
+
if (Result.isFailure(result)) {
|
|
268
|
+
const [failed, failure] = failProvider(result.failure)(current);
|
|
269
|
+
return [failed, [...effects, ...failure]];
|
|
270
|
+
}
|
|
271
|
+
applied = result.success[0];
|
|
272
|
+
current = { ...current, model: result.success[1] };
|
|
273
|
+
}
|
|
274
|
+
if (applied !== "stale" && message.type !== "unknown") {
|
|
275
|
+
const clips = clipsOf(message);
|
|
276
|
+
const [accepted, acceptedEffects] = sequence(current, clips.map((clip) => accept(clip, source)));
|
|
277
|
+
const [operations, observed] = Operations.observe({
|
|
278
|
+
table: accepted.operations,
|
|
279
|
+
message,
|
|
280
|
+
source,
|
|
281
|
+
});
|
|
282
|
+
current = { ...accepted, operations };
|
|
283
|
+
effects.push(...acceptedEffects, ...observed);
|
|
284
|
+
}
|
|
285
|
+
return [
|
|
286
|
+
current,
|
|
287
|
+
[...effects, hub.publish({ _tag: "Message", message, source, disposition: applied })],
|
|
288
|
+
];
|
|
289
|
+
};
|
|
290
|
+
yield* Effect.addFinalizer(() => step((internal) => {
|
|
291
|
+
const [failed, failure] = failProvider(ReactorError.fromCode("Closed", "H3 provider scope closed", {
|
|
292
|
+
operation: "H3 observation",
|
|
293
|
+
}))(internal);
|
|
294
|
+
const [operations, retired] = Operations.retire(failed.operations);
|
|
295
|
+
return [
|
|
296
|
+
{ ...failed, closed: true, pending: new Map(), operations },
|
|
297
|
+
[...failure, ...retired, hub.end],
|
|
298
|
+
];
|
|
299
|
+
}));
|
|
300
|
+
yield* observation.events.pipe(Stream.runForEach((source) => step(reduce(source))), Effect.catch((error) => error.pipe(failProvider, step)), Effect.andThen(step((internal) => internal.closed
|
|
301
|
+
? [internal, []]
|
|
302
|
+
: failProvider(ReactorError.fromCode("Closed", "H3 session observation ended"))(internal))), Effect.forkScoped);
|
|
303
|
+
// Enqueues run in a scope of their own. Finalizers run last-added first, so a
|
|
304
|
+
// closing provider refuses new work before that scope interrupts them.
|
|
305
|
+
const executions = yield* Scope.fork(scope);
|
|
306
|
+
yield* Effect.addFinalizer(() => SubscriptionRef.update(state, (internal) => ({ ...internal, closed: true })));
|
|
307
|
+
const refusal = (internal, needsFacts) => internal.closed
|
|
308
|
+
? ReactorError.fromCode("Closed", "H3 provider scope is closed")
|
|
309
|
+
: (internal.fatal ??
|
|
310
|
+
(needsFacts && State.availability(internal.model) !== "Ready"
|
|
311
|
+
? ReactorError.fromCode("InvalidState", "H3 provider needs current state and queue observations")
|
|
312
|
+
: undefined));
|
|
313
|
+
/** Waits, within one reply deadline, while the provider is only synchronizing. */
|
|
314
|
+
const settled = SubscriptionRef.changes(state).pipe(Stream.filter((internal) => refusal(internal, false) !== undefined ||
|
|
315
|
+
State.availability(internal.model) !== "Synchronizing"), Stream.runHead, Effect.timeoutOption(limits.command), Effect.asVoid);
|
|
316
|
+
const active = Effect.fnUntraced(function* (operation, needsFacts) {
|
|
317
|
+
if (needsFacts)
|
|
318
|
+
yield* settled;
|
|
319
|
+
const error = refusal(yield* SubscriptionRef.get(state), needsFacts);
|
|
320
|
+
if (error !== undefined)
|
|
321
|
+
return yield* localFailure(operation, error);
|
|
322
|
+
});
|
|
323
|
+
/**
|
|
324
|
+
* The reducer's own reading of a reply: it waits until the reducer applied
|
|
325
|
+
* the reply's event, so the caller reads the effects its command caused.
|
|
326
|
+
*/
|
|
327
|
+
const awaitReply = Effect.fnUntraced(function* (source) {
|
|
328
|
+
const reached = yield* SubscriptionRef.changes(state).pipe(Stream.filter((internal) => internal.model.revision >= source.sequence ||
|
|
329
|
+
internal.model.generation > source.generation ||
|
|
330
|
+
refusal(internal, false) !== undefined), Stream.runHead, Effect.timeoutOption(limits.command));
|
|
331
|
+
const internal = reached._tag === "Some" && reached.value._tag === "Some" ? reached.value.value : undefined;
|
|
332
|
+
if (internal === undefined)
|
|
333
|
+
return yield* ReactorError.fromCode("Timeout", "H3 did not observe the command's exact returned envelope");
|
|
334
|
+
if (internal.model.revision < source.sequence) {
|
|
335
|
+
const error = refusal(internal, false);
|
|
336
|
+
if (error !== undefined)
|
|
337
|
+
return yield* error;
|
|
338
|
+
}
|
|
339
|
+
if (source.correlation === "stale-generation" ||
|
|
340
|
+
(internal.model.revision < source.sequence && internal.model.generation > source.generation))
|
|
341
|
+
return yield* ReactorError.fromCode("Disconnected", "H3 received a stale command reply");
|
|
342
|
+
if (source.kind === "ack")
|
|
343
|
+
return undefined;
|
|
344
|
+
return yield* Effect.fromResult(decodeMessage(source));
|
|
345
|
+
});
|
|
346
|
+
const call = Effect.fnUntraced(function* (operation, args, needsFacts) {
|
|
347
|
+
if (!contract.commands.has(operation))
|
|
348
|
+
return yield* refused(operation, "UnsupportedCapability", `The deployment does not offer H3 ${operation}`);
|
|
349
|
+
yield* active(operation, needsFacts);
|
|
350
|
+
const source = yield* session.command(operation, args, { replyTimeout: limits.command });
|
|
351
|
+
const message = yield* awaitReply(source).pipe(Effect.mapError((error) => uncertain(operation, source, "H3 reply observation failed", error)));
|
|
352
|
+
if (message?.type === "command_error" && message.data.command === operation)
|
|
353
|
+
return yield* rejected(operation, source, message.data.reason);
|
|
354
|
+
return { source, message };
|
|
355
|
+
});
|
|
356
|
+
const named = (operation, args, needsFacts = true) => {
|
|
357
|
+
const expected = Commands[operation].reply;
|
|
358
|
+
return call(operation, args, needsFacts).pipe(Effect.flatMap(({ source, message }) => message?.type === expected
|
|
359
|
+
? // The payload is read back as its command's reply type, which TypeScript
|
|
360
|
+
// cannot correlate with the command. The broadcasts a reply implies follow
|
|
361
|
+
// it: the command settles once they are observed. The state and queue
|
|
362
|
+
// reads are that barrier themselves.
|
|
363
|
+
Schema.decodeEffect(Payloads[expected])(message.data).pipe(Effect.mapError(() => uncertain(operation, source, `H3 ${operation} reply is malformed`)), Effect.flatMap((value) => Effect.as(needsFacts ? settled : Effect.void, { value, source })))
|
|
364
|
+
: Effect.fail(uncertain(operation, source, `H3 ${operation} did not return ${expected}`))));
|
|
365
|
+
};
|
|
366
|
+
const control = (operation, args) => call(operation, args, true).pipe(Effect.flatMap(({ source, message }) => {
|
|
367
|
+
if (source.kind === "ack")
|
|
368
|
+
return Effect.succeed({ _tag: "Acknowledged", source });
|
|
369
|
+
if (message === undefined || message.type === "unknown")
|
|
370
|
+
return Effect.fail(uncertain(operation, source, "Unexpected H3 control response"));
|
|
371
|
+
return Effect.as(settled, { _tag: "Reply", message, source });
|
|
372
|
+
}));
|
|
373
|
+
const getState = named("get_state", {}, false);
|
|
374
|
+
const getQueue = named("get_queue", {}, false);
|
|
375
|
+
const refresh = getState.pipe(Effect.andThen(getQueue), Effect.flatMap((reply) => Effect.flatMap(SubscriptionRef.get(state), (internal) => State.availability(internal.model) === "Ready"
|
|
376
|
+
? Effect.void
|
|
377
|
+
: Effect.fail(CommandFailure.from(ReactorError.fromCode("InvalidState", "H3 full snapshots changed during refresh"), {
|
|
378
|
+
operation: "H3 refresh",
|
|
379
|
+
outcome: "replied",
|
|
380
|
+
requestId: reply.source.requestId,
|
|
381
|
+
generation: reply.source.generation,
|
|
382
|
+
})))));
|
|
383
|
+
/** One reference's upload, content-addressed within a transport generation. */
|
|
384
|
+
const upload = Effect.fnUntraced(function* (reference, generation) {
|
|
385
|
+
const material = materialOf(reference);
|
|
386
|
+
if (material === undefined)
|
|
387
|
+
return yield* refused("enqueue", "InvalidInput", "Reference was not validated by H3");
|
|
388
|
+
if (material._tag === "Uploaded")
|
|
389
|
+
return material.file;
|
|
390
|
+
const digest = yield* crypto
|
|
391
|
+
.digest("SHA-256", material.bytes)
|
|
392
|
+
.pipe(Effect.mapError(() => refused("enqueue", "InvalidState", "Could not hash an H3 reference")));
|
|
393
|
+
const key = `${generation}:${hex(digest)}`;
|
|
394
|
+
return yield* uploadGate.withPermit(Effect.gen(function* () {
|
|
395
|
+
const cached = (yield* Ref.get(uploads)).get(key);
|
|
396
|
+
if (cached !== undefined)
|
|
397
|
+
return cached;
|
|
398
|
+
const uploaded = yield* session
|
|
399
|
+
.upload(`h3-${hex(digest)}`, reference.mimeType, material.bytes, {
|
|
400
|
+
uploadTimeout: limits.upload,
|
|
401
|
+
})
|
|
402
|
+
.pipe(Effect.mapError((error) => localFailure("enqueue", error)));
|
|
403
|
+
if (uploaded.file.size !== BigInt(reference.size) ||
|
|
404
|
+
uploaded.file.mimeType !== reference.mimeType)
|
|
405
|
+
return yield* refused("enqueue", "Protocol", "H3 upload returned different file facts");
|
|
406
|
+
if ((yield* SubscriptionRef.get(state)).model.generation !== generation)
|
|
407
|
+
return yield* refused("enqueue", "Disconnected", "H3 reference upload crossed a generation");
|
|
408
|
+
yield* Ref.update(uploads, (all) => {
|
|
409
|
+
const next = new Map(all);
|
|
410
|
+
if (next.size >= bounds.uploads)
|
|
411
|
+
next.delete(next.keys().next().value ?? "");
|
|
412
|
+
return next.set(key, uploaded.file);
|
|
413
|
+
});
|
|
414
|
+
return uploaded.file;
|
|
415
|
+
}));
|
|
416
|
+
});
|
|
417
|
+
/** The request as the caller gave it, decoded and with its references validated and copied. */
|
|
418
|
+
const capture = Effect.fnUntraced(function* (input) {
|
|
419
|
+
const request = yield* Schema.decodeEffect(Request)(input).pipe(Effect.mapError((cause) => ReactorError.fromCode("InvalidInput", "Invalid H3 request", {
|
|
420
|
+
operation: "enqueue",
|
|
421
|
+
outcome: "not-submitted",
|
|
422
|
+
detail: cause,
|
|
423
|
+
})));
|
|
424
|
+
const references = yield* Effect.forEach(request.references ?? [], (reference) => Effect.fromResult(validateReference(reference)));
|
|
425
|
+
const audio = yield* Effect.forEach(request.audio ?? [], (reference) => Effect.fromResult(validateAudioReference(reference)));
|
|
426
|
+
const captured = { ...request, references, audio };
|
|
427
|
+
return captured;
|
|
428
|
+
});
|
|
429
|
+
const stage = Effect.fnUntraced(function* (request, metadata) {
|
|
430
|
+
yield* active("enqueue", true);
|
|
431
|
+
const internal = yield* SubscriptionRef.get(state);
|
|
432
|
+
const snapshot = State.snapshot(internal.model);
|
|
433
|
+
if (snapshot._tag !== "Ready")
|
|
434
|
+
return yield* refused("enqueue", "InvalidState", "H3 is not ready");
|
|
435
|
+
if (request.seconds !== undefined &&
|
|
436
|
+
(request.seconds < snapshot.state.clip_seconds_min ||
|
|
437
|
+
request.seconds > snapshot.state.clip_seconds_max))
|
|
438
|
+
return yield* refused("enqueue", "InvalidInput", "Clip duration is outside H3's accepted range");
|
|
439
|
+
if (request.audio.length > 0 && !contract.referenceAudio)
|
|
440
|
+
return yield* refused("enqueue", "UnsupportedCapability", "The H3 deployment does not declare reference audio");
|
|
441
|
+
const generation = snapshot.transportGeneration;
|
|
442
|
+
const images = yield* Effect.forEach(request.references, (reference) => upload(reference, generation));
|
|
443
|
+
const audio = yield* Effect.forEach(request.audio, (reference) => upload(reference, generation));
|
|
444
|
+
return { args: enqueueArguments({ request, images, audio, metadata }), generation };
|
|
445
|
+
});
|
|
446
|
+
const nextId = Ref.modify(counter, (n) => [`${namespace}:${n + 1n}`, n + 1n]);
|
|
447
|
+
/** Evidence held for `id` that has waited the reconcile window without its reply. */
|
|
448
|
+
const outwaited = (id) => SubscriptionRef.changes(state).pipe(Stream.filter((internal) => internal.pending.get(id)?.held !== undefined), Stream.runHead, Effect.andThen(Effect.sleep(limits.reconcile)));
|
|
449
|
+
/** The enqueue itself, run once in the submission's own execution fiber. */
|
|
450
|
+
const execute = Effect.fnUntraced(function* (id, args, entry) {
|
|
451
|
+
// The command waits for its reply in a fiber of its own, so held evidence can decide
|
|
452
|
+
// first. The request stays attributable after that, and nothing sends it again. That
|
|
453
|
+
// fiber starts at once, so the enqueue is handed to the transport before this execution
|
|
454
|
+
// goes on, as when the execution sent it itself: a command sent behind it stays behind.
|
|
455
|
+
const sending = yield* session
|
|
456
|
+
.command("enqueue", args, { replyTimeout: limits.command })
|
|
457
|
+
.pipe(Effect.forkIn(executions, { startImmediately: true }));
|
|
458
|
+
/**
|
|
459
|
+
* The reply's reading: a refusal fails the enqueue, and anything else is
|
|
460
|
+
* what it fails with when no evidence proves its clip.
|
|
461
|
+
*/
|
|
462
|
+
const replied = Effect.gen(function* () {
|
|
463
|
+
const sent = yield* sending.pipe(Fiber.join, Effect.result);
|
|
464
|
+
if (Result.isFailure(sent)) {
|
|
465
|
+
if (sent.failure.context.outcome !== "unknown")
|
|
466
|
+
return yield* sent.failure;
|
|
467
|
+
return sent.failure;
|
|
468
|
+
}
|
|
469
|
+
const source = sent.success;
|
|
470
|
+
const observed = yield* Effect.result(awaitReply(source));
|
|
471
|
+
if (Result.isSuccess(observed) &&
|
|
472
|
+
observed.success?.type === "command_error" &&
|
|
473
|
+
observed.success.data.command === "enqueue")
|
|
474
|
+
return yield* rejected("enqueue", source, observed.success.data.reason);
|
|
475
|
+
return uncertain("enqueue", source, "H3 enqueue has no proven clip acceptance", Result.isFailure(observed) ? observed.failure : undefined);
|
|
476
|
+
});
|
|
477
|
+
const answered = yield* Effect.raceFirst(Effect.asSome(replied), Effect.as(outwaited(id), Option.none()));
|
|
478
|
+
// The reply was observed, is lost, or stayed away past the window: evidence held
|
|
479
|
+
// meanwhile decides now.
|
|
480
|
+
yield* step((internal) => {
|
|
481
|
+
const current = internal.pending.get(id);
|
|
482
|
+
return current === undefined
|
|
483
|
+
? [internal, []]
|
|
484
|
+
: decideHeld(withPending(internal, id, { ...current, awaiting: false }), id);
|
|
485
|
+
});
|
|
486
|
+
// What the enqueue fails with if nothing settles it: the reply's reading, which is
|
|
487
|
+
// still to come when held evidence decided first.
|
|
488
|
+
const unproven = Option.isSome(answered)
|
|
489
|
+
? Effect.fail(answered.value)
|
|
490
|
+
: Effect.flatMap(replied, (failure) => Effect.fail(failure));
|
|
491
|
+
const acceptance = yield* Deferred.await(entry.deferred).pipe(Effect.timeoutOption(limits.reconcile), Effect.orElseSucceed(() => Option.none()), Effect.flatMap((decided) => Option.isSome(decided) ? Effect.succeed(decided.value) : unproven), Effect.withSpan("H3.reconcile", {}, { captureStackTrace: false }));
|
|
492
|
+
// An enqueue settles once the snapshots its reply implies are observed.
|
|
493
|
+
yield* settled;
|
|
494
|
+
return acceptance;
|
|
495
|
+
}, (effect, id) => Effect.onExit(effect, (exit) => step((internal) => {
|
|
496
|
+
// However the enqueue ends, the evidence it saw still decides; only a
|
|
497
|
+
// definite failure discards it.
|
|
498
|
+
const error = Exit.findError(exit);
|
|
499
|
+
const definite = error._tag === "Success" && error.success.context.outcome !== "unknown";
|
|
500
|
+
const [decided, recorded] = definite ? [internal, []] : decideHeld(internal, id);
|
|
501
|
+
const [operations, settledOperation] = Operations.settle({
|
|
502
|
+
table: decided.operations,
|
|
503
|
+
id,
|
|
504
|
+
exit,
|
|
505
|
+
});
|
|
506
|
+
return [
|
|
507
|
+
{ ...withPending(decided, id, undefined), operations },
|
|
508
|
+
[...recorded, ...settledOperation],
|
|
509
|
+
];
|
|
510
|
+
})),
|
|
511
|
+
// The span belongs to the execution fiber, so it ends with the enqueue's
|
|
512
|
+
// outcome even when the caller stopped waiting.
|
|
513
|
+
Effect.onExit((exit) => exit.pipe(outcomeOf, Effect.annotateCurrentSpan)), Effect.withSpan("H3.enqueue", (id) => ({ kind: "client", attributes: { "reactor.h3.submission.id": id } }), { captureStackTrace: false }));
|
|
514
|
+
const observeResult = (id, hooks, result) => hooks.result === undefined
|
|
515
|
+
? Effect.void
|
|
516
|
+
: Effect.suspend(() => hooks.result?.(id, result) ?? Effect.void).pipe(Effect.interruptible, Effect.timeoutOrElse({
|
|
517
|
+
duration: "1 second",
|
|
518
|
+
orElse: () => Effect.fail(ReactorError.fromCode("Timeout", "H3 result hook exceeded its deadline")),
|
|
519
|
+
}), Effect.exit, Effect.flatMap((exit) => Exit.isFailure(exit)
|
|
520
|
+
? hub.publish({
|
|
521
|
+
_tag: "Diagnostic",
|
|
522
|
+
error: ReactorError.fromCode("InvalidState", "H3 result hook failed", {
|
|
523
|
+
operation: "H3 result hook",
|
|
524
|
+
detail: exit.cause,
|
|
525
|
+
}),
|
|
526
|
+
})
|
|
527
|
+
: Effect.void));
|
|
528
|
+
const prepared = (id, request, metadata, hooks) => Submission.make({
|
|
529
|
+
id,
|
|
530
|
+
prepare: Effect.gen(function* () {
|
|
531
|
+
const staged = yield* stage(request, metadata);
|
|
532
|
+
const entry = {
|
|
533
|
+
id,
|
|
534
|
+
metadata,
|
|
535
|
+
prompt: request.prompt,
|
|
536
|
+
generation: staged.generation,
|
|
537
|
+
deferred: yield* Deferred.make(),
|
|
538
|
+
awaiting: true,
|
|
539
|
+
held: undefined,
|
|
540
|
+
};
|
|
541
|
+
return { args: staged.args, entry, waiters: yield* Operations.makeWaiters };
|
|
542
|
+
}),
|
|
543
|
+
commit: ({ entry, waiters }) => Effect.gen(function* () {
|
|
544
|
+
yield* active("enqueue", true);
|
|
545
|
+
const live = yield* session.ready.pipe(Effect.mapError((error) => localFailure("enqueue", error)));
|
|
546
|
+
// The operation's slot and the pending acceptance are taken together,
|
|
547
|
+
// before anything is sent.
|
|
548
|
+
const conflict = yield* SubscriptionRef.modify(state, (internal) => {
|
|
549
|
+
if (entry.generation !== internal.model.generation ||
|
|
550
|
+
live.generation !== entry.generation)
|
|
551
|
+
return [
|
|
552
|
+
ReactorError.fromCode("Disconnected", "H3 prepared input crossed a transport generation"),
|
|
553
|
+
internal,
|
|
554
|
+
];
|
|
555
|
+
if (internal.pending.size >= bounds.pending)
|
|
556
|
+
return [
|
|
557
|
+
ReactorError.fromCode("Overflow", "H3 pending acceptance bound reached"),
|
|
558
|
+
internal,
|
|
559
|
+
];
|
|
560
|
+
const reserved = Operations.reserve({
|
|
561
|
+
table: internal.operations,
|
|
562
|
+
identity: entry,
|
|
563
|
+
waiters,
|
|
564
|
+
});
|
|
565
|
+
return Result.isFailure(reserved)
|
|
566
|
+
? [reserved.failure, internal]
|
|
567
|
+
: [
|
|
568
|
+
undefined,
|
|
569
|
+
{ ...withPending(internal, id, entry), operations: reserved.success },
|
|
570
|
+
];
|
|
571
|
+
});
|
|
572
|
+
if (conflict !== undefined)
|
|
573
|
+
return yield* localFailure("enqueue", conflict);
|
|
574
|
+
if (hooks.commit !== undefined)
|
|
575
|
+
yield* hooks.commit(id).pipe(Effect.onExitIf(Exit.isFailure, () => SubscriptionRef.update(state, (internal) => ({
|
|
576
|
+
...withPending(internal, id, undefined),
|
|
577
|
+
operations: Operations.abandon({ table: internal.operations, id }),
|
|
578
|
+
}))));
|
|
579
|
+
}),
|
|
580
|
+
execute: ({ args, entry }) => Effect.result(execute(id, args, entry)).pipe(Effect.tap((result) => observeResult(id, hooks, result)), Effect.flatMap(Effect.fromResult)),
|
|
581
|
+
}).pipe(Scope.provide(executions));
|
|
582
|
+
const prepare = (input, hooks = {}) => Effect.gen(function* () {
|
|
583
|
+
yield* active("enqueue", true);
|
|
584
|
+
const id = yield* nextId;
|
|
585
|
+
const request = yield* capture(input);
|
|
586
|
+
const metadata = yield* Effect.fromResult(State.encodeMetadata({ namespace, submission: id, caller: request.metadata }));
|
|
587
|
+
return yield* prepared(id, request, metadata, hooks);
|
|
588
|
+
});
|
|
589
|
+
const clipId = (operation, id) => Schema.decodeEffect(Schema.String.check(Schema.isUUID()))(id).pipe(Effect.mapError(() => refused(operation, "InvalidInput", "clipId must be a UUID")));
|
|
590
|
+
const natural = (operation, name, value) => Number.isSafeInteger(value) && value >= 0
|
|
591
|
+
? Effect.succeed(value)
|
|
592
|
+
: Effect.fail(refused(operation, "InvalidInput", `${name} must be a nonnegative safe integer`));
|
|
593
|
+
const contract = yield* session.schema.pipe(Effect.flatMap(({ openapi }) => Effect.fromResult(deploymentContract(openapi))), Effect.timeoutOrElse({
|
|
594
|
+
duration: limits.setup,
|
|
595
|
+
orElse: () => Effect.fail(ReactorError.fromCode("Timeout", "H3 schema read timed out")),
|
|
596
|
+
}));
|
|
597
|
+
yield* refresh.pipe(Effect.timeoutOrElse({
|
|
598
|
+
duration: limits.setup,
|
|
599
|
+
orElse: () => Effect.fail(ReactorError.fromCode("Timeout", "H3 initial state and queue reads timed out")),
|
|
600
|
+
}));
|
|
601
|
+
const ready = yield* SubscriptionRef.get(state);
|
|
602
|
+
if (State.availability(ready.model) !== "Ready")
|
|
603
|
+
return yield* (ready.fatal ??
|
|
604
|
+
ReactorError.fromCode("InvalidState", "H3 initial observations are unavailable"));
|
|
605
|
+
const snapshot = Effect.map(SubscriptionRef.get(state), (internal) => State.snapshot(internal.model));
|
|
606
|
+
const provider = {
|
|
607
|
+
sessionId: session.id,
|
|
608
|
+
contract,
|
|
609
|
+
snapshot,
|
|
610
|
+
changes: Stream.map(SubscriptionRef.changes(state), (internal) => State.snapshot(internal.model)),
|
|
611
|
+
observe: (observeOptions) => Effect.gen(function* () {
|
|
612
|
+
const events = yield* hub.subscribe(observeOptions?.capacity);
|
|
613
|
+
const initial = yield* snapshot;
|
|
614
|
+
// The reducer may apply an event between the subscription and this read;
|
|
615
|
+
// the snapshot then covers it, so it is not repeated.
|
|
616
|
+
return {
|
|
617
|
+
initial,
|
|
618
|
+
revision: initial.revision,
|
|
619
|
+
events: Stream.filter(events, (event) => !covered(event, initial.revision)),
|
|
620
|
+
};
|
|
621
|
+
}),
|
|
622
|
+
events: (observeOptions) => Stream.unwrap(hub.subscribe(observeOptions?.capacity)),
|
|
623
|
+
failure: Deferred.await(fatal),
|
|
624
|
+
acceptance: (id) => Effect.map(SubscriptionRef.get(state), (internal) => internal.acceptances.get(id)),
|
|
625
|
+
operation: (submission) => Effect.acquireRelease(SubscriptionRef.modify(state, (internal) => {
|
|
626
|
+
const held = Operations.hold({ table: internal.operations, id: submission.id });
|
|
627
|
+
if (Result.isFailure(held))
|
|
628
|
+
return [Result.fail(held.failure), internal];
|
|
629
|
+
const operation = held.success.operations.get(submission.id);
|
|
630
|
+
return operation === undefined
|
|
631
|
+
? [
|
|
632
|
+
Result.fail(ReactorError.fromCode("InvalidState", "H3 clip operation vanished")),
|
|
633
|
+
internal,
|
|
634
|
+
]
|
|
635
|
+
: [Result.succeed(operation.waiters), { ...internal, operations: held.success }];
|
|
636
|
+
}).pipe(Effect.flatMap(Effect.fromResult)), () => SubscriptionRef.update(state, (internal) => ({
|
|
637
|
+
...internal,
|
|
638
|
+
operations: Operations.release({ table: internal.operations, id: submission.id }),
|
|
639
|
+
}))).pipe(Effect.map((waiters) => ({
|
|
640
|
+
submissionId: submission.id,
|
|
641
|
+
accepted: Deferred.await(waiters.accepted),
|
|
642
|
+
reached: (phase) => Deferred.await(phase === "generated" ? waiters.generated : waiters.started),
|
|
643
|
+
ended: Deferred.await(waiters.finished),
|
|
644
|
+
facts: Effect.map(SubscriptionRef.get(state), (internal) => Operations.factsOf({
|
|
645
|
+
id: submission.id,
|
|
646
|
+
operation: internal.operations.operations.get(submission.id),
|
|
647
|
+
})),
|
|
648
|
+
}))),
|
|
649
|
+
prepare,
|
|
650
|
+
enqueue: (request) => prepare(request).pipe(Effect.mapError((error) => ReactorError.is(error) ? localFailure("enqueue", error) : error), Effect.flatMap((submission) => submission.submit)),
|
|
651
|
+
getState,
|
|
652
|
+
getQueue,
|
|
653
|
+
refresh,
|
|
654
|
+
pop: (id) => clipId("pop", id).pipe(Effect.flatMap((clip) => named("pop", { clip_id: clip })), Effect.filterOrFail((reply) => reply.value.clip.clip_id === id, (reply) => uncertain("pop", reply.source, "H3 pop returned a different clip"))),
|
|
655
|
+
move: (id, position) => Effect.all([clipId("move", id), natural("move", "position", position)]).pipe(Effect.flatMap(([clip, at]) => named("move", { clip_id: clip, position: at })), Effect.filterOrFail((reply) => reply.value.clip.clip_id === id, (reply) => uncertain("move", reply.source, "H3 move returned a different clip"))),
|
|
656
|
+
play: (id) => (id === undefined ? Effect.succeed("") : clipId("play", id)).pipe(Effect.flatMap((clip) => control("play", { clip_id: clip }))),
|
|
657
|
+
stop: control("stop", {}),
|
|
658
|
+
setCanvas: (aspect) => Object.hasOwn(canvases, aspect)
|
|
659
|
+
? named("set_canvas", { aspect })
|
|
660
|
+
: Effect.fail(refused("set_canvas", "InvalidInput", "Unsupported H3 canvas aspect")),
|
|
661
|
+
setAutoplay: (enabled) => named("set_autoplay", { enabled }),
|
|
662
|
+
setFlushOnClipEnd: (enabled) => named("set_flush_on_clip_end", { enabled }),
|
|
663
|
+
reset: named("reset", {}),
|
|
664
|
+
};
|
|
665
|
+
return provider;
|
|
666
|
+
});
|
|
667
|
+
/** A failed acquisition closes its own observation scope at once. */
|
|
668
|
+
export const make = Effect.fn("H3.make")(function* (session, options = {}) {
|
|
669
|
+
const child = yield* Scope.fork(yield* Effect.scope);
|
|
670
|
+
return yield* build(session, options).pipe(Scope.provide(child), Effect.onExit((exit) => (Exit.isFailure(exit) ? Scope.close(child, exit) : Effect.void)));
|
|
671
|
+
});
|
|
672
|
+
//# sourceMappingURL=provider.js.map
|