Skip to content

Commit d2a7257

Browse files
authored
Merge pull request #10079 from Turbo87/summary-record
controllers/summary: Convert `Record` to named struct
2 parents 564ad52 + c068816 commit d2a7257

File tree

1 file changed

+59
-58
lines changed

1 file changed

+59
-58
lines changed

src/controllers/summary.rs

Lines changed: 59 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,8 @@ use crate::util::errors::AppResult;
77
use crate::views::{EncodableCategory, EncodableCrate, EncodableKeyword};
88
use axum_extra::json;
99
use axum_extra::response::ErasedJson;
10-
use diesel::{
11-
BelongingToDsl, ExpressionMethods, JoinOnDsl, NullableExpressionMethods, QueryDsl,
12-
SelectableHelper,
13-
};
14-
use diesel_async::AsyncPgConnection;
15-
use diesel_async::RunQueryDsl;
10+
use diesel::prelude::*;
11+
use diesel_async::{AsyncPgConnection, RunQueryDsl};
1612

1713
/// Handles the `GET /summary` route.
1814
pub async fn summary(state: AppState) -> AppResult<ErasedJson> {
@@ -30,58 +26,15 @@ pub async fn summary(state: AppState) -> AppResult<ErasedJson> {
3026
.get_result(&mut conn)
3127
.await?;
3228

33-
async fn encode_crates(
34-
conn: &mut AsyncPgConnection,
35-
data: Vec<Record>,
36-
) -> AppResult<Vec<EncodableCrate>> {
37-
use diesel::GroupedBy;
38-
use diesel_async::RunQueryDsl;
39-
40-
let krates = data.iter().map(|(c, ..)| c).collect::<Vec<_>>();
41-
let versions: Vec<Version> = Version::belonging_to(&krates)
42-
.filter(versions::yanked.eq(false))
43-
.select(Version::as_select())
44-
.load(conn)
45-
.await?;
46-
47-
versions
48-
.grouped_by(&krates)
49-
.into_iter()
50-
.map(TopVersions::from_versions)
51-
.zip(data)
52-
.map(
53-
|(top_versions, (krate, total, recent, default_version, yanked))| {
54-
Ok(EncodableCrate::from_minimal(
55-
krate,
56-
default_version.as_deref(),
57-
yanked,
58-
Some(&top_versions),
59-
false,
60-
total,
61-
recent,
62-
))
63-
},
64-
)
65-
.collect()
66-
}
67-
6829
let config = &state.config;
6930

70-
let selection = (
71-
Crate::as_select(),
72-
crate_downloads::downloads,
73-
recent_crate_downloads::downloads.nullable(),
74-
versions::num.nullable(),
75-
versions::yanked.nullable(),
76-
);
77-
7831
let new_crates = crates::table
7932
.inner_join(crate_downloads::table)
8033
.left_join(recent_crate_downloads::table)
8134
.left_join(default_versions::table)
8235
.left_join(versions::table.on(default_versions::version_id.eq(versions::id)))
8336
.order(crates::created_at.desc())
84-
.select(selection)
37+
.select(Record::as_select())
8538
.limit(10)
8639
.load(&mut conn)
8740
.await?;
@@ -92,7 +45,7 @@ pub async fn summary(state: AppState) -> AppResult<ErasedJson> {
9245
.left_join(versions::table.on(default_versions::version_id.eq(versions::id)))
9346
.filter(crates::updated_at.ne(crates::created_at))
9447
.order(crates::updated_at.desc())
95-
.select(selection)
48+
.select(Record::as_select())
9649
.limit(10)
9750
.load(&mut conn)
9851
.await?;
@@ -104,7 +57,7 @@ pub async fn summary(state: AppState) -> AppResult<ErasedJson> {
10457
.left_join(versions::table.on(default_versions::version_id.eq(versions::id)))
10558
.filter(crates::name.ne_all(&config.excluded_crate_names))
10659
.then_order_by(crate_downloads::downloads.desc())
107-
.select(selection)
60+
.select(Record::as_select())
10861
.limit(10)
10962
.load(&mut conn)
11063
.await?;
@@ -116,7 +69,7 @@ pub async fn summary(state: AppState) -> AppResult<ErasedJson> {
11669
.left_join(versions::table.on(default_versions::version_id.eq(versions::id)))
11770
.filter(crates::name.ne_all(&config.excluded_crate_names))
11871
.then_order_by(recent_crate_downloads::downloads.desc())
119-
.select(selection)
72+
.select(Record::as_select())
12073
.limit(10)
12174
.load(&mut conn)
12275
.await?;
@@ -130,16 +83,64 @@ pub async fn summary(state: AppState) -> AppResult<ErasedJson> {
13083
.map(Keyword::into)
13184
.collect::<Vec<EncodableKeyword>>();
13285

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+
13391
Ok(json!({
13492
"num_downloads": num_downloads,
13593
"num_crates": num_crates,
136-
"new_crates": encode_crates(&mut conn, new_crates).await?,
137-
"most_downloaded": encode_crates(&mut conn, most_downloaded).await?,
138-
"most_recently_downloaded": encode_crates(&mut conn, most_recently_downloaded).await?,
139-
"just_updated": encode_crates(&mut conn, just_updated).await?,
94+
"new_crates": new_crates,
95+
"most_downloaded": most_downloaded,
96+
"most_recently_downloaded": most_recently_downloaded,
97+
"just_updated": just_updated,
14098
"popular_keywords": popular_keywords,
14199
"popular_categories": popular_categories,
142100
}))
143101
}
144102

145-
type Record = (Crate, i64, Option<i64>, Option<String>, Option<bool>);
103+
#[derive(Debug, Queryable, Selectable)]
104+
#[diesel(check_for_backend(diesel::pg::Pg))]
105+
struct Record {
106+
#[diesel(embed)]
107+
krate: Crate,
108+
#[diesel(select_expression = crate_downloads::columns::downloads)]
109+
total_downloads: i64,
110+
#[diesel(select_expression = recent_crate_downloads::columns::downloads.nullable())]
111+
recent_downloads: Option<i64>,
112+
#[diesel(select_expression = versions::columns::num.nullable())]
113+
default_version: Option<String>,
114+
#[diesel(select_expression = versions::columns::yanked.nullable())]
115+
yanked: Option<bool>,
116+
}
117+
118+
async fn encode_crates(
119+
conn: &mut AsyncPgConnection,
120+
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)
124+
.filter(versions::yanked.eq(false))
125+
.select(Version::as_select())
126+
.load(conn)
127+
.await?;
128+
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+
}

0 commit comments

Comments
 (0)