mirror of
https://github.com/juspay/hyperswitch.git
synced 2025-10-29 09:07:09 +08:00
feat(v2): introduce configs and health endpoints for v2 (#8835)
This commit is contained in:
@ -14,6 +14,7 @@ pub struct RouterHealthCheckResponse {
|
|||||||
pub grpc_health_check: HealthCheckMap,
|
pub grpc_health_check: HealthCheckMap,
|
||||||
#[cfg(feature = "dynamic_routing")]
|
#[cfg(feature = "dynamic_routing")]
|
||||||
pub decision_engine: bool,
|
pub decision_engine: bool,
|
||||||
|
pub unified_connector_service: Option<bool>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl common_utils::events::ApiEventMetric for RouterHealthCheckResponse {}
|
impl common_utils::events::ApiEventMetric for RouterHealthCheckResponse {}
|
||||||
|
|||||||
@ -40,6 +40,10 @@ pub trait HealthCheckInterface {
|
|||||||
async fn health_check_decision_engine(
|
async fn health_check_decision_engine(
|
||||||
&self,
|
&self,
|
||||||
) -> CustomResult<HealthState, errors::HealthCheckDecisionEngineError>;
|
) -> CustomResult<HealthState, errors::HealthCheckDecisionEngineError>;
|
||||||
|
|
||||||
|
async fn health_check_unified_connector_service(
|
||||||
|
&self,
|
||||||
|
) -> CustomResult<HealthState, errors::HealthCheckUnifiedConnectorServiceError>;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_trait::async_trait]
|
#[async_trait::async_trait]
|
||||||
@ -210,4 +214,19 @@ impl HealthCheckInterface for app::SessionState {
|
|||||||
Ok(HealthState::NotApplicable)
|
Ok(HealthState::NotApplicable)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn health_check_unified_connector_service(
|
||||||
|
&self,
|
||||||
|
) -> CustomResult<HealthState, errors::HealthCheckUnifiedConnectorServiceError> {
|
||||||
|
if let Some(_ucs_client) = &self.grpc_client.unified_connector_service_client {
|
||||||
|
// For now, we'll just check if the client exists and is configured
|
||||||
|
// In the future, this could be enhanced to make an actual health check call
|
||||||
|
// to the unified connector service if it supports health check endpoints
|
||||||
|
logger::debug!("Unified Connector Service client is configured and available");
|
||||||
|
Ok(HealthState::Running)
|
||||||
|
} else {
|
||||||
|
logger::debug!("Unified Connector Service client not configured");
|
||||||
|
Ok(HealthState::NotApplicable)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -565,6 +565,7 @@ impl AppState {
|
|||||||
|
|
||||||
pub struct Health;
|
pub struct Health;
|
||||||
|
|
||||||
|
#[cfg(feature = "v1")]
|
||||||
impl Health {
|
impl Health {
|
||||||
pub fn server(state: AppState) -> Scope {
|
pub fn server(state: AppState) -> Scope {
|
||||||
web::scope("health")
|
web::scope("health")
|
||||||
@ -574,6 +575,16 @@ impl Health {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "v2")]
|
||||||
|
impl Health {
|
||||||
|
pub fn server(state: AppState) -> Scope {
|
||||||
|
web::scope("/v2/health")
|
||||||
|
.app_data(web::Data::new(state))
|
||||||
|
.service(web::resource("").route(web::get().to(health)))
|
||||||
|
.service(web::resource("/ready").route(web::get().to(deep_health_check)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(feature = "dummy_connector")]
|
#[cfg(feature = "dummy_connector")]
|
||||||
pub struct DummyConnector;
|
pub struct DummyConnector;
|
||||||
|
|
||||||
@ -1867,7 +1878,7 @@ impl Webhooks {
|
|||||||
|
|
||||||
pub struct Configs;
|
pub struct Configs;
|
||||||
|
|
||||||
#[cfg(any(feature = "olap", feature = "oltp"))]
|
#[cfg(all(feature = "v1", any(feature = "olap", feature = "oltp")))]
|
||||||
impl Configs {
|
impl Configs {
|
||||||
pub fn server(config: AppState) -> Scope {
|
pub fn server(config: AppState) -> Scope {
|
||||||
web::scope("/configs")
|
web::scope("/configs")
|
||||||
@ -1882,6 +1893,21 @@ impl Configs {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(all(feature = "v2", any(feature = "olap", feature = "oltp")))]
|
||||||
|
impl Configs {
|
||||||
|
pub fn server(config: AppState) -> Scope {
|
||||||
|
web::scope("/v2/configs")
|
||||||
|
.app_data(web::Data::new(config))
|
||||||
|
.service(web::resource("/").route(web::post().to(config_key_create)))
|
||||||
|
.service(
|
||||||
|
web::resource("/{key}")
|
||||||
|
.route(web::get().to(config_key_retrieve))
|
||||||
|
.route(web::post().to(config_key_update))
|
||||||
|
.route(web::delete().to(config_key_delete)),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub struct ApplePayCertificatesMigration;
|
pub struct ApplePayCertificatesMigration;
|
||||||
|
|
||||||
#[cfg(all(feature = "olap", feature = "v1"))]
|
#[cfg(all(feature = "olap", feature = "v1"))]
|
||||||
|
|||||||
@ -8,6 +8,11 @@ use crate::{
|
|||||||
types::api as api_types,
|
types::api as api_types,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#[cfg(feature = "v1")]
|
||||||
|
const ADMIN_API_AUTH: auth::AdminApiAuth = auth::AdminApiAuth;
|
||||||
|
#[cfg(feature = "v2")]
|
||||||
|
const ADMIN_API_AUTH: auth::V2AdminApiAuth = auth::V2AdminApiAuth;
|
||||||
|
|
||||||
#[instrument(skip_all, fields(flow = ?Flow::CreateConfigKey))]
|
#[instrument(skip_all, fields(flow = ?Flow::CreateConfigKey))]
|
||||||
pub async fn config_key_create(
|
pub async fn config_key_create(
|
||||||
state: web::Data<AppState>,
|
state: web::Data<AppState>,
|
||||||
@ -23,7 +28,7 @@ pub async fn config_key_create(
|
|||||||
&req,
|
&req,
|
||||||
payload,
|
payload,
|
||||||
|state, _, data, _| configs::set_config(state, data),
|
|state, _, data, _| configs::set_config(state, data),
|
||||||
&auth::AdminApiAuth,
|
&ADMIN_API_AUTH,
|
||||||
api_locking::LockAction::NotApplicable,
|
api_locking::LockAction::NotApplicable,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
@ -43,7 +48,7 @@ pub async fn config_key_retrieve(
|
|||||||
&req,
|
&req,
|
||||||
&key,
|
&key,
|
||||||
|state, _, key, _| configs::read_config(state, key),
|
|state, _, key, _| configs::read_config(state, key),
|
||||||
&auth::AdminApiAuth,
|
&ADMIN_API_AUTH,
|
||||||
api_locking::LockAction::NotApplicable,
|
api_locking::LockAction::NotApplicable,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
@ -66,7 +71,7 @@ pub async fn config_key_update(
|
|||||||
&req,
|
&req,
|
||||||
&payload,
|
&payload,
|
||||||
|state, _, payload, _| configs::update_config(state, payload),
|
|state, _, payload, _| configs::update_config(state, payload),
|
||||||
&auth::AdminApiAuth,
|
&ADMIN_API_AUTH,
|
||||||
api_locking::LockAction::NotApplicable,
|
api_locking::LockAction::NotApplicable,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
@ -87,7 +92,7 @@ pub async fn config_key_delete(
|
|||||||
&req,
|
&req,
|
||||||
key,
|
key,
|
||||||
|state, _, key, _| configs::config_delete(state, key),
|
|state, _, key, _| configs::config_delete(state, key),
|
||||||
&auth::AdminApiAuth,
|
&ADMIN_API_AUTH,
|
||||||
api_locking::LockAction::NotApplicable,
|
api_locking::LockAction::NotApplicable,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
|
|||||||
@ -150,6 +150,21 @@ async fn deep_health_check_func(
|
|||||||
|
|
||||||
logger::debug!("Outgoing Request health check end");
|
logger::debug!("Outgoing Request health check end");
|
||||||
|
|
||||||
|
logger::debug!("Unified Connector Service health check begin");
|
||||||
|
|
||||||
|
let unified_connector_service_status = state
|
||||||
|
.health_check_unified_connector_service()
|
||||||
|
.await
|
||||||
|
.map_err(|error| {
|
||||||
|
let message = error.to_string();
|
||||||
|
error.change_context(errors::ApiErrorResponse::HealthCheckError {
|
||||||
|
component: "Unified Connector Service",
|
||||||
|
message,
|
||||||
|
})
|
||||||
|
})?;
|
||||||
|
|
||||||
|
logger::debug!("Unified Connector Service health check end");
|
||||||
|
|
||||||
let response = RouterHealthCheckResponse {
|
let response = RouterHealthCheckResponse {
|
||||||
database: db_status.into(),
|
database: db_status.into(),
|
||||||
redis: redis_status.into(),
|
redis: redis_status.into(),
|
||||||
@ -163,6 +178,7 @@ async fn deep_health_check_func(
|
|||||||
grpc_health_check,
|
grpc_health_check,
|
||||||
#[cfg(feature = "dynamic_routing")]
|
#[cfg(feature = "dynamic_routing")]
|
||||||
decision_engine: decision_engine_health_check.into(),
|
decision_engine: decision_engine_health_check.into(),
|
||||||
|
unified_connector_service: unified_connector_service_status.into(),
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(api::ApplicationResponse::Json(response))
|
Ok(api::ApplicationResponse::Json(response))
|
||||||
|
|||||||
@ -294,3 +294,9 @@ pub enum HealthCheckDecisionEngineError {
|
|||||||
#[error("Failed to establish Decision Engine connection")]
|
#[error("Failed to establish Decision Engine connection")]
|
||||||
FailedToCallDecisionEngineService,
|
FailedToCallDecisionEngineService,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, thiserror::Error)]
|
||||||
|
pub enum HealthCheckUnifiedConnectorServiceError {
|
||||||
|
#[error("Failed to establish Unified Connector Service connection")]
|
||||||
|
FailedToCallUnifiedConnectorService,
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user