use crate::error::Result;
use async_trait::async_trait;
use std::fmt;
use std::time::Instant;
use super::health::ConnectionHealth;
#[async_trait]
pub trait Connection: Send + Sync {
async fn send(&self, frame: &[u8]) -> Result<()>;
async fn recv(&self) -> Result<Vec<u8>>;
async fn close(&self) -> Result<()>;
fn state(&self) -> ConnectionState;
fn stats(&self) -> ConnectionStats;
fn health(&self) -> ConnectionHealth {
ConnectionHealth::from_state_and_stats(self.state(), self.stats())
}
fn as_any(&self) -> &dyn std::any::Any;
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ConnectionState {
Connecting,
Connected,
Disconnecting,
Disconnected,
Failed,
}
impl fmt::Display for ConnectionState {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
ConnectionState::Connecting => write!(f, "connecting"),
ConnectionState::Connected => write!(f, "connected"),
ConnectionState::Disconnecting => write!(f, "disconnecting"),
ConnectionState::Disconnected => write!(f, "disconnected"),
ConnectionState::Failed => write!(f, "failed"),
}
}
}
#[derive(Debug, Clone, Default)]
pub struct ConnectionStats {
pub frames_sent: u64,
pub frames_received: u64,
pub send_errors: u64,
pub recv_errors: u64,
pub connection_errors: u64,
pub uptime_seconds: u64,
pub last_error: Option<String>,
pub last_error_at: Option<Instant>,
}
impl ConnectionStats {
pub(crate) fn record_connection_error(&mut self, error: &impl fmt::Display) {
self.connection_errors += 1;
self.record_error(error);
}
pub(crate) fn record_send_error(&mut self, error: &impl fmt::Display) {
self.send_errors += 1;
self.record_error(error);
}
pub(crate) fn record_receive_error(&mut self, error: &impl fmt::Display) {
self.recv_errors += 1;
self.record_error(error);
}
fn record_error(&mut self, error: &impl fmt::Display) {
self.last_error = Some(error.to_string());
self.last_error_at = Some(Instant::now());
}
}