fix(analytics): retry implementation for forex crate call (#7280)

Co-authored-by: hyperswitch-bot[bot] <148525504+hyperswitch-bot[bot]@users.noreply.github.com>
Co-authored-by: Sandeep Kumar <sandeep.kumar@juspay.in>
This commit is contained in:
Shivansh Mathur
2025-03-20 19:23:04 +05:30
committed by GitHub
parent cbc262fbdf
commit e93fce26b6
2 changed files with 46 additions and 5 deletions

View File

@ -229,3 +229,6 @@ pub(crate) const PROTOCOL: &str = "ECv2";
/// Sender ID for Google Pay Decryption
pub(crate) const SENDER_ID: &[u8] = b"Google";
/// Default value for the number of attempts to retry fetching forex rates
pub const DEFAULT_ANALYTICS_FOREX_RETRY_ATTEMPTS: u64 = 3;

View File

@ -2,11 +2,13 @@ use analytics::errors::AnalyticsError;
use common_utils::errors::CustomResult;
use currency_conversion::types::ExchangeRates;
use error_stack::ResultExt;
use router_env::logger;
use crate::{
consts::DEFAULT_ANALYTICS_FOREX_RETRY_ATTEMPTS,
core::errors::ApiErrorResponse,
services::ApplicationResponse,
utils::currency::{self, convert_currency, get_forex_rates},
utils::currency::{self, convert_currency, get_forex_rates, ForexError as ForexCacheError},
SessionState,
};
@ -48,9 +50,45 @@ pub async fn get_forex_exchange_rates(
state: SessionState,
) -> CustomResult<ExchangeRates, AnalyticsError> {
let forex_api = state.conf.forex_api.get_inner();
let rates = get_forex_rates(&state, forex_api.data_expiration_delay_in_seconds)
.await
.change_context(AnalyticsError::ForexFetchFailed)?;
let mut attempt = 1;
Ok((*rates.data).clone())
logger::info!("Starting forex exchange rates fetch");
loop {
logger::info!("Attempting to fetch forex rates - Attempt {attempt} of {DEFAULT_ANALYTICS_FOREX_RETRY_ATTEMPTS}");
match get_forex_rates(&state, forex_api.data_expiration_delay_in_seconds).await {
Ok(rates) => {
logger::info!("Successfully fetched forex rates");
return Ok((*rates.data).clone());
}
Err(error) => {
let is_retryable = matches!(
error.current_context(),
ForexCacheError::CouldNotAcquireLock
| ForexCacheError::EntryNotFound
| ForexCacheError::ForexDataUnavailable
| ForexCacheError::LocalReadError
| ForexCacheError::LocalWriteError
| ForexCacheError::RedisConnectionError
| ForexCacheError::RedisLockReleaseFailed
| ForexCacheError::RedisWriteError
| ForexCacheError::WriteLockNotAcquired
);
if !is_retryable {
return Err(error.change_context(AnalyticsError::ForexFetchFailed));
}
if attempt >= DEFAULT_ANALYTICS_FOREX_RETRY_ATTEMPTS {
logger::error!("Failed to fetch forex rates after {DEFAULT_ANALYTICS_FOREX_RETRY_ATTEMPTS} attempts");
return Err(error.change_context(AnalyticsError::ForexFetchFailed));
}
logger::warn!(
"Forex rates fetch failed with retryable error, retrying in {attempt} seconds"
);
tokio::time::sleep(std::time::Duration::from_secs(attempt * 2)).await;
attempt += 1;
}
}
}
}