Skip to content

Commit b6b54d2

Browse files
author
Marco Napetti
committed
Paginate versions only when per_page parameter is present
1 parent 5231704 commit b6b54d2

File tree

1 file changed

+39
-8
lines changed

1 file changed

+39
-8
lines changed

src/controllers/krate/metadata.rs

Lines changed: 39 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@ use std::cmp::Reverse;
88
use std::str::FromStr;
99

1010
use crate::controllers::frontend_prelude::*;
11-
use crate::controllers::helpers::pagination::PaginationOptions;
11+
use crate::controllers::helpers::Paginate;
12+
use crate::controllers::helpers::pagination::{PaginationOptions, Paginated};
1213

1314
use crate::models::{
1415
Category, Crate, CrateCategory, CrateKeyword, CrateVersions, Keyword, RecentCrateDownloads,
@@ -320,15 +321,34 @@ pub async fn readme(
320321
/// Handles the `GET /crates/:crate_id/versions` route.
321322
// FIXME: Not sure why this is necessary since /crates/:crate_id returns
322323
// this information already, but ember is definitely requesting it
323-
pub async fn versions(state: AppState, Path(crate_name): Path<String>) -> AppResult<Json<Value>> {
324+
pub async fn versions(state: AppState, Path(crate_name): Path<String>, req: Parts) -> AppResult<Json<Value>> {
324325
conduit_compat(move || {
325326
let conn = state.db_read()?;
326327
let krate: Crate = Crate::by_name(&crate_name).first(&*conn)?;
327-
let mut versions_and_publishers: Vec<(Version, Option<User>)> = krate
328-
.all_versions()
329-
.left_outer_join(users::table)
330-
.select((versions::all_columns, users::all_columns.nullable()))
331-
.load(&*conn)?;
328+
// to keep retrocompatibility, we paginate only if per_page parameter is present
329+
let (mut versions_and_publishers, meta) = if req.query().get("per_page").is_some() {
330+
let pagination_options = PaginationOptions::builder().gather(&req)?;
331+
let data: Paginated<(Version, Option<User>)> = krate
332+
.all_versions()
333+
.left_outer_join(users::table)
334+
.select((versions::all_columns, users::all_columns.nullable()))
335+
.order(versions::created_at.desc())
336+
.pages_pagination(pagination_options)
337+
.load(&conn)?;
338+
let more = data.next_page_params().is_some();
339+
340+
(
341+
data.into_iter().collect::<Vec<_>>(),
342+
Some(json!({ "more": more })),
343+
)
344+
} else {
345+
let data: Vec<(Version, Option<User>)> = krate
346+
.all_versions()
347+
.left_outer_join(users::table)
348+
.select((versions::all_columns, users::all_columns.nullable()))
349+
.load(&*conn)?;
350+
(data, None)
351+
};
332352

333353
versions_and_publishers
334354
.sort_by_cached_key(|(version, _)| Reverse(semver::Version::parse(&version.num).ok()));
@@ -344,7 +364,18 @@ pub async fn versions(state: AppState, Path(crate_name): Path<String>) -> AppRes
344364
.map(|((v, pb), aas)| EncodableVersion::from(v, &crate_name, pb, aas))
345365
.collect::<Vec<_>>();
346366

347-
Ok(Json(json!({ "versions": versions })))
367+
// probably here would be simplier with a concrete response type
368+
let response = if let Some(meta) = meta {
369+
json!({
370+
"versions": versions,
371+
"meta": meta,
372+
})
373+
} else {
374+
json!({
375+
"versions": versions,
376+
})
377+
};
378+
Ok(Json(response))
348379
})
349380
.await
350381
}

0 commit comments

Comments
 (0)