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.
This commit is contained in:
Ivan Enderlin
2025-08-27 15:04:26 +02:00
parent f3eeb82b0b
commit 6fc68dac83
2 changed files with 92 additions and 79 deletions

View File

@@ -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

View File

@@ -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"),