chore: add .attach_printable for InternalServerError (#368)

This commit is contained in:
Nishant Joshi
2023-01-17 17:23:57 +05:30
committed by GitHub
parent fb8d67a9f3
commit be9889b47a
14 changed files with 178 additions and 48 deletions

View File

@ -160,6 +160,10 @@ pub async fn merchant_account_update(
}
let mut response = req.clone();
let encode_error_handler =
|value: &str| format!("Unable to encode to serde_json::Value, {value}");
let updated_merchant_account = storage::MerchantAccountUpdate::Update {
merchant_id: merchant_id.to_string(),
merchant_name: req
@ -169,7 +173,8 @@ pub async fn merchant_account_update(
merchant_details: if req.merchant_details.is_some() {
Some(
utils::Encode::<api::MerchantDetails>::encode_to_value(&req.merchant_details)
.change_context(errors::ApiErrorResponse::InternalServerError)?,
.change_context(errors::ApiErrorResponse::InternalServerError)
.attach_printable_lazy(|| encode_error_handler("MerchantDetails"))?,
)
} else {
merchant_account.merchant_details.to_owned()
@ -180,7 +185,8 @@ pub async fn merchant_account_update(
webhook_details: if req.webhook_details.is_some() {
Some(
utils::Encode::<api::WebhookDetails>::encode_to_value(&req.webhook_details)
.change_context(errors::ApiErrorResponse::InternalServerError)?,
.change_context(errors::ApiErrorResponse::InternalServerError)
.attach_printable_lazy(|| encode_error_handler("WebhookDetails"))?,
)
} else {
merchant_account.webhook_details.to_owned()
@ -220,7 +226,8 @@ pub async fn merchant_account_update(
db.update_merchant(merchant_account, updated_merchant_account)
.await
.change_context(errors::ApiErrorResponse::InternalServerError)?;
.change_context(errors::ApiErrorResponse::InternalServerError)
.attach_printable_lazy(|| format!("Failed while updating merchant: {}", merchant_id))?;
Ok(service_api::ApplicationResponse::Json(response))
}
@ -297,7 +304,10 @@ pub async fn create_payment_connector(
Some(val) => {
for pm in val.into_iter() {
let pm_value = utils::Encode::<api::PaymentMethods>::encode_to_value(&pm)
.change_context(errors::ApiErrorResponse::InternalServerError)?;
.change_context(errors::ApiErrorResponse::InternalServerError)
.attach_printable(
"Failed while encoding to serde_json::Value, PaymentMethod",
)?;
vec.push(pm_value)
}
Some(vec)
@ -446,7 +456,13 @@ pub async fn update_payment_connector(
let updated_mca = db
.update_merchant_connector_account(mca, payment_connector)
.await
.change_context(errors::ApiErrorResponse::InternalServerError)?;
.change_context(errors::ApiErrorResponse::InternalServerError)
.attach_printable_lazy(|| {
format!(
"Failed while updating MerchantConnectorAccount: id: {}",
merchant_connector_id
)
})?;
let response = api::PaymentConnectorCreate {
connector_type: updated_mca.connector_type.foreign_into(),
connector_name: updated_mca.connector_name,

View File

@ -54,7 +54,8 @@ pub async fn create_customer(
..Default::default()
})
.await
.change_context(errors::ApiErrorResponse::InternalServerError)?;
.change_context(errors::ApiErrorResponse::InternalServerError)
.attach_printable("Failed while inserting new address")?;
};
let new_customer = storage::CustomerNew {
@ -74,9 +75,17 @@ pub async fn create_customer(
if error.current_context().is_db_unique_violation() {
db.find_customer_by_customer_id_merchant_id(customer_id, merchant_id)
.await
.change_context(errors::ApiErrorResponse::InternalServerError)?
.change_context(errors::ApiErrorResponse::InternalServerError)
.attach_printable_lazy(|| {
format!(
"Failed while fetching Customer, customer_id: {}",
customer_id
)
})?
} else {
Err(error.change_context(errors::ApiErrorResponse::InternalServerError))?
Err(error
.change_context(errors::ApiErrorResponse::InternalServerError)
.attach_printable("Failed while inserting new customer"))?
}
}
};
@ -252,7 +261,11 @@ pub async fn update_customer(
update_address,
)
.await
.change_context(errors::ApiErrorResponse::InternalServerError)?;
.change_context(errors::ApiErrorResponse::InternalServerError)
.attach_printable(format!(
"Failed while updating address: merchant_id: {}, customer_id: {}",
merchant_account.merchant_id, update_customer.customer_id
))?;
};
let response = db

View File

@ -70,7 +70,13 @@ pub async fn get_customer_mandates(
.store
.find_mandate_by_merchant_id_customer_id(&merchant_account.merchant_id, &req.customer_id)
.await
.change_context(errors::ApiErrorResponse::InternalServerError)?;
.change_context(errors::ApiErrorResponse::InternalServerError)
.attach_printable_lazy(|| {
format!(
"Failed while finding mandate: merchant_id: {}, customer_id: {}",
merchant_account.merchant_id, req.customer_id
)
})?;
if mandates.is_empty() {
Err(report!(errors::ApiErrorResponse::MandateNotFound).attach_printable("No Mandate found"))

View File

@ -18,7 +18,7 @@ use crate::{
storage::{self, enums},
transformers::ForeignInto,
},
utils::{BytesExt, OptionExt},
utils::{BytesExt, ConnectorResponseExt, OptionExt},
};
#[instrument(skip_all)]
@ -300,21 +300,15 @@ pub async fn get_card_from_legacy_locker<'a>(
let get_card_result = if !locker.mock_locker {
let response = services::call_connector_api(state, request)
.await
.change_context(errors::ApiErrorResponse::InternalServerError)?;
.change_context(errors::ApiErrorResponse::InternalServerError)
.attach_printable("Failed while executing call_connector_api for get_card");
match response {
Ok(card) => card
.response
.parse_struct("AddCardResponse")
.change_context(errors::ApiErrorResponse::InternalServerError)
.attach_printable("Decoding failed for AddCardResponse"),
Err(err) => Err(report!(errors::ApiErrorResponse::InternalServerError)
.attach_printable(format!("Got 4xx from the locker: {err:?}"))),
}?
response.get_response_inner("AddCardResponse")?
} else {
let (get_card_response, _) = mock_get_card(&*state.store, card_id)
.await
.change_context(errors::ApiErrorResponse::InternalServerError)?;
.change_context(errors::ApiErrorResponse::InternalServerError)
.attach_printable("Failed while fetching card from mock_locker")?;
get_card_response
};
@ -331,18 +325,17 @@ pub async fn delete_card<'a>(
let request = payment_methods::mk_delete_card_request(&state.conf.locker, merchant_id, card_id)
.change_context(errors::ApiErrorResponse::InternalServerError)
.attach_printable("Making Delete card request Failed")?;
let card_delete_failure_message = "Failed while deleting card from card_locker";
let delete_card_resp = if !locker.mock_locker {
services::call_connector_api(state, request)
.await
.change_context(errors::ApiErrorResponse::InternalServerError)?
.map_err(|_x| errors::ApiErrorResponse::InternalServerError)?
.response
.parse_struct("DeleteCardResponse")
.change_context(errors::ApiErrorResponse::InternalServerError)?
.get_response_inner("DeleteCardResponse")?
} else {
mock_delete_card(&*state.store, card_id)
.await
.change_context(errors::ApiErrorResponse::InternalServerError)?
.change_context(errors::ApiErrorResponse::InternalServerError)
.attach_printable(card_delete_failure_message)?
};
Ok(delete_card_resp)
@ -805,7 +798,8 @@ pub async fn retrieve_payment_method(
let get_card_resp =
get_card_from_legacy_locker(state, &locker_id, &pm.payment_method_id).await?;
let card_detail = payment_methods::get_card_detail(&pm, get_card_resp.card)
.change_context(errors::ApiErrorResponse::InternalServerError)?;
.change_context(errors::ApiErrorResponse::InternalServerError)
.attach_printable("Failed while getting card details from locker")?;
Some(card_detail)
} else {
None

View File

@ -88,7 +88,8 @@ where
validate_result.merchant_id,
)
.await
.change_context(errors::ApiErrorResponse::InternalServerError)?;
.change_context(errors::ApiErrorResponse::InternalServerError)
.attach_printable("Failed while fetching/creating customer")?;
let (operation, payment_method_data) = operation
.to_domain()?

View File

@ -467,7 +467,8 @@ where
)
.await
.into_report()
.change_context(errors::ApiErrorResponse::InternalServerError)?;
.change_context(errors::ApiErrorResponse::InternalServerError)
.attach_printable("Failed while getting process schedule time")?;
match schedule_time {
Some(stime) => {
@ -476,6 +477,7 @@ where
.await
.into_report()
.change_context(errors::ApiErrorResponse::InternalServerError)
.attach_printable("Failed while adding task to process tracker")
}
None => Ok(()),
}

View File

@ -83,7 +83,8 @@ impl<F: Send + Clone> GetTracker<F, PaymentData<F>, api::VerifyRequest> for Paym
let payment_id = payment_id
.get_payment_intent_id()
.change_context(errors::ApiErrorResponse::InternalServerError)?;
.change_context(errors::ApiErrorResponse::InternalServerError)
.attach_printable("Failed while getting payment_intent_id from PaymentIdType")?;
payment_attempt = match db
.insert_payment_attempt(

View File

@ -234,7 +234,13 @@ async fn get_tracker_for_sync<
let refunds = db
.find_refund_by_payment_id_merchant_id(&payment_id_str, merchant_id, storage_scheme)
.await
.change_context(errors::ApiErrorResponse::InternalServerError)?;
.change_context(errors::ApiErrorResponse::InternalServerError)
.attach_printable_lazy(|| {
format!(
"Failed while getting refund list for, payment_id: {}, merchant_id: {}",
&payment_id_str, merchant_id
)
})?;
Ok((
Box::new(operation),

View File

@ -48,7 +48,8 @@ where
let auth_type: types::ConnectorAuthType = merchant_connector_account
.connector_account_details
.parse_value("ConnectorAuthType")
.change_context(errors::ApiErrorResponse::InternalServerError)?;
.change_context(errors::ApiErrorResponse::InternalServerError)
.attach_printable("Failed while parsing value for ConnectorAuthType")?;
payment_method = payment_data
.payment_attempt

View File

@ -163,7 +163,13 @@ pub async fn trigger_refund_to_gateway(
merchant_account.storage_scheme,
)
.await
.change_context(errors::ApiErrorResponse::InternalServerError)?;
.change_context(errors::ApiErrorResponse::InternalServerError)
.attach_printable_lazy(|| {
format!(
"Failed while updating refund: refund_id: {}",
refund.refund_id
)
})?;
Ok(response)
}
@ -304,7 +310,13 @@ pub async fn sync_refund_with_gateway(
merchant_account.storage_scheme,
)
.await
.change_context(errors::ApiErrorResponse::InternalServerError)?;
.change_context(errors::ApiErrorResponse::InternalServerError)
.attach_printable_lazy(|| {
format!(
"Unable to update refund with refund_id: {}",
refund.refund_id
)
})?;
Ok(response)
}
@ -335,7 +347,10 @@ pub async fn refund_update_core(
merchant_account.storage_scheme,
)
.await
.change_context(errors::ApiErrorResponse::InternalServerError)?;
.change_context(errors::ApiErrorResponse::InternalServerError)
.attach_printable_lazy(|| {
format!("Unable to update refund with refund_id: {}", refund_id)
})?;
Ok(services::ApplicationResponse::Json(response.foreign_into()))
}
@ -382,8 +397,13 @@ pub async fn validate_and_create_refund(
merchant_account.storage_scheme,
)
.await
.change_context(errors::ApiErrorResponse::InternalServerError)?
{
.change_context(errors::ApiErrorResponse::InternalServerError)
.attach_printable_lazy(|| {
format!(
"Unique violation while checking refund_id: {} against merchant_id: {}",
refund_id, merchant_account.merchant_id
)
})? {
Some(refund) => refund,
None => {
let connecter_transaction_id = match &payment_attempt.connector_transaction_id {
@ -556,7 +576,8 @@ pub async fn schedule_refund_execution(
api_models::refunds::RefundType::Scheduled => {
add_refund_execute_task(db, &refund, runner)
.await
.change_context(errors::ApiErrorResponse::InternalServerError)?;
.change_context(errors::ApiErrorResponse::InternalServerError)
.attach_printable_lazy(|| format!("Failed while pushing refund execute task to scheduler, refund_id: {}", refund.refund_id))?;
Ok(refund)
}
@ -579,7 +600,8 @@ pub async fn schedule_refund_execution(
api_models::refunds::RefundType::Scheduled => {
add_refund_sync_task(db, &refund, runner)
.await
.change_context(errors::ApiErrorResponse::InternalServerError)?;
.change_context(errors::ApiErrorResponse::InternalServerError)
.attach_printable_lazy(|| format!("Failed while pushing refund sync task in scheduler: refund_id: {}", refund.refund_id))?;
Ok(refund)
}
api_models::refunds::RefundType::Instant => {
@ -797,7 +819,13 @@ pub async fn add_refund_sync_task(
let response = db
.insert_process(process_tracker_entry)
.await
.change_context(errors::ApiErrorResponse::InternalServerError)?;
.change_context(errors::ApiErrorResponse::InternalServerError)
.attach_printable_lazy(|| {
format!(
"Failed while inserting task in process_tracker: refund_id: {}",
refund.refund_id
)
})?;
Ok(response)
}
@ -832,7 +860,13 @@ pub async fn add_refund_execute_task(
let response = db
.insert_process(process_tracker_entry)
.await
.change_context(errors::ApiErrorResponse::InternalServerError)?;
.change_context(errors::ApiErrorResponse::InternalServerError)
.attach_printable_lazy(|| {
format!(
"Failed while inserting task in process_tracker: refund_id: {}",
refund.refund_id
)
})?;
Ok(response)
}

View File

@ -107,7 +107,9 @@ pub async fn validate_uniqueness_of_refund_id_against_merchant_id(
// to be on the safer side. Fixed this, now vector is not returned but should check the flow in detail later.
Ok(None)
} else {
Err(err.change_context(errors::ApiErrorResponse::InternalServerError))
Err(err
.change_context(errors::ApiErrorResponse::InternalServerError)
.attach_printable("Failed while finding refund, database error"))
}
}

View File

@ -126,8 +126,8 @@ impl ConnectorData {
let connector_name = api_enums::Connector::from_str(name)
.into_report()
.change_context(errors::ConnectorError::InvalidConnectorName)
.attach_printable_lazy(|| format!("unable to parse connector name {connector:?}"))
.change_context(errors::ApiErrorResponse::InternalServerError)?;
.change_context(errors::ApiErrorResponse::InternalServerError)
.attach_printable_lazy(|| format!("unable to parse connector name {connector:?}"))?;
Ok(Self {
connector,
connector_name,

View File

@ -60,7 +60,8 @@ impl MandateResponseExt for MandateResponse {
.await?;
let card_detail =
payment_methods::transformers::get_card_detail(&payment_method, get_card_resp.card)
.change_context(errors::ApiErrorResponse::InternalServerError)?;
.change_context(errors::ApiErrorResponse::InternalServerError)
.attach_printable("Failed while getting card details")?;
Some(MandateCardDetails::from(card_detail).into_inner())
} else {
None

View File

@ -11,10 +11,16 @@ pub(crate) use common_utils::{
fp_utils::when,
validation::validate_email,
};
use error_stack::{IntoReport, ResultExt};
use nanoid::nanoid;
use serde::de::DeserializeOwned;
pub(crate) use self::ext_traits::{OptionExt, ValidateCall};
use crate::consts;
use crate::{
consts,
core::errors::{self, RouterResult},
logger, types,
};
pub mod error_parser {
use std::fmt::Display;
@ -67,3 +73,50 @@ pub mod error_parser {
pub fn generate_id(length: usize, prefix: &str) -> String {
format!("{}_{}", prefix, nanoid!(length, &consts::ALPHABETS))
}
pub trait ConnectorResponseExt: Sized {
fn get_response(self) -> RouterResult<types::Response>;
fn get_error_response(self) -> RouterResult<types::Response>;
fn get_response_inner<T: DeserializeOwned>(self, type_name: &str) -> RouterResult<T> {
self.get_response()?
.response
.parse_struct(type_name)
.change_context(errors::ApiErrorResponse::InternalServerError)
}
}
impl<E> ConnectorResponseExt
for Result<Result<types::Response, types::Response>, error_stack::Report<E>>
{
fn get_error_response(self) -> RouterResult<types::Response> {
self.change_context(errors::ApiErrorResponse::InternalServerError)
.attach_printable("Error while receiving response")
.and_then(|inner| match inner {
Ok(res) => {
logger::error!(response=?res);
Err(errors::ApiErrorResponse::InternalServerError)
.into_report()
.attach_printable(format!(
"Expecting error response, received response: {res:?}"
))
}
Err(err_res) => Ok(err_res),
})
}
fn get_response(self) -> RouterResult<types::Response> {
self.change_context(errors::ApiErrorResponse::InternalServerError)
.attach_printable("Error while receiving response")
.and_then(|inner| match inner {
Err(err_res) => {
logger::error!(error_response=?err_res);
Err(errors::ApiErrorResponse::InternalServerError)
.into_report()
.attach_printable(format!(
"Expecting response, received error response: {err_res:?}"
))
}
Ok(res) => Ok(res),
})
}
}