@@ -9,85 +9,98 @@ use axum_extra::json;
99use axum_extra:: response:: ErasedJson ;
1010use diesel:: prelude:: * ;
1111use diesel_async:: { AsyncPgConnection , RunQueryDsl } ;
12+ use futures_util:: FutureExt ;
13+ use std:: future:: Future ;
1214
1315/// Handles the `GET /summary` route.
1416pub async fn summary ( state : AppState ) -> AppResult < ErasedJson > {
1517 let mut conn = state. db_read ( ) . await ?;
1618
17- let popular_categories = Category :: toplevel ( & mut conn, "crates" , 10 , 0 )
18- . await ?
19- . into_iter ( )
20- . map ( Category :: into)
21- . collect :: < Vec < EncodableCategory > > ( ) ;
22-
23- let num_crates: i64 = crates:: table. count ( ) . get_result ( & mut conn) . await ?;
24- let num_downloads: i64 = metadata:: table
25- . select ( metadata:: total_downloads)
26- . get_result ( & mut conn)
27- . await ?;
28-
2919 let config = & state. config ;
3020
31- let new_crates = crates:: table
32- . inner_join ( crate_downloads:: table)
33- . left_join ( recent_crate_downloads:: table)
34- . left_join ( default_versions:: table)
35- . left_join ( versions:: table. on ( default_versions:: version_id. eq ( versions:: id) ) )
36- . order ( crates:: created_at. desc ( ) )
37- . select ( Record :: as_select ( ) )
38- . limit ( 10 )
39- . load ( & mut conn)
40- . await ?;
41- let just_updated = crates:: table
42- . inner_join ( crate_downloads:: table)
43- . left_join ( recent_crate_downloads:: table)
44- . left_join ( default_versions:: table)
45- . left_join ( versions:: table. on ( default_versions:: version_id. eq ( versions:: id) ) )
46- . filter ( crates:: updated_at. ne ( crates:: created_at) )
47- . order ( crates:: updated_at. desc ( ) )
48- . select ( Record :: as_select ( ) )
49- . limit ( 10 )
50- . load ( & mut conn)
51- . await ?;
21+ let (
22+ num_crates,
23+ num_downloads,
24+ new_crates,
25+ just_updated,
26+ most_downloaded,
27+ most_recently_downloaded,
28+ popular_categories,
29+ popular_keywords,
30+ ) = tokio:: try_join!(
31+ crates:: table. count( ) . get_result:: <i64 >( & mut conn) . boxed( ) ,
32+ metadata:: table
33+ . select( metadata:: total_downloads)
34+ . get_result:: <i64 >( & mut conn)
35+ . boxed( ) ,
36+ crates:: table
37+ . inner_join( crate_downloads:: table)
38+ . left_join( recent_crate_downloads:: table)
39+ . left_join( default_versions:: table)
40+ . left_join( versions:: table. on( default_versions:: version_id. eq( versions:: id) ) )
41+ . order( crates:: created_at. desc( ) )
42+ . select( Record :: as_select( ) )
43+ . limit( 10 )
44+ . load( & mut conn)
45+ . boxed( ) ,
46+ crates:: table
47+ . inner_join( crate_downloads:: table)
48+ . left_join( recent_crate_downloads:: table)
49+ . left_join( default_versions:: table)
50+ . left_join( versions:: table. on( default_versions:: version_id. eq( versions:: id) ) )
51+ . filter( crates:: updated_at. ne( crates:: created_at) )
52+ . order( crates:: updated_at. desc( ) )
53+ . select( Record :: as_select( ) )
54+ . limit( 10 )
55+ . load( & mut conn)
56+ . boxed( ) ,
57+ crates:: table
58+ . inner_join( crate_downloads:: table)
59+ . left_join( recent_crate_downloads:: table)
60+ . left_join( default_versions:: table)
61+ . left_join( versions:: table. on( default_versions:: version_id. eq( versions:: id) ) )
62+ . filter( crates:: name. ne_all( & config. excluded_crate_names) )
63+ . then_order_by( crate_downloads:: downloads. desc( ) )
64+ . select( Record :: as_select( ) )
65+ . limit( 10 )
66+ . load( & mut conn)
67+ . boxed( ) ,
68+ crates:: table
69+ . inner_join( crate_downloads:: table)
70+ . inner_join( recent_crate_downloads:: table)
71+ . left_join( default_versions:: table)
72+ . left_join( versions:: table. on( default_versions:: version_id. eq( versions:: id) ) )
73+ . filter( crates:: name. ne_all( & config. excluded_crate_names) )
74+ . then_order_by( recent_crate_downloads:: downloads. desc( ) )
75+ . select( Record :: as_select( ) )
76+ . limit( 10 )
77+ . load( & mut conn)
78+ . boxed( ) ,
79+ Category :: toplevel( & mut conn, "crates" , 10 , 0 ) ,
80+ keywords:: table
81+ . order( keywords:: crates_cnt. desc( ) )
82+ . limit( 10 )
83+ . load( & mut conn)
84+ . boxed( ) ,
85+ ) ?;
5286
53- let most_downloaded = crates:: table
54- . inner_join ( crate_downloads:: table)
55- . left_join ( recent_crate_downloads:: table)
56- . left_join ( default_versions:: table)
57- . left_join ( versions:: table. on ( default_versions:: version_id. eq ( versions:: id) ) )
58- . filter ( crates:: name. ne_all ( & config. excluded_crate_names ) )
59- . then_order_by ( crate_downloads:: downloads. desc ( ) )
60- . select ( Record :: as_select ( ) )
61- . limit ( 10 )
62- . load ( & mut conn)
63- . await ?;
87+ let ( new_crates, most_downloaded, most_recently_downloaded, just_updated) = tokio:: try_join!(
88+ encode_crates( & mut conn, new_crates) ,
89+ encode_crates( & mut conn, most_downloaded) ,
90+ encode_crates( & mut conn, most_recently_downloaded) ,
91+ encode_crates( & mut conn, just_updated) ,
92+ ) ?;
6493
65- let most_recently_downloaded = crates:: table
66- . inner_join ( crate_downloads:: table)
67- . inner_join ( recent_crate_downloads:: table)
68- . left_join ( default_versions:: table)
69- . left_join ( versions:: table. on ( default_versions:: version_id. eq ( versions:: id) ) )
70- . filter ( crates:: name. ne_all ( & config. excluded_crate_names ) )
71- . then_order_by ( recent_crate_downloads:: downloads. desc ( ) )
72- . select ( Record :: as_select ( ) )
73- . limit ( 10 )
74- . load ( & mut conn)
75- . await ?;
94+ let popular_categories = popular_categories
95+ . into_iter ( )
96+ . map ( Category :: into)
97+ . collect :: < Vec < EncodableCategory > > ( ) ;
7698
77- let popular_keywords = keywords:: table
78- . order ( keywords:: crates_cnt. desc ( ) )
79- . limit ( 10 )
80- . load ( & mut conn)
81- . await ?
99+ let popular_keywords = popular_keywords
82100 . into_iter ( )
83101 . map ( Keyword :: into)
84102 . collect :: < Vec < EncodableKeyword > > ( ) ;
85103
86- let new_crates = encode_crates ( & mut conn, new_crates) . await ?;
87- let most_downloaded = encode_crates ( & mut conn, most_downloaded) . await ?;
88- let most_recently_downloaded = encode_crates ( & mut conn, most_recently_downloaded) . await ?;
89- let just_updated = encode_crates ( & mut conn, just_updated) . await ?;
90-
91104 Ok ( json ! ( {
92105 "num_downloads" : num_downloads,
93106 "num_crates" : num_crates,
@@ -115,32 +128,41 @@ struct Record {
115128 yanked : Option < bool > ,
116129}
117130
118- async fn encode_crates (
131+ fn encode_crates (
119132 conn : & mut AsyncPgConnection ,
120133 data : Vec < Record > ,
121- ) -> AppResult < Vec < EncodableCrate > > {
122- let krates = data. iter ( ) . map ( |record| & record. krate ) . collect :: < Vec < _ > > ( ) ;
123- let versions: Vec < Version > = Version :: belonging_to ( & krates)
134+ ) -> impl Future < Output = AppResult < Vec < EncodableCrate > > > {
135+ let crate_ids = data
136+ . iter ( )
137+ . map ( |record| record. krate . id )
138+ . collect :: < Vec < _ > > ( ) ;
139+
140+ let future = versions:: table
141+ . filter ( versions:: crate_id. eq_any ( crate_ids) )
124142 . filter ( versions:: yanked. eq ( false ) )
125143 . select ( Version :: as_select ( ) )
126- . load ( conn)
127- . await ?;
144+ . load ( conn) ;
128145
129- versions
130- . grouped_by ( & krates)
131- . into_iter ( )
132- . map ( TopVersions :: from_versions)
133- . zip ( data)
134- . map ( |( top_versions, record) | {
135- Ok ( EncodableCrate :: from_minimal (
136- record. krate ,
137- record. default_version . as_deref ( ) ,
138- record. yanked ,
139- Some ( & top_versions) ,
140- false ,
141- record. total_downloads ,
142- record. recent_downloads ,
143- ) )
144- } )
145- . collect ( )
146+ async move {
147+ let versions: Vec < Version > = future. await ?;
148+
149+ let krates = data. iter ( ) . map ( |record| & record. krate ) . collect :: < Vec < _ > > ( ) ;
150+ versions
151+ . grouped_by ( & krates)
152+ . into_iter ( )
153+ . map ( TopVersions :: from_versions)
154+ . zip ( data)
155+ . map ( |( top_versions, record) | {
156+ Ok ( EncodableCrate :: from_minimal (
157+ record. krate ,
158+ record. default_version . as_deref ( ) ,
159+ record. yanked ,
160+ Some ( & top_versions) ,
161+ false ,
162+ record. total_downloads ,
163+ record. recent_downloads ,
164+ ) )
165+ } )
166+ . collect ( )
167+ }
146168}
0 commit comments