mirror of
https://github.com/launchbadge/sqlx
synced 2024-11-10 14:34:19 +00:00
fix docs and guarantees for pool
This commit is contained in:
parent
4db1f70ae1
commit
c98c49ad47
3 changed files with 76 additions and 28 deletions
|
@ -38,8 +38,6 @@ where
|
|||
url: &str,
|
||||
options: Options,
|
||||
) -> crate::Result<(Arc<Self>, Sender<Idle<DB>>)> {
|
||||
// TODO: Establish [min_idle] connections
|
||||
|
||||
let (pool_tx, pool_rx) = channel(options.max_size as usize);
|
||||
|
||||
let pool = Arc::new(Self {
|
||||
|
@ -50,6 +48,18 @@ where
|
|||
options,
|
||||
});
|
||||
|
||||
for _ in 0.. pool.options.min_size {
|
||||
let raw = pool.new_conn(
|
||||
Instant::now() + pool.options.connect_timeout
|
||||
).await?;
|
||||
|
||||
pool_tx.send(Idle {
|
||||
raw,
|
||||
since: Instant::now()
|
||||
})
|
||||
.await;
|
||||
}
|
||||
|
||||
conn_reaper(&pool, &pool_tx);
|
||||
|
||||
Ok((pool, pool_tx))
|
||||
|
@ -225,7 +235,7 @@ where
|
|||
let max_reaped = pool
|
||||
.size
|
||||
.load(Ordering::Acquire)
|
||||
.saturating_sub(pool.options.min_idle);
|
||||
.saturating_sub(pool.options.min_size);
|
||||
|
||||
// collect connections to reap
|
||||
let (reap, keep) = (0..max_reaped)
|
||||
|
|
|
@ -50,7 +50,7 @@ where
|
|||
{
|
||||
/// Creates a connection pool with the default configuration.
|
||||
pub async fn new(url: &str) -> crate::Result<Self> {
|
||||
Self::with_options(url, Options::default()).await
|
||||
Self::builder().build(url).await
|
||||
}
|
||||
|
||||
async fn with_options(url: &str, options: Options) -> crate::Result<Self> {
|
||||
|
@ -76,8 +76,7 @@ where
|
|||
|
||||
/// Attempts to retrieve a connection from the pool if there is one available.
|
||||
///
|
||||
/// Returns `None` if there are no idle connections available in the pool.
|
||||
/// This method will not block waiting to establish a new connection.
|
||||
/// Returns `None` immediately if there are no idle connections available in the pool.
|
||||
pub fn try_acquire(&self) -> Option<impl DerefMut<Target = DB::Connection>> {
|
||||
self.inner.try_acquire().map(|conn| Connection {
|
||||
raw: Some(conn),
|
||||
|
@ -114,8 +113,8 @@ where
|
|||
}
|
||||
|
||||
/// Returns the configured minimum idle connection count.
|
||||
pub fn min_idle(&self) -> u32 {
|
||||
self.inner.options().min_idle
|
||||
pub fn min_size(&self) -> u32 {
|
||||
self.inner.options().min_size
|
||||
}
|
||||
|
||||
/// Returns the configured maximum connection lifetime.
|
||||
|
|
|
@ -4,7 +4,7 @@ use crate::Database;
|
|||
|
||||
use super::Pool;
|
||||
|
||||
#[derive(Default)]
|
||||
/// Builder for [Pool].
|
||||
pub struct Builder<DB>
|
||||
where
|
||||
DB: Database,
|
||||
|
@ -17,62 +17,101 @@ impl<DB> Builder<DB>
|
|||
where
|
||||
DB: Database,
|
||||
{
|
||||
/// Get a new builder with default options.
|
||||
///
|
||||
/// See the source of this method for current defaults.
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
phantom: PhantomData,
|
||||
options: Options::default(),
|
||||
options: Options {
|
||||
// pool a maximum of 10 connections to the same database
|
||||
max_size: 10,
|
||||
// don't open connections until necessary
|
||||
min_size: 0,
|
||||
// try to connect for 30 seconds before erroring
|
||||
connect_timeout: Duration::from_secs(30),
|
||||
// reap connections that have been alive > 30 minutes
|
||||
// prevents unbounded live-leaking of memory due to naive prepared statement caching
|
||||
// see src/cache.rs for context
|
||||
max_lifetime: Some(Duration::from_secs(1800)),
|
||||
// don't reap connections based on idle time
|
||||
idle_timeout: None,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
/// Set the maximum number of connections that this pool should maintain.
|
||||
pub fn max_size(mut self, max_size: u32) -> Self {
|
||||
self.options.max_size = max_size;
|
||||
self
|
||||
}
|
||||
|
||||
/// Set the amount of time to attempt connecting to the database.
|
||||
///
|
||||
/// If this timeout elapses, [Pool::acquire] will return an error.
|
||||
pub fn connect_timeout(mut self, connect_timeout: Duration) -> Self {
|
||||
self.options.connect_timeout = connect_timeout;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn min_idle(mut self, min_idle: u32) -> Self {
|
||||
self.options.min_idle = min_idle;
|
||||
/// Set the minimum number of connections to maintain at all times.
|
||||
///
|
||||
/// When the pool is built, this many connections will be automatically spun up.
|
||||
///
|
||||
/// If any connection is reaped by [max_lifetime] or [idle_timeout] and it brings
|
||||
/// the connection count below this amount, a new connection will be opened to replace it.
|
||||
pub fn min_size(mut self, min_size: u32) -> Self {
|
||||
self.options.min_size = min_size;
|
||||
self
|
||||
}
|
||||
|
||||
/// Set the maximum lifetime of individual connections.
|
||||
///
|
||||
/// Any connection with a lifetime greater than this will be closed.
|
||||
///
|
||||
/// When set to `None`, all connections live until either reaped by [idle_timeout]
|
||||
/// or explicitly disconnected.
|
||||
///
|
||||
/// Infinite connections are not recommended due to the unfortunate reality of memory/resource
|
||||
/// leaks on the database-side. It is better to retire connections periodically
|
||||
/// (even if only once daily) to allow the database the opportunity to clean up data structures
|
||||
/// (parse trees, query metadata caches, thread-local storage, etc.) that are associated with a
|
||||
/// session.
|
||||
pub fn max_lifetime(mut self, max_lifetime: impl Into<Option<Duration>>) -> Self {
|
||||
self.options.max_lifetime = max_lifetime.into();
|
||||
self
|
||||
}
|
||||
|
||||
/// Set a maximum idle duration for individual connections.
|
||||
///
|
||||
/// Any connection with an idle duration longer than this will be closed.
|
||||
///
|
||||
/// For usage-based database server billing, this can be a cost saver.
|
||||
pub fn idle_timeout(mut self, idle_timeout: impl Into<Option<Duration>>) -> Self {
|
||||
self.options.idle_timeout = idle_timeout.into();
|
||||
self
|
||||
}
|
||||
|
||||
/// Spin up the connection pool.
|
||||
///
|
||||
/// If [min_size] was set to a non-zero value, that many connections will be immediately
|
||||
/// opened and placed into the pool.
|
||||
pub async fn build(self, url: &str) -> crate::Result<Pool<DB>> {
|
||||
Pool::with_options(url, self.options).await
|
||||
}
|
||||
}
|
||||
|
||||
impl<DB> Default for Builder<DB>
|
||||
where
|
||||
DB: Database
|
||||
{
|
||||
fn default() -> Self { Self::new() }
|
||||
}
|
||||
|
||||
pub(crate) struct Options {
|
||||
pub max_size: u32,
|
||||
pub connect_timeout: Duration,
|
||||
pub min_idle: u32,
|
||||
pub min_size: u32,
|
||||
pub max_lifetime: Option<Duration>,
|
||||
pub idle_timeout: Option<Duration>,
|
||||
}
|
||||
|
||||
impl Default for Options {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
max_size: 10,
|
||||
min_idle: 0,
|
||||
connect_timeout: Duration::from_secs(30),
|
||||
// 30 minutes
|
||||
// prevents unbounded live-leaking of memory due to naive prepared statement caching
|
||||
// see src/cache.rs for context
|
||||
max_lifetime: Some(Duration::from_secs(1800)),
|
||||
idle_timeout: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue