From 6fc68dac8377fa0bda2eb995c917fde7697cf1e5 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Wed, 27 Aug 2025 15:04:26 +0200 Subject: [PATCH] refactor(sdk,base): Move `LatestEventValue` into `matrix_sdk_base`. This patch moves `LatestEventValue` into the `matrix_sdk_base::latest_event` module. If we want to store this value in `RoomInfo`, it must be in this crate. Because it's not allowed to `impl T` where `T` lives in a different crate, this patch changes the `impl LatestEventValue` to `struct LatestEventValueBuilder` + `impl LatestEventValueBuilder`. Luckily, all methods on `LatestEventValue` are only constructors, so the change is super straightforward. --- crates/matrix-sdk-base/src/latest_event.rs | 36 ++++- .../src/latest_events/latest_event.rs | 135 ++++++++---------- 2 files changed, 92 insertions(+), 79 deletions(-) diff --git a/crates/matrix-sdk-base/src/latest_event.rs b/crates/matrix-sdk-base/src/latest_event.rs index 41aafb00e..6dc4dd88a 100644 --- a/crates/matrix-sdk-base/src/latest_event.rs +++ b/crates/matrix-sdk-base/src/latest_event.rs @@ -2,7 +2,7 @@ //! use as a [crate::Room::latest_event]. use matrix_sdk_common::deserialized_responses::TimelineEvent; -use ruma::{MxcUri, OwnedEventId}; +use ruma::{MilliSecondsSinceUnixEpoch, MxcUri, OwnedEventId}; #[cfg(feature = "e2e-encryption")] use ruma::{ UserId, @@ -21,7 +21,39 @@ use ruma::{ }; use serde::{Deserialize, Serialize}; -use crate::MinimalRoomMemberEvent; +use crate::{MinimalRoomMemberEvent, store::SerializableEventContent}; + +/// A latest event value! +#[derive(Debug, Default, Clone, Serialize, Deserialize)] +pub enum LatestEventValue { + /// No value has been computed yet, or no candidate value was found. + #[default] + None, + + /// The latest event represents a remote event. + Remote(RemoteLatestEventValue), + + /// The latest event represents a local event that is sending. + LocalIsSending(LocalLatestEventValue), + + /// The latest event represents a local event that cannot be sent, either + /// because a previous local event, or this local event cannot be sent. + LocalCannotBeSent(LocalLatestEventValue), +} + +/// Represents the value for [`LatestEventValue::Remote`]. +pub type RemoteLatestEventValue = TimelineEvent; + +/// Represents the value for [`LatestEventValue::LocalIsSending`] and +/// [`LatestEventValue::LocalCannotBeSent`]. +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct LocalLatestEventValue { + /// The time where the event has been created (by this module). + pub timestamp: MilliSecondsSinceUnixEpoch, + + /// The content of the local event. + pub content: SerializableEventContent, +} /// Represents a decision about whether an event could be stored as the latest /// event in a room. Variants starting with Yes indicate that this message could diff --git a/crates/matrix-sdk/src/latest_events/latest_event.rs b/crates/matrix-sdk/src/latest_events/latest_event.rs index e9c55e076..425a64980 100644 --- a/crates/matrix-sdk/src/latest_events/latest_event.rs +++ b/crates/matrix-sdk/src/latest_events/latest_event.rs @@ -15,6 +15,9 @@ use std::{iter::once, ops::Not}; use eyeball::{AsyncLock, SharedObservable, Subscriber}; +pub use matrix_sdk_base::latest_event::{ + LatestEventValue, LocalLatestEventValue, RemoteLatestEventValue, +}; use matrix_sdk_base::{deserialized_responses::TimelineEvent, store::SerializableEventContent}; use ruma::{ events::{ @@ -24,7 +27,6 @@ use ruma::{ }, EventId, MilliSecondsSinceUnixEpoch, OwnedEventId, OwnedTransactionId, TransactionId, UserId, }; -use serde::{Deserialize, Serialize}; use tracing::error; use crate::{event_cache::RoomEventCache, room::WeakRoom, send_queue::RoomSendQueueUpdate}; @@ -60,7 +62,7 @@ impl LatestEvent { _thread_id: thread_id.map(ToOwned::to_owned), buffer_of_values_for_local_events: LatestEventValuesForLocalEvents::new(), current_value: SharedObservable::new_async( - LatestEventValue::new_remote(room_event_cache, weak_room).await, + LatestEventValueBuilder::new_remote(room_event_cache, weak_room).await, ), } } @@ -92,7 +94,8 @@ impl LatestEvent { } let new_value = - LatestEventValue::new_remote_with_power_levels(room_event_cache, power_levels).await; + LatestEventValueBuilder::new_remote_with_power_levels(room_event_cache, power_levels) + .await; self.update(new_value).await; } @@ -105,7 +108,7 @@ impl LatestEvent { room_event_cache: &RoomEventCache, power_levels: &Option<(&UserId, RoomPowerLevels)>, ) { - let new_value = LatestEventValue::new_local( + let new_value = LatestEventValueBuilder::new_local( send_queue_update, &mut self.buffer_of_values_for_local_events, room_event_cache, @@ -333,41 +336,15 @@ mod tests_latest_event { } } -/// A latest event value! -#[derive(Debug, Default, Clone, Serialize, Deserialize)] -pub enum LatestEventValue { - /// No value has been computed yet, or no candidate value was found. - #[default] - None, +/// A builder of [`LatestEventValue`]s. +struct LatestEventValueBuilder; - /// The latest event represents a remote event. - Remote(RemoteLatestEventValue), - - /// The latest event represents a local event that is sending. - LocalIsSending(LocalLatestEventValue), - - /// The latest event represents a local event that cannot be sent, either - /// because a previous local event, or this local event cannot be sent. - LocalCannotBeSent(LocalLatestEventValue), -} - -/// Represents the value for [`LatestEventValue::Remote`]. -pub type RemoteLatestEventValue = TimelineEvent; - -/// Represents the value for [`LatestEventValue::LocalIsSending`] and -/// [`LatestEventValue::LocalCannotBeSent`]. -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct LocalLatestEventValue { - /// The time where the event has been created (by this module). - pub timestamp: MilliSecondsSinceUnixEpoch, - - /// The content of the local event. - pub content: SerializableEventContent, -} - -impl LatestEventValue { +impl LatestEventValueBuilder { /// Create a new [`LatestEventValue::Remote`]. - async fn new_remote(room_event_cache: &RoomEventCache, weak_room: &WeakRoom) -> Self { + async fn new_remote( + room_event_cache: &RoomEventCache, + weak_room: &WeakRoom, + ) -> LatestEventValue { // Get the power levels of the user for the current room if the `WeakRoom` is // still valid. let room = weak_room.get(); @@ -389,13 +366,13 @@ impl LatestEventValue { async fn new_remote_with_power_levels( room_event_cache: &RoomEventCache, power_levels: &Option<(&UserId, RoomPowerLevels)>, - ) -> Self { + ) -> LatestEventValue { room_event_cache .rfind_map_event_in_memory_by(|event| { filter_timeline_event(event, power_levels).then(|| event.clone()) }) .await - .map(Self::Remote) + .map(LatestEventValue::Remote) .unwrap_or_default() } @@ -406,7 +383,7 @@ impl LatestEventValue { buffer_of_values_for_local_events: &mut LatestEventValuesForLocalEvents, room_event_cache: &RoomEventCache, power_levels: &Option<(&UserId, RoomPowerLevels)>, - ) -> Self { + ) -> LatestEventValue { use crate::send_queue::{LocalEcho, LocalEchoContent}; match send_queue_update { @@ -421,29 +398,30 @@ impl LatestEventValue { match serialized_event_content.deserialize() { Ok(content) => { if filter_any_message_like_event_content(content) { - let value = Self::LocalIsSending(LocalLatestEventValue { - timestamp: MilliSecondsSinceUnixEpoch::now(), - content: serialized_event_content.clone(), - }); + let value = + LatestEventValue::LocalIsSending(LocalLatestEventValue { + timestamp: MilliSecondsSinceUnixEpoch::now(), + content: serialized_event_content.clone(), + }); buffer_of_values_for_local_events .push(transaction_id.to_owned(), value.clone()); value } else { - Self::None + LatestEventValue::None } } Err(error) => { error!(?error, "Failed to deserialize an event from `RoomSendQueueUpdate::NewLocalEvent`"); - Self::None + LatestEventValue::None } } } - LocalEchoContent::React { .. } => Self::None, + LocalEchoContent::React { .. } => LatestEventValue::None, }, // A local event has been cancelled before being sent. @@ -525,7 +503,7 @@ impl LatestEventValue { Err(error) => { error!(?error, "Failed to deserialize an event from `RoomSendQueueUpdate::ReplacedLocalEvent`"); - return Self::None; + return LatestEventValue::None; } } } @@ -571,7 +549,7 @@ impl LatestEventValue { // A media upload has made progress. // // Nothing to do here. - RoomSendQueueUpdate::MediaUpload { .. } => Self::None, + RoomSendQueueUpdate::MediaUpload { .. } => LatestEventValue::None, } } @@ -585,7 +563,7 @@ impl LatestEventValue { buffer_of_values_for_local_events: &mut LatestEventValuesForLocalEvents, room_event_cache: &RoomEventCache, power_levels: &Option<(&UserId, RoomPowerLevels)>, - ) -> Self { + ) -> LatestEventValue { if let Some(value) = buffer_of_values_for_local_events.last() { value.clone() } else { @@ -1385,7 +1363,7 @@ mod tests_latest_event_values_for_local_events { } #[cfg(all(not(target_family = "wasm"), test))] -mod tests_latest_event_value { +mod tests_latest_event_value_builder { use std::sync::Arc; use assert_matches::assert_matches; @@ -1407,8 +1385,8 @@ mod tests_latest_event_value { }; use super::{ - LatestEventValue, LatestEventValuesForLocalEvents, RemoteLatestEventValue, RoomEventCache, - RoomSendQueueUpdate, + LatestEventValue, LatestEventValueBuilder, LatestEventValuesForLocalEvents, + RemoteLatestEventValue, RoomEventCache, RoomSendQueueUpdate, }; use crate::{ client::WeakClient, @@ -1515,7 +1493,7 @@ mod tests_latest_event_value { // We get `event_id_1` because `event_id_2` isn't a candidate, // and `event_id_0` hasn't been read yet (because events are read // backwards). - LatestEventValue::new_remote(&room_event_cache, &weak_room).await => with body = "world" + LatestEventValueBuilder::new_remote(&room_event_cache, &weak_room).await => with body = "world" ); } @@ -1572,7 +1550,7 @@ mod tests_latest_event_value { // The `LatestEventValue` matches the new local event. assert_local_value_matches_room_message_with_body!( - LatestEventValue::new_local(&update, &mut buffer, &room_event_cache, &None).await, + LatestEventValueBuilder::new_local(&update, &mut buffer, &room_event_cache, &None).await, LatestEventValue::LocalIsSending => with body = "A" ); } @@ -1586,7 +1564,7 @@ mod tests_latest_event_value { // The `LatestEventValue` matches the new local event. assert_local_value_matches_room_message_with_body!( - LatestEventValue::new_local(&update, &mut buffer, &room_event_cache, &None).await, + LatestEventValueBuilder::new_local(&update, &mut buffer, &room_event_cache, &None).await, LatestEventValue::LocalIsSending => with body = "B" ); } @@ -1617,7 +1595,7 @@ mod tests_latest_event_value { // The `LatestEventValue` matches the new local event. assert_local_value_matches_room_message_with_body!( - LatestEventValue::new_local(&update, &mut buffer, &room_event_cache, &None).await, + LatestEventValueBuilder::new_local(&update, &mut buffer, &room_event_cache, &None).await, LatestEventValue::LocalIsSending => with body = body ); } @@ -1635,7 +1613,7 @@ mod tests_latest_event_value { // The `LatestEventValue` hasn't changed, it still matches the latest local // event. assert_local_value_matches_room_message_with_body!( - LatestEventValue::new_local(&update, &mut buffer, &room_event_cache, &None).await, + LatestEventValueBuilder::new_local(&update, &mut buffer, &room_event_cache, &None).await, LatestEventValue::LocalIsSending => with body = "C" ); @@ -1652,7 +1630,7 @@ mod tests_latest_event_value { // The `LatestEventValue` has changed, it matches the previous (so the first) // local event. assert_local_value_matches_room_message_with_body!( - LatestEventValue::new_local(&update, &mut buffer, &room_event_cache, &None).await, + LatestEventValueBuilder::new_local(&update, &mut buffer, &room_event_cache, &None).await, LatestEventValue::LocalIsSending => with body = "A" ); @@ -1669,7 +1647,8 @@ mod tests_latest_event_value { // The `LatestEventValue` has changed, it's empty! assert_matches!( - LatestEventValue::new_local(&update, &mut buffer, &room_event_cache, &None).await, + LatestEventValueBuilder::new_local(&update, &mut buffer, &room_event_cache, &None) + .await, LatestEventValue::None ); @@ -1697,7 +1676,7 @@ mod tests_latest_event_value { // The `LatestEventValue` matches the new local event. assert_local_value_matches_room_message_with_body!( - LatestEventValue::new_local(&update, &mut buffer, &room_event_cache, &None).await, + LatestEventValueBuilder::new_local(&update, &mut buffer, &room_event_cache, &None).await, LatestEventValue::LocalIsSending => with body = body ); } @@ -1716,7 +1695,7 @@ mod tests_latest_event_value { // The `LatestEventValue` hasn't changed, it still matches the latest local // event. assert_local_value_matches_room_message_with_body!( - LatestEventValue::new_local(&update, &mut buffer, &room_event_cache, &None).await, + LatestEventValueBuilder::new_local(&update, &mut buffer, &room_event_cache, &None).await, LatestEventValue::LocalIsSending => with body = "B" ); @@ -1733,7 +1712,7 @@ mod tests_latest_event_value { // The `LatestEventValue` hasn't changed. assert_local_value_matches_room_message_with_body!( - LatestEventValue::new_local(&update, &mut buffer, &room_event_cache, &None).await, + LatestEventValueBuilder::new_local(&update, &mut buffer, &room_event_cache, &None).await, LatestEventValue::LocalIsSending => with body = "B" ); @@ -1761,7 +1740,7 @@ mod tests_latest_event_value { // The `LatestEventValue` matches the new local event. assert_local_value_matches_room_message_with_body!( - LatestEventValue::new_local(&update, &mut buffer, &room_event_cache, &None).await, + LatestEventValueBuilder::new_local(&update, &mut buffer, &room_event_cache, &None).await, LatestEventValue::LocalIsSending => with body = body ); } @@ -1787,7 +1766,7 @@ mod tests_latest_event_value { // The `LatestEventValue` hasn't changed, it still matches the latest local // event. assert_local_value_matches_room_message_with_body!( - LatestEventValue::new_local(&update, &mut buffer, &room_event_cache, &None).await, + LatestEventValueBuilder::new_local(&update, &mut buffer, &room_event_cache, &None).await, LatestEventValue::LocalIsSending => with body = "B" ); @@ -1812,7 +1791,7 @@ mod tests_latest_event_value { // The `LatestEventValue` has changed, it still matches the latest local // event but with its new content. assert_local_value_matches_room_message_with_body!( - LatestEventValue::new_local(&update, &mut buffer, &room_event_cache, &None).await, + LatestEventValueBuilder::new_local(&update, &mut buffer, &room_event_cache, &None).await, LatestEventValue::LocalIsSending => with body = "B." ); @@ -1838,7 +1817,7 @@ mod tests_latest_event_value { // The `LatestEventValue` matches the new local event. assert_local_value_matches_room_message_with_body!( - LatestEventValue::new_local(&update, &mut buffer, &room_event_cache, &None).await, + LatestEventValueBuilder::new_local(&update, &mut buffer, &room_event_cache, &None).await, LatestEventValue::LocalIsSending => with body = "A" ); @@ -1865,7 +1844,8 @@ mod tests_latest_event_value { // The `LatestEventValue` has changed! assert_matches!( - LatestEventValue::new_local(&update, &mut buffer, &room_event_cache, &None).await, + LatestEventValueBuilder::new_local(&update, &mut buffer, &room_event_cache, &None) + .await, LatestEventValue::None ); @@ -1893,7 +1873,7 @@ mod tests_latest_event_value { // The `LatestEventValue` matches the new local event. assert_local_value_matches_room_message_with_body!( - LatestEventValue::new_local(&update, &mut buffer, &room_event_cache, &None).await, + LatestEventValueBuilder::new_local(&update, &mut buffer, &room_event_cache, &None).await, LatestEventValue::LocalIsSending => with body = body ); } @@ -1913,7 +1893,7 @@ mod tests_latest_event_value { // The `LatestEventValue` has changed, it still matches the latest local // event but it's marked as “cannot be sent”. assert_local_value_matches_room_message_with_body!( - LatestEventValue::new_local(&update, &mut buffer, &room_event_cache, &None).await, + LatestEventValueBuilder::new_local(&update, &mut buffer, &room_event_cache, &None).await, LatestEventValue::LocalCannotBeSent => with body = "B" ); @@ -1934,7 +1914,7 @@ mod tests_latest_event_value { // The `LatestEventValue` has changed, it still matches the latest local // event but it's “is sending”. assert_local_value_matches_room_message_with_body!( - LatestEventValue::new_local(&update, &mut buffer, &room_event_cache, &None).await, + LatestEventValueBuilder::new_local(&update, &mut buffer, &room_event_cache, &None).await, LatestEventValue::LocalIsSending => with body = "B" ); @@ -1963,7 +1943,7 @@ mod tests_latest_event_value { // The `LatestEventValue` matches the new local event. assert_local_value_matches_room_message_with_body!( - LatestEventValue::new_local(&update, &mut buffer, &room_event_cache, &None).await, + LatestEventValueBuilder::new_local(&update, &mut buffer, &room_event_cache, &None).await, LatestEventValue::LocalIsSending => with body = body ); } @@ -1983,7 +1963,7 @@ mod tests_latest_event_value { // The `LatestEventValue` has changed, it still matches the latest local // event but it's marked as “cannot be sent”. assert_local_value_matches_room_message_with_body!( - LatestEventValue::new_local(&update, &mut buffer, &room_event_cache, &None).await, + LatestEventValueBuilder::new_local(&update, &mut buffer, &room_event_cache, &None).await, LatestEventValue::LocalCannotBeSent => with body = "B" ); @@ -2001,7 +1981,7 @@ mod tests_latest_event_value { // The `LatestEventValue` has changed, it still matches the latest local // event but it's “is sending”. assert_local_value_matches_room_message_with_body!( - LatestEventValue::new_local(&update, &mut buffer, &room_event_cache, &None).await, + LatestEventValueBuilder::new_local(&update, &mut buffer, &room_event_cache, &None).await, LatestEventValue::LocalIsSending => with body = "B" ); @@ -2029,7 +2009,7 @@ mod tests_latest_event_value { // The `LatestEventValue` matches the new local event. assert_local_value_matches_room_message_with_body!( - LatestEventValue::new_local(&update, &mut buffer, &room_event_cache, &None).await, + LatestEventValueBuilder::new_local(&update, &mut buffer, &room_event_cache, &None).await, LatestEventValue::LocalIsSending => with body = "A" ); @@ -2049,7 +2029,8 @@ mod tests_latest_event_value { // The `LatestEventValue` has changed somehow, it tells no new // `LatestEventValue` is computed. assert_matches!( - LatestEventValue::new_local(&update, &mut buffer, &room_event_cache, &None).await, + LatestEventValueBuilder::new_local(&update, &mut buffer, &room_event_cache, &None) + .await, LatestEventValue::None ); @@ -2109,7 +2090,7 @@ mod tests_latest_event_value { // We get a `Remote` because there is no `Local*` values! assert_remote_value_matches_room_message_with_body!( - LatestEventValue::new_local( + LatestEventValueBuilder::new_local( // An update that won't be create a new `LatestEventValue`. &RoomSendQueueUpdate::SentEvent { transaction_id: OwnedTransactionId::from("txnid"),