use std::error::Error; use std::ops::Deref; use std::path::PathBuf; use std::sync::Arc; use meilisearch_core::{Database, DatabaseOptions}; use sha2::Digest; use crate::index_update_callback; use crate::option::Opt; #[derive(Clone)] pub struct Data { inner: Arc, } impl Deref for Data { type Target = DataInner; fn deref(&self) -> &Self::Target { &self.inner } } #[derive(Clone)] pub struct DataInner { pub db: Arc, pub db_path: String, pub backup_folder: PathBuf, pub backup_batch_size: usize, pub api_keys: ApiKeys, pub server_pid: u32, pub http_payload_size_limit: usize, } #[derive(Clone)] pub struct ApiKeys { pub public: Option, pub private: Option, pub master: Option, } impl ApiKeys { pub fn generate_missing_api_keys(&mut self) { if let Some(master_key) = &self.master { if self.private.is_none() { let key = format!("{}-private", master_key); let sha = sha2::Sha256::digest(key.as_bytes()); self.private = Some(format!("{:x}", sha)); } if self.public.is_none() { let key = format!("{}-public", master_key); let sha = sha2::Sha256::digest(key.as_bytes()); self.public = Some(format!("{:x}", sha)); } } } } impl Data { pub fn new(opt: Opt) -> Result> { let db_path = opt.db_path.clone(); let backup_folder = opt.backup_folder.clone(); let backup_batch_size = opt.backup_batch_size; let server_pid = std::process::id(); let db_opt = DatabaseOptions { main_map_size: opt.max_mdb_size, update_map_size: opt.max_udb_size, }; let http_payload_size_limit = opt.http_payload_size_limit; let db = Arc::new(Database::open_or_create(opt.db_path, db_opt)?); let mut api_keys = ApiKeys { master: opt.master_key, private: None, public: None, }; api_keys.generate_missing_api_keys(); let inner_data = DataInner { db: db.clone(), db_path, backup_folder, backup_batch_size, api_keys, server_pid, http_payload_size_limit, }; let data = Data { inner: Arc::new(inner_data), }; let callback_context = data.clone(); db.set_update_callback(Box::new(move |index_uid, status| { index_update_callback(&index_uid, &callback_context, status); })); Ok(data) } }