@@ -857,7 +857,20 @@ impl HotTierManager {
857857 ) ;
858858 return Ok ( false ) ;
859859 }
860- sht. available_size -= parquet_file. file_size ;
860+ sht. available_size =
861+ if let Some ( val) = sht. available_size . checked_sub ( parquet_file. file_size ) {
862+ val
863+ } else {
864+ tracing:: error!(
865+ stream = %stream,
866+ tenant = ?tenant_id,
867+ file = %parquet_file. file_path,
868+ file_size = parquet_file. file_size,
869+ available = sht. available_size,
870+ "file_size > sht.available_size, setting available_size to 0 and moving on"
871+ ) ;
872+ 0
873+ } ;
861874 self . put_hot_tier ( stream, & mut sht, tenant_id) . await ?;
862875 info ! (
863876 stream = %stream,
@@ -1113,7 +1126,7 @@ impl HotTierManager {
11131126 path. exists ( )
11141127 }
11151128
1116- ///delete the parquet file from the hot tier directory for the stream
1129+ /// delete entire parquet file minute from the hot tier directory for the stream
11171130 /// loop through all manifests in the hot tier directory for the stream
11181131 /// loop through all parquet files in the manifest
11191132 /// check for the oldest entry to delete if the path exists in hot tier
@@ -1155,61 +1168,86 @@ impl HotTierManager {
11551168 let file = fs:: read ( manifest_file. path ( ) ) . await ?;
11561169 let mut manifest: Manifest = serde_json:: from_slice ( & file) ?;
11571170
1158- manifest. files . sort_by_key ( |file| file. file_path . clone ( ) ) ;
1159- manifest. files . reverse ( ) ;
1160-
1161- ' loop_files: while let Some ( file_to_delete) = manifest. files . pop ( ) {
1162- let file_size = file_to_delete. file_size ;
1163- let path_to_delete = self . hot_tier_path . join ( & file_to_delete. file_path ) ;
1164-
1165- if path_to_delete. exists ( ) {
1166- if let ( Some ( download_date_time) , Some ( delete_date_time) ) = (
1167- extract_datetime ( download_file_path. to_str ( ) . unwrap ( ) ) ,
1168- extract_datetime ( path_to_delete. to_str ( ) . unwrap ( ) ) ,
1169- ) && download_date_time <= delete_date_time
1170- {
1171- info ! (
1172- stream = %stream,
1173- tenant = ?tenant_id,
1174- candidate = %file_to_delete. file_path,
1175- target = %download_file_path. display( ) ,
1176- "skip evict: candidate newer than target"
1177- ) ;
1178- delete_successful = false ;
1179- break ' loop_files;
1180- }
1181-
1182- fs:: write ( manifest_file. path ( ) , serde_json:: to_vec ( & manifest) ?) . await ?;
1171+ if manifest. files . is_empty ( ) {
1172+ continue ;
1173+ }
11831174
1184- fs:: remove_dir_all ( path_to_delete. parent ( ) . unwrap ( ) ) . await ?;
1185- delete_empty_directory_hot_tier (
1186- path_to_delete. parent ( ) . unwrap ( ) . to_path_buf ( ) ,
1187- )
1188- . await ?;
1175+ // sort in an ascending manner
1176+ // idx0: minute=00
1177+ // idx59: minute=59
1178+ manifest. files . sort_by_key ( |file| file. file_path . clone ( ) ) ;
11891179
1190- stream_hot_tier. used_size -= file_size;
1191- stream_hot_tier. available_size += file_size;
1192- self . put_hot_tier ( stream, stream_hot_tier, tenant_id)
1193- . await ?;
1194- delete_successful = true ;
1195- freed_total += file_size;
1180+ // get first file's parent (/hottier/stream/date=d/hour=h/minute=m)
1181+ let first_file = manifest. files . first ( ) . unwrap ( ) ;
1182+ let first_file_path = self . hot_tier_path . join ( & first_file. file_path ) ;
1183+ let minute_to_delete = first_file_path. parent ( ) . unwrap ( ) ;
1184+
1185+ if minute_to_delete. exists ( ) {
1186+ if let ( Some ( download_date_time) , Some ( delete_date_time) ) = (
1187+ extract_datetime ( download_file_path. to_str ( ) . unwrap ( ) ) ,
1188+ extract_datetime ( first_file_path. to_str ( ) . unwrap ( ) ) ,
1189+ ) && download_date_time <= delete_date_time
1190+ {
11961191 info ! (
11971192 stream = %stream,
11981193 tenant = ?tenant_id,
1199- evicted_file = %file_to_delete. file_path,
1200- evicted_size = file_size,
1201- freed_total,
1202- new_available = stream_hot_tier. available_size,
1203- "evicted"
1194+ candidate = %minute_to_delete. display( ) ,
1195+ target = %download_file_path. display( ) ,
1196+ "skip evict: candidate newer than target"
12041197 ) ;
1198+ continue ;
1199+ }
12051200
1206- if stream_hot_tier. available_size <= parquet_file_size {
1207- continue ' loop_files;
1201+ let minute_to_delete_owned = minute_to_delete. to_path_buf ( ) ;
1202+ let mut minute_freed: u64 = 0 ;
1203+ manifest. files . retain ( |file| {
1204+ let file_path = self . hot_tier_path . join ( & file. file_path ) ;
1205+ let file_minute = file_path. parent ( ) . unwrap ( ) ;
1206+ if file_minute == minute_to_delete_owned {
1207+ minute_freed = minute_freed. saturating_add ( file. file_size ) ;
1208+ false
12081209 } else {
1209- break ' loop_dates ;
1210+ true
12101211 }
1212+ } ) ;
1213+
1214+ stream_hot_tier. used_size = stream_hot_tier
1215+ . used_size
1216+ . checked_sub ( minute_freed)
1217+ . unwrap_or_else ( || {
1218+ tracing:: error!(
1219+ stream = %stream,
1220+ tenant = ?tenant_id,
1221+ minute = %minute_to_delete_owned. display( ) ,
1222+ minute_freed,
1223+ used_size = stream_hot_tier. used_size,
1224+ "minute_freed > used_size, clamping used_size to 0"
1225+ ) ;
1226+ 0
1227+ } ) ;
1228+ stream_hot_tier. available_size =
1229+ stream_hot_tier. available_size . saturating_add ( minute_freed) ;
1230+ freed_total = freed_total. saturating_add ( minute_freed) ;
1231+
1232+ fs:: write ( manifest_file. path ( ) , serde_json:: to_vec ( & manifest) ?) . await ?;
1233+ fs:: remove_dir_all ( & minute_to_delete_owned) . await ?;
1234+ delete_empty_directory_hot_tier ( minute_to_delete_owned. clone ( ) ) . await ?;
1235+ self . put_hot_tier ( stream, stream_hot_tier, tenant_id)
1236+ . await ?;
1237+ delete_successful = true ;
1238+ info ! (
1239+ stream = %stream,
1240+ tenant = ?tenant_id,
1241+ evicted_minute = %minute_to_delete_owned. display( ) ,
1242+ evicted_size = minute_freed,
1243+ freed_total,
1244+ new_available = stream_hot_tier. available_size,
1245+ "evicted"
1246+ ) ;
1247+ if stream_hot_tier. available_size <= parquet_file_size {
1248+ continue ;
12111249 } else {
1212- fs :: write ( manifest_file . path ( ) , serde_json :: to_vec ( & manifest ) ? ) . await ? ;
1250+ break ' loop_dates ;
12131251 }
12141252 }
12151253 }
0 commit comments