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::ServiceError; #[async_trait::async_trait] pub trait SettingsStore: Send + Sync { async fn get_setting(&self, key: &str) -> Result; async fn set_setting(&self, key: &str, value: String) -> Result<(), ServiceError>; } pub struct SettingsService { 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(ServiceError::from(err)), Ok(None) => Err(ServiceError::from(DbErr::RecordNotFound(format!( "Setting with key '{}' not found", key )))), 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(ServiceError::from) }; match existing { Err(err) => match err { DbErr::RecordNotFound(_) => { handle_not_found(key.to_string(), value).await?; } _ => { return Err(ServiceError::from(err)); } }, Ok(None) => { handle_not_found(key.to_string(), value).await?; } Ok(Some(record)) => { let mut record_active_model = record.into_active_model(); record_active_model.value = ActiveValue::Set(value); record_active_model.updated_at = ActiveValue::Set(chrono::Utc::now()); record_active_model .update(&*self.connection) .await .map_err(ServiceError::from)?; } } Ok(()) } }