# Circle Launcher - Simplified Builder Pattern This example demonstrates the simplified builder pattern for creating circles and launching them using the unified launcher interface. ## Overview The system now uses a clean builder pattern with two main builders: 1. **Circle Builder** (`new_circle()`) - For creating and saving circles 2. **Launcher Builder** (`new_launcher()`) - For configuring and launching multiple circles ## Usage Examples ### Creating and Saving Circles ```rust use heromodels::models::circle::circle::new_circle; // Create and save a circle let circle = new_circle() .title("My Test Circle") .public_key("02a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2c3d4") .ws_url("ws://127.0.0.1:8080") .description("A test circle for demonstration") .save(); ``` ### Simple Launcher (Direct Spawn Mode) ```rust use heromodels::models::circle::circle::new_launcher; // Launch a single circle in direct spawn mode new_launcher() .add_circle("02a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2c3d4") .redis_url("redis://127.0.0.1:6379") .port(8080) .launch()?; ``` ### Service Manager Mode ```rust // Launch with service manager (uses default worker binary path) new_launcher() .add_circle("02a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2c3d4") .service_manager(true) // Enables service manager with default worker binary .redis_url("redis://127.0.0.1:6379") .port(8080) .launch()?; // Or with custom worker binary path new_launcher() .add_circle("02a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2c3d4") .worker_binary("./custom/path/to/worker") // Custom worker binary path .redis_url("redis://127.0.0.1:6379") .port(8080) .launch()?; ``` ### Multiple Circles with Initialization Scripts ```rust // Launch multiple circles with different configurations new_launcher() .add_circle("02a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2c3d4") .initialization_script("init_script1.rhai") .add_circle("03b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2c3d5") .initialization_script("init_script2.rhai") .add_circle("04c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2c3d6") .worker_binary("./target/release/worker") .redis_url("redis://127.0.0.1:6379") .port(8080) .launch()?; ``` ### Mixed Configuration ```rust // Some circles with scripts, some without new_launcher() .add_circle("02a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2c3d4") .initialization_script("setup.rhai") .add_circle("03b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2c3d5") // No script .add_circle("04c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2c3d6") .initialization_script("config.rhai") .redis_url("redis://127.0.0.1:6379") .port(3000) .launch() .await?; ``` ## Builder Methods ### Circle Builder Methods | Method | Description | Example | |--------|-------------|---------| | `title()` | Sets the circle title | `.title("My Circle")` | | `public_key()` | Sets the circle's public key | `.public_key("02a1b2c3...")` | | `ws_url()` | Sets the WebSocket URL | `.ws_url("ws://127.0.0.1:8080")` | | `description()` | Sets the description | `.description("Test circle")` | | `logo()` | Sets the logo URL | `.logo("https://example.com/logo.png")` | | `add_member()` | Adds a member | `.add_member("member_public_key")` | | `save()` | Saves the circle | `.save()` | ### Launcher Builder Methods | Method | Description | Example | |--------|-------------|---------| | `add_circle()` | Adds a circle by public key | `.add_circle("02a1b2c3...")` | | `initialization_script()` | Sets init script for last added circle | `.initialization_script("init.rhai")` | | `worker_binary()` | Sets custom worker binary path (enables service manager) | `.worker_binary("./custom/worker")` | | `redis_url()` | Sets Redis URL | `.redis_url("redis://127.0.0.1:6379")` | | `port()` | Sets the port | `.port(8080)` | | `service_manager()` | Enables service manager with default worker binary | `.service_manager(true)` | | `launch()` | Launches all configured circles | `.launch()?` | ## Generated Commands The launcher builder generates clean commands: ### Direct Spawn Mode ```bash launcher --redis-url redis://127.0.0.1:6379 --port 8080 \ -c 02a1b2c3... -c 03b2c3d4...:init.rhai -c 04c3d4e5... ``` ### Service Manager Mode ```bash launcher --redis-url redis://127.0.0.1:6379 --port 8080 \ --use-service-manager --worker-binary ../target/release/worker \ -c 02a1b2c3...:init1.rhai -c 03b2c3d4...:init2.rhai -c 04c3d4e5... ``` ## Key Features ### Simplified API - Single way to do things (no multiple methods for the same functionality) - Clean builder pattern for both circles and launcher - Method chaining for fluent interface ### Automatic Mode Detection - **Direct Spawn Mode**: Default behavior - **Service Manager Mode**: Enabled when `service_manager(true)` is called or when `worker_binary()` is called - **Default Worker Binary**: Uses `../target/release/worker` unless custom path is specified ### Flexible Configuration - Add multiple circles in a single launcher - Each circle can have its own initialization script - Mix circles with and without scripts ### Error Handling - Clear error messages for missing configuration - Validation of required parameters - Proper error propagation ## Running the Example ```bash # From the heromodels directory cargo run --example circle_launcher_example ``` ## Notes - The `initialization_script()` method applies to the last circle added with `add_circle()` - Setting a `worker_binary()` automatically enables service manager mode - Redis must be running for the workers to function properly - Public keys must be valid secp256k1 format (64 hex characters) - The launcher binary must be available in PATH or specify full path