mirror of
https://github.com/modrinth/code.git
synced 2026-09-02 04:56:52 +00:00
refactor: labrinth ApiError and error reporting (#6981)
* refactor: labrinth `ApiError` and error reporting * fix clippy * fix ci
This commit is contained in:
@@ -4,6 +4,7 @@
|
||||
//! This keeps version filters correlated without duplicating every version
|
||||
//! into its project document.
|
||||
|
||||
use crate::util::error::ApiContext as _;
|
||||
use async_trait::async_trait;
|
||||
use eyre::{Result, eyre};
|
||||
use itertools::Itertools;
|
||||
@@ -388,7 +389,7 @@ impl Elasticsearch {
|
||||
.wrap_internal_err("failed to execute Elasticsearch search")?;
|
||||
let mut body = response_json(response, "execute Elasticsearch search")
|
||||
.await
|
||||
.map_err(ApiError::Internal)?;
|
||||
.wrap_internal_err("parsing Elasticsearch search response")?;
|
||||
if sort_only && !body["hits"]["hits"].is_array() {
|
||||
body["hits"]["hits"] = Value::Array(Vec::new());
|
||||
}
|
||||
@@ -410,12 +411,15 @@ impl Elasticsearch {
|
||||
.wrap_internal_err("failed to open Elasticsearch point in time")?;
|
||||
let body = response_json(response, "open Elasticsearch point in time")
|
||||
.await
|
||||
.map_err(ApiError::Internal)?;
|
||||
body["id"].as_str().map(ToOwned::to_owned).ok_or_else(|| {
|
||||
ApiError::Internal(eyre!(
|
||||
"Elasticsearch point in time response did not contain an ID"
|
||||
))
|
||||
})
|
||||
.wrap_internal_err(
|
||||
"parsing Elasticsearch point-in-time response",
|
||||
)?;
|
||||
body["id"]
|
||||
.as_str()
|
||||
.map(ToOwned::to_owned)
|
||||
.wrap_internal_err(
|
||||
"finding ID in Elasticsearch point-in-time response",
|
||||
)
|
||||
}
|
||||
|
||||
async fn close_point_in_time(&self, id: &str) -> Result<(), ApiError> {
|
||||
@@ -428,7 +432,9 @@ impl Elasticsearch {
|
||||
.wrap_internal_err("failed to close Elasticsearch point in time")?;
|
||||
response_json(response, "close Elasticsearch point in time")
|
||||
.await
|
||||
.map_err(ApiError::Internal)?;
|
||||
.wrap_internal_err(
|
||||
"parsing Elasticsearch point-in-time response",
|
||||
)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -456,7 +462,9 @@ impl Elasticsearch {
|
||||
"execute Elasticsearch point in time search",
|
||||
)
|
||||
.await
|
||||
.map_err(ApiError::Internal)?;
|
||||
.wrap_internal_err(
|
||||
"parsing Elasticsearch point-in-time search response",
|
||||
)?;
|
||||
if sort_only && !body["hits"]["hits"].is_array() {
|
||||
body["hits"]["hits"] = Value::Array(Vec::new());
|
||||
}
|
||||
@@ -472,7 +480,10 @@ impl Elasticsearch {
|
||||
offset: usize,
|
||||
size: usize,
|
||||
) -> Result<Value, ApiError> {
|
||||
let mut point_in_time_id = self.open_point_in_time(alias).await?;
|
||||
let mut point_in_time_id = self
|
||||
.open_point_in_time(alias)
|
||||
.await
|
||||
.wrap_api_err("executing `open_point_in_time`")?;
|
||||
let result = self
|
||||
.execute_deep_search_with_point_in_time(
|
||||
query,
|
||||
@@ -517,7 +528,10 @@ impl Elasticsearch {
|
||||
"id": point_in_time_id,
|
||||
"keep_alive": "1m"
|
||||
});
|
||||
let body = self.execute_point_in_time_search(&body, true).await?;
|
||||
let body = self
|
||||
.execute_point_in_time_search(&body, true)
|
||||
.await
|
||||
.wrap_api_err("executing `execute_point_in_time_search`")?;
|
||||
if let Some(id) = body["pit_id"].as_str() {
|
||||
*point_in_time_id = id.to_string();
|
||||
}
|
||||
@@ -579,7 +593,10 @@ impl Elasticsearch {
|
||||
"id": point_in_time_id,
|
||||
"keep_alive": "1m"
|
||||
});
|
||||
let body = self.execute_point_in_time_search(&body, false).await?;
|
||||
let body = self
|
||||
.execute_point_in_time_search(&body, false)
|
||||
.await
|
||||
.wrap_api_err("executing `execute_point_in_time_search`")?;
|
||||
if let Some(id) = body["pit_id"].as_str() {
|
||||
*point_in_time_id = id.to_string();
|
||||
}
|
||||
@@ -832,10 +849,13 @@ impl Elasticsearch {
|
||||
&self,
|
||||
info: &SearchRequest,
|
||||
) -> Result<SearchResults, ApiError> {
|
||||
let parsed = parse_search_request(info)?;
|
||||
let parsed = parse_search_request(info)
|
||||
.wrap_api_err("executing `parse_search_request`")?;
|
||||
let search_sort =
|
||||
parse_search_index(parsed.index, info.new_filters.as_deref())?;
|
||||
let filter = Self::build_filter(info)?;
|
||||
parse_search_index(parsed.index, info.new_filters.as_deref())
|
||||
.wrap_api_err("executing `parse_search_index`")?;
|
||||
let filter = Self::build_filter(info)
|
||||
.wrap_api_err("executing `Self::build_filter`")?;
|
||||
let mut filters = vec![json!({"term": {"document_type": "project"}})];
|
||||
if let Some(filter) = &filter {
|
||||
filters.push(filter.query.clone());
|
||||
@@ -858,7 +878,8 @@ impl Elasticsearch {
|
||||
parsed.offset,
|
||||
parsed.hits_per_page,
|
||||
)
|
||||
.await?
|
||||
.await
|
||||
.wrap_api_err("executing `execute_deep_search`")?
|
||||
} else {
|
||||
let body = Self::search_body(
|
||||
&query,
|
||||
@@ -869,7 +890,9 @@ impl Elasticsearch {
|
||||
None,
|
||||
true,
|
||||
);
|
||||
self.execute_search(&alias, &body, false).await?
|
||||
self.execute_search(&alias, &body, false)
|
||||
.await
|
||||
.wrap_api_err("executing `execute_search`")?
|
||||
};
|
||||
let total_hits = body["hits"]["total"]["value"]
|
||||
.as_u64()
|
||||
|
||||
@@ -137,6 +137,7 @@
|
||||
//! enabled. This avoids repeating joins for popular queries at the cost of
|
||||
//! results remaining stale for Typesense's default 60-second cache lifetime.
|
||||
|
||||
use crate::util::error::ApiContext as _;
|
||||
use std::sync::LazyLock;
|
||||
|
||||
use async_trait::async_trait;
|
||||
@@ -911,7 +912,8 @@ impl Typesense {
|
||||
new_filters: Option<&str>,
|
||||
request_config: &RequestConfig,
|
||||
) -> Result<(String, String), ApiError> {
|
||||
let sort = parse_search_index(index, new_filters)?;
|
||||
let sort = parse_search_index(index, new_filters)
|
||||
.wrap_api_err("executing `parse_search_index`")?;
|
||||
let alias = self.config.get_alias_name("projects");
|
||||
Ok((alias, self.get_sort_fields(sort.index, request_config)))
|
||||
}
|
||||
@@ -1047,14 +1049,18 @@ impl SearchBackend for Typesense {
|
||||
&self,
|
||||
info: &SearchRequest,
|
||||
) -> Result<SearchResults, ApiError> {
|
||||
let parsed = parse_search_request(info)?;
|
||||
let (collection_alias, sort_by) = self.get_sort_index(
|
||||
parsed.index,
|
||||
info.new_filters.as_deref(),
|
||||
&info.typesense_config,
|
||||
)?;
|
||||
let parsed = parse_search_request(info)
|
||||
.wrap_api_err("executing `parse_search_request`")?;
|
||||
let (collection_alias, sort_by) = self
|
||||
.get_sort_index(
|
||||
parsed.index,
|
||||
info.new_filters.as_deref(),
|
||||
&info.typesense_config,
|
||||
)
|
||||
.wrap_api_err("fetching sort index")?;
|
||||
let versions_alias = self.config.get_alias_name("versions");
|
||||
let filter_by = Self::build_filter(info, &versions_alias)?;
|
||||
let filter_by = Self::build_filter(info, &versions_alias)
|
||||
.wrap_api_err("executing `Self::build_filter`")?;
|
||||
|
||||
let q = if parsed.query.is_empty() {
|
||||
"*"
|
||||
|
||||
@@ -4,6 +4,8 @@ use crate::models::ids::{ProjectId, VersionId};
|
||||
use crate::models::projects::DependencyType;
|
||||
use crate::queue::server_ping;
|
||||
use crate::routes::ApiError;
|
||||
use crate::util::error::ApiContext as _;
|
||||
use crate::util::error::Context as _;
|
||||
use crate::{database::PgPool, env::ENV};
|
||||
use ariadne::ids::base62_impl::parse_base62;
|
||||
use async_trait::async_trait;
|
||||
@@ -94,10 +96,13 @@ pub trait SearchBackend: Send + Sync {
|
||||
info: &SearchRequest,
|
||||
redis: &RedisPool,
|
||||
) -> Result<SearchResults, ApiError> {
|
||||
let mut results = self.search_for_project_raw(info).await?;
|
||||
let mut results = self
|
||||
.search_for_project_raw(info)
|
||||
.await
|
||||
.wrap_api_err("searching projects")?;
|
||||
hydrate_search_results(&mut results.hits, redis)
|
||||
.await
|
||||
.map_err(ApiError::Internal)?;
|
||||
.wrap_internal_err("hydrating search results from database")?;
|
||||
Ok(results)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user