@@ -128,8 +128,7 @@ impl EventCache {
128
128
let inner = Arc :: new ( EventCacheInner {
129
129
client : Arc :: downgrade ( client) ,
130
130
by_room : Default :: default ( ) ,
131
- store,
132
- process_lock : Default :: default ( ) ,
131
+ store : Arc :: new ( Mutex :: new ( store) ) ,
133
132
drop_handles : Default :: default ( ) ,
134
133
} ) ;
135
134
@@ -181,9 +180,10 @@ impl EventCache {
181
180
// Forget everything we know; we could have missed events, and we have
182
181
// no way to reconcile at the moment!
183
182
// TODO: implement Smart Matching™,
183
+ let store = inner. store . lock ( ) . await ;
184
184
let mut by_room = inner. by_room . write ( ) . await ;
185
185
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 {
187
187
error ! ( "unable to clear room after room updates lag: {err}" ) ;
188
188
}
189
189
}
@@ -230,10 +230,12 @@ impl EventCache {
230
230
// We could have received events during a previous sync; remove them all, since
231
231
// we can't know where to insert the "initial events" with respect to
232
232
// 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 ?;
234
236
let _ = room_cache. inner . sender . send ( RoomEventCacheUpdate :: Clear ) ;
235
237
236
- room_cache. inner . append_events ( events) . await ?;
238
+ room_cache. inner . append_events ( & * * store , events) . await ?;
237
239
238
240
Ok ( ( ) )
239
241
}
@@ -248,14 +250,13 @@ struct EventCacheInner {
248
250
by_room : RwLock < BTreeMap < OwnedRoomId , RoomEventCache > > ,
249
251
250
252
/// 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.
255
253
///
256
254
/// [`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 > > > ,
259
260
260
261
/// Handles to keep alive the task listening to updates.
261
262
drop_handles : OnceLock < Arc < EventCacheDropHandles > > ,
@@ -271,7 +272,7 @@ impl EventCacheInner {
271
272
async fn handle_room_updates ( & self , updates : RoomUpdates ) -> Result < ( ) > {
272
273
// First, take the lock that indicates we're processing updates, to avoid
273
274
// handling multiple updates concurrently.
274
- let _process_lock = self . process_lock . lock ( ) . await ;
275
+ let store = self . store . lock ( ) . await ;
275
276
276
277
// Left rooms.
277
278
for ( room_id, left_room_update) in updates. leave {
@@ -280,7 +281,7 @@ impl EventCacheInner {
280
281
continue ;
281
282
} ;
282
283
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 {
284
285
// Non-fatal error, try to continue to the next room.
285
286
error ! ( "handling left room update: {err}" ) ;
286
287
}
@@ -293,7 +294,9 @@ impl EventCacheInner {
293
294
continue ;
294
295
} ;
295
296
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
+ {
297
300
// Non-fatal error, try to continue to the next room.
298
301
error ! ( "handling joined room update: {err}" ) ;
299
302
}
@@ -358,7 +361,7 @@ impl Debug for RoomEventCache {
358
361
359
362
impl RoomEventCache {
360
363
/// 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 {
362
365
Self { inner : Arc :: new ( RoomEventCacheInner :: new ( room, store) ) }
363
366
}
364
367
@@ -369,10 +372,9 @@ impl RoomEventCache {
369
372
pub async fn subscribe (
370
373
& self ,
371
374
) -> 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 ( ) ) )
376
378
}
377
379
}
378
380
@@ -381,8 +383,10 @@ struct RoomEventCacheInner {
381
383
/// Sender part for subscribers to this room.
382
384
sender : Sender < RoomEventCacheUpdate > ,
383
385
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 > > > ,
386
390
387
391
/// The Client [`Room`] this event cache pertains to.
388
392
room : Room ,
@@ -391,13 +395,18 @@ struct RoomEventCacheInner {
391
395
impl RoomEventCacheInner {
392
396
/// Creates a new cache for a room, and subscribes to room updates, so as
393
397
/// 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 {
395
399
let sender = Sender :: new ( 32 ) ;
396
400
Self { room, store, sender }
397
401
}
398
402
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 < ( ) > {
400
408
self . handle_timeline (
409
+ store,
401
410
updates. timeline ,
402
411
updates. ephemeral . clone ( ) ,
403
412
updates. account_data ,
@@ -409,6 +418,7 @@ impl RoomEventCacheInner {
409
418
410
419
async fn handle_timeline (
411
420
& self ,
421
+ store : & dyn EventCacheStore ,
412
422
timeline : Timeline ,
413
423
ephemeral : Vec < Raw < AnySyncEphemeralRoomEvent > > ,
414
424
account_data : Vec < Raw < AnyRoomAccountDataEvent > > ,
@@ -419,7 +429,7 @@ impl RoomEventCacheInner {
419
429
// timeline, but we're not there yet. In the meanwhile, clear the
420
430
// items from the room. TODO: implement Smart Matching™.
421
431
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 ?;
423
433
let _ = self . sender . send ( RoomEventCacheUpdate :: Clear ) ;
424
434
}
425
435
@@ -431,7 +441,7 @@ impl RoomEventCacheInner {
431
441
|| !ambiguity_changes. is_empty ( )
432
442
{
433
443
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 ?;
435
445
436
446
// Propagate events to observers.
437
447
let _ = self . sender . send ( RoomEventCacheUpdate :: Append {
@@ -446,20 +456,34 @@ impl RoomEventCacheInner {
446
456
Ok ( ( ) )
447
457
}
448
458
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 ?;
452
472
Ok ( ( ) )
453
473
}
454
474
455
475
/// Append a set of events to the room cache and storage, notifying
456
476
/// 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 < ( ) > {
458
482
if events. is_empty ( ) {
459
483
return Ok ( ( ) ) ;
460
484
}
461
485
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 ?;
463
487
464
488
let _ = self . sender . send ( RoomEventCacheUpdate :: Append {
465
489
events,
0 commit comments