diff --git a/crates/db_schema/src/utils.rs b/crates/db_schema/src/utils.rs index 945a00647..5ec6c7523 100644 --- a/crates/db_schema/src/utils.rs +++ b/crates/db_schema/src/utils.rs @@ -25,10 +25,11 @@ use diesel::{ use diesel_async::{ pg::AsyncPgConnection, pooled_connection::{ - deadpool::{Object as PooledConnection, Pool}, + deadpool::{Hook, HookError, Object as PooledConnection, Pool}, AsyncDieselConnectionManager, ManagerConfig, }, + SimpleAsyncConnection, }; use diesel_migrations::EmbeddedMigrations; use futures_util::{future::BoxFuture, Future, FutureExt}; @@ -46,7 +47,7 @@ use rustls::{ use std::{ ops::{Deref, DerefMut}, sync::Arc, - time::SystemTime, + time::{Duration, SystemTime}, }; use tracing::{error, info}; use url::Url; @@ -335,7 +336,14 @@ fn establish_connection(config: &str) -> BoxFuture Result { let pool = Pool::builder(manager) .max_size(SETTINGS.database.pool_size) .runtime(Runtime::Tokio1) + // Limit connection age to prevent use of prepared statements that have query plans based on very old statistics + .pre_recycle(Hook::sync_fn(|_conn, metrics| { + // Preventing the first recycle can cause an infinite loop when trying to get a new connection from the pool + let conn_was_used = metrics.recycled.is_some(); + if metrics.age() > Duration::from_secs(3 * 24 * 60 * 60) && conn_was_used { + Err(HookError::Continue(None)) + } else { + Ok(()) + } + })) .build()?; run_migrations(&db_url)?;