Skip to content

Commit 391fb58

Browse files
authored
Merge pull request #8244 from Turbo87/search-downloads
controllers/krate/search: Read downloads from `crate_downloads` table
2 parents 213b184 + ef105ce commit 391fb58

File tree

5 files changed

+47
-32
lines changed

5 files changed

+47
-32
lines changed

src/controllers/krate/metadata.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ pub async fn show(app: AppState, Path(name): Path<String>, req: Parts) -> AppRes
115115
cats.as_deref(),
116116
badges,
117117
false,
118+
krate.downloads as i64,
118119
recent_downloads,
119120
);
120121
let encodable_versions = versions_publishers_and_audit_actions.map(|vpa| {

src/controllers/krate/publish.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -411,8 +411,9 @@ pub async fn publish(app: AppState, req: BytesRequest) -> AppResult<Json<GoodCra
411411
other: vec![],
412412
};
413413

414+
let downloads = krate.downloads as i64;
414415
Ok(Json(GoodCrate {
415-
krate: EncodableCrate::from_minimal(krate, Some(&top_versions), None, false, None),
416+
krate: EncodableCrate::from_minimal(krate, Some(&top_versions), None, false, downloads, None),
416417
warnings,
417418
}))
418419
})

src/controllers/krate/search.rs

Lines changed: 39 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ pub async fn search(app: AppState, req: Parts) -> AppResult<Json<Value>> {
7272
let selection = (
7373
ALL_COLUMNS,
7474
false.into_sql::<Bool>(),
75+
crate_downloads::downloads,
7576
recent_crate_downloads::downloads.nullable(),
7677
0_f32.into_sql::<Float>(),
7778
);
@@ -80,6 +81,7 @@ pub async fn search(app: AppState, req: Parts) -> AppResult<Json<Value>> {
8081
let mut seek: Option<Seek> = None;
8182
let mut query = filter_params
8283
.make_query(&req, conn)?
84+
.inner_join(crate_downloads::table)
8385
.left_join(recent_crate_downloads::table)
8486
.select(selection);
8587

@@ -97,6 +99,7 @@ pub async fn search(app: AppState, req: Parts) -> AppResult<Json<Value>> {
9799
query = query.select((
98100
ALL_COLUMNS,
99101
Crate::with_name(q_string),
102+
crate_downloads::downloads,
100103
recent_crate_downloads::downloads.nullable(),
101104
rank.clone(),
102105
));
@@ -106,6 +109,7 @@ pub async fn search(app: AppState, req: Parts) -> AppResult<Json<Value>> {
106109
query = query.select((
107110
ALL_COLUMNS,
108111
Crate::with_name(q_string),
112+
crate_downloads::downloads,
109113
recent_crate_downloads::downloads.nullable(),
110114
0_f32.into_sql::<Float>(),
111115
));
@@ -121,7 +125,7 @@ pub async fn search(app: AppState, req: Parts) -> AppResult<Json<Value>> {
121125
// to ensure predictable pagination behavior.
122126
if sort == Some("downloads") {
123127
seek = Some(Seek::Downloads);
124-
query = query.order((crates::downloads.desc(), crates::id.desc()))
128+
query = query.order((crate_downloads::downloads.desc(), crates::id.desc()))
125129
} else if sort == Some("recent-downloads") {
126130
seek = Some(Seek::RecentDownloads);
127131
query = query.order((
@@ -170,7 +174,7 @@ pub async fn search(app: AppState, req: Parts) -> AppResult<Json<Value>> {
170174
pagination,
171175
filter_params.make_query(&req, conn)?.count(),
172176
);
173-
let data: Paginated<(Crate, bool, Option<i64>, f32)> =
177+
let data: Paginated<(Crate, bool, i64, Option<i64>, f32)> =
174178
info_span!("db.query", message = "SELECT ..., COUNT(*) FROM crates")
175179
.in_scope(|| query.load(conn))?;
176180

@@ -187,7 +191,7 @@ pub async fn search(app: AppState, req: Parts) -> AppResult<Json<Value>> {
187191
pagination,
188192
filter_params.make_query(&req, conn)?.count(),
189193
);
190-
let data: Paginated<(Crate, bool, Option<i64>, f32)> =
194+
let data: Paginated<(Crate, bool, i64, Option<i64>, f32)> =
191195
info_span!("db.query", message = "SELECT ..., COUNT(*) FROM crates")
192196
.in_scope(|| query.load(conn))?;
193197
(
@@ -199,12 +203,15 @@ pub async fn search(app: AppState, req: Parts) -> AppResult<Json<Value>> {
199203
)
200204
};
201205

202-
let perfect_matches = data.iter().map(|&(_, b, _, _)| b).collect::<Vec<_>>();
203-
let recent_downloads = data
206+
let perfect_matches = data.iter().map(|&(_, b, _, _, _)| b).collect::<Vec<_>>();
207+
let downloads = data
204208
.iter()
205-
.map(|&(_, _, s, _)| s.unwrap_or(0))
209+
.map(|&(_, _, total, recent, _)| (total, recent.unwrap_or(0)))
210+
.collect::<Vec<_>>();
211+
let crates = data
212+
.into_iter()
213+
.map(|(c, _, _, _, _)| c)
206214
.collect::<Vec<_>>();
207-
let crates = data.into_iter().map(|(c, _, _, _)| c).collect::<Vec<_>>();
208215

209216
let versions: Vec<Version> = info_span!("db.query", message = "SELECT ... FROM versions")
210217
.in_scope(|| crates.versions().load(conn))?;
@@ -216,18 +223,17 @@ pub async fn search(app: AppState, req: Parts) -> AppResult<Json<Value>> {
216223
let crates = versions
217224
.zip(crates)
218225
.zip(perfect_matches)
219-
.zip(recent_downloads)
220-
.map(
221-
|(((max_version, krate), perfect_match), recent_downloads)| {
222-
EncodableCrate::from_minimal(
223-
krate,
224-
Some(&max_version),
225-
Some(vec![]),
226-
perfect_match,
227-
Some(recent_downloads),
228-
)
229-
},
230-
)
226+
.zip(downloads)
227+
.map(|(((max_version, krate), perfect_match), (total, recent))| {
228+
EncodableCrate::from_minimal(
229+
krate,
230+
Some(&max_version),
231+
Some(vec![]),
232+
perfect_match,
233+
total,
234+
Some(recent),
235+
)
236+
})
231237
.collect::<Vec<_>>();
232238

233239
Ok(Json(json!({
@@ -476,12 +482,12 @@ impl<'a> FilterParams<'a> {
476482
// `WHERE (downloads = downloads' AND id < id') OR downloads < downloads'`
477483
vec![
478484
Box::new(
479-
crates::downloads
485+
crate_downloads::downloads
480486
.eq(downloads)
481487
.and(crates::id.lt(id))
482488
.nullable(),
483489
),
484-
Box::new(crates::downloads.lt(downloads).nullable()),
490+
Box::new(crate_downloads::downloads.lt(downloads).nullable()),
485491
]
486492
}
487493
SeekPayload::Query(Query(exact_match, id)) => {
@@ -551,29 +557,30 @@ mod seek {
551557
New(#[serde(with="ts_microseconds")] chrono::NaiveDateTime, i32)
552558
RecentUpdates(#[serde(with="ts_microseconds")] chrono::NaiveDateTime, i32)
553559
RecentDownloads(Option<i64>, i32)
554-
Downloads(i32, i32)
560+
Downloads(i64, i32)
555561
Query(bool, i32)
556562
Relevance(bool, f32, i32)
557563
}
558564
}
559565

560566
impl Seek {
561-
pub(crate) fn to_payload(&self, record: &(Crate, bool, Option<i64>, f32)) -> SeekPayload {
567+
pub(crate) fn to_payload(
568+
&self,
569+
record: &(Crate, bool, i64, Option<i64>, f32),
570+
) -> SeekPayload {
562571
match *self {
563572
Seek::Name => SeekPayload::Name(Name(record.0.id)),
564573
Seek::New => SeekPayload::New(New(record.0.created_at, record.0.id)),
565574
Seek::RecentUpdates => {
566575
SeekPayload::RecentUpdates(RecentUpdates(record.0.updated_at, record.0.id))
567576
}
568577
Seek::RecentDownloads => {
569-
SeekPayload::RecentDownloads(RecentDownloads(record.2, record.0.id))
570-
}
571-
Seek::Downloads => {
572-
SeekPayload::Downloads(Downloads(record.0.downloads, record.0.id))
578+
SeekPayload::RecentDownloads(RecentDownloads(record.3, record.0.id))
573579
}
580+
Seek::Downloads => SeekPayload::Downloads(Downloads(record.2, record.0.id)),
574581
Seek::Query => SeekPayload::Query(Query(record.1, record.0.id)),
575582
Seek::Relevance => {
576-
SeekPayload::Relevance(Relevance(record.1, record.3, record.0.id))
583+
SeekPayload::Relevance(Relevance(record.1, record.4, record.0.id))
577584
}
578585
}
579586
}
@@ -582,7 +589,10 @@ mod seek {
582589

583590
type BoxedCondition<'a> = Box<
584591
dyn BoxableExpression<
585-
LeftJoinQuerySource<crates::table, recent_crate_downloads::table>,
592+
LeftJoinQuerySource<
593+
InnerJoinQuerySource<crates::table, crate_downloads::table>,
594+
recent_crate_downloads::table,
595+
>,
586596
diesel::pg::Pg,
587597
SqlType = diesel::sql_types::Nullable<Bool>,
588598
> + 'a,

src/controllers/summary.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,11 +35,13 @@ pub async fn summary(state: AppState) -> AppResult<Json<Value>> {
3535
.zip(krates)
3636
.zip(recent_downloads)
3737
.map(|((top_versions, krate), recent_downloads)| {
38+
let downloads = krate.downloads as i64;
3839
Ok(EncodableCrate::from_minimal(
3940
krate,
4041
Some(&top_versions),
4142
None,
4243
false,
44+
downloads,
4345
recent_downloads,
4446
))
4547
})

src/views.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -230,13 +230,13 @@ impl EncodableCrate {
230230
categories: Option<&[Category]>,
231231
badges: Option<Vec<()>>,
232232
exact_match: bool,
233+
downloads: i64,
233234
recent_downloads: Option<i64>,
234235
) -> Self {
235236
let Crate {
236237
name,
237238
created_at,
238239
updated_at,
239-
downloads,
240240
description,
241241
homepage,
242242
documentation,
@@ -272,7 +272,6 @@ impl EncodableCrate {
272272
// behind the number of "recent downloads". to hide this inconsistency
273273
// we will use the "recent downloads" as "total downloads" in case it is
274274
// higher.
275-
let downloads = downloads as i64;
276275
let downloads = if matches!(recent_downloads, Some(x) if x > downloads) {
277276
recent_downloads.unwrap()
278277
} else {
@@ -314,6 +313,7 @@ impl EncodableCrate {
314313
top_versions: Option<&TopVersions>,
315314
badges: Option<Vec<()>>,
316315
exact_match: bool,
316+
downloads: i64,
317317
recent_downloads: Option<i64>,
318318
) -> Self {
319319
Self::from(
@@ -324,6 +324,7 @@ impl EncodableCrate {
324324
None,
325325
badges,
326326
exact_match,
327+
downloads,
327328
recent_downloads,
328329
)
329330
}

0 commit comments

Comments
 (0)