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 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 { let updated_merchant_account = storage::MerchantAccountUpdate::Update {
merchant_id: merchant_id.to_string(), merchant_id: merchant_id.to_string(),
merchant_name: req merchant_name: req
@ -169,7 +173,8 @@ pub async fn merchant_account_update(
merchant_details: if req.merchant_details.is_some() { merchant_details: if req.merchant_details.is_some() {
Some( Some(
utils::Encode::<api::MerchantDetails>::encode_to_value(&req.merchant_details) 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 { } else {
merchant_account.merchant_details.to_owned() merchant_account.merchant_details.to_owned()
@ -180,7 +185,8 @@ pub async fn merchant_account_update(
webhook_details: if req.webhook_details.is_some() { webhook_details: if req.webhook_details.is_some() {
Some( Some(
utils::Encode::<api::WebhookDetails>::encode_to_value(&req.webhook_details) 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 { } else {
merchant_account.webhook_details.to_owned() merchant_account.webhook_details.to_owned()
@ -220,7 +226,8 @@ pub async fn merchant_account_update(
db.update_merchant(merchant_account, updated_merchant_account) db.update_merchant(merchant_account, updated_merchant_account)
.await .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)) Ok(service_api::ApplicationResponse::Json(response))
} }
@ -297,7 +304,10 @@ pub async fn create_payment_connector(
Some(val) => { Some(val) => {
for pm in val.into_iter() { for pm in val.into_iter() {
let pm_value = utils::Encode::<api::PaymentMethods>::encode_to_value(&pm) 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) vec.push(pm_value)
} }
Some(vec) Some(vec)
@ -446,7 +456,13 @@ pub async fn update_payment_connector(
let updated_mca = db let updated_mca = db
.update_merchant_connector_account(mca, payment_connector) .update_merchant_connector_account(mca, payment_connector)
.await .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 { let response = api::PaymentConnectorCreate {
connector_type: updated_mca.connector_type.foreign_into(), connector_type: updated_mca.connector_type.foreign_into(),
connector_name: updated_mca.connector_name, connector_name: updated_mca.connector_name,

View File

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

View File

@ -70,7 +70,13 @@ pub async fn get_customer_mandates(
.store .store
.find_mandate_by_merchant_id_customer_id(&merchant_account.merchant_id, &req.customer_id) .find_mandate_by_merchant_id_customer_id(&merchant_account.merchant_id, &req.customer_id)
.await .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() { if mandates.is_empty() {
Err(report!(errors::ApiErrorResponse::MandateNotFound).attach_printable("No Mandate found")) Err(report!(errors::ApiErrorResponse::MandateNotFound).attach_printable("No Mandate found"))

View File

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

View File

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

View File

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

View File

@ -234,7 +234,13 @@ async fn get_tracker_for_sync<
let refunds = db let refunds = db
.find_refund_by_payment_id_merchant_id(&payment_id_str, merchant_id, storage_scheme) .find_refund_by_payment_id_merchant_id(&payment_id_str, merchant_id, storage_scheme)
.await .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(( Ok((
Box::new(operation), Box::new(operation),

View File

@ -48,7 +48,8 @@ where
let auth_type: types::ConnectorAuthType = merchant_connector_account let auth_type: types::ConnectorAuthType = merchant_connector_account
.connector_account_details .connector_account_details
.parse_value("ConnectorAuthType") .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_method = payment_data
.payment_attempt .payment_attempt

View File

@ -163,7 +163,13 @@ pub async fn trigger_refund_to_gateway(
merchant_account.storage_scheme, merchant_account.storage_scheme,
) )
.await .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) Ok(response)
} }
@ -304,7 +310,13 @@ pub async fn sync_refund_with_gateway(
merchant_account.storage_scheme, merchant_account.storage_scheme,
) )
.await .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) Ok(response)
} }
@ -335,7 +347,10 @@ pub async fn refund_update_core(
merchant_account.storage_scheme, merchant_account.storage_scheme,
) )
.await .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())) Ok(services::ApplicationResponse::Json(response.foreign_into()))
} }
@ -382,8 +397,13 @@ pub async fn validate_and_create_refund(
merchant_account.storage_scheme, merchant_account.storage_scheme,
) )
.await .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, Some(refund) => refund,
None => { None => {
let connecter_transaction_id = match &payment_attempt.connector_transaction_id { 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 => { api_models::refunds::RefundType::Scheduled => {
add_refund_execute_task(db, &refund, runner) add_refund_execute_task(db, &refund, runner)
.await .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) Ok(refund)
} }
@ -579,7 +600,8 @@ pub async fn schedule_refund_execution(
api_models::refunds::RefundType::Scheduled => { api_models::refunds::RefundType::Scheduled => {
add_refund_sync_task(db, &refund, runner) add_refund_sync_task(db, &refund, runner)
.await .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) Ok(refund)
} }
api_models::refunds::RefundType::Instant => { api_models::refunds::RefundType::Instant => {
@ -797,7 +819,13 @@ pub async fn add_refund_sync_task(
let response = db let response = db
.insert_process(process_tracker_entry) .insert_process(process_tracker_entry)
.await .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) Ok(response)
} }
@ -832,7 +860,13 @@ pub async fn add_refund_execute_task(
let response = db let response = db
.insert_process(process_tracker_entry) .insert_process(process_tracker_entry)
.await .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) 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. // to be on the safer side. Fixed this, now vector is not returned but should check the flow in detail later.
Ok(None) Ok(None)
} else { } 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) let connector_name = api_enums::Connector::from_str(name)
.into_report() .into_report()
.change_context(errors::ConnectorError::InvalidConnectorName) .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 { Ok(Self {
connector, connector,
connector_name, connector_name,

View File

@ -60,7 +60,8 @@ impl MandateResponseExt for MandateResponse {
.await?; .await?;
let card_detail = let card_detail =
payment_methods::transformers::get_card_detail(&payment_method, get_card_resp.card) 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()) Some(MandateCardDetails::from(card_detail).into_inner())
} else { } else {
None None

View File

@ -11,10 +11,16 @@ pub(crate) use common_utils::{
fp_utils::when, fp_utils::when,
validation::validate_email, validation::validate_email,
}; };
use error_stack::{IntoReport, ResultExt};
use nanoid::nanoid; use nanoid::nanoid;
use serde::de::DeserializeOwned;
pub(crate) use self::ext_traits::{OptionExt, ValidateCall}; pub(crate) use self::ext_traits::{OptionExt, ValidateCall};
use crate::consts; use crate::{
consts,
core::errors::{self, RouterResult},
logger, types,
};
pub mod error_parser { pub mod error_parser {
use std::fmt::Display; use std::fmt::Display;
@ -67,3 +73,50 @@ pub mod error_parser {
pub fn generate_id(length: usize, prefix: &str) -> String { pub fn generate_id(length: usize, prefix: &str) -> String {
format!("{}_{}", prefix, nanoid!(length, &consts::ALPHABETS)) 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),
})
}
}