Skip to content

Commit

Permalink
fix: Fix emitting ContactsChanged events on "recently seen" status ch…
Browse files Browse the repository at this point in the history
…ange (#5377)

- Always emit `ContactsChanged` from `contact::update_last_seen()` if a contact was seen recently
  just for simplicity and symmetry with `RecentlySeenLoop::run()` which also may emit several events
  for single contact.
- Fix sleep time calculation in `RecentlySeenLoop::run()` -- `now` must be updated on every
  iteration, before the initial value was used every time which led to progressively long sleeps.
  • Loading branch information
iequidoo committed Apr 6, 2024
1 parent b753440 commit b6a12e3
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 5 deletions.
58 changes: 56 additions & 2 deletions src/contact.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1632,6 +1632,7 @@ pub(crate) async fn update_last_seen(
> 0
&& timestamp > time() - SEEN_RECENTLY_SECONDS
{
context.emit_event(EventType::ContactsChanged(Some(contact_id)));
context
.scheduler
.interrupt_recently_seen(contact_id, timestamp)
Expand Down Expand Up @@ -1762,6 +1763,7 @@ impl RecentlySeenLoop {
.unwrap_or_default();

loop {
let now = SystemTime::now();
let (until, contact_id) =
if let Some((Reverse(timestamp), contact_id)) = unseen_queue.peek() {
(
Expand Down Expand Up @@ -1804,7 +1806,10 @@ impl RecentlySeenLoop {
timestamp,
})) => {
// Received an interrupt.
unseen_queue.push((Reverse(timestamp + SEEN_RECENTLY_SECONDS), contact_id));
if contact_id != ContactId::UNDEFINED {
unseen_queue
.push((Reverse(timestamp + SEEN_RECENTLY_SECONDS), contact_id));
}
}
}
} else {
Expand All @@ -1822,7 +1827,7 @@ impl RecentlySeenLoop {
}
}

pub(crate) fn interrupt(&self, contact_id: ContactId, timestamp: i64) {
pub(crate) fn try_interrupt(&self, contact_id: ContactId, timestamp: i64) {
self.interrupt_send
.try_send(RecentlySeenInterrupt {
contact_id,
Expand All @@ -1831,6 +1836,17 @@ impl RecentlySeenLoop {
.ok();
}

#[cfg(test)]
pub(crate) async fn interrupt(&self, contact_id: ContactId, timestamp: i64) {
self.interrupt_send
.send(RecentlySeenInterrupt {
contact_id,
timestamp,
})
.await
.unwrap();
}

pub(crate) fn abort(self) {
self.handle.abort();
}
Expand Down Expand Up @@ -2812,6 +2828,44 @@ Hi."#;
Ok(())
}

#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn test_was_seen_recently_event() -> Result<()> {
let mut tcm = TestContextManager::new();
let alice = tcm.alice().await;
let bob = tcm.bob().await;
let recently_seen_loop = RecentlySeenLoop::new(bob.ctx.clone());
let chat = bob.create_chat(&alice).await;
let contacts = chat::get_chat_contacts(&bob, chat.id).await?;

for _ in 0..2 {
let chat = alice.create_chat(&bob).await;
let sent_msg = alice.send_text(chat.id, "moin").await;
let contact = Contact::get_by_id(&bob, *contacts.first().unwrap()).await?;
assert!(!contact.was_seen_recently());
while bob.evtracker.try_recv().is_ok() {}
bob.recv_msg(&sent_msg).await;
let contact = Contact::get_by_id(&bob, *contacts.first().unwrap()).await?;
assert!(contact.was_seen_recently());
bob.evtracker
.get_matching(|evt| matches!(evt, EventType::ContactsChanged { .. }))
.await;
recently_seen_loop
.interrupt(contact.id, contact.last_seen)
.await;

// Wait for `was_seen_recently()` to turn off.
while bob.evtracker.try_recv().is_ok() {}
SystemTime::shift(Duration::from_secs(SEEN_RECENTLY_SECONDS as u64 * 2));
recently_seen_loop.interrupt(ContactId::UNDEFINED, 0).await;
let contact = Contact::get_by_id(&bob, *contacts.first().unwrap()).await?;
assert!(!contact.was_seen_recently());
bob.evtracker
.get_matching(|evt| matches!(evt, EventType::ContactsChanged { .. }))
.await;
}
Ok(())
}

#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn test_verified_by_none() -> Result<()> {
let mut tcm = TestContextManager::new();
Expand Down
2 changes: 1 addition & 1 deletion src/events/payload.rs
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ pub enum EventType {
timer: EphemeralTimer,
},

/// Contact(s) created, renamed, blocked or deleted.
/// Contact(s) created, renamed, blocked, deleted or changed their "recently seen" status.
///
/// @param data1 (int) If set, this is the contact_id of an added contact that should be selected.
ContactsChanged(Option<ContactId>),
Expand Down
2 changes: 1 addition & 1 deletion src/scheduler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -924,7 +924,7 @@ impl Scheduler {
}

fn interrupt_recently_seen(&self, contact_id: ContactId, timestamp: i64) {
self.recently_seen_loop.interrupt(contact_id, timestamp);
self.recently_seen_loop.try_interrupt(contact_id, timestamp);
}

/// Halt the scheduler.
Expand Down
5 changes: 4 additions & 1 deletion src/test_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1100,7 +1100,10 @@ fn print_event(event: &Event) {
"Received MSGS_CHANGED(chat_id={chat_id}, msg_id={msg_id})",
))
),
EventType::ContactsChanged(_) => format!("{}", green.paint("Received CONTACTS_CHANGED()")),
EventType::ContactsChanged(contact) => format!(
"{}",
green.paint(format!("Received CONTACTS_CHANGED(contact={contact:?})"))
),
EventType::LocationChanged(contact) => format!(
"{}",
green.paint(format!("Received LOCATION_CHANGED(contact={contact:?})"))
Expand Down

0 comments on commit b6a12e3

Please sign in to comment.