diff --git a/crates/rib/src/table/journal.rs b/crates/rib/src/table/journal.rs index d65c90e..3b17d97 100644 --- a/crates/rib/src/table/journal.rs +++ b/crates/rib/src/table/journal.rs @@ -706,6 +706,11 @@ impl Reader { Progress { events, caught_up } } + /// Whether the last [`Reader::poll`] read everything there was. + pub fn caught_up(&self) -> bool { + self.caught_up + } + /// Waits until there may be something to read. Returns at once if the /// last [`Reader::poll`] did not catch up. pub async fn changed(&mut self) { diff --git a/crates/server/src/advertise.rs b/crates/server/src/advertise.rs index 2fdd3f2..11c6544 100644 --- a/crates/server/src/advertise.rs +++ b/crates/server/src/advertise.rs @@ -245,7 +245,10 @@ struct Exporter { } /// How many changes of best route are taken from the table at a time. -const EXPORT_BATCH: usize = 65_536; +/// Small enough that what one batch sends is being read by the peer +/// while the next is being dressed: a batch is dressed whole before any +/// of it goes, and the session's queue holds the exporter once full. +const EXPORT_BATCH: usize = 4_096; /// How long changes are gathered before they go out, once there are any. const COALESCE: Duration = Duration::from_millis(50); @@ -649,8 +652,11 @@ impl Exporter { // Changes come in runs: a table arriving, a peer // going. Gathered for a moment, the routes that go out // alike go in one message, and the whole run costs one - // look at what each peer is told. - tokio::time::sleep(COALESCE).await; + // look at what each peer is told. Not while the table + // is ahead of this exporter: there is a run in hand. + if self.caught_up() { + tokio::time::sleep(COALESCE).await; + } self.follow().await?; self.end_of_rib().await?; } @@ -732,6 +738,13 @@ impl Exporter { /// Takes the next changes of best route from the table and tells the /// peer of those that are for it. + /// Whether the last look at the table saw everything in it. + fn caught_up(&self) -> bool { + self.learned + .as_ref() + .is_none_or(|learned| learned.reader.caught_up()) + } + async fn follow(&mut self) -> Result<(), Finished> { let Some(learned) = &mut self.learned else { return Ok(());