use std::time::Instant;
use log::{debug, trace};
use crate::Poolable;
use super::inner_pool::PoolMessage;
use super::extended_connection_factory::ExtendedConnectionFactory;
pub(crate) struct Managed<T: Poolable> {
pub created_at: Instant,
pub checked_out_at: Option<Instant>,
connection: Option<T>,
pub factory: Option<ExtendedConnectionFactory<T>>,
}
impl<T: Poolable> Managed<T> {
pub fn fresh(connection: T, factory: ExtendedConnectionFactory<T>) -> Self {
Managed {
connection: Some(connection),
created_at: Instant::now(),
checked_out_at: None,
factory: Some(factory),
}
}
pub fn connection_mut(&mut self) -> Option<&mut T> {
self.connection.as_mut()
}
pub fn connection(&self) -> Option<&T> {
self.connection.as_ref()
}
#[cfg(test)]
pub fn take_connection(&mut self) -> Option<T> {
self.connection.take()
}
pub fn invalidate(&mut self) {
self.connection = None
}
pub fn drop_orphanized(mut self) {
self.factory = None; self.connection = None; drop(self); }
}
impl<T: Poolable> Drop for Managed<T> {
fn drop(&mut self) {
if self.factory.is_none() {
trace!("Orphan goes into the void");
return;
}
let factory = self.factory.take().unwrap();
let mut send_back = factory.send_back_cloned();
if let Some(connection) = self.connection.take() {
let msg = PoolMessage::CheckIn {
created_at: Instant::now(),
conn: Managed {
connection: Some(connection),
created_at: self.created_at,
checked_out_at: self.checked_out_at,
factory: Some(factory), },
};
if let Err(unsent_connection) = msg.send_on_internal_channel(&mut send_back) {
debug!("inner pool gone - simply dropping");
drop_connection_orphanized(unsent_connection);
} else {
debug!("sent connection to pool");
}
} else {
factory.instrumentation.connection_dropped(
self.checked_out_at.map(|d| d.elapsed()),
self.created_at.elapsed(),
);
if self.checked_out_at.is_some() {
factory.instrumentation.in_flight_dec();
}
debug!("no value - drop connection and request new one");
factory.create_connection(Instant::now());
}
}
}
fn drop_connection_orphanized<T: Poolable>(msg: PoolMessage<T>) {
let conn = match msg {
PoolMessage::CheckIn { conn, .. } => conn,
PoolMessage::CheckOut { .. } => return,
PoolMessage::CleanupReservations(_) => return,
PoolMessage::CheckAlive(_) => return,
};
conn.drop_orphanized()
}