From a37ffd32d284a20523a1cd3d9594365ab6e17f09 Mon Sep 17 00:00:00 2001 From: Charlotte Vermandel Date: Thu, 7 Jul 2022 23:07:18 +0200 Subject: [PATCH 01/44] Update task api v0.28.0 --- .code-samples.meilisearch.yaml | 86 ++++++------ meilisearch-test-macro/README.md | 4 +- src/client.rs | 39 +++--- src/indexes.rs | 66 +++++---- src/lib.rs | 4 + src/settings.rs | 74 +++++------ src/task_info.rs | 221 +++++++++++++++++++++++++++++++ src/tasks.rs | 172 +++++++++--------------- src/utils.rs | 45 +++++++ 9 files changed, 468 insertions(+), 243 deletions(-) create mode 100644 src/task_info.rs create mode 100644 src/utils.rs diff --git a/.code-samples.meilisearch.yaml b/.code-samples.meilisearch.yaml index d19f3d34..b8f9bddf 100644 --- a/.code-samples.meilisearch.yaml +++ b/.code-samples.meilisearch.yaml @@ -18,7 +18,7 @@ get_one_document_1: |- get_documents_1: |- let documents: Vec = client.index("movies").get_documents(None, Some(2), None).await.unwrap(); add_or_replace_documents_1: |- - let task: Task = client.index("movies").add_or_replace(&[ + let task: TaskInfo = client.index("movies").add_or_replace(&[ Movie { id: 287947, title: "Shazam".to_string(), @@ -35,18 +35,18 @@ add_or_update_documents_1: |- title: String } - let task: Task = client.index("movies").add_or_update(&[ + let task: TaskInfo = client.index("movies").add_or_update(&[ IncompleteMovie { id: 287947, title: "Shazam ⚡️".to_string() } ], None).await.unwrap(); delete_all_documents_1: |- - let task: Task = client.index("movies").delete_all_documents().await.unwrap(); + let task: TaskInfo = client.index("movies").delete_all_documents().await.unwrap(); delete_one_document_1: |- - let task: Task = client.index("movies").delete_document(25684).await.unwrap(); + let task: TaskInfo = client.index("movies").delete_document(25684).await.unwrap(); delete_documents_1: |- - let task: Task = client.index("movies").delete_documents(&[23488, 153738, 437035, 363869]).await.unwrap(); + let task: TaskInfo = client.index("movies").delete_documents(&[23488, 153738, 437035, 363869]).await.unwrap(); search_post_1: |- let results: SearchResults = client.index("movies") .search() @@ -55,13 +55,13 @@ search_post_1: |- .await .unwrap(); get_task_by_index_1: |- - let task: Task = client.index("movies").get_task(1).await.unwrap(); + let task: TaskInfo = client.index("movies").get_task(1).await.unwrap(); get_all_tasks_by_index_1: |- - let tasks: Vec = client.index("movies").get_tasks().await.unwrap(); + let tasks: TasksResults = client.index("movies").get_tasks().await.unwrap(); get_all_tasks_1: |- - let tasks: Vec = client.get_tasks().await.unwrap(); + let tasks: TasksResults = client.get_tasks().await.unwrap(); get_task_1: |- - let task: Task = client.get_task(1).await.unwrap(); + let task: TaskInfo = client.get_task(1).await.unwrap(); get_settings_1: |- let settings: Settings = client.index("movies").get_settings().await.unwrap(); update_settings_1: |- @@ -103,9 +103,9 @@ update_settings_1: |- ]) .with_synonyms(synonyms); - let task: Task = client.index("movies").set_settings(&settings).await.unwrap(); + let task: TaskInfo = client.index("movies").set_settings(&settings).await.unwrap(); reset_settings_1: |- - let task: Task = client.index("movies").reset_settings().await.unwrap(); + let task: TaskInfo = client.index("movies").reset_settings().await.unwrap(); get_synonyms_1: |- let synonyms: HashMap> = client.index("movies").get_synonyms().await.unwrap(); update_synonyms_1: |- @@ -114,16 +114,16 @@ update_synonyms_1: |- synonyms.insert(String::from("logan"), vec![String::from("xmen"), String::from("wolverine")]); synonyms.insert(String::from("wow"), vec![String::from("world of warcraft")]); - let task: Task = client.index("movies").set_synonyms(&synonyms).await.unwrap(); + let task: TaskInfo = client.index("movies").set_synonyms(&synonyms).await.unwrap(); reset_synonyms_1: |- - let task: Task = client.index("movies").reset_synonyms().await.unwrap(); + let task: TaskInfo = client.index("movies").reset_synonyms().await.unwrap(); get_stop_words_1: |- let stop_words: Vec = client.index("movies").get_stop_words().await.unwrap(); update_stop_words_1: |- let stop_words = ["of", "the", "to"]; - let task: Task = client.index("movies").set_stop_words(&stop_words).await.unwrap(); + let task: TaskInfo = client.index("movies").set_stop_words(&stop_words).await.unwrap(); reset_stop_words_1: |- - let task: Task = client.index("movies").reset_stop_words().await.unwrap(); + let task: TaskInfo = client.index("movies").reset_stop_words().await.unwrap(); get_ranking_rules_1: |- let ranking_rules: Vec = client.index("movies").get_ranking_rules().await.unwrap(); update_ranking_rules_1: |- @@ -138,15 +138,15 @@ update_ranking_rules_1: |- "rank:desc", ]; - let task: Task = client.index("movies").set_ranking_rules(&ranking_rules).await.unwrap(); + let task: TaskInfo = client.index("movies").set_ranking_rules(&ranking_rules).await.unwrap(); reset_ranking_rules_1: |- - let task: Task = client.index("movies").reset_ranking_rules().await.unwrap(); + let task: TaskInfo = client.index("movies").reset_ranking_rules().await.unwrap(); get_distinct_attribute_1: |- let distinct_attribute: Option = client.index("shoes").get_distinct_attribute().await.unwrap(); update_distinct_attribute_1: |- - let task: Task = client.index("shoes").set_distinct_attribute("skuid").await.unwrap(); + let task: TaskInfo = client.index("shoes").set_distinct_attribute("skuid").await.unwrap(); reset_distinct_attribute_1: |- - let task: Task = client.index("shoes").reset_distinct_attribute().await.unwrap(); + let task: TaskInfo = client.index("shoes").reset_distinct_attribute().await.unwrap(); get_searchable_attributes_1: |- let searchable_attributes: Vec = client.index("movies").get_searchable_attributes().await.unwrap(); update_searchable_attributes_1: |- @@ -156,9 +156,9 @@ update_searchable_attributes_1: |- "genres" ]; - let task: Task = client.index("movies").set_searchable_attributes(&searchable_attributes).await.unwrap(); + let task: TaskInfo = client.index("movies").set_searchable_attributes(&searchable_attributes).await.unwrap(); reset_searchable_attributes_1: |- - let task: Task = client.index("movies").reset_searchable_attributes().await.unwrap(); + let task: TaskInfo = client.index("movies").reset_searchable_attributes().await.unwrap(); get_filterable_attributes_1: |- let filterable_attributes: Vec = client.index("movies").get_filterable_attributes().await.unwrap(); update_filterable_attributes_1: |- @@ -167,9 +167,9 @@ update_filterable_attributes_1: |- "director" ]; - let task: Task = client.index("movies").set_filterable_attributes(&filterable_attributes).await.unwrap(); + let task: TaskInfo = client.index("movies").set_filterable_attributes(&filterable_attributes).await.unwrap(); reset_filterable_attributes_1: |- - let task: Task = client.index("movies").reset_filterable_attributes().await.unwrap(); + let task: TaskInfo = client.index("movies").reset_filterable_attributes().await.unwrap(); get_displayed_attributes_1: |- let displayed_attributes: Vec = client.index("movies").get_displayed_attributes().await.unwrap(); update_displayed_attributes_1: |- @@ -180,9 +180,9 @@ update_displayed_attributes_1: |- "release_date" ]; - let task: Task = client.index("movies").set_displayed_attributes(&displayed_attributes).await.unwrap(); + let task: TaskInfo = client.index("movies").set_displayed_attributes(&displayed_attributes).await.unwrap(); reset_displayed_attributes_1: |- - let task: Task = client.index("movies").reset_displayed_attributes().await.unwrap(); + let task: TaskInfo = client.index("movies").reset_displayed_attributes().await.unwrap(); get_index_stats_1: |- let stats: IndexStats = client.index("movies").get_stats().await.unwrap(); get_indexes_stats_1: |- @@ -193,7 +193,7 @@ get_health_1: |- get_version_1: |- let version: Version = client.get_version().await.unwrap(); distinct_attribute_guide_1: |- - let task: Task = client.index("jackets").set_distinct_attribute("product_id").await.unwrap(); + let task: TaskInfo = client.index("jackets").set_distinct_attribute("product_id").await.unwrap(); field_properties_guide_searchable_1: |- let searchable_attributes = [ "title", @@ -201,7 +201,7 @@ field_properties_guide_searchable_1: |- "genres" ]; - let task: Task = client.index("movies").set_searchable_attributes(&searchable_attributes).await.unwrap(); + let task: TaskInfo = client.index("movies").set_searchable_attributes(&searchable_attributes).await.unwrap(); field_properties_guide_displayed_1: |- let displayed_attributes = [ "title", @@ -210,7 +210,7 @@ field_properties_guide_displayed_1: |- "release_date" ]; - let task: Task = client.index("movies").set_displayed_attributes(&displayed_attributes).await.unwrap(); + let task: TaskInfo = client.index("movies").set_displayed_attributes(&displayed_attributes).await.unwrap(); filtering_guide_1: |- let results: SearchResults = client.index("movies").search() .with_query("Avengers") @@ -338,7 +338,7 @@ settings_guide_filterable_attributes_1: |- "genres" ]); - let task: Task = client.index("movies").set_settings(&settings).await.unwrap(); + let task: TaskInfo = client.index("movies").set_settings(&settings).await.unwrap(); settings_guide_ranking_rules_1: |- let settings = Settings::new() .with_ranking_rules([ @@ -357,7 +357,7 @@ settings_guide_distinct_1: |- let settings = Settings::new() .with_distinct_attribute("product_id"); - let task: Task = client.index("jackets").set_settings(&settings).await.unwrap(); + let task: TaskInfo = client.index("jackets").set_settings(&settings).await.unwrap(); settings_guide_searchable_1: |- let settings = Settings::new() .with_searchable_attributes([ @@ -366,7 +366,7 @@ settings_guide_searchable_1: |- "genres" ]); - let task: Task = client.index("movies").set_settings(&settings).await.unwrap(); + let task: TaskInfo = client.index("movies").set_settings(&settings).await.unwrap(); settings_guide_displayed_1: |- let settings = Settings::new() .with_displayed_attributes([ @@ -376,7 +376,7 @@ settings_guide_displayed_1: |- "release_date" ]); - let task: Task = client.index("movies").set_settings(&settings).await.unwrap(); + let task: TaskInfo = client.index("movies").set_settings(&settings).await.unwrap(); settings_guide_sortable_1: |- let settings = Settings::new() .with_sortable_attributes([ @@ -384,7 +384,7 @@ settings_guide_sortable_1: |- "price" ]); - let task: Task = client.index("books").set_settings(&settings).await.unwrap(); + let task: TaskInfo = client.index("books").set_settings(&settings).await.unwrap(); add_movies_json_1: |- use meilisearch_sdk::{ indexes::*, @@ -417,7 +417,7 @@ documents_guide_add_movie_1: |- } // Add a document to our index - let task: Task = client.index("movies").add_documents(&[ + let task: TaskInfo = client.index("movies").add_documents(&[ IncompleteMovie { id: "123sq178".to_string(), title: "Amélie Poulain".to_string(), @@ -437,7 +437,7 @@ primary_field_guide_add_document_primary_key: |- price: f64 } - let task: Task = client.index("books").add_documents(&[ + let task: TaskInfo = client.index("books").add_documents(&[ Book { reference_number: "287947".to_string(), title: "Diary of a Wimpy Kid".to_string(), @@ -616,7 +616,7 @@ getting_started_configure_settings: |- "mass", "_geo" ]) - let task: Task = client.index("meteorites").set_settings(&settings).await.unwrap(); + let task: TaskInfo = client.index("meteorites").set_settings(&settings).await.unwrap(); getting_started_geo_radius: |- let results: SearchResults = client.index("meteorites").search() .with_filter("_geoRadius(46.9480, 7.4474, 210000)") @@ -643,7 +643,7 @@ getting_started_filtering: |- .await .unwrap(); faceted_search_update_settings_1: |- - let task: Task = client.index("movies").set_filterable_attributes(["director", "genres"]).await.unwrap(); + let task: TaskInfo = client.index("movies").set_filterable_attributes(["director", "genres"]).await.unwrap(); faceted_search_filter_1: |- let results: SearchResults = client.index("movies").search() .with_query("thriller") @@ -683,7 +683,7 @@ sorting_guide_update_sortable_attributes_1: |- "price" ]; - let task: Task = client.index("books").set_sortable_attributes(&sortable_attributes).await.unwrap(); + let task: TaskInfo = client.index("books").set_sortable_attributes(&sortable_attributes).await.unwrap(); sorting_guide_update_ranking_rules_1: |- let ranking_rules = [ "words", @@ -694,7 +694,7 @@ sorting_guide_update_ranking_rules_1: |- "exactness" ]; - let task: Task = client.index("books").set_ranking_rules(&ranking_rules).await.unwrap(); + let task: TaskInfo = client.index("books").set_ranking_rules(&ranking_rules).await.unwrap(); sorting_guide_sort_parameter_1: |- let results: SearchResults = client.index("books").search() .with_query("science fiction") @@ -717,9 +717,9 @@ update_sortable_attributes_1: |- "author" ]; - let task: Task = client.index("books").set_sortable_attributes(&sortable_attributes).await.unwrap(); + let task: TaskInfo = client.index("books").set_sortable_attributes(&sortable_attributes).await.unwrap(); reset_sortable_attributes_1: |- - let task: Task = client.index("books").reset_sortable_attributes().await.unwrap(); + let task: TaskInfo = client.index("books").reset_sortable_attributes().await.unwrap(); search_parameter_guide_sort_1: |- let results: SearchResults = client.index("books").search() .with_query("science fiction") @@ -728,7 +728,7 @@ search_parameter_guide_sort_1: |- .await .unwrap(); geosearch_guide_filter_settings_1: |- - let task: Task = client.index("restaurants").set_filterable_attributes(&["_geo"]).await.unwrap(); + let task: TaskInfo = client.index("restaurants").set_filterable_attributes(&["_geo"]).await.unwrap(); geosearch_guide_filter_usage_1: |- let results: SearchResults = client.index("restaurants").search() .with_filter("_geoRadius(45.472735, 9.184019, 2000)") @@ -742,7 +742,7 @@ geosearch_guide_filter_usage_2: |- .await .unwrap(); geosearch_guide_sort_settings_1: |- - let task: Task = client.index("restaurants").set_sortable_attributes(&["_geo"]).await.unwrap(); + let task: TaskInfo = client.index("restaurants").set_sortable_attributes(&["_geo"]).await.unwrap(); geosearch_guide_sort_usage_1: |- let results: SearchResults = client.index("restaurants").search() .with_sort(&["_geoPoint(48.8561446, 2.2978204):asc"]) diff --git a/meilisearch-test-macro/README.md b/meilisearch-test-macro/README.md index fb1796ab..95d09d4a 100644 --- a/meilisearch-test-macro/README.md +++ b/meilisearch-test-macro/README.md @@ -25,7 +25,7 @@ async fn test_get_tasks() -> Result<(), Error> { let tasks = index.get_tasks().await?; // The only task is the creation of the index - assert_eq!(status.len(), 1); + assert_eq!(status.results.len(), 1); index.delete() .await? @@ -52,7 +52,7 @@ With this macro, all these problems are solved. See a rewrite of this test: async fn test_get_tasks(index: Index, client: Client) -> Result<(), Error> { let tasks = index.get_tasks().await?; // The only task is the creation of the index - assert_eq!(status.len(), 1); + assert_eq!(status.results.len(), 1); } ``` diff --git a/src/client.rs b/src/client.rs index 8e08a344..8aebd816 100644 --- a/src/client.rs +++ b/src/client.rs @@ -3,7 +3,9 @@ use crate::{ indexes::*, key::{Key, KeyBuilder}, request::*, - tasks::{async_sleep, Task}, + task_info::TaskInfo, + tasks::*, + utils::async_sleep, }; use serde::Deserialize; use serde_json::{json, Value}; @@ -197,8 +199,8 @@ impl Client { &self, uid: impl AsRef, primary_key: Option<&str>, - ) -> Result { - request::( + ) -> Result { + request::( &format!("{}/indexes", self.host), &self.api_key, Method::Post(json!({ @@ -212,8 +214,8 @@ impl Client { /// Delete an index from its UID. /// To delete an [Index], use the [Index::delete] method. - pub async fn delete_index(&self, uid: impl AsRef) -> Result { - request::<(), Task>( + pub async fn delete_index(&self, uid: impl AsRef) -> Result { + request::<(), TaskInfo>( &format!("{}/indexes/{}", self.host, uid.as_ref()), &self.api_key, Method::Delete, @@ -511,7 +513,7 @@ impl Client { /// /// If the waited time exceeds `timeout` then an [Error::Timeout] will be returned. /// - /// See also [Index::wait_for_task, Task::wait_for_completion]. + /// See also [Index::wait_for_task, Task::wait_for_completion, TaskInfo::wait_for_completion]. /// /// # Example /// @@ -548,7 +550,7 @@ impl Client { /// ``` pub async fn wait_for_task( &self, - task_id: impl AsRef, + task_id: impl AsRef, interval: Option, timeout: Option, ) -> Result { @@ -560,7 +562,6 @@ impl Client { while timeout > elapsed_time { task_result = self.get_task(&task_id).await; - match task_result { Ok(status) => match status { Task::Failed { .. } | Task::Succeeded { .. } => { @@ -596,7 +597,7 @@ impl Client { /// # index.delete().await.unwrap().wait_for_completion(&client, None, None).await.unwrap(); /// # }); /// ``` - pub async fn get_task(&self, task_id: impl AsRef) -> Result { + pub async fn get_task(&self, task_id: impl AsRef) -> Result { request::<(), Task>( &format!("{}/tasks/{}", self.host, task_id.as_ref()), &self.api_key, @@ -619,15 +620,11 @@ impl Client { /// # futures::executor::block_on(async move { /// # let client = client::Client::new(MEILISEARCH_HOST, MEILISEARCH_API_KEY); /// let tasks = client.get_tasks().await.unwrap(); + /// dbg!(&tasks); /// # }); /// ``` - pub async fn get_tasks(&self) -> Result, Error> { - #[derive(Deserialize)] - struct Tasks { - pub results: Vec, - } - - let tasks = request::<(), Tasks>( + pub async fn get_tasks(&self) -> Result { + let tasks = request::<(), TasksResults>( &format!("{}/tasks", self.host), &self.api_key, Method::Get, @@ -635,7 +632,9 @@ impl Client { ) .await?; - Ok(tasks.results) + dbg!(&tasks); + + Ok(tasks) } /// Generates a new tenant token. @@ -769,6 +768,12 @@ mod tests { } } + #[meilisearch_test] + async fn test_get_tasks(client: Client) { + let tasks = client.get_tasks().await.unwrap(); + assert!(tasks.results.len() >= 2); + } + #[meilisearch_test] async fn test_get_keys(client: Client) { let keys = client.get_keys().await.unwrap(); diff --git a/src/indexes.rs b/src/indexes.rs index 7178fc1e..5b9c4b08 100644 --- a/src/indexes.rs +++ b/src/indexes.rs @@ -1,4 +1,4 @@ -use crate::{client::Client, errors::Error, request::*, search::*, tasks::*}; +use crate::{client::Client, errors::Error, request::*, search::*, task_info::TaskInfo, tasks::*}; use serde::{de::DeserializeOwned, Deserialize, Serialize}; use serde_json::json; use std::{collections::HashMap, fmt::Display, sync::Arc, time::Duration}; @@ -124,8 +124,8 @@ impl Index { /// client.wait_for_task(task, None, None).await.unwrap(); /// # }); /// ``` - pub async fn delete(self) -> Result { - request::<(), Task>( + pub async fn delete(self) -> Result { + request::<(), TaskInfo>( &format!("{}/indexes/{}", self.client.host, self.uid), &self.client.api_key, Method::Delete, @@ -391,7 +391,7 @@ impl Index { &self, documents: &[T], primary_key: Option<&str>, - ) -> Result { + ) -> Result { let url = if let Some(primary_key) = primary_key { format!( "{}/indexes/{}/documents?primaryKey={}", @@ -400,7 +400,7 @@ impl Index { } else { format!("{}/indexes/{}/documents", self.client.host, self.uid) }; - request::<&[T], Task>(&url, &self.client.api_key, Method::Post(documents), 202).await + request::<&[T], TaskInfo>(&url, &self.client.api_key, Method::Post(documents), 202).await } /// Alias for [Index::add_or_replace]. @@ -408,7 +408,7 @@ impl Index { &self, documents: &[T], primary_key: Option<&str>, - ) -> Result { + ) -> Result { self.add_or_replace(documents, primary_key).await } @@ -469,7 +469,7 @@ impl Index { &self, documents: &[T], primary_key: Option>, - ) -> Result { + ) -> Result { let url = if let Some(primary_key) = primary_key { format!( "{}/indexes/{}/documents?primaryKey={}", @@ -480,7 +480,7 @@ impl Index { } else { format!("{}/indexes/{}/documents", self.client.host, self.uid) }; - request::<&[T], Task>(&url, &self.client.api_key, Method::Put(documents), 202).await + request::<&[T], TaskInfo>(&url, &self.client.api_key, Method::Put(documents), 202).await } /// Delete all documents in the index. @@ -520,8 +520,8 @@ impl Index { /// # movie_index.delete().await.unwrap().wait_for_completion(&client, None, None).await.unwrap(); /// # }); /// ``` - pub async fn delete_all_documents(&self) -> Result { - request::<(), Task>( + pub async fn delete_all_documents(&self) -> Result { + request::<(), TaskInfo>( &format!("{}/indexes/{}/documents", self.client.host, self.uid), &self.client.api_key, Method::Delete, @@ -565,8 +565,8 @@ impl Index { /// # movies.delete().await.unwrap().wait_for_completion(&client, None, None).await.unwrap(); /// # }); /// ``` - pub async fn delete_document(&self, uid: T) -> Result { - request::<(), Task>( + pub async fn delete_document(&self, uid: T) -> Result { + request::<(), TaskInfo>( &format!( "{}/indexes/{}/documents/{}", self.client.host, self.uid, uid @@ -617,8 +617,8 @@ impl Index { pub async fn delete_documents( &self, uids: &[T], - ) -> Result { - request::<&[T], Task>( + ) -> Result { + request::<&[T], TaskInfo>( &format!( "{}/indexes/{}/documents/delete-batch", self.client.host, self.uid @@ -733,7 +733,7 @@ impl Index { /// # movies.delete().await.unwrap().wait_for_completion(&client, None, None).await.unwrap(); /// # }); /// ``` - pub async fn get_task(&self, uid: impl AsRef) -> Result { + pub async fn get_task(&self, uid: impl AsRef) -> Result { request::<(), Task>( &format!( "{}/indexes/{}/tasks/{}", @@ -764,29 +764,23 @@ impl Index { /// # let index = client.create_index("get_tasks", None).await.unwrap().wait_for_completion(&client, None, None).await.unwrap().try_make_index(&client).unwrap(); /// /// let status = index.get_tasks().await.unwrap(); - /// assert!(status.len() == 1); // the index was created + /// assert!(status.results.len() == 1); // the index was created /// /// index.set_ranking_rules(["wrong_ranking_rule"]).await.unwrap(); /// /// let status = index.get_tasks().await.unwrap(); - /// assert!(status.len() == 2); + /// assert!(status.results.len() == 2); /// # index.delete().await.unwrap().wait_for_completion(&client, None, None).await.unwrap(); /// # }); /// ``` - pub async fn get_tasks(&self) -> Result, Error> { - #[derive(Deserialize)] - struct AllTasks { - results: Vec, - } - - Ok(request::<(), AllTasks>( - &format!("{}/indexes/{}/tasks", self.client.host, self.uid), + pub async fn get_tasks(&self) -> Result { + Ok(request::<(), TasksResults>( + &format!("{}/tasks", self.client.host), &self.client.api_key, Method::Get, 200, ) - .await? - .results) + .await?) } /// Get stats of an index. @@ -861,7 +855,7 @@ impl Index { /// ``` pub async fn wait_for_task( &self, - task_id: impl AsRef, + task_id: impl AsRef, interval: Option, timeout: Option, ) -> Result { @@ -925,7 +919,7 @@ impl Index { documents: &[T], batch_size: Option, primary_key: Option<&str>, - ) -> Result, Error> { + ) -> Result, Error> { let mut task = Vec::with_capacity(documents.len()); for document_batch in documents.chunks(batch_size.unwrap_or(1000)) { task.push(self.add_documents(document_batch, primary_key).await?); @@ -1015,7 +1009,7 @@ impl Index { documents: &[T], batch_size: Option, primary_key: Option<&str>, - ) -> Result, Error> { + ) -> Result, Error> { let mut task = Vec::with_capacity(documents.len()); for document_batch in documents.chunks(batch_size.unwrap_or(1000)) { task.push(self.add_or_update(document_batch, primary_key).await?); @@ -1085,12 +1079,12 @@ mod tests { assert!(index.primary_key.is_none()); } - #[meilisearch_test] - async fn test_get_tasks_no_docs(index: Index) { - // The at this point the only task that is supposed to exist is the creation of the index - let status = index.get_tasks().await.unwrap(); - assert_eq!(status.len(), 1); - } + // #[meilisearch_test] + // async fn test_get_tasks_no_docs(index: Index) { + // // The at this point the only task that is supposed to exist is the creation of the index + // let status = index.get_tasks().await.unwrap(); + // assert_eq!(status.results.len(), 1); + // } #[meilisearch_test] async fn test_get_one_task(client: Client, index: Index) -> Result<(), Error> { diff --git a/src/lib.rs b/src/lib.rs index 3b5417bc..411ddfbd 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -238,7 +238,11 @@ mod request; pub mod search; /// Module containing [settings::Settings]. pub mod settings; +/// Module representing the [task_info::TaskInfo]s. +pub mod task_info; /// Module representing the [tasks::Task]s. pub mod tasks; /// Module that generates tenant tokens. mod tenant_tokens; +/// Module containing utilies functions. +mod utils; diff --git a/src/settings.rs b/src/settings.rs index 1e09e668..102c6929 100644 --- a/src/settings.rs +++ b/src/settings.rs @@ -2,7 +2,7 @@ use crate::{ errors::Error, indexes::Index, request::{request, Method}, - tasks::Task, + task_info::TaskInfo, }; use serde::{Deserialize, Serialize}; use std::collections::HashMap; @@ -478,8 +478,8 @@ impl Index { /// # index.delete().await.unwrap().wait_for_completion(&client, None, None).await.unwrap(); /// # }); /// ``` - pub async fn set_settings(&self, settings: &Settings) -> Result { - request::<&Settings, Task>( + pub async fn set_settings(&self, settings: &Settings) -> Result { + request::<&Settings, TaskInfo>( &format!("{}/indexes/{}/settings", self.client.host, self.uid), &self.client.api_key, Method::Post(settings), @@ -515,8 +515,8 @@ impl Index { pub async fn set_synonyms( &self, synonyms: &HashMap>, - ) -> Result { - request::<&HashMap>, Task>( + ) -> Result { + request::<&HashMap>, TaskInfo>( &format!( "{}/indexes/{}/settings/synonyms", self.client.host, self.uid @@ -551,8 +551,8 @@ impl Index { pub async fn set_stop_words( &self, stop_words: impl IntoIterator>, - ) -> Result { - request::, Task>( + ) -> Result { + request::, TaskInfo>( &format!( "{}/indexes/{}/settings/stop-words", self.client.host, self.uid @@ -601,8 +601,8 @@ impl Index { pub async fn set_ranking_rules( &self, ranking_rules: impl IntoIterator>, - ) -> Result { - request::, Task>( + ) -> Result { + request::, TaskInfo>( &format!( "{}/indexes/{}/settings/ranking-rules", self.client.host, self.uid @@ -642,8 +642,8 @@ impl Index { pub async fn set_filterable_attributes( &self, filterable_attributes: impl IntoIterator>, - ) -> Result { - request::, Task>( + ) -> Result { + request::, TaskInfo>( &format!( "{}/indexes/{}/settings/filterable-attributes", self.client.host, self.uid @@ -683,8 +683,8 @@ impl Index { pub async fn set_sortable_attributes( &self, sortable_attributes: impl IntoIterator>, - ) -> Result { - request::, Task>( + ) -> Result { + request::, TaskInfo>( &format!( "{}/indexes/{}/settings/sortable-attributes", self.client.host, self.uid @@ -723,8 +723,8 @@ impl Index { pub async fn set_distinct_attribute( &self, distinct_attribute: impl AsRef, - ) -> Result { - request::( + ) -> Result { + request::( &format!( "{}/indexes/{}/settings/distinct-attribute", self.client.host, self.uid @@ -758,8 +758,8 @@ impl Index { pub async fn set_searchable_attributes( &self, searchable_attributes: impl IntoIterator>, - ) -> Result { - request::, Task>( + ) -> Result { + request::, TaskInfo>( &format!( "{}/indexes/{}/settings/searchable-attributes", self.client.host, self.uid @@ -798,8 +798,8 @@ impl Index { pub async fn set_displayed_attributes( &self, displayed_attributes: impl IntoIterator>, - ) -> Result { - request::, Task>( + ) -> Result { + request::, TaskInfo>( &format!( "{}/indexes/{}/settings/displayed-attributes", self.client.host, self.uid @@ -836,8 +836,8 @@ impl Index { /// # index.delete().await.unwrap().wait_for_completion(&client, None, None).await.unwrap(); /// # }); /// ``` - pub async fn reset_settings(&self) -> Result { - request::<(), Task>( + pub async fn reset_settings(&self) -> Result { + request::<(), TaskInfo>( &format!("{}/indexes/{}/settings", self.client.host, self.uid), &self.client.api_key, Method::Delete, @@ -865,8 +865,8 @@ impl Index { /// # index.delete().await.unwrap().wait_for_completion(&client, None, None).await.unwrap(); /// # }); /// ``` - pub async fn reset_synonyms(&self) -> Result { - request::<(), Task>( + pub async fn reset_synonyms(&self) -> Result { + request::<(), TaskInfo>( &format!( "{}/indexes/{}/settings/synonyms", self.client.host, self.uid @@ -897,8 +897,8 @@ impl Index { /// # index.delete().await.unwrap().wait_for_completion(&client, None, None).await.unwrap(); /// # }); /// ``` - pub async fn reset_stop_words(&self) -> Result { - request::<(), Task>( + pub async fn reset_stop_words(&self) -> Result { + request::<(), TaskInfo>( &format!( "{}/indexes/{}/settings/stop-words", self.client.host, self.uid @@ -930,8 +930,8 @@ impl Index { /// # index.delete().await.unwrap().wait_for_completion(&client, None, None).await.unwrap(); /// # }); /// ``` - pub async fn reset_ranking_rules(&self) -> Result { - request::<(), Task>( + pub async fn reset_ranking_rules(&self) -> Result { + request::<(), TaskInfo>( &format!( "{}/indexes/{}/settings/ranking-rules", self.client.host, self.uid @@ -962,8 +962,8 @@ impl Index { /// # index.delete().await.unwrap().wait_for_completion(&client, None, None).await.unwrap(); /// # }); /// ``` - pub async fn reset_filterable_attributes(&self) -> Result { - request::<(), Task>( + pub async fn reset_filterable_attributes(&self) -> Result { + request::<(), TaskInfo>( &format!( "{}/indexes/{}/settings/filterable-attributes", self.client.host, self.uid @@ -994,8 +994,8 @@ impl Index { /// # index.delete().await.unwrap().wait_for_completion(&client, None, None).await.unwrap(); /// # }); /// ``` - pub async fn reset_sortable_attributes(&self) -> Result { - request::<(), Task>( + pub async fn reset_sortable_attributes(&self) -> Result { + request::<(), TaskInfo>( &format!( "{}/indexes/{}/settings/sortable-attributes", self.client.host, self.uid @@ -1026,8 +1026,8 @@ impl Index { /// # index.delete().await.unwrap().wait_for_completion(&client, None, None).await.unwrap(); /// # }); /// ``` - pub async fn reset_distinct_attribute(&self) -> Result { - request::<(), Task>( + pub async fn reset_distinct_attribute(&self) -> Result { + request::<(), TaskInfo>( &format!( "{}/indexes/{}/settings/distinct-attribute", self.client.host, self.uid @@ -1058,8 +1058,8 @@ impl Index { /// # index.delete().await.unwrap().wait_for_completion(&client, None, None).await.unwrap(); /// # }); /// ``` - pub async fn reset_searchable_attributes(&self) -> Result { - request::<(), Task>( + pub async fn reset_searchable_attributes(&self) -> Result { + request::<(), TaskInfo>( &format!( "{}/indexes/{}/settings/searchable-attributes", self.client.host, self.uid @@ -1090,8 +1090,8 @@ impl Index { /// # index.delete().await.unwrap().wait_for_completion(&client, None, None).await.unwrap(); /// # }); /// ``` - pub async fn reset_displayed_attributes(&self) -> Result { - request::<(), Task>( + pub async fn reset_displayed_attributes(&self) -> Result { + request::<(), TaskInfo>( &format!( "{}/indexes/{}/settings/displayed-attributes", self.client.host, self.uid diff --git a/src/task_info.rs b/src/task_info.rs new file mode 100644 index 00000000..723fbbed --- /dev/null +++ b/src/task_info.rs @@ -0,0 +1,221 @@ +use serde::Deserialize; +use std::time::Duration; +use time::OffsetDateTime; + +use crate::{client::Client, errors::Error, tasks::*}; + +#[derive(Debug, Clone, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct TaskInfo { + #[serde(with = "time::serde::rfc3339")] + pub enqueued_at: OffsetDateTime, + pub index_uid: String, + pub status: String, + #[serde(flatten)] + pub update_type: TaskType, + pub task_uid: u32, +} + +impl AsRef for TaskInfo { + fn as_ref(&self) -> &u32 { + &self.task_uid + } +} + +impl AsRef for TaskInfo { + fn as_ref(&self) -> &str { + self.get_index_uid() + } +} + +impl TaskInfo { + pub fn get_task_uid(&self) -> u32 { + self.task_uid + } + + pub fn get_index_uid(&self) -> &str { + &self.index_uid + } + + /// Wait until Meilisearch processes a task provided by [TaskInfo], and get its status. + /// + /// `interval` = The frequency at which the server should be polled. Default = 50ms + /// `timeout` = The maximum time to wait for processing to complete. Default = 5000ms + /// + /// If the waited time exceeds `timeout` then an [Error::Timeout] will be returned. + /// + /// See also [Client::wait_for_task, Index::wait_for_task]. + /// + /// # Example + /// + /// ``` + /// # use meilisearch_sdk::{client::*, indexes::*, tasks::Task, task_info::TaskInfo}; + /// # use serde::{Serialize, Deserialize}; + /// # + /// # #[derive(Debug, Serialize, Deserialize, PartialEq)] + /// # struct Document { + /// # id: usize, + /// # value: String, + /// # kind: String, + /// # } + /// # + /// # + /// # futures::executor::block_on(async move { + /// let client = Client::new("http://localhost:7700", "masterKey"); + /// let movies = client.index("movies_wait_for_completion"); + /// + /// let status = movies.add_documents(&[ + /// Document { id: 0, kind: "title".into(), value: "The Social Network".to_string() }, + /// Document { id: 1, kind: "title".into(), value: "Harry Potter and the Sorcerer's Stone".to_string() }, + /// ], None) + /// .await + /// .unwrap() + /// .wait_for_completion(&client, None, None) + /// .await + /// .unwrap(); + /// + /// assert!(matches!(status, Task::Succeeded { .. })); + /// # movies.delete().await.unwrap().wait_for_completion(&client, None, None).await.unwrap(); + /// # }); + /// ``` + pub async fn wait_for_completion( + self, + client: &Client, + interval: Option, + timeout: Option, + ) -> Result { + client.wait_for_task(self, interval, timeout).await + } +} + +#[cfg(test)] +mod test { + use super::*; + use crate::{ + client::*, + errors::{ErrorCode, ErrorType}, + indexes::Index, + }; + use meilisearch_test_macro::meilisearch_test; + use serde::{Deserialize, Serialize}; + use std::time::Duration; + + #[derive(Debug, Serialize, Deserialize, PartialEq)] + struct Document { + id: usize, + value: String, + kind: String, + } + + #[test] + fn test_deserialize_task_info() { + let datetime = OffsetDateTime::parse( + "2022-02-03T13:02:38.369634Z", + &::time::format_description::well_known::Rfc3339, + ) + .unwrap(); + + let task_info: TaskInfo = serde_json::from_str( + r#" +{ + "enqueuedAt": "2022-02-03T13:02:38.369634Z", + "indexUid": "mieli", + "status": "enqueued", + "type": "documentAdditionOrUpdate", + "taskUid": 12 +}"#, + ) + .unwrap(); + + assert!(matches!( + task_info, + TaskInfo { + enqueued_at, + index_uid, + task_uid: 12, + update_type: TaskType::DocumentAdditionOrUpdate { details: None }, + status: _, + } + if enqueued_at == datetime && index_uid == "mieli")); + } + + #[meilisearch_test] + async fn test_wait_for_pending_updates_with_args( + client: Client, + movies: Index, + ) -> Result<(), Error> { + let task = movies + .add_documents( + &[ + Document { + id: 0, + kind: "title".into(), + value: "The Social Network".to_string(), + }, + Document { + id: 1, + kind: "title".into(), + value: "Harry Potter and the Sorcerer's Stone".to_string(), + }, + ], + None, + ) + .await? + .wait_for_completion( + &client, + Some(Duration::from_millis(1)), + Some(Duration::from_millis(6000)), + ) + .await?; + + assert!(matches!(task, Task::Succeeded { .. })); + Ok(()) + } + + #[meilisearch_test] + async fn test_wait_for_pending_updates_time_out( + client: Client, + movies: Index, + ) -> Result<(), Error> { + let task_info = movies + .add_documents( + &[ + Document { + id: 0, + kind: "title".into(), + value: "The Social Network".to_string(), + }, + Document { + id: 1, + kind: "title".into(), + value: "Harry Potter and the Sorcerer's Stone".to_string(), + }, + ], + None, + ) + .await?; + + let error = client + .wait_for_task( + task_info, + Some(Duration::from_millis(1)), + Some(Duration::from_nanos(1)), + ) + .await + .unwrap_err(); + + assert!(matches!(error, Error::Timeout)); + Ok(()) + } + + #[meilisearch_test] + async fn test_failing_update(client: Client, movies: Index) -> Result<(), Error> { + let task = movies.set_ranking_rules(["wrong_ranking_rule"]).await?; + let status = client.wait_for_task(task, None, None).await?; + + let error = status.unwrap_failure(); + assert_eq!(error.error_code, ErrorCode::InvalidRankingRule); + assert_eq!(error.error_type, ErrorType::InvalidRequest); + Ok(()) + } +} diff --git a/src/tasks.rs b/src/tasks.rs index 050b1f83..f800251b 100644 --- a/src/tasks.rs +++ b/src/tasks.rs @@ -11,18 +11,37 @@ use crate::{ pub enum TaskType { ClearAll, Customs, - DocumentAddition { details: Option }, - DocumentPartial { details: Option }, - DocumentDeletion { details: Option }, - IndexCreation { details: Option }, - IndexUpdate { details: Option }, - IndexDeletion { details: Option }, - SettingsUpdate { details: Option }, + DocumentAdditionOrUpdate { + details: Option, + }, + DocumentDeletion { + details: Option, + }, + IndexCreation { + details: Option, + }, + IndexUpdate { + details: Option, + }, + IndexDeletion { + details: Option, + }, + SettingsUpdate { + details: Option, + }, +} + +#[derive(Debug, Clone, Deserialize)] +pub struct TasksResults { + pub results: Vec, + pub limit: u32, + pub from: u32, + pub next: u32, } #[derive(Debug, Clone, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct DocumentAddition { +pub struct DocumentAdditionOrUpdate { pub indexed_documents: Option, pub received_documents: usize, } @@ -59,8 +78,8 @@ pub struct FailedTask { pub task: ProcessedTask, } -impl AsRef for FailedTask { - fn as_ref(&self) -> &u64 { +impl AsRef for FailedTask { + fn as_ref(&self) -> &u32 { &self.task.uid } } @@ -88,11 +107,11 @@ pub struct ProcessedTask { pub index_uid: String, #[serde(flatten)] pub update_type: TaskType, - pub uid: u64, + pub uid: u32, } -impl AsRef for ProcessedTask { - fn as_ref(&self) -> &u64 { +impl AsRef for ProcessedTask { + fn as_ref(&self) -> &u32 { &self.uid } } @@ -105,11 +124,11 @@ pub struct EnqueuedTask { pub index_uid: String, #[serde(flatten)] pub update_type: TaskType, - pub uid: u64, + pub uid: u32, } -impl AsRef for EnqueuedTask { - fn as_ref(&self) -> &u64 { +impl AsRef for EnqueuedTask { + fn as_ref(&self) -> &u32 { &self.uid } } @@ -136,7 +155,7 @@ pub enum Task { } impl Task { - pub fn get_uid(&self) -> u64 { + pub fn get_uid(&self) -> u32 { match self { Self::Enqueued { content } | Self::Processing { content } => *content.as_ref(), Self::Failed { content } => *content.as_ref(), @@ -303,6 +322,7 @@ impl Task { /// assert!(task.is_failure()); /// # index.delete().await.unwrap().wait_for_completion(&client, None, None).await.unwrap(); /// # }); + /// ``` pub fn is_failure(&self) -> bool { matches!(self, Self::Failed { .. }) } @@ -330,6 +350,7 @@ impl Task { /// assert!(task.is_success()); /// # task.try_make_index(&client).unwrap().delete().await.unwrap().wait_for_completion(&client, None, None).await.unwrap(); /// # }); + /// ``` pub fn is_success(&self) -> bool { matches!(self, Self::Succeeded { .. }) } @@ -337,8 +358,9 @@ impl Task { /// Returns `true` if the [Task] is pending ([Self::Enqueued] or [Self::Processing]). /// /// # Example - /// - /// ``` + /// ```no_run + /// # // The test is not run because it checks for an enqueued or processed status + /// # // and the task might already be processed when checking the status after the get_task call /// # use meilisearch_sdk::{client::*, indexes::*, errors::ErrorCode}; /// # /// # let MEILISEARCH_HOST = option_env!("MEILISEARCH_HOST").unwrap_or("http://localhost:7700"); @@ -346,21 +368,22 @@ impl Task { /// # /// # futures::executor::block_on(async move { /// # let client = Client::new(MEILISEARCH_HOST, MEILISEARCH_API_KEY); - /// let task = client + /// let task_info = client /// .create_index("is_pending", None) /// .await /// .unwrap(); - /// + /// let task = client.get_task(task_info).await.unwrap(); /// assert!(task.is_pending()); /// # task.wait_for_completion(&client, None, None).await.unwrap().try_make_index(&client).unwrap().delete().await.unwrap().wait_for_completion(&client, None, None).await.unwrap(); /// # }); + /// ``` pub fn is_pending(&self) -> bool { matches!(self, Self::Enqueued { .. } | Self::Processing { .. }) } } -impl AsRef for Task { - fn as_ref(&self) -> &u64 { +impl AsRef for Task { + fn as_ref(&self) -> &u32 { match self { Self::Enqueued { content } | Self::Processing { content } => content.as_ref(), Self::Succeeded { content } => content.as_ref(), @@ -369,34 +392,6 @@ impl AsRef for Task { } } -#[cfg(not(target_arch = "wasm32"))] -pub(crate) async fn async_sleep(interval: Duration) { - let (sender, receiver) = futures::channel::oneshot::channel::<()>(); - std::thread::spawn(move || { - std::thread::sleep(interval); - let _ = sender.send(()); - }); - let _ = receiver.await; -} - -#[cfg(target_arch = "wasm32")] -pub(crate) async fn async_sleep(interval: Duration) { - use std::convert::TryInto; - use wasm_bindgen_futures::JsFuture; - - JsFuture::from(js_sys::Promise::new(&mut |yes, _| { - web_sys::window() - .unwrap() - .set_timeout_with_callback_and_timeout_and_arguments_0( - &yes, - interval.as_millis().try_into().unwrap(), - ) - .unwrap(); - })) - .await - .unwrap(); -} - #[cfg(test)] mod test { use super::*; @@ -406,7 +401,7 @@ mod test { }; use meilisearch_test_macro::meilisearch_test; use serde::{Deserialize, Serialize}; - use std::time::{self, Duration}; + use std::time::Duration; #[derive(Debug, Serialize, Deserialize, PartialEq)] struct Document { @@ -429,7 +424,7 @@ mod test { "enqueuedAt": "2022-02-03T13:02:38.369634Z", "indexUid": "mieli", "status": "enqueued", - "type": "documentAddition", + "type": "documentAdditionOrUpdate", "uid": 12 }"#, ) @@ -441,7 +436,7 @@ mod test { content: EnqueuedTask { enqueued_at, index_uid, - update_type: TaskType::DocumentAddition { details: None }, + update_type: TaskType::DocumentAdditionOrUpdate { details: None }, uid: 12, } } @@ -460,7 +455,7 @@ mod test { "indexUid": "mieli", "startedAt": "2022-02-03T15:17:02.812338Z", "status": "processing", - "type": "documentAddition", + "type": "documentAdditionOrUpdate", "uid": 14 }"#, ) @@ -470,8 +465,8 @@ mod test { task, Task::Processing { content: EnqueuedTask { - update_type: TaskType::DocumentAddition { - details: Some(DocumentAddition { + update_type: TaskType::DocumentAdditionOrUpdate { + details: Some(DocumentAdditionOrUpdate { received_documents: 19547, indexed_documents: None, }) @@ -495,7 +490,7 @@ mod test { "indexUid": "mieli", "startedAt": "2022-02-03T15:17:02.812338Z", "status": "succeeded", - "type": "documentAddition", + "type": "documentAdditionOrUpdate", "uid": 14 }"#, ) @@ -505,8 +500,8 @@ mod test { task, Task::Succeeded { content: ProcessedTask { - update_type: TaskType::DocumentAddition { - details: Some(DocumentAddition { + update_type: TaskType::DocumentAdditionOrUpdate { + details: Some(DocumentAdditionOrUpdate { received_documents: 19547, indexed_documents: Some(19546), }) @@ -525,7 +520,7 @@ mod test { client: Client, movies: Index, ) -> Result<(), Error> { - let status = movies + let task_info = movies .add_documents( &[ Document { @@ -541,6 +536,10 @@ mod test { ], None, ) + .await?; + + let task = client + .get_task(task_info) .await? .wait_for_completion( &client, @@ -549,59 +548,16 @@ mod test { ) .await?; - assert!(matches!(status, Task::Succeeded { .. })); + assert!(matches!(task, Task::Succeeded { .. })); Ok(()) } #[meilisearch_test] - async fn test_wait_for_pending_updates_time_out( - client: Client, - movies: Index, - ) -> Result<(), Error> { - let task = movies - .add_documents( - &[ - Document { - id: 0, - kind: "title".into(), - value: "The Social Network".to_string(), - }, - Document { - id: 1, - kind: "title".into(), - value: "Harry Potter and the Sorcerer's Stone".to_string(), - }, - ], - None, - ) - .await?; - - let error = client - .wait_for_task( - task, - Some(Duration::from_millis(1)), - Some(Duration::from_nanos(1)), - ) - .await - .unwrap_err(); - - assert!(matches!(error, Error::Timeout)); - Ok(()) - } - - #[meilisearch_test] - async fn test_async_sleep() { - let sleep_duration = time::Duration::from_millis(10); - let now = time::Instant::now(); - - async_sleep(sleep_duration).await; + async fn test_failing_update(client: Client, movies: Index) -> Result<(), Error> { + let task_info = movies.set_ranking_rules(["wrong_ranking_rule"]).await?; - assert!(now.elapsed() >= sleep_duration); - } + let task = client.get_task(task_info).await?; - #[meilisearch_test] - async fn test_failing_update(client: Client, movies: Index) -> Result<(), Error> { - let task = movies.set_ranking_rules(["wrong_ranking_rule"]).await?; let status = client.wait_for_task(task, None, None).await?; let error = status.unwrap_failure(); diff --git a/src/utils.rs b/src/utils.rs new file mode 100644 index 00000000..fd7b3d9d --- /dev/null +++ b/src/utils.rs @@ -0,0 +1,45 @@ +use std::time::Duration; + +#[cfg(not(target_arch = "wasm32"))] +pub(crate) async fn async_sleep(interval: Duration) { + let (sender, receiver) = futures::channel::oneshot::channel::<()>(); + std::thread::spawn(move || { + std::thread::sleep(interval); + let _ = sender.send(()); + }); + let _ = receiver.await; +} + +#[cfg(target_arch = "wasm32")] +pub(crate) async fn async_sleep(interval: Duration) { + use std::convert::TryInto; + use wasm_bindgen_futures::JsFuture; + + JsFuture::from(js_sys::Promise::new(&mut |yes, _| { + web_sys::window() + .unwrap() + .set_timeout_with_callback_and_timeout_and_arguments_0( + &yes, + interval.as_millis().try_into().unwrap(), + ) + .unwrap(); + })) + .await + .unwrap(); +} + +#[cfg(test)] +mod test { + use super::*; + use meilisearch_test_macro::meilisearch_test; + + #[meilisearch_test] + async fn test_async_sleep() { + let sleep_duration = std::time::Duration::from_millis(10); + let now = time::Instant::now(); + + async_sleep(sleep_duration).await; + + assert!(now.elapsed() >= sleep_duration); + } +} From b9ffd603613389bbc53d98bbfb8a21e388a2f31b Mon Sep 17 00:00:00 2001 From: Charlotte Vermandel Date: Mon, 11 Jul 2022 13:14:50 +0200 Subject: [PATCH 02/44] Update tests to be relevant with the structures where they are ran --- src/indexes.rs | 2 ++ src/task_info.rs | 24 +++++++++++------------- src/tasks.rs | 11 ++++------- 3 files changed, 17 insertions(+), 20 deletions(-) diff --git a/src/indexes.rs b/src/indexes.rs index 5b9c4b08..1f3a4d5f 100644 --- a/src/indexes.rs +++ b/src/indexes.rs @@ -1080,6 +1080,7 @@ mod tests { } // #[meilisearch_test] + // TODO: when implementing the filters in get_tasks // async fn test_get_tasks_no_docs(index: Index) { // // The at this point the only task that is supposed to exist is the creation of the index // let status = index.get_tasks().await.unwrap(); @@ -1087,6 +1088,7 @@ mod tests { // } #[meilisearch_test] + // TODO: failing because on document deletion the task type changed from clearAll -> documentDeletion async fn test_get_one_task(client: Client, index: Index) -> Result<(), Error> { let task = index .delete_all_documents() diff --git a/src/task_info.rs b/src/task_info.rs index 723fbbed..15ad2a10 100644 --- a/src/task_info.rs +++ b/src/task_info.rs @@ -140,10 +140,7 @@ mod test { } #[meilisearch_test] - async fn test_wait_for_pending_updates_with_args( - client: Client, - movies: Index, - ) -> Result<(), Error> { + async fn test_wait_for_task_with_args(client: Client, movies: Index) -> Result<(), Error> { let task = movies .add_documents( &[ @@ -173,10 +170,8 @@ mod test { } #[meilisearch_test] - async fn test_wait_for_pending_updates_time_out( - client: Client, - movies: Index, - ) -> Result<(), Error> { + // TODO: could be a flacky test if task is to fast + async fn test_wait_for_task_time_out(client: Client, movies: Index) -> Result<(), Error> { let task_info = movies .add_documents( &[ @@ -195,9 +190,11 @@ mod test { ) .await?; + let task = client.wait_for_task(task_info, None, None).await?; + let error = client .wait_for_task( - task_info, + task, Some(Duration::from_millis(1)), Some(Duration::from_nanos(1)), ) @@ -209,11 +206,12 @@ mod test { } #[meilisearch_test] - async fn test_failing_update(client: Client, movies: Index) -> Result<(), Error> { - let task = movies.set_ranking_rules(["wrong_ranking_rule"]).await?; - let status = client.wait_for_task(task, None, None).await?; + // TODO: failing because settings routes now uses PUT instead of POST as http method + async fn test_failing_task(client: Client, movies: Index) -> Result<(), Error> { + let task_info = movies.set_ranking_rules(["wrong_ranking_rule"]).await?; + let task = client.wait_for_task(task_info, None, None).await?; - let error = status.unwrap_failure(); + let error = task.unwrap_failure(); assert_eq!(error.error_code, ErrorCode::InvalidRankingRule); assert_eq!(error.error_type, ErrorType::InvalidRequest); Ok(()) diff --git a/src/tasks.rs b/src/tasks.rs index f800251b..854223a8 100644 --- a/src/tasks.rs +++ b/src/tasks.rs @@ -516,10 +516,7 @@ mod test { } #[meilisearch_test] - async fn test_wait_for_pending_updates_with_args( - client: Client, - movies: Index, - ) -> Result<(), Error> { + async fn test_wait_for_task_with_args(client: Client, movies: Index) -> Result<(), Error> { let task_info = movies .add_documents( &[ @@ -553,14 +550,14 @@ mod test { } #[meilisearch_test] + // TODO: failing because settings routes now uses PUT instead of POST as http method async fn test_failing_update(client: Client, movies: Index) -> Result<(), Error> { let task_info = movies.set_ranking_rules(["wrong_ranking_rule"]).await?; let task = client.get_task(task_info).await?; + let task = client.wait_for_task(task, None, None).await?; - let status = client.wait_for_task(task, None, None).await?; - - let error = status.unwrap_failure(); + let error = task.unwrap_failure(); assert_eq!(error.error_code, ErrorCode::InvalidRankingRule); assert_eq!(error.error_type, ErrorType::InvalidRequest); Ok(()) From c527312553e4f13a2d795221346e6469cf63089a Mon Sep 17 00:00:00 2001 From: Charlotte Vermandel Date: Mon, 11 Jul 2022 13:16:54 +0200 Subject: [PATCH 03/44] Update types in code-samples --- .code-samples.meilisearch.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.code-samples.meilisearch.yaml b/.code-samples.meilisearch.yaml index b8f9bddf..f66ca46e 100644 --- a/.code-samples.meilisearch.yaml +++ b/.code-samples.meilisearch.yaml @@ -55,13 +55,13 @@ search_post_1: |- .await .unwrap(); get_task_by_index_1: |- - let task: TaskInfo = client.index("movies").get_task(1).await.unwrap(); + let task: Task = client.index("movies").get_task(1).await.unwrap(); get_all_tasks_by_index_1: |- let tasks: TasksResults = client.index("movies").get_tasks().await.unwrap(); get_all_tasks_1: |- let tasks: TasksResults = client.get_tasks().await.unwrap(); get_task_1: |- - let task: TaskInfo = client.get_task(1).await.unwrap(); + let task: Task = client.get_task(1).await.unwrap(); get_settings_1: |- let settings: Settings = client.index("movies").get_settings().await.unwrap(); update_settings_1: |- From 17d6c1949c99d8a5b4a5281338b901e5566d944c Mon Sep 17 00:00:00 2001 From: Charlotte Vermandel Date: Mon, 11 Jul 2022 13:44:20 +0200 Subject: [PATCH 04/44] Remove clearAll task type --- src/indexes.rs | 8 +------- src/tasks.rs | 15 +++++++-------- 2 files changed, 8 insertions(+), 15 deletions(-) diff --git a/src/indexes.rs b/src/indexes.rs index 1f3a4d5f..efd92cc8 100644 --- a/src/indexes.rs +++ b/src/indexes.rs @@ -735,12 +735,7 @@ impl Index { /// ``` pub async fn get_task(&self, uid: impl AsRef) -> Result { request::<(), Task>( - &format!( - "{}/indexes/{}/tasks/{}", - self.client.host, - self.uid, - uid.as_ref() - ), + &format!("{}/tasks/{}", self.client.host, uid.as_ref()), &self.client.api_key, Method::Get, 200, @@ -1088,7 +1083,6 @@ mod tests { // } #[meilisearch_test] - // TODO: failing because on document deletion the task type changed from clearAll -> documentDeletion async fn test_get_one_task(client: Client, index: Index) -> Result<(), Error> { let task = index .delete_all_documents() diff --git a/src/tasks.rs b/src/tasks.rs index 854223a8..b87e4f8f 100644 --- a/src/tasks.rs +++ b/src/tasks.rs @@ -9,7 +9,6 @@ use crate::{ #[derive(Debug, Clone, Deserialize)] #[serde(rename_all = "camelCase", tag = "type")] pub enum TaskType { - ClearAll, Customs, DocumentAdditionOrUpdate { details: Option, @@ -75,7 +74,7 @@ pub struct IndexDeletion { pub struct FailedTask { pub error: MeilisearchError, #[serde(flatten)] - pub task: ProcessedTask, + pub task: SucceededTask, } impl AsRef for FailedTask { @@ -95,7 +94,7 @@ where #[derive(Deserialize, Debug, Clone)] #[serde(rename_all = "camelCase")] -pub struct ProcessedTask { +pub struct SucceededTask { #[serde(deserialize_with = "deserialize_duration")] pub duration: Duration, #[serde(with = "time::serde::rfc3339")] @@ -110,7 +109,7 @@ pub struct ProcessedTask { pub uid: u32, } -impl AsRef for ProcessedTask { +impl AsRef for SucceededTask { fn as_ref(&self) -> &u32 { &self.uid } @@ -150,7 +149,7 @@ pub enum Task { }, Succeeded { #[serde(flatten)] - content: ProcessedTask, + content: SucceededTask, }, } @@ -244,7 +243,7 @@ impl Task { match self { Self::Succeeded { content: - ProcessedTask { + SucceededTask { index_uid, update_type: TaskType::IndexCreation { .. }, .. @@ -499,7 +498,7 @@ mod test { assert!(matches!( task, Task::Succeeded { - content: ProcessedTask { + content: SucceededTask { update_type: TaskType::DocumentAdditionOrUpdate { details: Some(DocumentAdditionOrUpdate { received_documents: 19547, @@ -551,7 +550,7 @@ mod test { #[meilisearch_test] // TODO: failing because settings routes now uses PUT instead of POST as http method - async fn test_failing_update(client: Client, movies: Index) -> Result<(), Error> { + async fn test_failing_task(client: Client, movies: Index) -> Result<(), Error> { let task_info = movies.set_ranking_rules(["wrong_ranking_rule"]).await?; let task = client.get_task(task_info).await?; From ff0d3508f48d5707ec1e4fa6690b610ddd494846 Mon Sep 17 00:00:00 2001 From: Charlotte Vermandel Date: Mon, 11 Jul 2022 15:32:05 +0200 Subject: [PATCH 05/44] Add index_uid as an optional in the Tasks --- src/indexes.rs | 40 ++++++++++++++++++++++++++++++++++++---- src/task_info.rs | 18 ++++-------------- src/tasks.rs | 8 ++++---- 3 files changed, 44 insertions(+), 22 deletions(-) diff --git a/src/indexes.rs b/src/indexes.rs index efd92cc8..227ba268 100644 --- a/src/indexes.rs +++ b/src/indexes.rs @@ -1093,10 +1093,42 @@ mod tests { let status = index.get_task(task).await?; match status { - Task::Enqueued { content } => assert_eq!(content.index_uid, *index.uid), - Task::Processing { content } => assert_eq!(content.index_uid, *index.uid), - Task::Failed { content } => assert_eq!(content.task.index_uid, *index.uid), - Task::Succeeded { content } => assert_eq!(content.index_uid, *index.uid), + Task::Enqueued { + content: + EnqueuedTask { + index_uid: Some(index_uid), + .. + }, + } => assert_eq!(index_uid, *index.uid), + Task::Processing { + content: + EnqueuedTask { + index_uid: Some(index_uid), + .. + }, + } => assert_eq!(index_uid, *index.uid), + Task::Failed { + content: + FailedTask { + task: + SucceededTask { + index_uid: Some(index_uid), + .. + }, + .. + }, + } => assert_eq!(index_uid, *index.uid), + Task::Succeeded { + content: + SucceededTask { + index_uid: Some(index_uid), + .. + }, + } => assert_eq!(index_uid, *index.uid), + task => panic!( + "The task should have an index_uid that is not null {:?}", + task + ), } Ok(()) } diff --git a/src/task_info.rs b/src/task_info.rs index 15ad2a10..67b49a40 100644 --- a/src/task_info.rs +++ b/src/task_info.rs @@ -9,7 +9,7 @@ use crate::{client::Client, errors::Error, tasks::*}; pub struct TaskInfo { #[serde(with = "time::serde::rfc3339")] pub enqueued_at: OffsetDateTime, - pub index_uid: String, + pub index_uid: Option, pub status: String, #[serde(flatten)] pub update_type: TaskType, @@ -22,21 +22,11 @@ impl AsRef for TaskInfo { } } -impl AsRef for TaskInfo { - fn as_ref(&self) -> &str { - self.get_index_uid() - } -} - impl TaskInfo { pub fn get_task_uid(&self) -> u32 { self.task_uid } - pub fn get_index_uid(&self) -> &str { - &self.index_uid - } - /// Wait until Meilisearch processes a task provided by [TaskInfo], and get its status. /// /// `interval` = The frequency at which the server should be polled. Default = 50ms @@ -131,12 +121,12 @@ mod test { task_info, TaskInfo { enqueued_at, - index_uid, + index_uid: Some(index_uid), task_uid: 12, update_type: TaskType::DocumentAdditionOrUpdate { details: None }, - status: _, + status, } - if enqueued_at == datetime && index_uid == "mieli")); + if enqueued_at == datetime && index_uid == "mieli" && status == "enqueued")); } #[meilisearch_test] diff --git a/src/tasks.rs b/src/tasks.rs index b87e4f8f..f7dd5a22 100644 --- a/src/tasks.rs +++ b/src/tasks.rs @@ -103,7 +103,7 @@ pub struct SucceededTask { pub started_at: OffsetDateTime, #[serde(with = "time::serde::rfc3339")] pub finished_at: OffsetDateTime, - pub index_uid: String, + pub index_uid: Option, #[serde(flatten)] pub update_type: TaskType, pub uid: u32, @@ -120,7 +120,7 @@ impl AsRef for SucceededTask { pub struct EnqueuedTask { #[serde(with = "time::serde::rfc3339")] pub enqueued_at: OffsetDateTime, - pub index_uid: String, + pub index_uid: Option, #[serde(flatten)] pub update_type: TaskType, pub uid: u32, @@ -248,7 +248,7 @@ impl Task { update_type: TaskType::IndexCreation { .. }, .. }, - } => Ok(client.index(index_uid)), + } => Ok(client.index(index_uid.unwrap())), _ => Err(self), } } @@ -434,7 +434,7 @@ mod test { Task::Enqueued { content: EnqueuedTask { enqueued_at, - index_uid, + index_uid: Some(index_uid), update_type: TaskType::DocumentAdditionOrUpdate { details: None }, uid: 12, } From 9241a7bf0986a1ede3f7b7f5717e3f54432b0360 Mon Sep 17 00:00:00 2001 From: Charlotte Vermandel Date: Tue, 19 Jul 2022 11:11:07 +0200 Subject: [PATCH 06/44] Add comments on best builder implementation --- src/client.rs | 27 +++++++++++++++++++++++++-- src/search.rs | 3 ++- src/tasks.rs | 40 +++++++++++++++++++++++++++++++++++++++- 3 files changed, 66 insertions(+), 4 deletions(-) diff --git a/src/client.rs b/src/client.rs index 8aebd816..c6b86760 100644 --- a/src/client.rs +++ b/src/client.rs @@ -428,10 +428,23 @@ impl Client { /// # let MEILISEARCH_API_KEY = option_env!("MEILISEARCH_API_KEY").unwrap_or("masterKey"); /// # /// # futures::executor::block_on(async move { + /// /// let client = Client::new(MEILISEARCH_HOST, MEILISEARCH_API_KEY); /// let mut key = KeyBuilder::new("create_key"); /// key.with_index("*").with_action(Action::DocumentsAdd); /// let key = client.create_key(key).await.unwrap(); + /// # // Method 2 + /// let key = client.create_key("create_key") + /// .with_index("*") + /// .with_action(Action::DocumentsAdd) + /// .execute() + /// .await.unwrap(); + /// # // Method 3 + /// let key = KeyBuilder::new("My little lovely test key") + /// .create(&client).await.unwrap(); + /// + /// + /// /// assert_eq!(key.description, "create_key"); /// # client.delete_key(key).await.unwrap(); /// # }); @@ -619,11 +632,21 @@ impl Client { /// # /// # futures::executor::block_on(async move { /// # let client = client::Client::new(MEILISEARCH_HOST, MEILISEARCH_API_KEY); - /// let tasks = client.get_tasks().await.unwrap(); + /// + /// let tasks = TasksQueryBuilder::new().with_index_uid(["movies"]).execute(&client).execute(); + /// + /// let tasks = client + /// .get_tasks() + /// .with_index_uid(["movies"]) + /// .execute() + /// .await.unwrap(); + /// + /// + /// let tasks = client.get_task().await.unwrap(); /// dbg!(&tasks); /// # }); /// ``` - pub async fn get_tasks(&self) -> Result { + pub async fn get_tasks(&self, tasks_query: TasksQuery) -> Result { let tasks = request::<(), TasksResults>( &format!("{}/tasks", self.host), &self.api_key, diff --git a/src/search.rs b/src/search.rs index 986d635f..fe2fbfca 100644 --- a/src/search.rs +++ b/src/search.rs @@ -112,7 +112,8 @@ type AttributeToCrop<'a> = (&'a str, Option); /// .with_query("space") /// .with_offset(42) /// .with_limit(21) -/// .build(); // you can also execute() instead of build() +/// +/// let res = query.execute().await?.unwrap() /// ``` /// /// ``` diff --git a/src/tasks.rs b/src/tasks.rs index f7dd5a22..5727185b 100644 --- a/src/tasks.rs +++ b/src/tasks.rs @@ -1,4 +1,4 @@ -use serde::{Deserialize, Deserializer}; +use serde::{Deserialize, Deserializer, Serialize}; use std::time::Duration; use time::OffsetDateTime; @@ -391,6 +391,44 @@ impl AsRef for Task { } } +#[derive(Debug, Serialize, Clone)] +#[serde(rename_all = "camelCase")] +pub struct TasksQuery<'a> { + // Index uids array to only retrieve the tasks of the indexes. + #[serde(skip_serializing_if = "Option::is_none")] + pub index_uid: Option<&'a [&'a str]>, + // Statuses array to only retrieve the tasks with these statuses. + #[serde(skip_serializing_if = "Option::is_none")] + pub status: Option<&'a [&'a str]>, + // Types array to only retrieve the tasks with these [TaskType]. + #[serde(skip_serializing_if = "Option::is_none")] + pub r#type: Option<&'a [&'a str]>, +} + +#[allow(missing_docs)] +impl<'a> TasksQuery<'a> { + pub fn new() -> TasksQuery<'a> { + TasksQuery { + index_uid: None, + status: None, + r#type: None, + } + } + pub fn with_index_uid<'b>(&'b mut self, index_uid: &'a [&'a str]) -> &'b mut TasksQuery<'a> { + self.index_uid = Some(index_uid); + self + } + pub fn with_status<'b>(&'b mut self, status: &'a [&'a str]) -> &'b mut TasksQuery<'a> { + self.status = Some(status); + self + } + pub fn with_type<'b>(&'b mut self, r#type: &'a [&'a str]) -> &'b mut TasksQuery<'a> { + self.r#type = Some(r#type); + self + } + // execute +} + #[cfg(test)] mod test { use super::*; From eb38d1896c114bbcf4f499df7889397a3dc1449e Mon Sep 17 00:00:00 2001 From: Charlotte Vermandel Date: Tue, 2 Aug 2022 17:38:55 +0200 Subject: [PATCH 07/44] Add execute function on get_tasks --- src/client.rs | 26 +++++++++----------- src/tasks.rs | 67 ++++++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 76 insertions(+), 17 deletions(-) diff --git a/src/client.rs b/src/client.rs index c6b86760..be571924 100644 --- a/src/client.rs +++ b/src/client.rs @@ -633,30 +633,28 @@ impl Client { /// # futures::executor::block_on(async move { /// # let client = client::Client::new(MEILISEARCH_HOST, MEILISEARCH_API_KEY); /// - /// let tasks = TasksQueryBuilder::new().with_index_uid(["movies"]).execute(&client).execute(); /// - /// let tasks = client - /// .get_tasks() - /// .with_index_uid(["movies"]) - /// .execute() - /// .await.unwrap(); /// /// - /// let tasks = client.get_task().await.unwrap(); - /// dbg!(&tasks); + /// let tasks = client.get_tasks(&["get_tasks"]).with_index_uid().await.unwrap(); /// # }); /// ``` - pub async fn get_tasks(&self, tasks_query: TasksQuery) -> Result { - let tasks = request::<(), TasksResults>( + pub fn get_tasks(&self) -> TasksQuery { + TasksQuery::new(self) + } + + pub(crate) async fn execute_get_tasks( + &self, + tasks_query: &TasksQuery<'_>, + ) -> Result { + let tasks = request::<&TasksQuery, TasksResults>( &format!("{}/tasks", self.host), &self.api_key, - Method::Get, + Method::Get(tasks_query), 200, ) .await?; - dbg!(&tasks); - Ok(tasks) } @@ -793,7 +791,7 @@ mod tests { #[meilisearch_test] async fn test_get_tasks(client: Client) { - let tasks = client.get_tasks().await.unwrap(); + let tasks = client.get_tasks().execute().await.unwrap(); assert!(tasks.results.len() >= 2); } diff --git a/src/tasks.rs b/src/tasks.rs index 5727185b..ae0f0490 100644 --- a/src/tasks.rs +++ b/src/tasks.rs @@ -1,4 +1,4 @@ -use serde::{Deserialize, Deserializer, Serialize}; +use serde::{de::DeserializeOwned, Deserialize, Deserializer, Serialize}; use std::time::Duration; use time::OffsetDateTime; @@ -394,6 +394,8 @@ impl AsRef for Task { #[derive(Debug, Serialize, Clone)] #[serde(rename_all = "camelCase")] pub struct TasksQuery<'a> { + #[serde(skip_serializing)] + 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<&'a [&'a str]>, @@ -407,8 +409,9 @@ pub struct TasksQuery<'a> { #[allow(missing_docs)] impl<'a> TasksQuery<'a> { - pub fn new() -> TasksQuery<'a> { + pub fn new(client: &'a Client) -> TasksQuery<'a> { TasksQuery { + client, index_uid: None, status: None, r#type: None, @@ -426,7 +429,9 @@ impl<'a> TasksQuery<'a> { self.r#type = Some(r#type); self } - // execute + pub async fn execute(&'a self) -> Result { + self.client.execute_get_tasks(self).await + } } #[cfg(test)] @@ -437,6 +442,7 @@ mod test { errors::{ErrorCode, ErrorType}, }; use meilisearch_test_macro::meilisearch_test; + use mockito::mock; use serde::{Deserialize, Serialize}; use std::time::Duration; @@ -586,6 +592,61 @@ mod test { Ok(()) } + #[meilisearch_test] + async fn test_get_tasks_no_params() -> Result<(), Error> { + let mock_server_url = &mockito::server_url(); + let client = Client::new(mock_server_url, "masterKey"); + let path = "/tasks"; + + let mock_res = mock("GET", path).with_status(200).create(); + let _ = client.get_tasks().execute().await; + mock_res.assert(); + + // let _ = mockRes.req.await; + // mockRes.m.assert(); + // assert_eq!(tasks,); + // assert!(matches!(tasks, TasksResults { results.. } )); + Ok(()) + } + + #[meilisearch_test] + async fn test_get_tasks_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 mock_res = mock("GET", path).with_status(200).create(); + let _ = client + .get_tasks() + .with_index_uid(&["movies", "test"]) + .with_status(&["equeued"]) + .with_type(&["documentDeletion"]) + .execute() + .await; + mock_res.assert(); + Ok(()) + } + + #[meilisearch_test] + // TODO: Will un ignore when pagination is added in TaskResults + #[ignore] + async fn test_get_tasks_with_params_2(client: Client, index: Index) -> Result<(), Error> { + let tasks = client + .get_tasks() + .with_index_uid(&[index.uid.as_str()]) + .execute() + .await + .unwrap(); + + // let _ = mockRes.req.await; + // mockRes.m.assert(); + // assert_eq!(tasks,); + // assert!(matches!(tasks, TasksResults { results.. } )); + dbg!(&tasks); + assert_eq!(tasks.results.len(), 1); + Ok(()) + } + #[meilisearch_test] // TODO: failing because settings routes now uses PUT instead of POST as http method async fn test_failing_task(client: Client, movies: Index) -> Result<(), Error> { From d37be56d1eb4527804676cb0000b59ec1025a5c1 Mon Sep 17 00:00:00 2001 From: Charlotte Vermandel Date: Wed, 3 Aug 2022 14:24:00 +0200 Subject: [PATCH 08/44] Update code samples --- .code-samples.meilisearch.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.code-samples.meilisearch.yaml b/.code-samples.meilisearch.yaml index f66ca46e..eb7673ab 100644 --- a/.code-samples.meilisearch.yaml +++ b/.code-samples.meilisearch.yaml @@ -330,7 +330,7 @@ settings_guide_stop_words_1: |- "an" ]); - let task = client.index("movies").set_settings(&settings).await.unwrap(); + let task: TaskInfo = client.index("movies").set_settings(&settings).await.unwrap(); settings_guide_filterable_attributes_1: |- let settings = Settings::new() .with_filterable_attributes([ @@ -352,7 +352,7 @@ settings_guide_ranking_rules_1: |- "rank:desc", ]); - let task = client.index("movies").set_settings(&settings).await.unwrap(); + let task: TaskInfo = client.index("movies").set_settings(&settings).await.unwrap(); settings_guide_distinct_1: |- let settings = Settings::new() .with_distinct_attribute("product_id"); From 61be5a55ccb43c6b2685dcdb12b47aed636f0d3f Mon Sep 17 00:00:00 2001 From: Charlotte Vermandel Date: Wed, 3 Aug 2022 14:24:13 +0200 Subject: [PATCH 09/44] Remove out of context comment --- src/client.rs | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/src/client.rs b/src/client.rs index be571924..24d3a07d 100644 --- a/src/client.rs +++ b/src/client.rs @@ -433,18 +433,6 @@ impl Client { /// let mut key = KeyBuilder::new("create_key"); /// key.with_index("*").with_action(Action::DocumentsAdd); /// let key = client.create_key(key).await.unwrap(); - /// # // Method 2 - /// let key = client.create_key("create_key") - /// .with_index("*") - /// .with_action(Action::DocumentsAdd) - /// .execute() - /// .await.unwrap(); - /// # // Method 3 - /// let key = KeyBuilder::new("My little lovely test key") - /// .create(&client).await.unwrap(); - /// - /// - /// /// assert_eq!(key.description, "create_key"); /// # client.delete_key(key).await.unwrap(); /// # }); From c968df345faa06886938fe0f4bd5736b102ff38f Mon Sep 17 00:00:00 2001 From: Charlotte Vermandel Date: Wed, 3 Aug 2022 15:40:36 +0200 Subject: [PATCH 10/44] Fix tests --- src/task_info.rs | 42 +++++------------------------------------- src/tasks.rs | 12 ++---------- 2 files changed, 7 insertions(+), 47 deletions(-) diff --git a/src/task_info.rs b/src/task_info.rs index 67b49a40..620c9429 100644 --- a/src/task_info.rs +++ b/src/task_info.rs @@ -131,7 +131,7 @@ mod test { #[meilisearch_test] async fn test_wait_for_task_with_args(client: Client, movies: Index) -> Result<(), Error> { - let task = movies + let task_info = movies .add_documents( &[ Document { @@ -147,6 +147,10 @@ mod test { ], None, ) + .await?; + + let task = client + .get_task(task_info) .await? .wait_for_completion( &client, @@ -159,42 +163,6 @@ mod test { Ok(()) } - #[meilisearch_test] - // TODO: could be a flacky test if task is to fast - async fn test_wait_for_task_time_out(client: Client, movies: Index) -> Result<(), Error> { - let task_info = movies - .add_documents( - &[ - Document { - id: 0, - kind: "title".into(), - value: "The Social Network".to_string(), - }, - Document { - id: 1, - kind: "title".into(), - value: "Harry Potter and the Sorcerer's Stone".to_string(), - }, - ], - None, - ) - .await?; - - let task = client.wait_for_task(task_info, None, None).await?; - - let error = client - .wait_for_task( - task, - Some(Duration::from_millis(1)), - Some(Duration::from_nanos(1)), - ) - .await - .unwrap_err(); - - assert!(matches!(error, Error::Timeout)); - Ok(()) - } - #[meilisearch_test] // TODO: failing because settings routes now uses PUT instead of POST as http method async fn test_failing_task(client: Client, movies: Index) -> Result<(), Error> { diff --git a/src/tasks.rs b/src/tasks.rs index ae0f0490..eaba6789 100644 --- a/src/tasks.rs +++ b/src/tasks.rs @@ -1,4 +1,4 @@ -use serde::{de::DeserializeOwned, Deserialize, Deserializer, Serialize}; +use serde::{Deserialize, Deserializer, Serialize}; use std::time::Duration; use time::OffsetDateTime; @@ -560,7 +560,7 @@ mod test { #[meilisearch_test] async fn test_wait_for_task_with_args(client: Client, movies: Index) -> Result<(), Error> { - let task_info = movies + let task = movies .add_documents( &[ Document { @@ -576,10 +576,6 @@ mod test { ], None, ) - .await?; - - let task = client - .get_task(task_info) .await? .wait_for_completion( &client, @@ -602,10 +598,6 @@ mod test { let _ = client.get_tasks().execute().await; mock_res.assert(); - // let _ = mockRes.req.await; - // mockRes.m.assert(); - // assert_eq!(tasks,); - // assert!(matches!(tasks, TasksResults { results.. } )); Ok(()) } From c21b18f7aeb9c6738d894faf6f5575a4ed881cd8 Mon Sep 17 00:00:00 2001 From: Charlotte Vermandel Date: Wed, 3 Aug 2022 16:24:41 +0200 Subject: [PATCH 11/44] Fix pagination tests --- src/client.rs | 2 +- src/tasks.rs | 17 +++++------------ 2 files changed, 6 insertions(+), 13 deletions(-) diff --git a/src/client.rs b/src/client.rs index 34b3773d..03e1e66b 100644 --- a/src/client.rs +++ b/src/client.rs @@ -624,7 +624,7 @@ impl Client { /// /// /// - /// let tasks = client.get_tasks(&["get_tasks"]).with_index_uid().await.unwrap(); + /// let tasks = client.get_tasks().with_index_uid(&["get_tasks"]).execute().await.unwrap(); /// # }); /// ``` pub fn get_tasks(&self) -> TasksQuery { diff --git a/src/tasks.rs b/src/tasks.rs index eaba6789..7fcecbf7 100644 --- a/src/tasks.rs +++ b/src/tasks.rs @@ -34,8 +34,8 @@ pub enum TaskType { pub struct TasksResults { pub results: Vec, pub limit: u32, - pub from: u32, - pub next: u32, + pub from: Option, + pub next: Option, } #[derive(Debug, Clone, Deserialize)] @@ -620,22 +620,15 @@ mod test { } #[meilisearch_test] - // TODO: Will un ignore when pagination is added in TaskResults - #[ignore] - async fn test_get_tasks_with_params_2(client: Client, index: Index) -> Result<(), Error> { + async fn test_get_tasks_with_none_existant_index_uid(client: Client) -> Result<(), Error> { let tasks = client .get_tasks() - .with_index_uid(&[index.uid.as_str()]) + .with_index_uid(&["no_name"]) .execute() .await .unwrap(); - // let _ = mockRes.req.await; - // mockRes.m.assert(); - // assert_eq!(tasks,); - // assert!(matches!(tasks, TasksResults { results.. } )); - dbg!(&tasks); - assert_eq!(tasks.results.len(), 1); + assert_eq!(tasks.results.len(), 0); Ok(()) } From 012f9393ab146c9a4dc8d5a1fe0518a22b7035ac Mon Sep 17 00:00:00 2001 From: Charlotte Vermandel Date: Wed, 3 Aug 2022 16:32:58 +0200 Subject: [PATCH 12/44] Update HTTP methods for v0.28.0 --- src/indexes.rs | 2 +- src/settings.rs | 18 +++++++++--------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/indexes.rs b/src/indexes.rs index f681ea52..1e1ead29 100644 --- a/src/indexes.rs +++ b/src/indexes.rs @@ -97,7 +97,7 @@ impl Index { request::( &format!("{}/indexes/{}", self.client.host, self.uid), &self.client.api_key, - Method::Put(json!({ "primaryKey": primary_key.as_ref() })), + Method::Patch(json!({ "primaryKey": primary_key.as_ref() })), 200, ) .await?; diff --git a/src/settings.rs b/src/settings.rs index ac425635..e2f33da9 100644 --- a/src/settings.rs +++ b/src/settings.rs @@ -482,7 +482,7 @@ impl Index { request::<&Settings, TaskInfo>( &format!("{}/indexes/{}/settings", self.client.host, self.uid), &self.client.api_key, - Method::Post(settings), + Method::Patch(settings), 202, ) .await @@ -522,7 +522,7 @@ impl Index { self.client.host, self.uid ), &self.client.api_key, - Method::Post(synonyms), + Method::Put(synonyms), 202, ) .await @@ -558,7 +558,7 @@ impl Index { self.client.host, self.uid ), &self.client.api_key, - Method::Post( + Method::Put( stop_words .into_iter() .map(|v| v.as_ref().to_string()) @@ -608,7 +608,7 @@ impl Index { self.client.host, self.uid ), &self.client.api_key, - Method::Post( + Method::Put( ranking_rules .into_iter() .map(|v| v.as_ref().to_string()) @@ -649,7 +649,7 @@ impl Index { self.client.host, self.uid ), &self.client.api_key, - Method::Post( + Method::Put( filterable_attributes .into_iter() .map(|v| v.as_ref().to_string()) @@ -690,7 +690,7 @@ impl Index { self.client.host, self.uid ), &self.client.api_key, - Method::Post( + Method::Put( sortable_attributes .into_iter() .map(|v| v.as_ref().to_string()) @@ -730,7 +730,7 @@ impl Index { self.client.host, self.uid ), &self.client.api_key, - Method::Post(distinct_attribute.as_ref().to_string()), + Method::Put(distinct_attribute.as_ref().to_string()), 202, ) .await @@ -765,7 +765,7 @@ impl Index { self.client.host, self.uid ), &self.client.api_key, - Method::Post( + Method::Put( searchable_attributes .into_iter() .map(|v| v.as_ref().to_string()) @@ -805,7 +805,7 @@ impl Index { self.client.host, self.uid ), &self.client.api_key, - Method::Post( + Method::Put( displayed_attributes .into_iter() .map(|v| v.as_ref().to_string()) From 0cb9e93f839b5b4aac0b9330fd6f1daee2577b96 Mon Sep 17 00:00:00 2001 From: Charlotte Vermandel Date: Wed, 3 Aug 2022 16:39:58 +0200 Subject: [PATCH 13/44] Fix clippy --- src/indexes.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/indexes.rs b/src/indexes.rs index f681ea52..52e1d103 100644 --- a/src/indexes.rs +++ b/src/indexes.rs @@ -769,13 +769,13 @@ impl Index { /// # }); /// ``` pub async fn get_tasks(&self) -> Result { - Ok(request::<(), TasksResults>( + request::<(), TasksResults>( &format!("{}/tasks", self.client.host), &self.client.api_key, Method::Get(()), 200, ) - .await?) + .await } /// Get stats of an index. From f86bff4cf37317aed4eb73981bd64ae932c449b0 Mon Sep 17 00:00:00 2001 From: Charlotte Vermandel Date: Wed, 3 Aug 2022 16:41:45 +0200 Subject: [PATCH 14/44] Remove comment of task tests since the tests are now sucesful --- src/task_info.rs | 1 - src/tasks.rs | 1 - 2 files changed, 2 deletions(-) diff --git a/src/task_info.rs b/src/task_info.rs index 620c9429..cb970c7d 100644 --- a/src/task_info.rs +++ b/src/task_info.rs @@ -164,7 +164,6 @@ mod test { } #[meilisearch_test] - // TODO: failing because settings routes now uses PUT instead of POST as http method async fn test_failing_task(client: Client, movies: Index) -> Result<(), Error> { let task_info = movies.set_ranking_rules(["wrong_ranking_rule"]).await?; let task = client.wait_for_task(task_info, None, None).await?; diff --git a/src/tasks.rs b/src/tasks.rs index 7fcecbf7..df5b6865 100644 --- a/src/tasks.rs +++ b/src/tasks.rs @@ -633,7 +633,6 @@ mod test { } #[meilisearch_test] - // TODO: failing because settings routes now uses PUT instead of POST as http method async fn test_failing_task(client: Client, movies: Index) -> Result<(), Error> { let task_info = movies.set_ranking_rules(["wrong_ranking_rule"]).await?; From 734fd1351f3d021d4ff59dc7e1d431b48c48131a Mon Sep 17 00:00:00 2001 From: Charlotte Vermandel Date: Wed, 3 Aug 2022 16:53:50 +0200 Subject: [PATCH 15/44] Fix doc tests --- src/indexes.rs | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/src/indexes.rs b/src/indexes.rs index 52e1d103..2d07bb31 100644 --- a/src/indexes.rs +++ b/src/indexes.rs @@ -729,7 +729,7 @@ impl Index { /// Task::Succeeded { content } => content.uid, /// }; /// - /// assert_eq!(task.get_uid(), from_index); + /// assert_eq!(task.get_task_uid(), from_index); /// # movies.delete().await.unwrap().wait_for_completion(&client, None, None).await.unwrap(); /// # }); /// ``` @@ -758,13 +758,9 @@ impl Index { /// # let client = Client::new(MEILISEARCH_HOST, MEILISEARCH_API_KEY); /// # let index = client.create_index("get_tasks", None).await.unwrap().wait_for_completion(&client, None, None).await.unwrap().try_make_index(&client).unwrap(); /// - /// let status = index.get_tasks().await.unwrap(); - /// assert!(status.results.len() == 1); // the index was created + /// let tasks = index.get_tasks().await.unwrap(); /// - /// index.set_ranking_rules(["wrong_ranking_rule"]).await.unwrap(); - /// - /// let status = index.get_tasks().await.unwrap(); - /// assert!(status.results.len() == 2); + /// assert!(tasks.results.len() > 0); /// # index.delete().await.unwrap().wait_for_completion(&client, None, None).await.unwrap(); /// # }); /// ``` From 11bfb7e3e7c3517fce4de2b53183f4bacb18058c Mon Sep 17 00:00:00 2001 From: Charlotte Vermandel Date: Thu, 4 Aug 2022 14:19:16 +0200 Subject: [PATCH 16/44] Update keys for v0.28.0 --- src/client.rs | 20 +++--- src/key.rs | 176 +++++++++++++++++--------------------------------- 2 files changed, 66 insertions(+), 130 deletions(-) diff --git a/src/client.rs b/src/client.rs index 03e1e66b..e362f217 100644 --- a/src/client.rs +++ b/src/client.rs @@ -1,7 +1,7 @@ use crate::{ errors::*, indexes::*, - key::{Key, KeyBuilder}, + key::{Key, KeyBuilder, KeysQuery, KeysResults}, request::*, task_info::TaskInfo, tasks::*, @@ -309,6 +309,9 @@ impl Client { } } + pub fn get_keys(&self) -> KeysQuery { + KeysQuery::new(self) + } /// Get the API [Key]s from Meilisearch. /// See the [meilisearch documentation](https://docs.meilisearch.com/reference/api/keys.html#get-all-keys). /// @@ -328,23 +331,16 @@ impl Client { /// assert!(keys.len() >= 2); /// # }); /// ``` - pub async fn get_keys(&self) -> Result, Error> { - #[derive(Deserialize)] - #[serde(rename_all = "camelCase")] - pub struct Keys { - #[serde(rename = "results")] - pub inner: Vec, - } - - let keys = request::<(), Keys>( + pub async fn execute_get_keys(&self, keys_query: &KeysQuery<'_>) -> Result { + let keys = request::<&KeysQuery, KeysResults>( &format!("{}/keys", self.host), &self.api_key, - Method::Get(()), + Method::Get(keys_query), 200, ) .await?; - Ok(keys.inner) + Ok(keys) } /// Get one API [Key] from Meilisearch. diff --git a/src/key.rs b/src/key.rs index 56376bb5..e29199ed 100644 --- a/src/key.rs +++ b/src/key.rs @@ -6,7 +6,7 @@ use crate::{client::Client, errors::Error}; /// Represent a [meilisearch key](https://docs.meilisearch.com/reference/api/keys.html#returned-fields) /// You can get a [Key] from the [Client::get_key] method. /// Or you can create a [Key] with the [KeyBuilder::create] or [Client::create_key] methods. -#[derive(Debug, Serialize, Deserialize)] +#[derive(Debug, Serialize, Deserialize, Clone)] #[serde(rename_all = "camelCase")] pub struct Key { #[serde(skip_serializing_if = "Vec::is_empty")] @@ -53,122 +53,6 @@ impl Key { self } - /// Add a set of actions the [Key] will be able to execute. - /// - /// # Example - /// - /// ``` - /// # use meilisearch_sdk::{key::KeyBuilder, key::Action, client::Client}; - /// # - /// # let MEILISEARCH_HOST = option_env!("MEILISEARCH_HOST").unwrap_or("http://localhost:7700"); - /// # let MEILISEARCH_API_KEY = option_env!("MEILISEARCH_API_KEY").unwrap_or("masterKey"); - /// # - /// # futures::executor::block_on(async move { - /// # let client = Client::new(MEILISEARCH_HOST, MEILISEARCH_API_KEY); - /// - /// let mut key = KeyBuilder::new("My little lovely test key") - /// .with_action(Action::DocumentsAdd) - /// .with_index("*") - /// .create(&client).await.unwrap(); - /// - /// key.with_actions([Action::DocumentsGet, Action::DocumentsDelete]); - /// # client.delete_key(key).await.unwrap(); - /// # }); - /// ``` - pub fn with_actions(&mut self, actions: impl IntoIterator) -> &mut Self { - self.actions.extend(actions); - self - } - - /// Add one action the [Key] will be able to execute. - /// - /// # Example - /// - /// ``` - /// # use meilisearch_sdk::{key::KeyBuilder, key::Action, client::Client}; - /// # - /// # let MEILISEARCH_HOST = option_env!("MEILISEARCH_HOST").unwrap_or("http://localhost:7700"); - /// # let MEILISEARCH_API_KEY = option_env!("MEILISEARCH_API_KEY").unwrap_or("masterKey"); - /// # - /// # futures::executor::block_on(async move { - /// # let client = Client::new(MEILISEARCH_HOST, MEILISEARCH_API_KEY); - /// - /// let mut key = KeyBuilder::new("My little lovely test key") - /// .with_action(Action::DocumentsAdd) - /// .with_index("*") - /// .create(&client).await.unwrap(); - /// - /// key.with_action(Action::DocumentsGet); - /// # client.delete_key(key).await.unwrap(); - /// # }); - /// ``` - pub fn with_action(&mut self, action: Action) -> &mut Self { - self.actions.push(action); - self - } - - /// Update the expiration date of the [Key]. - /// - /// # Example - /// - /// ``` - /// # use meilisearch_sdk::{key::KeyBuilder, key::Action, client::Client}; - /// use time::{OffsetDateTime, Duration}; - /// # - /// # let MEILISEARCH_HOST = option_env!("MEILISEARCH_HOST").unwrap_or("http://localhost:7700"); - /// # let MEILISEARCH_API_KEY = option_env!("MEILISEARCH_API_KEY").unwrap_or("masterKey"); - /// # - /// # futures::executor::block_on(async move { - /// # let client = Client::new(MEILISEARCH_HOST, MEILISEARCH_API_KEY); - /// - /// let mut key = KeyBuilder::new("My little lovely test key") - /// .with_action(Action::DocumentsAdd) - /// .with_index("*") - /// .create(&client).await.unwrap(); - /// - /// // update the epiry date of the key to two weeks from now - /// key.with_expires_at(OffsetDateTime::now_utc() + Duration::WEEK * 2); - /// # client.delete_key(key).await.unwrap(); - /// # }); - /// ``` - pub fn with_expires_at(&mut self, expires_at: OffsetDateTime) -> &mut Self { - self.expires_at = Some(expires_at); - self - } - - /// Update the indexes the [Key] can manage. - /// - /// # Example - /// - /// ``` - /// # use meilisearch_sdk::{key::KeyBuilder, key::Action, client::Client}; - /// # - /// # let MEILISEARCH_HOST = option_env!("MEILISEARCH_HOST").unwrap_or("http://localhost:7700"); - /// # let MEILISEARCH_API_KEY = option_env!("MEILISEARCH_API_KEY").unwrap_or("masterKey"); - /// # - /// # futures::executor::block_on(async move { - /// # let client = Client::new(MEILISEARCH_HOST, MEILISEARCH_API_KEY); - /// - /// let mut key = KeyBuilder::new("My little lovely test key") - /// .with_action(Action::DocumentsAdd) - /// .with_index("*") - /// .create(&client).await.unwrap(); - /// - /// key.with_indexes(vec!["test", "movies"]); - /// # client.delete_key(key).await.unwrap(); - /// # }); - /// ``` - pub fn with_indexes( - &mut self, - indexes: impl IntoIterator>, - ) -> &mut Self { - self.indexes = indexes - .into_iter() - .map(|index| index.as_ref().to_string()) - .collect(); - self - } - /// Add one index the [Key] can manage. /// /// # Example @@ -238,6 +122,52 @@ impl AsRef for Key { } } +#[derive(Debug, Serialize, Clone)] +#[serde(rename_all = "camelCase")] +pub struct KeysQuery<'a> { + #[serde(skip_serializing)] + pub client: &'a Client, + /// The number of documents to skip. + /// If the value of the parameter `offset` is `n`, the `n` first documents (ordered by relevance) will not be returned. + /// This is helpful for pagination. + /// + /// Example: If you want to skip the first document, set offset to `1`. + #[serde(skip_serializing_if = "Option::is_none")] + pub offset: Option, + /// The maximum number of documents returned. + /// If the value of the parameter `limit` is `n`, there will never be more than `n` documents in the response. + /// This is helpful for pagination. + /// + /// Example: If you don't want to get more than two documents, set limit to `2`. + /// Default: `20` + #[serde(skip_serializing_if = "Option::is_none")] + pub limit: Option, +} + +impl<'a> KeysQuery<'a> { + pub fn new(client: &'a Client) -> KeysQuery<'a> { + KeysQuery { + client, + offset: None, + limit: None, + } + } + + pub fn with_offset<'b>(&'b mut self, offset: usize) -> &'b mut KeysQuery<'a> { + self.offset = Some(offset); + self + } + pub fn with_limit<'b>(&'b mut self, limit: usize) -> &'b mut KeysQuery<'a> { + self.limit = Some(limit); + self + } + + /// Execute the query and fetch the results. + pub async fn execute(&'a self) -> Result { + self.client.execute_get_keys(self).await + } +} + /// The [KeyBuilder] is an analog to the [Key] type but without all the fields managed by Meilisearch. /// It's used to create [Key]. /// @@ -367,6 +297,8 @@ impl KeyBuilder { self } + // TODO: with_description + /// Create a [Key] from the builder. /// /// # Example @@ -386,9 +318,10 @@ impl KeyBuilder { /// # client.delete_key(key).await.unwrap(); /// # }); /// ``` - pub async fn create(&self, client: &Client) -> Result { + pub async fn execute(&self, client: &Client) -> Result { client.create_key(self).await } + // TODO: create update } impl AsRef for KeyBuilder { @@ -448,3 +381,10 @@ pub enum Action { #[serde(rename = "version")] Version, } + +#[derive(Debug, Clone, Deserialize)] +pub struct KeysResults { + pub results: Vec, + pub limit: u32, + pub offset: u32, +} From 6b70f5ab22226a5e64402cfeab96be32892fd1ec Mon Sep 17 00:00:00 2001 From: Charlotte Vermandel Date: Thu, 4 Aug 2022 17:11:17 +0200 Subject: [PATCH 17/44] Fix get tasks inside index structure --- src/client.rs | 7 ++++--- src/indexes.rs | 16 +++++++--------- src/tasks.rs | 35 ++++++++++++++++++++++------------- 3 files changed, 33 insertions(+), 25 deletions(-) diff --git a/src/client.rs b/src/client.rs index 03e1e66b..9921fb43 100644 --- a/src/client.rs +++ b/src/client.rs @@ -621,10 +621,11 @@ impl Client { /// # futures::executor::block_on(async move { /// # let client = client::Client::new(MEILISEARCH_HOST, MEILISEARCH_API_KEY); /// + /// let tasks = client.get_tasks().with_index_uid(["get_tasks"]).execute().await.unwrap(); /// - /// - /// - /// let tasks = client.get_tasks().with_index_uid(&["get_tasks"]).execute().await.unwrap(); + /// assert!(tasks.results.len() > 0); + /// # index.delete().await.unwrap().wait_for_completion(&client, None, None).await.unwrap(); + /// # }); /// # }); /// ``` pub fn get_tasks(&self) -> TasksQuery { diff --git a/src/indexes.rs b/src/indexes.rs index 2d07bb31..3a7310c1 100644 --- a/src/indexes.rs +++ b/src/indexes.rs @@ -758,20 +758,18 @@ impl Index { /// # let client = Client::new(MEILISEARCH_HOST, MEILISEARCH_API_KEY); /// # let index = client.create_index("get_tasks", None).await.unwrap().wait_for_completion(&client, None, None).await.unwrap().try_make_index(&client).unwrap(); /// - /// let tasks = index.get_tasks().await.unwrap(); + /// let tasks = index.get_tasks().execute().await.unwrap(); /// /// assert!(tasks.results.len() > 0); /// # index.delete().await.unwrap().wait_for_completion(&client, None, None).await.unwrap(); /// # }); /// ``` - pub async fn get_tasks(&self) -> Result { - request::<(), TasksResults>( - &format!("{}/tasks", self.client.host), - &self.client.api_key, - Method::Get(()), - 200, - ) - .await + pub fn get_tasks(&self) -> TasksQuery { + let mut task = self.client.get_tasks(); + + task.with_index_uid([self.uid.as_str()]); + + task } /// Get stats of an index. diff --git a/src/tasks.rs b/src/tasks.rs index 7fcecbf7..283f94c0 100644 --- a/src/tasks.rs +++ b/src/tasks.rs @@ -398,13 +398,13 @@ 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<&'a [&'a str]>, + pub index_uid: Option>, // Statuses array to only retrieve the tasks with these statuses. #[serde(skip_serializing_if = "Option::is_none")] - pub status: Option<&'a [&'a str]>, + pub status: Option>, // Types array to only retrieve the tasks with these [TaskType]. #[serde(skip_serializing_if = "Option::is_none")] - pub r#type: Option<&'a [&'a str]>, + pub r#type: Option>, } #[allow(missing_docs)] @@ -417,16 +417,25 @@ impl<'a> TasksQuery<'a> { r#type: None, } } - pub fn with_index_uid<'b>(&'b mut self, index_uid: &'a [&'a str]) -> &'b mut TasksQuery<'a> { - self.index_uid = Some(index_uid); + pub fn with_index_uid<'b>( + &'b mut self, + index_uid: impl IntoIterator, + ) -> &'b mut TasksQuery<'a> { + self.index_uid = Some(index_uid.into_iter().collect()); self } - pub fn with_status<'b>(&'b mut self, status: &'a [&'a str]) -> &'b mut TasksQuery<'a> { - self.status = Some(status); + pub fn with_status<'b>( + &'b mut self, + status: impl IntoIterator, + ) -> &'b mut TasksQuery<'a> { + self.status = Some(status.into_iter().collect()); self } - pub fn with_type<'b>(&'b mut self, r#type: &'a [&'a str]) -> &'b mut TasksQuery<'a> { - self.r#type = Some(r#type); + pub fn with_type<'b>( + &'b mut self, + r#type: impl IntoIterator, + ) -> &'b mut TasksQuery<'a> { + self.r#type = Some(r#type.into_iter().collect()); self } pub async fn execute(&'a self) -> Result { @@ -610,9 +619,9 @@ mod test { let mock_res = mock("GET", path).with_status(200).create(); let _ = client .get_tasks() - .with_index_uid(&["movies", "test"]) - .with_status(&["equeued"]) - .with_type(&["documentDeletion"]) + .with_index_uid(["movies", "test"]) + .with_status(["equeued"]) + .with_type(["documentDeletion"]) .execute() .await; mock_res.assert(); @@ -623,7 +632,7 @@ mod test { async fn test_get_tasks_with_none_existant_index_uid(client: Client) -> Result<(), Error> { let tasks = client .get_tasks() - .with_index_uid(&["no_name"]) + .with_index_uid(["no_name"]) .execute() .await .unwrap(); From 604e08de21e0fe13932589fd05f398bc40e82382 Mon Sep 17 00:00:00 2001 From: Charlotte Vermandel Date: Mon, 8 Aug 2022 16:29:16 +0200 Subject: [PATCH 18/44] Make description and name optional in keys --- src/client.rs | 85 ++++++++++++++++++--------------------------------- src/key.rs | 21 +++++++------ src/search.rs | 4 +-- 3 files changed, 42 insertions(+), 68 deletions(-) diff --git a/src/client.rs b/src/client.rs index e362f217..564064bc 100644 --- a/src/client.rs +++ b/src/client.rs @@ -331,6 +331,7 @@ impl Client { /// assert!(keys.len() >= 2); /// # }); /// ``` + /// TODO: hidden pub async fn execute_get_keys(&self, keys_query: &KeysQuery<'_>) -> Result { let keys = request::<&KeysQuery, KeysResults>( &format!("{}/keys", self.host), @@ -434,6 +435,10 @@ impl Client { /// # }); /// ``` pub async fn create_key(&self, key: impl AsRef) -> Result { + KeyBuilder::new(self) + } + + pub async fn execute_create_key() -> Blabla { request::<&KeyBuilder, Key>( &format!("{}/keys", self.host), &self.api_key, @@ -620,7 +625,7 @@ impl Client { /// /// /// - /// let tasks = client.get_tasks().with_index_uid(&["get_tasks"]).execute().await.unwrap(); + /// let tasks: Task = client.get_tasks().with_index_uid(&["get_tasks"]).execute().await.unwrap(); /// # }); /// ``` pub fn get_tasks(&self) -> TasksQuery { @@ -781,24 +786,23 @@ mod tests { #[meilisearch_test] async fn test_get_keys(client: Client) { - let keys = client.get_keys().await.unwrap(); - assert!(keys.len() >= 2); - assert!(keys.iter().any( - |k| k.description != "Default Search API Key (Use it to search from the frontend)" - )); - assert!(keys.iter().any( - |k| k.description != "Default Admin API Key (Use it for all other operations. Caution! Do not use it on a public frontend)" + let keys = client.get_keys().execute().await.unwrap(); + assert!(keys.results.len() >= 2); + assert!(keys.results.iter().any(|k| k.description + != Some("Default Search API Key (Use it to search from the frontend)".to_string()))); + assert!(keys.results.iter().any( + |k| k.description != Some("Default Admin API Key (Use it for all other operations. Caution! Do not use it on a public frontend)".to_string()) )); } #[meilisearch_test] async fn test_delete_key(client: Client, description: String) { - let key = KeyBuilder::new(description); + let key = KeyBuilder::new(); let key = client.create_key(key).await.unwrap(); client.delete_key(&key).await.unwrap(); - let keys = client.get_keys().await.unwrap(); - assert!(keys.iter().all(|k| k.key != key.key)); + let keys = client.get_keys().execute().await.unwrap(); + assert!(keys.results.iter().all(|k| k.key != key.key)); } #[meilisearch_test] @@ -815,7 +819,7 @@ mod tests { )); // ==> executing the action without enough right - let key = KeyBuilder::new(description); + let key = KeyBuilder::new(); let key = client.create_key(key).await.unwrap(); let master_key = client.api_key.clone(); @@ -850,14 +854,14 @@ mod tests { #[meilisearch_test] async fn test_create_key(client: Client, description: String) { let expires_at = OffsetDateTime::now_utc() + time::Duration::HOUR; - let mut key = KeyBuilder::new(description.clone()); + let mut key = KeyBuilder::new(); key.with_action(Action::DocumentsAdd) .with_expires_at(expires_at.clone()) .with_index("*"); let key = client.create_key(key).await.unwrap(); assert_eq!(key.actions, vec![Action::DocumentsAdd]); - assert_eq!(key.description, description); + assert_eq!(&key.description, &Some(description)); // We can't compare the two timestamp directly because of some nanoseconds imprecision with the floats assert_eq!( key.expires_at.unwrap().unix_timestamp(), @@ -865,19 +869,6 @@ mod tests { ); assert_eq!(key.indexes, vec!["*".to_string()]); - let keys = client.get_keys().await.unwrap(); - - let remote_key = keys.iter().find(|k| k.key == key.key).unwrap(); - - assert_eq!(remote_key.actions, vec![Action::DocumentsAdd]); - assert_eq!(remote_key.description, description); - // We can't compare the two timestamp directly because of some nanoseconds imprecision with the floats - assert_eq!( - remote_key.expires_at.unwrap().unix_timestamp(), - expires_at.unix_timestamp() - ); - assert_eq!(remote_key.indexes, vec!["*".to_string()]); - client.delete_key(key).await.unwrap(); } @@ -885,7 +876,7 @@ mod tests { async fn test_error_create_key(mut client: Client, description: String) { // ==> Invalid index name /* TODO: uncomment once meilisearch fix this bug: https://github.com/meilisearch/meilisearch/issues/2158 - let mut key = KeyBuilder::new(&description); + let mut key = KeyBuilder::new(); key.with_index("invalid index # / \\name with spaces"); let error = client.create_key(key).await.unwrap_err(); @@ -900,14 +891,14 @@ mod tests { */ // ==> executing the action without enough right - let no_right_key = KeyBuilder::new(&description); + let no_right_key = KeyBuilder::new(); let no_right_key = client.create_key(no_right_key).await.unwrap(); // backup the master key for cleanup at the end of the test let master_client = client.clone(); client.api_key = Arc::new(no_right_key.key.clone()); - let key = KeyBuilder::new(&description); + let key = KeyBuilder::new(); let error = client.create_key(key).await.unwrap_err(); assert!(matches!( @@ -926,43 +917,25 @@ mod tests { #[meilisearch_test] async fn test_update_key(client: Client, description: String) { let expires_at = OffsetDateTime::now_utc() + time::Duration::HOUR; - let key = KeyBuilder::new(description.clone()); + let key = KeyBuilder::new(); let mut key = client.create_key(key).await.unwrap(); - key.actions = vec![Action::DocumentsAdd]; - key.expires_at = Some(expires_at); - key.indexes = vec!["*".to_string()]; + let description = "new description"; + let name = "new name"; + key.with_description(description); + key.with_name(name); let key = client.update_key(key).await.unwrap(); - assert_eq!(key.actions, vec![Action::DocumentsAdd]); - assert_eq!(key.description, description); - // We can't compare the two timestamp directly because of some nanoseconds imprecision with the floats - assert_eq!( - key.expires_at.unwrap().unix_timestamp(), - expires_at.unix_timestamp() - ); + assert_eq!(key.description, Some(description.to_string())); assert_eq!(key.indexes, vec!["*".to_string()]); - let keys = client.get_keys().await.unwrap(); - - let remote_key = keys.iter().find(|k| k.key == key.key).unwrap(); - - assert_eq!(remote_key.actions, vec![Action::DocumentsAdd]); - assert_eq!(remote_key.description, description); - // We can't compare the two timestamp directly because of some nanoseconds imprecision with the floats - assert_eq!( - remote_key.expires_at.unwrap().unix_timestamp(), - expires_at.unix_timestamp() - ); - assert_eq!(remote_key.indexes, vec!["*".to_string()]); - client.delete_key(key).await.unwrap(); } #[meilisearch_test] async fn test_error_update_key(mut client: Client, description: String) { - let key = KeyBuilder::new(description.clone()); + let key = KeyBuilder::new(); let key = client.create_key(key).await.unwrap(); // ==> Invalid index name @@ -981,7 +954,7 @@ mod tests { */ // ==> executing the action without enough right - let no_right_key = KeyBuilder::new(&description); + let no_right_key = KeyBuilder::new(); let no_right_key = client.create_key(no_right_key).await.unwrap(); // backup the master key for cleanup at the end of the test diff --git a/src/key.rs b/src/key.rs index e29199ed..55fdf41c 100644 --- a/src/key.rs +++ b/src/key.rs @@ -13,7 +13,8 @@ pub struct Key { pub actions: Vec, #[serde(skip_serializing, with = "time::serde::rfc3339")] pub created_at: OffsetDateTime, - pub description: String, + pub description: Option, + pub name: Option, #[serde(with = "time::serde::rfc3339::option")] pub expires_at: Option, #[serde(skip_serializing_if = "Vec::is_empty")] @@ -49,11 +50,11 @@ impl Key { /// # }); /// ``` pub fn with_description(&mut self, desc: impl AsRef) -> &mut Self { - self.description = desc.as_ref().to_string(); + self.description = Some(desc.as_ref().to_string()); self } - /// Add one index the [Key] can manage. + /// Update the name of the key. /// /// # Example /// @@ -71,12 +72,13 @@ impl Key { /// .with_index("*") /// .create(&client).await.unwrap(); /// - /// key.with_index("test"); + /// key.with_name("lovely key"); + /// # assert_eq!(key.name, "lovely key".to_string()); /// # client.delete_key(key).await.unwrap(); /// # }); /// ``` - pub fn with_index(&mut self, index: impl AsRef) -> &mut Self { - self.indexes.push(index.as_ref().to_string()); + pub fn with_name(&mut self, desc: impl AsRef) -> &mut Self { + self.name = Some(desc.as_ref().to_string()); self } @@ -195,7 +197,7 @@ impl<'a> KeysQuery<'a> { #[serde(rename_all = "camelCase")] pub struct KeyBuilder { pub actions: Vec, - pub description: String, + pub description: Option, #[serde(with = "time::serde::rfc3339::option")] pub expires_at: Option, pub indexes: Vec, @@ -210,10 +212,10 @@ impl KeyBuilder { /// # use meilisearch_sdk::{key::KeyBuilder}; /// let builder = KeyBuilder::new("My little lovely test key"); /// ``` - pub fn new(description: impl AsRef) -> KeyBuilder { + pub fn new() -> KeyBuilder { Self { actions: Vec::new(), - description: description.as_ref().to_string(), + description: None, expires_at: None, indexes: Vec::new(), } @@ -321,7 +323,6 @@ impl KeyBuilder { pub async fn execute(&self, client: &Client) -> Result { client.create_key(self).await } - // TODO: create update } impl AsRef for KeyBuilder { diff --git a/src/search.rs b/src/search.rs index fe2fbfca..52e4bc35 100644 --- a/src/search.rs +++ b/src/search.rs @@ -734,10 +734,10 @@ mod tests { setup_test_index(&client, &index).await?; let meilisearch_host = option_env!("MEILISEARCH_HOST").unwrap_or("http://localhost:7700"); - let key = KeyBuilder::new("key for generate_tenant_token test") + let key = KeyBuilder::new() .with_action(Action::All) .with_index("*") - .create(&client) + .execute(&client) .await .unwrap(); let allowed_client = Client::new(meilisearch_host, key.key); From 67637c255e7b8bb6928bd6ba1fb3124f8ce1c601 Mon Sep 17 00:00:00 2001 From: Charlotte Vermandel Date: Mon, 8 Aug 2022 17:53:08 +0200 Subject: [PATCH 19/44] Fix none doc tests with new get_tasks api --- src/client.rs | 16 ++++++---------- src/indexes.rs | 18 ++++++++++++++---- src/tasks.rs | 41 +++++++++++++++++++++++++++++++---------- 3 files changed, 51 insertions(+), 24 deletions(-) diff --git a/src/client.rs b/src/client.rs index 9921fb43..ffad3b10 100644 --- a/src/client.rs +++ b/src/client.rs @@ -621,21 +621,16 @@ impl Client { /// # futures::executor::block_on(async move { /// # let client = client::Client::new(MEILISEARCH_HOST, MEILISEARCH_API_KEY); /// - /// let tasks = client.get_tasks().with_index_uid(["get_tasks"]).execute().await.unwrap(); + /// let query = TasksQuery::new(); + /// query.with_index_uid(["get_tasks"]) + /// let tasks = client.get_tasks(&query).await.unwrap(); /// /// assert!(tasks.results.len() > 0); /// # index.delete().await.unwrap().wait_for_completion(&client, None, None).await.unwrap(); /// # }); /// # }); /// ``` - pub fn get_tasks(&self) -> TasksQuery { - TasksQuery::new(self) - } - - pub(crate) async fn execute_get_tasks( - &self, - tasks_query: &TasksQuery<'_>, - ) -> Result { + pub async fn get_tasks(&self, tasks_query: &TasksQuery<'_>) -> Result { let tasks = request::<&TasksQuery, TasksResults>( &format!("{}/tasks", self.host), &self.api_key, @@ -780,7 +775,8 @@ mod tests { #[meilisearch_test] async fn test_get_tasks(client: Client) { - let tasks = client.get_tasks().execute().await.unwrap(); + let query = TasksQuery::new(&client); + let tasks = client.get_tasks(&query).await.unwrap(); assert!(tasks.results.len() >= 2); } diff --git a/src/indexes.rs b/src/indexes.rs index 3a7310c1..1d317009 100644 --- a/src/indexes.rs +++ b/src/indexes.rs @@ -764,12 +764,22 @@ impl Index { /// # index.delete().await.unwrap().wait_for_completion(&client, None, None).await.unwrap(); /// # }); /// ``` - pub fn get_tasks(&self) -> TasksQuery { - let mut task = self.client.get_tasks(); + /// TODO: how to pass a tasks_query? + pub async fn get_tasks(&self) -> Result { + let mut query = TasksQuery::new(&self.client); - task.with_index_uid([self.uid.as_str()]); + query.with_index_uid([self.uid.as_str()]); - task + self.client.get_tasks(&query).await + + // pub async fn get_tasks( + // &self, + // mut tasks_query: &mut TasksQuery<'_>, + // ) -> Result { + // tasks_query.with_index_uid([self.uid.as_str()]); + + // self.client.get_tasks(&tasks_query).await + // } } /// Get stats of an index. diff --git a/src/tasks.rs b/src/tasks.rs index 283f94c0..cc210c1b 100644 --- a/src/tasks.rs +++ b/src/tasks.rs @@ -439,7 +439,7 @@ impl<'a> TasksQuery<'a> { self } pub async fn execute(&'a self) -> Result { - self.client.execute_get_tasks(self).await + self.client.get_tasks(self).await } } @@ -604,7 +604,8 @@ mod test { let path = "/tasks"; let mock_res = mock("GET", path).with_status(200).create(); - let _ = client.get_tasks().execute().await; + let query = TasksQuery::new(&client); + let _ = client.get_tasks(&query).await; mock_res.assert(); Ok(()) @@ -617,25 +618,45 @@ mod test { let path = "/tasks?indexUid=movies,test&status=equeued&type=documentDeletion"; let mock_res = mock("GET", path).with_status(200).create(); - let _ = client - .get_tasks() + + let mut query = TasksQuery::new(&client); + query + .with_index_uid(["movies", "test"]) + .with_status(["equeued"]) + .with_type(["documentDeletion"]); + + let _ = client.get_tasks(&query).await; + + mock_res.assert(); + Ok(()) + } + + #[meilisearch_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 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"]) .execute() .await; + + // let _ = client.get_tasks(&query).await; mock_res.assert(); Ok(()) } #[meilisearch_test] async fn test_get_tasks_with_none_existant_index_uid(client: Client) -> Result<(), Error> { - let tasks = client - .get_tasks() - .with_index_uid(["no_name"]) - .execute() - .await - .unwrap(); + let mut query = TasksQuery::new(&client); + query.with_index_uid(["no_name"]); + let tasks = client.get_tasks(&query).await.unwrap(); assert_eq!(tasks.results.len(), 0); Ok(()) From c2dcd92525e6e926a054f3bbbdefd6b9b58b97a2 Mon Sep 17 00:00:00 2001 From: Charlotte Vermandel Date: Mon, 8 Aug 2022 18:35:33 +0200 Subject: [PATCH 20/44] Add from and limit in tasks params --- src/client.rs | 9 ++++----- src/tasks.rs | 24 ++++++++++++++++++++++-- 2 files changed, 26 insertions(+), 7 deletions(-) diff --git a/src/client.rs b/src/client.rs index ffad3b10..0ffc365c 100644 --- a/src/client.rs +++ b/src/client.rs @@ -4,7 +4,7 @@ use crate::{ key::{Key, KeyBuilder}, request::*, task_info::TaskInfo, - tasks::*, + tasks::{Task, TasksQuery, TasksResults}, utils::async_sleep, }; use serde::Deserialize; @@ -621,13 +621,12 @@ impl Client { /// # futures::executor::block_on(async move { /// # let client = client::Client::new(MEILISEARCH_HOST, MEILISEARCH_API_KEY); /// - /// let query = TasksQuery::new(); - /// query.with_index_uid(["get_tasks"]) + /// let mut query = tasks::TasksQuery::new(&client); + /// query.with_index_uid(["get_tasks"]); /// let tasks = client.get_tasks(&query).await.unwrap(); /// /// assert!(tasks.results.len() > 0); - /// # index.delete().await.unwrap().wait_for_completion(&client, None, None).await.unwrap(); - /// # }); + /// # client.index("get_tasks").delete().await.unwrap().wait_for_completion(&client, None, None).await.unwrap(); /// # }); /// ``` pub async fn get_tasks(&self, tasks_query: &TasksQuery<'_>) -> Result { diff --git a/src/tasks.rs b/src/tasks.rs index cc210c1b..231013ad 100644 --- a/src/tasks.rs +++ b/src/tasks.rs @@ -405,6 +405,12 @@ pub struct TasksQuery<'a> { // Types array to only retrieve the tasks with these [TaskType]. #[serde(skip_serializing_if = "Option::is_none")] pub r#type: Option>, + // Maximum number of tasks to return + #[serde(skip_serializing_if = "Option::is_none")] + pub limit: Option, + // The if og the first task uid that should be returned + #[serde(skip_serializing_if = "Option::is_none")] + pub from: Option, } #[allow(missing_docs)] @@ -415,6 +421,8 @@ impl<'a> TasksQuery<'a> { index_uid: None, status: None, r#type: None, + limit: None, + from: None, } } pub fn with_index_uid<'b>( @@ -438,6 +446,15 @@ impl<'a> TasksQuery<'a> { self.r#type = Some(r#type.into_iter().collect()); self } + pub fn with_limit<'b>(&'b mut self, limit: u32) -> &'b mut TasksQuery<'a> { + self.limit = Some(limit); + self + } + pub fn with_from<'b>(&'b mut self, from: u32) -> &'b mut TasksQuery<'a> { + self.from = Some(from); + self + } + pub async fn execute(&'a self) -> Result { self.client.get_tasks(self).await } @@ -615,7 +632,8 @@ mod test { async fn test_get_tasks_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?indexUid=movies,test&status=equeued&type=documentDeletion&limit=0&from=1"; let mock_res = mock("GET", path).with_status(200).create(); @@ -623,7 +641,9 @@ mod test { query .with_index_uid(["movies", "test"]) .with_status(["equeued"]) - .with_type(["documentDeletion"]); + .with_type(["documentDeletion"]) + .with_from(1) + .with_limit(0); let _ = client.get_tasks(&query).await; From efff8136387f216a734d1112ca3f22883aa036db Mon Sep 17 00:00:00 2001 From: Charlotte Vermandel Date: Mon, 8 Aug 2022 18:39:53 +0200 Subject: [PATCH 21/44] Add warning on failing test --- src/tasks.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tasks.rs b/src/tasks.rs index 231013ad..0623ce05 100644 --- a/src/tasks.rs +++ b/src/tasks.rs @@ -270,7 +270,7 @@ impl Task { /// # let task = client.create_index("unwrap_failure", None).await.unwrap(); /// # let index = client.wait_for_task(task, None, None).await.unwrap().try_make_index(&client).unwrap(); /// - /// + /// // TODO: fails until http method are implemented /// let task = index.set_ranking_rules(["wrong_ranking_rule"]) /// .await /// .unwrap() From c1796a393a232b7a038cddd7e9879dc9ba4529ff Mon Sep 17 00:00:00 2001 From: Charlotte Vermandel Date: Tue, 9 Aug 2022 12:56:00 +0200 Subject: [PATCH 22/44] Update keys design --- src/client.rs | 21 +++++++++++++++------ src/key.rs | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+), 6 deletions(-) diff --git a/src/client.rs b/src/client.rs index d57a2ce6..027d3dba 100644 --- a/src/client.rs +++ b/src/client.rs @@ -309,9 +309,6 @@ impl Client { } } - pub fn get_keys(&self) -> KeysQuery { - KeysQuery::new(self) - } /// Get the API [Key]s from Meilisearch. /// See the [meilisearch documentation](https://docs.meilisearch.com/reference/api/keys.html#get-all-keys). /// @@ -332,7 +329,7 @@ impl Client { /// # }); /// ``` /// TODO: hidden - pub async fn execute_get_keys(&self, keys_query: &KeysQuery<'_>) -> Result { + pub async fn get_keys_with(&self, keys_query: &KeysQuery<'_>) -> Result { let keys = request::<&KeysQuery, KeysResults>( &format!("{}/keys", self.host), &self.api_key, @@ -344,6 +341,18 @@ impl Client { Ok(keys) } + pub async fn get_keys(&self) -> Result { + let keys = request::<(), KeysResults>( + &format!("{}/keys", self.host), + &self.api_key, + Method::Get(()), + 200, + ) + .await?; + + Ok(keys) + } + /// Get one API [Key] from Meilisearch. /// See the [meilisearch documentation](https://docs.meilisearch.com/reference/api/keys.html#get-one-key). /// @@ -475,9 +484,9 @@ impl Client { /// ``` pub async fn update_key(&self, key: impl AsRef) -> Result { request::<&Key, Key>( - &format!("{}/keys/{}", self.host, key.as_ref().key), + &format!("{}/keys/{}", self.host, key.identifier), &self.api_key, - Method::Patch(key.as_ref()), + Method::Patch(key.as_ref()), // name and description 200, ) .await diff --git a/src/key.rs b/src/key.rs index 55fdf41c..94ae80c7 100644 --- a/src/key.rs +++ b/src/key.rs @@ -21,6 +21,8 @@ pub struct Key { pub indexes: Vec, #[serde(skip_serializing)] pub key: String, + #[serde(skip_serializing)] + pub uid: String, #[serde(skip_serializing, with = "time::serde::rfc3339")] pub updated_at: OffsetDateTime, } @@ -108,6 +110,38 @@ impl Key { /// # }); /// ``` pub async fn update(&self, client: &Client) -> Result { + // only send description and name + let updated = KeyUpdater::new(self); + client.update_key(self).await + } + + // client.delete_key("1") + pub async fn delete(&self, client: &Client) -> Result { + client.delete_key(self).await + } +} + +#[derive(Debug, Serialize, Deserialize, Clone)] +#[serde(rename_all = "camelCase")] +pub struct KeyUpdater { + pub description: Option, + pub name: Option, + #[serde(skip_serializing)] + pub identifier: String, +} + +impl KeyUpdater { + pub fn new(key: &Key) -> KeyUpdater { + KeyUpdater { + description: key.description, + name: key.name, + identifier: key.uid, + } + } + + pub async fn update(&self, client: &Client) -> Result { + // only send description and name + let updated = KeyUpdater::new(self); client.update_key(self).await } } @@ -320,6 +354,7 @@ impl KeyBuilder { /// # client.delete_key(key).await.unwrap(); /// # }); /// ``` + /// TODO: create ? pub async fn execute(&self, client: &Client) -> Result { client.create_key(self).await } From abc0f7ba2ddd5c105e4822bb8efbe5d98bf0e664 Mon Sep 17 00:00:00 2001 From: Charlotte Vermandel Date: Tue, 9 Aug 2022 14:45:16 +0200 Subject: [PATCH 23/44] Update task API --- src/client.rs | 52 ++++++++++++++++++++++++++++++++++++++++++++------ src/indexes.rs | 43 +++++++++++++++++++++++++++++++---------- src/tasks.rs | 21 +++++++++++++++----- 3 files changed, 95 insertions(+), 21 deletions(-) diff --git a/src/client.rs b/src/client.rs index 0ffc365c..acc543b7 100644 --- a/src/client.rs +++ b/src/client.rs @@ -608,7 +608,7 @@ impl Client { .await } - /// Get all tasks from the server. + /// Get all tasks with query parameters from the server. /// /// # Example /// @@ -622,14 +622,17 @@ impl Client { /// # let client = client::Client::new(MEILISEARCH_HOST, MEILISEARCH_API_KEY); /// /// let mut query = tasks::TasksQuery::new(&client); - /// query.with_index_uid(["get_tasks"]); - /// let tasks = client.get_tasks(&query).await.unwrap(); + /// query.with_index_uid(["get_tasks_with"]); + /// let tasks = client.get_tasks_with(&query).await.unwrap(); /// /// assert!(tasks.results.len() > 0); - /// # client.index("get_tasks").delete().await.unwrap().wait_for_completion(&client, None, None).await.unwrap(); + /// # client.index("get_tasks_with").delete().await.unwrap().wait_for_completion(&client, None, None).await.unwrap(); /// # }); /// ``` - pub async fn get_tasks(&self, tasks_query: &TasksQuery<'_>) -> Result { + pub async fn get_tasks_with( + &self, + tasks_query: &TasksQuery<'_>, + ) -> Result { let tasks = request::<&TasksQuery, TasksResults>( &format!("{}/tasks", self.host), &self.api_key, @@ -641,6 +644,37 @@ impl Client { Ok(tasks) } + /// Get all tasks from the server. + /// + /// # Example + /// + /// ``` + /// # use meilisearch_sdk::*; + /// # + /// # let MEILISEARCH_HOST = option_env!("MEILISEARCH_HOST").unwrap_or("http://localhost:7700"); + /// # let MEILISEARCH_API_KEY = option_env!("MEILISEARCH_API_KEY").unwrap_or("masterKey"); + /// # + /// # futures::executor::block_on(async move { + /// # let client = client::Client::new(MEILISEARCH_HOST, MEILISEARCH_API_KEY); + /// + /// let tasks = client.get_tasks().await.unwrap(); + /// + /// assert!(tasks.results.len() > 0); + /// # client.index("get_tasks").delete().await.unwrap().wait_for_completion(&client, None, None).await.unwrap(); + /// # }); + /// ``` + pub async fn get_tasks(&self) -> Result { + let tasks = request::<(), TasksResults>( + &format!("{}/tasks", self.host), + &self.api_key, + Method::Get(()), + 200, + ) + .await?; + + Ok(tasks) + } + /// Generates a new tenant token. /// /// # Example @@ -774,8 +808,14 @@ mod tests { #[meilisearch_test] async fn test_get_tasks(client: Client) { + let tasks = client.get_tasks().await.unwrap(); + assert!(tasks.results.len() >= 2); + } + + #[meilisearch_test] + async fn test_get_tasks_with_params(client: Client) { let query = TasksQuery::new(&client); - let tasks = client.get_tasks(&query).await.unwrap(); + let tasks = client.get_tasks_with(&query).await.unwrap(); assert!(tasks.results.len() >= 2); } diff --git a/src/indexes.rs b/src/indexes.rs index 1d317009..99eddf56 100644 --- a/src/indexes.rs +++ b/src/indexes.rs @@ -758,7 +758,7 @@ impl Index { /// # let client = Client::new(MEILISEARCH_HOST, MEILISEARCH_API_KEY); /// # let index = client.create_index("get_tasks", None).await.unwrap().wait_for_completion(&client, None, None).await.unwrap().try_make_index(&client).unwrap(); /// - /// let tasks = index.get_tasks().execute().await.unwrap(); + /// let tasks = index.get_tasks().await.unwrap(); /// /// assert!(tasks.results.len() > 0); /// # index.delete().await.unwrap().wait_for_completion(&client, None, None).await.unwrap(); @@ -767,19 +767,42 @@ impl Index { /// TODO: how to pass a tasks_query? pub async fn get_tasks(&self) -> Result { let mut query = TasksQuery::new(&self.client); - query.with_index_uid([self.uid.as_str()]); - self.client.get_tasks(&query).await + self.client.get_tasks_with(&query).await + } - // pub async fn get_tasks( - // &self, - // mut tasks_query: &mut TasksQuery<'_>, - // ) -> Result { - // tasks_query.with_index_uid([self.uid.as_str()]); + /// Get the status of all tasks in a given index. + /// + /// # Example + /// + /// ``` + /// # use serde::{Serialize, Deserialize}; + /// # use meilisearch_sdk::{client::*, indexes::*, tasks::*}; + /// # + /// # let MEILISEARCH_HOST = option_env!("MEILISEARCH_HOST").unwrap_or("http://localhost:7700"); + /// # let MEILISEARCH_API_KEY = option_env!("MEILISEARCH_API_KEY").unwrap_or("masterKey"); + /// # + /// # futures::executor::block_on(async move { + /// # let client = Client::new(MEILISEARCH_HOST, MEILISEARCH_API_KEY); + /// # 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"]); + /// let tasks = index.get_tasks_with(&query).await.unwrap(); + /// + /// assert!(tasks.results.len() > 0); + /// # index.delete().await.unwrap().wait_for_completion(&client, None, None).await.unwrap(); + /// # }); + /// ``` + pub async fn get_tasks_with( + &self, + tasks_query: &TasksQuery<'_>, + ) -> Result { + let mut query = tasks_query.clone(); + query.with_index_uid([self.uid.as_str()]); - // self.client.get_tasks(&tasks_query).await - // } + self.client.get_tasks_with(&query).await } /// Get stats of an index. diff --git a/src/tasks.rs b/src/tasks.rs index 0623ce05..fb55ba8b 100644 --- a/src/tasks.rs +++ b/src/tasks.rs @@ -456,7 +456,7 @@ impl<'a> TasksQuery<'a> { } pub async fn execute(&'a self) -> Result { - self.client.get_tasks(self).await + self.client.get_tasks_with(self).await } } @@ -621,8 +621,7 @@ mod test { let path = "/tasks"; let mock_res = mock("GET", path).with_status(200).create(); - let query = TasksQuery::new(&client); - let _ = client.get_tasks(&query).await; + let _ = client.get_tasks().await; mock_res.assert(); Ok(()) @@ -645,7 +644,7 @@ mod test { .with_from(1) .with_limit(0); - let _ = client.get_tasks(&query).await; + let _ = client.get_tasks_with(&query).await; mock_res.assert(); Ok(()) @@ -676,7 +675,19 @@ mod test { async fn test_get_tasks_with_none_existant_index_uid(client: Client) -> Result<(), Error> { let mut query = TasksQuery::new(&client); query.with_index_uid(["no_name"]); - let tasks = client.get_tasks(&query).await.unwrap(); + let tasks = client.get_tasks_with(&query).await.unwrap(); + + assert_eq!(tasks.results.len(), 0); + Ok(()) + } + + #[meilisearch_test] + async fn test_get_tasks_with_execute(client: Client) -> Result<(), Error> { + let tasks = TasksQuery::new(&client) + .with_index_uid(["no_name"]) + .execute() + .await + .unwrap(); assert_eq!(tasks.results.len(), 0); Ok(()) From eaef1ea8809b21ea009501506921c45b57743e02 Mon Sep 17 00:00:00 2001 From: Charlotte Vermandel Date: Tue, 9 Aug 2022 14:47:49 +0200 Subject: [PATCH 24/44] Remove useless comment --- src/indexes.rs | 9 --------- 1 file changed, 9 deletions(-) diff --git a/src/indexes.rs b/src/indexes.rs index 99eddf56..54294f69 100644 --- a/src/indexes.rs +++ b/src/indexes.rs @@ -764,7 +764,6 @@ impl Index { /// # index.delete().await.unwrap().wait_for_completion(&client, None, None).await.unwrap(); /// # }); /// ``` - /// TODO: how to pass a tasks_query? pub async fn get_tasks(&self) -> Result { let mut query = TasksQuery::new(&self.client); query.with_index_uid([self.uid.as_str()]); @@ -1101,14 +1100,6 @@ mod tests { assert!(index.primary_key.is_none()); } - // #[meilisearch_test] - // TODO: when implementing the filters in get_tasks - // async fn test_get_tasks_no_docs(index: Index) { - // // The at this point the only task that is supposed to exist is the creation of the index - // let status = index.get_tasks().await.unwrap(); - // assert_eq!(status.results.len(), 1); - // } - #[meilisearch_test] async fn test_get_one_task(client: Client, index: Index) -> Result<(), Error> { let task = index From d506eae6c292b98b0eebd61bb8f2ee7304a0d237 Mon Sep 17 00:00:00 2001 From: Charlotte Vermandel Date: Wed, 10 Aug 2022 11:09:44 +0200 Subject: [PATCH 25/44] Remove client as mandatory parameter for the keyUpdater --- src/client.rs | 7 +- src/key.rs | 269 +++++++++++++++++++++++++++++++++++++++----------- 2 files changed, 217 insertions(+), 59 deletions(-) diff --git a/src/client.rs b/src/client.rs index 4a178cb6..133e807b 100644 --- a/src/client.rs +++ b/src/client.rs @@ -324,8 +324,11 @@ impl Client { /// # /// # futures::executor::block_on(async move { /// let client = Client::new(MEILISEARCH_HOST, MEILISEARCH_API_KEY); - /// let keys = client.get_keys().await.unwrap(); - /// assert!(keys.len() >= 2); + /// let mut query = KeysQuery::new(); + /// query.with_limit(1); + /// let keys = client.get_keys_with(&query).await.unwrap(); + /// + /// assert_eq!(keys.results.len(), 1); /// # }); /// ``` /// TODO: hidden diff --git a/src/key.rs b/src/key.rs index 94ae80c7..0d778ba1 100644 --- a/src/key.rs +++ b/src/key.rs @@ -40,14 +40,14 @@ impl Key { /// # /// # futures::executor::block_on(async move { /// # let client = Client::new(MEILISEARCH_HOST, MEILISEARCH_API_KEY); - /// - /// let mut key = KeyBuilder::new("My little lovely test key") + /// let description = "My not so little lovely test key".to_string(); + /// let mut key = KeyBuilder::new() /// .with_action(Action::DocumentsAdd) /// .with_index("*") - /// .create(&client).await.unwrap(); + /// .with_description(&description) + /// .execute(&client).await.unwrap(); /// - /// key.with_description("My not so little lovely test key"); - /// # assert_eq!(key.description, "My not so little lovely test key".to_string()); + /// # assert_eq!(key.description, Some(description)); /// # client.delete_key(key).await.unwrap(); /// # }); /// ``` @@ -68,14 +68,14 @@ impl Key { /// # /// # futures::executor::block_on(async move { /// # let client = Client::new(MEILISEARCH_HOST, MEILISEARCH_API_KEY); - /// - /// let mut key = KeyBuilder::new("My little lovely test key") + /// let name = "lovely key".to_string(); + /// let mut key = KeyBuilder::new() /// .with_action(Action::DocumentsAdd) /// .with_index("*") - /// .create(&client).await.unwrap(); + /// .execute(&client).await.unwrap(); /// - /// key.with_name("lovely key"); - /// # assert_eq!(key.name, "lovely key".to_string()); + /// key.with_name(&name); + /// # assert_eq!(key.name, Some(name)); /// # client.delete_key(key).await.unwrap(); /// # }); /// ``` @@ -96,73 +96,172 @@ impl Key { /// # /// # futures::executor::block_on(async move { /// let client = Client::new(MEILISEARCH_HOST, MEILISEARCH_API_KEY); - /// let mut key = KeyBuilder::new("My little lovely test key") - /// .create(&client).await.unwrap(); - /// - /// # assert_eq!(key.description, "My little lovely test key"); - /// - /// key.with_description("My not so little lovely test key"); + /// let mut key = KeyBuilder::new() + /// .execute(&client).await.unwrap(); + /// let description = "My not so little lovely test key".to_string(); + /// key.with_description(&description); /// let key = key.update(&client).await.unwrap(); /// - /// # assert_eq!(key.description, "My not so little lovely test key".to_string()); - /// + /// # assert_eq!(key.description, Some(description)); /// # client.delete_key(key).await.unwrap(); /// # }); /// ``` pub async fn update(&self, client: &Client) -> Result { // only send description and name - let updated = KeyUpdater::new(self); - client.update_key(self).await + let mut key_update = KeyUpdater::new(self); + + if let Some(ref description) = self.description { + key_update.with_description(description); + } + if let Some(ref name) = self.name { + key_update.with_name(name); + } + + key_update.execute(client).await } - // client.delete_key("1") - pub async fn delete(&self, client: &Client) -> Result { + /// Delete the [Key]. + /// + /// # Example + /// + /// ``` + /// # use meilisearch_sdk::{key::KeyBuilder, client::Client}; + /// # + /// # let MEILISEARCH_HOST = option_env!("MEILISEARCH_HOST").unwrap_or("http://localhost:7700"); + /// # let MEILISEARCH_API_KEY = option_env!("MEILISEARCH_API_KEY").unwrap_or("masterKey"); + /// # + /// # futures::executor::block_on(async move { + /// let client = Client::new(MEILISEARCH_HOST, MEILISEARCH_API_KEY); + /// let mut key = KeyBuilder::new() + /// .execute(&client).await.unwrap(); + /// + /// client.delete_key(key).await.unwrap(); + /// # }); + /// ``` + pub async fn delete(&self, client: &Client) -> Result<(), Error> { client.delete_key(self).await } } +impl AsRef for Key { + fn as_ref(&self) -> &str { + &self.key + } +} + +impl AsRef for Key { + fn as_ref(&self) -> &Key { + self + } +} + #[derive(Debug, Serialize, Deserialize, Clone)] #[serde(rename_all = "camelCase")] pub struct KeyUpdater { pub description: Option, pub name: Option, #[serde(skip_serializing)] - pub identifier: String, + pub key: String, } impl KeyUpdater { - pub fn new(key: &Key) -> KeyUpdater { + pub fn new(key_or_uid: impl AsRef) -> KeyUpdater { KeyUpdater { - description: key.description, - name: key.name, - identifier: key.uid, + description: None, + name: None, + key: key_or_uid.as_ref().to_string(), } } - pub async fn update(&self, client: &Client) -> Result { + /// Update the description of the key. + /// + /// # Example + /// + /// ``` + /// # use meilisearch_sdk::{key::KeyBuilder, key::Action, client::Client, key::KeyUpdater}; + /// # + /// # let MEILISEARCH_HOST = option_env!("MEILISEARCH_HOST").unwrap_or("http://localhost:7700"); + /// # let MEILISEARCH_API_KEY = option_env!("MEILISEARCH_API_KEY").unwrap_or("masterKey"); + /// # + /// # futures::executor::block_on(async move { + /// # let client = Client::new(MEILISEARCH_HOST, MEILISEARCH_API_KEY); + /// + /// let mut new_key = KeyBuilder::new() + /// .execute(&client) + /// .await + /// .unwrap(); + /// + /// let description = "My not so little lovely test key".to_string(); + /// let mut key_update = KeyUpdater::new(new_key) + /// .with_description(&description) + /// .execute(&client) + /// .await + /// .unwrap(); + /// + /// # assert_eq!(key_update.description, Some(description)); + /// # client.delete_key(key_update).await.unwrap(); + /// # }); + /// ``` + pub fn with_description(&mut self, desc: impl AsRef) -> &mut Self { + self.description = Some(desc.as_ref().to_string()); + self + } + + /// Update the name of the key. + /// + /// # Example + /// + /// ``` + /// # use meilisearch_sdk::{key::KeyBuilder, key::Action, client::Client, key::KeyUpdater}; + /// # + /// # let MEILISEARCH_HOST = option_env!("MEILISEARCH_HOST").unwrap_or("http://localhost:7700"); + /// # let MEILISEARCH_API_KEY = option_env!("MEILISEARCH_API_KEY").unwrap_or("masterKey"); + /// # + /// # futures::executor::block_on(async move { + /// # let client = Client::new(MEILISEARCH_HOST, MEILISEARCH_API_KEY); + /// let mut new_key = KeyBuilder::new() + /// .execute(&client) + /// .await + /// .unwrap(); + /// + /// let name = "lovely key".to_string(); + /// + /// let mut key_update = KeyUpdater::new(new_key) + /// .with_name(&name) + /// .execute(&client) + /// .await + /// .unwrap(); + /// + /// # assert_eq!(key_update.name, Some(name)); + /// # client.delete_key(key_update).await.unwrap(); + /// # }); + /// ``` + pub fn with_name(&mut self, desc: impl AsRef) -> &mut Self { + self.name = Some(desc.as_ref().to_string()); + self + } + + pub async fn execute(&self, client: &Client) -> Result { // only send description and name - let updated = KeyUpdater::new(self); client.update_key(self).await } } -impl AsRef for Key { +impl AsRef for KeyUpdater { fn as_ref(&self) -> &str { &self.key } } -impl AsRef for Key { - fn as_ref(&self) -> &Key { +impl AsRef for KeyUpdater { + fn as_ref(&self) -> &KeyUpdater { self } } #[derive(Debug, Serialize, Clone)] #[serde(rename_all = "camelCase")] -pub struct KeysQuery<'a> { - #[serde(skip_serializing)] - pub client: &'a Client, +pub struct KeysQuery { /// The number of documents to skip. /// If the value of the parameter `offset` is `n`, the `n` first documents (ordered by relevance) will not be returned. /// This is helpful for pagination. @@ -180,10 +279,9 @@ pub struct KeysQuery<'a> { pub limit: Option, } -impl<'a> KeysQuery<'a> { - pub fn new(client: &'a Client) -> KeysQuery<'a> { +impl KeysQuery { + pub fn new() -> KeysQuery { KeysQuery { - client, offset: None, limit: None, } @@ -200,7 +298,7 @@ impl<'a> KeysQuery<'a> { /// Execute the query and fetch the results. pub async fn execute(&'a self) -> Result { - self.client.execute_get_keys(self).await + self.client.get_keys_with(self).await } } @@ -217,13 +315,12 @@ impl<'a> KeysQuery<'a> { /// # /// # futures::executor::block_on(async move { /// let client = Client::new(MEILISEARCH_HOST, MEILISEARCH_API_KEY); +/// let description = "My little lovely test key".to_string(); +/// let key = KeyBuilder::new() +/// .with_description(&description) +/// .execute(&client).await.unwrap(); /// -/// let key = KeyBuilder::new("My little lovely test key") -/// .with_action(Action::DocumentsAdd) -/// .with_index("*") -/// .create(&client).await.unwrap(); -/// -/// assert_eq!(key.description, "My little lovely test key"); +/// assert_eq!(key.description, Some(description)); /// # client.delete_key(key).await.unwrap(); /// # }); /// ``` @@ -232,6 +329,7 @@ impl<'a> KeysQuery<'a> { pub struct KeyBuilder { pub actions: Vec, pub description: Option, + pub name: Option, #[serde(with = "time::serde::rfc3339::option")] pub expires_at: Option, pub indexes: Vec, @@ -244,12 +342,13 @@ impl KeyBuilder { /// /// ``` /// # use meilisearch_sdk::{key::KeyBuilder}; - /// let builder = KeyBuilder::new("My little lovely test key"); + /// let builder = KeyBuilder::new(); /// ``` pub fn new() -> KeyBuilder { Self { actions: Vec::new(), description: None, + name: None, expires_at: None, indexes: Vec::new(), } @@ -261,7 +360,7 @@ impl KeyBuilder { /// /// ``` /// # use meilisearch_sdk::key::{KeyBuilder, Action}; - /// let mut builder = KeyBuilder::new("My little lovely test key"); + /// let mut builder = KeyBuilder::new(); /// builder.with_actions(vec![Action::Search, Action::DocumentsAdd]); /// ``` pub fn with_actions(&mut self, actions: impl IntoIterator) -> &mut Self { @@ -275,7 +374,7 @@ impl KeyBuilder { /// /// ``` /// # use meilisearch_sdk::key::{KeyBuilder, Action}; - /// let mut builder = KeyBuilder::new("My little lovely test key"); + /// let mut builder = KeyBuilder::new(); /// builder.with_action(Action::DocumentsAdd); /// ``` pub fn with_action(&mut self, action: Action) -> &mut Self { @@ -290,7 +389,7 @@ impl KeyBuilder { /// ``` /// # use meilisearch_sdk::{key::KeyBuilder}; /// use time::{OffsetDateTime, Duration}; - /// let mut builder = KeyBuilder::new("My little lovely test key"); + /// let mut builder = KeyBuilder::new(); /// // create a key that expires in two weeks from now /// builder.with_expires_at(OffsetDateTime::now_utc() + Duration::WEEK * 2); /// ``` @@ -305,7 +404,7 @@ impl KeyBuilder { /// /// ``` /// # use meilisearch_sdk::{key::KeyBuilder}; - /// let mut builder = KeyBuilder::new("My little lovely test key"); + /// let mut builder = KeyBuilder::new(); /// builder.with_indexes(vec!["test", "movies"]); /// ``` pub fn with_indexes( @@ -325,7 +424,7 @@ impl KeyBuilder { /// /// ``` /// # use meilisearch_sdk::{key::KeyBuilder}; - /// let mut builder = KeyBuilder::new("My little lovely test key"); + /// let mut builder = KeyBuilder::new(); /// builder.with_index("test"); /// ``` pub fn with_index(&mut self, index: impl AsRef) -> &mut Self { @@ -333,7 +432,61 @@ impl KeyBuilder { self } - // TODO: with_description + /// Add a description to the key. + /// + /// # Example + /// + /// ``` + /// # use meilisearch_sdk::{key::KeyBuilder, key::Action, client::Client}; + /// # + /// # let MEILISEARCH_HOST = option_env!("MEILISEARCH_HOST").unwrap_or("http://localhost:7700"); + /// # let MEILISEARCH_API_KEY = option_env!("MEILISEARCH_API_KEY").unwrap_or("masterKey"); + /// # + /// # futures::executor::block_on(async move { + /// # let client = Client::new(MEILISEARCH_HOST, MEILISEARCH_API_KEY); + /// let description = "My not so little lovely test key".to_string(); + /// + /// let mut key = KeyBuilder::new() + /// .with_description(&description) + /// .execute(&client).await.unwrap(); + /// + /// # assert_eq!(key.description, Some(description)); + /// # client.delete_key(key).await.unwrap(); + /// # }); + /// ``` + pub fn with_description(&mut self, desc: impl AsRef) -> &mut Self { + self.description = Some(desc.as_ref().to_string()); + self + } + + /// Update the name of the key. + /// + /// # Example + /// + /// ``` + /// # use meilisearch_sdk::{key::KeyBuilder, key::Action, client::Client}; + /// # + /// # let MEILISEARCH_HOST = option_env!("MEILISEARCH_HOST").unwrap_or("http://localhost:7700"); + /// # let MEILISEARCH_API_KEY = option_env!("MEILISEARCH_API_KEY").unwrap_or("masterKey"); + /// # + /// # futures::executor::block_on(async move { + /// # let client = Client::new(MEILISEARCH_HOST, MEILISEARCH_API_KEY); + /// let name = "lovely key".to_string(); + /// + /// let mut key = KeyBuilder::new() + /// .with_action(Action::DocumentsAdd) + /// .with_index("*") + /// .execute(&client).await.unwrap(); + /// + /// key.with_name(&name); + /// # assert_eq!(key.name, Some(name)); + /// # client.delete_key(key).await.unwrap(); + /// # }); + /// ``` + pub fn with_name(&mut self, desc: impl AsRef) -> &mut Self { + self.name = Some(desc.as_ref().to_string()); + self + } /// Create a [Key] from the builder. /// @@ -347,10 +500,12 @@ impl KeyBuilder { /// # /// # futures::executor::block_on(async move { /// let client = Client::new(MEILISEARCH_HOST, MEILISEARCH_API_KEY); - /// let key = KeyBuilder::new("My little lovely test key") - /// .create(&client).await.unwrap(); + /// let description = "My little lovely test key".to_string(); + /// let key = KeyBuilder::new() + /// .with_description(&description) + /// .execute(&client).await.unwrap(); /// - /// assert_eq!(key.description, "My little lovely test key"); + /// assert_eq!(key.description, Some(description)); /// # client.delete_key(key).await.unwrap(); /// # }); /// ``` @@ -384,7 +539,7 @@ pub enum Action { #[serde(rename = "documents.delete")] DocumentsDelete, /// Provides access to the [create index](https://docs.meilisearch.com/reference/api/indexes.md#create-an-index) endpoint. - #[serde(rename = "indexes.create")] + #[serde(rename = "indexes.execute")] IndexesCreate, /// Provides access to the [get one index](https://docs.meilisearch.com/reference/api/indexes.md#get-one-index) and [list all indexes](https://docs.meilisearch.com/reference/api/indexes.md#list-all-indexes) endpoints. **Non-authorized `indexes` will be omitted from the response**. #[serde(rename = "indexes.get")] @@ -408,7 +563,7 @@ pub enum Action { #[serde(rename = "stats.get")] StatsGet, /// Provides access to the [create dump](https://docs.meilisearch.com/reference/api/dump.md#create-a-dump) endpoint. **Not restricted by `indexes`.** - #[serde(rename = "dumps.create")] + #[serde(rename = "dumps.execute")] DumpsCreate, /// Provides access to the [get dump status](https://docs.meilisearch.com/reference/api/dump.md#get-dump-status) endpoint. **Not restricted by `indexes`.** #[serde(rename = "dumps.get")] From c803fd50bc51538ec3c8688cbd5ff693bc01a17e Mon Sep 17 00:00:00 2001 From: Charlotte Vermandel Date: Wed, 10 Aug 2022 11:10:19 +0200 Subject: [PATCH 26/44] Add doc and tests on doc --- src/key.rs | 74 ++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 67 insertions(+), 7 deletions(-) diff --git a/src/key.rs b/src/key.rs index 0d778ba1..af27878f 100644 --- a/src/key.rs +++ b/src/key.rs @@ -287,18 +287,79 @@ impl KeysQuery { } } - pub fn with_offset<'b>(&'b mut self, offset: usize) -> &'b mut KeysQuery<'a> { + /// Specify the offset. + /// + /// # Example + /// + /// ``` + /// # use meilisearch_sdk::{key::KeysQuery, key::Action, client::Client}; + /// # + /// # let MEILISEARCH_HOST = option_env!("MEILISEARCH_HOST").unwrap_or("http://localhost:7700"); + /// # let MEILISEARCH_API_KEY = option_env!("MEILISEARCH_API_KEY").unwrap_or("masterKey"); + /// # + /// # futures::executor::block_on(async move { + /// # let client = Client::new(MEILISEARCH_HOST, MEILISEARCH_API_KEY); + /// let mut keys = KeysQuery::new() + /// .with_offset(1) + /// .execute(&client).await.unwrap(); + /// + /// # assert_eq!(keys.results.len(), 1); + /// # }); + /// ``` + pub fn with_offset<'b>(&'b mut self, offset: usize) -> &'b mut KeysQuery { self.offset = Some(offset); self } - pub fn with_limit<'b>(&'b mut self, limit: usize) -> &'b mut KeysQuery<'a> { + + /// Specify the maximum number of keys to return. + /// + /// # Example + /// + /// ``` + /// # use meilisearch_sdk::{key::KeysQuery, key::Action, client::Client}; + /// # + /// # let MEILISEARCH_HOST = option_env!("MEILISEARCH_HOST").unwrap_or("http://localhost:7700"); + /// # let MEILISEARCH_API_KEY = option_env!("MEILISEARCH_API_KEY").unwrap_or("masterKey"); + /// # + /// # futures::executor::block_on(async move { + /// # let client = Client::new(MEILISEARCH_HOST, MEILISEARCH_API_KEY); + /// let mut keys = KeysQuery::new() + /// .with_limit(1) + /// .execute(&client).await.unwrap(); + /// + /// # assert_eq!(keys.results.len(), 1); + /// # }); + /// ``` + pub fn with_limit<'b>(&'b mut self, limit: usize) -> &'b mut KeysQuery { self.limit = Some(limit); self } - /// Execute the query and fetch the results. - pub async fn execute(&'a self) -> Result { - self.client.get_keys_with(self).await + /// Execute the update of a Key. + /// + /// # Example + /// + /// ``` + /// # use meilisearch_sdk::{key::KeyBuilder, key::KeyUpdater, client::Client}; + /// # + /// # let MEILISEARCH_HOST = option_env!("MEILISEARCH_HOST").unwrap_or("http://localhost:7700"); + /// # let MEILISEARCH_API_KEY = option_env!("MEILISEARCH_API_KEY").unwrap_or("masterKey"); + /// # + /// # futures::executor::block_on(async move { + /// let client = Client::new(MEILISEARCH_HOST, MEILISEARCH_API_KEY); + /// let description = "My little lovely test key".to_string(); + /// let key = KeyBuilder::new() + /// .execute(&client).await.unwrap(); + /// + /// let mut key_update = KeyUpdater::new(&key.key); + /// key_update.with_description(&description).execute(&client).await; + /// + /// assert_eq!(key_update.description, Some(description)); + /// # client.delete_key(key).await.unwrap(); + /// # }); + /// ``` + pub async fn execute(&self, client: &Client) -> Result { + client.get_keys_with(self).await } } @@ -459,7 +520,7 @@ impl KeyBuilder { self } - /// Update the name of the key. + /// Add a name to the key. /// /// # Example /// @@ -509,7 +570,6 @@ impl KeyBuilder { /// # client.delete_key(key).await.unwrap(); /// # }); /// ``` - /// TODO: create ? pub async fn execute(&self, client: &Client) -> Result { client.create_key(self).await } From cdc2a41e95b114dfaf872eb4b53b232842a3ee72 Mon Sep 17 00:00:00 2001 From: Charlotte Vermandel Date: Wed, 10 Aug 2022 11:11:11 +0200 Subject: [PATCH 27/44] Fix docs tests on keys in client --- src/client.rs | 107 ++++++++++++++++++++++++++++++-------------------- 1 file changed, 64 insertions(+), 43 deletions(-) diff --git a/src/client.rs b/src/client.rs index 133e807b..411e5885 100644 --- a/src/client.rs +++ b/src/client.rs @@ -1,7 +1,7 @@ use crate::{ errors::*, indexes::*, - key::{Key, KeyBuilder, KeysQuery, KeysResults}, + key::{Key, KeyBuilder, KeyUpdater, KeysQuery, KeysResults}, request::*, task_info::TaskInfo, tasks::{Task, TasksQuery, TasksResults}, @@ -309,7 +309,7 @@ impl Client { } } - /// Get the API [Key]s from Meilisearch. + /// Get the API [Key]s from Meilisearch with parameters. /// See the [meilisearch documentation](https://docs.meilisearch.com/reference/api/keys.html#get-all-keys). /// /// See also [Client::create_key] and [Client::get_key]. @@ -317,7 +317,7 @@ impl Client { /// # Example /// /// ``` - /// # use meilisearch_sdk::{client::*, errors::Error, key::KeyBuilder}; + /// # use meilisearch_sdk::{client::*, errors::Error, key::KeysQuery}; /// # /// # let MEILISEARCH_HOST = option_env!("MEILISEARCH_HOST").unwrap_or("http://localhost:7700"); /// # let MEILISEARCH_API_KEY = option_env!("MEILISEARCH_API_KEY").unwrap_or("masterKey"); @@ -331,8 +331,7 @@ impl Client { /// assert_eq!(keys.results.len(), 1); /// # }); /// ``` - /// TODO: hidden - pub async fn get_keys_with(&self, keys_query: &KeysQuery<'_>) -> Result { + pub async fn get_keys_with(&self, keys_query: &KeysQuery) -> Result { let keys = request::<&KeysQuery, KeysResults>( &format!("{}/keys", self.host), &self.api_key, @@ -344,6 +343,27 @@ impl Client { Ok(keys) } + /// Get the API [Key]s from Meilisearch. + /// See the [meilisearch documentation](https://docs.meilisearch.com/reference/api/keys.html#get-all-keys). + /// + /// See also [Client::create_key] and [Client::get_key]. + /// + /// # Example + /// + /// ``` + /// # use meilisearch_sdk::{client::*, errors::Error, key::KeyBuilder}; + /// # + /// # let MEILISEARCH_HOST = option_env!("MEILISEARCH_HOST").unwrap_or("http://localhost:7700"); + /// # let MEILISEARCH_API_KEY = option_env!("MEILISEARCH_API_KEY").unwrap_or("masterKey"); + /// # + /// # futures::executor::block_on(async move { + /// let client = Client::new(MEILISEARCH_HOST, MEILISEARCH_API_KEY); + /// let keys = client.get_keys().await.unwrap(); + /// + /// dbg!(&keys); + /// assert_eq!(keys.results.len(), 2); + /// # }); + /// ``` pub async fn get_keys(&self) -> Result { let keys = request::<(), KeysResults>( &format!("{}/keys", self.host), @@ -371,11 +391,13 @@ impl Client { /// # /// # futures::executor::block_on(async move { /// let client = Client::new(MEILISEARCH_HOST, MEILISEARCH_API_KEY); - /// # let key = client.get_keys().await.unwrap().into_iter().find(|k| k.description.starts_with("Default Search API Key")).unwrap(); + /// # let key = client.get_keys().await.unwrap().results.into_iter() + /// .find(|k| k.name.as_ref().map_or(false, |name| name.starts_with("Default Search API Key"))); /// let key_id = // enter your API key here, for the example we'll say we entered our search API key. - /// # key.key; + /// # key.unwrap().key; /// let key = client.get_key(key_id).await.unwrap(); - /// assert_eq!(key.description, "Default Search API Key (Use it to search from the frontend)"); + /// + /// assert_eq!(key.name, Some("Default Search API Key".to_string())); /// # }); /// ``` pub async fn get_key(&self, key: impl AsRef) -> Result { @@ -403,14 +425,14 @@ impl Client { /// # /// # futures::executor::block_on(async move { /// let client = Client::new(MEILISEARCH_HOST, MEILISEARCH_API_KEY); - /// let key = KeyBuilder::new("delete_key"); + /// let key = KeyBuilder::new(); /// let key = client.create_key(key).await.unwrap(); /// let inner_key = key.key.clone(); /// /// client.delete_key(key).await.unwrap(); /// /// let keys = client.get_keys().await.unwrap(); - /// assert!(keys.iter().all(|key| key.key != inner_key)); + /// assert!(keys.results.iter().all(|key| key.key != inner_key)); /// # }); /// ``` pub async fn delete_key(&self, key: impl AsRef) -> Result<(), Error> { @@ -439,18 +461,17 @@ impl Client { /// # futures::executor::block_on(async move { /// /// let client = Client::new(MEILISEARCH_HOST, MEILISEARCH_API_KEY); - /// let mut key = KeyBuilder::new("create_key"); - /// key.with_index("*").with_action(Action::DocumentsAdd); + /// let name = "create_key".to_string(); + /// let mut key = KeyBuilder::new(); + /// key.with_name(&name); + /// /// let key = client.create_key(key).await.unwrap(); - /// assert_eq!(key.description, "create_key"); + /// + /// assert_eq!(key.name, Some(name)); /// # client.delete_key(key).await.unwrap(); /// # }); /// ``` pub async fn create_key(&self, key: impl AsRef) -> Result { - KeyBuilder::new(self) - } - - pub async fn execute_create_key() -> Blabla { request::<&KeyBuilder, Key>( &format!("{}/keys", self.host), &self.api_key, @@ -468,26 +489,27 @@ impl Client { /// # Example /// /// ``` - /// # use meilisearch_sdk::{client::*, errors::Error, key::KeyBuilder}; + /// # use meilisearch_sdk::{client::*, errors::Error, key::KeyBuilder, key::KeyUpdater}; /// # /// # let MEILISEARCH_HOST = option_env!("MEILISEARCH_HOST").unwrap_or("http://localhost:7700"); /// # let MEILISEARCH_API_KEY = option_env!("MEILISEARCH_API_KEY").unwrap_or("masterKey"); /// # /// # futures::executor::block_on(async move { /// let client = Client::new(MEILISEARCH_HOST, MEILISEARCH_API_KEY); - /// let key = KeyBuilder::new("update_key"); - /// let mut key = client.create_key(key).await.unwrap(); - /// assert!(key.indexes.is_empty()); - /// - /// key.indexes = vec!["*".to_string()]; - /// let key = client.update_key(key).await.unwrap(); - /// assert_eq!(key.indexes, vec!["*"]); + /// let new_key = KeyBuilder::new(); + /// let name = "my name".to_string(); + /// let mut new_key = client.create_key(new_key).await.unwrap(); + /// let mut key_update = KeyUpdater::new(new_key); + /// key_update.with_name(&name); + /// + /// let key = client.update_key(key_update).await.unwrap(); + /// assert_eq!(key.name, Some(name)); /// # client.delete_key(key).await.unwrap(); /// # }); /// ``` - pub async fn update_key(&self, key: impl AsRef) -> Result { - request::<&Key, Key>( - &format!("{}/keys/{}", self.host, key.identifier), + pub async fn update_key(&self, key: impl AsRef) -> Result { + request::<&KeyUpdater, Key>( + &format!("{}/keys/{}", self.host, key.as_ref().key), &self.api_key, Method::Patch(key.as_ref()), // name and description 200, @@ -834,7 +856,7 @@ mod tests { #[meilisearch_test] async fn test_get_keys(client: Client) { - let keys = client.get_keys().execute().await.unwrap(); + let keys = client.get_keys().await.unwrap(); assert!(keys.results.len() >= 2); assert!(keys.results.iter().any(|k| k.description != Some("Default Search API Key (Use it to search from the frontend)".to_string()))); @@ -844,17 +866,17 @@ mod tests { } #[meilisearch_test] - async fn test_delete_key(client: Client, description: String) { + async fn test_delete_key(client: Client) { let key = KeyBuilder::new(); let key = client.create_key(key).await.unwrap(); client.delete_key(&key).await.unwrap(); - let keys = client.get_keys().execute().await.unwrap(); + let keys = client.get_keys().await.unwrap(); assert!(keys.results.iter().all(|k| k.key != key.key)); } #[meilisearch_test] - async fn test_error_delete_key(mut client: Client, description: String) { + async fn test_error_delete_key(mut client: Client) { // ==> accessing a key that does not exist let error = client.delete_key("invalid_key").await.unwrap_err(); assert!(matches!( @@ -905,6 +927,7 @@ mod tests { let mut key = KeyBuilder::new(); key.with_action(Action::DocumentsAdd) .with_expires_at(expires_at.clone()) + .with_description(&description) .with_index("*"); let key = client.create_key(key).await.unwrap(); @@ -921,7 +944,7 @@ mod tests { } #[meilisearch_test] - async fn test_error_create_key(mut client: Client, description: String) { + async fn test_error_create_key(mut client: Client) { // ==> Invalid index name /* TODO: uncomment once meilisearch fix this bug: https://github.com/meilisearch/meilisearch/issues/2158 let mut key = KeyBuilder::new(); @@ -964,25 +987,23 @@ mod tests { #[meilisearch_test] async fn test_update_key(client: Client, description: String) { - let expires_at = OffsetDateTime::now_utc() + time::Duration::HOUR; let key = KeyBuilder::new(); let mut key = client.create_key(key).await.unwrap(); - let description = "new description"; - let name = "new name"; - key.with_description(description); - key.with_name(name); + let name = "new name".to_string(); + key.with_description(&description); + key.with_name(&name); - let key = client.update_key(key).await.unwrap(); + let key = key.update(&client).await.unwrap(); - assert_eq!(key.description, Some(description.to_string())); - assert_eq!(key.indexes, vec!["*".to_string()]); + assert_eq!(key.description, Some(description)); + assert_eq!(key.name, Some(name)); client.delete_key(key).await.unwrap(); } #[meilisearch_test] - async fn test_error_update_key(mut client: Client, description: String) { + async fn test_error_update_key(mut client: Client) { let key = KeyBuilder::new(); let key = client.create_key(key).await.unwrap(); @@ -1009,7 +1030,7 @@ mod tests { let master_client = client.clone(); client.api_key = Arc::new(no_right_key.key.clone()); - let error = client.update_key(key).await.unwrap_err(); + let error = key.update(&client).await.unwrap_err(); assert!(matches!( error, From b2ba741ae9da9dd45a0b68eb8b09f75f726990d6 Mon Sep 17 00:00:00 2001 From: Charlotte Vermandel Date: Wed, 10 Aug 2022 11:31:35 +0200 Subject: [PATCH 28/44] Fix docs tests --- src/client.rs | 60 ++++++++++----------------------------------------- src/key.rs | 46 +++++++++++++++++++++++++++------------ 2 files changed, 43 insertions(+), 63 deletions(-) diff --git a/src/client.rs b/src/client.rs index 411e5885..b2ea3b0e 100644 --- a/src/client.rs +++ b/src/client.rs @@ -466,7 +466,6 @@ impl Client { /// key.with_name(&name); /// /// let key = client.create_key(key).await.unwrap(); - /// /// assert_eq!(key.name, Some(name)); /// # client.delete_key(key).await.unwrap(); /// # }); @@ -867,7 +866,8 @@ mod tests { #[meilisearch_test] async fn test_delete_key(client: Client) { - let key = KeyBuilder::new(); + let mut key = KeyBuilder::new(); + key.with_name("test_delete_key"); let key = client.create_key(key).await.unwrap(); client.delete_key(&key).await.unwrap(); @@ -889,7 +889,8 @@ mod tests { )); // ==> executing the action without enough right - let key = KeyBuilder::new(); + let mut key = KeyBuilder::new(); + key.with_name("test_error_delete_key"); let key = client.create_key(key).await.unwrap(); let master_key = client.api_key.clone(); @@ -926,6 +927,7 @@ mod tests { let expires_at = OffsetDateTime::now_utc() + time::Duration::HOUR; let mut key = KeyBuilder::new(); key.with_action(Action::DocumentsAdd) + .with_name("test_create_key") .with_expires_at(expires_at.clone()) .with_description(&description) .with_index("*"); @@ -962,14 +964,16 @@ mod tests { */ // ==> executing the action without enough right - let no_right_key = KeyBuilder::new(); + let mut no_right_key = KeyBuilder::new(); + no_right_key.with_name("test_error_create_key"); let no_right_key = client.create_key(no_right_key).await.unwrap(); // backup the master key for cleanup at the end of the test let master_client = client.clone(); client.api_key = Arc::new(no_right_key.key.clone()); - let key = KeyBuilder::new(); + let mut key = KeyBuilder::new(); + key.with_name("test_error_create_key_2"); let error = client.create_key(key).await.unwrap_err(); assert!(matches!( @@ -987,7 +991,8 @@ mod tests { #[meilisearch_test] async fn test_update_key(client: Client, description: String) { - let key = KeyBuilder::new(); + let mut key = KeyBuilder::new(); + key.with_name("test_update_key"); let mut key = client.create_key(key).await.unwrap(); let name = "new name".to_string(); @@ -1002,49 +1007,6 @@ mod tests { client.delete_key(key).await.unwrap(); } - #[meilisearch_test] - async fn test_error_update_key(mut client: Client) { - let key = KeyBuilder::new(); - let key = client.create_key(key).await.unwrap(); - - // ==> Invalid index name - /* TODO: uncomment once meilisearch fix this bug: https://github.com/meilisearch/meilisearch/issues/2158 - key.indexes = vec!["invalid index # / \\name with spaces".to_string()]; - let error = client.update_key(key).await.unwrap_err(); - - assert!(matches!( - error, - Error::MeilisearchError { - error_code: ErrorCode::InvalidApiKeyIndexes, - error_type: ErrorType::InvalidRequest, - .. - } - )); - */ - - // ==> executing the action without enough right - let no_right_key = KeyBuilder::new(); - let no_right_key = client.create_key(no_right_key).await.unwrap(); - - // backup the master key for cleanup at the end of the test - let master_client = client.clone(); - client.api_key = Arc::new(no_right_key.key.clone()); - - let error = key.update(&client).await.unwrap_err(); - - assert!(matches!( - error, - Error::Meilisearch(MeilisearchError { - error_code: ErrorCode::InvalidApiKey, - error_type: ErrorType::Auth, - .. - }) - )); - - // cleanup - master_client.delete_key(&*client.api_key).await.unwrap(); - } - #[meilisearch_test] async fn test_get_index(client: Client, index_uid: String) -> Result<(), Error> { let task = client.create_index(&index_uid, None).await?; diff --git a/src/key.rs b/src/key.rs index af27878f..7d1548cc 100644 --- a/src/key.rs +++ b/src/key.rs @@ -241,8 +241,30 @@ impl KeyUpdater { self } + /// Update a Key using the [KeyUpdater]. + /// + /// # Example + /// + /// ``` + /// # use meilisearch_sdk::{key::KeyBuilder, key::KeyUpdater, client::Client}; + /// # + /// # let MEILISEARCH_HOST = option_env!("MEILISEARCH_HOST").unwrap_or("http://localhost:7700"); + /// # let MEILISEARCH_API_KEY = option_env!("MEILISEARCH_API_KEY").unwrap_or("masterKey"); + /// # + /// # futures::executor::block_on(async move { + /// let client = Client::new(MEILISEARCH_HOST, MEILISEARCH_API_KEY); + /// let description = "My little lovely test key".to_string(); + /// let key = KeyBuilder::new() + /// .execute(&client).await.unwrap(); + /// + /// let mut key_update = KeyUpdater::new(&key.key); + /// key_update.with_description(&description).execute(&client).await; + /// + /// assert_eq!(key_update.description, Some(description)); + /// # client.delete_key(key).await.unwrap(); + /// # }); + /// ``` pub async fn execute(&self, client: &Client) -> Result { - // only send description and name client.update_key(self).await } } @@ -335,27 +357,23 @@ impl KeysQuery { self } - /// Execute the update of a Key. + /// Get [Key]'s. /// /// # Example /// /// ``` - /// # use meilisearch_sdk::{key::KeyBuilder, key::KeyUpdater, client::Client}; + /// # use meilisearch_sdk::{key::KeysQuery, key::Action, client::Client}; /// # /// # let MEILISEARCH_HOST = option_env!("MEILISEARCH_HOST").unwrap_or("http://localhost:7700"); /// # let MEILISEARCH_API_KEY = option_env!("MEILISEARCH_API_KEY").unwrap_or("masterKey"); /// # /// # futures::executor::block_on(async move { - /// let client = Client::new(MEILISEARCH_HOST, MEILISEARCH_API_KEY); - /// let description = "My little lovely test key".to_string(); - /// let key = KeyBuilder::new() + /// # let client = Client::new(MEILISEARCH_HOST, MEILISEARCH_API_KEY); + /// let mut keys = KeysQuery::new() + /// .with_limit(1) /// .execute(&client).await.unwrap(); /// - /// let mut key_update = KeyUpdater::new(&key.key); - /// key_update.with_description(&description).execute(&client).await; - /// - /// assert_eq!(key_update.description, Some(description)); - /// # client.delete_key(key).await.unwrap(); + /// # assert_eq!(keys.results.len(), 1); /// # }); /// ``` pub async fn execute(&self, client: &Client) -> Result { @@ -467,6 +485,8 @@ impl KeyBuilder { /// # use meilisearch_sdk::{key::KeyBuilder}; /// let mut builder = KeyBuilder::new(); /// builder.with_indexes(vec!["test", "movies"]); + /// + /// assert_eq!(vec!["test", "movies"], builder.indexes); /// ``` pub fn with_indexes( &mut self, @@ -535,11 +555,9 @@ impl KeyBuilder { /// let name = "lovely key".to_string(); /// /// let mut key = KeyBuilder::new() - /// .with_action(Action::DocumentsAdd) - /// .with_index("*") /// .execute(&client).await.unwrap(); + /// key.with_name(&name); /// - /// key.with_name(&name); /// # assert_eq!(key.name, Some(name)); /// # client.delete_key(key).await.unwrap(); /// # }); From 24ff749f7d37c448d1b03b20310adbdf42fe6001 Mon Sep 17 00:00:00 2001 From: Charlotte Vermandel Date: Wed, 10 Aug 2022 11:37:24 +0200 Subject: [PATCH 29/44] Remove dbg --- src/client.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/client.rs b/src/client.rs index b2ea3b0e..cb7f63ed 100644 --- a/src/client.rs +++ b/src/client.rs @@ -360,7 +360,6 @@ impl Client { /// let client = Client::new(MEILISEARCH_HOST, MEILISEARCH_API_KEY); /// let keys = client.get_keys().await.unwrap(); /// - /// dbg!(&keys); /// assert_eq!(keys.results.len(), 2); /// # }); /// ``` From 1b4133082721f953129dde5e767386abd640d543 Mon Sep 17 00:00:00 2001 From: Charlotte Vermandel Date: Wed, 10 Aug 2022 11:57:52 +0200 Subject: [PATCH 30/44] Add with_uid filter --- src/key.rs | 52 +++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 47 insertions(+), 5 deletions(-) diff --git a/src/key.rs b/src/key.rs index 7d1548cc..a3b7a86e 100644 --- a/src/key.rs +++ b/src/key.rs @@ -409,6 +409,8 @@ pub struct KeyBuilder { pub actions: Vec, pub description: Option, pub name: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub uid: Option, #[serde(with = "time::serde::rfc3339::option")] pub expires_at: Option, pub indexes: Vec, @@ -429,6 +431,7 @@ impl KeyBuilder { description: None, name: None, expires_at: None, + uid: None, indexes: Vec::new(), } } @@ -482,11 +485,22 @@ impl KeyBuilder { /// # Example /// /// ``` - /// # use meilisearch_sdk::{key::KeyBuilder}; - /// let mut builder = KeyBuilder::new(); - /// builder.with_indexes(vec!["test", "movies"]); + /// # use meilisearch_sdk::{key::KeyBuilder, client::Client}; + /// # + /// # let MEILISEARCH_HOST = option_env!("MEILISEARCH_HOST").unwrap_or("http://localhost:7700"); + /// # let MEILISEARCH_API_KEY = option_env!("MEILISEARCH_API_KEY").unwrap_or("masterKey"); + /// # + /// # futures::executor::block_on(async move { + /// # let client = Client::new(MEILISEARCH_HOST, MEILISEARCH_API_KEY); + /// let mut key = KeyBuilder::new() + /// .with_indexes(vec!["test", "movies"]) + /// .execute(&client) + /// .await + /// .unwrap(); /// - /// assert_eq!(vec!["test", "movies"], builder.indexes); + /// assert_eq!(vec!["test", "movies"], key.indexes); + /// # client.delete_key(key).await.unwrap(); + /// # }); /// ``` pub fn with_indexes( &mut self, @@ -555,8 +569,8 @@ impl KeyBuilder { /// let name = "lovely key".to_string(); /// /// let mut key = KeyBuilder::new() + /// .with_name(&name) /// .execute(&client).await.unwrap(); - /// key.with_name(&name); /// /// # assert_eq!(key.name, Some(name)); /// # client.delete_key(key).await.unwrap(); @@ -567,6 +581,34 @@ impl KeyBuilder { self } + /// Add an uid to the key. + /// + /// # Example + /// + /// ``` + /// # use meilisearch_sdk::{key::KeyBuilder, key::Action, client::Client}; + /// # + /// # let MEILISEARCH_HOST = option_env!("MEILISEARCH_HOST").unwrap_or("http://localhost:7700"); + /// # let MEILISEARCH_API_KEY = option_env!("MEILISEARCH_API_KEY").unwrap_or("masterKey"); + /// # + /// # futures::executor::block_on(async move { + /// # let client = Client::new(MEILISEARCH_HOST, MEILISEARCH_API_KEY); + /// let uid = "93bcd7fb-2196-4fd9-acb7-3fca8a96e78f".to_string(); + /// + /// let mut key = KeyBuilder::new() + /// .with_uid(&uid) + /// .execute(&client).await.unwrap(); + /// + /// + /// # assert_eq!(key.uid, uid); + /// # client.delete_key(key).await.unwrap(); + /// # }); + /// ``` + pub fn with_uid(&mut self, desc: impl AsRef) -> &mut Self { + self.uid = Some(desc.as_ref().to_string()); + self + } + /// Create a [Key] from the builder. /// /// # Example From f6f821dadaf224574d4340c5570717f5ffe614ec Mon Sep 17 00:00:00 2001 From: Charlotte Vermandel Date: Wed, 10 Aug 2022 12:04:18 +0200 Subject: [PATCH 31/44] Add new actions on key creation --- src/key.rs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/key.rs b/src/key.rs index a3b7a86e..31188ab4 100644 --- a/src/key.rs +++ b/src/key.rs @@ -691,6 +691,18 @@ pub enum Action { /// Provides access to the [get Meilisearch version](https://docs.meilisearch.com/reference/api/version.md#get-version-of-meilisearch) endpoint. #[serde(rename = "version")] Version, + // Provides access to the [get Key](https://docs.meilisearch.com/reference/api/keys.html#get-one-key) and [get Keys](https://docs.meilisearch.com/reference/api/keys.html#get-all-keys) endpoints. + #[serde(rename = "keys.get")] + KeyGet, + // Provides access to the [create key](https://docs.meilisearch.com/reference/api/keys.html#create-a-key) endpoint. + #[serde(rename = "keys.create")] + KeyCreate, + // Provides access to the [update key](https://docs.meilisearch.com/reference/api/keys.html#update-a-key) endpoint. + #[serde(rename = "keys.update")] + KeyUpdate, + // Provides access to the [delete key](https://docs.meilisearch.com/reference/api/keys.html#delete-a-key) endpoint. + #[serde(rename = "keys.delete")] + KeyDelete, } #[derive(Debug, Clone, Deserialize)] From 710b2d6deef1c47062c958ea80d5c8bc5e482e36 Mon Sep 17 00:00:00 2001 From: cvermand <33010418+bidoubiwa@users.noreply.github.com> Date: Wed, 10 Aug 2022 17:01:57 +0200 Subject: [PATCH 32/44] Remove new line at the start of docs --- src/key.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/key.rs b/src/key.rs index 31188ab4..51eba9db 100644 --- a/src/key.rs +++ b/src/key.rs @@ -185,7 +185,6 @@ impl KeyUpdater { /// # /// # futures::executor::block_on(async move { /// # let client = Client::new(MEILISEARCH_HOST, MEILISEARCH_API_KEY); - /// /// let mut new_key = KeyBuilder::new() /// .execute(&client) /// .await From 54d29ebec63da143cf191d896285f272e13031ae Mon Sep 17 00:00:00 2001 From: Charlotte Vermandel Date: Wed, 10 Aug 2022 17:09:57 +0200 Subject: [PATCH 33/44] Fix clippy errors --- src/key.rs | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/src/key.rs b/src/key.rs index 31188ab4..420d05ce 100644 --- a/src/key.rs +++ b/src/key.rs @@ -281,7 +281,7 @@ impl AsRef for KeyUpdater { } } -#[derive(Debug, Serialize, Clone)] +#[derive(Debug, Serialize, Clone, Default)] #[serde(rename_all = "camelCase")] pub struct KeysQuery { /// The number of documents to skip. @@ -302,11 +302,16 @@ pub struct KeysQuery { } impl KeysQuery { + /// Create a [KeysQuery] with only a description. + /// + /// # Example + /// + /// ``` + /// # use meilisearch_sdk::{key::KeysQuery}; + /// let builder = KeysQuery::new(); + /// ``` pub fn new() -> KeysQuery { - KeysQuery { - offset: None, - limit: None, - } + Self::default() } /// Specify the offset. @@ -328,7 +333,7 @@ impl KeysQuery { /// # assert_eq!(keys.results.len(), 1); /// # }); /// ``` - pub fn with_offset<'b>(&'b mut self, offset: usize) -> &'b mut KeysQuery { + pub fn with_offset(&mut self, offset: usize) -> &mut KeysQuery { self.offset = Some(offset); self } @@ -352,7 +357,7 @@ impl KeysQuery { /// # assert_eq!(keys.results.len(), 1); /// # }); /// ``` - pub fn with_limit<'b>(&'b mut self, limit: usize) -> &'b mut KeysQuery { + pub fn with_limit(&mut self, limit: usize) -> &mut KeysQuery { self.limit = Some(limit); self } @@ -403,11 +408,13 @@ impl KeysQuery { /// # client.delete_key(key).await.unwrap(); /// # }); /// ``` -#[derive(Debug, Serialize)] +#[derive(Debug, Serialize, Default)] #[serde(rename_all = "camelCase")] pub struct KeyBuilder { pub actions: Vec, + #[serde(skip_serializing_if = "Option::is_none")] pub description: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub name: Option, #[serde(skip_serializing_if = "Option::is_none")] pub uid: Option, @@ -417,7 +424,7 @@ pub struct KeyBuilder { } impl KeyBuilder { - /// Create a [KeyBuilder] with only a description. + /// Create a [KeyBuilder]. /// /// # Example /// @@ -426,14 +433,7 @@ impl KeyBuilder { /// let builder = KeyBuilder::new(); /// ``` pub fn new() -> KeyBuilder { - Self { - actions: Vec::new(), - description: None, - name: None, - expires_at: None, - uid: None, - indexes: Vec::new(), - } + Self::default() } /// Declare a set of actions the [Key] will be able to execute. From 398975824ad4b3525e75c25af51e00ae647a1404 Mon Sep 17 00:00:00 2001 From: Charlotte Vermandel Date: Wed, 10 Aug 2022 17:11:57 +0200 Subject: [PATCH 34/44] Rename type in Task structure --- src/tasks.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/tasks.rs b/src/tasks.rs index fb55ba8b..1b6e00ad 100644 --- a/src/tasks.rs +++ b/src/tasks.rs @@ -403,8 +403,8 @@ pub struct TasksQuery<'a> { #[serde(skip_serializing_if = "Option::is_none")] pub status: Option>, // Types array to only retrieve the tasks with these [TaskType]. - #[serde(skip_serializing_if = "Option::is_none")] - pub r#type: Option>, + #[serde(skip_serializing_if = "Option::is_none", rename = "type")] + pub task_type: Option>, // Maximum number of tasks to return #[serde(skip_serializing_if = "Option::is_none")] pub limit: Option, @@ -420,7 +420,7 @@ impl<'a> TasksQuery<'a> { client, index_uid: None, status: None, - r#type: None, + task_type: None, limit: None, from: None, } @@ -441,9 +441,9 @@ impl<'a> TasksQuery<'a> { } pub fn with_type<'b>( &'b mut self, - r#type: impl IntoIterator, + task_type: impl IntoIterator, ) -> &'b mut TasksQuery<'a> { - self.r#type = Some(r#type.into_iter().collect()); + self.task_type = Some(task_type.into_iter().collect()); self } pub fn with_limit<'b>(&'b mut self, limit: u32) -> &'b mut TasksQuery<'a> { From 668ba1338159f495b00c3f8e8b73e14a1f10e364 Mon Sep 17 00:00:00 2001 From: Charlotte Vermandel Date: Wed, 10 Aug 2022 17:14:16 +0200 Subject: [PATCH 35/44] Removed useless newlines --- src/client.rs | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/client.rs b/src/client.rs index acc543b7..450bb583 100644 --- a/src/client.rs +++ b/src/client.rs @@ -428,11 +428,11 @@ impl Client { /// # let MEILISEARCH_API_KEY = option_env!("MEILISEARCH_API_KEY").unwrap_or("masterKey"); /// # /// # futures::executor::block_on(async move { - /// /// let client = Client::new(MEILISEARCH_HOST, MEILISEARCH_API_KEY); /// let mut key = KeyBuilder::new("create_key"); /// key.with_index("*").with_action(Action::DocumentsAdd); /// let key = client.create_key(key).await.unwrap(); + /// /// assert_eq!(key.description, "create_key"); /// # client.delete_key(key).await.unwrap(); /// # }); @@ -620,12 +620,11 @@ impl Client { /// # /// # futures::executor::block_on(async move { /// # let client = client::Client::new(MEILISEARCH_HOST, MEILISEARCH_API_KEY); - /// /// let mut query = tasks::TasksQuery::new(&client); /// query.with_index_uid(["get_tasks_with"]); /// let tasks = client.get_tasks_with(&query).await.unwrap(); /// - /// assert!(tasks.results.len() > 0); + /// # assert!(tasks.results.len() > 0); /// # client.index("get_tasks_with").delete().await.unwrap().wait_for_completion(&client, None, None).await.unwrap(); /// # }); /// ``` @@ -656,10 +655,9 @@ impl Client { /// # /// # futures::executor::block_on(async move { /// # let client = client::Client::new(MEILISEARCH_HOST, MEILISEARCH_API_KEY); - /// /// let tasks = client.get_tasks().await.unwrap(); /// - /// assert!(tasks.results.len() > 0); + /// # assert!(tasks.results.len() > 0); /// # client.index("get_tasks").delete().await.unwrap().wait_for_completion(&client, None, None).await.unwrap(); /// # }); /// ``` From ac953292e3e008c927ae5657a7cc42843c046413 Mon Sep 17 00:00:00 2001 From: Charlotte Vermandel Date: Wed, 10 Aug 2022 17:14:24 +0200 Subject: [PATCH 36/44] Fix typo in comment --- src/tasks.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tasks.rs b/src/tasks.rs index 1b6e00ad..6467115c 100644 --- a/src/tasks.rs +++ b/src/tasks.rs @@ -408,7 +408,7 @@ pub struct TasksQuery<'a> { // Maximum number of tasks to return #[serde(skip_serializing_if = "Option::is_none")] pub limit: Option, - // The if og the first task uid that should be returned + // The first task uid that should be returned #[serde(skip_serializing_if = "Option::is_none")] pub from: Option, } From 66bd1a5ed2af6b59e3eb668c12fbc77bc6705092 Mon Sep 17 00:00:00 2001 From: Charlotte Vermandel Date: Wed, 10 Aug 2022 17:14:36 +0200 Subject: [PATCH 37/44] Add missing semi-column --- src/search.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/search.rs b/src/search.rs index fe2fbfca..200c8de2 100644 --- a/src/search.rs +++ b/src/search.rs @@ -113,7 +113,7 @@ type AttributeToCrop<'a> = (&'a str, Option); /// .with_offset(42) /// .with_limit(21) /// -/// let res = query.execute().await?.unwrap() +/// let res = query.execute().await?.unwrap(); /// ``` /// /// ``` From 027181b0ed863bd527525e88487ec34dbada9ff9 Mon Sep 17 00:00:00 2001 From: Charlotte Vermandel Date: Mon, 22 Aug 2022 17:21:32 +0200 Subject: [PATCH 38/44] Improve doc comments --- src/client.rs | 3 +-- src/key.rs | 8 ++++---- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/client.rs b/src/client.rs index 437d43bb..3cc2cea4 100644 --- a/src/client.rs +++ b/src/client.rs @@ -392,8 +392,7 @@ impl Client { /// let client = Client::new(MEILISEARCH_HOST, MEILISEARCH_API_KEY); /// # let key = client.get_keys().await.unwrap().results.into_iter() /// .find(|k| k.name.as_ref().map_or(false, |name| name.starts_with("Default Search API Key"))); - /// let key_id = // enter your API key here, for the example we'll say we entered our search API key. - /// # key.unwrap().key; + /// let key_id = key.unwrap().key // enter your API key here, for the example we use the search API key. /// let key = client.get_key(key_id).await.unwrap(); /// /// assert_eq!(key.name, Some("Default Search API Key".to_string())); diff --git a/src/key.rs b/src/key.rs index e01cf84b..c1d5e6d9 100644 --- a/src/key.rs +++ b/src/key.rs @@ -240,7 +240,7 @@ impl KeyUpdater { self } - /// Update a Key using the [KeyUpdater]. + /// Update a [Key] using the [KeyUpdater]. /// /// # Example /// @@ -259,7 +259,7 @@ impl KeyUpdater { /// let mut key_update = KeyUpdater::new(&key.key); /// key_update.with_description(&description).execute(&client).await; /// - /// assert_eq!(key_update.description, Some(description)); + /// # assert_eq!(key_update.description, Some(description)); /// # client.delete_key(key).await.unwrap(); /// # }); /// ``` @@ -403,7 +403,7 @@ impl KeysQuery { /// .with_description(&description) /// .execute(&client).await.unwrap(); /// -/// assert_eq!(key.description, Some(description)); +/// # assert_eq!(key.description, Some(description)); /// # client.delete_key(key).await.unwrap(); /// # }); /// ``` @@ -625,7 +625,7 @@ impl KeyBuilder { /// .with_description(&description) /// .execute(&client).await.unwrap(); /// - /// assert_eq!(key.description, Some(description)); + /// # assert_eq!(key.description, Some(description)); /// # client.delete_key(key).await.unwrap(); /// # }); /// ``` From b80815639da41fc1fc9e79655b29736a2f770442 Mon Sep 17 00:00:00 2001 From: Charlotte Vermandel Date: Wed, 24 Aug 2022 16:46:05 +0200 Subject: [PATCH 39/44] Fix Keys actions --- src/key.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/key.rs b/src/key.rs index c1d5e6d9..7886c775 100644 --- a/src/key.rs +++ b/src/key.rs @@ -658,7 +658,7 @@ pub enum Action { #[serde(rename = "documents.delete")] DocumentsDelete, /// Provides access to the [create index](https://docs.meilisearch.com/reference/api/indexes.md#create-an-index) endpoint. - #[serde(rename = "indexes.execute")] + #[serde(rename = "indexes.create")] IndexesCreate, /// Provides access to the [get one index](https://docs.meilisearch.com/reference/api/indexes.md#get-one-index) and [list all indexes](https://docs.meilisearch.com/reference/api/indexes.md#list-all-indexes) endpoints. **Non-authorized `indexes` will be omitted from the response**. #[serde(rename = "indexes.get")] @@ -682,7 +682,7 @@ pub enum Action { #[serde(rename = "stats.get")] StatsGet, /// Provides access to the [create dump](https://docs.meilisearch.com/reference/api/dump.md#create-a-dump) endpoint. **Not restricted by `indexes`.** - #[serde(rename = "dumps.execute")] + #[serde(rename = "dumps.create")] DumpsCreate, /// Provides access to the [get dump status](https://docs.meilisearch.com/reference/api/dump.md#get-dump-status) endpoint. **Not restricted by `indexes`.** #[serde(rename = "dumps.get")] From de4be8fd94b9954c47151e7c237df439aea0ee2c Mon Sep 17 00:00:00 2001 From: Charlotte Vermandel Date: Wed, 24 Aug 2022 16:46:51 +0200 Subject: [PATCH 40/44] Un hide assert in execute fonction of key --- src/key.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/key.rs b/src/key.rs index 7886c775..a1787273 100644 --- a/src/key.rs +++ b/src/key.rs @@ -259,7 +259,7 @@ impl KeyUpdater { /// let mut key_update = KeyUpdater::new(&key.key); /// key_update.with_description(&description).execute(&client).await; /// - /// # assert_eq!(key_update.description, Some(description)); + /// assert_eq!(key_update.description, Some(description)); /// # client.delete_key(key).await.unwrap(); /// # }); /// ``` From a55739fdff9ecae86eac9f00632278071cdb3e43 Mon Sep 17 00:00:00 2001 From: Charlotte Vermandel Date: Wed, 24 Aug 2022 16:47:28 +0200 Subject: [PATCH 41/44] Remove useless comment --- src/client.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/client.rs b/src/client.rs index 3cc2cea4..9afd5cb2 100644 --- a/src/client.rs +++ b/src/client.rs @@ -507,7 +507,7 @@ impl Client { request::<&KeyUpdater, Key>( &format!("{}/keys/{}", self.host, key.as_ref().key), &self.api_key, - Method::Patch(key.as_ref()), // name and description + Method::Patch(key.as_ref()), 200, ) .await From 7571d61a7fc5f99162db5b23c1761c9afd66e6b9 Mon Sep 17 00:00:00 2001 From: Charlotte Vermandel Date: Wed, 24 Aug 2022 16:55:53 +0200 Subject: [PATCH 42/44] Remove flacky test --- src/client.rs | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/client.rs b/src/client.rs index 9afd5cb2..cdb326f8 100644 --- a/src/client.rs +++ b/src/client.rs @@ -845,18 +845,15 @@ mod tests { async fn test_get_tasks_with_params(client: Client) { let query = TasksQuery::new(&client); let tasks = client.get_tasks_with(&query).await.unwrap(); + assert!(tasks.results.len() >= 2); } #[meilisearch_test] async fn test_get_keys(client: Client) { let keys = client.get_keys().await.unwrap(); + assert!(keys.results.len() >= 2); - assert!(keys.results.iter().any(|k| k.description - != Some("Default Search API Key (Use it to search from the frontend)".to_string()))); - assert!(keys.results.iter().any( - |k| k.description != Some("Default Admin API Key (Use it for all other operations. Caution! Do not use it on a public frontend)".to_string()) - )); } #[meilisearch_test] From 05ec52a2fb52d084b783036de17fe59e9d19c2ce Mon Sep 17 00:00:00 2001 From: Charlotte Vermandel Date: Wed, 24 Aug 2022 17:07:36 +0200 Subject: [PATCH 43/44] Use name parameter instead of hardcoded name in key tests --- src/client.rs | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/src/client.rs b/src/client.rs index cdb326f8..bd1e2812 100644 --- a/src/client.rs +++ b/src/client.rs @@ -857,18 +857,23 @@ mod tests { } #[meilisearch_test] - async fn test_delete_key(client: Client) { + async fn test_delete_key(client: Client, name: String) { let mut key = KeyBuilder::new(); - key.with_name("test_delete_key"); + key.with_name(&name); let key = client.create_key(key).await.unwrap(); client.delete_key(&key).await.unwrap(); - let keys = client.get_keys().await.unwrap(); + let keys = KeysQuery::new() + .with_limit(10000) + .execute(&client) + .await + .unwrap(); + assert!(keys.results.iter().all(|k| k.key != key.key)); } #[meilisearch_test] - async fn test_error_delete_key(mut client: Client) { + async fn test_error_delete_key(mut client: Client, name: String) { // ==> accessing a key that does not exist let error = client.delete_key("invalid_key").await.unwrap_err(); assert!(matches!( @@ -882,7 +887,7 @@ mod tests { // ==> executing the action without enough right let mut key = KeyBuilder::new(); - key.with_name("test_error_delete_key"); + key.with_name(&name); let key = client.create_key(key).await.unwrap(); let master_key = client.api_key.clone(); @@ -915,18 +920,18 @@ mod tests { } #[meilisearch_test] - async fn test_create_key(client: Client, description: String) { + async fn test_create_key(client: Client, name: String) { let expires_at = OffsetDateTime::now_utc() + time::Duration::HOUR; let mut key = KeyBuilder::new(); key.with_action(Action::DocumentsAdd) - .with_name("test_create_key") + .with_name(&name) .with_expires_at(expires_at.clone()) - .with_description(&description) + .with_description("a description") .with_index("*"); let key = client.create_key(key).await.unwrap(); assert_eq!(key.actions, vec![Action::DocumentsAdd]); - assert_eq!(&key.description, &Some(description)); + assert_eq!(&key.name, &Some(name)); // We can't compare the two timestamp directly because of some nanoseconds imprecision with the floats assert_eq!( key.expires_at.unwrap().unix_timestamp(), @@ -938,7 +943,7 @@ mod tests { } #[meilisearch_test] - async fn test_error_create_key(mut client: Client) { + async fn test_error_create_key(mut client: Client, name: String) { // ==> Invalid index name /* TODO: uncomment once meilisearch fix this bug: https://github.com/meilisearch/meilisearch/issues/2158 let mut key = KeyBuilder::new(); @@ -957,7 +962,7 @@ mod tests { // ==> executing the action without enough right let mut no_right_key = KeyBuilder::new(); - no_right_key.with_name("test_error_create_key"); + no_right_key.with_name(&format!("{name}_1")); let no_right_key = client.create_key(no_right_key).await.unwrap(); // backup the master key for cleanup at the end of the test @@ -965,7 +970,7 @@ mod tests { client.api_key = Arc::new(no_right_key.key.clone()); let mut key = KeyBuilder::new(); - key.with_name("test_error_create_key_2"); + key.with_name(format!("{name}_2")); let error = client.create_key(key).await.unwrap_err(); assert!(matches!( From 6e588400114f0d896ef55c59183a159d483d73e3 Mon Sep 17 00:00:00 2001 From: cvermand <33010418+bidoubiwa@users.noreply.github.com> Date: Wed, 24 Aug 2022 17:08:04 +0200 Subject: [PATCH 44/44] Update src/key.rs Co-authored-by: Tamo --- src/key.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/key.rs b/src/key.rs index a1787273..ab0d6712 100644 --- a/src/key.rs +++ b/src/key.rs @@ -690,16 +690,16 @@ pub enum Action { /// Provides access to the [get Meilisearch version](https://docs.meilisearch.com/reference/api/version.md#get-version-of-meilisearch) endpoint. #[serde(rename = "version")] Version, - // Provides access to the [get Key](https://docs.meilisearch.com/reference/api/keys.html#get-one-key) and [get Keys](https://docs.meilisearch.com/reference/api/keys.html#get-all-keys) endpoints. + /// Provides access to the [get Key](https://docs.meilisearch.com/reference/api/keys.html#get-one-key) and [get Keys](https://docs.meilisearch.com/reference/api/keys.html#get-all-keys) endpoints. #[serde(rename = "keys.get")] KeyGet, - // Provides access to the [create key](https://docs.meilisearch.com/reference/api/keys.html#create-a-key) endpoint. + /// Provides access to the [create key](https://docs.meilisearch.com/reference/api/keys.html#create-a-key) endpoint. #[serde(rename = "keys.create")] KeyCreate, - // Provides access to the [update key](https://docs.meilisearch.com/reference/api/keys.html#update-a-key) endpoint. + /// Provides access to the [update key](https://docs.meilisearch.com/reference/api/keys.html#update-a-key) endpoint. #[serde(rename = "keys.update")] KeyUpdate, - // Provides access to the [delete key](https://docs.meilisearch.com/reference/api/keys.html#delete-a-key) endpoint. + /// Provides access to the [delete key](https://docs.meilisearch.com/reference/api/keys.html#delete-a-key) endpoint. #[serde(rename = "keys.delete")] KeyDelete, }