Compare commits
	
		
			4 Commits
		
	
	
		
			131d978450
			...
			a63cbe2bd9
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | a63cbe2bd9 | ||
|  | 1e4c0ac41a | ||
|  | 0e49be8d71 | ||
|  | 32339e6063 | 
							
								
								
									
										47
									
								
								service_manager/examples/README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								service_manager/examples/README.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,47 @@ | |||||||
|  | # Service Manager Examples | ||||||
|  |  | ||||||
|  | This directory contains examples demonstrating the usage of the `sal-service-manager` crate. | ||||||
|  |  | ||||||
|  | ## Running Examples | ||||||
|  |  | ||||||
|  | To run any example, use the following command structure from the `service_manager` crate's root directory: | ||||||
|  |  | ||||||
|  | ```sh | ||||||
|  | cargo run --example <EXAMPLE_NAME> | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | --- | ||||||
|  |  | ||||||
|  | ### 1. `simple_service` | ||||||
|  |  | ||||||
|  | This example demonstrates the ideal, clean lifecycle of a service using the separated `create` and `start` steps. | ||||||
|  |  | ||||||
|  | **Behavior:** | ||||||
|  | 1.  Creates a new service definition. | ||||||
|  | 2.  Starts the newly created service. | ||||||
|  | 3.  Checks its status to confirm it's running. | ||||||
|  | 4.  Stops the service. | ||||||
|  | 5.  Checks its status again to confirm it's stopped. | ||||||
|  | 6.  Removes the service definition. | ||||||
|  |  | ||||||
|  | **Run it:** | ||||||
|  | ```sh | ||||||
|  | cargo run --example simple_service | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | ### 2. `service_spaghetti` | ||||||
|  |  | ||||||
|  | This example demonstrates how the service manager handles "messy" or improper sequences of operations, showcasing its error handling and robustness. | ||||||
|  |  | ||||||
|  | **Behavior:** | ||||||
|  | 1.  Creates a service. | ||||||
|  | 2.  Starts the service. | ||||||
|  | 3.  Tries to start the **same service again** (which should fail as it's already running). | ||||||
|  | 4.  Removes the service **without stopping it first** (the manager should handle this gracefully). | ||||||
|  | 5.  Tries to stop the **already removed** service (which should fail). | ||||||
|  | 6.  Tries to remove the service **again** (which should also fail). | ||||||
|  |  | ||||||
|  | **Run it:** | ||||||
|  | ```sh | ||||||
|  | cargo run --example service_spaghetti | ||||||
|  | ``` | ||||||
							
								
								
									
										100
									
								
								service_manager/examples/service_spaghetti.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										100
									
								
								service_manager/examples/service_spaghetti.rs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,100 @@ | |||||||
|  | //! service_spaghetti - An example of messy service management. | ||||||
|  | //! | ||||||
|  | //! This example demonstrates how the service manager behaves when commands | ||||||
|  | //! are issued in a less-than-ideal order, such as starting a service that's | ||||||
|  | //! already running or removing a service that hasn't been stopped. | ||||||
|  |  | ||||||
|  | use sal_service_manager::{create_service_manager, ServiceConfig}; | ||||||
|  | use std::collections::HashMap; | ||||||
|  | use std::thread; | ||||||
|  | use std::time::Duration; | ||||||
|  |  | ||||||
|  | fn main() { | ||||||
|  |     let manager = create_service_manager(); | ||||||
|  |     let service_name = "com.herocode.examples.spaghetti"; | ||||||
|  |  | ||||||
|  |     let service_config = ServiceConfig { | ||||||
|  |         name: service_name.to_string(), | ||||||
|  |         binary_path: "/bin/sh".to_string(), | ||||||
|  |         args: vec![ | ||||||
|  |             "-c".to_string(), | ||||||
|  |             "while true; do echo 'Spaghetti service is running...'; sleep 5; done".to_string(), | ||||||
|  |         ], | ||||||
|  |         working_directory: None, | ||||||
|  |         environment: HashMap::new(), | ||||||
|  |         auto_restart: false, | ||||||
|  |     }; | ||||||
|  |  | ||||||
|  |     println!("--- Service Spaghetti Example ---"); | ||||||
|  |     println!("This example demonstrates messy, error-prone service management."); | ||||||
|  |  | ||||||
|  |     // Cleanup from previous runs to ensure a clean slate | ||||||
|  |     if let Ok(true) = manager.exists(service_name) { | ||||||
|  |         println!( | ||||||
|  |             "\nService '{}' found from a previous run. Cleaning up first.", | ||||||
|  |             service_name | ||||||
|  |         ); | ||||||
|  |         let _ = manager.stop(service_name); | ||||||
|  |         let _ = manager.remove(service_name); | ||||||
|  |         println!("Cleanup complete."); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     // 1. Start the service (creates and starts in one step) | ||||||
|  |     println!("\n1. Starting the service for the first time..."); | ||||||
|  |     match manager.start(&service_config) { | ||||||
|  |         Ok(()) => println!("   -> Success: Service '{}' started.", service_name), | ||||||
|  |         Err(e) => { | ||||||
|  |             eprintln!( | ||||||
|  |                 "   -> Error: Failed to start service: {}. Halting example.", | ||||||
|  |                 e | ||||||
|  |             ); | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     thread::sleep(Duration::from_secs(2)); | ||||||
|  |  | ||||||
|  |     // 2. Try to start the service again while it's already running | ||||||
|  |     println!("\n2. Trying to start the *same service* again..."); | ||||||
|  |     match manager.start(&service_config) { | ||||||
|  |         Ok(()) => println!("   -> Unexpected Success: Service started again."), | ||||||
|  |         Err(e) => eprintln!( | ||||||
|  |             "   -> Expected Error: {}. The manager should detect it is already running.", | ||||||
|  |             e | ||||||
|  |         ), | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     // 3. Let it run for a bit | ||||||
|  |     println!("\n3. Letting the service run for 5 seconds..."); | ||||||
|  |     thread::sleep(Duration::from_secs(5)); | ||||||
|  |  | ||||||
|  |     // 4. Remove the service without stopping it first | ||||||
|  |     // The `remove` function is designed to stop the service if it's running. | ||||||
|  |     println!("\n4. Removing the service without explicitly stopping it first..."); | ||||||
|  |     match manager.remove(service_name) { | ||||||
|  |         Ok(()) => println!("   -> Success: Service was stopped and removed."), | ||||||
|  |         Err(e) => eprintln!("   -> Error: Failed to remove service: {}", e), | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     // 5. Try to stop the service after it has been removed | ||||||
|  |     println!("\n5. Trying to stop the service that was just removed..."); | ||||||
|  |     match manager.stop(service_name) { | ||||||
|  |         Ok(()) => println!("   -> Unexpected Success: Stopped a removed service."), | ||||||
|  |         Err(e) => eprintln!( | ||||||
|  |             "   -> Expected Error: {}. The manager knows the service is gone.", | ||||||
|  |             e | ||||||
|  |         ), | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     // 6. Try to remove the service again | ||||||
|  |     println!("\n6. Trying to remove the service again..."); | ||||||
|  |     match manager.remove(service_name) { | ||||||
|  |         Ok(()) => println!("   -> Unexpected Success: Removed a non-existent service."), | ||||||
|  |         Err(e) => eprintln!( | ||||||
|  |             "   -> Expected Error: {}. The manager correctly reports it's not found.", | ||||||
|  |             e | ||||||
|  |         ), | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     println!("\n--- Spaghetti Example Finished ---"); | ||||||
|  | } | ||||||
							
								
								
									
										101
									
								
								service_manager/examples/simple_service.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										101
									
								
								service_manager/examples/simple_service.rs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,101 @@ | |||||||
|  | use sal_service_manager::{create_service_manager, ServiceConfig}; | ||||||
|  | use std::collections::HashMap; | ||||||
|  | use std::thread; | ||||||
|  | use std::time::Duration; | ||||||
|  |  | ||||||
|  | fn main() { | ||||||
|  |     // 1. Create a service manager for the current platform | ||||||
|  |     let manager = create_service_manager(); | ||||||
|  |  | ||||||
|  |     // 2. Define the configuration for our new service | ||||||
|  |     let service_name = "com.herocode.examples.simpleservice"; | ||||||
|  |     let service_config = ServiceConfig { | ||||||
|  |         name: service_name.to_string(), | ||||||
|  |         // A simple command that runs in a loop | ||||||
|  |         binary_path: "/bin/sh".to_string(), | ||||||
|  |         args: vec![ | ||||||
|  |             "-c".to_string(), | ||||||
|  |             "while true; do echo 'Simple service is running...'; date; sleep 5; done".to_string(), | ||||||
|  |         ], | ||||||
|  |         working_directory: None, | ||||||
|  |         environment: HashMap::new(), | ||||||
|  |         auto_restart: false, | ||||||
|  |     }; | ||||||
|  |  | ||||||
|  |     println!("--- Service Manager Example ---"); | ||||||
|  |  | ||||||
|  |     // Cleanup from previous runs, if necessary | ||||||
|  |     if let Ok(true) = manager.exists(service_name) { | ||||||
|  |         println!( | ||||||
|  |             "Service '{}' already exists. Cleaning up before starting.", | ||||||
|  |             service_name | ||||||
|  |         ); | ||||||
|  |         if let Err(e) = manager.stop(service_name) { | ||||||
|  |             println!( | ||||||
|  |                 "Note: could not stop existing service (it might not be running): {}", | ||||||
|  |                 e | ||||||
|  |             ); | ||||||
|  |         } | ||||||
|  |         if let Err(e) = manager.remove(service_name) { | ||||||
|  |             eprintln!("Error: failed to remove existing service: {}", e); | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  |         println!("Cleanup complete."); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     // 3. Start the service (creates and starts in one step) | ||||||
|  |     println!("\n1. Starting service: '{}'", service_name); | ||||||
|  |     match manager.start(&service_config) { | ||||||
|  |         Ok(()) => println!("Service '{}' started successfully.", service_name), | ||||||
|  |         Err(e) => { | ||||||
|  |             eprintln!("Error: Failed to start service '{}': {}", service_name, e); | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     // Give it a moment to run | ||||||
|  |     println!("\nWaiting for 2 seconds for the service to initialize..."); | ||||||
|  |     thread::sleep(Duration::from_secs(2)); | ||||||
|  |  | ||||||
|  |     // 4. Check the status of the service | ||||||
|  |     println!("\n2. Checking service status..."); | ||||||
|  |     match manager.status(service_name) { | ||||||
|  |         Ok(status) => println!("Service status: {:?}", status), | ||||||
|  |         Err(e) => eprintln!( | ||||||
|  |             "Error: Failed to get status for service '{}': {}", | ||||||
|  |             service_name, e | ||||||
|  |         ), | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     println!("\nLetting the service run for 10 seconds. Check logs if you can."); | ||||||
|  |     thread::sleep(Duration::from_secs(10)); | ||||||
|  |  | ||||||
|  |     // 5. Stop the service | ||||||
|  |     println!("\n3. Stopping service: '{}'", service_name); | ||||||
|  |     match manager.stop(service_name) { | ||||||
|  |         Ok(()) => println!("Service '{}' stopped successfully.", service_name), | ||||||
|  |         Err(e) => eprintln!("Error: Failed to stop service '{}': {}", service_name, e), | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     println!("\nWaiting for 2 seconds for the service to stop..."); | ||||||
|  |     thread::sleep(Duration::from_secs(2)); | ||||||
|  |  | ||||||
|  |     // Check status again | ||||||
|  |     println!("\n4. Checking status after stopping..."); | ||||||
|  |     match manager.status(service_name) { | ||||||
|  |         Ok(status) => println!("Service status: {:?}", status), | ||||||
|  |         Err(e) => eprintln!( | ||||||
|  |             "Error: Failed to get status for service '{}': {}", | ||||||
|  |             service_name, e | ||||||
|  |         ), | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     // 6. Remove the service | ||||||
|  |     println!("\n5. Removing service: '{}'", service_name); | ||||||
|  |     match manager.remove(service_name) { | ||||||
|  |         Ok(()) => println!("Service '{}' removed successfully.", service_name), | ||||||
|  |         Err(e) => eprintln!("Error: Failed to remove service '{}': {}", service_name, e), | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     println!("\n--- Example Finished ---"); | ||||||
|  | } | ||||||
		Reference in New Issue
	
	Block a user