Skip to content

Commit e43e184

Browse files
committed
fix(pool): don't stop emptying idle queue in .close()
1 parent aacf308 commit e43e184

File tree

1 file changed

+15
-6
lines changed

1 file changed

+15
-6
lines changed

sqlx-core/src/pool/inner.rs

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ use crate::rt::JoinHandle;
1717
use crate::{private_tracing_dynamic_event, rt};
1818
use either::Either;
1919
use futures_util::future::{self, OptionFuture};
20-
use futures_util::FutureExt;
20+
use futures_util::{select, FutureExt};
2121
use std::time::{Duration, Instant};
2222
use tracing::Level;
2323

@@ -75,12 +75,18 @@ impl<DB: Database> PoolInner<DB> {
7575
pub(super) fn close<'a>(self: &'a Arc<Self>) -> impl Future<Output = ()> + 'a {
7676
self.mark_closed();
7777

78+
// Keep clearing the idle queue as connections are released until the count reaches zero.
7879
async move {
79-
while let Some(idle) = self.idle.try_acquire(self) {
80-
idle.close().await;
80+
let mut drained = pin!(self.counter.drain());
81+
82+
loop {
83+
select! {
84+
idle = self.idle.acquire(self) => {
85+
idle.close().await;
86+
},
87+
() = drained.as_mut() => break,
88+
}
8189
}
82-
83-
self.counter.drain().await;
8490
}
8591
}
8692

@@ -116,7 +122,7 @@ impl<DB: Database> PoolInner<DB> {
116122
let acquire_started_at = Instant::now();
117123

118124
let mut close_event = pin!(self.close_event());
119-
let mut deadline = pin!(crate::rt::sleep(self.options.acquire_timeout));
125+
let mut deadline = pin!(rt::sleep(self.options.acquire_timeout));
120126
let mut acquire_idle = pin!(self.idle.acquire(self).fuse());
121127
let mut before_acquire = OptionFuture::from(None);
122128
let mut acquire_connect_permit = pin!(OptionFuture::from(Some(
@@ -130,6 +136,9 @@ impl<DB: Database> PoolInner<DB> {
130136
// * If we acquire a `ConnectPermit`, we begin the connection loop (with backoff)
131137
// as implemented by `DynConnector`.
132138
// * If we acquire an idle connection, we then start polling `check_idle_conn()`.
139+
//
140+
// This doesn't quite fit into `select!{}` because the set of futures that may be polled
141+
// at a given time is dynamic, so it's actually simpler to hand-roll it.
133142
let acquired = future::poll_fn(|cx| {
134143
use std::task::Poll::*;
135144

0 commit comments

Comments
 (0)