diff --git a/crates/crates_io_database/src/models/category.rs b/crates/crates_io_database/src/models/category.rs index 62287b954ab..2692471654e 100644 --- a/crates/crates_io_database/src/models/category.rs +++ b/crates/crates_io_database/src/models/category.rs @@ -5,6 +5,8 @@ use diesel::dsl; use diesel::prelude::*; use diesel_async::scoped_futures::ScopedFutureExt; use diesel_async::{AsyncConnection, AsyncPgConnection, RunQueryDsl}; +use futures_util::future::BoxFuture; +use futures_util::FutureExt; use std::future::Future; #[derive(Clone, Identifiable, Queryable, QueryableByName, Debug, Selectable)] @@ -116,13 +118,16 @@ impl Category { .load(conn) } - pub async fn subcategories(&self, conn: &mut AsyncPgConnection) -> QueryResult> { + pub fn subcategories( + &self, + conn: &mut AsyncPgConnection, + ) -> BoxFuture<'_, QueryResult>> { use diesel::sql_types::Text; diesel::sql_query(include_str!("subcategories.sql")) .bind::(&self.category) .load(conn) - .await + .boxed() } /// Gathers the parent categories from the top-level Category to the direct parent of this Category. diff --git a/src/controllers/category.rs b/src/controllers/category.rs index 3c18b93c0fd..ea06cfa01ff 100644 --- a/src/controllers/category.rs +++ b/src/controllers/category.rs @@ -8,6 +8,7 @@ use axum::Json; use axum::extract::{FromRequestParts, Path, Query}; use diesel::QueryDsl; use diesel_async::RunQueryDsl; +use futures_util::FutureExt; use http::request::Parts; #[derive(Debug, Deserialize, FromRequestParts, utoipa::IntoParams)] @@ -62,11 +63,13 @@ pub async fn list_categories( let offset = options.offset().unwrap_or_default(); - let categories = Category::toplevel(&mut conn, sort, options.per_page, offset).await?; - let categories = categories.into_iter().map(Category::into).collect(); + let (categories, total) = tokio::try_join!( + Category::toplevel(&mut conn, sort, options.per_page, offset).boxed(), + // Query for the total count of categories + Category::count_toplevel(&mut conn).boxed(), + )?; - // Query for the total count of categories - let total = Category::count_toplevel(&mut conn).await?; + let categories = categories.into_iter().map(Category::into).collect(); let meta = ListMeta { total }; Ok(Json(ListResponse { categories, meta })) @@ -94,18 +97,13 @@ pub async fn find_category( let mut conn = state.db_read().await?; let cat: Category = Category::by_slug(&slug).first(&mut conn).await?; - let subcats = cat - .subcategories(&mut conn) - .await? - .into_iter() - .map(Category::into) - .collect(); - let parents = cat - .parent_categories(&mut conn) - .await? - .into_iter() - .map(Category::into) - .collect(); + let (subcats, parents) = tokio::try_join!( + cat.subcategories(&mut conn), + cat.parent_categories(&mut conn).boxed(), + )?; + + let subcats = subcats.into_iter().map(Category::into).collect(); + let parents = parents.into_iter().map(Category::into).collect(); let mut category = EncodableCategory::from(cat); category.subcategories = Some(subcats);