From 0b2ff5d0e24b45755355879da6659399786406c3 Mon Sep 17 00:00:00 2001 From: link2xt Date: Sat, 22 Aug 2026 18:18:17 +0000 Subject: [PATCH] fix: take timestamp_rcvd into account in estimate_deletion_cnt This did not affect actual message deletion, because select_expired_messages already takes timestamp_rcvd into account and does not delete system messages that say "Messages are end-to-end encrypted" too early. So it is a minor bug as estimate_deletion_cnt is meant to only roughly estimate the number of messages to be deleted. Still, there were no tests before, so now estimate_deletion_cnt is tested. --- src/ephemeral/ephemeral_tests.rs | 16 +++++++++++++++- src/message.rs | 9 +++++---- 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/src/ephemeral/ephemeral_tests.rs b/src/ephemeral/ephemeral_tests.rs index a253a7cc4..46d2806b3 100644 --- a/src/ephemeral/ephemeral_tests.rs +++ b/src/ephemeral/ephemeral_tests.rs @@ -7,7 +7,7 @@ use crate::config::Config; use crate::constants::DC_CHAT_ID_ARCHIVED_LINK; use crate::download::DownloadState; use crate::location; -use crate::message::markseen_msgs; +use crate::message::{estimate_deletion_cnt, markseen_msgs}; use crate::receive_imf::receive_imf; use crate::test_utils; use crate::test_utils::{TestContext, TestContextManager}; @@ -280,12 +280,14 @@ async fn test_ephemeral_delete_msgs() -> Result<()> { // Set DeleteDeviceAfter to 1800s. Then send a saved message which will // still be deleted after 3600s because DeleteDeviceAfter doesn't apply to saved messages. + assert_eq!(estimate_deletion_cnt(t, false, 1800).await.unwrap(), 0); t.set_config(Config::DeleteDeviceAfter, Some("1800")) .await?; let now = time(); let msg = t.send_text(self_chat.id, "Message text").await; + assert_eq!(estimate_deletion_cnt(t, false, 1800).await.unwrap(), 0); check_msg_will_be_deleted(t, msg.sender_msg_id, &self_chat, now + 3559, time() + 3601) .await .unwrap(); @@ -894,6 +896,11 @@ async fn test_delete_device_after_unknown_viewtype() -> Result<()> { let bob = &tcm.bob().await; let chat = alice.create_chat(bob).await; + + // There may be a message created saying that all messages are encrypted + // with timestamp 0 so it is always at the top. + // It should still be not deleted because of the "received timestamp" that is recent. + assert_eq!(estimate_deletion_cnt(alice, false, 600).await.unwrap(), 0); alice .set_config(Config::DeleteDeviceAfter, Some("600")) .await?; @@ -901,6 +908,9 @@ async fn test_delete_device_after_unknown_viewtype() -> Result<()> { let mut msg = Message::new_text("Some message".to_string()); let _alice_sent_message = alice.send_msg(chat.id, &mut msg).await; + // New message should not be deleted as well yet. + assert_eq!(estimate_deletion_cnt(alice, false, 600).await.unwrap(), 0); + // Set message viewtype to unassigned // type 70 that was previously used for videochat invitations. alice @@ -910,6 +920,10 @@ async fn test_delete_device_after_unknown_viewtype() -> Result<()> { SystemTime::shift(Duration::from_secs(1000)); + // Now both the system message about the chat being encrypted + // and the message sent by Alice are going to be deleted. + assert_eq!(estimate_deletion_cnt(alice, false, 600).await.unwrap(), 2); + // This should not fail. delete_expired_messages(alice, time()).await?; alice diff --git a/src/message.rs b/src/message.rs index ac3c29fd2..6dab8ef5a 100644 --- a/src/message.rs +++ b/src/message.rs @@ -2100,10 +2100,11 @@ pub async fn estimate_deletion_cnt( .count( "SELECT COUNT(*) FROM msgs m - WHERE m.id > ? - AND timestamp < ? - AND chat_id != ? - AND chat_id != ? AND hidden = 0;", + WHERE m.id > ?1 + AND timestamp < ?2 -- Sorting timestamp may be 0 for system messages + AND timestamp_rcvd < ?2 -- so we check 'received' timestamp as well. + AND chat_id != ?3 + AND chat_id != ?4 AND hidden = 0;", ( DC_MSG_ID_LAST_SPECIAL, threshold_timestamp,