use crate::{SqlColdBackend, SqlColdError};
use signet_cold::ColdConnect;
use sqlx::pool::PoolOptions;
use std::time::Duration;
#[derive(Debug, thiserror::Error)]
pub enum SqlConnectorError {
#[error("missing environment variable: {0}")]
MissingEnvVar(&'static str),
#[error("cold storage initialization failed: {0}")]
ColdInit(#[from] SqlColdError),
}
#[cfg(any(feature = "sqlite", feature = "postgres"))]
#[derive(Debug, Clone)]
pub struct SqlConnector {
url: String,
pool_opts: PoolOptions<sqlx::Any>,
}
#[cfg(any(feature = "sqlite", feature = "postgres"))]
impl SqlConnector {
pub fn new(url: impl Into<String>) -> Self {
Self { url: url.into(), pool_opts: PoolOptions::new() }
}
pub fn url(&self) -> &str {
&self.url
}
pub fn with_pool_options(mut self, pool_opts: PoolOptions<sqlx::Any>) -> Self {
self.pool_opts = pool_opts;
self
}
pub fn with_max_connections(mut self, n: u32) -> Self {
self.pool_opts = self.pool_opts.max_connections(n);
self
}
pub fn with_min_connections(mut self, n: u32) -> Self {
self.pool_opts = self.pool_opts.min_connections(n);
self
}
pub fn with_acquire_timeout(mut self, timeout: Duration) -> Self {
self.pool_opts = self.pool_opts.acquire_timeout(timeout);
self
}
pub fn with_max_lifetime(mut self, lifetime: Option<Duration>) -> Self {
self.pool_opts = self.pool_opts.max_lifetime(lifetime);
self
}
pub fn with_idle_timeout(mut self, timeout: Option<Duration>) -> Self {
self.pool_opts = self.pool_opts.idle_timeout(timeout);
self
}
pub fn from_env(env_var: &'static str) -> Result<Self, SqlConnectorError> {
let url = std::env::var(env_var).map_err(|_| SqlConnectorError::MissingEnvVar(env_var))?;
Ok(Self::new(url))
}
}
#[cfg(any(feature = "sqlite", feature = "postgres"))]
impl ColdConnect for SqlConnector {
type Cold = SqlColdBackend;
type Error = SqlColdError;
fn connect(&self) -> impl std::future::Future<Output = Result<Self::Cold, Self::Error>> + Send {
let url = self.url.clone();
let pool_opts = self.pool_opts.clone();
async move { SqlColdBackend::connect_with(&url, pool_opts).await }
}
}