Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: timed out fetching a new connection from the connection pool. #4998

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
84 changes: 60 additions & 24 deletions quaint/src/connector/postgres/native/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ use std::{
sync::atomic::{AtomicBool, Ordering},
time::Duration,
};
use tokio::sync::OnceCell;
use tokio_postgres::{config::ChannelBinding, Client, Config, Statement};

/// The underlying postgres driver. Only available with the `expose-drivers`
Expand Down Expand Up @@ -228,27 +229,10 @@ impl PostgresUrl {

impl PostgreSql {
/// Create a new connection to the database.
pub async fn new(url: PostgresUrl) -> crate::Result<Self> {
pub async fn new(url: PostgresUrl, tls_manager: &MakeTlsConnectorManager) -> crate::Result<Self> {
let config = url.to_config();

let mut tls_builder = TlsConnector::builder();

{
let ssl_params = url.ssl_params();
let auth = ssl_params.to_owned().into_auth().await?;

if let Some(certificate) = auth.certificate.0 {
tls_builder.add_root_certificate(certificate);
}

tls_builder.danger_accept_invalid_certs(auth.ssl_accept_mode == SslAcceptMode::AcceptInvalidCerts);

if let Some(identity) = auth.identity.0 {
tls_builder.identity(identity);
}
}

let tls = MakeTlsConnector::new(tls_builder.build()?);
let tls = tls_manager.get_connector().await?;
let (client, conn) = timeout::connect(url.connect_timeout(), config.connect(tls)).await?;

let is_cockroachdb = conn.parameter("crdb_version").is_some();
Expand Down Expand Up @@ -907,6 +891,48 @@ fn is_safe_identifier(ident: &str) -> bool {
true
}

pub struct MakeTlsConnectorManager {
url: PostgresUrl,
connector: OnceCell<MakeTlsConnector>,
}

impl MakeTlsConnectorManager {
pub fn new(url: PostgresUrl) -> Self {
MakeTlsConnectorManager {
url,
connector: OnceCell::new(),
}
}

pub async fn get_connector(&self) -> crate::Result<MakeTlsConnector> {
self.connector
.get_or_try_init(|| async {
let mut tls_builder = TlsConnector::builder();

{
let ssl_params = self.url.ssl_params();
let auth = ssl_params.to_owned().into_auth().await?;

if let Some(certificate) = auth.certificate.0 {
tls_builder.add_root_certificate(certificate);
}

tls_builder.danger_accept_invalid_certs(auth.ssl_accept_mode == SslAcceptMode::AcceptInvalidCerts);

if let Some(identity) = auth.identity.0 {
tls_builder.identity(identity);
}
}

let tls_connector = MakeTlsConnector::new(tls_builder.build()?);

Ok(tls_connector)
})
.await
.cloned()
}
}

#[cfg(test)]
mod tests {
use super::*;
Expand All @@ -925,7 +951,9 @@ mod tests {
let mut pg_url = PostgresUrl::new(url).unwrap();
pg_url.set_flavour(PostgresFlavour::Postgres);

let client = PostgreSql::new(pg_url).await.unwrap();
let tls_manager = MakeTlsConnectorManager::new(pg_url.clone());

let client = PostgreSql::new(pg_url, &tls_manager).await.unwrap();

let result_set = client.query_raw("SHOW search_path", &[]).await.unwrap();
let row = result_set.first().unwrap();
Expand Down Expand Up @@ -977,7 +1005,9 @@ mod tests {
let mut pg_url = PostgresUrl::new(url).unwrap();
pg_url.set_flavour(PostgresFlavour::Postgres);

let client = PostgreSql::new(pg_url).await.unwrap();
let tls_manager = MakeTlsConnectorManager::new(pg_url.clone());

let client = PostgreSql::new(pg_url, &tls_manager).await.unwrap();

let result_set = client.query_raw("SHOW search_path", &[]).await.unwrap();
let row = result_set.first().unwrap();
Expand Down Expand Up @@ -1028,7 +1058,9 @@ mod tests {
let mut pg_url = PostgresUrl::new(url).unwrap();
pg_url.set_flavour(PostgresFlavour::Cockroach);

let client = PostgreSql::new(pg_url).await.unwrap();
let tls_manager = MakeTlsConnectorManager::new(pg_url.clone());

let client = PostgreSql::new(pg_url, &tls_manager).await.unwrap();

let result_set = client.query_raw("SHOW search_path", &[]).await.unwrap();
let row = result_set.first().unwrap();
Expand Down Expand Up @@ -1079,7 +1111,9 @@ mod tests {
let mut pg_url = PostgresUrl::new(url).unwrap();
pg_url.set_flavour(PostgresFlavour::Unknown);

let client = PostgreSql::new(pg_url).await.unwrap();
let tls_manager = MakeTlsConnectorManager::new(pg_url.clone());

let client = PostgreSql::new(pg_url, &tls_manager).await.unwrap();

let result_set = client.query_raw("SHOW search_path", &[]).await.unwrap();
let row = result_set.first().unwrap();
Expand Down Expand Up @@ -1130,7 +1164,9 @@ mod tests {
let mut pg_url = PostgresUrl::new(url).unwrap();
pg_url.set_flavour(PostgresFlavour::Unknown);

let client = PostgreSql::new(pg_url).await.unwrap();
let tls_manager = MakeTlsConnectorManager::new(pg_url.clone());

let client = PostgreSql::new(pg_url, &tls_manager).await.unwrap();

let result_set = client.query_raw("SHOW search_path", &[]).await.unwrap();
let row = result_set.first().unwrap();
Expand Down
11 changes: 8 additions & 3 deletions quaint/src/pooled.rs
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@
use crate::error::NativeErrorKind;

use crate::{
connector::ConnectionInfo,
connector::{ConnectionInfo, MakeTlsConnectorManager},

Check failure on line 159 in quaint/src/pooled.rs

View workflow job for this annotation

GitHub Actions / React Native / Android build for commit c3b77e4bd1564650e0f2ee98939d79368c667b27

unresolved import `crate::connector::MakeTlsConnectorManager`
error::{Error, ErrorKind},
};
use mobc::Pool;
Expand Down Expand Up @@ -312,7 +312,11 @@
url.set_flavour(flavour);
}

if let QuaintManager::Postgres { ref mut url } = self.manager {
if let QuaintManager::Postgres {
ref mut url,
tls_manager: _,
} = self.manager
{
url.set_flavour(flavour);
}
}
Expand Down Expand Up @@ -421,7 +425,8 @@
let max_connection_lifetime = url.max_connection_lifetime();
let max_idle_connection_lifetime = url.max_idle_connection_lifetime();

let manager = QuaintManager::Postgres { url };
let tls_manager = MakeTlsConnectorManager::new(url.clone());
let manager = QuaintManager::Postgres { url, tls_manager };
let mut builder = Builder::new(s, manager)?;

if let Some(limit) = connection_limit {
Expand Down
11 changes: 7 additions & 4 deletions quaint/src/pooled/manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use crate::connector::MssqlUrl;
#[cfg(feature = "mysql-native")]
use crate::connector::MysqlUrl;
#[cfg(feature = "postgresql-native")]
use crate::connector::PostgresUrl;
use crate::connector::{MakeTlsConnectorManager, PostgresUrl};
use crate::{
ast,
connector::{self, impl_default_TransactionCapable, IsolationLevel, Queryable, Transaction, TransactionCapable},
Expand Down Expand Up @@ -85,7 +85,10 @@ pub enum QuaintManager {
Mysql { url: MysqlUrl },

#[cfg(feature = "postgresql")]
Postgres { url: PostgresUrl },
Postgres {
url: PostgresUrl,
tls_manager: MakeTlsConnectorManager,
},

#[cfg(feature = "sqlite")]
Sqlite { url: String, db_name: String },
Expand Down Expand Up @@ -117,9 +120,9 @@ impl Manager for QuaintManager {
}

#[cfg(feature = "postgresql-native")]
QuaintManager::Postgres { url } => {
QuaintManager::Postgres { url, tls_manager } => {
use crate::connector::PostgreSql;
Ok(Box::new(PostgreSql::new(url.clone()).await?) as Self::Connection)
Ok(Box::new(PostgreSql::new(url.clone(), tls_manager).await?) as Self::Connection)
}

#[cfg(feature = "mssql-native")]
Expand Down
3 changes: 2 additions & 1 deletion quaint/src/single.rs
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,8 @@ impl Quaint {
#[cfg(feature = "postgresql-native")]
s if s.starts_with("postgres") || s.starts_with("postgresql") => {
let url = connector::PostgresUrl::new(url::Url::parse(s)?)?;
let psql = connector::PostgreSql::new(url).await?;
let tls_manager = connector::MakeTlsConnectorManager::new(url.clone());
let psql = connector::PostgreSql::new(url, &tls_manager).await?;
Arc::new(psql) as Arc<dyn Queryable>
}
#[cfg(feature = "mssql-native")]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use enumflags2::BitFlags;
use indoc::indoc;
use psl::PreviewFeature;
use quaint::{
connector::{self, tokio_postgres::error::ErrorPosition, PostgresUrl},
connector::{self, tokio_postgres::error::ErrorPosition, MakeTlsConnectorManager, PostgresUrl},
prelude::{ConnectionInfo, NativeConnectionInfo, Queryable},
};
use schema_connector::{ConnectorError, ConnectorResult, Namespaces};
Expand All @@ -22,8 +22,9 @@ impl Connection {
details: err.to_string(),
})
})?;
let tls_manager = MakeTlsConnectorManager::new(url.clone());

let quaint = connector::PostgreSql::new(url.clone())
let quaint = connector::PostgreSql::new(url.clone(), &tls_manager)
.await
.map_err(quaint_err(&url))?;

Expand Down
Loading