sqlx_core_oldapi/pool/
mod.rs

1//! Provides the connection pool for asynchronous SQLx connections.
2//!
3//! Opening a database connection for each and every operation to the database can quickly
4//! become expensive. Furthermore, sharing a database connection between threads and functions
5//! can be difficult to express in Rust.
6//!
7//! A connection pool is a standard technique that can manage opening and re-using connections.
8//! Normally it also enforces a maximum number of connections as these are an expensive resource
9//! on the database server.
10//!
11//! SQLx provides a canonical connection pool implementation intended to satisfy the majority
12//! of use cases.
13//!
14//! See [Pool][crate::pool::Pool] for details.
15//!
16//! Type aliases are provided for each database to make it easier to sprinkle `Pool` through
17//! your codebase:
18//!
19//! * [MssqlPool][crate::mssql::MssqlPool] (MSSQL)
20//! * [MySqlPool][crate::mysql::MySqlPool] (MySQL)
21//! * [PgPool][crate::postgres::PgPool] (PostgreSQL)
22//! * [SqlitePool][crate::sqlite::SqlitePool] (SQLite)
23//!
24//! # Opening a connection pool
25//!
26//! A new connection pool with a default configuration can be created by supplying `Pool`
27//! with the database driver and a connection string.
28//!
29//! ```rust,ignore
30//! use sqlx::Pool;
31//! use sqlx::postgres::Postgres;
32//!
33//! let pool = Pool::<Postgres>::connect("postgres://").await?;
34//! ```
35//!
36//! For convenience, database-specific type aliases are provided:
37//!
38//! ```rust,ignore
39//! use sqlx::mssql::MssqlPool;
40//!
41//! let pool = MssqlPool::connect("mssql://").await?;
42//! ```
43//!
44//! # Using a connection pool
45//!
46//! A connection pool implements [`Executor`][crate::executor::Executor] and can be used directly
47//! when executing a query. Notice that only an immutable reference (`&Pool`) is needed.
48//!
49//! ```rust,ignore
50//! sqlx::query("DELETE FROM articles").execute(&pool).await?;
51//! ```
52//!
53//! A connection or transaction may also be manually acquired with
54//! [`Pool::acquire`] or
55//! [`Pool::begin`].
56
57use self::inner::PoolInner;
58#[cfg(all(
59    any(
60        feature = "postgres",
61        feature = "mysql",
62        feature = "mssql",
63        feature = "sqlite"
64    ),
65    feature = "any"
66))]
67use crate::any::{Any, AnyKind};
68use crate::connection::Connection;
69use crate::database::Database;
70use crate::error::Error;
71use crate::transaction::Transaction;
72use event_listener::EventListener;
73use futures_core::FusedFuture;
74use futures_util::FutureExt;
75use std::fmt;
76use std::future::Future;
77use std::pin::Pin;
78use std::sync::Arc;
79use std::task::{Context, Poll};
80use std::time::{Duration, Instant};
81
82#[macro_use]
83mod executor;
84
85#[macro_use]
86mod maybe;
87
88mod connection;
89mod inner;
90mod options;
91
92pub use self::connection::PoolConnection;
93pub(crate) use self::maybe::MaybePoolConnection;
94pub use self::options::{PoolConnectionMetadata, PoolOptions};
95
96/// An asynchronous pool of SQLx database connections.
97///
98/// Create a pool with [Pool::connect] or [Pool::connect_with] and then call [Pool::acquire]
99/// to get a connection from the pool; when the connection is dropped it will return to the pool
100/// so it can be reused.
101///
102/// You can also pass `&Pool` directly anywhere an `Executor` is required; this will automatically
103/// checkout a connection for you.
104///
105/// See [the module documentation](crate::pool) for examples.
106///
107/// The pool has a maximum connection limit that it will not exceed; if `acquire()` is called
108/// when at this limit and all connections are checked out, the task will be made to wait until
109/// a connection becomes available.
110///
111/// You can configure the connection limit, and other parameters, using [PoolOptions][crate::pool::PoolOptions].
112///
113/// Calls to `acquire()` are fair, i.e. fulfilled on a first-come, first-serve basis.
114///
115/// `Pool` is `Send`, `Sync` and `Clone`. It is intended to be created once at the start of your
116/// application/daemon/web server/etc. and then shared with all tasks throughout the process'
117/// lifetime. How best to accomplish this depends on your program architecture.
118///
119/// In Actix-Web, for example, you can share a single pool with all request handlers using [web::Data].
120///
121/// Cloning `Pool` is cheap as it is simply a reference-counted handle to the inner pool state.
122/// When the last remaining handle to the pool is dropped, the connections owned by the pool are
123/// immediately closed (also by dropping). `PoolConnection` returned by [Pool::acquire] and
124/// `Transaction` returned by [Pool::begin] both implicitly hold a reference to the pool for
125/// their lifetimes.
126///
127/// If you prefer to explicitly shutdown the pool and gracefully close its connections (which
128/// depending on the database type, may include sending a message to the database server that the
129/// connection is being closed), you can call [Pool::close] which causes all waiting and subsequent
130/// calls to [Pool::acquire] to return [Error::PoolClosed], and waits until all connections have
131/// been returned to the pool and gracefully closed.
132///
133/// Type aliases are provided for each database to make it easier to sprinkle `Pool` through
134/// your codebase:
135///
136/// * [MssqlPool][crate::mssql::MssqlPool] (MSSQL)
137/// * [MySqlPool][crate::mysql::MySqlPool] (MySQL)
138/// * [PgPool][crate::postgres::PgPool] (PostgreSQL)
139/// * [SqlitePool][crate::sqlite::SqlitePool] (SQLite)
140///
141/// [web::Data]: https://docs.rs/actix-web/3/actix_web/web/struct.Data.html
142///
143/// ### Why Use a Pool?
144///
145/// A single database connection (in general) cannot be used by multiple threads simultaneously
146/// for various reasons, but an application or web server will typically need to execute numerous
147/// queries or commands concurrently (think of concurrent requests against a web server; many or all
148/// of them will probably need to hit the database).
149///
150/// You could place the connection in a `Mutex` but this will make it a huge bottleneck.
151///
152/// Naively, you might also think to just open a new connection per request, but this
153/// has a number of other caveats, generally due to the high overhead involved in working with
154/// a fresh connection. Examples to follow.
155///
156/// Connection pools facilitate reuse of connections to _amortize_ these costs, helping to ensure
157/// that you're not paying for them each time you need a connection.
158///
159/// ##### 1. Overhead of Opening a Connection
160/// Opening a database connection is not exactly a cheap operation.
161///
162/// For SQLite, it means numerous requests to the filesystem and memory allocations, while for
163/// server-based databases it involves performing DNS resolution, opening a new TCP connection and
164/// allocating buffers.
165///
166/// Each connection involves a nontrivial allocation of resources for the database server, usually
167/// including spawning a new thread or process specifically to handle the connection, both for
168/// concurrency and isolation of faults.
169///
170/// Additionally, database connections typically involve a complex handshake including
171/// authentication, negotiation regarding connection parameters (default character sets, timezones,
172/// locales, supported features) and upgrades to encrypted tunnels.
173///
174/// If `acquire()` is called on a pool with all connections checked out but it is not yet at its
175/// connection limit (see next section), then a new connection is immediately opened, so this pool
176/// does not _automatically_ save you from the overhead of creating a new connection.
177///
178/// However, because this pool by design enforces _reuse_ of connections, this overhead cost
179/// is not paid each and every time you need a connection. In fact, if you set
180/// [the `min_connections` option in PoolOptions][PoolOptions::min_connections], the pool will
181/// create that many connections up-front so that they are ready to go when a request comes in,
182/// and maintain that number on a best-effort basis for consistent performance.
183///
184/// ##### 2. Connection Limits (MySQL, MSSQL, Postgres)
185/// Database servers usually place hard limits on the number of connections that are allowed open at
186/// any given time, to maintain performance targets and prevent excessive allocation of resources,
187/// such as RAM, journal files, disk caches, etc.
188///
189/// These limits have different defaults per database flavor, and may vary between different
190/// distributions of the same database, but are typically configurable on server start;
191/// if you're paying for managed database hosting then the connection limit will typically vary with
192/// your pricing tier.
193///
194/// In MySQL, the default limit is typically 150, plus 1 which is reserved for a user with the
195/// `CONNECTION_ADMIN` privilege so you can still access the server to diagnose problems even
196/// with all connections being used.
197///
198/// In MSSQL the only documentation for the default maximum limit is that it depends on the version
199/// and server configuration.
200///
201/// In Postgres, the default limit is typically 100, minus 3 which are reserved for superusers
202/// (putting the default limit for unprivileged users at 97 connections).
203///
204/// In any case, exceeding these limits results in an error when opening a new connection, which
205/// in a web server context will turn into a `500 Internal Server Error` if not handled, but should
206/// be turned into either `403 Forbidden` or `429 Too Many Requests` depending on your rate-limiting
207/// scheme. However, in a web context, telling a client "go away, maybe try again later" results in
208/// a sub-optimal user experience.
209///
210/// Instead with a connection pool, clients are made to wait in a fair queue for a connection to
211/// become available; by using a single connection pool for your whole application, you can ensure
212/// that you don't exceed the connection limit of your database server while allowing response
213/// time to degrade gracefully at high load.
214///
215/// Of course, if multiple applications are connecting to the same database server, then you
216/// should ensure that the connection limits for all applications add up to your server's maximum
217/// connections or less.
218///
219/// ##### 3. Resource Reuse
220/// The first time you execute a query against your database, the database engine must first turn
221/// the SQL into an actionable _query plan_ which it may then execute against the database. This
222/// involves parsing the SQL query, validating and analyzing it, and in the case of Postgres 12+ and
223/// SQLite, generating code to execute the query plan (native or bytecode, respectively).
224///
225/// These database servers provide a way to amortize this overhead by _preparing_ the query,
226/// associating it with an object ID and placing its query plan in a cache to be referenced when
227/// it is later executed.
228///
229/// Prepared statements have other features, like bind parameters, which make them safer and more
230/// ergonomic to use as well. By design, SQLx pushes you towards using prepared queries/statements
231/// via the [Query][crate::query::Query] API _et al._ and the `query!()` macro _et al._, for
232/// reasons of safety, ergonomics, and efficiency.
233///
234/// However, because database connections are typically isolated from each other in the database
235/// server (either by threads or separate processes entirely), they don't typically share prepared
236/// statements between connections so this work must be redone _for each connection_.
237///
238/// As with section 1, by facilitating reuse of connections, `Pool` helps to ensure their prepared
239/// statements (and thus cached query plans) can be reused as much as possible, thus amortizing
240/// the overhead involved.
241///
242/// Depending on the database server, a connection will have caches for all kinds of other data as
243/// well and queries will generally benefit from these caches being "warm" (populated with data).
244pub struct Pool<DB: Database>(pub(crate) Arc<PoolInner<DB>>);
245
246/// A future that resolves when the pool is closed.
247///
248/// See [`Pool::close_event()`] for details.
249pub struct CloseEvent {
250    listener: Option<Pin<Box<EventListener>>>,
251}
252
253impl<DB: Database> Pool<DB> {
254    /// Create a new connection pool with a default pool configuration and
255    /// the given connection URL, and immediately establish one connection.
256    ///
257    /// Refer to the relevant `ConnectOptions` impl for your database for the expected URL format:
258    ///
259    /// * Postgres: [`PgConnectOptions`][crate::postgres::PgConnectOptions]
260    /// * MySQL: [`MySqlConnectOptions`][crate::mysql::MySqlConnectOptions]
261    /// * SQLite: [`SqliteConnectOptions`][crate::sqlite::SqliteConnectOptions]
262    /// * MSSQL: [`MssqlConnectOptions`][crate::mssql::MssqlConnectOptions]
263    ///
264    /// The default configuration is mainly suited for testing and light-duty applications.
265    /// For production applications, you'll likely want to make at least few tweaks.
266    ///
267    /// See [`PoolOptions::new()`] for details.
268    pub async fn connect(url: &str) -> Result<Self, Error> {
269        PoolOptions::<DB>::new().connect(url).await
270    }
271
272    /// Create a new connection pool with a default pool configuration and
273    /// the given `ConnectOptions`, and immediately establish one connection.
274    ///
275    /// The default configuration is mainly suited for testing and light-duty applications.
276    /// For production applications, you'll likely want to make at least few tweaks.
277    ///
278    /// See [`PoolOptions::new()`] for details.
279    pub async fn connect_with(
280        options: <DB::Connection as Connection>::Options,
281    ) -> Result<Self, Error> {
282        PoolOptions::<DB>::new().connect_with(options).await
283    }
284
285    /// Create a new connection pool with a default pool configuration and
286    /// the given connection URL.
287    ///
288    /// The pool will establish connections only as needed.
289    ///
290    /// Refer to the relevant [`ConnectOptions`] impl for your database for the expected URL format:
291    ///
292    /// * Postgres: [`PgConnectOptions`][crate::postgres::PgConnectOptions]
293    /// * MySQL: [`MySqlConnectOptions`][crate::mysql::MySqlConnectOptions]
294    /// * SQLite: [`SqliteConnectOptions`][crate::sqlite::SqliteConnectOptions]
295    /// * MSSQL: [`MssqlConnectOptions`][crate::mssql::MssqlConnectOptions]
296    ///
297    /// The default configuration is mainly suited for testing and light-duty applications.
298    /// For production applications, you'll likely want to make at least few tweaks.
299    ///
300    /// See [`PoolOptions::new()`] for details.
301    pub fn connect_lazy(url: &str) -> Result<Self, Error> {
302        PoolOptions::<DB>::new().connect_lazy(url)
303    }
304
305    /// Create a new connection pool with a default pool configuration and
306    /// the given `ConnectOptions`.
307    ///
308    /// The pool will establish connections only as needed.
309    ///
310    /// The default configuration is mainly suited for testing and light-duty applications.
311    /// For production applications, you'll likely want to make at least few tweaks.
312    ///
313    /// See [`PoolOptions::new()`] for details.
314    pub fn connect_lazy_with(options: <DB::Connection as Connection>::Options) -> Self {
315        PoolOptions::<DB>::new().connect_lazy_with(options)
316    }
317
318    /// Retrieves a connection from the pool.
319    ///
320    /// The total time this method is allowed to execute is capped by
321    /// [`PoolOptions::acquire_timeout`].
322    /// If that timeout elapses, this will return [`Error::PoolClosed`].
323    ///
324    /// ### Note: Cancellation/Timeout May Drop Connections
325    /// If `acquire` is cancelled or times out after it acquires a connection from the idle queue or
326    /// opens a new one, it will drop that connection because we don't want to assume it
327    /// is safe to return to the pool, and testing it to see if it's safe to release could introduce
328    /// subtle bugs if not implemented correctly. To avoid that entirely, we've decided to not
329    /// gracefully handle cancellation here.
330    ///
331    /// However, if your workload is sensitive to dropped connections such as using an in-memory
332    /// SQLite database with a pool size of 1, you can pretty easily ensure that a cancelled
333    /// `acquire()` call will never drop connections by tweaking your [`PoolOptions`]:
334    ///
335    /// * Set [`test_before_acquire(false)`][PoolOptions::test_before_acquire]
336    /// * Never set [`before_acquire`][PoolOptions::before_acquire] or
337    ///   [`after_connect`][PoolOptions::after_connect].
338    ///
339    /// This should eliminate any potential `.await` points between acquiring a connection and
340    /// returning it.
341    pub fn acquire(&self) -> impl Future<Output = Result<PoolConnection<DB>, Error>> + 'static {
342        let shared = self.0.clone();
343        async move { shared.acquire().await.map(|conn| conn.reattach()) }
344    }
345
346    /// Attempts to retrieve a connection from the pool if there is one available.
347    ///
348    /// Returns `None` immediately if there are no idle connections available in the pool
349    /// or there are tasks waiting for a connection which have yet to wake.
350    pub fn try_acquire(&self) -> Option<PoolConnection<DB>> {
351        self.0.try_acquire().map(|conn| conn.into_live().reattach())
352    }
353
354    /// Retrieves a connection and immediately begins a new transaction.
355    pub async fn begin(&self) -> Result<Transaction<'static, DB>, Error> {
356        Transaction::begin(MaybePoolConnection::PoolConnection(self.acquire().await?)).await
357    }
358
359    /// Attempts to retrieve a connection and immediately begins a new transaction if successful.
360    pub async fn try_begin(&self) -> Result<Option<Transaction<'static, DB>>, Error> {
361        match self.try_acquire() {
362            Some(conn) => Transaction::begin(MaybePoolConnection::PoolConnection(conn))
363                .await
364                .map(Some),
365
366            None => Ok(None),
367        }
368    }
369
370    /// Shut down the connection pool, immediately waking all tasks waiting for a connection.
371    ///
372    /// Upon calling this method, any currently waiting or subsequent calls to [`Pool::acquire`] and
373    /// the like will immediately return [`Error::PoolClosed`] and no new connections will be opened.
374    /// Checked-out connections are unaffected, but will be gracefully closed on-drop
375    /// rather than being returned to the pool.
376    ///
377    /// Returns a `Future` which can be `.await`ed to ensure all connections are
378    /// gracefully closed. It will first close any idle connections currently waiting in the pool,
379    /// then wait for all checked-out connections to be returned or closed.
380    ///
381    /// Waiting for connections to be gracefully closed is optional, but will allow the database
382    /// server to clean up the resources sooner rather than later. This is especially important
383    /// for tests that create a new pool every time, otherwise you may see errors about connection
384    /// limits being exhausted even when running tests in a single thread.
385    ///
386    /// If the returned `Future` is not run to completion, any remaining connections will be dropped
387    /// when the last handle for the given pool instance is dropped, which could happen in a task
388    /// spawned by `Pool` internally and so may be unpredictable otherwise.
389    ///
390    /// `.close()` may be safely called and `.await`ed on multiple handles concurrently.
391    pub fn close(&self) -> impl Future<Output = ()> + '_ {
392        self.0.close()
393    }
394
395    /// Returns `true` if [`.close()`][Pool::close] has been called on the pool, `false` otherwise.
396    pub fn is_closed(&self) -> bool {
397        self.0.is_closed()
398    }
399
400    /// Get a future that resolves when [`Pool::close()`] is called.
401    ///
402    /// If the pool is already closed, the future resolves immediately.
403    ///
404    /// This can be used to cancel long-running operations that hold onto a [`PoolConnection`]
405    /// so they don't prevent the pool from closing (which would otherwise wait until all
406    /// connections are returned).
407    ///
408    /// Examples
409    /// ========
410    /// These examples use Postgres and Tokio, but should suffice to demonstrate the concept.
411    ///
412    /// Do something when the pool is closed:
413    /// ```rust,no_run
414    /// # #[cfg(feature = "postgres")]
415    /// # async fn bleh() -> sqlx_core_oldapi::error::Result<()> {
416    /// use sqlx::PgPool;
417    ///
418    /// let pool = PgPool::connect("postgresql://...").await?;
419    ///
420    /// let pool2 = pool.clone();
421    ///
422    /// tokio::spawn(async move {
423    ///     // Demonstrates that `CloseEvent` is itself a `Future` you can wait on.
424    ///     // This lets you implement any kind of on-close event that you like.
425    ///     pool2.close_event().await;
426    ///
427    ///     println!("Pool is closing!");
428    ///
429    ///     // Imagine maybe recording application statistics or logging a report, etc.
430    /// });
431    ///
432    /// // The rest of the application executes normally...
433    ///
434    /// // Close the pool before the application exits...
435    /// pool.close().await;
436    ///
437    /// # Ok(())
438    /// # }
439    /// ```
440    ///
441    /// Cancel a long-running operation:
442    /// ```rust,no_run
443    /// # #[cfg(feature = "postgres")]
444    /// # async fn bleh() -> sqlx_core_oldapi::error::Result<()> {
445    /// use sqlx::{Executor, PgPool};
446    ///
447    /// let pool = PgPool::connect("postgresql://...").await?;
448    ///
449    /// let pool2 = pool.clone();
450    ///
451    /// tokio::spawn(async move {
452    ///     pool2.close_event().do_until(async {
453    ///         // This statement normally won't return for 30 days!
454    ///         // (Assuming the connection doesn't time out first, of course.)
455    ///         pool2.execute("SELECT pg_sleep('30 days')").await;
456    ///
457    ///         // If the pool is closed before the statement completes, this won't be printed.
458    ///         // This is because `.do_until()` cancels the future it's given if the
459    ///         // pool is closed first.
460    ///         println!("Waited!");
461    ///     }).await;
462    /// });
463    ///
464    /// // This normally wouldn't return until the above statement completed and the connection
465    /// // was returned to the pool. However, thanks to `.do_until()`, the operation was
466    /// // cancelled as soon as we called `.close().await`.
467    /// pool.close().await;
468    ///
469    /// # Ok(())
470    /// # }
471    /// ```
472    pub fn close_event(&self) -> CloseEvent {
473        self.0.close_event()
474    }
475
476    /// Returns the number of connections currently active. This includes idle connections.
477    pub fn size(&self) -> u32 {
478        self.0.size()
479    }
480
481    /// Returns the number of connections active and idle (not in use).
482    ///
483    /// As of 0.6.0, this has been fixed to use a separate atomic counter and so should be fine to
484    /// call even at high load.
485    ///
486    /// This previously called [`crossbeam::queue::ArrayQueue::len()`] which waits for the head and
487    /// tail pointers to be in a consistent state, which may never happen at high levels of churn.
488    pub fn num_idle(&self) -> usize {
489        self.0.num_idle()
490    }
491
492    /// Get the connection options for this pool
493    pub fn connect_options(&self) -> &<DB::Connection as Connection>::Options {
494        &self.0.connect_options
495    }
496
497    /// Get the options for this pool
498    pub fn options(&self) -> &PoolOptions<DB> {
499        &self.0.options
500    }
501}
502
503#[cfg(all(
504    any(
505        feature = "postgres",
506        feature = "mysql",
507        feature = "mssql",
508        feature = "sqlite"
509    ),
510    feature = "any"
511))]
512impl Pool<Any> {
513    /// Returns the database driver currently in-use by this `Pool`.
514    ///
515    /// Determined by the connection URL.
516    pub fn any_kind(&self) -> AnyKind {
517        self.0.connect_options.kind()
518    }
519}
520
521/// Returns a new [Pool] tied to the same shared connection pool.
522impl<DB: Database> Clone for Pool<DB> {
523    fn clone(&self) -> Self {
524        Self(Arc::clone(&self.0))
525    }
526}
527
528impl<DB: Database> fmt::Debug for Pool<DB> {
529    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
530        fmt.debug_struct("Pool")
531            .field("size", &self.0.size())
532            .field("num_idle", &self.0.num_idle())
533            .field("is_closed", &self.0.is_closed())
534            .field("options", &self.0.options)
535            .finish()
536    }
537}
538
539impl CloseEvent {
540    /// Execute the given future until it returns or the pool is closed.
541    ///
542    /// Cancels the future and returns `Err(PoolClosed)` if/when the pool is closed.
543    /// If the pool was already closed, the future is never run.
544    pub async fn do_until<Fut: Future>(&mut self, fut: Fut) -> Result<Fut::Output, Error> {
545        // Check that the pool wasn't closed already.
546        //
547        // We use `poll_immediate()` as it will use the correct waker instead of
548        // a no-op one like `.now_or_never()`, but it won't actually suspend execution here.
549        futures_util::future::poll_immediate(&mut *self)
550            .await
551            .map_or(Ok(()), |_| Err(Error::PoolClosed))?;
552
553        futures_util::pin_mut!(fut);
554
555        // I find that this is clearer in intent than `futures_util::future::select()`
556        // or `futures_util::select_biased!{}` (which isn't enabled anyway).
557        futures_util::future::poll_fn(|cx| {
558            // Poll `fut` first as the wakeup event is more likely for it than `self`.
559            if let Poll::Ready(ret) = fut.as_mut().poll(cx) {
560                return Poll::Ready(Ok(ret));
561            }
562
563            // Can't really factor out mapping to `Err(Error::PoolClosed)` though it seems like
564            // we should because that results in a different `Ok` type each time.
565            //
566            // Ideally we'd map to something like `Result<!, Error>` but using `!` as a type
567            // is not allowed on stable Rust yet.
568            self.poll_unpin(cx).map(|_| Err(Error::PoolClosed))
569        })
570        .await
571    }
572}
573
574impl Future for CloseEvent {
575    type Output = ();
576
577    fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
578        if let Some(listener) = &mut self.listener {
579            futures_core::ready!(listener.poll_unpin(cx));
580        }
581
582        // `EventListener` doesn't like being polled after it yields, and even if it did it
583        // would probably just wait for the next event, neither of which we want.
584        //
585        // So this way, once we get our close event, we fuse this future to immediately return.
586        self.listener = None;
587
588        Poll::Ready(())
589    }
590}
591
592impl FusedFuture for CloseEvent {
593    fn is_terminated(&self) -> bool {
594        self.listener.is_none()
595    }
596}
597
598/// get the time between the deadline and now and use that as our timeout
599///
600/// returns `Error::PoolTimedOut` if the deadline is in the past
601fn deadline_as_timeout(deadline: Instant) -> Result<Duration, Error> {
602    deadline
603        .checked_duration_since(Instant::now())
604        .ok_or(Error::PoolTimedOut)
605}
606
607#[test]
608#[allow(dead_code)]
609fn assert_pool_traits() {
610    fn assert_send_sync<T: Send + Sync>() {}
611    fn assert_clone<T: Clone>() {}
612
613    fn assert_pool<DB: Database>() {
614        assert_send_sync::<Pool<DB>>();
615        assert_clone::<Pool<DB>>();
616    }
617}