- 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.
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
# 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
# Run the basic usage example
herodo examples/service_manager/basic_usage.rhai
Prerequisites
Linux (zinit)
Make sure zinit is installed and running:
# 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 managerstart(manager, config)
- Start a new servicestop(manager, service_name)
- Stop a running servicerestart(manager, service_name)
- Restart a servicestatus(manager, service_name)
- Get service statuslogs(manager, service_name, lines)
- Retrieve service logslist(manager)
- List all managed servicesremove(manager, service_name)
- Remove a serviceexists(manager, service_name)
- Check if service existsstart_and_confirm(manager, config, timeout)
- Start with confirmation
Service Configuration
Services are configured using a map with these fields:
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:
- Dynamic service creation - Create services on-demand for new residents
- Cross-platform support - Works on both macOS and Linux
- Lifecycle management - Full control over service lifecycle
- Monitoring and logging - Track service status and retrieve logs
- 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:
try {
sm::start(manager, config);
print("✅ Service started successfully");
} catch (error) {
print(`❌ Failed to start service: ${error}`);
}