Skip to main content

signet_cold_sql/
connector.rs

1//! SQL cold storage connector.
2
3use crate::{SqlColdBackend, SqlColdError};
4use signet_cold::ColdConnect;
5
6/// Errors that can occur when initializing SQL connectors.
7#[derive(Debug, thiserror::Error)]
8pub enum SqlConnectorError {
9    /// Missing environment variable.
10    #[error("missing environment variable: {0}")]
11    MissingEnvVar(&'static str),
12
13    /// Cold storage initialization failed.
14    #[error("cold storage initialization failed: {0}")]
15    ColdInit(#[from] SqlColdError),
16}
17
18/// Connector for SQL cold storage (PostgreSQL or SQLite).
19///
20/// Automatically detects the database type from the URL:
21/// - URLs starting with `postgres://` or `postgresql://` use PostgreSQL
22/// - URLs starting with `sqlite:` use SQLite
23///
24/// # Example
25///
26/// ```ignore
27/// use signet_cold_sql::SqlConnector;
28///
29/// // PostgreSQL
30/// let pg = SqlConnector::new("postgres://localhost/signet");
31/// let backend = pg.connect().await?;
32///
33/// // SQLite
34/// let sqlite = SqlConnector::new("sqlite::memory:");
35/// let backend = sqlite.connect().await?;
36/// ```
37#[cfg(any(feature = "sqlite", feature = "postgres"))]
38#[derive(Debug, Clone)]
39pub struct SqlConnector {
40    url: String,
41}
42
43#[cfg(any(feature = "sqlite", feature = "postgres"))]
44impl SqlConnector {
45    /// Create a new SQL connector.
46    ///
47    /// The database type is detected from the URL prefix.
48    pub fn new(url: impl Into<String>) -> Self {
49        Self { url: url.into() }
50    }
51
52    /// Get a reference to the connection URL.
53    pub fn url(&self) -> &str {
54        &self.url
55    }
56
57    /// Create a connector from environment variables.
58    ///
59    /// Reads the SQL URL from the specified environment variable.
60    ///
61    /// # Example
62    ///
63    /// ```ignore
64    /// use signet_cold_sql::SqlConnector;
65    ///
66    /// let cold = SqlConnector::from_env("SIGNET_COLD_SQL_URL")?;
67    /// ```
68    pub fn from_env(env_var: &'static str) -> Result<Self, SqlConnectorError> {
69        let url = std::env::var(env_var).map_err(|_| SqlConnectorError::MissingEnvVar(env_var))?;
70        Ok(Self::new(url))
71    }
72}
73
74#[cfg(any(feature = "sqlite", feature = "postgres"))]
75impl ColdConnect for SqlConnector {
76    type Cold = SqlColdBackend;
77    type Error = SqlColdError;
78
79    fn connect(&self) -> impl std::future::Future<Output = Result<Self::Cold, Self::Error>> + Send {
80        let url = self.url.clone();
81        async move { SqlColdBackend::connect(&url).await }
82    }
83}