floopy/resources/
experiments.rs1use std::sync::Arc;
2
3use futures::Stream;
4use reqwest::Method;
5
6use crate::constants::{
7 experiment_results, experiment_rollback, CONFIRM_EXPERIMENTS, ENDPOINT_EXPERIMENTS,
8 HEADER_CONFIRM,
9};
10use crate::error::Result;
11use crate::http::HttpTransport;
12use crate::options::RequestOptions;
13use crate::types::{
14 Experiment, ExperimentCreateParams, ExperimentListPage, ExperimentListParams, ExperimentResults,
15};
16
17use super::require;
18
19pub struct Experiments {
21 t: Arc<HttpTransport>,
22}
23
24fn with_confirm(req: Option<RequestOptions>) -> RequestOptions {
27 let mut req = req.unwrap_or_default();
28 req = req.header(HEADER_CONFIRM, CONFIRM_EXPERIMENTS);
29 req
30}
31
32impl Experiments {
33 pub(crate) fn new(t: Arc<HttpTransport>) -> Self {
34 Self { t }
35 }
36
37 pub async fn list(
43 &self,
44 params: &ExperimentListParams,
45 req: impl Into<Option<RequestOptions>>,
46 ) -> Result<ExperimentListPage> {
47 let (data, _) = self
48 .t
49 .request(
50 Method::GET,
51 ENDPOINT_EXPERIMENTS,
52 None,
53 ¶ms.query(),
54 req.into().as_ref(),
55 )
56 .await?;
57 require(data)
58 }
59
60 pub fn pages(
62 &self,
63 params: ExperimentListParams,
64 req: Option<RequestOptions>,
65 ) -> impl Stream<Item = Result<ExperimentListPage>> + Send + 'static {
66 let t = self.t.clone();
67 async_stream::try_stream! {
68 let mut params = params;
69 loop {
70 let (data, _) = t
71 .request::<ExperimentListPage>(
72 Method::GET,
73 ENDPOINT_EXPERIMENTS,
74 None,
75 ¶ms.query(),
76 req.as_ref(),
77 )
78 .await?;
79 let page = require(data)?;
80 let next = page.next_cursor.clone();
81 let has_more = page.has_more;
82 yield page;
83 match next {
84 Some(cursor) if has_more && !cursor.is_empty() => {
85 params.cursor = Some(cursor);
86 }
87 _ => break,
88 }
89 }
90 }
91 }
92
93 pub async fn create(
100 &self,
101 params: ExperimentCreateParams,
102 req: Option<RequestOptions>,
103 ) -> Result<Experiment> {
104 let body =
105 serde_json::to_value(¶ms).map_err(|e| crate::Error::Decode(e.to_string()))?;
106 let (data, _) = self
107 .t
108 .request(
109 Method::POST,
110 ENDPOINT_EXPERIMENTS,
111 Some(&body),
112 &[],
113 Some(&with_confirm(req)),
114 )
115 .await?;
116 require(data)
117 }
118
119 pub async fn rollback(
126 &self,
127 experiment_id: &str,
128 req: Option<RequestOptions>,
129 ) -> Result<Experiment> {
130 let (data, _) = self
131 .t
132 .request(
133 Method::POST,
134 &experiment_rollback(experiment_id),
135 None,
136 &[],
137 Some(&with_confirm(req)),
138 )
139 .await?;
140 require(data)
141 }
142
143 pub async fn results(
149 &self,
150 experiment_id: &str,
151 req: impl Into<Option<RequestOptions>>,
152 ) -> Result<ExperimentResults> {
153 let (data, _) = self
154 .t
155 .request(
156 Method::GET,
157 &experiment_results(experiment_id),
158 None,
159 &[],
160 req.into().as_ref(),
161 )
162 .await?;
163 require(data)
164 }
165}