Skip to content

Commit 9744ad4

Browse files
committed
feat(base): Store the timestamp from SS in RoomInfo::recency_timestamp.
This patch adds a new field in `RoomInfo`: `recency_timestamp: Option<MilliSecondsSinceUnixEpoch>>`. Its value comes from a Sliding Sync Room response, that's why all this API is behind `cfg(feature = "experimental-sliding-sync")`.
1 parent 765b954 commit 9744ad4

File tree

3 files changed

+130
-4
lines changed

3 files changed

+130
-4
lines changed

crates/matrix-sdk-base/src/rooms/normal.rs

+31-2
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,8 @@ use ruma::{
4848
},
4949
room::RoomType,
5050
serde::Raw,
51-
EventId, MxcUri, OwnedEventId, OwnedMxcUri, OwnedRoomAliasId, OwnedRoomId, OwnedUserId,
52-
RoomAliasId, RoomId, RoomVersionId, UserId,
51+
EventId, MilliSecondsSinceUnixEpoch, MxcUri, OwnedEventId, OwnedMxcUri, OwnedRoomAliasId,
52+
OwnedRoomId, OwnedUserId, RoomAliasId, RoomId, RoomVersionId, UserId,
5353
};
5454
use serde::{Deserialize, Serialize};
5555
use tokio::sync::broadcast;
@@ -888,6 +888,14 @@ impl Room {
888888
pub fn is_marked_unread(&self) -> bool {
889889
self.inner.read().base_info.is_marked_unread
890890
}
891+
892+
/// Returns the recency timestamp of the room.
893+
///
894+
/// Please read [`RoomInfo::recency_timestamp`] to learn more.
895+
#[cfg(feature = "experimental-sliding-sync")]
896+
pub fn recency_timestamp(&self) -> Option<MilliSecondsSinceUnixEpoch> {
897+
self.inner.read().recency_timestamp.clone()
898+
}
891899
}
892900

893901
/// The underlying pure data structure for joined and left rooms.
@@ -946,6 +954,15 @@ pub struct RoomInfo {
946954
/// filled at start when creating a room, or on every successful sync.
947955
#[serde(default, skip_serializing_if = "Option::is_none")]
948956
pub(crate) cached_display_name: Option<DisplayName>,
957+
958+
/// The recency timestamp of this room.
959+
///
960+
/// It's not to be confused with `origin_server_ts` of the latest event.
961+
/// Sliding Sync might "ignore” some events when computing the recency
962+
/// timestamp of the room. Thus, using this `recency_timestamp` value is
963+
/// more accurate than relying on the latest event.
964+
#[cfg(feature = "experimental-sliding-sync")]
965+
pub(crate) recency_timestamp: Option<MilliSecondsSinceUnixEpoch>,
949966
}
950967

951968
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
@@ -983,6 +1000,8 @@ impl RoomInfo {
9831000
base_info: Box::new(BaseRoomInfo::new()),
9841001
warned_about_unknown_room_version: Arc::new(false.into()),
9851002
cached_display_name: None,
1003+
#[cfg(feature = "experimental-sliding-sync")]
1004+
recency_timestamp: None,
9861005
}
9871006
}
9881007

@@ -1387,6 +1406,14 @@ impl RoomInfo {
13871406
pub fn latest_event(&self) -> Option<&LatestEvent> {
13881407
self.latest_event.as_deref()
13891408
}
1409+
1410+
/// Updates the recency timestamp of this room.
1411+
///
1412+
/// Please read [`Self::recency_timestamp`] to learn more.
1413+
#[cfg(feature = "experimental-sliding-sync")]
1414+
pub(crate) fn update_recency_timestamp(&mut self, timestamp: MilliSecondsSinceUnixEpoch) {
1415+
self.recency_timestamp = Some(timestamp);
1416+
}
13901417
}
13911418

13921419
#[cfg(feature = "experimental-sliding-sync")]
@@ -1601,6 +1628,7 @@ mod tests {
16011628
read_receipts: Default::default(),
16021629
warned_about_unknown_room_version: Arc::new(false.into()),
16031630
cached_display_name: None,
1631+
recency_timestamp: Some(MilliSecondsSinceUnixEpoch(42u32.into())),
16041632
};
16051633

16061634
let info_json = json!({
@@ -1653,6 +1681,7 @@ mod tests {
16531681
"latest_active": null,
16541682
"pending": []
16551683
},
1684+
"recency_timestamp": 42,
16561685
});
16571686

16581687
assert_eq!(serde_json::to_value(info).unwrap(), info_json);

crates/matrix-sdk-base/src/sliding_sync.rs

+92-1
Original file line numberDiff line numberDiff line change
@@ -733,6 +733,10 @@ fn process_room_properties(room_data: &v4::SlidingSyncRoom, room_info: &mut Room
733733
if room_data.limited {
734734
room_info.mark_members_missing();
735735
}
736+
737+
if let Some(recency_timestamp) = &room_data.timestamp {
738+
room_info.update_recency_timestamp(*recency_timestamp);
739+
}
736740
}
737741

738742
#[cfg(test)]
@@ -762,7 +766,8 @@ mod tests {
762766
},
763767
mxc_uri, owned_mxc_uri, owned_user_id, room_alias_id, room_id,
764768
serde::Raw,
765-
uint, user_id, JsOption, MxcUri, OwnedRoomId, OwnedUserId, RoomAliasId, RoomId, UserId,
769+
uint, user_id, JsOption, MilliSecondsSinceUnixEpoch, MxcUri, OwnedRoomId, OwnedUserId,
770+
RoomAliasId, RoomId, UserId,
766771
};
767772
use serde_json::json;
768773

@@ -1736,6 +1741,92 @@ mod tests {
17361741
assert_eq!(rawev_id(room.latest_event().unwrap().event().clone()), "$a");
17371742
}
17381743

1744+
#[async_test]
1745+
async fn test_recency_timestamp_is_found_when_processing_sliding_sync_response() {
1746+
// Given a logged-in client
1747+
let client = logged_in_base_client(None).await;
1748+
let room_id = room_id!("!r:e.uk");
1749+
1750+
// When I send sliding sync response containing a room with a recency timestamp
1751+
let room = {
1752+
let mut room = v4::SlidingSyncRoom::new();
1753+
room.timestamp = Some(MilliSecondsSinceUnixEpoch(42u32.into()));
1754+
1755+
room
1756+
};
1757+
let response = response_with_room(room_id, room);
1758+
client.process_sliding_sync(&response, &()).await.expect("Failed to process sync");
1759+
1760+
// Then the room in the client has the recency timestamp
1761+
let client_room = client.get_room(room_id).expect("No room found");
1762+
assert_eq!(client_room.recency_timestamp().expect("No recency timestamp").0, 42u32.into());
1763+
}
1764+
1765+
#[async_test]
1766+
async fn test_recency_timestamp_can_be_overwritten_when_present_in_a_sliding_sync_response() {
1767+
// Given a logged-in client
1768+
let client = logged_in_base_client(None).await;
1769+
let room_id = room_id!("!r:e.uk");
1770+
1771+
{
1772+
// When I send sliding sync response containing a room with a recency timestamp
1773+
let room = {
1774+
let mut room = v4::SlidingSyncRoom::new();
1775+
room.timestamp = Some(MilliSecondsSinceUnixEpoch(42u32.into()));
1776+
1777+
room
1778+
};
1779+
let response = response_with_room(room_id, room);
1780+
client.process_sliding_sync(&response, &()).await.expect("Failed to process sync");
1781+
1782+
// Then the room in the client has the avatar
1783+
let client_room = client.get_room(room_id).expect("No room found");
1784+
assert_eq!(
1785+
client_room.recency_timestamp().expect("No recency timestamp").0,
1786+
42u32.into()
1787+
);
1788+
}
1789+
1790+
{
1791+
// When I send sliding sync response containing a room with NO recency timestamp
1792+
let room = {
1793+
let mut room = v4::SlidingSyncRoom::new();
1794+
room.timestamp = None;
1795+
1796+
room
1797+
};
1798+
let response = response_with_room(room_id, room);
1799+
client.process_sliding_sync(&response, &()).await.expect("Failed to process sync");
1800+
1801+
// Then the room in the client has the previous recency timestamp
1802+
let client_room = client.get_room(room_id).expect("No room found");
1803+
assert_eq!(
1804+
client_room.recency_timestamp().expect("No recency timestamp").0,
1805+
42u32.into()
1806+
);
1807+
}
1808+
1809+
{
1810+
// When I send sliding sync response containing a room with a NEW recency
1811+
// timestamp
1812+
let room = {
1813+
let mut room = v4::SlidingSyncRoom::new();
1814+
room.timestamp = Some(MilliSecondsSinceUnixEpoch(153u32.into()));
1815+
1816+
room
1817+
};
1818+
let response = response_with_room(room_id, room);
1819+
client.process_sliding_sync(&response, &()).await.expect("Failed to process sync");
1820+
1821+
// Then the room in the client has the avatar
1822+
let client_room = client.get_room(room_id).expect("No room found");
1823+
assert_eq!(
1824+
client_room.recency_timestamp().expect("No recency timestamp").0,
1825+
153u32.into()
1826+
);
1827+
}
1828+
}
1829+
17391830
async fn choose_event_to_cache(events: &[SyncTimelineEvent]) -> Option<SyncTimelineEvent> {
17401831
let room = make_room();
17411832
let mut room_info = room.clone_info();

crates/matrix-sdk-base/src/store/migration_helpers.rs

+7-1
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ use ruma::{
3737
},
3838
EmptyStateKey, EventContent, RedactContent, StateEventContent, StateEventType,
3939
},
40-
OwnedRoomId, OwnedUserId, RoomId,
40+
MilliSecondsSinceUnixEpoch, OwnedRoomId, OwnedUserId, RoomId,
4141
};
4242
use serde::{Deserialize, Serialize};
4343

@@ -80,6 +80,8 @@ pub struct RoomInfoV1 {
8080
#[cfg(feature = "experimental-sliding-sync")]
8181
latest_event: Option<SyncTimelineEvent>,
8282
base_info: BaseRoomInfoV1,
83+
#[cfg(feature = "experimental-sliding-sync")]
84+
recency_timestamp: Option<MilliSecondsSinceUnixEpoch>,
8385
}
8486

8587
impl RoomInfoV1 {
@@ -108,6 +110,8 @@ impl RoomInfoV1 {
108110
#[cfg(feature = "experimental-sliding-sync")]
109111
latest_event,
110112
base_info,
113+
#[cfg(feature = "experimental-sliding-sync")]
114+
recency_timestamp,
111115
} = self;
112116

113117
RoomInfo {
@@ -125,6 +129,8 @@ impl RoomInfoV1 {
125129
base_info: base_info.migrate(create),
126130
warned_about_unknown_room_version: Arc::new(false.into()),
127131
cached_display_name: None,
132+
#[cfg(feature = "experimental-sliding-sync")]
133+
recency_timestamp,
128134
}
129135
}
130136
}

0 commit comments

Comments
 (0)