From 425215442097b86959dfad3a14829818727b7745 Mon Sep 17 00:00:00 2001 From: GW_MC <72297530+GWMCwing@users.noreply.github.com> Date: Mon, 27 Apr 2026 07:15:30 +0000 Subject: [PATCH] fix: enhance NginxHandler to return config file paths and improve error handling --- .../nxmesh-agent/src/service/nginx_handler.rs | 25 +++++++++++-------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/apps/nxmesh-agent/src/service/nginx_handler.rs b/apps/nxmesh-agent/src/service/nginx_handler.rs index b5b0979..1a48cb4 100644 --- a/apps/nxmesh-agent/src/service/nginx_handler.rs +++ b/apps/nxmesh-agent/src/service/nginx_handler.rs @@ -1,6 +1,6 @@ use std::sync::Arc; -use anyhow::Result; +use anyhow::{Context, Result}; use fs4::tokio::AsyncFileExt; use tokio::{io::AsyncWriteExt, process::Command}; use tracing::{debug, warn}; @@ -13,7 +13,7 @@ use mockall::predicate::*; #[async_trait::async_trait] #[cfg_attr(test, mockall::automock)] -pub trait NginxHandler { +pub trait NginxHandler: Send + Sync { // Reload nginx to apply new config. The config_path is an optional parameter that specifies the path to the nginx config file to be used for this reload operation. If not provided, the default config path will be used. async fn reload(&self, config_path: Option<&str>) -> Result<()>; async fn stop(&self) -> Result<()>; @@ -27,14 +27,14 @@ pub trait NginxHandler { deployment_id: &str, config_content: &str, output_path: &str, - ) -> Result<()>; + ) -> Result; // Append a new config content to an existing config file for nginx. This is useful for some use cases where we want to keep the existing config and just add some new config content to it. The output_path is a relative path to the nginx config directory of the deployment folder, which should be the same as the one used in write_config function. Path traversal is not allowed. async fn append_config( &self, deployment_id: &str, config_content: &str, output_path: &str, - ) -> Result<()>; + ) -> Result; // clean up old config files that are applied to nginx // keep only latest n deployments. @@ -231,15 +231,20 @@ impl NginxHandler for NginxHandlerImpl { deployment_id: &str, config_content: &str, output_path: &str, - ) -> Result<()> { + ) -> Result { let full_output_path = self .get_deployment_config_path(deployment_id, output_path, true) .await?; + let parent_dir = full_output_path + .parent() + .context("Failed to get parent directory of the config file")?; + // ensure the parent directory exists before creating the file + tokio::fs::create_dir_all(parent_dir).await?; let mut file = tokio::fs::OpenOptions::new() .write(true) .create(true) .truncate(true) - .open(full_output_path) + .open(full_output_path.clone()) .await?; // lock the file for writing to prevent concurrent write issue file.lock_exclusive()?; @@ -247,7 +252,7 @@ impl NginxHandler for NginxHandlerImpl { file.unlock()?; file.flush().await?; - Ok(()) + Ok(full_output_path.to_string_lossy().to_string()) } async fn append_config( @@ -255,7 +260,7 @@ impl NginxHandler for NginxHandlerImpl { deployment_id: &str, config_content: &str, output_path: &str, - ) -> Result<()> { + ) -> Result { let full_output_path = self .get_deployment_config_path(deployment_id, output_path, true) .await?; @@ -263,7 +268,7 @@ impl NginxHandler for NginxHandlerImpl { .write(true) .create(true) .append(true) - .open(full_output_path) + .open(full_output_path.clone()) .await?; // lock the file for writing to prevent concurrent write issue file.lock_exclusive()?; @@ -271,7 +276,7 @@ impl NginxHandler for NginxHandlerImpl { file.unlock()?; file.flush().await?; - Ok(()) + Ok(full_output_path.to_string_lossy().to_string()) } async fn cleanup_config(&self, n: usize) -> Result<()> {