- Improve Linux support by automatically discovering zinit sockets using environment variables and common paths. - Add fallback to systemd if no zinit server is detected. - Enhance README with detailed instructions for zinit usage, including custom socket path configuration. - Add example demonstrating zinit socket discovery. - Add logging to show socket discovery process. - Add unit tests for service manager creation and socket discovery.
110 lines
3.9 KiB
Rust
110 lines
3.9 KiB
Rust
//! 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() {
|
|
// Initialize logging to see socket discovery in action
|
|
env_logger::init();
|
|
|
|
let manager = match create_service_manager() {
|
|
Ok(manager) => manager,
|
|
Err(e) => {
|
|
eprintln!("Error: Failed to create service manager: {}", e);
|
|
return;
|
|
}
|
|
};
|
|
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 ---");
|
|
}
|