first commit
This commit is contained in:
228
ARCHITECTURE.md
Normal file
228
ARCHITECTURE.md
Normal file
@@ -0,0 +1,228 @@
|
||||
# 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.
|
Reference in New Issue
Block a user