feat(health): Health check for Decision engine (#8243)

Co-authored-by: hyperswitch-bot[bot] <148525504+hyperswitch-bot[bot]@users.noreply.github.com>
This commit is contained in:
Sarthak Soni
2025-06-09 12:54:12 +05:30
committed by GitHub
parent 78f1a7d57f
commit 5ab769d116
4 changed files with 53 additions and 0 deletions

View File

@ -12,6 +12,8 @@ pub struct RouterHealthCheckResponse {
pub outgoing_request: bool, pub outgoing_request: bool,
#[cfg(feature = "dynamic_routing")] #[cfg(feature = "dynamic_routing")]
pub grpc_health_check: HealthCheckMap, pub grpc_health_check: HealthCheckMap,
#[cfg(feature = "dynamic_routing")]
pub decision_engine: bool,
} }
impl common_utils::events::ApiEventMetric for RouterHealthCheckResponse {} impl common_utils::events::ApiEventMetric for RouterHealthCheckResponse {}

View File

@ -35,6 +35,11 @@ pub trait HealthCheckInterface {
async fn health_check_grpc( async fn health_check_grpc(
&self, &self,
) -> CustomResult<HealthCheckMap, errors::HealthCheckGRPCServiceError>; ) -> CustomResult<HealthCheckMap, errors::HealthCheckGRPCServiceError>;
#[cfg(feature = "dynamic_routing")]
async fn health_check_decision_engine(
&self,
) -> CustomResult<HealthState, errors::HealthCheckDecisionEngineError>;
} }
#[async_trait::async_trait] #[async_trait::async_trait]
@ -184,4 +189,25 @@ impl HealthCheckInterface for app::SessionState {
logger::debug!("Health check successful"); logger::debug!("Health check successful");
Ok(health_check_map) Ok(health_check_map)
} }
#[cfg(feature = "dynamic_routing")]
async fn health_check_decision_engine(
&self,
) -> CustomResult<HealthState, errors::HealthCheckDecisionEngineError> {
if self.conf.open_router.enabled {
let url = format!("{}/{}", &self.conf.open_router.url, "health");
let request = services::Request::new(services::Method::Get, &url);
let _ = services::call_connector_api(self, request, "health_check_for_decision_engine")
.await
.change_context(
errors::HealthCheckDecisionEngineError::FailedToCallDecisionEngineService,
)?;
logger::debug!("Decision engine health check successful");
Ok(HealthState::Running)
} else {
logger::debug!("Decision engine health check not applicable");
Ok(HealthState::NotApplicable)
}
}
} }

View File

@ -108,6 +108,23 @@ async fn deep_health_check_func(
logger::debug!("gRPC health check end"); logger::debug!("gRPC health check end");
logger::debug!("Decision Engine health check begin");
#[cfg(feature = "dynamic_routing")]
let decision_engine_health_check =
state
.health_check_decision_engine()
.await
.map_err(|error| {
let message = error.to_string();
error.change_context(errors::ApiErrorResponse::HealthCheckError {
component: "Decision Engine service",
message,
})
})?;
logger::debug!("Decision Engine health check end");
logger::debug!("Opensearch health check begin"); logger::debug!("Opensearch health check begin");
#[cfg(feature = "olap")] #[cfg(feature = "olap")]
@ -144,6 +161,8 @@ async fn deep_health_check_func(
outgoing_request: outgoing_check.into(), outgoing_request: outgoing_check.into(),
#[cfg(feature = "dynamic_routing")] #[cfg(feature = "dynamic_routing")]
grpc_health_check, grpc_health_check,
#[cfg(feature = "dynamic_routing")]
decision_engine: decision_engine_health_check.into(),
}; };
Ok(api::ApplicationResponse::Json(response)) Ok(api::ApplicationResponse::Json(response))

View File

@ -280,3 +280,9 @@ pub enum RecoveryError {
#[error("Failed to fetch billing connector account id")] #[error("Failed to fetch billing connector account id")]
BillingMerchantConnectorAccountIdNotFound, BillingMerchantConnectorAccountIdNotFound,
} }
#[derive(Debug, Clone, thiserror::Error)]
pub enum HealthCheckDecisionEngineError {
#[error("Failed to establish Decision Engine connection")]
FailedToCallDecisionEngineService,
}