From 4d819ea636e5ebbb6406e0b48879555f74d2a877 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Renault?= Date: Thu, 5 Jun 2025 10:54:46 +0200 Subject: [PATCH 01/12] Initial working version for a prompt for email --- .../src/analytics/segment_analytics.rs | 1 + crates/meilisearch/src/main.rs | 30 ++++++++++++++++++- crates/meilisearch/src/option.rs | 10 +++++++ 3 files changed, 40 insertions(+), 1 deletion(-) diff --git a/crates/meilisearch/src/analytics/segment_analytics.rs b/crates/meilisearch/src/analytics/segment_analytics.rs index ee8a9ee20..2c0121ffc 100644 --- a/crates/meilisearch/src/analytics/segment_analytics.rs +++ b/crates/meilisearch/src/analytics/segment_analytics.rs @@ -277,6 +277,7 @@ impl Infos { log_level, indexer_options, config_file_path, + contact_email: _, no_analytics: _, } = options; diff --git a/crates/meilisearch/src/main.rs b/crates/meilisearch/src/main.rs index b16dda097..cca704df5 100644 --- a/crates/meilisearch/src/main.rs +++ b/crates/meilisearch/src/main.rs @@ -21,6 +21,7 @@ use meilisearch::{ }; use meilisearch_auth::{generate_master_key, AuthController, MASTER_KEY_MIN_SIZE}; use termcolor::{Color, ColorChoice, ColorSpec, StandardStream, WriteColor}; +use tokio::io::{AsyncBufReadExt, BufReader}; use tracing::level_filters::LevelFilter; use tracing_subscriber::layer::SubscriberExt as _; use tracing_subscriber::Layer; @@ -89,10 +90,16 @@ async fn main() -> anyhow::Result<()> { } async fn try_main() -> anyhow::Result<()> { - let (opt, config_read_from) = Opt::try_build()?; + let (mut opt, config_read_from) = Opt::try_build()?; std::panic::set_hook(Box::new(on_panic)); + opt.contact_email = match opt.contact_email.as_ref().map(|email| email.as_deref()) { + Some(Some("false")) | None => prompt_for_contact_email().await.map(Some)?, + Some(Some(email)) => Some(Some(email.to_string())), + Some(None) => None, + }; + anyhow::ensure!( !(cfg!(windows) && opt.experimental_reduce_indexing_memory_usage), "The `experimental-reduce-indexing-memory-usage` flag is not supported on Windows" @@ -139,6 +146,27 @@ async fn try_main() -> anyhow::Result<()> { Ok(()) } +/// Prompt the user about the contact email for support and news. +/// It only displays the prompt if the input is an interactive terminal. +async fn prompt_for_contact_email() -> anyhow::Result> { + let stdin = tokio::io::stdin(); + + if !stdin.is_terminal() { + return Ok(None); + } + + println!("Would you mind providing your contact email for support and news?"); + println!("We will use it to contact you with news only."); + print!("contact email> "); + std::io::stdout().flush()?; + + let mut email = String::new(); + let mut stdin = BufReader::new(stdin); + let _ = stdin.read_line(&mut email).await?; + + Ok(Some(email.trim().to_string())) +} + async fn run_http( index_scheduler: Arc, auth_controller: Arc, diff --git a/crates/meilisearch/src/option.rs b/crates/meilisearch/src/option.rs index 6e06b161d..8b34ef8dd 100644 --- a/crates/meilisearch/src/option.rs +++ b/crates/meilisearch/src/option.rs @@ -66,6 +66,7 @@ const MEILI_EXPERIMENTAL_LIMIT_BATCHED_TASKS_TOTAL_SIZE: &str = const MEILI_EXPERIMENTAL_EMBEDDING_CACHE_ENTRIES: &str = "MEILI_EXPERIMENTAL_EMBEDDING_CACHE_ENTRIES"; const MEILI_EXPERIMENTAL_NO_SNAPSHOT_COMPACTION: &str = "MEILI_EXPERIMENTAL_NO_SNAPSHOT_COMPACTION"; +const MEILI_CONTACT_EMAIL: &str = "MEILI_CONTACT_EMAIL"; const DEFAULT_CONFIG_FILE_PATH: &str = "./config.toml"; const DEFAULT_DB_PATH: &str = "./data.ms"; const DEFAULT_HTTP_ADDR: &str = "localhost:7700"; @@ -347,6 +348,10 @@ pub struct Opt { #[serde(default)] pub log_level: LogLevel, + /// Sets the email address to contact for support and news. + #[clap(long, env = MEILI_CONTACT_EMAIL)] + pub contact_email: Option>, + /// Experimental contains filter feature. For more information, /// see: /// @@ -556,6 +561,7 @@ impl Opt { ignore_dump_if_db_exists: _, config_file_path: _, no_analytics, + contact_email, experimental_contains_filter, experimental_enable_metrics, experimental_search_queue_size, @@ -588,6 +594,10 @@ impl Opt { } export_to_env_if_not_present(MEILI_NO_ANALYTICS, no_analytics.to_string()); + export_to_env_if_not_present( + MEILI_CONTACT_EMAIL, + contact_email.flatten().unwrap_or_else(|| "false".to_string()), + ); export_to_env_if_not_present( MEILI_HTTP_PAYLOAD_SIZE_LIMIT, http_payload_size_limit.to_string(), From c7cb72a77a213c709ef09d3021b7c310621fb0c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Renault?= Date: Thu, 5 Jun 2025 10:59:06 +0200 Subject: [PATCH 02/12] Make sure we skip empty prompted emails --- crates/meilisearch/src/main.rs | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/crates/meilisearch/src/main.rs b/crates/meilisearch/src/main.rs index cca704df5..87e3bf725 100644 --- a/crates/meilisearch/src/main.rs +++ b/crates/meilisearch/src/main.rs @@ -155,16 +155,21 @@ async fn prompt_for_contact_email() -> anyhow::Result> { return Ok(None); } - println!("Would you mind providing your contact email for support and news?"); - println!("We will use it to contact you with news only."); + println!("Would you mind providing your contact email for support and news? We will use it to contact you with news only."); + println!("Press enter to skip."); print!("contact email> "); std::io::stdout().flush()?; let mut email = String::new(); let mut stdin = BufReader::new(stdin); let _ = stdin.read_line(&mut email).await?; + let email = email.trim(); - Ok(Some(email.trim().to_string())) + if email.is_empty() { + Ok(None) + } else { + Ok(Some(email.to_string())) + } } async fn run_http( From 60796dfb14de6c452147037eb2eead899184c370 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Renault?= Date: Thu, 5 Jun 2025 11:02:30 +0200 Subject: [PATCH 03/12] Disable it by default in our Docker image --- Dockerfile | 1 + 1 file changed, 1 insertion(+) diff --git a/Dockerfile b/Dockerfile index 5a9a4691f..3d706e4c7 100644 --- a/Dockerfile +++ b/Dockerfile @@ -25,6 +25,7 @@ LABEL org.opencontainers.image.source="https://github.com/meilisearch/meilisea ENV MEILI_HTTP_ADDR 0.0.0.0:7700 ENV MEILI_SERVER_PROVIDER docker +ENV MEILI_CONTACT_EMAIL RUN apk add -q --no-cache libgcc tini curl From 239851046dae4be5dce0e449cd01d0a6a835b708 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Renault?= Date: Thu, 5 Jun 2025 12:00:23 +0200 Subject: [PATCH 04/12] Send requests to Hubspot --- crates/meilisearch/src/main.rs | 61 +++++++++++++++++++++++++++++++++- 1 file changed, 60 insertions(+), 1 deletion(-) diff --git a/crates/meilisearch/src/main.rs b/crates/meilisearch/src/main.rs index 87e3bf725..e8bff7997 100644 --- a/crates/meilisearch/src/main.rs +++ b/crates/meilisearch/src/main.rs @@ -20,12 +20,17 @@ use meilisearch::{ LogStderrType, Opt, SubscriberForSecondLayer, }; use meilisearch_auth::{generate_master_key, AuthController, MASTER_KEY_MIN_SIZE}; +use meilisearch_types::versioning::{VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH}; +use serde_json::json; use termcolor::{Color, ColorChoice, ColorSpec, StandardStream, WriteColor}; use tokio::io::{AsyncBufReadExt, BufReader}; use tracing::level_filters::LevelFilter; use tracing_subscriber::layer::SubscriberExt as _; use tracing_subscriber::Layer; +const PORTAL_ID: &str = "25945010"; +const FORM_GUID: &str = "991e2a09-77c2-4428-9242-ebf26bfc6c64"; + #[cfg(not(windows))] #[global_allocator] static ALLOC: mimalloc::MiMalloc = mimalloc::MiMalloc; @@ -96,10 +101,20 @@ async fn try_main() -> anyhow::Result<()> { opt.contact_email = match opt.contact_email.as_ref().map(|email| email.as_deref()) { Some(Some("false")) | None => prompt_for_contact_email().await.map(Some)?, + Some(Some("")) | Some(None) => None, Some(Some(email)) => Some(Some(email.to_string())), - Some(None) => None, }; + if let Some(Some(email)) = opt.contact_email.as_ref() { + let email = email.clone(); + let _ = tokio::spawn(async move { + dbg!(&email); + if let Err(err) = register_contact_email(&email).await { + eprintln!("Failed to register email: {}", err); + } + }); + } + anyhow::ensure!( !(cfg!(windows) && opt.experimental_reduce_indexing_memory_usage), "The `experimental-reduce-indexing-memory-usage` flag is not supported on Windows" @@ -172,6 +187,50 @@ async fn prompt_for_contact_email() -> anyhow::Result> { } } +async fn register_contact_email(email: &str) -> anyhow::Result<()> { + let url = format!( + "https://api.hsforms.com/submissions/v3/integration/submit/{PORTAL_ID}/{FORM_GUID}" + ); + + let page_name = format!( + "Meilisearch terminal prompt v{}.{}.{}", + VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH + ); + let response = reqwest::Client::new() + .post(url) + .json(&json!({ + "fields": [{ + "objectTypeId": "0-1", + "name": "email", + "value": email, + }], + "context": { + "pageName": page_name, + }, + "legalConsentOptions": { + "consent": { + "consentToProcess": true, + "text": "I agree to allow Meilisearch to store and process my personal data.", + "communications": [{ + "value": true, + "subscriptionTypeId": 999, + "text": "I agree to receive marketing communications from Meilisearch.", + }], + }, + }, + })) + .send() + .await?; + + let status = response.status(); + if status.is_client_error() || status.is_server_error() { + let response: serde_json::Value = response.json().await?; + eprintln!("Failed to register email: {response:?}"); + } + + Ok(()) +} + async fn run_http( index_scheduler: Arc, auth_controller: Arc, From 7b49c30d8c31bb3c7b71c18be5e3fb3c56dfedf9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Renault?= Date: Thu, 5 Jun 2025 12:02:30 +0200 Subject: [PATCH 05/12] Change the email prompting --- crates/meilisearch/src/main.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/meilisearch/src/main.rs b/crates/meilisearch/src/main.rs index e8bff7997..b5c9e0792 100644 --- a/crates/meilisearch/src/main.rs +++ b/crates/meilisearch/src/main.rs @@ -170,8 +170,8 @@ async fn prompt_for_contact_email() -> anyhow::Result> { return Ok(None); } - println!("Would you mind providing your contact email for support and news? We will use it to contact you with news only."); - println!("Press enter to skip."); + println!("Enter your email to receive occasional updates and tips about Meilisearch."); + println!("Leave blank to skip."); print!("contact email> "); std::io::stdout().flush()?; From 8bc8484e95d90d93a98f7c2b8f55c2ddd913ef0b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Renault?= Date: Thu, 5 Jun 2025 14:43:05 +0200 Subject: [PATCH 06/12] Skip the prompt when the email was once provided --- crates/meilisearch/src/main.rs | 41 +++++++++++++++++++++------------- 1 file changed, 25 insertions(+), 16 deletions(-) diff --git a/crates/meilisearch/src/main.rs b/crates/meilisearch/src/main.rs index b5c9e0792..4e2b25ffd 100644 --- a/crates/meilisearch/src/main.rs +++ b/crates/meilisearch/src/main.rs @@ -28,6 +28,7 @@ use tracing::level_filters::LevelFilter; use tracing_subscriber::layer::SubscriberExt as _; use tracing_subscriber::Layer; +const SKIP_EMAIL_FILENAME: &str = "skip-email"; const PORTAL_ID: &str = "25945010"; const FORM_GUID: &str = "991e2a09-77c2-4428-9242-ebf26bfc6c64"; @@ -99,22 +100,6 @@ async fn try_main() -> anyhow::Result<()> { std::panic::set_hook(Box::new(on_panic)); - opt.contact_email = match opt.contact_email.as_ref().map(|email| email.as_deref()) { - Some(Some("false")) | None => prompt_for_contact_email().await.map(Some)?, - Some(Some("")) | Some(None) => None, - Some(Some(email)) => Some(Some(email.to_string())), - }; - - if let Some(Some(email)) = opt.contact_email.as_ref() { - let email = email.clone(); - let _ = tokio::spawn(async move { - dbg!(&email); - if let Err(err) = register_contact_email(&email).await { - eprintln!("Failed to register email: {}", err); - } - }); - } - anyhow::ensure!( !(cfg!(windows) && opt.experimental_reduce_indexing_memory_usage), "The `experimental-reduce-indexing-memory-usage` flag is not supported on Windows" @@ -146,6 +131,30 @@ async fn try_main() -> anyhow::Result<()> { let (index_scheduler, auth_controller) = setup_meilisearch(&opt)?; + // We ask users their emails just after the data.ms is created + let skip_email_path = opt.db_path.join(SKIP_EMAIL_FILENAME); + opt.contact_email = match opt.contact_email.as_ref().map(|email| email.as_deref()) { + Some(Some("false")) | None if !skip_email_path.exists() => { + prompt_for_contact_email().await.map(Some)? + } + Some(Some(email)) if !skip_email_path.exists() => Some(Some(email.to_string())), + _otherwise => None, + }; + + if let Some(Some(email)) = opt.contact_email.as_ref() { + let email = email.clone(); + // We spawn a task to register the email and create the skip email + // file to avoid blocking the Meilisearch launch further. + let _ = tokio::spawn(async move { + if let Err(e) = tokio::fs::File::create_new(skip_email_path).await { + eprintln!("Failed to create skip email file: {e}"); + } + if let Err(err) = register_contact_email(&email).await { + eprintln!("Failed to register email: {}", err); + } + }); + } + let analytics = analytics::Analytics::new(&opt, index_scheduler.clone(), auth_controller.clone()).await; From 4fc24cb6912453d911f27032f3bbf9930a8054b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Renault?= Date: Thu, 5 Jun 2025 14:43:46 +0200 Subject: [PATCH 07/12] Improve prompting again --- crates/meilisearch/src/main.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/meilisearch/src/main.rs b/crates/meilisearch/src/main.rs index 4e2b25ffd..022395397 100644 --- a/crates/meilisearch/src/main.rs +++ b/crates/meilisearch/src/main.rs @@ -179,9 +179,9 @@ async fn prompt_for_contact_email() -> anyhow::Result> { return Ok(None); } - println!("Enter your email to receive occasional updates and tips about Meilisearch."); - println!("Leave blank to skip."); - print!("contact email> "); + println!("Stay up to date! Get monthly updates about new features and tips to get the most out of Meilisearch."); + println!("You can use the `--contact-email` parameter to disable this prompt."); + print!("Enter your email or leave blank to skip> "); std::io::stdout().flush()?; let mut email = String::new(); From e575b5af7460acd6c2432621dfcec37de482c0f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Renault?= Date: Thu, 5 Jun 2025 14:49:08 +0200 Subject: [PATCH 08/12] Improve the contact email flag to make it friendly to disable prompt --- crates/meilisearch/src/option.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/crates/meilisearch/src/option.rs b/crates/meilisearch/src/option.rs index 8b34ef8dd..2a5de7011 100644 --- a/crates/meilisearch/src/option.rs +++ b/crates/meilisearch/src/option.rs @@ -349,6 +349,9 @@ pub struct Opt { pub log_level: LogLevel, /// Sets the email address to contact for support and news. + /// + /// Use this option to disable contact email prompting. Leave + /// blank or without value to disable contact email prompting. #[clap(long, env = MEILI_CONTACT_EMAIL)] pub contact_email: Option>, From 204cf423b28a8bc24749544d4f303209e53b8e83 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Renault?= Date: Thu, 5 Jun 2025 15:02:09 +0200 Subject: [PATCH 09/12] Fix Docker Image --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 3d706e4c7..937537728 100644 --- a/Dockerfile +++ b/Dockerfile @@ -25,7 +25,7 @@ LABEL org.opencontainers.image.source="https://github.com/meilisearch/meilisea ENV MEILI_HTTP_ADDR 0.0.0.0:7700 ENV MEILI_SERVER_PROVIDER docker -ENV MEILI_CONTACT_EMAIL +ENV MEILI_CONTACT_EMAIL "" RUN apk add -q --no-cache libgcc tini curl From 765e76857f4b08982671685e137f371e805ae6a9 Mon Sep 17 00:00:00 2001 From: Tamo Date: Thu, 5 Jun 2025 16:01:30 +0200 Subject: [PATCH 10/12] store the email file in the global config directory instead of the local data.ms so it's shared between all instances --- crates/meilisearch/src/analytics/mod.rs | 2 +- crates/meilisearch/src/main.rs | 20 ++++++++++++++------ 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/crates/meilisearch/src/analytics/mod.rs b/crates/meilisearch/src/analytics/mod.rs index bd14b0bfa..cd5641375 100644 --- a/crates/meilisearch/src/analytics/mod.rs +++ b/crates/meilisearch/src/analytics/mod.rs @@ -45,7 +45,7 @@ macro_rules! empty_analytics { /// `~/.config/Meilisearch` on *NIX or *BSD. /// `~/Library/ApplicationSupport` on macOS. /// `%APPDATA` (= `C:\Users%USERNAME%\AppData\Roaming`) on windows. -static MEILISEARCH_CONFIG_PATH: Lazy> = +pub static MEILISEARCH_CONFIG_PATH: Lazy> = Lazy::new(|| AppDirs::new(Some("Meilisearch"), false).map(|appdir| appdir.config_dir)); fn config_user_id_path(db_path: &Path) -> Option { diff --git a/crates/meilisearch/src/main.rs b/crates/meilisearch/src/main.rs index 022395397..84742f671 100644 --- a/crates/meilisearch/src/main.rs +++ b/crates/meilisearch/src/main.rs @@ -12,7 +12,7 @@ use actix_web::web::Data; use actix_web::HttpServer; use index_scheduler::IndexScheduler; use is_terminal::IsTerminal; -use meilisearch::analytics::Analytics; +use meilisearch::analytics::{Analytics, MEILISEARCH_CONFIG_PATH}; use meilisearch::option::LogMode; use meilisearch::search_queue::SearchQueue; use meilisearch::{ @@ -132,12 +132,14 @@ async fn try_main() -> anyhow::Result<()> { let (index_scheduler, auth_controller) = setup_meilisearch(&opt)?; // We ask users their emails just after the data.ms is created - let skip_email_path = opt.db_path.join(SKIP_EMAIL_FILENAME); + let skip_email_path = MEILISEARCH_CONFIG_PATH.as_ref().map(|conf| conf.join(SKIP_EMAIL_FILENAME)); + // If the config path does not exist, it means the user don't have a home directory + let skip_email = skip_email_path.as_ref().map_or(true, |path| path.exists()); opt.contact_email = match opt.contact_email.as_ref().map(|email| email.as_deref()) { - Some(Some("false")) | None if !skip_email_path.exists() => { + Some(Some("false")) | None if !skip_email => { prompt_for_contact_email().await.map(Some)? } - Some(Some(email)) if !skip_email_path.exists() => Some(Some(email.to_string())), + Some(Some(email)) if !skip_email => Some(Some(email.to_string())), _otherwise => None, }; @@ -146,8 +148,14 @@ async fn try_main() -> anyhow::Result<()> { // We spawn a task to register the email and create the skip email // file to avoid blocking the Meilisearch launch further. let _ = tokio::spawn(async move { - if let Err(e) = tokio::fs::File::create_new(skip_email_path).await { - eprintln!("Failed to create skip email file: {e}"); + if let Some(skip_email_path) = skip_email_path { + // If the analytics are disabled the directory might not exist at all + if let Err(e) = tokio::fs::create_dir_all(skip_email_path.parent().unwrap()).await { + eprintln!("Failed to create skip email file: {e}"); + } + if let Err(e) = tokio::fs::File::create_new(skip_email_path).await { + eprintln!("Failed to create skip email file: {e}"); + } } if let Err(err) = register_contact_email(&email).await { eprintln!("Failed to register email: {}", err); From 38b317857d7a97610e9c63a9ec1ac94ed5b81275 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Renault?= Date: Thu, 5 Jun 2025 18:19:19 +0200 Subject: [PATCH 11/12] Improve the wording again --- crates/meilisearch/src/main.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/meilisearch/src/main.rs b/crates/meilisearch/src/main.rs index 84742f671..cf2379d11 100644 --- a/crates/meilisearch/src/main.rs +++ b/crates/meilisearch/src/main.rs @@ -187,8 +187,8 @@ async fn prompt_for_contact_email() -> anyhow::Result> { return Ok(None); } - println!("Stay up to date! Get monthly updates about new features and tips to get the most out of Meilisearch."); - println!("You can use the `--contact-email` parameter to disable this prompt."); + println!("Get monthly updates about new features and tips to get the most out of Meilisearch."); + println!("Use the --contact-email option to disable this prompt."); print!("Enter your email or leave blank to skip> "); std::io::stdout().flush()?; From 90d96ee4159f2f380dc8a54baa8446af7f04511b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Renault?= Date: Thu, 5 Jun 2025 18:21:55 +0200 Subject: [PATCH 12/12] Make clippy happy --- crates/meilisearch/src/main.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/crates/meilisearch/src/main.rs b/crates/meilisearch/src/main.rs index cf2379d11..13f76732a 100644 --- a/crates/meilisearch/src/main.rs +++ b/crates/meilisearch/src/main.rs @@ -132,13 +132,12 @@ async fn try_main() -> anyhow::Result<()> { let (index_scheduler, auth_controller) = setup_meilisearch(&opt)?; // We ask users their emails just after the data.ms is created - let skip_email_path = MEILISEARCH_CONFIG_PATH.as_ref().map(|conf| conf.join(SKIP_EMAIL_FILENAME)); + let skip_email_path = + MEILISEARCH_CONFIG_PATH.as_ref().map(|conf| conf.join(SKIP_EMAIL_FILENAME)); // If the config path does not exist, it means the user don't have a home directory - let skip_email = skip_email_path.as_ref().map_or(true, |path| path.exists()); + let skip_email = skip_email_path.as_ref().is_none_or(|path| path.exists()); opt.contact_email = match opt.contact_email.as_ref().map(|email| email.as_deref()) { - Some(Some("false")) | None if !skip_email => { - prompt_for_contact_email().await.map(Some)? - } + Some(Some("false")) | None if !skip_email => prompt_for_contact_email().await.map(Some)?, Some(Some(email)) if !skip_email => Some(Some(email.to_string())), _otherwise => None, }; @@ -147,7 +146,7 @@ async fn try_main() -> anyhow::Result<()> { let email = email.clone(); // We spawn a task to register the email and create the skip email // file to avoid blocking the Meilisearch launch further. - let _ = tokio::spawn(async move { + let handle = tokio::spawn(async move { if let Some(skip_email_path) = skip_email_path { // If the analytics are disabled the directory might not exist at all if let Err(e) = tokio::fs::create_dir_all(skip_email_path.parent().unwrap()).await { @@ -161,6 +160,7 @@ async fn try_main() -> anyhow::Result<()> { eprintln!("Failed to register email: {}", err); } }); + drop(handle); } let analytics =