diff --git a/apps/api/src/services/nginx/info/upstream.rs b/apps/api/src/services/nginx/info/upstream.rs index 1756e6d..8389109 100644 --- a/apps/api/src/services/nginx/info/upstream.rs +++ b/apps/api/src/services/nginx/info/upstream.rs @@ -55,10 +55,11 @@ impl NginxConfigProvider for UpstreamInfo { } } -impl From for upstream::ActiveModel { - fn from(val: UpstreamCreateInfo) -> Self { - upstream::ActiveModel { - id: sea_orm::ActiveValue::Set(Uuid::new_v4()), +impl From for (upstream::ActiveModel, Vec) { + fn from(val: UpstreamCreateInfo) -> (upstream::ActiveModel, Vec) { + let upstream_uuid = Uuid::new_v4(); + let upstream = upstream::ActiveModel { + id: sea_orm::ActiveValue::Set(upstream_uuid), name: sea_orm::ActiveValue::Set(val.name), protocol: sea_orm::ActiveValue::Set(val.protocol), algorithm: sea_orm::ActiveValue::Set(val.algorithm), @@ -66,7 +67,17 @@ impl From for upstream::ActiveModel { created_by: sea_orm::ActiveValue::Set(val.created_by), created_at: sea_orm::ActiveValue::Set(chrono::Utc::now()), updated_at: sea_orm::ActiveValue::Set(chrono::Utc::now()), - } + }; + let upstream_targets = val + .upstream_targets + .into_iter() + .map(|target| { + let mut active_model: upstream_target::ActiveModel = target.into(); + active_model.upstream_id = sea_orm::ActiveValue::Set(upstream_uuid); + active_model + }) + .collect(); + (upstream, upstream_targets) } } diff --git a/apps/api/src/services/nginx/upstream.rs b/apps/api/src/services/nginx/upstream.rs index a3d2752..f9fd054 100644 --- a/apps/api/src/services/nginx/upstream.rs +++ b/apps/api/src/services/nginx/upstream.rs @@ -2,7 +2,7 @@ use std::sync::Arc; use sea_orm::{ ActiveModelTrait, ColumnTrait, DatabaseConnection, DatabaseTransaction, EntityTrait, - ModelTrait, QueryFilter, QuerySelect, + ModelTrait, QueryFilter, QuerySelect, TransactionTrait, }; use database::generated::entities::{upstream, upstream_target}; @@ -42,8 +42,40 @@ impl UpstreamService { create_info: UpstreamCreateInfo, tx: Option<&mut DatabaseTransaction>, ) -> Result { - let model: upstream::ActiveModel = create_info.into(); - let r = with_conn!(&*self.connection, tx, conn, { model.insert(*conn).await? }); + let (upstream_model, upstream_target_models): ( + upstream::ActiveModel, + Vec, + ) = create_info.into(); + + // If a transaction was provided use it, otherwise create and own one here. + let mut maybe_owned_tx: Option = None; + let tx_ref: Option<&mut DatabaseTransaction> = if let Some(tx) = tx { + Some(tx) + } else { + maybe_owned_tx = Some(self.connection.begin().await?); + maybe_owned_tx.as_mut() + }; + + let r = with_conn!(&*self.connection, tx_ref, conn, { + let created_upstream = upstream_model.insert(*conn).await?; + let created_targets = upstream_target::Entity::insert_many( + upstream_target_models + .into_iter() + .map(|mut model| { + model.upstream_id = sea_orm::ActiveValue::Set(created_upstream.id); + model + }) + .collect::>(), + ) + .exec_with_returning(*conn) + .await?; + (created_upstream, created_targets) + }); + + // Commit only if we created the transaction here (we own it). + if let Some(t) = maybe_owned_tx.take() { + t.commit().await?; + } Ok(r.into()) }