use std::{sync::Arc, time::Duration};
use kmip::client::ConnectionSettings;
use log::warn;
use crate::commons::crypto::signers::{
error::SignerError, kmip::signer::KmipTlsClient,
};
#[derive(Debug)]
pub struct ConnectionManager {
conn_settings: Arc<ConnectionSettings>,
}
impl ConnectionManager {
#[rustfmt::skip]
pub fn create_connection_pool(
conn_settings: Arc<ConnectionSettings>,
max_response_bytes: u32,
max_life_time: Duration,
max_idle_time: Duration,
) -> Result<r2d2::Pool<ConnectionManager>, SignerError> {
let max_life_time = Some(max_life_time);
let max_idle_time = Some(max_idle_time);
let pool = r2d2::Pool::builder()
.min_idle(Some(0))
.max_size(max_response_bytes)
.test_on_check_out(false)
.error_handler(Box::new(ErrorLoggingHandler))
.max_lifetime(max_life_time)
.idle_timeout(max_idle_time)
.connection_timeout(conn_settings.connect_timeout.unwrap_or(Duration::from_secs(30)))
.build(ConnectionManager { conn_settings })?;
Ok(pool)
}
pub fn connect_one_off(
settings: &ConnectionSettings,
) -> Result<KmipTlsClient, kmip::client::Error> {
let conn = kmip::client::tls::openssl::connect(settings)?;
Ok(conn)
}
}
impl r2d2::ManageConnection for ConnectionManager {
type Connection = KmipTlsClient;
type Error = kmip::client::Error;
fn connect(&self) -> Result<Self::Connection, Self::Error> {
Self::connect_one_off(&self.conn_settings)
}
fn is_valid(
&self,
_conn: &mut Self::Connection,
) -> Result<(), Self::Error> {
unreachable!()
}
fn has_broken(&self, conn: &mut Self::Connection) -> bool {
conn.connection_error_count() > 1
}
}
#[derive(Debug)]
struct ErrorLoggingHandler;
impl<E> r2d2::HandleError<E> for ErrorLoggingHandler
where
E: std::fmt::Display,
{
fn handle_error(&self, err: E) {
warn!("Pool error: {err}")
}
}
impl From<r2d2::Error> for SignerError {
fn from(err: r2d2::Error) -> Self {
SignerError::KmipError(format!("{err}"))
}
}