From 74bfc872cd99b5e2824c407768ad29afc1501b27 Mon Sep 17 00:00:00 2001 From: Jiahao XU Date: Mon, 6 May 2024 22:42:35 +1000 Subject: [PATCH] Refactor: Extract new mod error Signed-off-by: Jiahao XU --- .../src/gh_api_client.rs | 4 +- .../src/gh_api_client/request.rs | 142 +----------------- 2 files changed, 8 insertions(+), 138 deletions(-) diff --git a/crates/binstalk-git-repo-api/src/gh_api_client.rs b/crates/binstalk-git-repo-api/src/gh_api_client.rs index d6655c4ce..23b9194ec 100644 --- a/crates/binstalk-git-repo-api/src/gh_api_client.rs +++ b/crates/binstalk-git-repo-api/src/gh_api_client.rs @@ -16,7 +16,9 @@ use percent_encoding::{ use tokio::sync::OnceCell; mod request; -pub use request::{GhApiContextError, GhApiError, GhGraphQLErrors}; + +mod error; +pub use error::{GhApiContextError, GhApiError, GhGraphQLErrors}; /// default retry duration if x-ratelimit-reset is not found in response header const DEFAULT_RETRY_DURATION: Duration = Duration::from_secs(10 * 60); diff --git a/crates/binstalk-git-repo-api/src/gh_api_client/request.rs b/crates/binstalk-git-repo-api/src/gh_api_client/request.rs index d226d819f..ff73c17a4 100644 --- a/crates/binstalk-git-repo-api/src/gh_api_client/request.rs +++ b/crates/binstalk-git-repo-api/src/gh_api_client/request.rs @@ -1,59 +1,19 @@ use std::{ borrow::Borrow, collections::HashSet, - error, fmt, + fmt, hash::{Hash, Hasher}, - io, sync::OnceLock, time::Duration, }; use binstalk_downloader::remote::{header::HeaderMap, StatusCode, Url}; -use compact_str::{CompactString, ToCompactString}; -use serde::{de::Deserializer, Deserialize, Serialize}; +use compact_str::CompactString; +use serde::{Deserialize, Serialize}; use serde_json::to_string as to_json_string; -use thiserror::Error as ThisError; use tracing::debug; -use super::{percent_encode_http_url_path, remote, GhRelease}; - -#[derive(ThisError, Debug)] -#[error("Context: '{context}', err: '{err}'")] -pub struct GhApiContextError { - context: CompactString, - #[source] - err: GhApiError, -} - -#[derive(ThisError, Debug)] -#[non_exhaustive] -pub enum GhApiError { - #[error("IO Error: {0}")] - Io(#[from] io::Error), - - #[error("Remote Error: {0}")] - Remote(#[from] remote::Error), - - #[error("Failed to parse url: {0}")] - InvalidUrl(#[from] url::ParseError), - - /// A wrapped error providing the context the error is about. - #[error(transparent)] - Context(Box), - - #[error("Remote failed to process GraphQL query: {0}")] - GraphQLErrors(#[from] GhGraphQLErrors), -} - -impl GhApiError { - /// Attach context to [`GhApiError`] - pub fn context(self, context: impl fmt::Display) -> Self { - Self::Context(Box::new(GhApiContextError { - context: context.to_compact_string(), - err: self, - })) - } -} +use super::{percent_encode_http_url_path, remote, GhApiError, GhGraphQLErrors, GhRelease}; // Only include fields we do care about @@ -169,99 +129,6 @@ enum GraphQLResponse { Errors(GhGraphQLErrors), } -#[derive(Debug, Deserialize)] -pub struct GhGraphQLErrors(Box<[GraphQLError]>); - -impl GhGraphQLErrors { - fn is_rate_limited(&self) -> bool { - self.0 - .iter() - .any(|error| matches!(error.error_type, GraphQLErrorType::RateLimited)) - } -} - -impl error::Error for GhGraphQLErrors {} - -impl fmt::Display for GhGraphQLErrors { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let last_error_index = self.0.len() - 1; - - for (i, error) in self.0.iter().enumerate() { - write!( - f, - "type: '{error_type}', msg: '{msg}'", - error_type = error.error_type, - msg = error.message, - )?; - - for location in error.locations.as_deref().into_iter().flatten() { - write!( - f, - ", occured on query line {line} col {col}", - line = location.line, - col = location.column - )?; - } - - for (k, v) in &error.others { - write!(f, ", {k}: {v}")?; - } - - if i < last_error_index { - f.write_str("\n")?; - } - } - - Ok(()) - } -} - -#[derive(Debug, Deserialize)] -struct GraphQLError { - message: CompactString, - locations: Option>, - - #[serde(rename = "type")] - error_type: GraphQLErrorType, - - #[serde(flatten, with = "tuple_vec_map")] - others: Vec<(CompactString, serde_json::Value)>, -} - -#[derive(Debug)] -enum GraphQLErrorType { - RateLimited, - Other(CompactString), -} - -impl fmt::Display for GraphQLErrorType { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.write_str(match self { - GraphQLErrorType::RateLimited => "RATE_LIMITED", - GraphQLErrorType::Other(s) => s, - }) - } -} - -impl<'de> Deserialize<'de> for GraphQLErrorType { - fn deserialize(deserializer: D) -> Result - where - D: Deserializer<'de>, - { - let s = CompactString::deserialize(deserializer)?; - Ok(match &*s { - "RATE_LIMITED" => GraphQLErrorType::RateLimited, - _ => GraphQLErrorType::Other(s), - }) - } -} - -#[derive(Debug, Deserialize)] -struct GraphQLLocation { - line: u64, - column: u64, -} - #[derive(Deserialize)] struct GraphQLData { repository: Option, @@ -415,6 +282,7 @@ pub(super) async fn fetch_release_artifacts( #[cfg(test)] mod test { use super::*; + use crate::gh_api_client::error::GraphQLErrorType; use serde::de::value::{BorrowedStrDeserializer, Error}; macro_rules! assert_matches {