Commit f82c4ac42cb4
tarball2 files changed+34-2
@@ -13,6 +13,7 @@
1313
// limitations under the License.1414
1515
use std::{16
+ future::Future,1617
sync::{Arc, atomic::AtomicU64},1718
time::Duration,1819
};@@ -79,6 +80,29 @@ pub(super) async fn save_events(
7980
}8081
}8182
83
+/// How long a store read may go unanswered before it is asked again.84
+const STORE_READ_RETRY: Duration = Duration::from_secs(5);85
+86
+/// Run a store read, and ask once more if the first one never answers.87
+///88
+/// On wasm an IndexedDB read during cache creation has been seen to stay pending with no89
+/// transaction left open, wedging every room behind it. The logs say whether a fresh read90
+/// goes through, which tells a lost wakeup from a task that is never polled again.91
+pub(super) async fn read_store<T, F>(what: &'static str, read: impl Fn() -> F) -> T92
+where93
+ F: Future<Output = T>,94
+{95
+ match timeout(read(), STORE_READ_RETRY).await {96
+ Ok(answer) => answer,97
+ Err(_) => {98
+ warn!(what, "a store read went unanswered, asking again");99
+ let answer = read().await;100
+ warn!(what, "the repeated store read answered");101
+ answer102
+ }103
+ }104
+}105
+82106
/// A type to hold all the caches for a given room.83107
#[derive(Debug)]84108
pub(super) struct Caches {@@ -345,7 +345,11 @@ impl LockedRoomEventCacheState {
345345
// indicates that at some point, there's some malformed data.346346
// a storage error can be transient (an IndexedDB transaction aborted under us), and the347347
// clear below throws away the room's whole history, so read once more before trusting it348
- let metadata = match load_linked_chunk_metadata(&store_guard, linked_chunk_id).await {348
+ let metadata = match super::super::read_store("linked chunk metadata", || {349
+ load_linked_chunk_metadata(&store_guard, linked_chunk_id)350
+ })351
+ .await352
+ {349353
Err(EventCacheError::Storage(err)) => {350354
warn!("retrying a linked chunk's metadata after a storage error: {err}");351355
load_linked_chunk_metadata(&store_guard, linked_chunk_id).await@@ -367,7 +371,11 @@ impl LockedRoomEventCacheState {
367371
}368372
};369373
370
- let last_chunk = match store_guard.load_last_chunk(linked_chunk_id).await {374
+ let last_chunk = match super::super::read_store("latest chunk", || {375
+ store_guard.load_last_chunk(linked_chunk_id)376
+ })377
+ .await378
+ {371379
Err(err) => {372380
warn!("retrying a linked chunk's latest chunk after a storage error: {err}");373381
store_guard.load_last_chunk(linked_chunk_id).await