diff --git a/http-ui/src/main.rs b/http-ui/src/main.rs index a29eb8895..2ce7f8bd1 100644 --- a/http-ui/src/main.rs +++ b/http-ui/src/main.rs @@ -225,6 +225,7 @@ enum UpdateMeta { ClearDocuments, Settings(Settings), Facets(Facets), + WordsPrefixes(WordsPrefixes), } #[derive(Debug, Clone, Serialize, Deserialize)] @@ -275,6 +276,14 @@ struct Facets { min_level_size: Option, } +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(deny_unknown_fields)] +#[serde(rename_all = "camelCase")] +struct WordsPrefixes { + threshold: Option, + max_prefix_length: Option, +} + // Any value that is present is considered Some value, including null. fn deserialize_some<'de, T, D>(deserializer: D) -> Result, D::Error> where T: Deserialize<'de>, @@ -467,6 +476,21 @@ async fn main() -> anyhow::Result<()> { Ok(()) => wtxn.commit().map_err(Into::into), Err(e) => Err(e.into()) } + }, + UpdateMeta::WordsPrefixes(settings) => { + // We must use the write transaction of the update here. + let mut wtxn = index_cloned.write_txn()?; + let mut builder = update_builder.words_prefixes(&mut wtxn, &index_cloned); + if let Some(value) = settings.threshold { + builder.threshold(value); + } + if let Some(value) = settings.max_prefix_length { + builder.max_prefix_length(value); + } + match builder.execute() { + Ok(()) => wtxn.commit().map_err(Into::into), + Err(e) => Err(e.into()) + } } }; @@ -884,6 +908,19 @@ async fn main() -> anyhow::Result<()> { warp::reply() }); + let update_store_cloned = update_store.clone(); + let update_status_sender_cloned = update_status_sender.clone(); + let change_words_prefixes_route = warp::filters::method::post() + .and(warp::path!("words-prefixes")) + .and(warp::body::json()) + .map(move |settings: WordsPrefixes| { + let meta = UpdateMeta::WordsPrefixes(settings); + let update_id = update_store_cloned.register_update(&meta, &[]).unwrap(); + let _ = update_status_sender_cloned.send(UpdateStatus::Pending { update_id, meta }); + eprintln!("update {} registered", update_id); + warp::reply() + }); + let update_store_cloned = update_store.clone(); let update_status_sender_cloned = update_status_sender.clone(); let abort_update_id_route = warp::filters::method::delete() @@ -958,6 +995,7 @@ async fn main() -> anyhow::Result<()> { .or(clearing_route) .or(change_settings_route) .or(change_facet_levels_route) + .or(change_words_prefixes_route) .or(update_ws_route); let addr = SocketAddr::from_str(&opt.http_listen_addr)?; diff --git a/milli/src/update/update_builder.rs b/milli/src/update/update_builder.rs index 8d6eb034d..c966f72d2 100644 --- a/milli/src/update/update_builder.rs +++ b/milli/src/update/update_builder.rs @@ -2,7 +2,7 @@ use grenad::CompressionType; use rayon::ThreadPool; use crate::Index; -use super::{ClearDocuments, DeleteDocuments, IndexDocuments, Settings, Facets}; +use super::{ClearDocuments, DeleteDocuments, IndexDocuments, Settings, Facets, WordsPrefixes}; pub struct UpdateBuilder<'a> { pub(crate) log_every_n: Option, @@ -135,4 +135,19 @@ impl<'a> UpdateBuilder<'a> { builder } + + pub fn words_prefixes<'t, 'u, 'i>( + self, + wtxn: &'t mut heed::RwTxn<'i, 'u>, + index: &'i Index, + ) -> WordsPrefixes<'t, 'u, 'i> + { + let mut builder = WordsPrefixes::new(wtxn, index, self.update_id); + + builder.chunk_compression_type = self.chunk_compression_type; + builder.chunk_compression_level = self.chunk_compression_level; + builder.chunk_fusing_shrink_size = self.chunk_fusing_shrink_size; + + builder + } }