atagen

macltok

public
Star0
Watch0

Commit 8127bd8b03da

tarball

atagen <boss@atagen.co>2026-10-27 04:01 UTC

4 files changed+25-31
mentions: keep the profile pass off the network

A device build stopped updating every room after 3eee54c8. Its pass went through get_member, which fetches /members for any room whose members aren't synced, and walked room after room. profiles() also forced a refetch with mark_members_missing. Each fetched roster is saved in competition with sync processing. The pass now reads only the member store, and the mark_members_missing workaround is gone.
Modified file: src/engine/context.rs+9 additions−27 deletions
@@ -552,40 +552,22 @@ async fn fetch_reply(
552552
553553 /// under lazy-loaded members a sender may be unknown locally, and `get_member` fetches the
554554 /// member list once for the room when it is
555-pub(crate) async fn profiles<'a>(
555+async fn profiles<'a>(
556556 room: &Room,
557557 user_ids: impl Iterator<Item = &'a OwnedUserId>,
558558 ) -> HashMap<OwnedUserId, Sender> {
559559 let mut unique: Vec<&OwnedUserId> = user_ids.collect();
560560 unique.sort();
561561 unique.dedup();
562- let lookup = |users: Vec<&'a OwnedUserId>| {
563- join_all(users.into_iter().map(|user_id| async move {
562+ join_all(
563+ unique.into_iter().map(|user_id| async move {
564564 Some((user_id.clone(), member_sender(room, user_id).await?))
565- }))
566- };
567- let mut found: HashMap<_, _> = lookup(unique.clone()).await.into_iter().flatten().collect();
568- let missing: Vec<_> = unique
569- .into_iter()
570- .filter(|user| !found.contains_key(*user))
571- .collect();
572- // stores have been seen with members_synced persisted over a partial roster, after which
573- // the sdk never asks /members again, so a sender it can't find marks it stale once a run
574- if !missing.is_empty() && members_rechecked(room) {
575- room.mark_members_missing();
576- found.extend(lookup(missing).await.into_iter().flatten());
577- }
578- found
579-}
580-
581-fn members_rechecked(room: &Room) -> bool {
582- static CHECKED: std::sync::LazyLock<
583- std::sync::Mutex<std::collections::HashSet<(Option<OwnedUserId>, ruma::OwnedRoomId)>>,
584- > = std::sync::LazyLock::new(Default::default);
585- CHECKED.lock().unwrap().insert((
586- room.client().user_id().map(ToOwned::to_owned),
587- room.room_id().to_owned(),
588- ))
565+ }),
566+ )
567+ .await
568+ .into_iter()
569+ .flatten()
570+ .collect()
589571 }
590572
591573 fn validate_limit(limit: u16) -> Result<(), Error> {
Modified file: src/mentions/service.rs+14 additions−2 deletions
@@ -1442,7 +1442,8 @@ impl Service {
14421442 }
14431443
14441444 /// rows observed after their window's capture never got a profile, so one room at a time
1445- /// looks its bare senders up the way a capture does, outside the actor
1445+ /// looks its bare senders up in the member store. get_member would fetch /members for every room
1446+ /// whose members aren't synced, one after another, and that can starve sync
14461447 fn schedule_profiles(&mut self, work: &mut FuturesUnordered<EngineBoxFuture<'static, Work>>) {
14471448 if self.profiling {
14481449 return;
@@ -1502,7 +1503,18 @@ impl Service {
15021503 self.profiling = true;
15031504 let users: Vec<_> = users.into_iter().collect();
15041505 work.push(Box::pin(async move {
1505- let found = context::profiles(&room, users.iter()).await;
1506+ let found = futures_util::future::join_all(users.iter().map(|user_id| {
1507+ let room = &room;
1508+ async move {
1509+ crate::normalise::stored_member_sender(room, user_id)
1510+ .await
1511+ .map(|sender| (user_id.clone(), sender))
1512+ }
1513+ }))
1514+ .await
1515+ .into_iter()
1516+ .flatten()
1517+ .collect();
15061518 Work::Profiles(room_id, users, found)
15071519 }));
15081520 }
Modified file: src/normalise/member.rs+1 additions−1 deletions
@@ -33,7 +33,7 @@ pub(crate) async fn member_sender(room: &Room, user_id: &OwnedUserId) -> Option<
3333 }
3434
3535 /// what the state store already knows, without asking the server
36-async fn stored_member_sender(room: &Room, user_id: &OwnedUserId) -> Option<Sender> {
36+pub(crate) async fn stored_member_sender(room: &Room, user_id: &OwnedUserId) -> Option<Sender> {
3737 let member = room.get_member_no_sync(user_id).await.ok().flatten()?;
3838 Some(sender(user_id, &member))
3939 }
Modified file: src/normalise/mod.rs+1 additions−1 deletions
@@ -15,7 +15,7 @@ pub(crate) use image_pack::{
1515 };
1616 pub(crate) use link_preview::{ROOM_PREVIEW_URLS, server_preview, url_previews_allowed};
1717 pub(crate) use media::{MediaRegistration, MediaScope, MediaSourceInfo};
18-pub(crate) use member::{member_sender, member_summary};
18+pub(crate) use member::{member_sender, member_summary, stored_member_sender};
1919 pub(crate) use observed::{normalise_observed, poll_question};
2020 pub(crate) use room::notification_mode;
2121 pub(crate) use room::{room_summaries, space_child, stored_space_order};