diff --git a/src/utils/mod.rs b/src/utils/mod.rs index ae6560914..9b9592e09 100644 --- a/src/utils/mod.rs +++ b/src/utils/mod.rs @@ -20,7 +20,7 @@ mod html; mod queue; pub(crate) mod queue_builder; mod rustc_version; -use anyhow::Result; +use anyhow::{Context as _, Result}; use postgres::Client; use serde::de::DeserializeOwned; use serde::Serialize; @@ -78,6 +78,40 @@ where ) } +/// a wrapper around tokio's `spawn_blocking` that +/// enables us to write nicer code when the closure +/// returns an `anyhow::Result`. +/// +/// The join-error will also be converted into an `anyhow::Error`. +/// +/// with standard `tokio::task::spawn_blocking`: +/// ```ignore +/// let data = spawn_blocking(move || -> anyhow::Result<_> { +/// let data = get_the_data()?; +/// Ok(data) +/// }) +/// .await +/// .context("failed to join thread")??; +/// ``` +/// +/// with this helper function: +/// ```ignore +/// let data = spawn_blocking(move || { +/// let data = get_the_data()?; +/// Ok(data) +/// }) +/// .await? +/// ``` +pub(crate) async fn spawn_blocking(f: F) -> Result +where + F: FnOnce() -> Result + Send + 'static, + R: Send + 'static, +{ + tokio::task::spawn_blocking(f) + .await + .context("failed to join thread")? +} + #[cfg(test)] mod tests { use super::*; diff --git a/src/web/releases.rs b/src/web/releases.rs index cd00d268a..6a237852e 100644 --- a/src/web/releases.rs +++ b/src/web/releases.rs @@ -5,7 +5,7 @@ use crate::{ cdn::{self, CrateInvalidation}, db::{Pool, PoolClient}, impl_axum_webpage, impl_webpage, - utils::report_error, + utils::{report_error, spawn_blocking}, web::{ error::{Nope, WebResult}, match_version, @@ -14,7 +14,7 @@ use crate::{ }, BuildQueue, Config, }; -use anyhow::{anyhow, Context as _, Result}; +use anyhow::{anyhow, Result}; use axum::{ extract::{Extension, Path}, response::IntoResponse, @@ -31,7 +31,6 @@ use router::Router; use serde::{Deserialize, Serialize}; use std::collections::{BTreeMap, HashMap}; use std::str; -use tokio::task::spawn_blocking; use tracing::{debug, warn}; use url::form_urlencoded; @@ -346,7 +345,7 @@ pub(crate) async fn releases_handler( } }; - let releases = spawn_blocking(move || -> Result<_> { + let releases = spawn_blocking(move || { let mut conn = pool.get()?; get_releases( &mut conn, @@ -356,8 +355,7 @@ pub(crate) async fn releases_handler( latest_only, ) }) - .await - .context("failed to join thread")??; + .await?; // Show next and previous page buttons let (show_next_page, show_previous_page) = ( diff --git a/src/web/sitemap.rs b/src/web/sitemap.rs index e183a94f8..eadeeb250 100644 --- a/src/web/sitemap.rs +++ b/src/web/sitemap.rs @@ -2,13 +2,12 @@ use crate::{ db::Pool, docbuilder::Limits, impl_axum_webpage, impl_webpage, - utils::{get_config, ConfigName}, + utils::{get_config, spawn_blocking, ConfigName}, web::{ error::{AxumNope, WebResult}, page::WebPage, }, }; -use anyhow::Context; use axum::{ extract::{Extension, Path}, response::IntoResponse, @@ -16,7 +15,6 @@ use axum::{ use chrono::{DateTime, TimeZone, Utc}; use iron::{IronResult, Request as IronRequest, Response as IronResponse}; use serde::Serialize; -use tokio::task::spawn_blocking; /// sitemap index #[derive(Debug, Clone, PartialEq, Eq, Serialize)] @@ -64,7 +62,7 @@ pub(crate) async fn sitemap_handler( return Err(AxumNope::ResourceNotFound); } } - let releases = spawn_blocking(move || -> anyhow::Result<_> { + let releases = spawn_blocking(move || { let mut conn = pool.get()?; let query = conn.query( "SELECT crates.name, @@ -95,8 +93,7 @@ pub(crate) async fn sitemap_handler( }) .collect()) }) - .await - .context("failed to join thread")??; + .await?; Ok(SitemapXml { releases }) } @@ -116,12 +113,11 @@ impl_axum_webpage!(AboutBuilds = "core/about/builds.html"); pub(crate) async fn about_builds_handler( Extension(pool): Extension, ) -> WebResult { - let rustc_version = spawn_blocking(move || -> anyhow::Result<_> { + let rustc_version = spawn_blocking(move || { let mut conn = pool.get()?; get_config::(&mut conn, ConfigName::RustcVersion) }) - .await - .context("failed to join thread")??; + .await?; Ok(AboutBuilds { rustc_version,