Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions crates/api_models/src/health_check.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ pub struct RouterHealthCheckResponse {
pub outgoing_request: bool,
#[cfg(feature = "dynamic_routing")]
pub grpc_health_check: HealthCheckMap,
#[cfg(feature = "dynamic_routing")]
pub decision_engine: bool,
}

impl common_utils::events::ApiEventMetric for RouterHealthCheckResponse {}
Expand Down
32 changes: 32 additions & 0 deletions crates/router/src/core/health_check.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,11 @@ pub trait HealthCheckInterface {
async fn health_check_grpc(
&self,
) -> CustomResult<HealthCheckMap, errors::HealthCheckGRPCServiceError>;

#[cfg(feature = "dynamic_routing")]
async fn health_check_decision_engine(
&self,
) -> CustomResult<HealthState, errors::HealthCheckDecisionEngineError>;
}

#[async_trait::async_trait]
Expand Down Expand Up @@ -184,4 +189,31 @@ impl HealthCheckInterface for app::SessionState {
logger::debug!("Health check successful");
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);
services::call_connector_api(self, request, "health_check_for_decision_engine")
.await
.change_context(
errors::HealthCheckDecisionEngineError::FailedToCallDecisionEngineService,
)?
.map_err(|err| {
logger::error!(error=?err, "Failed to call decision engine service: {:?}", err);
error_stack::report!(
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)
}
}
}
19 changes: 19 additions & 0 deletions crates/router/src/routes/health.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,23 @@ async fn deep_health_check_func(

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");

#[cfg(feature = "olap")]
Expand Down Expand Up @@ -144,6 +161,8 @@ async fn deep_health_check_func(
outgoing_request: outgoing_check.into(),
#[cfg(feature = "dynamic_routing")]
grpc_health_check,
#[cfg(feature = "dynamic_routing")]
decision_engine: decision_engine_health_check.into(),
};

Ok(api::ApplicationResponse::Json(response))
Expand Down
6 changes: 6 additions & 0 deletions crates/storage_impl/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -280,3 +280,9 @@ pub enum RecoveryError {
#[error("Failed to fetch billing connector account id")]
BillingMerchantConnectorAccountIdNotFound,
}

#[derive(Debug, Clone, thiserror::Error)]
pub enum HealthCheckDecisionEngineError {
#[error("Failed to establish Decision Engine connection")]
FailedToCallDecisionEngineService,
}
Loading