framework/ARCHITECTURE.md
2025-07-21 00:17:46 +02:00

228 lines
7.7 KiB
Markdown

# 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<RefCell<HashMap<String, CircleWsClient>>>,
private_key: Option<String>,
server_urls: Vec<String>,
}
```
**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.