Skip to content

Commit 2ba5425

Browse files
committed
Add test for reclaiming idle conns.
1 parent 66925db commit 2ba5425

File tree

2 files changed

+43
-3
lines changed

2 files changed

+43
-3
lines changed

iroh-connection-pool/src/connection_pool.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,10 @@ impl Actor {
243243
self.idle.retain(|&x| x != id);
244244
}
245245

246+
fn pop_oldest_idle(&mut self) -> Option<NodeId> {
247+
self.idle.pop_front()
248+
}
249+
246250
fn remove_connection(&mut self, id: NodeId) {
247251
self.connections.remove(&id);
248252
self.remove_idle(id);
@@ -266,8 +270,9 @@ impl Actor {
266270

267271
// No connection actor or it died - check limits
268272
if self.connections.len() >= self.context.options.max_connections {
269-
if let Some(idle) = self.idle.pop_front() {
273+
if let Some(idle) = self.pop_oldest_idle() {
270274
// remove the oldest idle connection to make room for one more
275+
trace!("removing oldest idle connection {}", idle);
271276
self.connections.remove(&idle);
272277
} else {
273278
handler(Err(PoolConnectError::TooManyConnections))

iroh-connection-pool/src/tests.rs

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -166,10 +166,8 @@ async fn connection_pool_smoke() -> TestResult<()> {
166166
let msg = b"Hello, world!".to_vec();
167167
for id in &ids {
168168
let (cid1, res) = client.echo(*id, msg.clone()).await???;
169-
println!("First response from {}: {:?}", cid1, res);
170169
assert_eq!(res, msg);
171170
let (cid2, res) = client.echo(*id, msg.clone()).await???;
172-
println!("Second response from {}: {:?}", cid2, res);
173171
assert_eq!(res, msg);
174172
assert_eq!(cid1, cid2);
175173
connection_ids.insert(id, cid1);
@@ -183,3 +181,40 @@ async fn connection_pool_smoke() -> TestResult<()> {
183181
}
184182
Ok(())
185183
}
184+
185+
/// Tests that idle connections are being reclaimed to make room if we hit the
186+
/// maximum connection limit.
187+
#[tokio::test]
188+
async fn connection_pool_idle() -> TestResult<()> {
189+
let n = 32;
190+
let filter = tracing_subscriber::EnvFilter::from_default_env();
191+
tracing_subscriber::fmt().with_env_filter(filter).init();
192+
let nodes = echo_servers(n).await?;
193+
let ids = nodes
194+
.iter()
195+
.map(|(addr, _)| addr.node_id)
196+
.collect::<Vec<_>>();
197+
// set up static discovery for all addrs
198+
let discovery = StaticProvider::from_node_info(nodes.iter().map(|(addr, _)| addr.clone()));
199+
// build a client endpoint that can resolve all the node ids
200+
let endpoint = iroh::Endpoint::builder()
201+
.discovery(discovery.clone())
202+
.bind()
203+
.await?;
204+
let pool = ConnectionPool::new(
205+
endpoint.clone(),
206+
ECHO_ALPN,
207+
Options {
208+
idle_timeout: Duration::from_secs(100),
209+
max_connections: 8,
210+
..test_options()
211+
},
212+
);
213+
let client = EchoClient { pool };
214+
let msg = b"Hello, world!".to_vec();
215+
for id in &ids {
216+
let (_, res) = client.echo(*id, msg.clone()).await???;
217+
assert_eq!(res, msg);
218+
}
219+
Ok(())
220+
}

0 commit comments

Comments
 (0)