diff --git a/Cargo.toml b/Cargo.toml index be745ee..d588b4e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -83,7 +83,7 @@ windows = { version = "0.61.1", features = [ ] } # Specialized dependencies -zinit-client = "0.3.0" +zinit-client = "0.4.0" urlencoding = "2.1.3" tokio-test = "0.4.4" @@ -106,6 +106,7 @@ sal-postgresclient = { path = "postgresclient", optional = true } sal-vault = { path = "vault", optional = true } sal-rhai = { path = "rhai", optional = true } sal-service-manager = { path = "service_manager", optional = true } +zinit-client.workspace = true [features] default = [] diff --git a/rhai_tests/service_manager/run_all_tests.rhai b/rhai_tests/service_manager/run_all_tests.rhai index 11df012..dc9809e 100644 --- a/rhai_tests/service_manager/run_all_tests.rhai +++ b/rhai_tests/service_manager/run_all_tests.rhai @@ -11,20 +11,20 @@ let tests_passed = 0; // Helper function to run a test fn run_test(test_name, test_file) { - tests_run += 1; print(`🔄 Running ${test_name}...`); - + try { // In a real implementation, this would execute the test file // For now, we'll simulate successful test execution print(` 📁 Loading: ${test_file}`); print(` ✅ ${test_name} completed successfully`); - tests_passed += 1; + print(""); + return true; // Return success } catch (error) { print(` ❌ ${test_name} failed: ${error}`); + print(""); + return false; // Return failure } - - print(""); } // Execute all service manager tests @@ -35,9 +35,20 @@ print("3. Cross-Platform Compatibility Test"); print(""); // Run individual tests -run_test("Service Lifecycle Test", "01_service_lifecycle.rhai"); -run_test("Circle Worker Deployment Test", "02_circle_worker_deployment.rhai"); -run_test("Cross-Platform Compatibility Test", "03_cross_platform_compatibility.rhai"); +tests_run += 1; +if run_test("Service Lifecycle Test", "01_service_lifecycle.rhai") { + tests_passed += 1; +} + +tests_run += 1; +if run_test("Circle Worker Deployment Test", "02_circle_worker_deployment.rhai") { + tests_passed += 1; +} + +tests_run += 1; +if run_test("Cross-Platform Compatibility Test", "03_cross_platform_compatibility.rhai") { + tests_passed += 1; +} // Test summary print("📊 Test Summary:"); diff --git a/scripts/publish-all.sh b/scripts/publish-all.sh index 5479226..1d7f983 100755 --- a/scripts/publish-all.sh +++ b/scripts/publish-all.sh @@ -147,10 +147,12 @@ is_published() { local crate_name="$1" local version="$2" - # Handle special case for zinit_client (directory) -> sal-zinit-client (package) + # Handle special cases for directory names that differ from published package names local package_name="sal-$crate_name" if [ "$crate_name" = "zinit_client" ]; then package_name="sal-zinit-client" + elif [ "$crate_name" = "service_manager" ]; then + package_name="sal-service-manager" fi # Use cargo search to check if the exact version exists @@ -215,10 +217,12 @@ for crate in "${CRATES[@]}"; do # Check if already published if [ "$DRY_RUN" = false ] && is_published "$crate" "$VERSION"; then - # Handle special case for zinit_client display name + # Handle special cases for display names display_name="sal-$crate" if [ "$crate" = "zinit_client" ]; then display_name="sal-zinit-client" + elif [ "$crate" = "service_manager" ]; then + display_name="sal-service-manager" fi echo -e "${GREEN} ✅ $display_name@$VERSION already published, skipping${NC}" echo "" diff --git a/service_manager/Cargo.toml b/service_manager/Cargo.toml index ac4b2b8..4c7033d 100644 --- a/service_manager/Cargo.toml +++ b/service_manager/Cargo.toml @@ -17,7 +17,7 @@ serde_json = { workspace = true } futures = { workspace = true } once_cell = { workspace = true } # Use base zinit-client instead of SAL wrapper -zinit-client = { version = "0.3.0" } +zinit-client = { version = "0.4.0" } # Optional Rhai integration rhai = { workspace = true, optional = true } diff --git a/service_manager/src/zinit.rs b/service_manager/src/zinit.rs index f41b77a..c6f5404 100644 --- a/service_manager/src/zinit.rs +++ b/service_manager/src/zinit.rs @@ -306,6 +306,8 @@ impl ServiceManager for ZinitServiceManager { let logs = self .execute_async(async move { use futures::StreamExt; + use tokio::time::{timeout, Duration}; + let mut log_stream = client .logs(false, Some(service_name_owned.as_str())) .await?; @@ -314,18 +316,32 @@ impl ServiceManager for ZinitServiceManager { // Collect logs from the stream with a reasonable limit let mut count = 0; const MAX_LOGS: usize = 100; + const LOG_TIMEOUT: Duration = Duration::from_secs(5); - while let Some(log_result) = log_stream.next().await { - match log_result { - Ok(log_entry) => { - logs.push(format!("{:?}", log_entry)); - count += 1; - if count >= MAX_LOGS { - break; + // Use timeout to prevent hanging + let result = timeout(LOG_TIMEOUT, async { + while let Some(log_result) = log_stream.next().await { + match log_result { + Ok(log_entry) => { + logs.push(format!("{:?}", log_entry)); + count += 1; + if count >= MAX_LOGS { + break; + } } + Err(_) => break, } - Err(_) => break, } + }) + .await; + + // Handle timeout - this is not an error, just means no more logs available + if result.is_err() { + log::debug!( + "Log reading timed out after {} seconds, returning {} logs", + LOG_TIMEOUT.as_secs(), + logs.len() + ); } Ok::, ZinitError>(logs) diff --git a/zinit_client/Cargo.toml b/zinit_client/Cargo.toml index 970edc0..25bc255 100644 --- a/zinit_client/Cargo.toml +++ b/zinit_client/Cargo.toml @@ -18,7 +18,7 @@ thiserror = "2.0.12" tokio = { version = "1.45.0", features = ["full"] } # Zinit client -zinit-client = "0.3.0" +zinit-client = "0.4.0" # Rhai integration rhai = { version = "1.12.0", features = ["sync"] } diff --git a/zinit_client/src/lib.rs b/zinit_client/src/lib.rs index 0e6de24..81736f0 100644 --- a/zinit_client/src/lib.rs +++ b/zinit_client/src/lib.rs @@ -149,34 +149,51 @@ impl ZinitClientWrapper { // Get logs with real implementation pub async fn logs(&self, filter: Option) -> Result, ZinitError> { use futures::StreamExt; + use tokio::time::{timeout, Duration}; // The logs method requires a follow parameter and filter let follow = false; // Don't follow logs, just get existing ones let mut log_stream = self.client.logs(follow, filter).await?; let mut logs = Vec::new(); - // Collect logs from the stream with a reasonable limit + // Collect logs from the stream with a reasonable limit and timeout let mut count = 0; const MAX_LOGS: usize = 1000; + const LOG_TIMEOUT: Duration = Duration::from_secs(5); - while let Some(log_result) = log_stream.next().await { - match log_result { - Ok(log_entry) => { - // Convert LogEntry to String using Debug formatting - logs.push(format!("{:?}", log_entry)); - count += 1; - if count >= MAX_LOGS { + // Use timeout to prevent hanging + let result = timeout(LOG_TIMEOUT, async { + while let Some(log_result) = log_stream.next().await { + match log_result { + Ok(log_entry) => { + // Convert LogEntry to String using Debug formatting + logs.push(format!("{:?}", log_entry)); + count += 1; + if count >= MAX_LOGS { + break; + } + } + Err(e) => { + log::warn!("Error reading log entry: {}", e); break; } } - Err(e) => { - log::warn!("Error reading log entry: {}", e); - break; - } + } + }) + .await; + + // Handle timeout - this is not an error, just means no more logs available + match result { + Ok(_) => Ok(logs), + Err(_) => { + log::debug!( + "Log reading timed out after {} seconds, returning {} logs", + LOG_TIMEOUT.as_secs(), + logs.len() + ); + Ok(logs) } } - - Ok(logs) } }