79 lines
2.7 KiB
Rust
79 lines
2.7 KiB
Rust
use crank_config::DatabaseSettings;
|
|
use crank_registry::{PostgresPoolConfig, PostgresRegistry, RegistryError};
|
|
use sqlx::{
|
|
PgPool,
|
|
postgres::{PgConnectOptions, PgPoolOptions},
|
|
};
|
|
use std::time::Duration;
|
|
|
|
use super::CliError;
|
|
|
|
pub(super) async fn connect(config: &DatabaseSettings) -> Result<PgPool, CliError> {
|
|
let options = connect_options(config)?;
|
|
for attempt in 1..=10 {
|
|
let result = PgPoolOptions::new()
|
|
.max_connections(config.pool.max_connections)
|
|
.min_connections(config.pool.min_connections)
|
|
.acquire_timeout(Duration::from_millis(config.pool.acquire_timeout_ms))
|
|
.idle_timeout(Duration::from_millis(config.pool.idle_timeout_ms))
|
|
.max_lifetime(Duration::from_millis(config.pool.max_lifetime_ms))
|
|
.connect_with(options.clone())
|
|
.await;
|
|
match result {
|
|
Ok(pool) => return Ok(pool),
|
|
Err(_) if attempt < 10 => tokio::time::sleep(Duration::from_secs(1)).await,
|
|
Err(_) => break,
|
|
}
|
|
}
|
|
Err(CliError::new(
|
|
"storage_unavailable",
|
|
"database.connect",
|
|
"contact_operator",
|
|
))
|
|
}
|
|
|
|
pub(super) async fn connect_registry(
|
|
config: &DatabaseSettings,
|
|
) -> Result<PostgresRegistry, CliError> {
|
|
let options = connect_options(config)?;
|
|
let pool_config = PostgresPoolConfig {
|
|
max_connections: config.pool.max_connections,
|
|
min_connections: config.pool.min_connections,
|
|
acquire_timeout_ms: config.pool.acquire_timeout_ms,
|
|
idle_timeout_ms: config.pool.idle_timeout_ms,
|
|
max_lifetime_ms: config.pool.max_lifetime_ms,
|
|
};
|
|
for attempt in 1..=10 {
|
|
let result =
|
|
PostgresRegistry::connect_with_options_and_pool_config(options.clone(), pool_config)
|
|
.await;
|
|
match result {
|
|
Ok(registry) => return Ok(registry),
|
|
Err(RegistryError::Storage(_)) if attempt < 10 => {
|
|
tokio::time::sleep(Duration::from_secs(1)).await;
|
|
}
|
|
Err(error) => return Err(CliError::from_registry(error)),
|
|
}
|
|
}
|
|
Err(CliError::new(
|
|
"storage_unavailable",
|
|
"database.connect",
|
|
"contact_operator",
|
|
))
|
|
}
|
|
|
|
fn connect_options(config: &DatabaseSettings) -> Result<PgConnectOptions, CliError> {
|
|
if let Some(url) = &config.url {
|
|
url.expose_secret()
|
|
.parse::<PgConnectOptions>()
|
|
.map_err(|_| CliError::new("config_invalid", "database.source", "run_preflight"))
|
|
} else {
|
|
Ok(PgConnectOptions::new()
|
|
.host(&config.host)
|
|
.port(config.port)
|
|
.database(&config.database)
|
|
.username(&config.username)
|
|
.password(config.password.expose_secret()))
|
|
}
|
|
}
|