use std::{
sync::{atomic::Ordering, Weak},
time::Duration,
};
use super::{ConnectionPool, ConnectionPoolInner};
use crate::event::cmap::ConnectionClosedReason;
pub(crate) fn start_background_thread(pool: Weak<ConnectionPoolInner>) {
std::thread::spawn(move || loop {
match pool.upgrade() {
Some(pool) => perform_checks(pool.into()),
None => return,
};
std::thread::sleep(Duration::from_millis(10));
});
}
fn perform_checks(pool: ConnectionPool) {
remove_perished_connections_from_pool(&pool);
ensure_min_connections_in_pool(&pool);
}
fn remove_perished_connections_from_pool(pool: &ConnectionPool) {
let mut connections = pool.inner.connections.write().unwrap();
let mut i = 0;
while i < connections.len() {
if connections[i].is_stale(pool.inner.generation.load(Ordering::SeqCst)) {
pool.close_connection(connections.remove(i), ConnectionClosedReason::Stale);
} else if connections[i].is_idle(pool.inner.max_idle_time) {
pool.close_connection(connections.remove(i), ConnectionClosedReason::Idle);
} else {
i += 1;
}
}
}
fn ensure_min_connections_in_pool(pool: &ConnectionPool) {
if let Some(min_pool_size) = pool.inner.min_pool_size {
loop {
let mut connections = pool.inner.connections.write().unwrap();
if pool.inner.total_connection_count.load(Ordering::SeqCst) < min_pool_size {
match pool.create_connection(false) {
Ok(connection) => connections.push(connection),
e @ Err(_) => {
return;
}
}
} else {
return;
}
}
}
}