use crate::client::backend::{BackendError, BackendType};
use crate::client::config::{ClientConfig, ConnectionConfig, HealthConfig, PoolConfig};
use std::time::Duration;
use thiserror::Error;
#[derive(Error, Debug)]
pub enum BuilderError {
#[error("backend type was not specified")]
MissingBackend,
#[error("connection URL is required")]
MissingUrl,
}
pub struct AthenaClientBuilder {
backend: Option<BackendType>,
url: Option<String>,
key: Option<String>,
ssl: Option<bool>,
port: Option<u16>,
database: Option<String>,
pool: PoolConfig,
health: HealthConfig,
}
impl AthenaClientBuilder {
pub fn new() -> Self {
Self {
backend: None,
url: None,
key: None,
ssl: None,
port: None,
database: None,
pool: PoolConfig::default(),
health: HealthConfig::default(),
}
}
pub fn backend(mut self, backend: BackendType) -> Self {
self.backend = Some(backend);
self
}
pub fn url(mut self, url: impl Into<String>) -> Self {
self.url = Some(url.into());
self
}
pub fn key(mut self, key: impl Into<String>) -> Self {
self.key = Some(key.into());
self
}
pub fn ssl(mut self, enabled: bool) -> Self {
self.ssl = Some(enabled);
self
}
pub fn port(mut self, port: u16) -> Self {
self.port = Some(port);
self
}
pub fn database(mut self, database: impl Into<String>) -> Self {
self.database = Some(database.into());
self
}
pub fn max_connections(mut self, max: u32) -> Self {
self.pool.max_connections = max;
self
}
pub fn min_connections(mut self, min: u32) -> Self {
self.pool.min_connections = min;
self
}
pub fn connection_timeout(mut self, timeout: Duration) -> Self {
self.pool.connection_timeout = timeout;
self
}
pub fn idle_timeout(mut self, timeout: Duration) -> Self {
self.pool.idle_timeout = timeout;
self
}
pub fn health_tracking(mut self, enabled: bool) -> Self {
self.health.enabled = enabled;
self
}
pub fn circuit_breaker_threshold(mut self, threshold: u32) -> Self {
self.health.circuit_breaker_threshold = threshold;
self
}
pub fn circuit_breaker_timeout(mut self, timeout: Duration) -> Self {
self.health.circuit_breaker_timeout = timeout;
self
}
pub fn health_check_interval(mut self, interval: Duration) -> Self {
self.health.check_interval = interval;
self
}
pub fn build_config(self) -> Result<ClientConfig, BuilderError> {
let backend_type = self.backend.ok_or(BuilderError::MissingBackend)?;
let url = self.url.ok_or(BuilderError::MissingUrl)?;
let mut connection = ConnectionConfig::new(url);
if let Some(key) = self.key {
connection.key = Some(key);
}
if let Some(ssl) = self.ssl {
connection.ssl = ssl;
}
connection.port = self.port;
connection.database = self.database;
Ok(ClientConfig::new(
backend_type,
connection,
self.pool,
self.health,
))
}
}
impl From<BuilderError> for BackendError {
fn from(value: BuilderError) -> Self {
BackendError::Generic(value.to_string())
}
}