diff --git a/src/router.rs b/src/router.rs index 00f65b3..e0e6120 100644 --- a/src/router.rs +++ b/src/router.rs @@ -1245,6 +1245,10 @@ impl RouterInner { self.expired_source_key_sink.clone(), ) } + // We also reset the garbage collection timer (unless the update is a retraction) + else if !metric.is_infinite() { + source_table.reset_timer(source_key, self.expired_source_key_sink.clone()); + } } // no entry for this source key, so insert it else { diff --git a/src/source_table.rs b/src/source_table.rs index 0fdd74f..96de575 100644 --- a/src/source_table.rs +++ b/src/source_table.rs @@ -100,6 +100,26 @@ impl SourceTable { }; } + /// Resets the garbage collection timer for a given source key. + /// + /// Does nothing if the source key is not present. + pub fn reset_timer(&mut self, key: SourceKey, sink: mpsc::Sender) { + self.table + .entry(key) + .and_modify(|(old_expiration_handle, _)| { + // First cancel the existing task + old_expiration_handle.abort(); + // Then set the new one + *old_expiration_handle = tokio::spawn(async move { + tokio::time::sleep(SOURCE_HOLD_DURATION).await; + + if let Err(e) = sink.send(key).await { + error!("Failed to notify router of expired source key {e}"); + } + }); + }); + } + /// Get the [`FeasibilityDistance`] currently associated with the [`SourceKey`]. pub fn get(&self, key: &SourceKey) -> Option<&FeasibilityDistance> { self.table.get(key).map(|(_, v)| v)