From 7717de3f896dacabea667bac34f8ceebc9862355 Mon Sep 17 00:00:00 2001 From: iequidoo Date: Thu, 21 May 2026 15:27:30 -0300 Subject: [PATCH] fix: Don't mark messages added to the db later as noticed when handling self-MDN The device which issued the MDN might not have these messages at that moment, or the user might not see them there, so only mark messages having lower ids as noticed. This doesn't fix the problem completely because messages may be received by devices in different order, but should fix it in most cases. --- src/receive_imf.rs | 6 ++++- src/receive_imf/receive_imf_tests.rs | 40 ++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+), 1 deletion(-) diff --git a/src/receive_imf.rs b/src/receive_imf.rs index c1bc3e491..f0345c132 100644 --- a/src/receive_imf.rs +++ b/src/receive_imf.rs @@ -982,12 +982,16 @@ UPDATE config SET value=? WHERE keyname='configured_addr' AND value!=?1 context .sql .execute( + // Don't mark messages added to the db later as noticed, regardless of + // `timestamp`: the device which issued the MDN might not have these + // messages at that moment, or the user might not see them there. " UPDATE msgs SET state=? WHERE state=? AND hidden=0 AND chat_id=? AND - (timestamp,id)<(?,?)", + timestamp<=? AND + id Result<()> { Ok(()) } +#[tokio::test(flavor = "multi_thread", worker_threads = 2)] +async fn test_self_mdn_vs_delayed_msg() -> Result<()> { + let mut tcm = TestContextManager::new(); + let alice = &tcm.alice().await; + let bob1 = &tcm.bob().await; + let bob2 = &tcm.bob().await; + + let alice_chat = alice.create_chat(bob1).await; + let sent1 = alice.send_text(alice_chat.id, "1").await; + SystemTime::shift(Duration::from_secs(1)); + let sent2 = alice.send_text(alice_chat.id, "2").await; + + let msg2_id = bob1.recv_msg(&sent2).await.id; + let msg1_id = bob1.recv_msg(&sent1).await.id; + let bob2_chat_id = bob2.recv_msg(&sent2).await.chat_id; + bob2.recv_msg(&sent1).await; + + message::markseen_msgs(bob1, vec![msg2_id]).await?; + assert_eq!(msg1_id.get_state(bob1).await?, MessageState::InFresh); + smtp::queue_mdn(bob1).await?; + let sent = bob1.pop_sent_msg().await; + + bob2.recv_msg_trash(&sent).await; + let mut msgs = get_chat_msgs(bob2, bob2_chat_id).await?; + let ChatItem::Message { msg_id } = msgs.pop().unwrap() else { + unreachable!(); + }; + let msg = Message::load_from_db(bob2, msg_id).await?; + assert_eq!(msg.text, "2"); + assert_eq!(msg.state, MessageState::InSeen); + let ChatItem::Message { msg_id } = msgs.pop().unwrap() else { + unreachable!(); + }; + let msg = Message::load_from_db(bob2, msg_id).await?; + assert_eq!(msg.text, "1"); + assert_eq!(msg.state, MessageState::InFresh); + Ok(()) +} + #[tokio::test(flavor = "multi_thread", worker_threads = 2)] async fn test_gmx_forwarded_msg() -> Result<()> { let t = TestContext::new_alice().await;