@@ -13,6 +13,7 @@ use log::debug;
1313use rand:: { thread_rng, Rng } ;
1414use sqlx:: any:: AnyConnectOptions ;
1515use sqlx:: { query_as, Any , AnyPool , FromRow } ;
16+ use std:: sync:: atomic:: { AtomicBool , Ordering } ;
1617use std:: time:: Instant ;
1718use tokio:: time:: Duration ;
1819
@@ -27,6 +28,7 @@ pub struct UserStorageAccess {
2728struct CachedAccess {
2829 access : Vec < UserStorageAccess > ,
2930 valid_till : Instant ,
31+ updating : AtomicBool ,
3032}
3133
3234impl 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