use std::sync::Arc; use database::generated::entities::config::{self, ActiveModel as ConfigActiveModel}; use sea_orm::{ ActiveModelTrait, ActiveValue, ColumnTrait, DatabaseConnection, DbErr, EntityTrait, IntoActiveModel, QueryFilter, }; use crate::errors::service_error::{IntoServiceError, ServiceError}; #[async_trait::async_trait] pub trait SettingsStore: Send + Sync { #[allow(dead_code)] // TODO: remove when used async fn get_setting(&self, key: &str) -> Result; #[allow(dead_code)] // TODO: remove when used async fn set_setting(&self, key: &str, value: String) -> Result<(), ServiceError>; } pub struct SettingsService { #[allow(dead_code)] // TODO: remove when used connection: Arc, } impl SettingsService { pub fn new(connection: Arc) -> Self { Self { connection } } } #[async_trait::async_trait] impl SettingsStore for SettingsService { async fn get_setting(&self, key: &str) -> Result { let setting = config::Entity::find() .filter(config::Column::Key.eq(key)) .one(&*self.connection) .await; match setting { Err(err) => Err(err.into_service_error()), Ok(None) => Err( DbErr::RecordNotFound(format!("Setting with key '{}' not found", key)) .into_service_error(), ), Ok(Some(record)) => Ok(record.value), } } async fn set_setting(&self, key: &str, value: String) -> Result<(), ServiceError> { let existing = config::Entity::find() .filter(config::Column::Key.eq(key)) .one(&*self.connection) .await; let handle_not_found = async |key: String, value: String| { let new_record = ConfigActiveModel { key: ActiveValue::Set(key), value: ActiveValue::Set(value), created_at: ActiveValue::Set(chrono::Utc::now()), updated_at: ActiveValue::Set(chrono::Utc::now()), }; new_record .insert(&*self.connection) .await .map_err(|err| err.into_service_error()) }; match existing { Err(err) => match err { DbErr::RecordNotFound(_) => { handle_not_found(key.to_string(), value).await?; } _ => { return Err(Box::new(err)); } }, Ok(None) => { handle_not_found(key.to_string(), value).await?; } Ok(Some(mut record)) => { record.value = value; record .into_active_model() .update(&*self.connection) .await .map_err(|err| err.into_service_error())?; } } Ok(()) } }