Radish alpha
h
Radicle Heartwood Protocol & Stack
Radicle
Git (anonymous pull)
Log in to clone via SSH
protocol: add adaptive backoff for gossip/sync
Quaylyn Rimer committed 3 months ago
commit 8efa29a00f26c7e6297a1248c1b069aea9aaf33b
parent b896746f33195c77bf98c6e090b158195c220eff
1 file changed +35 -9
modified crates/radicle-protocol/src/service.rs
@@ -471,6 +471,10 @@ pub struct Service<D, S, G> {
    refs_populate_pending: bool,
    /// Whether inventory scan is pending.
    inventory_scan_pending: bool,
+
    /// Gossip backoff multiplier.
+
    gossip_backoff: u64,
+
    /// Sync backoff multiplier.
+
    sync_backoff: u64,
}

impl<D, S, G> Service<D, S, G> {
@@ -500,6 +504,14 @@ impl<D, S, G> Service<D, S, G> {
        self.config.limits.network.sync_interval.into()
    }

+
    fn gossip_interval_effective(&self) -> LocalDuration {
+
        self.gossip_interval() * self.gossip_backoff
+
    }
+

+
    fn sync_interval_effective(&self) -> LocalDuration {
+
        self.sync_interval() * self.sync_backoff
+
    }
+

    fn announce_interval(&self) -> LocalDuration {
        self.config.limits.network.announce_interval.into()
    }
@@ -585,6 +597,8 @@ where
            metrics: Metrics::default(),
            refs_populate_pending: false,
            inventory_scan_pending: false,
+
            gossip_backoff: 1,
+
            sync_backoff: 1,
        }
    }

@@ -742,7 +756,7 @@ where
        self.maintain_connections();
        // Start periodic tasks.
        self.outbox.wakeup(self.idle_interval());
-
        self.outbox.wakeup(self.gossip_interval());
+
        self.outbox.wakeup(self.gossip_interval_effective());

        Ok(())
    }
@@ -770,6 +784,8 @@ where
    pub fn wake(&mut self) {
        let now = self.clock;

+
        const MAX_BACKOFF: u64 = 10;
+

        trace!(
            target: "service",
            "Wake +{}",
@@ -806,22 +822,32 @@ where
            self.outbox.wakeup(self.idle_interval());
            self.last_idle = now;
        }
-
        if now - self.last_gossip >= self.gossip_interval() {
+
        if now - self.last_gossip >= self.gossip_interval_effective() {
            trace!(target: "service", "Running 'gossip' task...");

-
            if let Err(e) = self.relay_announcements() {
-
                warn!(target: "service", "Failed to relay stored announcements: {e}");
+
            if self.is_online() {
+
                if let Err(e) = self.relay_announcements() {
+
                    warn!(target: "service", "Failed to relay stored announcements: {e}");
+
                }
+
                self.gossip_backoff = 1;
+
            } else {
+
                self.gossip_backoff = (self.gossip_backoff * 2).min(MAX_BACKOFF);
            }
-
            self.outbox.wakeup(self.gossip_interval());
+
            self.outbox.wakeup(self.gossip_interval_effective());
            self.last_gossip = now;
        }
-
        if now - self.last_sync >= self.sync_interval() {
+
        if now - self.last_sync >= self.sync_interval_effective() {
            trace!(target: "service", "Running 'sync' task...");

-
            if let Err(e) = self.fetch_missing_repositories() {
-
                warn!(target: "service", "Failed to fetch missing inventory: {e}");
+
            if self.is_online() {
+
                if let Err(e) = self.fetch_missing_repositories() {
+
                    warn!(target: "service", "Failed to fetch missing inventory: {e}");
+
                }
+
                self.sync_backoff = 1;
+
            } else {
+
                self.sync_backoff = (self.sync_backoff * 2).min(MAX_BACKOFF);
            }
-
            self.outbox.wakeup(self.sync_interval());
+
            self.outbox.wakeup(self.sync_interval_effective());
            self.last_sync = now;
        }
        if now - self.last_announce >= self.announce_interval() {