mirror of
https://github.com/juspay/hyperswitch.git
synced 2025-10-29 17:19:15 +08:00
feat(dynamic_routing): add get api for dynamic routing volume split (#8114)
Co-authored-by: hyperswitch-bot[bot] <148525504+hyperswitch-bot[bot]@users.noreply.github.com>
This commit is contained in:
@ -26254,6 +26254,19 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"RoutingVolumeSplitResponse": {
|
||||||
|
"type": "object",
|
||||||
|
"required": [
|
||||||
|
"split"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"split": {
|
||||||
|
"type": "integer",
|
||||||
|
"format": "int32",
|
||||||
|
"minimum": 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"RuleConnectorSelection": {
|
"RuleConnectorSelection": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"description": "Represents a rule\n\n```text\nrule_name: [stripe, adyen, checkout]\n{\npayment.method = card {\npayment.method.cardtype = (credit, debit) {\npayment.method.network = (amex, rupay, diners)\n}\n\npayment.method.cardtype = credit\n}\n}\n```",
|
"description": "Represents a rule\n\n```text\nrule_name: [stripe, adyen, checkout]\n{\npayment.method = card {\npayment.method.cardtype = (credit, debit) {\npayment.method.network = (amex, rupay, diners)\n}\n\npayment.method.cardtype = credit\n}\n}\n```",
|
||||||
|
|||||||
@ -7,8 +7,9 @@ use crate::routing::{
|
|||||||
RoutingAlgorithmId, RoutingConfigRequest, RoutingDictionaryRecord, RoutingKind,
|
RoutingAlgorithmId, RoutingConfigRequest, RoutingDictionaryRecord, RoutingKind,
|
||||||
RoutingLinkWrapper, RoutingPayloadWrapper, RoutingRetrieveLinkQuery,
|
RoutingLinkWrapper, RoutingPayloadWrapper, RoutingRetrieveLinkQuery,
|
||||||
RoutingRetrieveLinkQueryWrapper, RoutingRetrieveQuery, RoutingVolumeSplit,
|
RoutingRetrieveLinkQueryWrapper, RoutingRetrieveQuery, RoutingVolumeSplit,
|
||||||
RoutingVolumeSplitWrapper, SuccessBasedRoutingConfig, SuccessBasedRoutingPayloadWrapper,
|
RoutingVolumeSplitResponse, RoutingVolumeSplitWrapper, SuccessBasedRoutingConfig,
|
||||||
ToggleDynamicRoutingQuery, ToggleDynamicRoutingWrapper,
|
SuccessBasedRoutingPayloadWrapper, ToggleDynamicRoutingPath, ToggleDynamicRoutingQuery,
|
||||||
|
ToggleDynamicRoutingWrapper,
|
||||||
};
|
};
|
||||||
|
|
||||||
impl ApiEventMetric for RoutingKind {
|
impl ApiEventMetric for RoutingKind {
|
||||||
@ -135,6 +136,18 @@ impl ApiEventMetric for RoutingVolumeSplitWrapper {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl ApiEventMetric for ToggleDynamicRoutingPath {
|
||||||
|
fn get_api_event_type(&self) -> Option<ApiEventsType> {
|
||||||
|
Some(ApiEventsType::Routing)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ApiEventMetric for RoutingVolumeSplitResponse {
|
||||||
|
fn get_api_event_type(&self) -> Option<ApiEventsType> {
|
||||||
|
Some(ApiEventsType::Routing)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl ApiEventMetric for RoutingVolumeSplit {
|
impl ApiEventMetric for RoutingVolumeSplit {
|
||||||
fn get_api_event_type(&self) -> Option<ApiEventsType> {
|
fn get_api_event_type(&self) -> Option<ApiEventsType> {
|
||||||
Some(ApiEventsType::Routing)
|
Some(ApiEventsType::Routing)
|
||||||
|
|||||||
@ -857,6 +857,11 @@ pub struct ToggleDynamicRoutingPath {
|
|||||||
pub profile_id: common_utils::id_type::ProfileId,
|
pub profile_id: common_utils::id_type::ProfileId,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize, ToSchema)]
|
||||||
|
pub struct RoutingVolumeSplitResponse {
|
||||||
|
pub split: u8,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone, ToSchema)]
|
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone, ToSchema)]
|
||||||
#[serde(deny_unknown_fields)]
|
#[serde(deny_unknown_fields)]
|
||||||
pub struct EliminationRoutingConfig {
|
pub struct EliminationRoutingConfig {
|
||||||
|
|||||||
@ -671,6 +671,7 @@ Never share your secret api keys. Keep them guarded and secure.
|
|||||||
api_models::routing::SuccessRateSpecificityLevel,
|
api_models::routing::SuccessRateSpecificityLevel,
|
||||||
api_models::routing::ToggleDynamicRoutingQuery,
|
api_models::routing::ToggleDynamicRoutingQuery,
|
||||||
api_models::routing::ToggleDynamicRoutingPath,
|
api_models::routing::ToggleDynamicRoutingPath,
|
||||||
|
api_models::routing::RoutingVolumeSplitResponse,
|
||||||
api_models::routing::ast::RoutableChoiceKind,
|
api_models::routing::ast::RoutableChoiceKind,
|
||||||
api_models::enums::RoutableConnectors,
|
api_models::enums::RoutableConnectors,
|
||||||
api_models::routing::ast::ProgramConnectorSelection,
|
api_models::routing::ast::ProgramConnectorSelection,
|
||||||
|
|||||||
@ -1554,6 +1554,48 @@ pub async fn configure_dynamic_routing_volume_split(
|
|||||||
Ok(service_api::ApplicationResponse::Json(routing_info))
|
Ok(service_api::ApplicationResponse::Json(routing_info))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "v1")]
|
||||||
|
pub async fn retrieve_dynamic_routing_volume_split(
|
||||||
|
state: SessionState,
|
||||||
|
merchant_context: domain::MerchantContext,
|
||||||
|
profile_id: common_utils::id_type::ProfileId,
|
||||||
|
) -> RouterResponse<routing_types::RoutingVolumeSplitResponse> {
|
||||||
|
let db = state.store.as_ref();
|
||||||
|
let key_manager_state = &(&state).into();
|
||||||
|
|
||||||
|
let business_profile: domain::Profile = core_utils::validate_and_get_business_profile(
|
||||||
|
db,
|
||||||
|
key_manager_state,
|
||||||
|
merchant_context.get_merchant_key_store(),
|
||||||
|
Some(&profile_id),
|
||||||
|
merchant_context.get_merchant_account().get_id(),
|
||||||
|
)
|
||||||
|
.await?
|
||||||
|
.get_required_value("Profile")
|
||||||
|
.change_context(errors::ApiErrorResponse::ProfileNotFound {
|
||||||
|
id: profile_id.get_string_repr().to_owned(),
|
||||||
|
})?;
|
||||||
|
|
||||||
|
let dynamic_routing_algo_ref: routing_types::DynamicRoutingAlgorithmRef = business_profile
|
||||||
|
.dynamic_routing_algorithm
|
||||||
|
.clone()
|
||||||
|
.map(|val| val.parse_value("DynamicRoutingAlgorithmRef"))
|
||||||
|
.transpose()
|
||||||
|
.change_context(errors::ApiErrorResponse::InternalServerError)
|
||||||
|
.attach_printable(
|
||||||
|
"unable to deserialize dynamic routing algorithm ref from business profile",
|
||||||
|
)?
|
||||||
|
.unwrap_or_default();
|
||||||
|
|
||||||
|
let resp = routing_types::RoutingVolumeSplitResponse {
|
||||||
|
split: dynamic_routing_algo_ref
|
||||||
|
.dynamic_routing_volume_split
|
||||||
|
.unwrap_or_default(),
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(service_api::ApplicationResponse::Json(resp))
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(all(feature = "v1", feature = "dynamic_routing"))]
|
#[cfg(all(feature = "v1", feature = "dynamic_routing"))]
|
||||||
pub async fn success_based_routing_update_configs(
|
pub async fn success_based_routing_update_configs(
|
||||||
state: SessionState,
|
state: SessionState,
|
||||||
|
|||||||
@ -2082,6 +2082,10 @@ impl Profile {
|
|||||||
web::resource("/set_volume_split")
|
web::resource("/set_volume_split")
|
||||||
.route(web::post().to(routing::set_dynamic_routing_volume_split)),
|
.route(web::post().to(routing::set_dynamic_routing_volume_split)),
|
||||||
)
|
)
|
||||||
|
.service(
|
||||||
|
web::resource("/get_volume_split")
|
||||||
|
.route(web::get().to(routing::get_dynamic_routing_volume_split)),
|
||||||
|
)
|
||||||
.service(
|
.service(
|
||||||
web::scope("/elimination")
|
web::scope("/elimination")
|
||||||
.service(
|
.service(
|
||||||
|
|||||||
@ -1502,3 +1502,44 @@ pub async fn set_dynamic_routing_volume_split(
|
|||||||
))
|
))
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(all(feature = "olap", feature = "v1"))]
|
||||||
|
#[instrument(skip_all)]
|
||||||
|
pub async fn get_dynamic_routing_volume_split(
|
||||||
|
state: web::Data<AppState>,
|
||||||
|
req: HttpRequest,
|
||||||
|
path: web::Path<routing_types::ToggleDynamicRoutingPath>,
|
||||||
|
) -> impl Responder {
|
||||||
|
let flow = Flow::VolumeSplitOnRoutingType;
|
||||||
|
|
||||||
|
let payload = path.into_inner();
|
||||||
|
Box::pin(oss_api::server_wrap(
|
||||||
|
flow,
|
||||||
|
state,
|
||||||
|
&req,
|
||||||
|
payload.clone(),
|
||||||
|
|state, auth: auth::AuthenticationData, payload, _| {
|
||||||
|
let merchant_context = domain::MerchantContext::NormalMerchant(Box::new(
|
||||||
|
domain::Context(auth.merchant_account, auth.key_store),
|
||||||
|
));
|
||||||
|
routing::retrieve_dynamic_routing_volume_split(
|
||||||
|
state,
|
||||||
|
merchant_context,
|
||||||
|
payload.profile_id,
|
||||||
|
)
|
||||||
|
},
|
||||||
|
auth::auth_type(
|
||||||
|
&auth::HeaderAuth(auth::ApiKeyAuth {
|
||||||
|
is_connected_allowed: false,
|
||||||
|
is_platform_allowed: false,
|
||||||
|
}),
|
||||||
|
&auth::JWTAuthProfileFromRoute {
|
||||||
|
profile_id: payload.profile_id,
|
||||||
|
required_permission: Permission::ProfileRoutingRead,
|
||||||
|
},
|
||||||
|
req.headers(),
|
||||||
|
),
|
||||||
|
api_locking::LockAction::NotApplicable,
|
||||||
|
))
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user