diff --git a/.code-samples.meilisearch.yaml b/.code-samples.meilisearch.yaml index d4ff9f35..637958d8 100644 --- a/.code-samples.meilisearch.yaml +++ b/.code-samples.meilisearch.yaml @@ -110,14 +110,14 @@ get_all_tasks_1: |- .unwrap(); get_all_tasks_filtering_1: |- let mut query = TasksQuery::new(&client) - .with_index_uid(["movies"]) + .with_index_uids(["movies"]) .execute() .await .unwrap(); get_all_tasks_filtering_2: |- let mut query = TasksQuery::new(&client) - .with_status(["succeeded", "failed"]) - .with_type(["documentAdditionOrUpdate"]) + .with_statuses(["succeeded", "failed"]) + .with_types(["documentAdditionOrUpdate"]) .execute() .await .unwrap(); diff --git a/README.md b/README.md index bae2b403..1c7faf89 100644 --- a/README.md +++ b/README.md @@ -253,7 +253,7 @@ WARNING: `meilisearch-sdk` will panic if no Window is available (ex: Web extensi ## 🤖 Compatibility with Meilisearch -This package only guarantees the compatibility with the [version v0.29.0 of Meilisearch](https://github.com/meilisearch/meilisearch/releases/tag/v0.29.0). +This package only guarantees the compatibility with the [version v0.30.0 of Meilisearch](https://github.com/meilisearch/meilisearch/releases/tag/v0.30.0). ## ⚙️ Contributing diff --git a/README.tpl b/README.tpl index f8bfbb75..94b68add 100644 --- a/README.tpl +++ b/README.tpl @@ -108,7 +108,7 @@ WARNING: `meilisearch-sdk` will panic if no Window is available (ex: Web extensi ## 🤖 Compatibility with Meilisearch -This package only guarantees the compatibility with the [version v0.29.0 of Meilisearch](https://github.com/meilisearch/meilisearch/releases/tag/v0.29.0). +This package only guarantees the compatibility with the [version v0.30.0 of Meilisearch](https://github.com/meilisearch/meilisearch/releases/tag/v0.30.0). ## ⚙️ Contributing diff --git a/src/client.rs b/src/client.rs index 0fcacf21..c307a8ad 100644 --- a/src/client.rs +++ b/src/client.rs @@ -744,7 +744,7 @@ impl Client { /// # let client = client::Client::new(MEILISEARCH_URL, MEILISEARCH_API_KEY); /// /// let mut query = tasks::TasksQuery::new(&client); - /// query.with_index_uid(["get_tasks_with"]); + /// query.with_index_uids(["get_tasks_with"]); /// let tasks = client.get_tasks_with(&query).await.unwrap(); /// # }); /// ``` @@ -930,7 +930,7 @@ mod tests { #[meilisearch_test] async fn test_get_tasks(client: Client) { let tasks = client.get_tasks().await.unwrap(); - assert!(tasks.results.len() >= 2); + assert!(tasks.limit == 20); } #[meilisearch_test] @@ -938,7 +938,7 @@ mod tests { let query = TasksQuery::new(&client); let tasks = client.get_tasks_with(&query).await.unwrap(); - assert!(tasks.results.len() >= 2); + assert!(tasks.limit == 20); } #[meilisearch_test] diff --git a/src/errors.rs b/src/errors.rs index cde83248..40555289 100644 --- a/src/errors.rs +++ b/src/errors.rs @@ -156,6 +156,12 @@ pub enum ErrorCode { InvalidApiKeyIndexes, InvalidApiKeyExpiresAt, ApiKeyNotFound, + InvalidTaskTypesFilter, + InvalidTaskStatusesFilter, + InvalidTaskCanceledByFilter, + InvalidTaskUidsFilter, + InvalidTaskDateFilter, + MissingTaskFilters, /// That's unexpected. Please open a GitHub issue after ensuring you are /// using the supported version of the Meilisearch server. diff --git a/src/indexes.rs b/src/indexes.rs index 28d8574c..52d8e49a 100644 --- a/src/indexes.rs +++ b/src/indexes.rs @@ -436,7 +436,8 @@ impl Index { /// /// # futures::executor::block_on(async move { /// let client = Client::new(MEILISEARCH_URL, MEILISEARCH_API_KEY); - /// let movie_index = client.index("get_documents"); + /// + /// let movie_index = client.index("get_documents_with"); /// /// # movie_index.add_or_replace(&[Movie{name:String::from("Interstellar"), description:String::from("Interstellar chronicles the adventures of a group of explorers who make use of a newly discovered wormhole to surpass the limitations on human space travel and conquer the vast distances involved in an interstellar voyage.")}], Some("name")).await.unwrap().wait_for_completion(&client, None, None).await.unwrap(); /// @@ -902,7 +903,7 @@ impl Index { /// ``` pub async fn get_tasks(&self) -> Result { let mut query = TasksQuery::new(&self.client); - query.with_index_uid([self.uid.as_str()]); + query.with_index_uids([self.uid.as_str()]); self.client.get_tasks_with(&query).await } @@ -923,7 +924,7 @@ impl Index { /// # let index = client.create_index("get_tasks_with", None).await.unwrap().wait_for_completion(&client, None, None).await.unwrap().try_make_index(&client).unwrap(); /// /// let mut query = TasksQuery::new(&client); - /// query.with_index_uid(["none_existant"]); + /// query.with_index_uids(["none_existant"]); /// let tasks = index.get_tasks_with(&query).await.unwrap(); /// /// assert!(tasks.results.len() > 0); @@ -935,7 +936,7 @@ impl Index { tasks_query: &TasksQuery<'_>, ) -> Result { let mut query = tasks_query.clone(); - query.with_index_uid([self.uid.as_str()]); + query.with_index_uids([self.uid.as_str()]); self.client.get_tasks_with(&query).await } diff --git a/src/tasks.rs b/src/tasks.rs index aab72798..dea78951 100644 --- a/src/tasks.rs +++ b/src/tasks.rs @@ -406,13 +406,52 @@ pub struct TasksQuery<'a> { pub client: &'a Client, // Index uids array to only retrieve the tasks of the indexes. #[serde(skip_serializing_if = "Option::is_none")] - pub index_uid: Option>, + pub index_uids: Option>, // Statuses array to only retrieve the tasks with these statuses. #[serde(skip_serializing_if = "Option::is_none")] - pub status: Option>, + pub statuses: Option>, // Types array to only retrieve the tasks with these [TaskType]. - #[serde(skip_serializing_if = "Option::is_none", rename = "type")] - pub task_type: Option>, + #[serde(skip_serializing_if = "Option::is_none", rename = "types")] + pub task_types: Option>, + // Uids of the tasks to retrieve + #[serde(skip_serializing_if = "Option::is_none")] + pub uids: Option>, + // Date to retrieve all tasks that were enqueued before it. + #[serde( + skip_serializing_if = "Option::is_none", + serialize_with = "time::serde::rfc3339::option::serialize" + )] + pub before_enqueued_at: Option, + // Date to retrieve all tasks that were enqueued after it. + #[serde( + skip_serializing_if = "Option::is_none", + serialize_with = "time::serde::rfc3339::option::serialize" + )] + pub after_enqueued_at: Option, + // Date to retrieve all tasks that were started before it. + #[serde( + skip_serializing_if = "Option::is_none", + serialize_with = "time::serde::rfc3339::option::serialize" + )] + pub before_started_at: Option, + // Date to retrieve all tasks that were started after it. + #[serde( + skip_serializing_if = "Option::is_none", + serialize_with = "time::serde::rfc3339::option::serialize" + )] + pub after_started_at: Option, + // Date to retrieve all tasks that were finished before it. + #[serde( + skip_serializing_if = "Option::is_none", + serialize_with = "time::serde::rfc3339::option::serialize" + )] + pub before_finished_at: Option, + // Date to retrieve all tasks that were finished after it. + #[serde( + skip_serializing_if = "Option::is_none", + serialize_with = "time::serde::rfc3339::option::serialize" + )] + pub after_finished_at: Option, // Maximum number of tasks to return #[serde(skip_serializing_if = "Option::is_none")] pub limit: Option, @@ -426,32 +465,88 @@ impl<'a> TasksQuery<'a> { pub fn new(client: &'a Client) -> TasksQuery<'a> { TasksQuery { client, - index_uid: None, - status: None, - task_type: None, + index_uids: None, + statuses: None, + task_types: None, limit: None, from: None, + uids: None, + before_enqueued_at: None, + after_enqueued_at: None, + before_started_at: None, + after_started_at: None, + before_finished_at: None, + after_finished_at: None, } } - pub fn with_index_uid<'b>( + pub fn with_index_uids<'b>( + &'b mut self, + index_uids: impl IntoIterator, + ) -> &'b mut TasksQuery<'a> { + self.index_uids = Some(index_uids.into_iter().collect()); + self + } + pub fn with_statuses<'b>( + &'b mut self, + statuses: impl IntoIterator, + ) -> &'b mut TasksQuery<'a> { + self.statuses = Some(statuses.into_iter().collect()); + self + } + pub fn with_types<'b>( + &'b mut self, + task_types: impl IntoIterator, + ) -> &'b mut TasksQuery<'a> { + self.task_types = Some(task_types.into_iter().collect()); + self + } + pub fn with_uids<'b>( + &'b mut self, + uids: impl IntoIterator, + ) -> &'b mut TasksQuery<'a> { + self.uids = Some(uids.into_iter().collect()); + self + } + pub fn with_before_enqueued_at<'b>( &'b mut self, - index_uid: impl IntoIterator, + before_enqueued_at: &'a OffsetDateTime, ) -> &'b mut TasksQuery<'a> { - self.index_uid = Some(index_uid.into_iter().collect()); + self.before_enqueued_at = Some(*before_enqueued_at); self } - pub fn with_status<'b>( + pub fn with_after_enqueued_at<'b>( &'b mut self, - status: impl IntoIterator, + after_enqueued_at: &'a OffsetDateTime, ) -> &'b mut TasksQuery<'a> { - self.status = Some(status.into_iter().collect()); + self.after_enqueued_at = Some(*after_enqueued_at); self } - pub fn with_type<'b>( + pub fn with_before_started_at<'b>( &'b mut self, - task_type: impl IntoIterator, + before_started_at: &'a OffsetDateTime, ) -> &'b mut TasksQuery<'a> { - self.task_type = Some(task_type.into_iter().collect()); + self.before_started_at = Some(*before_started_at); + self + } + pub fn with_after_started_at<'b>( + &'b mut self, + after_started_at: &'a OffsetDateTime, + ) -> &'b mut TasksQuery<'a> { + self.after_started_at = Some(*after_started_at); + self + } + pub fn with_before_finished_at<'b>( + &'b mut self, + before_finished_at: &'a OffsetDateTime, + ) -> &'b mut TasksQuery<'a> { + self.before_finished_at = Some(*before_finished_at); + self + } + pub fn with_after_finished_at<'b>( + &'b mut self, + after_finished_at: &'a OffsetDateTime, + ) -> &'b mut TasksQuery<'a> { + self.after_finished_at = Some(*after_finished_at); self } pub fn with_limit<'b>(&'b mut self, limit: u32) -> &'b mut TasksQuery<'a> { @@ -640,17 +735,81 @@ mod test { let mock_server_url = &mockito::server_url(); let client = Client::new(mock_server_url, "masterKey"); let path = - "/tasks?indexUid=movies,test&status=equeued&type=documentDeletion&limit=0&from=1"; + "/tasks?indexUids=movies,test&statuses=equeued&types=documentDeletion&uids=1&limit=0&from=1"; let mock_res = mock("GET", path).with_status(200).create(); let mut query = TasksQuery::new(&client); query - .with_index_uid(["movies", "test"]) - .with_status(["equeued"]) - .with_type(["documentDeletion"]) + .with_index_uids(["movies", "test"]) + .with_statuses(["equeued"]) + .with_types(["documentDeletion"]) .with_from(1) - .with_limit(0); + .with_limit(0) + .with_uids([&1]); + + let _ = client.get_tasks_with(&query).await; + + mock_res.assert(); + Ok(()) + } + + #[meilisearch_test] + async fn test_get_tasks_with_date_params() -> Result<(), Error> { + let mock_server_url = &mockito::server_url(); + let client = Client::new(mock_server_url, "masterKey"); + let path = "/tasks?\ + beforeEnqueuedAt=2022-02-03T13%3A02%3A38.369634Z\ + &afterEnqueuedAt=2023-02-03T13%3A02%3A38.369634Z\ + &beforeStartedAt=2024-02-03T13%3A02%3A38.369634Z\ + &afterStartedAt=2025-02-03T13%3A02%3A38.369634Z\ + &beforeFinishedAt=2026-02-03T13%3A02%3A38.369634Z\ + &afterFinishedAt=2027-02-03T13%3A02%3A38.369634Z"; + + let mock_res = mock("GET", path).with_status(200).create(); + + let before_enqueued_at = OffsetDateTime::parse( + "2022-02-03T13:02:38.369634Z", + &::time::format_description::well_known::Rfc3339, + ) + .unwrap(); + let after_enqueued_at = OffsetDateTime::parse( + "2023-02-03T13:02:38.369634Z", + &::time::format_description::well_known::Rfc3339, + ) + .unwrap(); + let before_started_at = OffsetDateTime::parse( + "2024-02-03T13:02:38.369634Z", + &::time::format_description::well_known::Rfc3339, + ) + .unwrap(); + + let after_started_at = OffsetDateTime::parse( + "2025-02-03T13:02:38.369634Z", + &::time::format_description::well_known::Rfc3339, + ) + .unwrap(); + + let before_finished_at = OffsetDateTime::parse( + "2026-02-03T13:02:38.369634Z", + &::time::format_description::well_known::Rfc3339, + ) + .unwrap(); + + let after_finished_at = OffsetDateTime::parse( + "2027-02-03T13:02:38.369634Z", + &::time::format_description::well_known::Rfc3339, + ) + .unwrap(); + + let mut query = TasksQuery::new(&client); + query + .with_before_enqueued_at(&before_enqueued_at) + .with_after_enqueued_at(&after_enqueued_at) + .with_before_started_at(&before_started_at) + .with_after_started_at(&after_started_at) + .with_before_finished_at(&before_finished_at) + .with_after_finished_at(&after_finished_at); let _ = client.get_tasks_with(&query).await; @@ -662,15 +821,15 @@ mod test { async fn test_get_tasks_on_struct_with_params() -> Result<(), Error> { let mock_server_url = &mockito::server_url(); let client = Client::new(mock_server_url, "masterKey"); - let path = "/tasks?indexUid=movies,test&status=equeued&type=documentDeletion"; + let path = "/tasks?indexUids=movies,test&statuses=equeued&types=documentDeletion"; let mock_res = mock("GET", path).with_status(200).create(); let mut query = TasksQuery::new(&client); let _ = query - .with_index_uid(["movies", "test"]) - .with_status(["equeued"]) - .with_type(["documentDeletion"]) + .with_index_uids(["movies", "test"]) + .with_statuses(["equeued"]) + .with_types(["documentDeletion"]) .execute() .await; @@ -680,9 +839,9 @@ mod test { } #[meilisearch_test] - async fn test_get_tasks_with_none_existant_index_uid(client: Client) -> Result<(), Error> { + async fn test_get_tasks_with_none_existant_index_uids(client: Client) -> Result<(), Error> { let mut query = TasksQuery::new(&client); - query.with_index_uid(["no_name"]); + query.with_index_uids(["no_name"]); let tasks = client.get_tasks_with(&query).await.unwrap(); assert_eq!(tasks.results.len(), 0); @@ -692,7 +851,7 @@ mod test { #[meilisearch_test] async fn test_get_tasks_with_execute(client: Client) -> Result<(), Error> { let tasks = TasksQuery::new(&client) - .with_index_uid(["no_name"]) + .with_index_uids(["no_name"]) .execute() .await .unwrap();