use sea_orm::{ActiveModelTrait, ActiveValue::Set, DatabaseConnection, EntityTrait, prelude::*}; use uuid::Uuid; use crate::service::proxy::types::{ OverrideRef, ProxyServiceError, ProxyServiceResult, UpstreamConfig, }; pub struct CreateUpstreamParams { pub config_id: Uuid, pub name: String, pub target_host: String, pub target_port: i32, pub metadata: Option, pub override_of_id: Option, } pub struct UpdateUpstreamParams { pub name: Option, pub target_host: Option, pub target_port: Option, pub metadata: Option>, pub override_of_id: Option>, } fn model_to_config(model: crate::db::entities::upstream::Model) -> UpstreamConfig { UpstreamConfig { id: model.id, name: model.name, target_host: model.target_host, target_port: model.target_port, metadata: model.metadata, override_of_id: model.override_of_id, location_blocks: vec![], } } #[async_trait::async_trait] pub trait UpstreamService: Send + Sync + 'static { async fn get(&self, id: Uuid) -> ProxyServiceResult; async fn list_by_config(&self, config_id: Uuid) -> ProxyServiceResult>; async fn create(&self, params: CreateUpstreamParams) -> ProxyServiceResult; async fn update( &self, id: Uuid, params: UpdateUpstreamParams, ) -> ProxyServiceResult; async fn delete(&self, id: Uuid) -> ProxyServiceResult; } pub(crate) struct UpstreamServiceImpl { db: DatabaseConnection, } impl UpstreamServiceImpl { pub fn new(db: DatabaseConnection) -> Self { Self { db } } } #[async_trait::async_trait] impl UpstreamService for UpstreamServiceImpl { async fn get(&self, id: Uuid) -> ProxyServiceResult { use crate::db::entities::upstream; let model = upstream::Entity::find_by_id(id) .one(&self.db) .await? .ok_or(ProxyServiceError::ConfigNotFound)?; Ok(model_to_config(model)) } async fn list_by_config(&self, config_id: Uuid) -> ProxyServiceResult> { use crate::db::entities::upstream; let models = upstream::Entity::find() .filter(upstream::Column::ConfigId.eq(config_id)) .all(&self.db) .await?; Ok(models.into_iter().map(model_to_config).collect()) } async fn create(&self, params: CreateUpstreamParams) -> ProxyServiceResult { use crate::db::entities::upstream::ActiveModel; let model = ActiveModel { id: Set(Uuid::new_v4()), config_id: Set(params.config_id), name: Set(params.name), target_host: Set(params.target_host), target_port: Set(params.target_port), metadata: Set(params.metadata), override_of_id: Set(params.override_of_id), }; let result = model.insert(&self.db).await?; Ok(model_to_config(result)) } async fn update( &self, id: Uuid, params: UpdateUpstreamParams, ) -> ProxyServiceResult { use crate::db::entities::upstream::{ActiveModel, Entity as UpstreamEntity}; let existing = UpstreamEntity::find_by_id(id) .one(&self.db) .await? .ok_or(ProxyServiceError::ConfigNotFound)?; let mut model: ActiveModel = existing.into(); if let Some(name) = params.name { model.name = Set(name); } if let Some(target_host) = params.target_host { model.target_host = Set(target_host); } if let Some(target_port) = params.target_port { model.target_port = Set(target_port); } if let Some(metadata) = params.metadata { model.metadata = Set(metadata); } if let Some(override_of_id) = params.override_of_id { model.override_of_id = Set(override_of_id); } let result = model.update(&self.db).await?; Ok(model_to_config(result)) } async fn delete(&self, id: Uuid) -> ProxyServiceResult { let result = crate::db::entities::upstream::Entity::delete_by_id(id) .exec(&self.db) .await?; Ok(result.rows_affected > 0) } }