@@ -4,6 +4,7 @@ use bathbot_client::ClientError;
44use bathbot_psql:: model:: osu:: { ArtistTitle , DbBeatmap , DbBeatmapset , DbMapContent , MapVersion } ;
55use bathbot_util:: { ExponentialBackoff , IntHasher } ;
66use eyre:: { ContextCompat , Report , WrapErr } ;
7+ use futures:: { TryStreamExt , stream:: FuturesUnordered } ;
78use rosu_pp:: {
89 Beatmap ,
910 any:: DifficultyAttributes ,
@@ -117,34 +118,30 @@ impl MapManager {
117118 . await
118119 . wrap_err ( "Failed to get maps" ) ?;
119120
120- let iter = maps_id_checksum
121+ maps_id_checksum
121122 . keys ( )
122- . map ( |map_id| ( * map_id as u32 , db_maps. remove ( map_id) ) ) ;
123-
124- let mut maps = HashMap :: with_capacity_and_hasher ( maps_id_checksum. len ( ) , IntHasher ) ;
125-
126- // Having this non-async is pretty sad but the many I/O operations appear
127- // to cause thread-limitation issues when collected into a FuturesUnordered.
128- for ( map_id, map_opt) in iter {
129- let map = if let Some ( ( map, mapset, filename) ) = map_opt {
130- let ( pp_map, map_opt) = self . prepare_map ( map_id, filename) . await ?;
131-
132- match map_opt {
133- Some ( map) => OsuMap :: new ( map, pp_map) ,
134- None => OsuMap :: new ( OsuMapSlim :: new ( map, mapset) , pp_map) ,
135- }
136- } else {
137- let map_fut = self . retrieve_map ( map_id) ;
138- let prepare_fut = self . prepare_map ( map_id, DbMapContent :: Missing ) ;
139- let ( map, ( pp_map, _) ) = tokio:: try_join!( map_fut, prepare_fut) ?;
140-
141- OsuMap :: new ( map, pp_map)
142- } ;
123+ . map ( |map_id| ( * map_id as u32 , db_maps. remove ( map_id) ) )
124+ . map ( |( map_id, map_opt) | async move {
125+ let map = if let Some ( ( map, mapset, filepath) ) = map_opt {
126+ let ( pp_map, map_opt) = self . prepare_map ( map_id, filepath) . await ?;
127+
128+ match map_opt {
129+ Some ( map) => OsuMap :: new ( map, pp_map) ,
130+ None => OsuMap :: new ( OsuMapSlim :: new ( map, mapset) , pp_map) ,
131+ }
132+ } else {
133+ let map_fut = self . retrieve_map ( map_id) ;
134+ let prepare_fut = self . prepare_map ( map_id, DbMapContent :: Missing ) ;
135+ let ( map, ( pp_map, _) ) = tokio:: try_join!( map_fut, prepare_fut) ?;
143136
144- maps . insert ( map_id , map ) ;
145- }
137+ OsuMap :: new ( map , pp_map )
138+ } ;
146139
147- Ok ( maps)
140+ Ok ( ( map_id, map) )
141+ } )
142+ . collect :: < FuturesUnordered < _ > > ( )
143+ . try_collect ( )
144+ . await
148145 }
149146
150147 pub async fn artist_title ( self , mapset_id : u32 ) -> Result < ArtistTitle > {
@@ -346,7 +343,7 @@ impl MapManager {
346343 let db_fut = Context :: psql ( ) . insert_beatmap_file_content ( map_id, & bytes) ;
347344
348345 if let Err ( err) = db_fut. await {
349- warn ! ( ?err, "Failed to insert map file" ) ;
346+ warn ! ( map_id , ?err, "Failed to insert file content " ) ;
350347 } else {
351348 info ! ( "Downloaded {map_id}.osu successfully" ) ;
352349 }
0 commit comments