feat(base): Rename recency_timestamp to recency_stamp.

This patch renames “recency timestamp” to “recency stamp”. It prepares
the fact that simplified sliding sync has a `bump_stamp` instead of a
`timestamp`. The notion of _timestamp_ must be removed.
This commit is contained in:
Ivan Enderlin
2024-07-17 15:05:25 +02:00
parent ea9f79a006
commit dc9b975fc0
5 changed files with 68 additions and 87 deletions

View File

@@ -91,8 +91,8 @@ bitflags! {
/// The reason why a [`RoomInfoNotableUpdate`] is emitted.
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct RoomInfoNotableUpdateReasons: u8 {
/// The recency timestamp of the `Room` has changed.
const RECENCY_TIMESTAMP = 0b0000_0001;
/// The recency stamp of the `Room` has changed.
const RECENCY_STAMP = 0b0000_0001;
/// The latest event of the `Room` has changed.
const LATEST_EVENT = 0b0000_0010;
@@ -940,12 +940,12 @@ impl Room {
self.inner.read().base_info.is_marked_unread
}
/// Returns the recency timestamp of the room.
/// Returns the recency stamp of the room.
///
/// Please read `RoomInfo::recency_timestamp` to learn more.
/// Please read `RoomInfo::recency_stamp` to learn more.
#[cfg(feature = "experimental-sliding-sync")]
pub fn recency_timestamp(&self) -> Option<MilliSecondsSinceUnixEpoch> {
self.inner.read().recency_timestamp
pub fn recency_stamp(&self) -> Option<u64> {
self.inner.read().recency_stamp
}
}
@@ -1006,15 +1006,15 @@ pub struct RoomInfo {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub(crate) cached_display_name: Option<DisplayName>,
/// The recency timestamp of this room.
/// The recency stamp of this room.
///
/// It's not to be confused with `origin_server_ts` of the latest event.
/// Sliding Sync might "ignore” some events when computing the recency
/// timestamp of the room. Thus, using this `recency_timestamp` value is
/// stamp of the room. Thus, using this `recency_stamp` value is
/// more accurate than relying on the latest event.
#[cfg(feature = "experimental-sliding-sync")]
#[serde(default)]
pub(crate) recency_timestamp: Option<MilliSecondsSinceUnixEpoch>,
pub(crate) recency_stamp: Option<u64>,
}
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
@@ -1053,7 +1053,7 @@ impl RoomInfo {
warned_about_unknown_room_version: Arc::new(false.into()),
cached_display_name: None,
#[cfg(feature = "experimental-sliding-sync")]
recency_timestamp: None,
recency_stamp: None,
}
}
@@ -1459,12 +1459,12 @@ impl RoomInfo {
self.latest_event.as_deref()
}
/// Updates the recency timestamp of this room.
/// Updates the recency stamp of this room.
///
/// Please read [`Self::recency_timestamp`] to learn more.
/// Please read [`Self::recency_stamp`] to learn more.
#[cfg(feature = "experimental-sliding-sync")]
pub(crate) fn update_recency_timestamp(&mut self, timestamp: MilliSecondsSinceUnixEpoch) {
self.recency_timestamp = Some(timestamp);
pub(crate) fn update_recency_stamp(&mut self, stamp: u64) {
self.recency_stamp = Some(stamp);
}
}
@@ -1675,7 +1675,7 @@ mod tests {
read_receipts: Default::default(),
warned_about_unknown_room_version: Arc::new(false.into()),
cached_display_name: None,
recency_timestamp: Some(MilliSecondsSinceUnixEpoch(42u32.into())),
recency_stamp: Some(42),
};
let info_json = json!({
@@ -1728,7 +1728,7 @@ mod tests {
"latest_active": null,
"pending": []
},
"recency_timestamp": 42,
"recency_stamp": 42,
});
assert_eq!(serde_json::to_value(info).unwrap(), info_json);

View File

@@ -29,7 +29,7 @@ use ruma::{
},
events::{AnyRoomAccountDataEvent, AnySyncStateEvent, AnySyncTimelineEvent},
serde::Raw,
JsOption, OwnedRoomId, RoomId,
JsOption, MilliSecondsSinceUnixEpoch, OwnedRoomId, RoomId,
};
use tracing::{instrument, trace, warn};
@@ -768,18 +768,20 @@ fn process_room_properties(
room_info.mark_members_missing();
}
if let Some(recency_timestamp) = &room_data.timestamp {
if room_info.recency_timestamp.as_ref() != Some(recency_timestamp) {
room_info.update_recency_timestamp(*recency_timestamp);
if let Some(MilliSecondsSinceUnixEpoch(recency_stamp)) = &room_data.timestamp {
let recency_stamp: u64 = (*recency_stamp).into();
// If it's not a new room, let's emit a `RECENCY_TIMESTAMP` update.
if room_info.recency_stamp != Some(recency_stamp) {
room_info.update_recency_stamp(recency_stamp);
// If it's not a new room, let's emit a `RECENCY_STAMP` update.
// For a new room, the room will appear as new, so we don't care about this
// update.
if !is_new_room {
room_info_notable_updates
.entry(room_id.to_owned())
.or_default()
.insert(RoomInfoNotableUpdateReasons::RECENCY_TIMESTAMP);
.insert(RoomInfoNotableUpdateReasons::RECENCY_STAMP);
}
}
}
@@ -812,8 +814,7 @@ mod tests {
},
mxc_uri, owned_mxc_uri, owned_user_id, room_alias_id, room_id,
serde::Raw,
uint, user_id, JsOption, MilliSecondsSinceUnixEpoch, MxcUri, OwnedRoomId, OwnedUserId,
RoomAliasId, RoomId, UserId,
uint, user_id, JsOption, MxcUri, OwnedRoomId, OwnedUserId, RoomAliasId, RoomId, UserId,
};
use serde_json::json;
@@ -1790,59 +1791,53 @@ mod tests {
}
#[async_test]
async fn test_recency_timestamp_is_found_when_processing_sliding_sync_response() {
async fn test_recency_stamp_is_found_when_processing_sliding_sync_response() {
// Given a logged-in client
let client = logged_in_base_client(None).await;
let room_id = room_id!("!r:e.uk");
// When I send sliding sync response containing a room with a recency timestamp
// When I send sliding sync response containing a room with a recency stamp
let room = assign!(v4::SlidingSyncRoom::new(), {
timestamp: Some(MilliSecondsSinceUnixEpoch(42u32.into())),
});
let response = response_with_room(room_id, room);
client.process_sliding_sync(&response, &()).await.expect("Failed to process sync");
// Then the room in the client has the recency timestamp
// Then the room in the client has the recency stamp
let client_room = client.get_room(room_id).expect("No room found");
assert_eq!(client_room.recency_timestamp().expect("No recency timestamp").0, 42u32.into());
assert_eq!(client_room.recency_stamp().expect("No recency stamp"), 42);
}
#[async_test]
async fn test_recency_timestamp_can_be_overwritten_when_present_in_a_sliding_sync_response() {
async fn test_recency_stamp_can_be_overwritten_when_present_in_a_sliding_sync_response() {
// Given a logged-in client
let client = logged_in_base_client(None).await;
let room_id = room_id!("!r:e.uk");
{
// When I send sliding sync response containing a room with a recency timestamp
// When I send sliding sync response containing a room with a recency stamp
let room = assign!(v4::SlidingSyncRoom::new(), {
timestamp: Some(MilliSecondsSinceUnixEpoch(42u32.into())),
});
let response = response_with_room(room_id, room);
client.process_sliding_sync(&response, &()).await.expect("Failed to process sync");
// Then the room in the client has the recency timestamp
// Then the room in the client has the recency stamp
let client_room = client.get_room(room_id).expect("No room found");
assert_eq!(
client_room.recency_timestamp().expect("No recency timestamp").0,
42u32.into()
);
assert_eq!(client_room.recency_stamp().expect("No recency stamp"), 42);
}
{
// When I send sliding sync response containing a room with NO recency timestamp
// When I send sliding sync response containing a room with NO recency stamp
let room = assign!(v4::SlidingSyncRoom::new(), {
timestamp: None,
});
let response = response_with_room(room_id, room);
client.process_sliding_sync(&response, &()).await.expect("Failed to process sync");
// Then the room in the client has the previous recency timestamp
// Then the room in the client has the previous recency stamp
let client_room = client.get_room(room_id).expect("No room found");
assert_eq!(
client_room.recency_timestamp().expect("No recency timestamp").0,
42u32.into()
);
assert_eq!(client_room.recency_stamp().expect("No recency stamp"), 42);
}
{
@@ -1854,23 +1849,20 @@ mod tests {
let response = response_with_room(room_id, room);
client.process_sliding_sync(&response, &()).await.expect("Failed to process sync");
// Then the room in the client has the recency timestamp
// Then the room in the client has the recency stamp
let client_room = client.get_room(room_id).expect("No room found");
assert_eq!(
client_room.recency_timestamp().expect("No recency timestamp").0,
153u32.into()
);
assert_eq!(client_room.recency_stamp().expect("No recency stamp"), 153);
}
}
#[async_test]
async fn test_recency_timestamp_can_trigger_a_notable_update_reason() {
async fn test_recency_stamp_can_trigger_a_notable_update_reason() {
// Given a logged-in client
let client = logged_in_base_client(None).await;
let mut room_info_notable_update_stream = client.room_info_notable_update_receiver();
let room_id = room_id!("!r:e.uk");
// When I send sliding sync response containing a room with a recency timestamp.
// When I send sliding sync response containing a room with a recency stamp.
let room = assign!(v4::SlidingSyncRoom::new(), {
timestamp: Some(MilliSecondsSinceUnixEpoch(42u32.into())),
});
@@ -1883,11 +1875,11 @@ mod tests {
room_info_notable_update_stream.recv().await,
Ok(RoomInfoNotableUpdate { room_id: received_room_id, reasons: received_reasons }) => {
assert_eq!(received_room_id, room_id);
assert!(!received_reasons.contains(RoomInfoNotableUpdateReasons::RECENCY_TIMESTAMP));
assert!(!received_reasons.contains(RoomInfoNotableUpdateReasons::RECENCY_STAMP));
}
);
// When I send sliding sync response containing a room with a recency timestamp.
// When I send sliding sync response containing a room with a recency stamp.
let room = assign!(v4::SlidingSyncRoom::new(), {
timestamp: Some(MilliSecondsSinceUnixEpoch(43u32.into())),
});
@@ -1899,7 +1891,7 @@ mod tests {
room_info_notable_update_stream.recv().await,
Ok(RoomInfoNotableUpdate { room_id: received_room_id, reasons: received_reasons }) => {
assert_eq!(received_room_id, room_id);
assert!(received_reasons.contains(RoomInfoNotableUpdateReasons::RECENCY_TIMESTAMP));
assert!(received_reasons.contains(RoomInfoNotableUpdateReasons::RECENCY_STAMP));
}
);
}

View File

@@ -126,7 +126,7 @@ impl RoomInfoV1 {
warned_about_unknown_room_version: Arc::new(false.into()),
cached_display_name: None,
#[cfg(feature = "experimental-sliding-sync")]
recency_timestamp: None,
recency_stamp: None,
}
}
}

View File

@@ -222,7 +222,7 @@ fn merge_stream_and_receiver(
// We are interested by these _reasons_.
if reasons.contains(NotableUpdate::LATEST_EVENT) ||
reasons.contains(NotableUpdate::RECENCY_TIMESTAMP) ||
reasons.contains(NotableUpdate::RECENCY_STAMP) ||
reasons.contains(NotableUpdate::READ_RECEIPT) ||
reasons.contains(NotableUpdate::UNREAD_MARKER) {
// Emit a `VectorDiff::Set` for the specific rooms.

View File

@@ -14,20 +14,18 @@
use std::cmp::Ordering;
use ruma::MilliSecondsSinceUnixEpoch;
use super::{Room, Sorter};
struct RecencyMatcher<F>
where
F: Fn(&Room, &Room) -> (Option<MilliSecondsSinceUnixEpoch>, Option<MilliSecondsSinceUnixEpoch>),
F: Fn(&Room, &Room) -> (Option<u64>, Option<u64>),
{
timestamps: F,
recency_stamps: F,
}
impl<F> RecencyMatcher<F>
where
F: Fn(&Room, &Room) -> (Option<MilliSecondsSinceUnixEpoch>, Option<MilliSecondsSinceUnixEpoch>),
F: Fn(&Room, &Room) -> (Option<u64>, Option<u64>),
{
fn matches(&self, left: &Room, right: &Room) -> Ordering {
if left.id() == right.id() {
@@ -51,7 +49,7 @@ where
return Ordering::Greater;
}
match (self.timestamps)(left, right) {
match (self.recency_stamps)(left, right) {
(Some(left_timestamp), Some(right_timestamp)) => {
left_timestamp.cmp(&right_timestamp).reverse()
}
@@ -66,11 +64,11 @@ where
}
/// Create a new sorter that will sort two [`Room`] by recency, i.e. by
/// comparing their [`matrix_sdk_base::RoomInfo::recency_timestamp`] value. The
/// `Room` with the newest recency timestamp comes first, i.e. newest < oldest.
/// comparing their [`matrix_sdk_base::RoomInfo::recency_stamp`] value. The
/// `Room` with the newest recency stamp comes first, i.e. newest < oldest.
pub fn new_sorter() -> impl Sorter {
let matcher = RecencyMatcher {
timestamps: move |left, right| (left.recency_timestamp(), right.recency_timestamp()),
recency_stamps: move |left, right| (left.recency_stamp(), right.recency_stamp()),
};
move |left, right| -> Ordering { matcher.matches(left, right) }
@@ -79,85 +77,76 @@ pub fn new_sorter() -> impl Sorter {
#[cfg(test)]
mod tests {
use matrix_sdk_test::async_test;
use ruma::{room_id, MilliSecondsSinceUnixEpoch, UInt};
use ruma::room_id;
use super::{
super::super::filters::{client_and_server_prelude, new_rooms},
*,
};
macro_rules! ms {
($value:literal) => {
MilliSecondsSinceUnixEpoch(UInt::new_wrapping($value))
};
}
#[async_test]
async fn test_with_two_recency_timestamps() {
async fn test_with_two_recency_stamps() {
let (client, server, sliding_sync) = client_and_server_prelude().await;
let [room_a, room_b] =
new_rooms([room_id!("!a:b.c"), room_id!("!d:e.f")], &client, &server, &sliding_sync)
.await;
// `room_a` has an older recency timestamp than `room_b`.
// `room_a` has an older recency stamp than `room_b`.
{
let matcher =
RecencyMatcher { timestamps: |_left, _right| (Some(ms!(1)), Some(ms!(2))) };
let matcher = RecencyMatcher { recency_stamps: |_left, _right| (Some(1), Some(2)) };
// `room_a` is greater than `room_b`, i.e. it must come after `room_b`.
assert_eq!(matcher.matches(&room_a, &room_b), Ordering::Greater);
}
// `room_b` has an older recency timestamp than `room_a`.
// `room_b` has an older recency stamp than `room_a`.
{
let matcher =
RecencyMatcher { timestamps: |_left, _right| (Some(ms!(2)), Some(ms!(1))) };
let matcher = RecencyMatcher { recency_stamps: |_left, _right| (Some(2), Some(1)) };
// `room_a` is less than `room_b`, i.e. it must come before `room_b`.
assert_eq!(matcher.matches(&room_a, &room_b), Ordering::Less);
}
// `room_a` has an equally old recency timestamp than `room_b`.
// `room_a` has an equally old recency stamp than `room_b`.
{
let matcher =
RecencyMatcher { timestamps: |_left, _right| (Some(ms!(1)), Some(ms!(1))) };
let matcher = RecencyMatcher { recency_stamps: |_left, _right| (Some(1), Some(1)) };
assert_eq!(matcher.matches(&room_a, &room_b), Ordering::Equal);
}
}
#[async_test]
async fn test_with_one_recency_timestamp() {
async fn test_with_one_recency_stamp() {
let (client, server, sliding_sync) = client_and_server_prelude().await;
let [room_a, room_b] =
new_rooms([room_id!("!a:b.c"), room_id!("!d:e.f")], &client, &server, &sliding_sync)
.await;
// `room_a` has a recency timestamp, `room_b` has no recency timestamp.
// `room_a` has a recency stamp, `room_b` has no recency stamp.
{
let matcher = RecencyMatcher { timestamps: |_left, _right| (Some(ms!(1)), None) };
let matcher = RecencyMatcher { recency_stamps: |_left, _right| (Some(1), None) };
assert_eq!(matcher.matches(&room_a, &room_b), Ordering::Less);
}
// `room_a` has no recency timestamp, `room_b` has a recency timestamp.
// `room_a` has no recency stamp, `room_b` has a recency stamp.
{
let matcher = RecencyMatcher { timestamps: |_left, _right| (None, Some(ms!(1))) };
let matcher = RecencyMatcher { recency_stamps: |_left, _right| (None, Some(1)) };
assert_eq!(matcher.matches(&room_a, &room_b), Ordering::Greater);
}
}
#[async_test]
async fn test_with_zero_recency_timestamp() {
async fn test_with_zero_recency_stamp() {
let (client, server, sliding_sync) = client_and_server_prelude().await;
let [room_a, room_b] =
new_rooms([room_id!("!a:b.c"), room_id!("!d:e.f")], &client, &server, &sliding_sync)
.await;
// `room_a` and `room_b` has no recency timestamp.
// `room_a` and `room_b` has no recency stamp.
{
let matcher = RecencyMatcher { timestamps: |_left, _right| (None, None) };
let matcher = RecencyMatcher { recency_stamps: |_left, _right| (None, None) };
assert_eq!(matcher.matches(&room_a, &room_b), Ordering::Equal);
}