refactor(dynamic_routing): make the dynamo configs optional (#8589)

This commit is contained in:
Chethan Rao
2025-07-14 18:57:27 +05:30
committed by GitHub
parent 7d54ce87f0
commit 4048aa16ca
6 changed files with 62 additions and 66 deletions

View File

@ -35,7 +35,7 @@ pub type Client = hyper_util::client::legacy::Client<HttpConnector, Body>;
pub struct GrpcClients { pub struct GrpcClients {
/// The routing client /// The routing client
#[cfg(feature = "dynamic_routing")] #[cfg(feature = "dynamic_routing")]
pub dynamic_routing: RoutingStrategy, pub dynamic_routing: Option<RoutingStrategy>,
/// Health Check client for all gRPC services /// Health Check client for all gRPC services
#[cfg(feature = "dynamic_routing")] #[cfg(feature = "dynamic_routing")]
pub health_client: HealthCheckClient, pub health_client: HealthCheckClient,
@ -47,7 +47,7 @@ pub struct GrpcClients {
pub struct GrpcClientSettings { pub struct GrpcClientSettings {
#[cfg(feature = "dynamic_routing")] #[cfg(feature = "dynamic_routing")]
/// Configs for Dynamic Routing Client /// Configs for Dynamic Routing Client
pub dynamic_routing_client: DynamicRoutingClientConfig, pub dynamic_routing_client: Option<DynamicRoutingClientConfig>,
/// Configs for Unified Connector Service client /// Configs for Unified Connector Service client
pub unified_connector_service: Option<UnifiedConnectorServiceClientConfig>, pub unified_connector_service: Option<UnifiedConnectorServiceClientConfig>,
} }
@ -69,9 +69,10 @@ impl GrpcClientSettings {
let dynamic_routing_connection = self let dynamic_routing_connection = self
.dynamic_routing_client .dynamic_routing_client
.clone() .clone()
.get_dynamic_routing_connection(client.clone()) .map(|config| config.get_dynamic_routing_connection(client.clone()))
.await .transpose()
.expect("Failed to establish a connection with the Dynamic Routing Server"); .expect("Failed to establish a connection with the Dynamic Routing Server")
.flatten();
#[cfg(feature = "dynamic_routing")] #[cfg(feature = "dynamic_routing")]
let health_client = HealthCheckClient::build_connections(self, client) let health_client = HealthCheckClient::build_connections(self, client)

View File

@ -47,11 +47,11 @@ pub enum DynamicRoutingError {
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct RoutingStrategy { pub struct RoutingStrategy {
/// success rate service for Dynamic Routing /// success rate service for Dynamic Routing
pub success_rate_client: Option<SuccessRateCalculatorClient<Client>>, pub success_rate_client: SuccessRateCalculatorClient<Client>,
/// contract based routing service for Dynamic Routing /// contract based routing service for Dynamic Routing
pub contract_based_client: Option<ContractScoreCalculatorClient<Client>>, pub contract_based_client: ContractScoreCalculatorClient<Client>,
/// elimination service for Dynamic Routing /// elimination service for Dynamic Routing
pub elimination_based_client: Option<EliminationAnalyserClient<Client>>, pub elimination_based_client: EliminationAnalyserClient<Client>,
} }
/// Contains the Dynamic Routing Client Config /// Contains the Dynamic Routing Client Config
@ -74,32 +74,28 @@ pub enum DynamicRoutingClientConfig {
impl DynamicRoutingClientConfig { impl DynamicRoutingClientConfig {
/// establish connection with the server /// establish connection with the server
pub async fn get_dynamic_routing_connection( pub fn get_dynamic_routing_connection(
self, self,
client: Client, client: Client,
) -> Result<RoutingStrategy, Box<dyn std::error::Error>> { ) -> Result<Option<RoutingStrategy>, Box<dyn std::error::Error>> {
let (success_rate_client, contract_based_client, elimination_based_client) = match self { match self {
Self::Enabled { host, port, .. } => { Self::Enabled { host, port, .. } => {
let uri = format!("http://{host}:{port}").parse::<tonic::transport::Uri>()?; let uri = format!("http://{host}:{port}").parse::<tonic::transport::Uri>()?;
logger::info!("Connection established with dynamic routing gRPC Server"); logger::info!("Connection established with dynamic routing gRPC Server");
(
Some(SuccessRateCalculatorClient::with_origin( let (success_rate_client, contract_based_client, elimination_based_client) = (
client.clone(), SuccessRateCalculatorClient::with_origin(client.clone(), uri.clone()),
uri.clone(), ContractScoreCalculatorClient::with_origin(client.clone(), uri.clone()),
)), EliminationAnalyserClient::with_origin(client, uri),
Some(ContractScoreCalculatorClient::with_origin( );
client.clone(),
uri.clone(), Ok(Some(RoutingStrategy {
)), success_rate_client,
Some(EliminationAnalyserClient::with_origin(client, uri)), contract_based_client,
) elimination_based_client,
}))
} }
Self::Disabled => (None, None, None), Self::Disabled => Ok(None),
}; }
Ok(RoutingStrategy {
success_rate_client,
contract_based_client,
elimination_based_client,
})
} }
} }

View File

@ -53,11 +53,11 @@ impl HealthCheckClient {
) -> Result<Self, Box<dyn std::error::Error>> { ) -> Result<Self, Box<dyn std::error::Error>> {
let dynamic_routing_config = &config.dynamic_routing_client; let dynamic_routing_config = &config.dynamic_routing_client;
let connection = match dynamic_routing_config { let connection = match dynamic_routing_config {
DynamicRoutingClientConfig::Enabled { Some(DynamicRoutingClientConfig::Enabled {
host, host,
port, port,
service, service,
} => Some((host.clone(), *port, service.clone())), }) => Some((host.clone(), *port, service.clone())),
_ => None, _ => None,
}; };
@ -81,11 +81,11 @@ impl HealthCheckClient {
) -> HealthCheckResult<HealthCheckMap> { ) -> HealthCheckResult<HealthCheckMap> {
let dynamic_routing_config = &config.dynamic_routing_client; let dynamic_routing_config = &config.dynamic_routing_client;
let connection = match dynamic_routing_config { let connection = match dynamic_routing_config {
DynamicRoutingClientConfig::Enabled { Some(DynamicRoutingClientConfig::Enabled {
host, host,
port, port,
service, service,
} => Some((host.clone(), *port, service.clone())), }) => Some((host.clone(), *port, service.clone())),
_ => None, _ => None,
}; };

View File

@ -2100,13 +2100,13 @@ where
"performing success_based_routing for profile {}", "performing success_based_routing for profile {}",
profile_id.get_string_repr() profile_id.get_string_repr()
); );
let client = state let client = &state
.grpc_client .grpc_client
.dynamic_routing .dynamic_routing
.success_rate_client
.as_ref() .as_ref()
.ok_or(errors::RoutingError::SuccessRateClientInitializationError) .ok_or(errors::RoutingError::SuccessRateClientInitializationError)
.attach_printable("success_rate gRPC client not found")?; .attach_printable("dynamic routing gRPC client not found")?
.success_rate_client;
let success_based_routing_configs = routing::helpers::fetch_dynamic_routing_configs::< let success_based_routing_configs = routing::helpers::fetch_dynamic_routing_configs::<
api_routing::SuccessBasedRoutingConfig, api_routing::SuccessBasedRoutingConfig,
@ -2284,13 +2284,13 @@ pub async fn perform_elimination_routing(
"performing elimination_routing for profile {}", "performing elimination_routing for profile {}",
profile_id.get_string_repr() profile_id.get_string_repr()
); );
let client = state let client = &state
.grpc_client .grpc_client
.dynamic_routing .dynamic_routing
.elimination_based_client
.as_ref() .as_ref()
.ok_or(errors::RoutingError::EliminationClientInitializationError) .ok_or(errors::RoutingError::EliminationClientInitializationError)
.attach_printable("elimination routing's gRPC client not found")?; .attach_printable("dynamic routing gRPC client not found")?
.elimination_based_client;
let elimination_routing_config = routing::helpers::fetch_dynamic_routing_configs::< let elimination_routing_config = routing::helpers::fetch_dynamic_routing_configs::<
api_routing::EliminationRoutingConfig, api_routing::EliminationRoutingConfig,
@ -2484,13 +2484,13 @@ where
"performing contract_based_routing for profile {}", "performing contract_based_routing for profile {}",
profile_id.get_string_repr() profile_id.get_string_repr()
); );
let client = state let client = &state
.grpc_client .grpc_client
.dynamic_routing .dynamic_routing
.contract_based_client
.as_ref() .as_ref()
.ok_or(errors::RoutingError::ContractRoutingClientInitializationError) .ok_or(errors::RoutingError::ContractRoutingClientInitializationError)
.attach_printable("contract routing gRPC client not found")?; .attach_printable("dynamic routing gRPC client not found")?
.contract_based_client;
let contract_based_routing_configs = routing::helpers::fetch_dynamic_routing_configs::< let contract_based_routing_configs = routing::helpers::fetch_dynamic_routing_configs::<
api_routing::ContractBasedRoutingConfig, api_routing::ContractBasedRoutingConfig,

View File

@ -1848,10 +1848,10 @@ pub async fn success_based_routing_update_configs(
state state
.grpc_client .grpc_client
.dynamic_routing .dynamic_routing
.success_rate_client
.as_ref() .as_ref()
.async_map(|sr_client| async { .async_map(|dr_client| async {
sr_client dr_client
.success_rate_client
.invalidate_success_rate_routing_keys( .invalidate_success_rate_routing_keys(
profile_id.get_string_repr().into(), profile_id.get_string_repr().into(),
state.get_grpc_headers(), state.get_grpc_headers(),
@ -1952,10 +1952,10 @@ pub async fn elimination_routing_update_configs(
state state
.grpc_client .grpc_client
.dynamic_routing .dynamic_routing
.elimination_based_client
.as_ref() .as_ref()
.async_map(|er_client| async { .async_map(|dr_client| async {
er_client dr_client
.elimination_based_client
.invalidate_elimination_bucket( .invalidate_elimination_bucket(
profile_id.get_string_repr().into(), profile_id.get_string_repr().into(),
state.get_grpc_headers(), state.get_grpc_headers(),
@ -2287,12 +2287,11 @@ pub async fn contract_based_routing_update_configs(
state state
.grpc_client .grpc_client
.clone()
.dynamic_routing .dynamic_routing
.contract_based_client .as_ref()
.clone() .async_map(|dr_client| async {
.async_map(|ct_client| async move { dr_client
ct_client .contract_based_client
.invalidate_contracts( .invalidate_contracts(
profile_id.get_string_repr().into(), profile_id.get_string_repr().into(),
state.get_grpc_headers(), state.get_grpc_headers(),

View File

@ -845,14 +845,14 @@ pub async fn push_metrics_with_update_window_for_success_based_routing(
) -> RouterResult<()> { ) -> RouterResult<()> {
if let Some(success_based_algo_ref) = dynamic_routing_algo_ref.success_based_algorithm { if let Some(success_based_algo_ref) = dynamic_routing_algo_ref.success_based_algorithm {
if success_based_algo_ref.enabled_feature != routing_types::DynamicRoutingFeatures::None { if success_based_algo_ref.enabled_feature != routing_types::DynamicRoutingFeatures::None {
let client = state let client = &state
.grpc_client .grpc_client
.dynamic_routing .dynamic_routing
.success_rate_client
.as_ref() .as_ref()
.ok_or(errors::ApiErrorResponse::GenericNotFoundError { .ok_or(errors::ApiErrorResponse::GenericNotFoundError {
message: "success_rate gRPC client not found".to_string(), message: "dynamic routing gRPC client not found".to_string(),
})?; })?
.success_rate_client;
let payment_connector = &payment_attempt.connector.clone().ok_or( let payment_connector = &payment_attempt.connector.clone().ok_or(
errors::ApiErrorResponse::GenericNotFoundError { errors::ApiErrorResponse::GenericNotFoundError {
@ -1214,14 +1214,14 @@ pub async fn update_window_for_elimination_routing(
) -> RouterResult<()> { ) -> RouterResult<()> {
if let Some(elimination_algo_ref) = dynamic_algo_ref.elimination_routing_algorithm { if let Some(elimination_algo_ref) = dynamic_algo_ref.elimination_routing_algorithm {
if elimination_algo_ref.enabled_feature != routing_types::DynamicRoutingFeatures::None { if elimination_algo_ref.enabled_feature != routing_types::DynamicRoutingFeatures::None {
let client = state let client = &state
.grpc_client .grpc_client
.dynamic_routing .dynamic_routing
.elimination_based_client
.as_ref() .as_ref()
.ok_or(errors::ApiErrorResponse::GenericNotFoundError { .ok_or(errors::ApiErrorResponse::GenericNotFoundError {
message: "elimination_rate gRPC client not found".to_string(), message: "dynamic routing gRPC client not found".to_string(),
})?; })?
.elimination_based_client;
let elimination_routing_config = fetch_dynamic_routing_configs::< let elimination_routing_config = fetch_dynamic_routing_configs::<
routing_types::EliminationRoutingConfig, routing_types::EliminationRoutingConfig,
@ -1394,14 +1394,14 @@ pub async fn push_metrics_with_update_window_for_contract_based_routing(
if let Some(contract_routing_algo_ref) = dynamic_routing_algo_ref.contract_based_routing { if let Some(contract_routing_algo_ref) = dynamic_routing_algo_ref.contract_based_routing {
if contract_routing_algo_ref.enabled_feature != routing_types::DynamicRoutingFeatures::None if contract_routing_algo_ref.enabled_feature != routing_types::DynamicRoutingFeatures::None
{ {
let client = state let client = &state
.grpc_client .grpc_client
.dynamic_routing .dynamic_routing
.contract_based_client .as_ref()
.clone()
.ok_or(errors::ApiErrorResponse::GenericNotFoundError { .ok_or(errors::ApiErrorResponse::GenericNotFoundError {
message: "contract_routing gRPC client not found".to_string(), message: "dynamic routing gRPC client not found".to_string(),
})?; })?
.contract_based_client;
let payment_connector = &payment_attempt.connector.clone().ok_or( let payment_connector = &payment_attempt.connector.clone().ok_or(
errors::ApiErrorResponse::GenericNotFoundError { errors::ApiErrorResponse::GenericNotFoundError {