Support alternative read-replica PgPool (#4374)

* Add ReadOnlyPgPool

* Clippy, fmt
This commit is contained in:
François-Xavier Talbot
2025-09-14 11:44:52 -04:00
committed by GitHub
parent 67e090565e
commit 3fc55184a7
8 changed files with 88 additions and 23 deletions

View File

@@ -2,10 +2,35 @@ use prometheus::{IntGauge, Registry};
use sqlx::migrate::MigrateDatabase;
use sqlx::postgres::{PgPool, PgPoolOptions};
use sqlx::{Connection, PgConnection, Postgres};
use std::ops::{Deref, DerefMut};
use std::time::Duration;
use tracing::info;
pub async fn connect() -> Result<PgPool, sqlx::Error> {
#[derive(Clone)]
#[repr(transparent)]
pub struct ReadOnlyPgPool(PgPool);
impl From<PgPool> for ReadOnlyPgPool {
fn from(pool: PgPool) -> Self {
ReadOnlyPgPool(pool)
}
}
impl Deref for ReadOnlyPgPool {
type Target = PgPool;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl DerefMut for ReadOnlyPgPool {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
pub async fn connect_all() -> Result<(PgPool, ReadOnlyPgPool), sqlx::Error> {
info!("Initializing database connection");
let database_url =
dotenvy::var("DATABASE_URL").expect("`DATABASE_URL` not in .env");
@@ -26,7 +51,29 @@ pub async fn connect() -> Result<PgPool, sqlx::Error> {
.connect(&database_url)
.await?;
Ok(pool)
if let Ok(url) = dotenvy::var("READONLY_DATABASE_URL") {
let ro_pool = PgPoolOptions::new()
.min_connections(
dotenvy::var("READONLY_DATABASE_MIN_CONNECTIONS")
.ok()
.and_then(|x| x.parse().ok())
.unwrap_or(0),
)
.max_connections(
dotenvy::var("READONLY_DATABASE_MAX_CONNECTIONS")
.ok()
.and_then(|x| x.parse().ok())
.unwrap_or(1),
)
.max_lifetime(Some(Duration::from_secs(60 * 60)))
.connect(&url)
.await?;
Ok((pool, ReadOnlyPgPool(ro_pool)))
} else {
let ro = ReadOnlyPgPool(pool.clone());
Ok((pool, ro))
}
}
pub async fn check_for_migrations() -> Result<(), sqlx::Error> {
let uri = dotenvy::var("DATABASE_URL").expect("`DATABASE_URL` not in .env");