Files
crank/apps/admin-api/src/bin/crank_migrate/db_connect.rs
T

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()))
}
}