Skip to content

Commit 6f84a44

Browse files
committed
feat(sdk): Create LatestEventsError.
1 parent cf16978 commit 6f84a44

File tree

2 files changed

+87
-33
lines changed

2 files changed

+87
-33
lines changed
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// Copyright 2025 The Matrix.org Foundation C.I.C.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
use crate::event_cache::EventCacheError;
16+
17+
/// Errors for the [`LatestEvents`][super::LatestEvents].
18+
#[derive(Debug, thiserror::Error)]
19+
pub enum LatestEventsError {
20+
/// An error from the event cache happened.
21+
#[error(transparent)]
22+
EventCache(EventCacheError),
23+
}

crates/matrix-sdk/src/latest_events/mod.rs

Lines changed: 64 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
//! [`Subscriber`], which brings all the tooling to get the current value or the
4747
//! future values with a stream.
4848
49+
mod error;
4950
mod latest_event;
5051

5152
use std::{
@@ -54,6 +55,7 @@ use std::{
5455
sync::Arc,
5556
};
5657

58+
pub use error::LatestEventsError;
5759
use eyeball::{AsyncLock, Subscriber};
5860
use futures_util::{select, FutureExt};
5961
use latest_event::LatestEvent;
@@ -64,7 +66,7 @@ use tokio::sync::{broadcast, mpsc, RwLock, RwLockReadGuard, RwLockWriteGuard};
6466
use tracing::error;
6567

6668
use crate::{
67-
event_cache::{EventCache, RoomEventCacheGenericUpdate},
69+
event_cache::{EventCache, EventCacheError, RoomEventCacheGenericUpdate},
6870
send_queue::SendQueue,
6971
};
7072

@@ -126,8 +128,8 @@ impl LatestEvents {
126128
/// Start listening to updates (if not already) for a particular room.
127129
///
128130
/// It returns `true` if the room exists, `false` otherwise.
129-
pub async fn listen_to_room(&self, room_id: &RoomId) -> bool {
130-
self.state.registered_rooms.for_room(room_id).await.is_some()
131+
pub async fn listen_to_room(&self, room_id: &RoomId) -> Result<bool, LatestEventsError> {
132+
Ok(self.state.registered_rooms.for_room(room_id).await?.is_some())
131133
}
132134

133135
/// Start listening to updates (if not already) for a particular room, and
@@ -138,18 +140,24 @@ impl LatestEvents {
138140
pub async fn listen_and_subscribe_to_room(
139141
&self,
140142
room_id: &RoomId,
141-
) -> Option<Subscriber<LatestEventValue, AsyncLock>> {
142-
let latest_event = self.state.registered_rooms.for_room(room_id).await?;
143+
) -> Result<Option<Subscriber<LatestEventValue, AsyncLock>>, LatestEventsError> {
144+
let Some(latest_event) = self.state.registered_rooms.for_room(room_id).await? else {
145+
return Ok(None);
146+
};
143147

144-
Some(latest_event.subscribe().await)
148+
Ok(Some(latest_event.subscribe().await))
145149
}
146150

147151
/// Start listening to updates (if not already) for a particular room and a
148152
/// particular thread in this room.
149153
///
150154
/// It returns `true` if the room and the thread exists, `false` otherwise.
151-
pub async fn listen_to_thread(&self, room_id: &RoomId, thread_id: &EventId) -> bool {
152-
self.state.registered_rooms.for_thread(room_id, thread_id).await.is_some()
155+
pub async fn listen_to_thread(
156+
&self,
157+
room_id: &RoomId,
158+
thread_id: &EventId,
159+
) -> Result<bool, LatestEventsError> {
160+
Ok(self.state.registered_rooms.for_thread(room_id, thread_id).await?.is_some())
153161
}
154162

155163
/// Start listening to updates (if not already) for a particular room and a
@@ -161,10 +169,13 @@ impl LatestEvents {
161169
&self,
162170
room_id: &RoomId,
163171
thread_id: &EventId,
164-
) -> Option<Subscriber<LatestEventValue, AsyncLock>> {
165-
let latest_event = self.state.registered_rooms.for_thread(room_id, thread_id).await?;
172+
) -> Result<Option<Subscriber<LatestEventValue, AsyncLock>>, LatestEventsError> {
173+
let Some(latest_event) = self.state.registered_rooms.for_thread(room_id, thread_id).await?
174+
else {
175+
return Ok(None);
176+
};
166177

167-
Some(latest_event.subscribe().await)
178+
Ok(Some(latest_event.subscribe().await))
168179
}
169180

170181
/// Forget a room.
@@ -230,8 +241,8 @@ impl RegisteredRooms {
230241
&self,
231242
room_id: &RoomId,
232243
thread_id: Option<&EventId>,
233-
) -> Option<RwLockReadGuard<'_, RoomLatestEvents>> {
234-
match thread_id {
244+
) -> Result<Option<RwLockReadGuard<'_, RoomLatestEvents>>, LatestEventsError> {
245+
Ok(match thread_id {
235246
// Get the room latest event with the aim of fetching the latest event for a particular
236247
// thread.
237248
//
@@ -243,7 +254,9 @@ impl RegisteredRooms {
243254
// The `RoomLatestEvents` doesn't exist. Let's create and insert it.
244255
if rooms.contains_key(room_id).not() {
245256
// Insert the room if it's been successfully created.
246-
if let Some(room_latest_event) = RoomLatestEvents::new(room_id).await {
257+
if let Some(room_latest_event) =
258+
RoomLatestEvents::new(room_id, &self.event_cache).await?
259+
{
247260
rooms.insert(room_id.to_owned(), room_latest_event);
248261

249262
let _ = self
@@ -281,7 +294,9 @@ impl RegisteredRooms {
281294

282295
if rooms.contains_key(room_id).not() {
283296
// Insert the room if it's been successfully created.
284-
if let Some(room_latest_event) = RoomLatestEvents::new(room_id).await {
297+
if let Some(room_latest_event) =
298+
RoomLatestEvents::new(room_id, &self.event_cache).await?
299+
{
285300
rooms.insert(room_id.to_owned(), room_latest_event);
286301

287302
let _ = self
@@ -295,17 +310,20 @@ impl RegisteredRooms {
295310
}
296311
}
297312
}
298-
}
313+
})
299314
}
300315

301316
/// Start listening to updates (if not already) for a particular room, and
302317
/// fetch the [`LatestEvent`] for this room.
303318
///
304319
/// It returns `None` if the room doesn't exist.
305-
pub async fn for_room(&self, room_id: &RoomId) -> Option<RwLockReadGuard<'_, LatestEvent>> {
306-
self.room_latest_event(room_id, None).await.map(|lock_guard| {
320+
pub async fn for_room(
321+
&self,
322+
room_id: &RoomId,
323+
) -> Result<Option<RwLockReadGuard<'_, LatestEvent>>, LatestEventsError> {
324+
Ok(self.room_latest_event(room_id, None).await?.map(|lock_guard| {
307325
RwLockReadGuard::map(lock_guard, |room_latest_event| room_latest_event.for_room())
308-
})
326+
}))
309327
}
310328

311329
/// Start listening to updates (if not already) for a particular room, and
@@ -316,13 +334,13 @@ impl RegisteredRooms {
316334
&self,
317335
room_id: &RoomId,
318336
thread_id: &EventId,
319-
) -> Option<RwLockReadGuard<'_, LatestEvent>> {
320-
self.room_latest_event(room_id, Some(thread_id)).await.and_then(|lock_guard| {
337+
) -> Result<Option<RwLockReadGuard<'_, LatestEvent>>, LatestEventsError> {
338+
Ok(self.room_latest_event(room_id, Some(thread_id)).await?.and_then(|lock_guard| {
321339
RwLockReadGuard::try_map(lock_guard, |room_latest_event| {
322340
room_latest_event.for_thread(thread_id)
323341
})
324342
.ok()
325-
})
343+
}))
326344
}
327345

328346
/// Forget a room.
@@ -383,11 +401,24 @@ struct RoomLatestEvents {
383401
}
384402

385403
impl RoomLatestEvents {
386-
async fn new(room_id: &RoomId) -> Option<Self> {
387-
Some(Self {
388-
for_the_room: Self::create_latest_event_for(room_id, None).await?,
389-
per_thread: HashMap::new(),
390-
})
404+
async fn new(
405+
room_id: &RoomId,
406+
event_cache: &EventCache,
407+
) -> Result<Option<Self>, LatestEventsError> {
408+
let _room_event_cache = match event_cache.for_room(room_id).await {
409+
// It's fine to drop the `EventCacheDropHandles` here as the caller
410+
// (`LatestEventState`) owns a clone of the `EventCache`.
411+
Ok((room_event_cache, _drop_handles)) => room_event_cache,
412+
Err(EventCacheError::RoomNotFound { .. }) => return Ok(None),
413+
Err(err) => return Err(LatestEventsError::EventCache(err)),
414+
};
415+
416+
let latest_event = match Self::create_latest_event_for(room_id, None).await {
417+
Some(latest_event) => latest_event,
418+
None => return Ok(None),
419+
};
420+
421+
Ok(Some(Self { for_the_room: latest_event, per_thread: HashMap::new() }))
391422
}
392423

393424
#[allow(clippy::unused_async)]
@@ -565,8 +596,8 @@ mod tests {
565596
assert!(latest_events.state.registered_rooms.rooms.read().await.is_empty());
566597

567598
// Now let's listen to two rooms.
568-
assert!(latest_events.listen_to_room(room_id_0).await);
569-
assert!(latest_events.listen_to_room(room_id_1).await);
599+
assert!(latest_events.listen_to_room(room_id_0).await.unwrap());
600+
assert!(latest_events.listen_to_room(room_id_1).await.unwrap());
570601

571602
{
572603
let rooms = latest_events.state.registered_rooms.rooms.read().await;
@@ -583,8 +614,8 @@ mod tests {
583614
}
584615

585616
// Now let's listen to one thread respectively for two rooms.
586-
assert!(latest_events.listen_to_thread(room_id_1, thread_id_1_0).await);
587-
assert!(latest_events.listen_to_thread(room_id_2, thread_id_2_0).await);
617+
assert!(latest_events.listen_to_thread(room_id_1, thread_id_1_0).await.unwrap());
618+
assert!(latest_events.listen_to_thread(room_id_2, thread_id_2_0).await.unwrap());
588619

589620
{
590621
let rooms = latest_events.state.registered_rooms.rooms.read().await;
@@ -623,7 +654,7 @@ mod tests {
623654
let latest_events = client.latest_events().await;
624655

625656
// Now let's fetch one room.
626-
assert!(latest_events.listen_to_room(room_id_0).await);
657+
assert!(latest_events.listen_to_room(room_id_0).await.unwrap());
627658

628659
{
629660
let rooms = latest_events.state.registered_rooms.rooms.read().await;
@@ -662,7 +693,7 @@ mod tests {
662693
let latest_events = client.latest_events().await;
663694

664695
// Now let's fetch one thread .
665-
assert!(latest_events.listen_to_thread(room_id_0, thread_id_0_0).await);
696+
assert!(latest_events.listen_to_thread(room_id_0, thread_id_0_0).await.unwrap());
666697

667698
{
668699
let rooms = latest_events.state.registered_rooms.rooms.read().await;

0 commit comments

Comments
 (0)