wip
This commit is contained in:
		
							
								
								
									
										116
									
								
								examples/scripts/service_manager/README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										116
									
								
								examples/scripts/service_manager/README.md
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,116 @@
 | 
			
		||||
# Service Manager Examples
 | 
			
		||||
 | 
			
		||||
This directory contains examples demonstrating the SAL service manager functionality for dynamically launching and managing services across platforms.
 | 
			
		||||
 | 
			
		||||
## Overview
 | 
			
		||||
 | 
			
		||||
The service manager provides a unified interface for managing system services:
 | 
			
		||||
- **macOS**: Uses `launchctl` for service management
 | 
			
		||||
- **Linux**: Uses `zinit` for service management (systemd also available as alternative)
 | 
			
		||||
 | 
			
		||||
## Examples
 | 
			
		||||
 | 
			
		||||
### 1. Circle Worker Manager (`circle_worker_manager.rhai`)
 | 
			
		||||
 | 
			
		||||
**Primary Use Case**: Demonstrates dynamic circle worker management for freezone residents.
 | 
			
		||||
 | 
			
		||||
This example shows:
 | 
			
		||||
- Creating service configurations for circle workers
 | 
			
		||||
- Complete service lifecycle management (start, stop, restart, remove)
 | 
			
		||||
- Status monitoring and log retrieval
 | 
			
		||||
- Error handling and cleanup
 | 
			
		||||
 | 
			
		||||
```bash
 | 
			
		||||
# Run the circle worker management example
 | 
			
		||||
herodo examples/service_manager/circle_worker_manager.rhai
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
### 2. Basic Usage (`basic_usage.rhai`)
 | 
			
		||||
 | 
			
		||||
**Learning Example**: Simple demonstration of the core service manager API.
 | 
			
		||||
 | 
			
		||||
This example covers:
 | 
			
		||||
- Creating and configuring services
 | 
			
		||||
- Starting and stopping services
 | 
			
		||||
- Checking service status
 | 
			
		||||
- Listing managed services
 | 
			
		||||
- Retrieving service logs
 | 
			
		||||
 | 
			
		||||
```bash
 | 
			
		||||
# Run the basic usage example
 | 
			
		||||
herodo examples/service_manager/basic_usage.rhai
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
## Prerequisites
 | 
			
		||||
 | 
			
		||||
### Linux (zinit)
 | 
			
		||||
 | 
			
		||||
Make sure zinit is installed and running:
 | 
			
		||||
 | 
			
		||||
```bash
 | 
			
		||||
# Start zinit with default socket
 | 
			
		||||
zinit -s /tmp/zinit.sock init
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
### macOS (launchctl)
 | 
			
		||||
 | 
			
		||||
No additional setup required - uses the built-in launchctl system.
 | 
			
		||||
 | 
			
		||||
## Service Manager API
 | 
			
		||||
 | 
			
		||||
The service manager provides these key functions:
 | 
			
		||||
 | 
			
		||||
- `create_service_manager()` - Create platform-appropriate service manager
 | 
			
		||||
- `start(manager, config)` - Start a new service
 | 
			
		||||
- `stop(manager, service_name)` - Stop a running service
 | 
			
		||||
- `restart(manager, service_name)` - Restart a service
 | 
			
		||||
- `status(manager, service_name)` - Get service status
 | 
			
		||||
- `logs(manager, service_name, lines)` - Retrieve service logs
 | 
			
		||||
- `list(manager)` - List all managed services
 | 
			
		||||
- `remove(manager, service_name)` - Remove a service
 | 
			
		||||
- `exists(manager, service_name)` - Check if service exists
 | 
			
		||||
- `start_and_confirm(manager, config, timeout)` - Start with confirmation
 | 
			
		||||
 | 
			
		||||
## Service Configuration
 | 
			
		||||
 | 
			
		||||
Services are configured using a map with these fields:
 | 
			
		||||
 | 
			
		||||
```rhai
 | 
			
		||||
let config = #{
 | 
			
		||||
    name: "my-service",                    // Service name
 | 
			
		||||
    binary_path: "/usr/bin/my-app",        // Executable path
 | 
			
		||||
    args: ["--config", "/etc/my-app.conf"], // Command arguments
 | 
			
		||||
    working_directory: "/var/lib/my-app",   // Working directory (optional)
 | 
			
		||||
    environment: #{                         // Environment variables
 | 
			
		||||
        "VAR1": "value1",
 | 
			
		||||
        "VAR2": "value2"
 | 
			
		||||
    },
 | 
			
		||||
    auto_restart: true                      // Auto-restart on failure
 | 
			
		||||
};
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
## Real-World Usage
 | 
			
		||||
 | 
			
		||||
The circle worker example demonstrates the exact use case requested by the team:
 | 
			
		||||
 | 
			
		||||
> "We want to be able to launch circle workers dynamically. For instance when someone registers to the freezone, we need to be able to launch a circle worker for the new resident."
 | 
			
		||||
 | 
			
		||||
The service manager enables:
 | 
			
		||||
1. **Dynamic service creation** - Create services on-demand for new residents
 | 
			
		||||
2. **Cross-platform support** - Works on both macOS and Linux
 | 
			
		||||
3. **Lifecycle management** - Full control over service lifecycle
 | 
			
		||||
4. **Monitoring and logging** - Track service status and retrieve logs
 | 
			
		||||
5. **Cleanup** - Proper service removal when no longer needed
 | 
			
		||||
 | 
			
		||||
## Error Handling
 | 
			
		||||
 | 
			
		||||
All service manager functions can throw errors. Use try-catch blocks for robust error handling:
 | 
			
		||||
 | 
			
		||||
```rhai
 | 
			
		||||
try {
 | 
			
		||||
    sm::start(manager, config);
 | 
			
		||||
    print("✅ Service started successfully");
 | 
			
		||||
} catch (error) {
 | 
			
		||||
    print(`❌ Failed to start service: ${error}`);
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
							
								
								
									
										85
									
								
								examples/scripts/service_manager/basic_usage.rhai
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										85
									
								
								examples/scripts/service_manager/basic_usage.rhai
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,85 @@
 | 
			
		||||
// Basic Service Manager Usage Example
 | 
			
		||||
//
 | 
			
		||||
// This example demonstrates the basic API of the service manager.
 | 
			
		||||
// It works on both macOS (launchctl) and Linux (zinit/systemd).
 | 
			
		||||
//
 | 
			
		||||
// Prerequisites:
 | 
			
		||||
//
 | 
			
		||||
// Linux: The service manager will automatically discover running zinit servers
 | 
			
		||||
//        or fall back to systemd. To use zinit, start it with:
 | 
			
		||||
//   zinit -s /tmp/zinit.sock init
 | 
			
		||||
//
 | 
			
		||||
//   You can also specify a custom socket path:
 | 
			
		||||
//   export ZINIT_SOCKET_PATH=/your/custom/path/zinit.sock
 | 
			
		||||
//
 | 
			
		||||
// macOS: No additional setup required (uses launchctl).
 | 
			
		||||
//
 | 
			
		||||
// Usage:
 | 
			
		||||
//   herodo examples/service_manager/basic_usage.rhai
 | 
			
		||||
 | 
			
		||||
// Service Manager Basic Usage Example
 | 
			
		||||
// This example uses the SAL service manager through Rhai integration
 | 
			
		||||
 | 
			
		||||
print("🚀 Basic Service Manager Usage Example");
 | 
			
		||||
print("======================================");
 | 
			
		||||
 | 
			
		||||
// Create a service manager for the current platform
 | 
			
		||||
let manager = create_service_manager();
 | 
			
		||||
 | 
			
		||||
print("🍎 Using service manager for current platform");
 | 
			
		||||
 | 
			
		||||
// Create a simple service configuration
 | 
			
		||||
let config = #{
 | 
			
		||||
    name: "example-service",
 | 
			
		||||
    binary_path: "/bin/echo",
 | 
			
		||||
    args: ["Hello from service manager!"],
 | 
			
		||||
    working_directory: "/tmp",
 | 
			
		||||
    environment: #{
 | 
			
		||||
        "EXAMPLE_VAR": "hello_world"
 | 
			
		||||
    },
 | 
			
		||||
    auto_restart: false
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
print("\n📝 Service Configuration:");
 | 
			
		||||
print(`   Name: ${config.name}`);
 | 
			
		||||
print(`   Binary: ${config.binary_path}`);
 | 
			
		||||
print(`   Args: ${config.args}`);
 | 
			
		||||
 | 
			
		||||
// Start the service
 | 
			
		||||
print("\n🚀 Starting service...");
 | 
			
		||||
start(manager, config);
 | 
			
		||||
print("✅ Service started successfully");
 | 
			
		||||
 | 
			
		||||
// Check service status
 | 
			
		||||
print("\n📊 Checking service status...");
 | 
			
		||||
let status = status(manager, "example-service");
 | 
			
		||||
print(`Status: ${status}`);
 | 
			
		||||
 | 
			
		||||
// List all services
 | 
			
		||||
print("\n📋 Listing all managed services...");
 | 
			
		||||
let services = list(manager);
 | 
			
		||||
print(`Found ${services.len()} services:`);
 | 
			
		||||
for service in services {
 | 
			
		||||
    print(`  - ${service}`);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Get service logs
 | 
			
		||||
print("\n📄 Getting service logs...");
 | 
			
		||||
let logs = logs(manager, "example-service", 5);
 | 
			
		||||
if logs.trim() == "" {
 | 
			
		||||
    print("No logs available");
 | 
			
		||||
} else {
 | 
			
		||||
    print(`Logs:\n${logs}`);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Stop the service
 | 
			
		||||
print("\n🛑 Stopping service...");
 | 
			
		||||
stop(manager, "example-service");
 | 
			
		||||
print("✅ Service stopped");
 | 
			
		||||
 | 
			
		||||
// Remove the service
 | 
			
		||||
print("\n🗑️  Removing service...");
 | 
			
		||||
remove(manager, "example-service");
 | 
			
		||||
print("✅ Service removed");
 | 
			
		||||
 | 
			
		||||
print("\n🎉 Example completed successfully!");
 | 
			
		||||
							
								
								
									
										141
									
								
								examples/scripts/service_manager/circle_worker_manager.rhai
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										141
									
								
								examples/scripts/service_manager/circle_worker_manager.rhai
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,141 @@
 | 
			
		||||
// Circle Worker Manager Example
 | 
			
		||||
//
 | 
			
		||||
// This example demonstrates how to use the service manager to dynamically launch
 | 
			
		||||
// circle workers for new freezone residents. This is the primary use case requested
 | 
			
		||||
// by the team.
 | 
			
		||||
//
 | 
			
		||||
// Usage:
 | 
			
		||||
//
 | 
			
		||||
// On macOS (uses launchctl):
 | 
			
		||||
//   herodo examples/service_manager/circle_worker_manager.rhai
 | 
			
		||||
//
 | 
			
		||||
// On Linux (uses zinit - requires zinit to be running):
 | 
			
		||||
//   First start zinit: zinit -s /tmp/zinit.sock init
 | 
			
		||||
//   herodo examples/service_manager/circle_worker_manager.rhai
 | 
			
		||||
 | 
			
		||||
// Circle Worker Manager Example
 | 
			
		||||
// This example uses the SAL service manager through Rhai integration
 | 
			
		||||
 | 
			
		||||
print("🚀 Circle Worker Manager Example");
 | 
			
		||||
print("=================================");
 | 
			
		||||
 | 
			
		||||
// Create the appropriate service manager for the current platform
 | 
			
		||||
let service_manager = create_service_manager();
 | 
			
		||||
print("✅ Created service manager for current platform");
 | 
			
		||||
 | 
			
		||||
// Simulate a new freezone resident registration
 | 
			
		||||
let resident_id = "resident_12345";
 | 
			
		||||
let worker_name = `circle-worker-${resident_id}`;
 | 
			
		||||
 | 
			
		||||
print(`\n📝 New freezone resident registered: ${resident_id}`);
 | 
			
		||||
print(`🔧 Creating circle worker service: ${worker_name}`);
 | 
			
		||||
 | 
			
		||||
// Create service configuration for the circle worker
 | 
			
		||||
let config = #{
 | 
			
		||||
    name: worker_name,
 | 
			
		||||
    binary_path: "/bin/sh",
 | 
			
		||||
    args: [
 | 
			
		||||
        "-c",
 | 
			
		||||
        `echo 'Circle worker for ${resident_id} starting...'; sleep 30; echo 'Circle worker for ${resident_id} completed'`
 | 
			
		||||
    ],
 | 
			
		||||
    working_directory: "/tmp",
 | 
			
		||||
    environment: #{
 | 
			
		||||
        "RESIDENT_ID": resident_id,
 | 
			
		||||
        "WORKER_TYPE": "circle",
 | 
			
		||||
        "LOG_LEVEL": "info"
 | 
			
		||||
    },
 | 
			
		||||
    auto_restart: true
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
print("📋 Service configuration created:");
 | 
			
		||||
print(`   Name: ${config.name}`);
 | 
			
		||||
print(`   Binary: ${config.binary_path}`);
 | 
			
		||||
print(`   Args: ${config.args}`);
 | 
			
		||||
print(`   Auto-restart: ${config.auto_restart}`);
 | 
			
		||||
 | 
			
		||||
print(`\n🔄 Demonstrating service lifecycle for: ${worker_name}`);
 | 
			
		||||
 | 
			
		||||
// 1. Check if service already exists
 | 
			
		||||
print("\n1️⃣ Checking if service exists...");
 | 
			
		||||
if exists(service_manager, worker_name) {
 | 
			
		||||
    print("⚠️  Service already exists, removing it first...");
 | 
			
		||||
    remove(service_manager, worker_name);
 | 
			
		||||
    print("🗑️  Existing service removed");
 | 
			
		||||
} else {
 | 
			
		||||
    print("✅ Service doesn't exist, ready to create");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 2. Start the service
 | 
			
		||||
print("\n2️⃣ Starting the circle worker service...");
 | 
			
		||||
start(service_manager, config);
 | 
			
		||||
print("✅ Service started successfully");
 | 
			
		||||
 | 
			
		||||
// 3. Check service status
 | 
			
		||||
print("\n3️⃣ Checking service status...");
 | 
			
		||||
let status = status(service_manager, worker_name);
 | 
			
		||||
print(`📊 Service status: ${status}`);
 | 
			
		||||
 | 
			
		||||
// 4. List all services to show our service is there
 | 
			
		||||
print("\n4️⃣ Listing all managed services...");
 | 
			
		||||
let services = list(service_manager);
 | 
			
		||||
print(`📋 Managed services (${services.len()}):`);
 | 
			
		||||
for service in services {
 | 
			
		||||
    let marker = if service == worker_name { "👉" } else { "  " };
 | 
			
		||||
    print(`   ${marker} ${service}`);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 5. Wait a moment and check status again
 | 
			
		||||
print("\n5️⃣ Waiting 3 seconds and checking status again...");
 | 
			
		||||
sleep(3000); // 3 seconds in milliseconds
 | 
			
		||||
let status = status(service_manager, worker_name);
 | 
			
		||||
print(`📊 Service status after 3s: ${status}`);
 | 
			
		||||
 | 
			
		||||
// 6. Get service logs
 | 
			
		||||
print("\n6️⃣ Retrieving service logs...");
 | 
			
		||||
let logs = logs(service_manager, worker_name, 10);
 | 
			
		||||
if logs.trim() == "" {
 | 
			
		||||
    print("📄 No logs available yet (this is normal for new services)");
 | 
			
		||||
} else {
 | 
			
		||||
    print("📄 Recent logs:");
 | 
			
		||||
    let log_lines = logs.split('\n');
 | 
			
		||||
    for i in 0..5 {
 | 
			
		||||
        if i < log_lines.len() {
 | 
			
		||||
            print(`   ${log_lines[i]}`);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 7. Demonstrate start_and_confirm with timeout
 | 
			
		||||
print("\n7️⃣ Testing start_and_confirm (should succeed quickly since already running)...");
 | 
			
		||||
start_and_confirm(service_manager, config, 5);
 | 
			
		||||
print("✅ Service confirmed running within timeout");
 | 
			
		||||
 | 
			
		||||
// 8. Stop the service
 | 
			
		||||
print("\n8️⃣ Stopping the service...");
 | 
			
		||||
stop(service_manager, worker_name);
 | 
			
		||||
print("🛑 Service stopped");
 | 
			
		||||
 | 
			
		||||
// 9. Check status after stopping
 | 
			
		||||
print("\n9️⃣ Checking status after stop...");
 | 
			
		||||
let status = status(service_manager, worker_name);
 | 
			
		||||
print(`📊 Service status after stop: ${status}`);
 | 
			
		||||
 | 
			
		||||
// 10. Restart the service
 | 
			
		||||
print("\n🔟 Restarting the service...");
 | 
			
		||||
restart(service_manager, worker_name);
 | 
			
		||||
print("🔄 Service restarted successfully");
 | 
			
		||||
 | 
			
		||||
// 11. Final cleanup
 | 
			
		||||
print("\n🧹 Cleaning up - removing the service...");
 | 
			
		||||
remove(service_manager, worker_name);
 | 
			
		||||
print("🗑️  Service removed successfully");
 | 
			
		||||
 | 
			
		||||
// 12. Verify removal
 | 
			
		||||
print("\n✅ Verifying service removal...");
 | 
			
		||||
if !exists(service_manager, worker_name) {
 | 
			
		||||
    print("✅ Service successfully removed");
 | 
			
		||||
} else {
 | 
			
		||||
    print("⚠️  Service still exists after removal");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
print("\n🎉 Circle worker management demonstration complete!");
 | 
			
		||||
		Reference in New Issue
	
	Block a user