diff options
| author | tv <tv@krebsco.de> | 2026-10-26 05:50:14 +0100 |
|---|---|---|
| committer | tv <tv@krebsco.de> | 2026-10-26 05:50:14 +0100 |
| commit | f00378e8609e0117132d7aab3f4468a1721f52fa (patch) | |
| tree | 5a252c09685cf833f5e1a7fc2e2e4e4b3f3c02dd /src/swarm/peer/forget.rs | |
| parent | 51e8c8e38c05d98487784e21f9df54cc18875b8b (diff) | |
keep silent strangers for a day
Diffstat (limited to 'src/swarm/peer/forget.rs')
| -rw-r--r-- | src/swarm/peer/forget.rs | 40 |
1 files changed, 38 insertions, 2 deletions
diff --git a/src/swarm/peer/forget.rs b/src/swarm/peer/forget.rs index 624ca97..df09c3c 100644 --- a/src/swarm/peer/forget.rs +++ b/src/swarm/peer/forget.rs @@ -1,5 +1,8 @@ //! Swarm-wide forget records (`_continuum/forgotten/<pk>`): a peer forgotten on one -//! node is forgotten by all; a forgotten node that is alive cancels its record. +//! node is forgotten by all; a forgotten node that is alive cancels its record. And +//! locally, strangers that went silent. + +use std::time::Duration; use automerge::AutoCommit; use tokio::time::Instant; @@ -7,7 +10,7 @@ use tracing::{info, warn}; use crate::document::meta; use crate::document::store::{self, StoreError}; -use crate::state::AppState; +use crate::state::{AppState, Standing}; fn forgotten_dir() -> Vec<String> { meta::path(&[meta::FORGOTTEN]) @@ -77,3 +80,36 @@ pub(super) async fn apply_forget_records(state: &AppState) { }) .await; } + +/// How long a peer that never became a member is kept once nothing more is heard from +/// it: one listed to us that never answered, or one that keeps failing the handshake +/// (another swarm, a wrong key). Anyone can name peers to a node, so without a limit +/// the map of peers would only grow. +const STRANGER_KEPT: Duration = Duration::from_secs(24 * 3600); + +/// Forgets peers that never became members and were silent for `STRANGER_KEPT`. Only +/// here, not swarm-wide; one that comes back is a stranger again. +pub(super) async fn forget_strangers(state: &AppState) { + let now = Instant::now(); + let mut strangers = Vec::new(); + for (peer, peer_state) in state.peers_snapshot().await { + let peer_state = peer_state.lock().await; + let quiet_since = peer_state.last_seen.unwrap_or(peer_state.added_at); + if !matches!(peer_state.standing, Standing::Member { .. }) + && now.saturating_duration_since(quiet_since) >= STRANGER_KEPT + { + strangers.push(peer); + } + } + if strangers.is_empty() { + return; + } + let mut peer_states = state.peer_states.write().await; + for peer in &strangers { + peer_states.remove(peer); + } + info!( + forgotten = strangers.len(), + "Forgot peers that never became members and were silent for a day" + ); +} |
