93 lines
3.1 KiB
Markdown
93 lines
3.1 KiB
Markdown
# Connectivity & Network Architecture
|
|
|
|
## HTTP Client with Retry Logic
|
|
|
|
**Location**: `src-tauri/src/jellyfin/http_client.rs`
|
|
|
|
The HTTP client provides automatic retry with exponential backoff for network resilience:
|
|
|
|
```rust
|
|
pub struct HttpClient {
|
|
client: reqwest::Client,
|
|
config: HttpConfig,
|
|
}
|
|
|
|
pub struct HttpConfig {
|
|
pub base_url: String,
|
|
pub timeout: Duration, // Default: 10s
|
|
pub max_retries: u32, // Default: 3
|
|
}
|
|
```
|
|
|
|
**Retry Strategy:**
|
|
- Retry delays: 1s, 2s, 4s (exponential backoff)
|
|
- Retries on: Network errors, 5xx server errors
|
|
- No retry on: 4xx client errors, 401/403 authentication errors
|
|
|
|
**Error Classification:**
|
|
```rust
|
|
pub enum ErrorKind {
|
|
Network, // Connection failures, timeouts, DNS errors
|
|
Authentication, // 401/403 responses
|
|
Server, // 5xx server errors
|
|
Client, // Other 4xx errors
|
|
}
|
|
```
|
|
|
|
## Connectivity Monitor
|
|
|
|
**Location**: `src-tauri/src/connectivity/mod.rs`
|
|
|
|
The connectivity monitor tracks server reachability with adaptive polling:
|
|
|
|
```mermaid
|
|
flowchart TB
|
|
Monitor["ConnectivityMonitor"] --> Poller["Background Task"]
|
|
Poller --> Check{"Server<br/>Reachable?"}
|
|
Check -->|"Yes"| Online["30s Interval"]
|
|
Check -->|"No"| Offline["5s Interval"]
|
|
Online --> Emit["Emit Events"]
|
|
Offline --> Emit
|
|
Emit --> Frontend["Frontend Store"]
|
|
```
|
|
|
|
**Features:**
|
|
- **Adaptive Polling**: 30s when online, 5s when offline (for quick reconnection detection)
|
|
- **Event Emission**: Emits `connectivity:changed` and `connectivity:reconnected` events
|
|
- **Manual Marking**: Can mark reachable/unreachable based on API call results
|
|
- **Thread-Safe**: Uses Arc<RwLock<>> for shared state
|
|
|
|
**Tauri Commands:**
|
|
| Command | Description |
|
|
|---------|-------------|
|
|
| `connectivity_check_server` | Manual reachability check |
|
|
| `connectivity_set_server_url` | Update monitored server URL |
|
|
| `connectivity_get_status` | Get current connectivity status |
|
|
| `connectivity_start_monitoring` | Start background monitoring |
|
|
| `connectivity_stop_monitoring` | Stop monitoring |
|
|
| `connectivity_mark_reachable` | Mark server as reachable (after successful API call) |
|
|
| `connectivity_mark_unreachable` | Mark server as unreachable (after failed API call) |
|
|
|
|
**Frontend Integration:**
|
|
```typescript
|
|
// TypeScript store listens to Rust events
|
|
listen<{ isReachable: boolean }>("connectivity:changed", (event) => {
|
|
updateConnectivityState(event.payload.isReachable);
|
|
});
|
|
```
|
|
|
|
## Network Resilience Architecture
|
|
|
|
The connectivity system provides resilience through multiple layers:
|
|
|
|
1. **HTTP Client Layer**: Automatic retry with exponential backoff
|
|
2. **Connectivity Monitoring**: Background reachability checks
|
|
3. **Frontend Integration**: Offline mode detection and UI updates
|
|
4. **Sync Queue**: Offline mutations queued for later (see [06-downloads-and-offline.md](06-downloads-and-offline.md))
|
|
|
|
**Design Principles:**
|
|
- **Fail Fast**: Don't retry 4xx errors (client errors, authentication)
|
|
- **Fail Slow**: Retry network and 5xx errors with increasing delays
|
|
- **Adaptive Polling**: Reduce polling frequency when online, increase when offline
|
|
- **Event-Driven**: Frontend reacts to connectivity changes via events
|