Skip to content

Commit b7d6fd0

Browse files
committed
event cache: enforce unique access on the EventCacheStore
1 parent 0469c27 commit b7d6fd0

File tree

1 file changed

+54
-30
lines changed
  • crates/matrix-sdk/src/event_cache

1 file changed

+54
-30
lines changed

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

Lines changed: 54 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -128,8 +128,7 @@ impl EventCache {
128128
let inner = Arc::new(EventCacheInner {
129129
client: Arc::downgrade(client),
130130
by_room: Default::default(),
131-
store,
132-
process_lock: Default::default(),
131+
store: Arc::new(Mutex::new(store)),
133132
drop_handles: Default::default(),
134133
});
135134

@@ -181,9 +180,10 @@ impl EventCache {
181180
// Forget everything we know; we could have missed events, and we have
182181
// no way to reconcile at the moment!
183182
// TODO: implement Smart Matching™,
183+
let store = inner.store.lock().await;
184184
let mut by_room = inner.by_room.write().await;
185185
for room_id in by_room.keys() {
186-
if let Err(err) = inner.store.clear_room_events(room_id).await {
186+
if let Err(err) = store.clear_room_events(room_id).await {
187187
error!("unable to clear room after room updates lag: {err}");
188188
}
189189
}
@@ -230,10 +230,12 @@ impl EventCache {
230230
// We could have received events during a previous sync; remove them all, since
231231
// we can't know where to insert the "initial events" with respect to
232232
// them.
233-
self.inner.store.clear_room_events(room_id).await?;
233+
let store = self.inner.store.lock().await;
234+
235+
store.clear_room_events(room_id).await?;
234236
let _ = room_cache.inner.sender.send(RoomEventCacheUpdate::Clear);
235237

236-
room_cache.inner.append_events(events).await?;
238+
room_cache.inner.append_events(&**store, events).await?;
237239

238240
Ok(())
239241
}
@@ -248,14 +250,13 @@ struct EventCacheInner {
248250
by_room: RwLock<BTreeMap<OwnedRoomId, RoomEventCache>>,
249251

250252
/// Backend used for storage.
251-
store: Arc<dyn EventCacheStore>,
252-
253-
/// A lock to make sure that despite multiple updates coming to the
254-
/// `EventCache`, it will only handle one at a time.
255253
///
256254
/// [`Mutex`] is “fair”, as it is implemented as a FIFO. It is important to
257-
/// ensure that multiple updates will be applied in the correct order.
258-
process_lock: Mutex<()>,
255+
/// ensure that multiple updates will be applied in the correct order, which
256+
/// is enforced by taking the store lock when handling an update.
257+
///
258+
/// TODO: replace with a cross-process lock
259+
store: Arc<Mutex<Arc<dyn EventCacheStore>>>,
259260

260261
/// Handles to keep alive the task listening to updates.
261262
drop_handles: OnceLock<Arc<EventCacheDropHandles>>,
@@ -271,7 +272,7 @@ impl EventCacheInner {
271272
async fn handle_room_updates(&self, updates: RoomUpdates) -> Result<()> {
272273
// First, take the lock that indicates we're processing updates, to avoid
273274
// handling multiple updates concurrently.
274-
let _process_lock = self.process_lock.lock().await;
275+
let store = self.store.lock().await;
275276

276277
// Left rooms.
277278
for (room_id, left_room_update) in updates.leave {
@@ -280,7 +281,7 @@ impl EventCacheInner {
280281
continue;
281282
};
282283

283-
if let Err(err) = room.inner.handle_left_room_update(left_room_update).await {
284+
if let Err(err) = room.inner.handle_left_room_update(&**store, left_room_update).await {
284285
// Non-fatal error, try to continue to the next room.
285286
error!("handling left room update: {err}");
286287
}
@@ -293,7 +294,9 @@ impl EventCacheInner {
293294
continue;
294295
};
295296

296-
if let Err(err) = room.inner.handle_joined_room_update(joined_room_update).await {
297+
if let Err(err) =
298+
room.inner.handle_joined_room_update(&**store, joined_room_update).await
299+
{
297300
// Non-fatal error, try to continue to the next room.
298301
error!("handling joined room update: {err}");
299302
}
@@ -358,7 +361,7 @@ impl Debug for RoomEventCache {
358361

359362
impl RoomEventCache {
360363
/// Create a new [`RoomEventCache`] using the given room and store.
361-
fn new(room: Room, store: Arc<dyn EventCacheStore>) -> Self {
364+
fn new(room: Room, store: Arc<Mutex<Arc<dyn EventCacheStore>>>) -> Self {
362365
Self { inner: Arc::new(RoomEventCacheInner::new(room, store)) }
363366
}
364367

@@ -369,10 +372,9 @@ impl RoomEventCache {
369372
pub async fn subscribe(
370373
&self,
371374
) -> Result<(Vec<SyncTimelineEvent>, Receiver<RoomEventCacheUpdate>)> {
372-
Ok((
373-
self.inner.store.room_events(self.inner.room.room_id()).await?,
374-
self.inner.sender.subscribe(),
375-
))
375+
let store = self.inner.store.lock().await;
376+
377+
Ok((store.room_events(self.inner.room.room_id()).await?, self.inner.sender.subscribe()))
376378
}
377379
}
378380

@@ -381,8 +383,10 @@ struct RoomEventCacheInner {
381383
/// Sender part for subscribers to this room.
382384
sender: Sender<RoomEventCacheUpdate>,
383385

384-
/// A pointer to the store implementation used for this event cache.
385-
store: Arc<dyn EventCacheStore>,
386+
/// Backend used for storage, shared with the parent [`EventCacheInner`].
387+
///
388+
/// See comment there.
389+
store: Arc<Mutex<Arc<dyn EventCacheStore>>>,
386390

387391
/// The Client [`Room`] this event cache pertains to.
388392
room: Room,
@@ -391,13 +395,18 @@ struct RoomEventCacheInner {
391395
impl RoomEventCacheInner {
392396
/// Creates a new cache for a room, and subscribes to room updates, so as
393397
/// to handle new timeline events.
394-
fn new(room: Room, store: Arc<dyn EventCacheStore>) -> Self {
398+
fn new(room: Room, store: Arc<Mutex<Arc<dyn EventCacheStore>>>) -> Self {
395399
let sender = Sender::new(32);
396400
Self { room, store, sender }
397401
}
398402

399-
async fn handle_joined_room_update(&self, updates: JoinedRoomUpdate) -> Result<()> {
403+
async fn handle_joined_room_update(
404+
&self,
405+
store: &dyn EventCacheStore,
406+
updates: JoinedRoomUpdate,
407+
) -> Result<()> {
400408
self.handle_timeline(
409+
store,
401410
updates.timeline,
402411
updates.ephemeral.clone(),
403412
updates.account_data,
@@ -409,6 +418,7 @@ impl RoomEventCacheInner {
409418

410419
async fn handle_timeline(
411420
&self,
421+
store: &dyn EventCacheStore,
412422
timeline: Timeline,
413423
ephemeral: Vec<Raw<AnySyncEphemeralRoomEvent>>,
414424
account_data: Vec<Raw<AnyRoomAccountDataEvent>>,
@@ -419,7 +429,7 @@ impl RoomEventCacheInner {
419429
// timeline, but we're not there yet. In the meanwhile, clear the
420430
// items from the room. TODO: implement Smart Matching™.
421431
trace!("limited timeline, clearing all previous events");
422-
self.store.clear_room_events(self.room.room_id()).await?;
432+
store.clear_room_events(self.room.room_id()).await?;
423433
let _ = self.sender.send(RoomEventCacheUpdate::Clear);
424434
}
425435

@@ -431,7 +441,7 @@ impl RoomEventCacheInner {
431441
|| !ambiguity_changes.is_empty()
432442
{
433443
trace!("adding new events");
434-
self.store.add_room_events(self.room.room_id(), timeline.events.clone()).await?;
444+
store.add_room_events(self.room.room_id(), timeline.events.clone()).await?;
435445

436446
// Propagate events to observers.
437447
let _ = self.sender.send(RoomEventCacheUpdate::Append {
@@ -446,20 +456,34 @@ impl RoomEventCacheInner {
446456
Ok(())
447457
}
448458

449-
async fn handle_left_room_update(&self, updates: LeftRoomUpdate) -> Result<()> {
450-
self.handle_timeline(updates.timeline, Vec::new(), Vec::new(), updates.ambiguity_changes)
451-
.await?;
459+
async fn handle_left_room_update(
460+
&self,
461+
store: &dyn EventCacheStore,
462+
updates: LeftRoomUpdate,
463+
) -> Result<()> {
464+
self.handle_timeline(
465+
store,
466+
updates.timeline,
467+
Vec::new(),
468+
Vec::new(),
469+
updates.ambiguity_changes,
470+
)
471+
.await?;
452472
Ok(())
453473
}
454474

455475
/// Append a set of events to the room cache and storage, notifying
456476
/// observers.
457-
async fn append_events(&self, events: Vec<SyncTimelineEvent>) -> Result<()> {
477+
async fn append_events(
478+
&self,
479+
store: &dyn EventCacheStore,
480+
events: Vec<SyncTimelineEvent>,
481+
) -> Result<()> {
458482
if events.is_empty() {
459483
return Ok(());
460484
}
461485

462-
self.store.add_room_events(self.room.room_id(), events.clone()).await?;
486+
store.add_room_events(self.room.room_id(), events.clone()).await?;
463487

464488
let _ = self.sender.send(RoomEventCacheUpdate::Append {
465489
events,

0 commit comments

Comments
 (0)