From 8395fc4621d1bda2508df576f019149312efe8ad Mon Sep 17 00:00:00 2001 From: ManyTheFish Date: Tue, 22 Jul 2025 11:12:42 +0200 Subject: [PATCH] feat: add experimental_personalization_api_key feature to RoFeatures - Add MEILI_EXPERIMENTAL_PERSONALIZATION_API_KEY environment variable - Add experimental_personalization_api_key field to Opt struct with CLI and env support - Add experimental_personalization_api_key field to InstanceTogglableFeatures - Store personalization API key in FeatureData for access through IndexScheduler - Add experimental_personalization_api_key() method to IndexScheduler - Update analytics destructuring to include new field - Maintain RoFeatures Copy trait while properly handling Option --- crates/index-scheduler/src/features.rs | 13 ++++++++++++- crates/index-scheduler/src/lib.rs | 4 ++++ crates/meilisearch-types/src/features.rs | 3 ++- .../src/analytics/segment_analytics.rs | 1 + crates/meilisearch/src/option.rs | 16 ++++++++++++++++ 5 files changed, 35 insertions(+), 2 deletions(-) diff --git a/crates/index-scheduler/src/features.rs b/crates/index-scheduler/src/features.rs index 5646a5d80..13b4bc6ca 100644 --- a/crates/index-scheduler/src/features.rs +++ b/crates/index-scheduler/src/features.rs @@ -25,6 +25,7 @@ pub(crate) struct FeatureData { persisted: Database>, runtime: Arc>, network: Arc>, + experimental_personalization_api_key: Option, } #[derive(Debug, Clone, Copy)] @@ -188,7 +189,12 @@ impl FeatureData { let persisted_features: RuntimeTogglableFeatures = runtime_features_db.get(wtxn, db_keys::EXPERIMENTAL_FEATURES)?.unwrap_or_default(); - let InstanceTogglableFeatures { metrics, logs_route, contains_filter } = instance_features; + let InstanceTogglableFeatures { + metrics, + logs_route, + contains_filter, + experimental_personalization_api_key, + } = instance_features; let runtime = Arc::new(RwLock::new(RuntimeTogglableFeatures { metrics: metrics || persisted_features.metrics, logs_route: logs_route || persisted_features.logs_route, @@ -204,6 +210,7 @@ impl FeatureData { persisted: runtime_features_db, runtime, network: Arc::new(RwLock::new(network)), + experimental_personalization_api_key, }) } @@ -234,6 +241,10 @@ impl FeatureData { RoFeatures::new(self) } + pub fn experimental_personalization_api_key(&self) -> Option<&String> { + self.experimental_personalization_api_key.as_ref() + } + pub fn put_network(&self, mut wtxn: RwTxn, new_network: Network) -> Result<()> { self.persisted.remap_data_type::>().put( &mut wtxn, diff --git a/crates/index-scheduler/src/lib.rs b/crates/index-scheduler/src/lib.rs index 5e31feab8..c8e1a0363 100644 --- a/crates/index-scheduler/src/lib.rs +++ b/crates/index-scheduler/src/lib.rs @@ -886,6 +886,10 @@ impl IndexScheduler { self.features.features() } + pub fn experimental_personalization_api_key(&self) -> Option<&String> { + self.features.experimental_personalization_api_key() + } + pub fn put_runtime_features(&self, features: RuntimeTogglableFeatures) -> Result<()> { let wtxn = self.env.write_txn().map_err(Error::HeedTransaction)?; self.features.put_runtime_features(wtxn, features)?; diff --git a/crates/meilisearch-types/src/features.rs b/crates/meilisearch-types/src/features.rs index 9c2a6a135..04b2c33e7 100644 --- a/crates/meilisearch-types/src/features.rs +++ b/crates/meilisearch-types/src/features.rs @@ -24,11 +24,12 @@ pub struct RuntimeTogglableFeatures { pub vector_store_setting: bool, } -#[derive(Default, Debug, Clone, Copy)] +#[derive(Default, Debug, Clone)] pub struct InstanceTogglableFeatures { pub metrics: bool, pub logs_route: bool, pub contains_filter: bool, + pub experimental_personalization_api_key: Option, } #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, Default)] diff --git a/crates/meilisearch/src/analytics/segment_analytics.rs b/crates/meilisearch/src/analytics/segment_analytics.rs index 04020a74f..754bc12d9 100644 --- a/crates/meilisearch/src/analytics/segment_analytics.rs +++ b/crates/meilisearch/src/analytics/segment_analytics.rs @@ -283,6 +283,7 @@ impl Infos { indexer_options, config_file_path, no_analytics: _, + experimental_personalization_api_key: _, } = options; let schedule_snapshot = match schedule_snapshot { diff --git a/crates/meilisearch/src/option.rs b/crates/meilisearch/src/option.rs index 803fecf01..358a568cd 100644 --- a/crates/meilisearch/src/option.rs +++ b/crates/meilisearch/src/option.rs @@ -70,6 +70,8 @@ const MEILI_EXPERIMENTAL_EMBEDDING_CACHE_ENTRIES: &str = const MEILI_EXPERIMENTAL_NO_SNAPSHOT_COMPACTION: &str = "MEILI_EXPERIMENTAL_NO_SNAPSHOT_COMPACTION"; const MEILI_EXPERIMENTAL_NO_EDITION_2024_FOR_DUMPS: &str = "MEILI_EXPERIMENTAL_NO_EDITION_2024_FOR_DUMPS"; +const MEILI_EXPERIMENTAL_PERSONALIZATION_API_KEY: &str = + "MEILI_EXPERIMENTAL_PERSONALIZATION_API_KEY"; const DEFAULT_CONFIG_FILE_PATH: &str = "./config.toml"; const DEFAULT_DB_PATH: &str = "./data.ms"; const DEFAULT_HTTP_ADDR: &str = "localhost:7700"; @@ -471,6 +473,12 @@ pub struct Opt { #[serde(default)] pub experimental_no_snapshot_compaction: bool, + /// Experimental personalization API key feature. + /// + /// Sets the API key for personalization features. + #[clap(long, env = MEILI_EXPERIMENTAL_PERSONALIZATION_API_KEY)] + pub experimental_personalization_api_key: Option, + #[serde(flatten)] #[clap(flatten)] pub indexer_options: IndexerOpts, @@ -576,6 +584,7 @@ impl Opt { experimental_limit_batched_tasks_total_size, experimental_embedding_cache_entries, experimental_no_snapshot_compaction, + experimental_personalization_api_key, } = self; export_to_env_if_not_present(MEILI_DB_PATH, db_path); export_to_env_if_not_present(MEILI_HTTP_ADDR, http_addr); @@ -676,6 +685,12 @@ impl Opt { MEILI_EXPERIMENTAL_NO_SNAPSHOT_COMPACTION, experimental_no_snapshot_compaction.to_string(), ); + if let Some(experimental_personalization_api_key) = experimental_personalization_api_key { + export_to_env_if_not_present( + MEILI_EXPERIMENTAL_PERSONALIZATION_API_KEY, + experimental_personalization_api_key, + ); + } indexer_options.export_to_env(); } @@ -728,6 +743,7 @@ impl Opt { metrics: self.experimental_enable_metrics, logs_route: self.experimental_enable_logs_route, contains_filter: self.experimental_contains_filter, + experimental_personalization_api_key: self.experimental_personalization_api_key.clone(), } } }