Skip to content

Commit aaf9270

Browse files
authored
Merge pull request #699 from nextcloud/bugfix/noid/reduce-db-access-when-updating-storagemapping
fix: avoid too many concurrent db queries when cache becomes invalid
2 parents 1c9f096 + 4c56666 commit aaf9270

1 file changed

Lines changed: 27 additions & 7 deletions

File tree

src/storage_mapping.rs

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ use log::debug;
1313
use rand::{thread_rng, Rng};
1414
use sqlx::any::AnyConnectOptions;
1515
use sqlx::{query_as, Any, AnyPool, FromRow};
16+
use std::sync::atomic::{AtomicBool, Ordering};
1617
use std::time::Instant;
1718
use tokio::time::Duration;
1819

@@ -27,6 +28,7 @@ pub struct UserStorageAccess {
2728
struct CachedAccess {
2829
access: Vec<UserStorageAccess>,
2930
valid_till: Instant,
31+
updating: AtomicBool,
3032
}
3133

3234
impl CachedAccess {
@@ -36,11 +38,16 @@ impl CachedAccess {
3638
access,
3739
valid_till: Instant::now()
3840
+ Duration::from_millis(rng.gen_range((4 * 60 * 1000)..(5 * 60 * 1000))),
41+
updating: AtomicBool::new(false),
3942
}
4043
}
4144

4245
pub fn is_valid(&self) -> bool {
43-
self.valid_till > Instant::now()
46+
self.valid_till > Instant::now() || self.updating.load(Ordering::SeqCst)
47+
}
48+
49+
pub fn prepare_update(&self, value: bool) {
50+
self.updating.store(value, Ordering::SeqCst);
4451
}
4552
}
4653

@@ -71,14 +78,27 @@ impl StorageMapping {
7178
&self,
7279
storage: u32,
7380
) -> Result<Ref<'_, u32, CachedAccess>, DatabaseError> {
74-
if let Some(cached) = self.cache.get(&storage).filter(|cached| cached.is_valid()) {
75-
Ok(cached)
76-
} else {
77-
let users = self.load_storage_mapping(storage).await?;
81+
if let Some(cached) = self.cache.get(&storage) {
82+
if cached.is_valid() {
83+
return Ok(cached);
84+
}
85+
86+
cached.prepare_update(true);
87+
let users = self
88+
.load_storage_mapping(storage)
89+
.await
90+
.inspect_err(|_| cached.prepare_update(false))?;
7891

79-
self.cache.insert(storage, CachedAccess::new(users));
80-
Ok(self.cache.get(&storage).unwrap())
92+
drop(cached);
93+
let cached = CachedAccess::new(users);
94+
self.cache.insert(storage, cached);
95+
return Ok(self.cache.get(&storage).unwrap());
8196
}
97+
98+
let users = self.load_storage_mapping(storage).await?;
99+
100+
self.cache.insert(storage, CachedAccess::new(users));
101+
Ok(self.cache.get(&storage).unwrap())
82102
}
83103

84104
pub async fn get_users_for_storage_path(

0 commit comments

Comments
 (0)