@@ -7,7 +7,7 @@ use base64::Engine;
77use hashbrown:: HashMap ;
88use http:: uri:: PathAndQuery ;
99use http:: StatusCode ;
10- use libdd_capabilities:: HttpClientCapability ;
10+ use libdd_capabilities:: { HttpClientCapability , SleepCapability } ;
1111use libdd_common:: { Endpoint , MutexExt } ;
1212use libdd_trace_protobuf:: remoteconfig:: {
1313 ClientGetConfigsRequest , ClientGetConfigsResponse , ClientState , ClientTracer , ConfigState ,
@@ -104,7 +104,7 @@ impl ConfigProductCapabilities {
104104 }
105105}
106106
107- pub struct ConfigFetcherState < S , C : HttpClientCapability > {
107+ pub struct ConfigFetcherState < S , C : HttpClientCapability + SleepCapability > {
108108 target_files_by_path : Mutex < HashMap < Arc < RemoteConfigPath > , StoredTargetFile < S > > > ,
109109 pub invariants : ConfigInvariants ,
110110 endpoint : Endpoint ,
@@ -153,7 +153,7 @@ impl<S> ConfigFetcherFilesLock<'_, S> {
153153 }
154154}
155155
156- impl < S , C : HttpClientCapability > ConfigFetcherState < S , C > {
156+ impl < S , C : HttpClientCapability + SleepCapability > ConfigFetcherState < S , C > {
157157 pub fn with_client ( invariants : ConfigInvariants , http_client : C ) -> Self {
158158 ConfigFetcherState {
159159 target_files_by_path : Default :: default ( ) ,
@@ -203,7 +203,7 @@ impl<S, C: HttpClientCapability> ConfigFetcherState<S, C> {
203203 }
204204}
205205
206- pub struct ConfigFetcher < S : FileStorage , C : HttpClientCapability > {
206+ pub struct ConfigFetcher < S : FileStorage , C : HttpClientCapability + SleepCapability > {
207207 pub file_storage : S ,
208208 state : Arc < ConfigFetcherState < S :: StoredFile , C > > ,
209209}
@@ -238,7 +238,7 @@ impl ConfigClientState {
238238 }
239239}
240240
241- impl < S : FileStorage , C : HttpClientCapability > ConfigFetcher < S , C > {
241+ impl < S : FileStorage , C : HttpClientCapability + SleepCapability > ConfigFetcher < S , C > {
242242 pub fn new ( file_storage : S , state : Arc < ConfigFetcherState < S :: StoredFile , C > > ) -> Self {
243243 ConfigFetcher {
244244 file_storage,
@@ -364,19 +364,31 @@ impl<S: FileStorage, C: HttpClientCapability> ConfigFetcher<S, C> {
364364 libdd_common:: header:: APPLICATION_JSON ,
365365 )
366366 . body ( bytes:: Bytes :: from ( serde_json:: to_string ( & config_req) ?) ) ?;
367- let response = tokio:: time:: timeout (
368- Duration :: from_millis ( self . state . endpoint . timeout_ms ) ,
369- self . state . http_client . request ( req) ,
370- )
371- . await
372- . map_err ( |e| anyhow:: Error :: msg ( e) . context ( format ! ( "Url: {:?}" , self . state. endpoint) ) ) ?
373- . map_err ( |e| anyhow:: Error :: msg ( e) . context ( format ! ( "Url: {:?}" , self . state. endpoint) ) ) ?;
367+ let sleeper = <C as SleepCapability >:: new ( ) ;
368+ let response = tokio:: select! {
369+ biased;
370+ result = self . state. http_client. request( req) => result
371+ . map_err( |e| anyhow:: Error :: msg( e) . context( format!( "Url: {:?}" , self . state. endpoint) ) ) ?,
372+ _ = sleeper. sleep( Duration :: from_millis( self . state. endpoint. timeout_ms) ) => {
373+ anyhow:: bail!(
374+ "Remote config request timed out after {}ms. Url: {:?}" ,
375+ self . state. endpoint. timeout_ms,
376+ self . state. endpoint
377+ )
378+ }
379+ } ;
374380 let status = response. status ( ) ;
375381 let body_bytes = response. into_body ( ) ;
376382 if status != StatusCode :: OK {
377383 // Not active
378384 if status == StatusCode :: NOT_FOUND {
379385 trace ! ( "Requested remote config and but remote config not active" ) ;
386+ if self . state . expire_unused_files {
387+ self . state . target_files_by_path . lock_or_panic ( ) . clear ( ) ;
388+ }
389+ client_state. last_config_paths . clear ( ) ;
390+ client_state. targets_version = 0 ;
391+ client_state. opaque_backend_state . clear ( ) ;
380392 return Ok ( Some ( vec ! [ ] ) ) ;
381393 }
382394
@@ -592,7 +604,7 @@ pub mod tests {
592604 use crate :: fetch:: test_server:: RemoteConfigServer ;
593605 use crate :: RemoteConfigSource ;
594606 use http:: Response ;
595- use libdd_capabilities_impl:: NativeHttpClient ;
607+ use libdd_capabilities_impl:: NativeCapabilities ;
596608 use libdd_common:: http_common;
597609 use std:: mem:: transmute;
598610 use std:: sync:: LazyLock ;
@@ -708,7 +720,7 @@ pub mod tests {
708720 storage. clone ( ) ,
709721 Arc :: new ( ConfigFetcherState :: with_client (
710722 server. dummy_options ( ) . invariants ,
711- NativeHttpClient :: new_without_connection_pooling ( ) ,
723+ NativeCapabilities :: new_without_connection_pooling ( ) ,
712724 ) ) ,
713725 ) ;
714726 let mut opaque_state = ConfigClientState :: default ( ) ;
@@ -746,7 +758,7 @@ pub mod tests {
746758 storage. clone ( ) ,
747759 Arc :: new ( ConfigFetcherState :: with_client (
748760 server. dummy_options ( ) . invariants ,
749- NativeHttpClient :: new_without_connection_pooling ( ) ,
761+ NativeCapabilities :: new_without_connection_pooling ( ) ,
750762 ) ) ,
751763 ) ;
752764 let mut opaque_state = ConfigClientState :: default ( ) ;
@@ -863,7 +875,7 @@ pub mod tests {
863875 storage. clone ( ) ,
864876 Arc :: new ( ConfigFetcherState :: with_client (
865877 invariants,
866- NativeHttpClient :: new_without_connection_pooling ( ) ,
878+ NativeCapabilities :: new_without_connection_pooling ( ) ,
867879 ) ) ,
868880 ) ;
869881 let mut opaque_state = ConfigClientState :: default ( ) ;
@@ -1050,7 +1062,7 @@ pub mod tests {
10501062 storage,
10511063 Arc :: new ( ConfigFetcherState :: with_client (
10521064 server. dummy_options ( ) . invariants ,
1053- NativeHttpClient :: new_without_connection_pooling ( ) ,
1065+ NativeCapabilities :: new_without_connection_pooling ( ) ,
10541066 ) ) ,
10551067 ) ;
10561068 let mut opaque_state = ConfigClientState :: default ( ) ;
@@ -1151,7 +1163,7 @@ pub mod tests {
11511163 storage,
11521164 Arc :: new ( ConfigFetcherState :: with_client (
11531165 server. dummy_options ( ) . invariants ,
1154- NativeHttpClient :: new_without_connection_pooling ( ) ,
1166+ NativeCapabilities :: new_without_connection_pooling ( ) ,
11551167 ) ) ,
11561168 ) ;
11571169 let mut opaque_state = ConfigClientState :: default ( ) ;
0 commit comments