Skip to content

Commit dff0329

Browse files
committed
Retry native database pool startup
1 parent e9a90dc commit dff0329

1 file changed

Lines changed: 57 additions & 30 deletions

File tree

src/webserver/database/connect.rs

Lines changed: 57 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -28,12 +28,12 @@ impl Database {
2828
let mut options = database_url.parse::<SqliteConnectOptions>()?;
2929
options = set_common_connect_options(options);
3030
options = set_custom_connect_options_sqlite(options, config);
31-
let pool = Self::create_sqlite_pool_options(config, db_kind)
32-
.connect_with(options)
33-
.await
34-
.with_context(|| {
35-
format!("Unable to open connection pool to {}", config.database_url)
36-
})?;
31+
let pool = connect_pool_with_retries(
32+
Self::create_sqlite_pool_options(config, db_kind),
33+
options,
34+
config,
35+
)
36+
.await?;
3737
DatabasePool::Sqlite(pool)
3838
}
3939
DbKind::Postgres => {
@@ -42,12 +42,12 @@ impl Database {
4242
options = options.password(password);
4343
}
4444
options = set_common_connect_options(options);
45-
let pool = Self::create_pool_options::<sqlx::Postgres>(config, db_kind)
46-
.connect_with(options)
47-
.await
48-
.with_context(|| {
49-
format!("Unable to open connection pool to {}", config.database_url)
50-
})?;
45+
let pool = connect_pool_with_retries(
46+
Self::create_pool_options::<sqlx::Postgres>(config, db_kind),
47+
options,
48+
config,
49+
)
50+
.await?;
5151
DatabasePool::Postgres(pool)
5252
}
5353
DbKind::MySql => {
@@ -56,12 +56,12 @@ impl Database {
5656
options = options.password(password);
5757
}
5858
options = set_common_connect_options(options);
59-
let pool = Self::create_pool_options::<sqlx::MySql>(config, db_kind)
60-
.connect_with(options)
61-
.await
62-
.with_context(|| {
63-
format!("Unable to open connection pool to {}", config.database_url)
64-
})?;
59+
let pool = connect_pool_with_retries(
60+
Self::create_pool_options::<sqlx::MySql>(config, db_kind),
61+
options,
62+
config,
63+
)
64+
.await?;
6565
DatabasePool::MySql(pool)
6666
}
6767
DbKind::Mssql => {
@@ -70,12 +70,12 @@ impl Database {
7070
.parse::<MssqlConnectOptions>()
7171
.with_context(|| format!("Unable to parse {}", config.database_url))?,
7272
);
73-
let pool = Self::create_pool_options::<sqlx_sqlserver::Mssql>(config, db_kind)
74-
.connect_with(options)
75-
.await
76-
.with_context(|| {
77-
format!("Unable to open connection pool to {}", config.database_url)
78-
})?;
73+
let pool = connect_pool_with_retries(
74+
Self::create_pool_options::<sqlx_sqlserver::Mssql>(config, db_kind),
75+
options,
76+
config,
77+
)
78+
.await?;
7979
DatabasePool::Mssql(pool)
8080
}
8181
DbKind::Odbc => {
@@ -89,12 +89,12 @@ impl Database {
8989
let dbms_name = detect_odbc_dbms_name(&options, config).await?;
9090
let database_type = SupportedDatabase::from_dbms_name(&dbms_name);
9191
let options = set_common_connect_options(options);
92-
let pool = Self::create_pool_options::<sqlx_odbc::Odbc>(config, db_kind)
93-
.connect_with(options)
94-
.await
95-
.with_context(|| {
96-
format!("Unable to open connection pool to {}", config.database_url)
97-
})?;
92+
let pool = connect_pool_with_retries(
93+
Self::create_pool_options::<sqlx_odbc::Odbc>(config, db_kind),
94+
options,
95+
config,
96+
)
97+
.await?;
9898
log::debug!("Initialized {dbms_name:?} database pool: {pool:#?}");
9999
return Ok(Database {
100100
connection: DatabasePool::Odbc(pool),
@@ -157,6 +157,33 @@ impl Database {
157157
}
158158
}
159159

160+
async fn connect_pool_with_retries<DB>(
161+
pool_options: PoolOptions<DB>,
162+
options: <DB::Connection as Connection>::Options,
163+
config: &AppConfig,
164+
) -> anyhow::Result<sqlx::Pool<DB>>
165+
where
166+
DB: SqlxDatabase,
167+
{
168+
let mut retries = config.database_connection_retries;
169+
loop {
170+
match pool_options.clone().connect_with(options.clone()).await {
171+
Ok(pool) => return Ok(pool),
172+
Err(e) => {
173+
if retries == 0 {
174+
return Err(anyhow::Error::new(e).context(format!(
175+
"Unable to open connection pool to {}",
176+
config.database_url
177+
)));
178+
}
179+
log::warn!("Failed to connect to the database: {e:#}. Retrying in 5 seconds.");
180+
retries -= 1;
181+
tokio::time::sleep(Duration::from_secs(5)).await;
182+
}
183+
}
184+
}
185+
}
186+
160187
fn default_max_connections(config: &AppConfig, kind: DbKind) -> u32 {
161188
match kind {
162189
DbKind::Postgres | DbKind::Odbc => 50,

0 commit comments

Comments
 (0)