diff --git a/meilisearch-http/src/routes/indexes/documents.rs b/meilisearch-http/src/routes/indexes/documents.rs index b5437c093..821b962ea 100644 --- a/meilisearch-http/src/routes/indexes/documents.rs +++ b/meilisearch-http/src/routes/indexes/documents.rs @@ -170,7 +170,7 @@ pub async fn add_documents( format: DocumentAdditionFormat::Json, }; let update_status = meilisearch - .register_update(path.index_uid.as_str(), update) + .register_update(path.into_inner().index_uid, update) .await?; debug!("returns: {:?}", update_status); @@ -193,7 +193,7 @@ pub async fn update_documents( format: DocumentAdditionFormat::Json, }; let update_status = meilisearch - .register_update(path.index_uid.as_str(), update) + .register_update(path.into_inner().index_uid, update) .await?; debug!("returns: {:?}", update_status); diff --git a/meilisearch-http/src/routes/indexes/mod.rs b/meilisearch-http/src/routes/indexes/mod.rs index 2bf8afa08..59ad6fa0f 100644 --- a/meilisearch-http/src/routes/indexes/mod.rs +++ b/meilisearch-http/src/routes/indexes/mod.rs @@ -32,7 +32,7 @@ pub fn configure(cfg: &mut web::ServiceConfig) { .service(web::scope("/documents").configure(documents::configure)) .service(web::scope("/search").configure(search::configure)) .service(web::scope("/updates").configure(updates::configure)) - //.service(web::scope("/settings").configure(settings::configure)), + .service(web::scope("/settings").configure(settings::configure)), ); } diff --git a/meilisearch-http/src/routes/indexes/settings.rs b/meilisearch-http/src/routes/indexes/settings.rs index 07a96003f..180be4108 100644 --- a/meilisearch-http/src/routes/indexes/settings.rs +++ b/meilisearch-http/src/routes/indexes/settings.rs @@ -1,184 +1,191 @@ -//use log::debug; +use log::debug; -//use crate::extractors::authentication::{policies::*, GuardedData}; -//use crate::index::Settings; -//use crate::Data; -//use crate::error::ResponseError; +use actix_web::{HttpResponse, web}; +use meilisearch_lib::MeiliSearch; +use meilisearch_lib::index::{Settings, Unchecked}; +use meilisearch_lib::index_controller::Update; -//#[macro_export] -//macro_rules! make_setting_route { - //($route:literal, $type:ty, $attr:ident, $camelcase_attr:literal) => { - //pub mod $attr { - //use log::debug; - //use actix_web::{web, HttpResponse, Resource}; +use crate::extractors::authentication::{policies::*, GuardedData}; +use crate::error::ResponseError; - //use milli::update::Setting; +#[macro_export] +macro_rules! make_setting_route { + ($route:literal, $type:ty, $attr:ident, $camelcase_attr:literal) => { + pub mod $attr { + use log::debug; + use actix_web::{web, HttpResponse, Resource}; - //use crate::data; - //use crate::error::ResponseError; - //use crate::index::Settings; - //use crate::extractors::authentication::{GuardedData, policies::*}; + use milli::update::Setting; + use meilisearch_lib::{MeiliSearch, index::Settings, index_controller::Update}; - //pub async fn delete( - //data: GuardedData, - //index_uid: web::Path, - //) -> Result { - //use crate::index::Settings; - //let settings = Settings { - //$attr: Setting::Reset, - //..Default::default() - //}; - //let update_status = data.update_settings(index_uid.into_inner(), settings, false).await?; - //debug!("returns: {:?}", update_status); - //Ok(HttpResponse::Accepted().json(serde_json::json!({ "updateId": update_status.id() }))) - //} + use crate::error::ResponseError; + use crate::extractors::authentication::{GuardedData, policies::*}; - //pub async fn update( - //data: GuardedData, - //index_uid: actix_web::web::Path, - //body: actix_web::web::Json>, - //) -> std::result::Result { - //let settings = Settings { - //$attr: match body.into_inner() { - //Some(inner_body) => Setting::Set(inner_body), - //None => Setting::Reset - //}, - //..Default::default() - //}; + pub async fn delete( + meilisearch: GuardedData, + index_uid: web::Path, + ) -> Result { + let settings = Settings { + $attr: Setting::Reset, + ..Default::default() + }; + let update = Update::Settings(settings); + let update_status = meilisearch.register_update(index_uid.into_inner(), update).await?; + debug!("returns: {:?}", update_status); + Ok(HttpResponse::Accepted().json(serde_json::json!({ "updateId": update_status.id() }))) + } - //let update_status = data.update_settings(index_uid.into_inner(), settings, true).await?; - //debug!("returns: {:?}", update_status); - //Ok(HttpResponse::Accepted().json(serde_json::json!({ "updateId": update_status.id() }))) - //} + pub async fn update( + meilisearch: GuardedData, + index_uid: actix_web::web::Path, + body: actix_web::web::Json>, + ) -> std::result::Result { + let settings = Settings { + $attr: match body.into_inner() { + Some(inner_body) => Setting::Set(inner_body), + None => Setting::Reset + }, + ..Default::default() + }; - //pub async fn get( - //data: GuardedData, - //index_uid: actix_web::web::Path, - //) -> std::result::Result { - //let settings = data.settings(index_uid.into_inner()).await?; - //debug!("returns: {:?}", settings); - //let mut json = serde_json::json!(&settings); - //let val = json[$camelcase_attr].take(); - //Ok(HttpResponse::Ok().json(val)) - //} + let update = Update::Settings(settings); + let update_status = meilisearch.register_update(index_uid.into_inner(), update).await?; + debug!("returns: {:?}", update_status); + Ok(HttpResponse::Accepted().json(serde_json::json!({ "updateId": update_status.id() }))) + } - //pub fn resources() -> Resource { - //Resource::new($route) - //.route(web::get().to(get)) - //.route(web::post().to(update)) - //.route(web::delete().to(delete)) - //} - //} - //}; -//} + pub async fn get( + meilisearch: GuardedData, + index_uid: actix_web::web::Path, + ) -> std::result::Result { + let settings = meilisearch.settings(index_uid.into_inner()).await?; + debug!("returns: {:?}", settings); + let mut json = serde_json::json!(&settings); + let val = json[$camelcase_attr].take(); + Ok(HttpResponse::Ok().json(val)) + } -//make_setting_route!( - //"/filterable-attributes", - //std::collections::BTreeSet, - //filterable_attributes, - //"filterableAttributes" -//); + pub fn resources() -> Resource { + Resource::new($route) + .route(web::get().to(get)) + .route(web::post().to(update)) + .route(web::delete().to(delete)) + } + } + }; +} -//make_setting_route!( - //"/sortable-attributes", - //std::collections::BTreeSet, - //sortable_attributes, - //"sortableAttributes" -//); +make_setting_route!( + "/filterable-attributes", + std::collections::BTreeSet, + filterable_attributes, + "filterableAttributes" +); -//make_setting_route!( - //"/displayed-attributes", - //Vec, - //displayed_attributes, - //"displayedAttributes" -//); +make_setting_route!( + "/sortable-attributes", + std::collections::BTreeSet, + sortable_attributes, + "sortableAttributes" +); -//make_setting_route!( - //"/searchable-attributes", - //Vec, - //searchable_attributes, - //"searchableAttributes" -//); +make_setting_route!( + "/displayed-attributes", + Vec, + displayed_attributes, + "displayedAttributes" +); -//make_setting_route!( - //"/stop-words", - //std::collections::BTreeSet, - //stop_words, - //"stopWords" -//); +make_setting_route!( + "/searchable-attributes", + Vec, + searchable_attributes, + "searchableAttributes" +); -//make_setting_route!( - //"/synonyms", - //std::collections::BTreeMap>, - //synonyms, - //"synonyms" -//); +make_setting_route!( + "/stop-words", + std::collections::BTreeSet, + stop_words, + "stopWords" +); -//make_setting_route!( - //"/distinct-attribute", - //String, - //distinct_attribute, - //"distinctAttribute" -//); +make_setting_route!( + "/synonyms", + std::collections::BTreeMap>, + synonyms, + "synonyms" +); -//make_setting_route!("/ranking-rules", Vec, ranking_rules, "rankingRules"); +make_setting_route!( + "/distinct-attribute", + String, + distinct_attribute, + "distinctAttribute" +); -//macro_rules! generate_configure { - //($($mod:ident),*) => { - //pub fn configure(cfg: &mut web::ServiceConfig) { - //cfg.service( - //web::resource("") - ////.route(web::post().to(update_all)) - //.route(web::get().to(get_all)) - ////.route(web::delete().to(delete_all))) - //$(.service($mod::resources()))*; - //} - //}; -//} +make_setting_route!("/ranking-rules", Vec, ranking_rules, "rankingRules"); -//generate_configure!( - //filterable_attributes, - //sortable_attributes, - //displayed_attributes, - //searchable_attributes, - //distinct_attribute, - //stop_words, - //synonyms, - //ranking_rules -//); +macro_rules! generate_configure { + ($($mod:ident),*) => { + pub fn configure(cfg: &mut web::ServiceConfig) { + cfg.service( + web::resource("") + .route(web::post().to(update_all)) + .route(web::get().to(get_all)) + .route(web::delete().to(delete_all))) + $(.service($mod::resources()))*; + } + }; +} -//pub async fn update_all( - //data: GuardedData, - //index_uid: web::Path, - //body: web::Json>, -//) -> Result { - //let settings = body.into_inner().check(); - //let update_result = data - //.update_settings(index_uid.into_inner(), settings, true) - //.await?; - //let json = serde_json::json!({ "updateId": update_result.id() }); - //debug!("returns: {:?}", json); - //Ok(HttpResponse::Accepted().json(json)) -//} +generate_configure!( + filterable_attributes, + sortable_attributes, + displayed_attributes, + searchable_attributes, + distinct_attribute, + stop_words, + synonyms, + ranking_rules +); -//pub async fn get_all( - //data: GuardedData, - //index_uid: web::Path, -//) -> Result { - //let settings = data.settings(index_uid.into_inner()).await?; - //debug!("returns: {:?}", settings); - //Ok(HttpResponse::Ok().json(settings)) -//} +pub async fn update_all( + meilisearch: GuardedData, + index_uid: web::Path, + body: web::Json>, +) -> Result { + let settings = body.into_inner(); -//pub async fn delete_all( - //data: GuardedData, - //index_uid: web::Path, -//) -> Result { - //let settings = Settings::cleared(); - //let update_result = data - //.update_settings(index_uid.into_inner(), settings, false) - //.await?; - //let json = serde_json::json!({ "updateId": update_result.id() }); - //debug!("returns: {:?}", json); - //Ok(HttpResponse::Accepted().json(json)) -//} + let update = Update::Settings(settings); + let update_result = meilisearch + .register_update(index_uid.into_inner(), update) + .await?; + let json = serde_json::json!({ "updateId": update_result.id() }); + debug!("returns: {:?}", json); + Ok(HttpResponse::Accepted().json(json)) +} + +pub async fn get_all( + data: GuardedData, + index_uid: web::Path, +) -> Result { + let settings = data.settings(index_uid.into_inner()).await?; + debug!("returns: {:?}", settings); + Ok(HttpResponse::Ok().json(settings)) +} + +pub async fn delete_all( + data: GuardedData, + index_uid: web::Path, +) -> Result { + let settings = Settings::cleared(); + + let update = Update::Settings(settings.into_unchecked()); + let update_result = data + .register_update(index_uid.into_inner(), update) + .await?; + let json = serde_json::json!({ "updateId": update_result.id() }); + debug!("returns: {:?}", json); + Ok(HttpResponse::Accepted().json(json)) +} diff --git a/meilisearch-http/src/routes/mod.rs b/meilisearch-http/src/routes/mod.rs index ff8681498..b30fce164 100644 --- a/meilisearch-http/src/routes/mod.rs +++ b/meilisearch-http/src/routes/mod.rs @@ -69,13 +69,13 @@ impl From<&UpdateStatus> for UpdateType { _ => unreachable!(), } } + RegisterUpdate::Settings(settings) => UpdateType::Settings { + settings: settings.clone(), + }, //UpdateMeta::ClearDocuments => UpdateType::ClearAll, //UpdateMeta::DeleteDocuments { ids } => UpdateType::DocumentsDeletion { //number: Some(ids.len()), //}, - //UpdateMeta::Settings(settings) => UpdateType::Settings { - //settings: settings.clone(), - //}, } } } diff --git a/meilisearch-lib/src/index/update_handler.rs b/meilisearch-lib/src/index/update_handler.rs index 6969b4567..07d57376d 100644 --- a/meilisearch-lib/src/index/update_handler.rs +++ b/meilisearch-lib/src/index/update_handler.rs @@ -1,10 +1,7 @@ -use crate::index::Index; use milli::update::UpdateBuilder; use milli::CompressionType; use rayon::ThreadPool; -use crate::index_controller::updates::RegisterUpdate; -use crate::index_controller::updates::status::{Failed, Processed, Processing}; use crate::options::IndexerOpts; pub struct UpdateHandler { @@ -49,24 +46,4 @@ impl UpdateHandler { update_builder.chunk_compression_type(self.chunk_compression_type); update_builder } - - pub fn handle_update( - &self, - index: &Index, - meta: Processing, - ) -> Result { - let update_id = meta.id(); - let update_builder = self.update_builder(update_id); - - let result = match meta.meta() { - RegisterUpdate::DocumentAddition { primary_key, content_uuid, method } => { - index.update_documents(*method, *content_uuid, update_builder, primary_key.as_deref()) - } - }; - - match result { - Ok(result) => Ok(meta.process(result)), - Err(e) => Err(meta.fail(e)), - } - } } diff --git a/meilisearch-lib/src/index/updates.rs b/meilisearch-lib/src/index/updates.rs index 20cf6b2ec..fca925031 100644 --- a/meilisearch-lib/src/index/updates.rs +++ b/meilisearch-lib/src/index/updates.rs @@ -8,6 +8,7 @@ use milli::update::{IndexDocumentsMethod, Setting, UpdateBuilder}; use serde::{Deserialize, Serialize, Serializer}; use uuid::Uuid; +use crate::RegisterUpdate; use crate::index_controller::updates::status::{Failed, Processed, Processing, UpdateResult}; use super::{Index, IndexMeta}; @@ -164,7 +165,27 @@ pub struct Facets { impl Index { pub fn handle_update(&self, update: Processing) -> std::result::Result { - self.update_handler.handle_update(self, update) + let update_id = update.id(); + let update_builder = self.update_handler.update_builder(update_id); + let result = (|| { + let mut txn = self.write_txn()?; + let result = match update.meta() { + RegisterUpdate::DocumentAddition { primary_key, content_uuid, method } => { + self.update_documents(&mut txn, *method, *content_uuid, update_builder, primary_key.as_deref()) + } + RegisterUpdate::Settings(settings) => { + let settings = settings.clone().check(); + self.update_settings(&mut txn, &settings, update_builder) + }, + }; + txn.commit()?; + result + })(); + + match result { + Ok(result) => Ok(update.process(result)), + Err(e) => Err(update.fail(e)), + } } pub fn update_primary_key(&self, primary_key: Option) -> Result { @@ -188,21 +209,7 @@ impl Index { } } - pub fn update_documents( - &self, - method: IndexDocumentsMethod, - content_uuid: Uuid, - update_builder: UpdateBuilder, - primary_key: Option<&str>, - ) -> Result { - let mut txn = self.write_txn()?; - let result = self.update_documents_txn(&mut txn, method, content_uuid, update_builder, primary_key)?; - txn.commit()?; - - Ok(result) - } - - pub fn update_documents_txn<'a, 'b>( + fn update_documents<'a, 'b>( &'a self, txn: &mut heed::RwTxn<'a, 'b>, method: IndexDocumentsMethod, @@ -246,86 +253,75 @@ impl Index { //.map_err(Into::into) //} - //pub fn update_settings_txn<'a, 'b>( - //&'a self, - //txn: &mut heed::RwTxn<'a, 'b>, - //settings: &Settings, - //update_builder: UpdateBuilder, - //) -> Result { - //// We must use the write transaction of the update here. - //let mut builder = update_builder.settings(txn, self); + fn update_settings<'a, 'b>( + &'a self, + txn: &mut heed::RwTxn<'a, 'b>, + settings: &Settings, + update_builder: UpdateBuilder, + ) -> Result { + // We must use the write transaction of the update here. + let mut builder = update_builder.settings(txn, self); - //match settings.searchable_attributes { - //Setting::Set(ref names) => builder.set_searchable_fields(names.clone()), - //Setting::Reset => builder.reset_searchable_fields(), - //Setting::NotSet => (), - //} + match settings.searchable_attributes { + Setting::Set(ref names) => builder.set_searchable_fields(names.clone()), + Setting::Reset => builder.reset_searchable_fields(), + Setting::NotSet => (), + } - //match settings.displayed_attributes { - //Setting::Set(ref names) => builder.set_displayed_fields(names.clone()), - //Setting::Reset => builder.reset_displayed_fields(), - //Setting::NotSet => (), - //} + match settings.displayed_attributes { + Setting::Set(ref names) => builder.set_displayed_fields(names.clone()), + Setting::Reset => builder.reset_displayed_fields(), + Setting::NotSet => (), + } - //match settings.filterable_attributes { - //Setting::Set(ref facets) => { - //builder.set_filterable_fields(facets.clone().into_iter().collect()) - //} - //Setting::Reset => builder.reset_filterable_fields(), - //Setting::NotSet => (), - //} + match settings.filterable_attributes { + Setting::Set(ref facets) => { + builder.set_filterable_fields(facets.clone().into_iter().collect()) + } + Setting::Reset => builder.reset_filterable_fields(), + Setting::NotSet => (), + } - //match settings.sortable_attributes { - //Setting::Set(ref fields) => { - //builder.set_sortable_fields(fields.iter().cloned().collect()) - //} - //Setting::Reset => builder.reset_sortable_fields(), - //Setting::NotSet => (), - //} + match settings.sortable_attributes { + Setting::Set(ref fields) => { + builder.set_sortable_fields(fields.iter().cloned().collect()) + } + Setting::Reset => builder.reset_sortable_fields(), + Setting::NotSet => (), + } - //match settings.ranking_rules { - //Setting::Set(ref criteria) => builder.set_criteria(criteria.clone()), - //Setting::Reset => builder.reset_criteria(), - //Setting::NotSet => (), - //} + match settings.ranking_rules { + Setting::Set(ref criteria) => builder.set_criteria(criteria.clone()), + Setting::Reset => builder.reset_criteria(), + Setting::NotSet => (), + } - //match settings.stop_words { - //Setting::Set(ref stop_words) => builder.set_stop_words(stop_words.clone()), - //Setting::Reset => builder.reset_stop_words(), - //Setting::NotSet => (), - //} + match settings.stop_words { + Setting::Set(ref stop_words) => builder.set_stop_words(stop_words.clone()), + Setting::Reset => builder.reset_stop_words(), + Setting::NotSet => (), + } - //match settings.synonyms { - //Setting::Set(ref synonyms) => { - //builder.set_synonyms(synonyms.clone().into_iter().collect()) - //} - //Setting::Reset => builder.reset_synonyms(), - //Setting::NotSet => (), - //} + match settings.synonyms { + Setting::Set(ref synonyms) => { + builder.set_synonyms(synonyms.clone().into_iter().collect()) + } + Setting::Reset => builder.reset_synonyms(), + Setting::NotSet => (), + } - //match settings.distinct_attribute { - //Setting::Set(ref attr) => builder.set_distinct_field(attr.clone()), - //Setting::Reset => builder.reset_distinct_field(), - //Setting::NotSet => (), - //} + match settings.distinct_attribute { + Setting::Set(ref attr) => builder.set_distinct_field(attr.clone()), + Setting::Reset => builder.reset_distinct_field(), + Setting::NotSet => (), + } - //builder.execute(|indexing_step, update_id| { - //debug!("update {}: {:?}", update_id, indexing_step) - //})?; + builder.execute(|indexing_step, update_id| { + debug!("update {}: {:?}", update_id, indexing_step) + })?; - //Ok(UpdateResult::Other) - //} - - //pub fn update_settings( - //&self, - //settings: &Settings, - //update_builder: UpdateBuilder, - //) -> Result { - //let mut txn = self.write_txn()?; - //let result = self.update_settings_txn(&mut txn, settings, update_builder)?; - //txn.commit()?; - //Ok(result) - //} + Ok(UpdateResult::Other) + } //pub fn delete_documents( //&self, diff --git a/meilisearch-lib/src/index_controller/mod.rs b/meilisearch-lib/src/index_controller/mod.rs index da108fe68..f9ff4fbbe 100644 --- a/meilisearch-lib/src/index_controller/mod.rs +++ b/meilisearch-lib/src/index_controller/mod.rs @@ -18,7 +18,7 @@ use dump_actor::DumpActorHandle; pub use dump_actor::{DumpInfo, DumpStatus}; use snapshot::load_snapshot; -use crate::index::{Checked, Document, IndexMeta, IndexStats, SearchQuery, SearchResult, Settings}; +use crate::index::{Checked, Document, IndexMeta, IndexStats, SearchQuery, SearchResult, Settings, Unchecked}; use crate::index_controller::index_resolver::create_index_resolver; use crate::options::IndexerOpts; use error::Result; @@ -95,6 +95,7 @@ pub struct Stats { #[derive(derivative::Derivative)] #[derivative(Debug)] pub enum Update { + Settings(Settings), DocumentAddition { #[derivative(Debug="ignore")] payload: Payload, @@ -242,8 +243,8 @@ impl IndexController { IndexControllerBuilder::default() } - pub async fn register_update(&self, uid: &str, update: Update) -> Result { - match self.index_resolver.get_uuid(uid.to_string()).await { + pub async fn register_update(&self, uid: String, update: Update) -> Result { + match self.index_resolver.get_uuid(uid).await { Ok(uuid) => { let update_result = UpdateMsg::update(&self.update_handle, uuid, update).await?; Ok(update_result) diff --git a/meilisearch-lib/src/index_controller/updates/mod.rs b/meilisearch-lib/src/index_controller/updates/mod.rs index 7cc38490f..30b6d98f6 100644 --- a/meilisearch-lib/src/index_controller/updates/mod.rs +++ b/meilisearch-lib/src/index_controller/updates/mod.rs @@ -24,6 +24,7 @@ use uuid::Uuid; use self::error::{Result, UpdateLoopError}; pub use self::message::UpdateMsg; use self::store::{UpdateStore, UpdateStoreInfo}; +use crate::index::{Settings, Unchecked}; use crate::index_controller::update_file_store::UpdateFileStore; use status::UpdateStatus; @@ -53,6 +54,7 @@ pub enum RegisterUpdate { method: IndexDocumentsMethod, content_uuid: Uuid, }, + Settings(Settings), } /// A wrapper type to implement read on a `Stream>`. @@ -207,6 +209,7 @@ impl UpdateLoop { content_uuid, } } + Update::Settings(settings) => RegisterUpdate::Settings(settings), }; let store = self.store.clone();