mirror of
https://github.com/juspay/hyperswitch.git
synced 2025-10-29 09:07:09 +08:00
refactor: add result type for Program (#8179)
This commit is contained in:
@ -1,6 +1,9 @@
|
|||||||
use std::collections::{HashMap, HashSet};
|
use std::collections::{HashMap, HashSet};
|
||||||
|
|
||||||
use api_models::routing as api_routing;
|
use api_models::{
|
||||||
|
routing as api_routing,
|
||||||
|
routing::{ConnectorSelection, RoutableConnectorChoice},
|
||||||
|
};
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use common_utils::id_type;
|
use common_utils::id_type;
|
||||||
use diesel_models::{enums, routing_algorithm};
|
use diesel_models::{enums, routing_algorithm};
|
||||||
@ -712,48 +715,70 @@ impl From<RoutingAlgorithmRecord> for routing_algorithm::RoutingProfileMetadata
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
use api_models::routing::{ConnectorSelection, RoutableConnectorChoice};
|
|
||||||
impl From<ast::Program<ConnectorSelection>> for Program {
|
impl TryFrom<ast::Program<ConnectorSelection>> for Program {
|
||||||
fn from(p: ast::Program<ConnectorSelection>) -> Self {
|
type Error = error_stack::Report<errors::RoutingError>;
|
||||||
Self {
|
|
||||||
|
fn try_from(p: ast::Program<ConnectorSelection>) -> Result<Self, Self::Error> {
|
||||||
|
let rules = p
|
||||||
|
.rules
|
||||||
|
.into_iter()
|
||||||
|
.map(convert_rule)
|
||||||
|
.collect::<Result<Vec<_>, _>>()?;
|
||||||
|
|
||||||
|
Ok(Self {
|
||||||
globals: HashMap::new(),
|
globals: HashMap::new(),
|
||||||
default_selection: convert_output(p.default_selection),
|
default_selection: convert_output(p.default_selection),
|
||||||
rules: p.rules.into_iter().map(convert_rule).collect(),
|
rules,
|
||||||
metadata: Some(p.metadata),
|
metadata: Some(p.metadata),
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn convert_rule(rule: ast::Rule<ConnectorSelection>) -> Rule {
|
fn convert_rule(rule: ast::Rule<ConnectorSelection>) -> RoutingResult<Rule> {
|
||||||
let routing_type = match &rule.connector_selection {
|
let routing_type = match &rule.connector_selection {
|
||||||
ConnectorSelection::Priority(_) => RoutingType::Priority,
|
ConnectorSelection::Priority(_) => RoutingType::Priority,
|
||||||
ConnectorSelection::VolumeSplit(_) => RoutingType::VolumeSplit,
|
ConnectorSelection::VolumeSplit(_) => RoutingType::VolumeSplit,
|
||||||
};
|
};
|
||||||
|
|
||||||
Rule {
|
Ok(Rule {
|
||||||
name: rule.name,
|
name: rule.name,
|
||||||
routing_type,
|
routing_type,
|
||||||
output: convert_output(rule.connector_selection),
|
output: convert_output(rule.connector_selection),
|
||||||
statements: rule.statements.into_iter().map(convert_if_stmt).collect(),
|
statements: rule
|
||||||
}
|
.statements
|
||||||
|
.into_iter()
|
||||||
|
.map(convert_if_stmt)
|
||||||
|
.collect::<RoutingResult<Vec<IfStatement>>>()?,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn convert_if_stmt(stmt: ast::IfStatement) -> IfStatement {
|
fn convert_if_stmt(stmt: ast::IfStatement) -> RoutingResult<IfStatement> {
|
||||||
IfStatement {
|
Ok(IfStatement {
|
||||||
condition: stmt.condition.into_iter().map(convert_comparison).collect(),
|
condition: stmt
|
||||||
|
.condition
|
||||||
|
.into_iter()
|
||||||
|
.map(convert_comparison)
|
||||||
|
.collect::<RoutingResult<Vec<Comparison>>>()?,
|
||||||
|
|
||||||
nested: stmt
|
nested: stmt
|
||||||
.nested
|
.nested
|
||||||
.map(|v| v.into_iter().map(convert_if_stmt).collect()),
|
.map(|v| {
|
||||||
}
|
v.into_iter()
|
||||||
|
.map(convert_if_stmt)
|
||||||
|
.collect::<RoutingResult<Vec<IfStatement>>>()
|
||||||
|
})
|
||||||
|
.transpose()?,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn convert_comparison(c: ast::Comparison) -> Comparison {
|
fn convert_comparison(c: ast::Comparison) -> RoutingResult<Comparison> {
|
||||||
Comparison {
|
Ok(Comparison {
|
||||||
lhs: c.lhs,
|
lhs: c.lhs,
|
||||||
comparison: convert_comparison_type(c.comparison),
|
comparison: convert_comparison_type(c.comparison),
|
||||||
value: convert_value(c.value),
|
value: convert_value(c.value)?,
|
||||||
metadata: c.metadata,
|
metadata: c.metadata,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn convert_comparison_type(ct: ast::ComparisonType) -> ComparisonType {
|
fn convert_comparison_type(ct: ast::ComparisonType) -> ComparisonType {
|
||||||
@ -767,18 +792,21 @@ fn convert_comparison_type(ct: ast::ComparisonType) -> ComparisonType {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::unimplemented)]
|
fn convert_value(v: ast::ValueType) -> RoutingResult<ValueType> {
|
||||||
fn convert_value(v: ast::ValueType) -> ValueType {
|
|
||||||
use ast::ValueType::*;
|
use ast::ValueType::*;
|
||||||
match v {
|
match v {
|
||||||
Number(n) => ValueType::Number(n.get_amount_as_i64().try_into().unwrap_or_default()),
|
Number(n) => Ok(ValueType::Number(
|
||||||
EnumVariant(e) => ValueType::EnumVariant(e),
|
n.get_amount_as_i64().try_into().unwrap_or_default(),
|
||||||
MetadataVariant(m) => ValueType::MetadataVariant(MetadataValue {
|
)),
|
||||||
|
EnumVariant(e) => Ok(ValueType::EnumVariant(e)),
|
||||||
|
MetadataVariant(m) => Ok(ValueType::MetadataVariant(MetadataValue {
|
||||||
key: m.key,
|
key: m.key,
|
||||||
value: m.value,
|
value: m.value,
|
||||||
}),
|
})),
|
||||||
StrValue(s) => ValueType::StrValue(s),
|
StrValue(s) => Ok(ValueType::StrValue(s)),
|
||||||
_ => unimplemented!(), // GlobalRef(r) => ValueType::GlobalRef(r),
|
_ => Err(error_stack::Report::new(
|
||||||
|
errors::RoutingError::InvalidRoutingAlgorithmStructure,
|
||||||
|
)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -342,26 +342,32 @@ pub async fn create_routing_algorithm_under_profile(
|
|||||||
let mut decision_engine_routing_id: Option<String> = None;
|
let mut decision_engine_routing_id: Option<String> = None;
|
||||||
|
|
||||||
if let Some(EuclidAlgorithm::Advanced(program)) = request.algorithm.clone() {
|
if let Some(EuclidAlgorithm::Advanced(program)) = request.algorithm.clone() {
|
||||||
let internal_program: Program = program.into();
|
match program.try_into() {
|
||||||
let routing_rule = RoutingRule {
|
Ok(internal_program) => {
|
||||||
name: name.clone(),
|
let routing_rule = RoutingRule {
|
||||||
description: Some(description.clone()),
|
name: name.clone(),
|
||||||
created_by: profile_id.get_string_repr().to_string(),
|
description: Some(description.clone()),
|
||||||
algorithm: internal_program,
|
created_by: profile_id.get_string_repr().to_string(),
|
||||||
metadata: Some(RoutingMetadata {
|
algorithm: internal_program,
|
||||||
kind: algorithm.get_kind().foreign_into(),
|
metadata: Some(RoutingMetadata {
|
||||||
algorithm_for: transaction_type.to_owned(),
|
kind: algorithm.get_kind().foreign_into(),
|
||||||
}),
|
algorithm_for: transaction_type.to_owned(),
|
||||||
};
|
}),
|
||||||
|
};
|
||||||
|
|
||||||
decision_engine_routing_id = create_de_euclid_routing_algo(&state, &routing_rule)
|
decision_engine_routing_id = create_de_euclid_routing_algo(&state, &routing_rule)
|
||||||
.await
|
.await
|
||||||
.map_err(|e| {
|
.map_err(|e| {
|
||||||
|
// errors are ignored as this is just for diff checking as of now (optional flow).
|
||||||
|
logger::error!(decision_engine_error=?e,decision_engine_euclid_request=?routing_rule, "failed to create rule in decision_engine");
|
||||||
|
})
|
||||||
|
.ok();
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
// errors are ignored as this is just for diff checking as of now (optional flow).
|
// errors are ignored as this is just for diff checking as of now (optional flow).
|
||||||
logger::error!(decision_engine_error=?e, "decision_engine_euclid");
|
logger::error!(decision_engine_error=?e, "decision_engine_euclid");
|
||||||
logger::debug!(decision_engine_request=?routing_rule, "decision_engine_euclid");
|
}
|
||||||
})
|
};
|
||||||
.ok();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if decision_engine_routing_id.is_some() {
|
if decision_engine_routing_id.is_some() {
|
||||||
|
|||||||
Reference in New Issue
Block a user