v0.0.5: WebSocket real-time messaging
Server: - WS endpoint: /v1/ws/:fingerprint - Connection registry in AppState (fingerprint → WS senders) - On connect: flushes queued DB messages, then pushes in real-time - send_message: pushes to WS if connected, falls back to DB queue - Auto-cleanup on disconnect - WS accepts both binary and JSON text frames for sending Web client: - Replaces 2-second HTTP polling with persistent WebSocket - Auto-reconnects on disconnect (3-second backoff) - Sends via WS when connected, HTTP fallback - Messages arrive instantly (no polling delay) - "Real-time connection established" shown on connect HTTP polling still works: - CLI recv command uses HTTP (unchanged) - Web falls back to HTTP if WS fails - Mules/scripts can still use HTTP API Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -9,7 +9,7 @@ use crate::errors::AppResult;
|
||||
use crate::state::AppState;
|
||||
|
||||
/// Touch the alias TTL for a fingerprint (renew on authenticated action).
|
||||
fn renew_alias_ttl(db: &sled::Tree, fp: &str) {
|
||||
pub fn renew_alias_ttl(db: &sled::Tree, fp: &str) {
|
||||
let alias_key = format!("fp:{}", fp);
|
||||
if let Ok(Some(alias_bytes)) = db.get(alias_key.as_bytes()) {
|
||||
let alias = String::from_utf8_lossy(&alias_bytes).to_string();
|
||||
@@ -54,9 +54,16 @@ async fn send_message(
|
||||
Json(req): Json<SendRequest>,
|
||||
) -> AppResult<Json<serde_json::Value>> {
|
||||
let to = normalize_fp(&req.to);
|
||||
let key = format!("queue:{}:{}", to, uuid::Uuid::new_v4());
|
||||
tracing::info!("Queuing message for {} ({} bytes)", to, req.message.len());
|
||||
state.db.messages.insert(key.as_bytes(), req.message)?;
|
||||
|
||||
// Try WebSocket push first (instant delivery)
|
||||
if state.push_to_client(&to, &req.message).await {
|
||||
tracing::info!("Pushed message to {} via WS ({} bytes)", to, req.message.len());
|
||||
} else {
|
||||
// Queue in DB (offline delivery)
|
||||
let key = format!("queue:{}:{}", to, uuid::Uuid::new_v4());
|
||||
tracing::info!("Queuing message for {} ({} bytes)", to, req.message.len());
|
||||
state.db.messages.insert(key.as_bytes(), req.message)?;
|
||||
}
|
||||
|
||||
// Renew sender's alias TTL (sending = authenticated action)
|
||||
if let Some(ref from) = req.from {
|
||||
|
||||
Reference in New Issue
Block a user