use async_trait::async_trait;
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum PoolEvent {
ConnectionAcquired {
connection_id: String,
timestamp: DateTime<Utc>,
},
ConnectionReturned {
connection_id: String,
timestamp: DateTime<Utc>,
},
ConnectionCreated {
connection_id: String,
timestamp: DateTime<Utc>,
},
ConnectionClosed {
connection_id: String,
reason: String,
timestamp: DateTime<Utc>,
},
ConnectionTestFailed {
connection_id: String,
error: String,
timestamp: DateTime<Utc>,
},
ConnectionInvalidated {
connection_id: String,
reason: String,
timestamp: DateTime<Utc>,
},
ConnectionSoftInvalidated {
connection_id: String,
timestamp: DateTime<Utc>,
},
ConnectionReset {
connection_id: String,
timestamp: DateTime<Utc>,
},
}
impl PoolEvent {
pub fn connection_acquired(connection_id: String) -> Self {
Self::ConnectionAcquired {
connection_id,
timestamp: Utc::now(),
}
}
pub fn connection_returned(connection_id: String) -> Self {
Self::ConnectionReturned {
connection_id,
timestamp: Utc::now(),
}
}
pub fn connection_created(connection_id: String) -> Self {
Self::ConnectionCreated {
connection_id,
timestamp: Utc::now(),
}
}
pub fn connection_closed(connection_id: String, reason: String) -> Self {
Self::ConnectionClosed {
connection_id,
reason,
timestamp: Utc::now(),
}
}
pub fn connection_test_failed(connection_id: String, error: String) -> Self {
Self::ConnectionTestFailed {
connection_id,
error,
timestamp: Utc::now(),
}
}
pub fn connection_invalidated(connection_id: String, reason: String) -> Self {
Self::ConnectionInvalidated {
connection_id,
reason,
timestamp: Utc::now(),
}
}
pub fn connection_soft_invalidated(connection_id: String) -> Self {
Self::ConnectionSoftInvalidated {
connection_id,
timestamp: Utc::now(),
}
}
pub fn connection_reset(connection_id: String) -> Self {
Self::ConnectionReset {
connection_id,
timestamp: Utc::now(),
}
}
}
#[async_trait]
pub trait PoolEventListener: Send + Sync {
async fn on_event(&self, event: PoolEvent);
}
pub struct EventLogger;
#[async_trait]
impl PoolEventListener for EventLogger {
async fn on_event(&self, event: PoolEvent) {
match event {
PoolEvent::ConnectionAcquired { connection_id, .. } => {
println!("Connection acquired: {}", connection_id);
}
PoolEvent::ConnectionReturned { connection_id, .. } => {
println!("Connection returned: {}", connection_id);
}
PoolEvent::ConnectionCreated { connection_id, .. } => {
println!("Connection created: {}", connection_id);
}
PoolEvent::ConnectionClosed {
connection_id,
reason,
..
} => {
println!("Connection closed: {} (reason: {})", connection_id, reason);
}
PoolEvent::ConnectionTestFailed {
connection_id,
error,
..
} => {
println!(
"Connection test failed: {} (error: {})",
connection_id, error
);
}
PoolEvent::ConnectionInvalidated {
connection_id,
reason,
..
} => {
println!(
"Connection invalidated: {} (reason: {})",
connection_id, reason
);
}
PoolEvent::ConnectionSoftInvalidated { connection_id, .. } => {
println!("Connection soft invalidated: {}", connection_id);
}
PoolEvent::ConnectionReset { connection_id, .. } => {
println!("Connection reset: {}", connection_id);
}
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_pool_event_creation() {
let event = PoolEvent::connection_acquired("conn-1".to_string());
match event {
PoolEvent::ConnectionAcquired { connection_id, .. } => {
assert_eq!(connection_id, "conn-1");
}
_ => panic!("Wrong event type"),
}
}
}