From 7bb7748b6b0c40dd19b86f2855524de8c25046f7 Mon Sep 17 00:00:00 2001 From: link2xt Date: Fri, 6 Aug 2021 22:28:50 +0000 Subject: [PATCH] Deduplicate peerstates during housekeeping --- src/peerstate.rs | 24 ++++++++++++++++++++++++ src/sql.rs | 6 +++++- 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/src/peerstate.rs b/src/peerstate.rs index 84a2d1851..3e216b126 100644 --- a/src/peerstate.rs +++ b/src/peerstate.rs @@ -496,6 +496,30 @@ impl Peerstate { } } +/// Removes duplicate peerstates from `acpeerstates` database table. +/// +/// Normally there should be no more than one peerstate per address. +/// However, the database does not enforce this condition. +/// +/// Previously there were bugs that caused creation of additional +/// peerstates when existing peerstate could not be read due to a +/// temporary database error or a failure to parse stored data. This +/// procedure fixes the problem by removing duplicate records. +pub(crate) async fn deduplicate_peerstates(sql: &Sql) -> Result<()> { + sql.execute( + "DELETE FROM acpeerstates + WHERE id NOT IN ( + SELECT MIN(id) + FROM acpeerstates + GROUP BY addr + )", + paramsv![], + ) + .await?; + + Ok(()) +} + #[cfg(test)] mod tests { use super::*; diff --git a/src/sql.rs b/src/sql.rs index 9809ff936..99ae09134 100644 --- a/src/sql.rs +++ b/src/sql.rs @@ -20,7 +20,7 @@ use crate::dc_tools::{dc_delete_file, time}; use crate::ephemeral::start_ephemeral_timers; use crate::message::Message; use crate::param::{Param, Params}; -use crate::peerstate::Peerstate; +use crate::peerstate::{deduplicate_peerstates, Peerstate}; use crate::stock_str; #[macro_export] @@ -598,6 +598,10 @@ pub async fn housekeeping(context: &Context) -> Result<()> { ); } + if let Err(err) = deduplicate_peerstates(&context.sql).await { + warn!(context, "Failed to deduplicate peerstates: {}", err) + } + context.schedule_quota_update().await?; if let Err(e) = context