1
1
use futures:: { channel:: mpsc, FutureExt , StreamExt } ;
2
2
use std:: collections:: { BTreeMap , BTreeSet } ;
3
3
use std:: fmt;
4
+ use std:: time:: { Duration , Instant } ;
4
5
use std:: { cell:: RefCell , cmp:: Ordering , rc:: Rc } ;
5
6
use thiserror:: Error ;
6
7
use tracing:: { debug, error, info, trace, warn} ;
@@ -312,6 +313,7 @@ pub struct SubMan {
312
313
pool : RelayPool ,
313
314
local : BTreeMap < LocalId , SubStateRef > ,
314
315
remote : BTreeMap < RemoteId , SubStateRef > ,
316
+ idle : BTreeMap < String , Instant > ,
315
317
}
316
318
317
319
impl SubMan {
@@ -321,6 +323,7 @@ impl SubMan {
321
323
pool,
322
324
local : BTreeMap :: new ( ) ,
323
325
remote : BTreeMap :: new ( ) ,
326
+ idle : BTreeMap :: new ( ) ,
324
327
}
325
328
}
326
329
@@ -688,14 +691,40 @@ impl SubMan {
688
691
}
689
692
}
690
693
694
+ const IDLE_EXPIRATION_SECS : Duration = Duration :: from_secs ( 20 ) ;
695
+
691
696
fn close_unneeded_relays ( & mut self , default_relays : & [ RelaySpec ] ) {
692
697
let current_relays: BTreeSet < String > = self . pool . urls ( ) ;
693
698
let needed_relays: BTreeSet < String > = self . needed_relays ( default_relays) ;
694
699
let unneeded_relays: BTreeSet < _ > =
695
700
current_relays. difference ( & needed_relays) . cloned ( ) . collect ( ) ;
696
- if !unneeded_relays. is_empty ( ) {
697
- debug ! ( "closing unneeded relays: {:?}" , unneeded_relays) ;
698
- self . pool . remove_urls ( & unneeded_relays) ;
701
+
702
+ // remove all needed relays from the idle collection
703
+ for r in needed_relays {
704
+ self . idle . remove ( & r) ;
705
+ }
706
+
707
+ // manage idle relays
708
+ let mut expired = BTreeSet :: new ( ) ;
709
+ let now = Instant :: now ( ) ;
710
+ for r in unneeded_relays {
711
+ // could be a new entry, an entry that has only been idle
712
+ // a short time, or an expired entry
713
+ let entry = self . idle . entry ( r. clone ( ) ) . or_insert ( now) ;
714
+ if now. duration_since ( * entry) > Self :: IDLE_EXPIRATION_SECS {
715
+ expired. insert ( r. clone ( ) ) ;
716
+ }
717
+ }
718
+
719
+ // close the expired relays
720
+ if !expired. is_empty ( ) {
721
+ debug ! ( "closing expired relays: {:?}" , expired) ;
722
+ self . pool . remove_urls ( & expired) ;
723
+ }
724
+
725
+ // remove the expired relays from the idle collection
726
+ for r in expired {
727
+ self . idle . remove ( & r) ;
699
728
}
700
729
}
701
730
0 commit comments