fix(base): Add a way for handle_timeline to ignore state events.

Sliding sync expects all state events to be in `required_state`. State
events in `timeline` **must be ignored**. However, in sync v2, state
events in `timeline` **must be handled**.

In the sync response flow, both sliding sync and sync v2 uses the same
`handle_timeline` method. This patch adds an argument to ignore state
events. This is not ideal, but it's a temporary solution as a first
step. The next step is to refactor this code, but let's start easy.

The rest of the patch updates the tests accordingly.
This commit is contained in:
Ivan Enderlin
2024-10-08 17:06:20 +02:00
committed by Benjamin Bouvier
parent 248cf55272
commit 72dc307400
3 changed files with 44 additions and 7 deletions

View File

@@ -384,6 +384,7 @@ impl BaseClient {
room: &Room,
limited: bool,
events: Vec<Raw<AnySyncTimelineEvent>>,
ignore_state_events: bool,
prev_batch: Option<String>,
push_rules: &Ruleset,
user_ids: &mut BTreeSet<OwnedUserId>,
@@ -402,7 +403,7 @@ impl BaseClient {
Ok(e) => {
#[allow(clippy::single_match)]
match &e {
AnySyncTimelineEvent::State(s) => {
AnySyncTimelineEvent::State(s) if !ignore_state_events => {
match s {
AnySyncStateEvent::RoomMember(member) => {
Box::pin(ambiguity_cache.handle_event(
@@ -436,6 +437,8 @@ impl BaseClient {
changes.add_state_event(room.room_id(), s.clone(), raw_event);
}
AnySyncTimelineEvent::State(_) => { /* do nothing */ }
AnySyncTimelineEvent::MessageLike(
AnySyncMessageLikeEvent::RoomRedaction(r),
) => {
@@ -981,6 +984,7 @@ impl BaseClient {
&room,
new_info.timeline.limited,
new_info.timeline.events,
false,
new_info.timeline.prev_batch,
&push_rules,
&mut user_ids,
@@ -1075,6 +1079,7 @@ impl BaseClient {
&room,
new_info.timeline.limited,
new_info.timeline.events,
false,
new_info.timeline.prev_batch,
&push_rules,
&mut user_ids,

View File

@@ -28,7 +28,7 @@ use ruma::api::client::sync::sync_events::v5;
use ruma::events::AnyToDeviceEvent;
use ruma::{
api::client::sync::sync_events::v3::{self, InvitedRoom},
events::{AnyRoomAccountDataEvent, AnySyncStateEvent, AnySyncTimelineEvent},
events::{AnyRoomAccountDataEvent, AnySyncStateEvent},
serde::Raw,
JsOption, OwnedRoomId, RoomId, UInt,
};
@@ -453,6 +453,7 @@ impl BaseClient {
&room,
room_data.limited,
room_data.timeline.clone(),
true,
room_data.prev_batch.clone(),
&push_rules,
&mut user_ids,
@@ -1135,8 +1136,8 @@ mod tests {
let response = response_with_room(room_id, room);
client.process_sliding_sync(&response, &(), true).await.expect("Failed to process sync");
// The room is left.
assert_eq!(client.get_room(room_id).unwrap().state(), RoomState::Left);
// The room is NOT left because state events from `timeline` must be IGNORED!
assert_eq!(client.get_room(room_id).unwrap().state(), RoomState::Joined);
}
#[async_test]

View File

@@ -724,7 +724,7 @@ mod tests {
deserialized_responses::SyncTimelineEvent, latest_event::LatestEvent, sliding_sync::http,
MinimalStateEvent, OriginalMinimalStateEvent,
};
use matrix_sdk_test::{async_test, sync_timeline_event};
use matrix_sdk_test::{async_test, sync_state_event, sync_timeline_event};
use ruma::{
event_id,
events::{
@@ -732,7 +732,7 @@ mod tests {
member::RoomMemberEventContent,
message::{MessageFormat, MessageType},
},
AnySyncTimelineEvent, BundledMessageLikeRelations,
AnySyncStateEvent, AnySyncTimelineEvent, BundledMessageLikeRelations,
},
room_id,
serde::Raw,
@@ -889,7 +889,12 @@ mod tests {
let event = message_event(room_id, user_id, "**My M**", "<b>My M</b>", 122344);
let client = logged_in_client(None).await;
let mut room = http::response::Room::new();
room.timeline.push(member_event(room_id, user_id, "Alice Margatroid", "mxc://e.org/SEs"));
room.required_state.push(member_event_as_state_event(
room_id,
user_id,
"Alice Margatroid",
"mxc://e.org/SEs",
));
// And the room is stored in the client so it can be extracted when needed
let response = response_with_room(room_id, room);
@@ -1000,6 +1005,32 @@ mod tests {
})
}
fn member_event_as_state_event(
room_id: &RoomId,
user_id: &UserId,
display_name: &str,
avatar_url: &str,
) -> Raw<AnySyncStateEvent> {
sync_state_event!({
"type": "m.room.member",
"content": {
"avatar_url": avatar_url,
"displayname": display_name,
"membership": "join",
"reason": ""
},
"event_id": "$143273582443PhrSn:example.org",
"origin_server_ts": 143273583,
"room_id": room_id,
"sender": "@example:example.org",
"state_key": user_id,
"type": "m.room.member",
"unsigned": {
"age": 1234
}
})
}
fn response_with_room(room_id: &RoomId, room: http::response::Room) -> http::Response {
let mut response = http::Response::new("6".to_owned());
response.rooms.insert(room_id.to_owned(), room);