Skip to content

Commit

Permalink
Update error handling
Browse files Browse the repository at this point in the history
  • Loading branch information
rimrakhimov committed Aug 28, 2023
1 parent a1368fe commit f8abea6
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 25 deletions.
51 changes: 34 additions & 17 deletions libs/sourcify/src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,7 @@ use reqwest::{Response, StatusCode};
use reqwest_middleware::{ClientWithMiddleware, Middleware};
use reqwest_retry::{policies::ExponentialBackoff, RetryTransientMiddleware};
use serde::{Deserialize, Serialize};
use std::{str::FromStr};
use std::sync::Arc;
use std::{str::FromStr, sync::Arc};
use url::Url;

#[derive(Clone)]
Expand Down Expand Up @@ -175,6 +174,14 @@ impl Client {
Err(Error::Sourcify(SourcifyError::BadRequest(message)))
}
}
StatusCode::BAD_GATEWAY => {
let message = error_message(response).await?;
if let Some(err) = E::handle_bad_gateway(&message) {
Err(Error::Sourcify(SourcifyError::Custom(err)))
} else {
Err(Error::Sourcify(SourcifyError::BadGateway(message)))
}
}
StatusCode::INTERNAL_SERVER_ERROR => {
let message = error_message(response).await?;
if let Some(err) = E::handle_internal_server_error(&message) {
Expand Down Expand Up @@ -206,32 +213,42 @@ impl Client {

#[cfg(test)]
mod tests {
use std::num::NonZeroU32;
use super::*;
use serde_json::json;
use reqwest_rate_limiter::RateLimiterMiddleware;
use governor::{RateLimiter, Quota};
use governor::clock::DefaultClock;
use governor::middleware::NoOpMiddleware;
use governor::state::{InMemoryState, NotKeyed};
use governor::{
clock::DefaultClock,
middleware::NoOpMiddleware,
state::{InMemoryState, NotKeyed},
Quota, RateLimiter,
};
use once_cell::sync::OnceCell;
use reqwest_rate_limiter::RateLimiterMiddleware;
use serde_json::json;
use std::num::NonZeroU32;

fn parse_contract_address(contract_address: &str) -> Bytes {
DisplayBytes::from_str(contract_address).unwrap().0
}

static RATE_LIMITER_MIDDLEWARE: OnceCell<Arc<RateLimiterMiddleware<NotKeyed, InMemoryState, DefaultClock, NoOpMiddleware>>> = OnceCell::new();
fn rate_limiter_middleware() -> &'static Arc<RateLimiterMiddleware<NotKeyed, InMemoryState, DefaultClock, NoOpMiddleware>> {
RATE_LIMITER_MIDDLEWARE
.get_or_init(|| {
let max_burst = NonZeroU32::new(1).unwrap();
Arc::new(RateLimiterMiddleware::new(RateLimiter::direct(Quota::per_second(max_burst))))
})
static RATE_LIMITER_MIDDLEWARE: OnceCell<
Arc<RateLimiterMiddleware<NotKeyed, InMemoryState, DefaultClock, NoOpMiddleware>>,
> = OnceCell::new();
fn rate_limiter_middleware(
) -> &'static Arc<RateLimiterMiddleware<NotKeyed, InMemoryState, DefaultClock, NoOpMiddleware>>
{
RATE_LIMITER_MIDDLEWARE.get_or_init(|| {
let max_burst = NonZeroU32::new(1).unwrap();
Arc::new(RateLimiterMiddleware::new(RateLimiter::direct(
Quota::per_second(max_burst),
)))
})
}

fn client() -> Client {
let rate_limiter = rate_limiter_middleware().clone();
ClientBuilder::default().max_retries(1).with_arc_middleware(rate_limiter).build()
ClientBuilder::default()
.max_retries(1)
.with_arc_middleware(rate_limiter)
.build()
}

mod success {
Expand Down
2 changes: 2 additions & 0 deletions libs/sourcify/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ pub enum SourcifyError<E: std::error::Error> {
NotFound(String),
#[error("'Bad Request': {0}")]
BadRequest(String),
#[error("'Bad Gateway': {0}")]
BadGateway(String),
#[error("unexpected status code: {status_code} - {msg}")]
UnexpectedStatusCode {
status_code: reqwest::StatusCode,
Expand Down
26 changes: 18 additions & 8 deletions libs/sourcify/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ mod custom_error {
None
}

fn handle_bad_gateway(_message: &str) -> Option<Self> {
None
}

fn handle_internal_server_error(_message: &str) -> Option<Self> {
None
}
Expand Down Expand Up @@ -285,26 +289,32 @@ mod verify_from_etherscan {
));
}

if message.contains("Error in Etherscan API response") {
return Some(VerifyFromEtherscanError::ApiResponseError(
if message.contains("cannot generate the solcJsonInput") {
return Some(VerifyFromEtherscanError::CannotGenerateSolcJsonInput(
message.to_string(),
));
}

if message.contains("contract is not verified on Etherscan") {
return Some(VerifyFromEtherscanError::ContractNotVerified(
if message.contains("contract was verified with errors") {
return Some(VerifyFromEtherscanError::VerifiedWithErrors(
message.to_string(),
));
}

if message.contains("cannot generate the solcJsonInput") {
return Some(VerifyFromEtherscanError::CannotGenerateSolcJsonInput(
None
}

fn handle_bad_gateway(message: &str) -> Option<Self> {
if (message.contains("Request to") && message.contains("apiKey=XXX failed with code"))
|| message.contains("Error in Etherscan API response")
{
return Some(VerifyFromEtherscanError::ApiResponseError(
message.to_string(),
));
}

if message.contains("contract was verified with errors") {
return Some(VerifyFromEtherscanError::VerifiedWithErrors(
if message.contains("contract is not verified on Etherscan") {
return Some(VerifyFromEtherscanError::ContractNotVerified(
message.to_string(),
));
}
Expand Down

0 comments on commit f8abea6

Please sign in to comment.