Commit a88b3d82b396
tarball2 files changed+59-35
@@ -184,11 +184,16 @@ impl PaginatedCache for Arc<RoomEventCacheInner> {
184184
185185
// The first chunk is not a gap, we can load its previous chunk.186186
let linked_chunk_id = LinkedChunkId::Room(&state.state.room_id);187
- let new_first_chunk = match state188
- .store189
- .load_previous_chunk(linked_chunk_id, prev_first_chunk.identifier())190
- .await191
- {187
+ let first_chunk = prev_first_chunk.identifier();188
+ let loaded = match state.store.load_previous_chunk(linked_chunk_id, first_chunk).await {189
+ // a failed read resets the room, so a transient IndexedDB error gets a second read190
+ Err(err) => {191
+ tracing::warn!("retrying the previous chunk after a storage error: {err}");192
+ state.store.load_previous_chunk(linked_chunk_id, first_chunk).await193
+ }194
+ loaded => loaded,195
+ };196
+ let new_first_chunk = match loaded {192197
Ok(Some(new_first_chunk)) => {193198
// All good, let's continue with this chunk.194199
new_first_chunk@@ -333,30 +333,43 @@ impl LockedRoomEventCacheState {
333333
//334334
// If loading the full linked chunk failed, we'll clear the event cache, as it335335
// indicates that at some point, there's some malformed data.336
- let full_linked_chunk_metadata =337
- match load_linked_chunk_metadata(&store_guard, linked_chunk_id).await {338
- Ok(metas) => metas,339
- Err(err) => {340
- error!("error when loading a linked chunk's metadata from the store: {err}");341
-342
- // Try to clear storage for this room.343
- store_guard344
- .handle_linked_chunk_updates(linked_chunk_id, vec![Update::Clear])345
- .await?;346
-347
- // Restart with an empty linked chunk.348
- None349
- }350
- };336
+ // a storage error can be transient (an IndexedDB transaction aborted under us), and the337
+ // clear below throws away the room's whole history, so read once more before trusting it338
+ let metadata = match load_linked_chunk_metadata(&store_guard, linked_chunk_id).await {339
+ Err(EventCacheError::Storage(err)) => {340
+ warn!("retrying a linked chunk's metadata after a storage error: {err}");341
+ load_linked_chunk_metadata(&store_guard, linked_chunk_id).await342
+ }343
+ other => other,344
+ };345
+ let full_linked_chunk_metadata = match metadata {346
+ Ok(metas) => metas,347
+ Err(err) => {348
+ error!("error when loading a linked chunk's metadata from the store: {err}");349
+350
+ // Try to clear storage for this room.351
+ store_guard352
+ .handle_linked_chunk_updates(linked_chunk_id, vec![Update::Clear])353
+ .await?;354
+355
+ // Restart with an empty linked chunk.356
+ None357
+ }358
+ };351359
352
- let linked_chunk = match store_guard353
- .load_last_chunk(linked_chunk_id)354
- .await355
- .map_err(EventCacheError::from)356
- .and_then(|(last_chunk, chunk_identifier_generator)| {360
+ let last_chunk = match store_guard.load_last_chunk(linked_chunk_id).await {361
+ Err(err) => {362
+ warn!("retrying a linked chunk's latest chunk after a storage error: {err}");363
+ store_guard.load_last_chunk(linked_chunk_id).await364
+ }365
+ loaded => loaded,366
+ };367
+ let linked_chunk = match last_chunk.map_err(EventCacheError::from).and_then(368
+ |(last_chunk, chunk_identifier_generator)| {357369
lazy_loader::from_last_chunk(last_chunk, chunk_identifier_generator)358370
.map_err(EventCacheError::from)359
- }) {371
+ },372
+ ) {360373
Ok(linked_chunk) => linked_chunk,361374
Err(err) => {362375
error!("error when loading a linked chunk's latest chunk from the store: {err}");@@ -622,17 +635,23 @@ impl<'a> RoomEventCacheStateLockWriteGuard<'a> {
622635
pub async fn shrink_to_last_chunk(&mut self) -> Result<(), EventCacheError> {623636
// Attempt to load the last chunk.624637
let linked_chunk_id = LinkedChunkId::Room(&self.state.room_id);625
- let (last_chunk, chunk_identifier_generator) =626
- match self.store.load_last_chunk(linked_chunk_id).await {627
- Ok(pair) => pair,638
+ let loaded = match self.store.load_last_chunk(linked_chunk_id).await {639
+ Err(err) => {640
+ warn!("retrying a linked chunk's latest chunk after a storage error: {err}");641
+ self.store.load_last_chunk(linked_chunk_id).await642
+ }643
+ loaded => loaded,644
+ };645
+ let (last_chunk, chunk_identifier_generator) = match loaded {646
+ Ok(pair) => pair,628647
629
- Err(err) => {630
- // If loading the last chunk failed, clear the entire linked chunk.631
- error!("error when reloading a linked chunk from memory: {err}");648
+ Err(err) => {649
+ // If loading the last chunk failed, clear the entire linked chunk.650
+ error!("error when reloading a linked chunk from memory: {err}");632651
633
- return self.reset_internal().await;634
- }635
- };652
+ return self.reset_internal().await;653
+ }654
+ };636655
637656
debug!("unloading the linked chunk, and resetting it to its last chunk");