mirror of
https://seed.radicle.dev/rad:z3gqcJUoA1n9HaHKufZs5FCSGazv5.git
synced 2026-10-18 19:10:30 +08:00
node/routing: Enforce routingMaxSize
`limits.routingMaxSize` is documented as "Number of routing table entries
before we start pruning", but the implementation diverges from this.
DELETE FROM routing WHERE node <> ?1 AND rowid IN
(SELECT rowid FROM routing WHERE timestamp < ?2 ORDER BY timestamp LIMIT ?3)
`?2` is `now - routingMaxAge`. So if nothing is older than routingMaxAge,
nothing is deleted, however far over routingMaxSize the table has grown. On a
seed following a busy network, entries are refreshed by gossip faster than
they age out, and the cap is never reachable.
For example, on a permissive node with routingMaxSize=1000, routingMaxAge=7d,
I observed:
routing rows 94,254
older than routingMaxAge, ie. prunable 16
Dropping routingMaxAge to 1 day cleared the backlog the 7-day setting had
accumulated -- from 94,254 down to 82,400 rows -- but then stopped, with
8 rows prunable and the table still ... 82x over the cap. The `routing` table
size is therefore decided by arrival rate; the configured max size has no
effect on it.
Split the two evictions so each does what its name says:
- size eviction removes the oldest entries down to `routingMaxSize`,
regardless of age;
- age eviction then removes anything still older than
`routingMaxAge`.
Size runs first: it takes the oldest rows, so the age pass only fires when
the table was near its limit.
This commit is contained in:
committed by
Lorenz Leutgeb
parent
3129de3b95
commit
73ad1de2a4
@@ -221,20 +221,33 @@ impl Store for Database {
|
||||
limit: Option<usize>,
|
||||
ignore: &NodeId,
|
||||
) -> Result<usize, Error> {
|
||||
let limit: i64 = limit
|
||||
.and_then(|limit| i64::try_from(limit).ok())
|
||||
.unwrap_or(i64::MAX);
|
||||
let mut stmt = self.db.prepare(
|
||||
"DELETE FROM routing
|
||||
WHERE node <> ?1 AND rowid IN
|
||||
(SELECT rowid FROM routing WHERE timestamp < ?2 ORDER BY timestamp LIMIT ?3)",
|
||||
)?;
|
||||
let mut pruned = 0;
|
||||
|
||||
if let Some(limit) = limit {
|
||||
let limit = i64::try_from(limit).unwrap_or(i64::MAX);
|
||||
let mut stmt = self.db.prepare(
|
||||
"DELETE FROM routing
|
||||
WHERE node <> ?1 AND rowid IN
|
||||
(SELECT rowid FROM routing
|
||||
WHERE node <> ?1
|
||||
ORDER BY timestamp ASC
|
||||
LIMIT ?2)",
|
||||
)?;
|
||||
stmt.bind((1, ignore))?;
|
||||
stmt.bind((2, limit))?;
|
||||
stmt.next()?;
|
||||
pruned += self.db.change_count();
|
||||
}
|
||||
|
||||
let mut stmt = self
|
||||
.db
|
||||
.prepare("DELETE FROM routing WHERE node <> ?1 AND timestamp < ?2")?;
|
||||
stmt.bind((1, ignore))?;
|
||||
stmt.bind((2, &oldest))?;
|
||||
stmt.bind((3, limit))?;
|
||||
stmt.next()?;
|
||||
pruned += self.db.change_count();
|
||||
|
||||
Ok(self.db.change_count())
|
||||
Ok(pruned)
|
||||
}
|
||||
|
||||
fn count(&self, id: &RepoId) -> Result<usize, Error> {
|
||||
|
||||
Reference in New Issue
Block a user