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.
This commit is contained in:
link2xt
2026-08-22 18:18:17 +00:00
committed by l
parent 48888898ee
commit 0b2ff5d0e2
2 changed files with 20 additions and 5 deletions

View File

@@ -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

View File

@@ -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,