# Framework Architecture This document describes the simplified architecture of the WebSocket connection manager framework, built on top of the `circle_client_ws` library. ## Overview The framework provides a clean, builder-pattern API for managing multiple self-managing WebSocket connections. The key architectural principle is **delegation of responsibility** - each `CircleWsClient` is completely autonomous and handles its own lifecycle. ## Core Components ### 1. WsManagerBuilder The builder provides a fluent API for configuring WebSocket connections: ```rust let manager = ws_manager() .private_key("hex_private_key".to_string()) .add_server_url("ws://server1.com".to_string()) .add_server_url("ws://server2.com".to_string()) .build(); ``` **Responsibilities:** - Validate configuration parameters (private key format, URL format) - Collect server URLs and authentication settings - Build the final `WsManager` instance ### 2. WsManager A simplified connection manager that acts as a container for self-managing clients: ```rust pub struct WsManager { clients: Rc>>, private_key: Option, server_urls: Vec, } ``` **Responsibilities:** - Store and organize multiple `CircleWsClient` instances - Provide API for script execution across connections - Coordinate connection establishment (but not maintenance) - Provide connection status and management utilities **What it does NOT do:** - Keep-alive monitoring (delegated to individual clients) - Reconnection logic (delegated to individual clients) - Complex connection state management (delegated to individual clients) ### 3. Self-Managing CircleWsClient Each client is completely autonomous and handles its own lifecycle: **Internal Responsibilities:** - WebSocket connection establishment and maintenance - secp256k1 authentication flow (when private keys are provided) - Periodic keep-alive health checks - Automatic reconnection with exponential backoff - Connection status tracking - Resource cleanup when dropped ## Architectural Flow ```mermaid sequenceDiagram participant User as User Code participant Builder as WsManagerBuilder participant Manager as WsManager participant Client1 as CircleWsClient 1 participant Client2 as CircleWsClient 2 participant Server1 as WebSocket Server 1 participant Server2 as WebSocket Server 2 User->>+Builder: ws_manager() User->>Builder: .private_key("key") User->>Builder: .add_server_url("ws://server1") User->>Builder: .add_server_url("ws://server2") User->>Builder: .build() Builder->>-Manager: WsManager instance User->>+Manager: connect() Manager->>+Client1: new() + connect() Client1->>Client1: Self-manage connection Client1->>+Server1: WebSocket connection Client1->>Client1: Start keep-alive loop Client1->>Client1: Start reconnection handler Server1-->>-Client1: Connected Client1-->>-Manager: Connection established Manager->>+Client2: new() + connect() Client2->>Client2: Self-manage connection Client2->>+Server2: WebSocket connection Client2->>Client2: Start keep-alive loop Client2->>Client2: Start reconnection handler Server2-->>-Client2: Connected Client2-->>-Manager: Connection established Manager-->>-User: All connections established Note over Client1, Server1: Client1 autonomously maintains connection Note over Client2, Server2: Client2 autonomously maintains connection User->>+Manager: execute_script("ws://server1", script) Manager->>+Client1: play(script) Client1->>+Server1: Execute script Server1-->>-Client1: Script result Client1-->>-Manager: Result Manager-->>-User: Script result ``` ## Key Architectural Benefits ### 1. Simplified Complexity - **Before**: Complex WsManager with external keep-alive and reconnection logic - **After**: Simple WsManager that delegates lifecycle management to individual clients ### 2. Autonomous Clients - Each client is self-contained and manages its own state - No external coordination required for connection health - Clients can be used independently outside of WsManager ### 3. Clean Separation of Concerns - **WsManagerBuilder**: Configuration and validation - **WsManager**: Organization and coordination - **CircleWsClient**: Connection lifecycle and maintenance ### 4. Improved Reliability - Connection failures in one client don't affect others - Each client has its own reconnection strategy - No single point of failure in connection management ## Connection Lifecycle ### 1. Initialization Phase ```rust // Builder validates configuration let manager = ws_manager() .private_key("valid_hex_key") // Validates 64-char hex .add_server_url("ws://valid") // Validates WebSocket URL format .build(); // Creates WsManager with validated config ``` ### 2. Connection Phase ```rust // Manager creates and connects individual clients manager.connect().await?; // For each configured URL: // 1. Create CircleWsClient with URL and optional private key // 2. Call client.connect() which handles: // - WebSocket connection establishment // - Authentication flow (if private key provided) // - Start internal keep-alive monitoring // - Start internal reconnection handling // 3. Store connected client in manager's HashMap ``` ### 3. Operation Phase ```rust // Execute scripts on specific servers let result = manager.execute_script("ws://server1", script).await?; // Manager simply forwards to the appropriate client // Client handles the actual script execution over its maintained connection ``` ### 4. Maintenance Phase (Automatic) ```rust // Each client autonomously: // - Sends periodic keep-alive pings // - Detects connection failures // - Attempts reconnection with exponential backoff // - Re-authenticates after successful reconnection // - Updates internal connection status ``` ### 5. Cleanup Phase ```rust // Explicit cleanup (optional) manager.disconnect_all().await; // Or automatic cleanup when manager is dropped // Each client cleans up its own resources ``` ## Error Handling Strategy ### Builder Validation - **Invalid private key**: Panic during build (fail-fast) - **Invalid URL format**: Panic during build (fail-fast) ### Connection Errors - **Individual connection failures**: Logged but don't prevent other connections - **All connections fail**: Return `CircleWsClientError::NotConnected` - **Partial failures**: Log summary, continue with successful connections ### Runtime Errors - **Script execution errors**: Return specific error for that client - **Connection loss**: Handled automatically by individual client reconnection - **Authentication failures**: Logged and retried by individual clients ## Platform Considerations ### WASM (Browser) - Uses `gloo-net` for WebSocket connections - Uses `gloo-timers` for keep-alive timing - Uses `spawn_local` for async task management - Each client manages its own async tasks ### Native (Tokio) - Uses `tokio-tungstenite` for WebSocket connections - Uses `tokio::time` for keep-alive timing - Uses `tokio::spawn` for async task management - Each client manages its own async tasks ## Future Enhancements ### Potential Improvements 1. **Connection Pooling**: Share connections for the same URL 2. **Load Balancing**: Distribute scripts across multiple connections to the same server 3. **Metrics Collection**: Gather connection health and performance metrics 4. **Circuit Breaker**: Temporarily disable failing connections 5. **Connection Prioritization**: Prefer certain connections over others ### Backward Compatibility The current architecture maintains backward compatibility while providing a foundation for future enhancements. The self-managing client approach makes it easy to add new features without disrupting the core architecture.