Skip to content

Commit 9d65ca3

Browse files
committed
controllers/krate/versions: Merge list_by_date() and list_by_semver() fns
1 parent 7a9364d commit 9d65ca3

File tree

1 file changed

+34
-124
lines changed

1 file changed

+34
-124
lines changed

src/controllers/krate/versions.rs

Lines changed: 34 additions & 124 deletions
Original file line numberDiff line numberDiff line change
@@ -99,13 +99,8 @@ pub async fn list_versions(
9999
None => None,
100100
};
101101

102-
// Sort by semver by default
103-
let versions_and_publishers = match &params.sort.as_ref().map(|s| s.to_lowercase()).as_deref() {
104-
Some("date") => {
105-
list_by_date(crate_id, pagination.as_ref(), &params, &req, &mut conn).await?
106-
}
107-
_ => list_by_semver(crate_id, pagination.as_ref(), &params, &req, &mut conn).await?,
108-
};
102+
let versions_and_publishers =
103+
list(crate_id, pagination.as_ref(), &params, &req, &mut conn).await?;
109104

110105
let versions = versions_and_publishers
111106
.data
@@ -126,12 +121,12 @@ pub async fn list_versions(
126121
}))
127122
}
128123

129-
/// Seek-based pagination of versions by date
124+
/// Seek-based pagination of versions
130125
///
131126
/// # Panics
132127
///
133-
/// This function will panic if `option` is built with `enable_pages` set to true.
134-
async fn list_by_date(
128+
/// This function will panic if `options` is built with `enable_pages` set to true.
129+
async fn list(
135130
crate_id: i32,
136131
options: Option<&PaginationOptions>,
137132
params: &ListQueryParams,
@@ -140,113 +135,11 @@ async fn list_by_date(
140135
) -> AppResult<PaginatedVersionsAndPublishers> {
141136
use seek::*;
142137

143-
let make_base_query = || {
144-
let mut query = versions::table
145-
.filter(versions::crate_id.eq(crate_id))
146-
.left_outer_join(users::table)
147-
.select(<(Version, Option<User>)>::as_select())
148-
.into_boxed();
149-
150-
if !params.nums.is_empty() {
151-
query = query.filter(versions::num.eq_any(params.nums.iter().map(|s| s.as_str())));
152-
}
153-
query
138+
let seek = match &params.sort.as_ref().map(|s| s.to_lowercase()).as_deref() {
139+
Some("date") => Seek::Date,
140+
_ => Seek::Semver,
154141
};
155142

156-
let mut query = make_base_query();
157-
158-
if let Some(options) = options {
159-
assert!(
160-
!matches!(&options.page, Page::Numeric(_)),
161-
"?page= is not supported"
162-
);
163-
if let Some(SeekPayload::Date(Date { created_at, id })) = Seek::Date.after(&options.page)? {
164-
query = query.filter(
165-
versions::created_at
166-
.eq(created_at)
167-
.and(versions::id.lt(id))
168-
.or(versions::created_at.lt(created_at)),
169-
)
170-
}
171-
query = query.limit(options.per_page);
172-
}
173-
174-
query = query.order((versions::created_at.desc(), versions::id.desc()));
175-
176-
let data: Vec<(Version, Option<User>)> = query.load(conn).await?;
177-
let mut next_page = None;
178-
if let Some(options) = options {
179-
next_page = next_seek_params(&data, options, |last| Seek::Date.to_payload(last))?
180-
.map(|p| req.query_with_params(p));
181-
};
182-
183-
let release_tracks = if params.include()?.release_tracks {
184-
let mut sorted_versions = IndexSet::new();
185-
if options.is_some() {
186-
versions::table
187-
.filter(versions::crate_id.eq(crate_id))
188-
.filter(not(versions::yanked))
189-
.select(versions::num)
190-
.load_stream::<String>(conn)
191-
.await?
192-
.try_for_each(|num| {
193-
if let Ok(semver) = semver::Version::parse(&num) {
194-
sorted_versions.insert(semver);
195-
};
196-
future::ready(Ok(()))
197-
})
198-
.await?;
199-
} else {
200-
sorted_versions = data
201-
.iter()
202-
.flat_map(|(version, _)| {
203-
(!version.yanked)
204-
.then_some(version)
205-
.and_then(|v| semver::Version::parse(&v.num).ok())
206-
})
207-
.collect();
208-
}
209-
210-
sorted_versions.sort_unstable_by(|a, b| b.cmp(a));
211-
Some(ReleaseTracks::from_sorted_semver_iter(
212-
sorted_versions.iter(),
213-
))
214-
} else {
215-
None
216-
};
217-
218-
// Since the total count is retrieved through an additional query, to maintain consistency
219-
// with other pagination methods, we only make a count query while data is not empty.
220-
let total = if !data.is_empty() {
221-
make_base_query().count().get_result(conn).await?
222-
} else {
223-
0
224-
};
225-
226-
Ok(PaginatedVersionsAndPublishers {
227-
data,
228-
meta: ResponseMeta {
229-
total,
230-
next_page,
231-
release_tracks,
232-
},
233-
})
234-
}
235-
236-
/// Seek-based pagination of versions by semver
237-
///
238-
/// # Panics
239-
///
240-
/// This function will panic if `option` is built with `enable_pages` set to true.
241-
async fn list_by_semver(
242-
crate_id: i32,
243-
options: Option<&PaginationOptions>,
244-
params: &ListQueryParams,
245-
req: &Parts,
246-
conn: &mut AsyncPgConnection,
247-
) -> AppResult<PaginatedVersionsAndPublishers> {
248-
use seek::*;
249-
250143
let make_base_query = || {
251144
let mut query = versions::table
252145
.filter(versions::crate_id.eq(crate_id))
@@ -267,23 +160,40 @@ async fn list_by_semver(
267160
!matches!(&options.page, Page::Numeric(_)),
268161
"?page= is not supported"
269162
);
270-
if let Some(SeekPayload::Semver(Semver { num, id })) = Seek::Semver.after(&options.page)? {
271-
query = query.filter(
272-
versions::semver_ord
273-
.eq(semver_ord(num.clone()))
274-
.and(versions::id.lt(id))
275-
.or(versions::semver_ord.lt(semver_ord(num))),
276-
)
163+
164+
match seek.after(&options.page)? {
165+
Some(SeekPayload::Date(Date { created_at, id })) => {
166+
query = query.filter(
167+
versions::created_at
168+
.eq(created_at)
169+
.and(versions::id.lt(id))
170+
.or(versions::created_at.lt(created_at)),
171+
)
172+
}
173+
Some(SeekPayload::Semver(Semver { num, id })) => {
174+
query = query.filter(
175+
versions::semver_ord
176+
.eq(semver_ord(num.clone()))
177+
.and(versions::id.lt(id))
178+
.or(versions::semver_ord.lt(semver_ord(num))),
179+
)
180+
}
181+
None => {}
277182
}
183+
278184
query = query.limit(options.per_page);
279185
}
280186

281-
query = query.order((versions::semver_ord.desc(), versions::id.desc()));
187+
if seek == Seek::Date {
188+
query = query.order((versions::created_at.desc(), versions::id.desc()));
189+
} else {
190+
query = query.order((versions::semver_ord.desc(), versions::id.desc()));
191+
}
282192

283193
let data: Vec<(Version, Option<User>)> = query.load(conn).await?;
284194
let mut next_page = None;
285195
if let Some(options) = options {
286-
next_page = next_seek_params(&data, options, |last| Seek::Semver.to_payload(last))?
196+
next_page = next_seek_params(&data, options, |last| seek.to_payload(last))?
287197
.map(|p| req.query_with_params(p));
288198
};
289199

0 commit comments

Comments
 (0)