matrix-mcp: sync through a filter that drops presence, typing and unbounded state
This commit is contained in:
parent
b8b55ba23e
commit
e436d356f3
1 changed files with 57 additions and 11 deletions
|
|
@ -749,6 +749,27 @@ async fn restore_account(cfg: &AccountCfg, is_primary: bool) -> Result<Option<Cl
|
|||
Ok(Some(client))
|
||||
}
|
||||
|
||||
/// The server-side sync filter every account uses. The default (no filter)
|
||||
/// ships presence, typing notices, full member state and unbounded
|
||||
/// timelines in every delta, about 50 MB/h on a busy public homeserver.
|
||||
/// This keeps what the daemon uses: room messages (short timelines; unread
|
||||
/// scanning pages back with `/messages`), read receipts (the agent's own
|
||||
/// receipt marks what it has read), invites and account data. Members are
|
||||
/// lazy-loaded: `Room::members` fetches the full list on demand.
|
||||
fn sync_filter() -> matrix_sdk::ruma::api::client::sync::sync_events::v3::Filter {
|
||||
use matrix_sdk::ruma::api::client::{filter::FilterDefinition, sync::sync_events::v3::Filter};
|
||||
let definition: FilterDefinition = serde_json::from_value(serde_json::json!({
|
||||
"presence": {"not_types": ["*"]},
|
||||
"room": {
|
||||
"ephemeral": {"not_types": ["m.typing"]},
|
||||
"state": {"lazy_load_members": true},
|
||||
"timeline": {"limit": 20},
|
||||
},
|
||||
}))
|
||||
.expect("the sync filter is a valid filter definition");
|
||||
Filter::FilterDefinition(definition)
|
||||
}
|
||||
|
||||
/// `client`'s sync loop, sweeping invites and unread rooms into todos tagged
|
||||
/// `tag` after each sync. Builds the loop only; nothing runs until it is
|
||||
/// polled. Never wipes the todo set: that is `main`'s, once, at startup.
|
||||
|
|
@ -762,17 +783,20 @@ fn account_sync_loop(client: &Client, tag: Option<String>) -> SyncLoop {
|
|||
let unread_notified = Arc::new(tokio::sync::Mutex::new(std::collections::HashSet::new()));
|
||||
Box::pin(async move {
|
||||
sync_client
|
||||
.sync_with_callback(SyncSettings::default(), move |_response| {
|
||||
let client = cb_client.clone();
|
||||
let invite_notified = invite_notified.clone();
|
||||
let unread_notified = unread_notified.clone();
|
||||
let tag = tag.clone();
|
||||
async move {
|
||||
timeline::sweep_invites(&client, &invite_notified, tag.as_deref()).await;
|
||||
timeline::sweep_unread(&client, &unread_notified, tag.as_deref()).await;
|
||||
matrix_sdk::LoopCtrl::Continue
|
||||
}
|
||||
})
|
||||
.sync_with_callback(
|
||||
SyncSettings::default().filter(sync_filter()),
|
||||
move |_response| {
|
||||
let client = cb_client.clone();
|
||||
let invite_notified = invite_notified.clone();
|
||||
let unread_notified = unread_notified.clone();
|
||||
let tag = tag.clone();
|
||||
async move {
|
||||
timeline::sweep_invites(&client, &invite_notified, tag.as_deref()).await;
|
||||
timeline::sweep_unread(&client, &unread_notified, tag.as_deref()).await;
|
||||
matrix_sdk::LoopCtrl::Continue
|
||||
}
|
||||
},
|
||||
)
|
||||
.await
|
||||
.context("matrix-sdk sync loop exited")?;
|
||||
Ok(())
|
||||
|
|
@ -781,6 +805,28 @@ fn account_sync_loop(client: &Client, tag: Option<String>) -> SyncLoop {
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
/// The filter keeps the sync cheap: no presence, no typing, lazy members,
|
||||
/// short timelines. Receipts must stay: the unread check reads the
|
||||
/// agent's own.
|
||||
#[test]
|
||||
fn the_sync_filter_drops_the_bulk_and_keeps_receipts() {
|
||||
use matrix_sdk::ruma::api::client::sync::sync_events::v3::Filter;
|
||||
|
||||
let Filter::FilterDefinition(def) = super::sync_filter() else {
|
||||
panic!("an inline definition, not a filter id");
|
||||
};
|
||||
let v = serde_json::to_value(&def).expect("serialize");
|
||||
assert_eq!(v["presence"]["not_types"], serde_json::json!(["*"]));
|
||||
let ephemeral = &v["room"]["ephemeral"]["not_types"];
|
||||
assert_eq!(*ephemeral, serde_json::json!(["m.typing"]));
|
||||
assert!(
|
||||
!ephemeral.to_string().contains("receipt"),
|
||||
"receipts are kept"
|
||||
);
|
||||
assert_eq!(v["room"]["state"]["lazy_load_members"], true);
|
||||
assert_eq!(v["room"]["timeline"]["limit"], 20);
|
||||
}
|
||||
|
||||
use std::time::Duration;
|
||||
|
||||
use tokio::time::Instant;
|
||||
|
|
|
|||
Loading…
Reference in a new issue