@@ -612,7 +612,10 @@ mod private {
612612 deserialized_responses:: { ThreadSummary , ThreadSummaryStatus , TimelineEventKind } ,
613613 event_cache:: {
614614 Event , Gap ,
615- store:: { DynEventCacheStore , EventCacheStoreLock } ,
615+ store:: {
616+ DynEventCacheStore , EventCacheStoreLock , EventCacheStoreLockGuard ,
617+ EventCacheStoreLockState ,
618+ } ,
616619 } ,
617620 linked_chunk:: {
618621 ChunkContent , ChunkIdentifierGenerator , ChunkMetadata , LinkedChunkId ,
@@ -707,7 +710,19 @@ mod private {
707710 store : EventCacheStoreLock ,
708711 pagination_status : SharedObservable < RoomPaginationStatus > ,
709712 ) -> Result < Self , EventCacheError > {
710- let store_lock = store. lock ( ) . await ?;
713+ let store_guard = match store. lock ( ) . await ? {
714+ // The lock is clean: all good.
715+ EventCacheStoreLockState :: Clean ( guard) => guard,
716+
717+ // The lock is dirty: that's not a problem here! Why? Because we are creating the
718+ // state, so it's necessarily new, which means we don't need to refresh it. We must
719+ // clear the dirtiness though.
720+ EventCacheStoreLockState :: Dirty ( guard) => {
721+ EventCacheStoreLockGuard :: clear_dirty ( & guard) ;
722+
723+ guard
724+ }
725+ } ;
711726
712727 let linked_chunk_id = LinkedChunkId :: Room ( & room_id) ;
713728
@@ -716,15 +731,15 @@ mod private {
716731 // If loading the full linked chunk failed, we'll clear the event cache, as it
717732 // indicates that at some point, there's some malformed data.
718733 let full_linked_chunk_metadata =
719- match Self :: load_linked_chunk_metadata ( & * store_lock , linked_chunk_id) . await {
734+ match Self :: load_linked_chunk_metadata ( & * store_guard , linked_chunk_id) . await {
720735 Ok ( metas) => metas,
721736 Err ( err) => {
722737 error ! (
723738 "error when loading a linked chunk's metadata from the store: {err}"
724739 ) ;
725740
726741 // Try to clear storage for this room.
727- store_lock
742+ store_guard
728743 . handle_linked_chunk_updates ( linked_chunk_id, vec ! [ Update :: Clear ] )
729744 . await ?;
730745
@@ -733,7 +748,7 @@ mod private {
733748 }
734749 } ;
735750
736- let linked_chunk = match store_lock
751+ let linked_chunk = match store_guard
737752 . load_last_chunk ( linked_chunk_id)
738753 . await
739754 . map_err ( EventCacheError :: from)
@@ -748,7 +763,7 @@ mod private {
748763 ) ;
749764
750765 // Try to clear storage for this room.
751- store_lock
766+ store_guard
752767 . handle_linked_chunk_updates ( linked_chunk_id, vec ! [ Update :: Clear ] )
753768 . await ?;
754769
@@ -910,20 +925,32 @@ mod private {
910925 pub ( in super :: super ) async fn load_more_events_backwards (
911926 & mut self ,
912927 ) -> Result < LoadMoreEventsBackwardsOutcome , EventCacheError > {
928+ let store_guard = match self . store . lock ( ) . await ? {
929+ // The lock is clean: we don't need to refresh the in-memory state.
930+ EventCacheStoreLockState :: Clean ( guard) => guard,
931+
932+ // The lock is dirty: we need to refresh the in-memory state before working with it.
933+ EventCacheStoreLockState :: Dirty ( guard) => {
934+ EventCacheStoreLockGuard :: clear_dirty ( & guard) ;
935+
936+ self . shrink_to_last_chunk_with_store_guard ( & guard) . await ?;
937+
938+ guard
939+ }
940+ } ;
941+
913942 // If any in-memory chunk is a gap, don't load more events, and let the caller
914943 // resolve the gap.
915944 if let Some ( prev_token) = self . room_linked_chunk . rgap ( ) . map ( |gap| gap. prev_token ) {
916945 return Ok ( LoadMoreEventsBackwardsOutcome :: Gap { prev_token : Some ( prev_token) } ) ;
917946 }
918947
919- let store = self . store . lock ( ) . await ?;
920-
921948 let prev_first_chunk =
922949 self . room_linked_chunk . chunks ( ) . next ( ) . expect ( "a linked chunk is never empty" ) ;
923950
924951 // The first chunk is not a gap, we can load its previous chunk.
925952 let linked_chunk_id = LinkedChunkId :: Room ( & self . room ) ;
926- let new_first_chunk = match store
953+ let new_first_chunk = match store_guard
927954 . load_previous_chunk ( linked_chunk_id, prev_first_chunk. identifier ( ) )
928955 . await
929956 {
@@ -952,7 +979,9 @@ mod private {
952979 error ! ( "error when loading the previous chunk of a linked chunk: {err}" ) ;
953980
954981 // Clear storage for this room.
955- store. handle_linked_chunk_updates ( linked_chunk_id, vec ! [ Update :: Clear ] ) . await ?;
982+ store_guard
983+ . handle_linked_chunk_updates ( linked_chunk_id, vec ! [ Update :: Clear ] )
984+ . await ?;
956985
957986 // Return the error.
958987 return Err ( err. into ( ) ) ;
@@ -972,7 +1001,9 @@ mod private {
9721001 error ! ( "error when inserting the previous chunk into its linked chunk: {err}" ) ;
9731002
9741003 // Clear storage for this room.
975- store. handle_linked_chunk_updates ( linked_chunk_id, vec ! [ Update :: Clear ] ) . await ?;
1004+ store_guard
1005+ . handle_linked_chunk_updates ( linked_chunk_id, vec ! [ Update :: Clear ] )
1006+ . await ?;
9761007
9771008 // Return the error.
9781009 return Err ( err. into ( ) ) ;
@@ -1011,8 +1042,27 @@ mod private {
10111042 ///
10121043 /// Otherwise, returns `None`.
10131044 pub ( super ) async fn shrink_to_last_chunk ( & mut self ) -> Result < ( ) , EventCacheError > {
1014- let store_lock = self . store . lock ( ) . await ?;
1045+ let store_guard = match self . store . lock ( ) . await ? {
1046+ // The lock is clean: all good!
1047+ EventCacheStoreLockState :: Clean ( guard) => guard,
1048+
1049+ // The lock is dirty. We need to refresh the in-memory state. Fortunately for us,
1050+ // that's exactly what this current method does. Let's clear the dirtiness, and
1051+ // let's keep going.
1052+ EventCacheStoreLockState :: Dirty ( guard) => {
1053+ EventCacheStoreLockGuard :: clear_dirty ( & guard) ;
1054+
1055+ guard
1056+ }
1057+ } ;
1058+
1059+ self . shrink_to_last_chunk_with_store_guard ( & store_guard) . await
1060+ }
10151061
1062+ async fn shrink_to_last_chunk_with_store_guard (
1063+ & mut self ,
1064+ store_lock : & EventCacheStoreLockGuard ,
1065+ ) -> Result < ( ) , EventCacheError > {
10161066 // Attempt to load the last chunk.
10171067 let linked_chunk_id = LinkedChunkId :: Room ( & self . room ) ;
10181068 let ( last_chunk, chunk_identifier_generator) =
@@ -1081,6 +1131,7 @@ mod private {
10811131 & mut self ,
10821132 ) -> Result < Vec < VectorDiff < Event > > , EventCacheError > {
10831133 self . shrink_to_last_chunk ( ) . await ?;
1134+
10841135 Ok ( self . room_linked_chunk . updates_as_vector_diffs ( ) )
10851136 }
10861137
0 commit comments