228 lines
7.7 KiB
Markdown
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. |