feat: added proxy_host builder, and improve transaction borrowing

This commit is contained in:
GW_MC
2026-01-07 16:37:51 +08:00
parent 9b8232d94d
commit 7ae76f622c
17 changed files with 136 additions and 66 deletions

View File

@@ -81,12 +81,13 @@ impl NginxService {
pub async fn generate_config(
&self,
tx: Option<&mut DatabaseTransaction>,
tx: &Option<&mut DatabaseTransaction>,
) -> Result<String, ServiceError> {
let mut builder = NginxConfigBuilder::default();
self.upstream_service
.generate_config(&mut builder, tx)
.await?;
self.proxy_service.generate_config(&mut builder, tx).await?;
builder.to_nginx_config(None)
}
@@ -94,7 +95,7 @@ impl NginxService {
pub async fn regenerate_and_apply_config(
&self,
agent: Arc<dyn AgentService>,
tx: Option<&mut DatabaseTransaction>,
tx: &Option<&mut DatabaseTransaction>,
) -> Result<(), ServiceError> {
let config = self.generate_config(tx).await?;

View File

@@ -1,4 +1,7 @@
use crate::{errors::service_error::ServiceError, services::nginx::info::upstream::UpstreamInfo};
use crate::{
errors::service_error::ServiceError,
services::nginx::info::{proxy_host::ProxyHostInfo, upstream::UpstreamInfo},
};
pub const INDENT_SIZE: usize = 2;
@@ -9,6 +12,7 @@ pub trait NginxConfigProvider {
#[derive(Default)]
pub struct NginxConfigBuilder {
upstreams: Vec<UpstreamInfo>,
proxy_hosts: Vec<ProxyHostInfo>,
}
impl NginxConfigBuilder {
@@ -21,6 +25,16 @@ impl NginxConfigBuilder {
self.add_upstream(upstream);
}
}
pub fn add_proxy_host(&mut self, proxy_host: ProxyHostInfo) {
self.proxy_hosts.push(proxy_host);
}
pub fn add_proxy_hosts(&mut self, proxy_hosts: Vec<ProxyHostInfo>) {
for proxy_host in proxy_hosts {
self.add_proxy_host(proxy_host);
}
}
}
impl NginxConfigProvider for NginxConfigBuilder {
@@ -35,6 +49,10 @@ impl NginxConfigProvider for NginxConfigBuilder {
config.push_str(&upstream.to_nginx_config(indent)?);
}
for proxy_host in &self.proxy_hosts {
config.push('\n');
config.push_str(&proxy_host.to_nginx_config(indent)?);
}
// TODO: Add other sections like servers, locations, etc.
// trailing newline for file ending
config.push('\n');

View File

@@ -11,7 +11,10 @@ use database::generated::entities::{location, proxy_host};
use crate::{
errors::service_error::ServiceError,
helpers::database::PaginationFilter,
services::nginx::info::proxy_host::{ProxyHostCreateInfo, ProxyHostInfo, UpdateProxyHostInfo},
services::nginx::{
builder::NginxConfigBuilder,
info::proxy_host::{ProxyHostCreateInfo, ProxyHostInfo, UpdateProxyHostInfo},
},
with_conn,
};
@@ -20,35 +23,40 @@ pub trait ProxyService: Send + Sync {
async fn create_proxy(
&self,
create_info: ProxyHostCreateInfo,
tx: Option<&mut DatabaseTransaction>,
tx: &Option<&mut DatabaseTransaction>,
) -> Result<ProxyHostInfo, ServiceError>;
async fn get_total_proxies(
&self,
options: Option<ProxyTotalCountOptions>,
tx: Option<&mut DatabaseTransaction>,
tx: &Option<&mut DatabaseTransaction>,
) -> Result<u64, ServiceError>;
async fn get_proxies(
&self,
pagination: Option<PaginationFilter>,
options: Option<ProxyHostListOptions>,
tx: Option<&mut DatabaseTransaction>,
tx: &Option<&mut DatabaseTransaction>,
) -> Result<Vec<ProxyHostInfo>, ServiceError>;
async fn get_proxy(
&self,
proxy_id: uuid::Uuid,
options: Option<ProxyHostGetOptions>,
tx: Option<&mut DatabaseTransaction>,
tx: &Option<&mut DatabaseTransaction>,
) -> Result<ProxyHostInfo, ServiceError>;
async fn update_proxy(
&self,
proxy_id: uuid::Uuid,
update: UpdateProxyHostInfo,
tx: Option<&mut DatabaseTransaction>,
tx: &Option<&mut DatabaseTransaction>,
) -> Result<ProxyHostInfo, ServiceError>;
async fn delete_proxy(
&self,
proxy_id: uuid::Uuid,
tx: Option<&mut DatabaseTransaction>,
tx: &Option<&mut DatabaseTransaction>,
) -> Result<(), ServiceError>;
async fn generate_config(
&self,
builder: &mut NginxConfigBuilder,
tx: &Option<&mut DatabaseTransaction>,
) -> Result<(), ServiceError>;
}
@@ -78,18 +86,18 @@ impl ProxyService for ProxyServiceImpl {
async fn create_proxy(
&self,
create_info: ProxyHostCreateInfo,
tx: Option<&mut DatabaseTransaction>,
tx: &Option<&mut DatabaseTransaction>,
) -> Result<ProxyHostInfo, ServiceError> {
let (proxy_host, location_models): (proxy_host::ActiveModel, Vec<location::ActiveModel>) =
create_info.into();
let mut maybe_owned_tx: Option<DatabaseTransaction> = 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 owned_tx = match tx {
Some(_) => None,
None => Some(self.connection.begin().await.map_err(ServiceError::from)?),
};
let tx_ref = owned_tx.as_ref().or(tx.as_deref());
let r = with_conn!(&*self.connection, tx_ref, conn, {
let inserted_proxy = proxy_host.insert(*conn).await?;
let mut inserted_location_models: Vec<location::Model> =
@@ -103,16 +111,13 @@ impl ProxyService for ProxyServiceImpl {
(inserted_proxy, inserted_location_models)
});
if let Some(t) = maybe_owned_tx.take() {
t.commit().await?;
}
Ok(r.into())
}
async fn get_total_proxies(
&self,
_options: Option<ProxyTotalCountOptions>,
tx: Option<&mut DatabaseTransaction>,
tx: &Option<&mut DatabaseTransaction>,
) -> Result<u64, ServiceError> {
#[derive(Debug, FromQueryResult)]
struct CountResult {
@@ -133,7 +138,7 @@ impl ProxyService for ProxyServiceImpl {
&self,
pagination: Option<PaginationFilter>,
options: Option<ProxyHostListOptions>,
tx: Option<&mut DatabaseTransaction>,
tx: &Option<&mut DatabaseTransaction>,
) -> Result<Vec<ProxyHostInfo>, ServiceError> {
let r = with_conn!(&*self.connection, tx, conn, {
let mut find_query = proxy_host::Entity::find();
@@ -177,7 +182,7 @@ impl ProxyService for ProxyServiceImpl {
&self,
proxy_id: uuid::Uuid,
options: Option<ProxyHostGetOptions>,
tx: Option<&mut DatabaseTransaction>,
tx: &Option<&mut DatabaseTransaction>,
) -> Result<ProxyHostInfo, ServiceError> {
let r: ProxyHostInfo = with_conn!(&*self.connection, tx, conn, {
let find_query = proxy_host::Entity::find_by_id(proxy_id)
@@ -217,7 +222,7 @@ impl ProxyService for ProxyServiceImpl {
&self,
proxy_id: uuid::Uuid,
update: UpdateProxyHostInfo,
tx: Option<&mut DatabaseTransaction>,
tx: &Option<&mut DatabaseTransaction>,
) -> Result<ProxyHostInfo, ServiceError> {
let current_model = with_conn!(&*self.connection, tx, conn, {
proxy_host::Entity::find_by_id(proxy_id)
@@ -239,7 +244,7 @@ impl ProxyService for ProxyServiceImpl {
async fn delete_proxy(
&self,
proxy_id: uuid::Uuid,
tx: Option<&mut DatabaseTransaction>,
tx: &Option<&mut DatabaseTransaction>,
) -> Result<(), ServiceError> {
let model = with_conn!(&*self.connection, tx, conn, {
proxy_host::Entity::find_by_id(proxy_id)
@@ -255,6 +260,25 @@ impl ProxyService for ProxyServiceImpl {
Ok(())
})
}
async fn generate_config(
&self,
builder: &mut NginxConfigBuilder,
tx: &Option<&mut DatabaseTransaction>,
) -> Result<(), ServiceError> {
let proxies = self
.get_proxies(
None,
Some(ProxyHostListOptions {
include_upstream: true,
..Default::default()
}),
tx,
)
.await?;
builder.add_proxy_hosts(proxies);
Ok(())
}
}
#[cfg(test)]
@@ -331,7 +355,7 @@ mod tests {
locations: Vec::new(),
};
let res = svc.create_proxy(create_info, None).await;
let res = svc.create_proxy(create_info, &None).await;
assert!(res.is_ok());
let info = res.expect("Failed to create proxy");
assert_eq!(info.domain, "example.com");
@@ -345,7 +369,7 @@ mod tests {
let svc = ProxyServiceImpl::new(Arc::new(db));
let res = svc
.get_total_proxies(None, None)
.get_total_proxies(None, &None)
.await
.expect("Failed to get total proxies");
assert_eq!(res, 0u64);
@@ -398,7 +422,7 @@ mod tests {
.into_connection();
let svc = ProxyServiceImpl::new(Arc::new(db));
let res = svc.get_proxies(None, None, None).await;
let res = svc.get_proxies(None, None, &None).await;
assert!(res.is_ok());
let list = res.expect("Failed to get proxies");
assert_eq!(list.len(), 2);
@@ -431,7 +455,7 @@ mod tests {
.into_connection();
let svc = ProxyServiceImpl::new(Arc::new(db));
let res = svc.get_proxy(id, None, None).await;
let res = svc.get_proxy(id, None, &None).await;
assert!(res.is_ok());
let got = res.expect("Failed to get proxy");
assert_eq!(got.id, id);
@@ -444,7 +468,7 @@ mod tests {
.into_connection();
let svc = ProxyServiceImpl::new(Arc::new(db));
let res = svc.get_proxy(uuid::Uuid::new_v4(), None, None).await;
let res = svc.get_proxy(uuid::Uuid::new_v4(), None, &None).await;
assert!(matches!(res, Err(ServiceError::NotFound(_))));
}
@@ -510,7 +534,7 @@ mod tests {
default_upstream_id: None,
};
let res = svc.update_proxy(id, update_info, None).await;
let res = svc.update_proxy(id, update_info, &None).await;
assert!(res.is_ok());
let got = res.expect("Failed to update proxy");
assert_eq!(got.name.expect("Name should be present"), "new");
@@ -541,7 +565,7 @@ mod tests {
meta: None,
default_upstream_id: None,
},
None,
&None,
)
.await;
@@ -580,7 +604,7 @@ mod tests {
let svc = ProxyServiceImpl::new(Arc::new(db));
let res = svc.delete_proxy(id, None).await;
let res = svc.delete_proxy(id, &None).await;
assert!(res.is_ok());
}
@@ -592,7 +616,7 @@ mod tests {
let svc = ProxyServiceImpl::new(Arc::new(db));
let res = svc.delete_proxy(uuid::Uuid::new_v4(), None).await;
let res = svc.delete_proxy(uuid::Uuid::new_v4(), &None).await;
assert!(matches!(res, Err(ServiceError::NotFound(_))));
}
}

View File

@@ -88,7 +88,7 @@ pub trait UpstreamService: Send + Sync {
async fn generate_config(
&self,
builder: &mut NginxConfigBuilder,
tx: Option<&mut DatabaseTransaction>,
tx: &Option<&mut DatabaseTransaction>,
) -> Result<(), ServiceError>;
}
@@ -457,7 +457,7 @@ impl UpstreamService for UpstreamServiceImpl {
async fn generate_config(
&self,
builder: &mut NginxConfigBuilder,
tx: Option<&mut DatabaseTransaction>,
tx: &Option<&mut DatabaseTransaction>,
) -> Result<(), ServiceError> {
// get all upstreams and their targets
let upstreams = with_conn!(&*self.connection, tx, conn, {