refactor: add result type for Program (#8179)

This commit is contained in:
Prajjwal Kumar
2025-06-12 16:07:36 +05:30
committed by GitHub
parent 4318c934dd
commit 261818f215
2 changed files with 79 additions and 45 deletions

View File

@ -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,
)),
} }
} }

View File

@ -342,7 +342,8 @@ 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() {
Ok(internal_program) => {
let routing_rule = RoutingRule { let routing_rule = RoutingRule {
name: name.clone(), name: name.clone(),
description: Some(description.clone()), description: Some(description.clone()),
@ -358,11 +359,16 @@ pub async fn create_routing_algorithm_under_profile(
.await .await
.map_err(|e| { .map_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_request=?routing_rule, "failed to create rule in decision_engine");
logger::debug!(decision_engine_request=?routing_rule, "decision_engine_euclid");
}) })
.ok(); .ok();
} }
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");
}
};
}
if decision_engine_routing_id.is_some() { if decision_engine_routing_id.is_some() {
logger::info!(routing_flow=?"create_euclid_routing_algorithm", is_equal=?"true", "decision_engine_euclid"); logger::info!(routing_flow=?"create_euclid_routing_algorithm", is_equal=?"true", "decision_engine_euclid");