Expand description
Shared application state management.
This module provides a type-safe, thread-safe container for storing and retrieving application state that needs to be shared across all WebSocket connections. State is commonly used for database connections, configuration, caches, and other shared resources.
§Overview
The AppState type uses a type-map pattern, allowing you to store multiple
different types of state in a single container. Each type is stored separately
and can be retrieved by its type, ensuring type safety at compile time.
§Design
- Type-safe: Each state type is stored and retrieved by its exact type
- Thread-safe: Uses
ArcandDashMapfor lock-free concurrent access - Zero-cost abstraction: No runtime overhead when state is not used
- Flexible: Any type that is
Send + Sync + 'staticcan be stored
§Common Use Cases
| Use Case | Example Type | Description |
|---|---|---|
| Database | Arc<DatabasePool> | Shared database connection pool |
| Configuration | Arc<Config> | Application settings and configuration |
| Cache | Arc<Cache> | In-memory cache for frequently accessed data |
| Metrics | Arc<Metrics> | Performance metrics and monitoring |
| Connection Manager | Arc<ConnectionManager> | Manage all active WebSocket connections |
§Examples
§Single State Type
use wsforge::prelude::*;
use std::sync::Arc;
struct Database {
connection_string: String,
}
async fn query_handler(State(db): State<Arc<Database>>) -> Result<String> {
Ok(format!("Connected to: {}", db.connection_string))
}
let db = Arc::new(Database {
connection_string: "postgres://localhost/mydb".to_string(),
});
let router = Router::new()
.with_state(db)
.default_handler(handler(query_handler));§Multiple State Types
use wsforge::prelude::*;
use std::sync::Arc;
struct Database {
url: String,
}
struct Config {
max_connections: usize,
timeout_seconds: u64,
}
struct Cache {
data: std::collections::HashMap<String, String>,
}
async fn handler(
State(db): State<Arc<Database>>,
State(config): State<Arc<Config>>,
State(cache): State<Arc<Cache>>,
) -> Result<String> {
Ok(format!(
"DB: {}, Max: {}, Cache size: {}",
db.url,
config.max_connections,
cache.data.len()
))
}
let router = Router::new()
.with_state(Arc::new(Database { url: "...".to_string() }))
.with_state(Arc::new(Config { max_connections: 100, timeout_seconds: 30 }))
.with_state(Arc::new(Cache { data: Default::default() }))
.default_handler(handler(handler));§Mutable State with RwLock
use wsforge::prelude::*;
use std::sync::{Arc, RwLock};
struct Counter {
value: RwLock<u64>,
}
impl Counter {
fn increment(&self) {
let mut value = self.value.write().unwrap();
*value += 1;
}
fn get(&self) -> u64 {
*self.value.read().unwrap()
}
}
async fn count_handler(State(counter): State<Arc<Counter>>) -> Result<String> {
counter.increment();
Ok(format!("Count: {}", counter.get()))
}
let counter = Arc::new(Counter {
value: RwLock::new(0),
});
let router = Router::new()
.with_state(counter)
.default_handler(handler(count_handler));Structs§
- AppState
- A type-safe container for shared application state.