@@ -135,6 +135,8 @@ impl HostDenyList {
135135 block_time : config. deny_list_block_time ,
136136 never_block : config. deny_list_never_block_hosts . clone ( ) ,
137137 failures : moka:: sync:: Cache :: builder ( )
138+ // If a host hasn't had download failures for an entire `deny_list_time_window`
139+ // we can remove it from the `failures` cache.
138140 . time_to_idle ( config. deny_list_time_window )
139141 . build ( ) ,
140142 blocked_hosts : moka:: sync:: Cache :: builder ( )
@@ -161,12 +163,19 @@ impl HostDenyList {
161163 ///
162164 /// If that puts the host over the threshold, it is added
163165 /// to the blocked servers.
164- fn register_failure ( & self , source_name : & str , host : String ) {
166+ fn register_failure ( & self , source_name : & str , host : String , error : & CacheError ) {
165167 let current_ts = SystemTime :: now ( ) ;
166168
169+ // Sanity check: we don't need to count failures for hosts which are currently blocked.
170+ // This can happen if multiple download requests fail around the same time.
171+ if self . is_blocked ( & host) {
172+ return ;
173+ }
174+
167175 tracing:: trace!(
168176 host = %host,
169177 time = %humantime:: format_rfc3339( current_ts) ,
178+ %error,
170179 "Registering download failure"
171180 ) ;
172181
@@ -205,6 +214,7 @@ impl HostDenyList {
205214 tracing:: info!(
206215 %host,
207216 block_time = %humantime:: format_duration( self . block_time) ,
217+ %error,
208218 "Blocking host due to too many download failures"
209219 ) ;
210220
@@ -386,7 +396,7 @@ impl DownloadService {
386396 if let Some ( ref deny_list) = self . host_deny_list
387397 && source_can_be_blocked
388398 {
389- deny_list. register_failure ( & source_metric_key, host) ;
399+ deny_list. register_failure ( & source_metric_key, host, e ) ;
390400 }
391401 }
392402
@@ -1211,12 +1221,20 @@ mod tests {
12111221 let deny_list = HostDenyList :: from_config ( & config) ;
12121222 let host = String :: from ( "test" ) ;
12131223
1214- deny_list. register_failure ( "test" , host. clone ( ) ) ;
1224+ deny_list. register_failure (
1225+ "test" ,
1226+ host. clone ( ) ,
1227+ & CacheError :: DownloadError ( "Test error" . to_owned ( ) ) ,
1228+ ) ;
12151229
12161230 // shouldn't be blocked after one failure
12171231 assert ! ( !deny_list. is_blocked( & host) ) ;
12181232
1219- deny_list. register_failure ( "test" , host. clone ( ) ) ;
1233+ deny_list. register_failure (
1234+ "test" ,
1235+ host. clone ( ) ,
1236+ & CacheError :: DownloadError ( "Test error" . to_owned ( ) ) ,
1237+ ) ;
12201238
12211239 // should be blocked after two failures
12221240 assert ! ( deny_list. is_blocked( & host) ) ;
@@ -1240,8 +1258,16 @@ mod tests {
12401258 let deny_list = HostDenyList :: from_config ( & config) ;
12411259 let host = String :: from ( "test" ) ;
12421260
1243- deny_list. register_failure ( "test" , host. clone ( ) ) ;
1244- deny_list. register_failure ( "test" , host. clone ( ) ) ;
1261+ deny_list. register_failure (
1262+ "test" ,
1263+ host. clone ( ) ,
1264+ & CacheError :: DownloadError ( "Test error" . to_owned ( ) ) ,
1265+ ) ;
1266+ deny_list. register_failure (
1267+ "test" ,
1268+ host. clone ( ) ,
1269+ & CacheError :: DownloadError ( "Test error" . to_owned ( ) ) ,
1270+ ) ;
12451271
12461272 assert ! ( !deny_list. is_blocked( & host) ) ;
12471273 }
0 commit comments