meilisearch_sdk/
batches.rs1use serde::{Deserialize, Serialize};
2use time::OffsetDateTime;
3
4use crate::{client::Client, errors::Error, request::HttpClient};
5
6#[derive(Debug, Clone, Deserialize)]
10#[serde(rename_all = "camelCase")]
11pub struct Batch {
12 pub uid: u32,
14 #[serde(default, with = "time::serde::rfc3339::option")]
16 pub enqueued_at: Option<OffsetDateTime>,
17 #[serde(default, with = "time::serde::rfc3339::option")]
19 pub started_at: Option<OffsetDateTime>,
20 #[serde(default, with = "time::serde::rfc3339::option")]
22 pub finished_at: Option<OffsetDateTime>,
23 #[serde(skip_serializing_if = "Option::is_none")]
25 pub index_uid: Option<String>,
26 #[serde(skip_serializing_if = "Option::is_none")]
28 pub task_uids: Option<Vec<u32>>,
29 #[serde(skip_serializing_if = "Option::is_none")]
33 pub batch_strategy: Option<BatchStrategy>,
34}
35
36#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
38#[serde(rename_all = "snake_case")]
39#[non_exhaustive]
40pub enum BatchStrategy {
41 SizeLimitReached,
43 TimeLimitReached,
45 #[serde(other)]
47 Unknown,
48}
49
50#[derive(Debug, Clone, Deserialize)]
51#[serde(rename_all = "camelCase")]
52pub struct BatchesResults {
53 pub results: Vec<Batch>,
54 pub total: u32,
55 pub limit: u32,
56 #[serde(skip_serializing_if = "Option::is_none")]
57 pub from: Option<u32>,
58 #[serde(skip_serializing_if = "Option::is_none")]
59 pub next: Option<u32>,
60}
61
62#[derive(Debug, Serialize, Clone)]
64#[serde(rename_all = "camelCase")]
65pub struct BatchesQuery<'a, Http: HttpClient> {
66 #[serde(skip_serializing)]
67 client: &'a Client<Http>,
68 #[serde(skip_serializing_if = "Option::is_none")]
70 limit: Option<u32>,
71 #[serde(skip_serializing_if = "Option::is_none")]
73 from: Option<u32>,
74}
75
76impl<'a, Http: HttpClient> BatchesQuery<'a, Http> {
77 #[must_use]
78 pub fn new(client: &'a Client<Http>) -> BatchesQuery<'a, Http> {
79 BatchesQuery {
80 client,
81 limit: None,
82 from: None,
83 }
84 }
85
86 #[must_use]
87 pub fn with_limit(&mut self, limit: u32) -> &mut Self {
88 self.limit = Some(limit);
89 self
90 }
91
92 #[must_use]
93 pub fn with_from(&mut self, from: u32) -> &mut Self {
94 self.from = Some(from);
95 self
96 }
97
98 pub async fn execute(&self) -> Result<BatchesResults, Error> {
100 self.client.get_batches_with(self).await
101 }
102}
103
104#[cfg(test)]
105mod tests {
106 use crate::batches::BatchStrategy;
107 use crate::client::Client;
108
109 #[tokio::test]
110 async fn test_get_batches_parses_batch_strategy() {
111 let mut s = mockito::Server::new_async().await;
112 let base = s.url();
113
114 let response_body = serde_json::json!({
115 "results": [
116 {
117 "uid": 42,
118 "enqueuedAt": "2024-10-11T11:49:53.000Z",
119 "startedAt": "2024-10-11T11:49:54.000Z",
120 "finishedAt": "2024-10-11T11:49:55.000Z",
121 "indexUid": "movies",
122 "taskUids": [1, 2, 3],
123 "batchStrategy": "time_limit_reached"
124 }
125 ],
126 "limit": 20,
127 "from": null,
128 "next": null,
129 "total": 1
130 })
131 .to_string();
132
133 let _m = s
134 .mock("GET", "/batches")
135 .with_status(200)
136 .with_header("content-type", "application/json")
137 .with_body(response_body)
138 .create_async()
139 .await;
140
141 let client = Client::new(base, None::<String>).unwrap();
142 let batches = client.get_batches().await.expect("list batches failed");
143 assert_eq!(batches.results.len(), 1);
144 let b = &batches.results[0];
145 assert_eq!(b.uid, 42);
146 assert_eq!(b.batch_strategy, Some(BatchStrategy::TimeLimitReached));
147 }
148
149 #[tokio::test]
150 async fn test_get_batch_by_uid_parses_batch_strategy() {
151 let mut s = mockito::Server::new_async().await;
152 let base = s.url();
153
154 let response_body = serde_json::json!({
155 "uid": 99,
156 "batchStrategy": "size_limit_reached",
157 "taskUids": [10, 11]
158 })
159 .to_string();
160
161 let _m = s
162 .mock("GET", "/batches/99")
163 .with_status(200)
164 .with_header("content-type", "application/json")
165 .with_body(response_body)
166 .create_async()
167 .await;
168
169 let client = Client::new(base, None::<String>).unwrap();
170 let batch = client.get_batch(99).await.expect("get batch failed");
171 assert_eq!(batch.uid, 99);
172 assert_eq!(batch.batch_strategy, Some(BatchStrategy::SizeLimitReached));
173 }
174
175 #[tokio::test]
176 async fn test_query_serialization_for_batches() {
177 use mockito::Matcher;
178 let mut s = mockito::Server::new_async().await;
179 let base = s.url();
180
181 let _m = s
182 .mock("GET", "/batches")
183 .match_query(Matcher::AllOf(vec![
184 Matcher::UrlEncoded("limit".into(), "2".into()),
185 Matcher::UrlEncoded("from".into(), "40".into()),
186 ]))
187 .with_status(200)
188 .with_header("content-type", "application/json")
189 .with_body(r#"{"results":[],"limit":2,"total":0}"#)
190 .create_async()
191 .await;
192
193 let client = Client::new(base, None::<String>).unwrap();
194 let mut q = crate::batches::BatchesQuery::new(&client);
195 let _ = q.with_limit(2).with_from(40);
196 let res = client.get_batches_with(&q).await.expect("request failed");
197 assert_eq!(res.limit, 2);
198 }
199}