Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions crates/crates_io_database/src/models/category.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
Expand Down Expand Up @@ -116,13 +118,16 @@ impl Category {
.load(conn)
}

pub async fn subcategories(&self, conn: &mut AsyncPgConnection) -> QueryResult<Vec<Category>> {
pub fn subcategories(
&self,
conn: &mut AsyncPgConnection,
) -> BoxFuture<'_, QueryResult<Vec<Category>>> {
use diesel::sql_types::Text;

diesel::sql_query(include_str!("subcategories.sql"))
.bind::<Text, _>(&self.category)
.load(conn)
.await
.boxed()
}

/// Gathers the parent categories from the top-level Category to the direct parent of this Category.
Expand Down
30 changes: 14 additions & 16 deletions src/controllers/category.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
Expand Down Expand Up @@ -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 }))
Expand Down Expand Up @@ -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);
Expand Down