From efd5fd96ccc63a886005b0d42e79cd9a5aaa13f9 Mon Sep 17 00:00:00 2001 From: Mubelotix Date: Tue, 1 Jul 2025 11:02:42 +0200 Subject: [PATCH] Add the overrideSettings parameter --- .../src/scheduler/process_export.rs | 83 +++++++++++++------ crates/meilisearch-types/src/error.rs | 1 + crates/meilisearch-types/src/tasks.rs | 1 + crates/meilisearch/src/routes/export.rs | 8 +- 4 files changed, 65 insertions(+), 28 deletions(-) diff --git a/crates/index-scheduler/src/scheduler/process_export.rs b/crates/index-scheduler/src/scheduler/process_export.rs index bf2917b73..19b2bf743 100644 --- a/crates/index-scheduler/src/scheduler/process_export.rs +++ b/crates/index-scheduler/src/scheduler/process_export.rs @@ -59,42 +59,73 @@ impl IndexScheduler { indexes.len() as u32, )); - let ExportIndexSettings { filter } = export_settings; + let ExportIndexSettings { filter, override_settings } = export_settings; let index = self.index(uid)?; let index_rtxn = index.read_txn()?; - // Send the primary key + let url = format!("{base_url}/indexes/{uid}"); + + // First, check if the index already exists + let response = retry(&must_stop_processing, || { + let mut request = agent.get(&url); + if let Some(api_key) = api_key { + request = request.set("Authorization", &format!("Bearer {api_key}")); + } + + request.send_string("").map_err(into_backoff_error) + })?; + let already_existed = response.status() == 200; + let primary_key = index .primary_key(&index_rtxn) .map_err(|e| Error::from_milli(e.into(), Some(uid.to_string())))?; - let url = format!("{base_url}/indexes"); - retry(&must_stop_processing, || { - let mut request = agent.post(&url); - if let Some(api_key) = api_key { - request = request.set("Authorization", &format!("Bearer {api_key}")); - } - let index_param = json!({ "uid": uid, "primaryKey": primary_key }); - request.send_json(&index_param).map_err(into_backoff_error) - })?; + // Create the index + if !already_existed { + let url = format!("{base_url}/indexes"); + retry(&must_stop_processing, || { + let mut request = agent.post(&url); + if let Some(api_key) = api_key { + request = request.set("Authorization", &format!("Bearer {api_key}")); + } + let index_param = json!({ "uid": uid, "primaryKey": primary_key }); + request.send_json(&index_param).map_err(into_backoff_error) + })?; + } + + // Patch the index primary key + if already_existed && *override_settings { + let url = format!("{base_url}/indexes/{uid}"); + retry(&must_stop_processing, || { + let mut request = agent.patch(&url); + if let Some(api_key) = api_key { + request = request.set("Authorization", &format!("Bearer {api_key}")); + } + let index_param = json!({ "primaryKey": primary_key }); + request.send_json(&index_param).map_err(into_backoff_error) + })?; + } // Send the index settings - let mut settings = settings::settings(&index, &index_rtxn, SecretPolicy::RevealSecrets) - .map_err(|e| Error::from_milli(e, Some(uid.to_string())))?; - // Remove the experimental chat setting if not enabled - if self.features().check_chat_completions("exporting chat settings").is_err() { - settings.chat = Setting::NotSet; - } - // Retry logic for sending settings - let url = format!("{base_url}/indexes/{uid}/settings"); - let bearer = api_key.map(|api_key| format!("Bearer {api_key}")); - retry(&must_stop_processing, || { - let mut request = agent.patch(&url); - if let Some(bearer) = bearer.as_ref() { - request = request.set("Authorization", bearer); + if !already_existed || *override_settings { + let mut settings = + settings::settings(&index, &index_rtxn, SecretPolicy::RevealSecrets) + .map_err(|e| Error::from_milli(e, Some(uid.to_string())))?; + // Remove the experimental chat setting if not enabled + if self.features().check_chat_completions("exporting chat settings").is_err() { + settings.chat = Setting::NotSet; } - request.send_json(settings.clone()).map_err(into_backoff_error) - })?; + // Retry logic for sending settings + let url = format!("{base_url}/indexes/{uid}/settings"); + let bearer = api_key.map(|api_key| format!("Bearer {api_key}")); + retry(&must_stop_processing, || { + let mut request = agent.patch(&url); + if let Some(bearer) = bearer.as_ref() { + request = request.set("Authorization", bearer); + } + request.send_json(settings.clone()).map_err(into_backoff_error) + })?; + } let filter = filter .as_ref() diff --git a/crates/meilisearch-types/src/error.rs b/crates/meilisearch-types/src/error.rs index 1c2840084..30f6868f6 100644 --- a/crates/meilisearch-types/src/error.rs +++ b/crates/meilisearch-types/src/error.rs @@ -395,6 +395,7 @@ InvalidExportApiKey , InvalidRequest , BAD_REQU InvalidExportPayloadSize , InvalidRequest , BAD_REQUEST ; InvalidExportIndexesPatterns , InvalidRequest , BAD_REQUEST ; InvalidExportIndexFilter , InvalidRequest , BAD_REQUEST ; +InvalidExportIndexOverrideSettings , InvalidRequest , BAD_REQUEST ; // Experimental features - Chat Completions UnimplementedExternalFunctionCalling , InvalidRequest , NOT_IMPLEMENTED ; UnimplementedNonStreamingChatCompletions , InvalidRequest , NOT_IMPLEMENTED ; diff --git a/crates/meilisearch-types/src/tasks.rs b/crates/meilisearch-types/src/tasks.rs index 0618fa333..99b04f1e3 100644 --- a/crates/meilisearch-types/src/tasks.rs +++ b/crates/meilisearch-types/src/tasks.rs @@ -178,6 +178,7 @@ pub struct IndexSwap { #[serde(rename_all = "camelCase")] pub struct ExportIndexSettings { pub filter: Option, + pub override_settings: bool, } impl KindWithContent { diff --git a/crates/meilisearch/src/routes/export.rs b/crates/meilisearch/src/routes/export.rs index 31f8812c7..172a162c6 100644 --- a/crates/meilisearch/src/routes/export.rs +++ b/crates/meilisearch/src/routes/export.rs @@ -84,8 +84,8 @@ async fn export( let indexes = match indexes { Some(indexes) => indexes .into_iter() - .map(|(pattern, ExportIndexSettings { filter })| { - (pattern, DbExportIndexSettings { filter }) + .map(|(pattern, ExportIndexSettings { filter, override_settings })| { + (pattern, DbExportIndexSettings { filter, override_settings }) }) .collect(), None => BTreeMap::from([( @@ -179,4 +179,8 @@ pub struct ExportIndexSettings { #[serde(default)] #[deserr(default, error = DeserrJsonError)] pub filter: Option, + #[schema(value_type = Option, example = json!(true))] + #[serde(default)] + #[deserr(default, error = DeserrJsonError)] + pub override_settings: bool, }