use crate::{Chain, Chord, Group};
#[derive(Debug, Clone)]
pub struct ValidationError {
pub message: String,
pub task_name: Option<String>,
}
impl ValidationError {
pub fn new(message: impl Into<String>) -> Self {
Self {
message: message.into(),
task_name: None,
}
}
pub fn with_task(message: impl Into<String>, task_name: impl Into<String>) -> Self {
Self {
message: message.into(),
task_name: Some(task_name.into()),
}
}
}
impl std::fmt::Display for ValidationError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
if let Some(task) = &self.task_name {
write!(f, "[{}] {}", task, self.message)
} else {
write!(f, "{}", self.message)
}
}
}
pub fn validate_chain(chain: &Chain) -> Result<(), Vec<ValidationError>> {
let mut errors = Vec::new();
if chain.tasks.is_empty() {
errors.push(ValidationError::new("Chain must contain at least one task"));
}
for task in &chain.tasks {
if task.task.is_empty() {
errors.push(ValidationError::new("Task name cannot be empty"));
}
}
if errors.is_empty() {
Ok(())
} else {
Err(errors)
}
}
pub fn validate_group(group: &Group) -> Result<(), Vec<ValidationError>> {
let mut errors = Vec::new();
if group.tasks.is_empty() {
errors.push(ValidationError::new("Group must contain at least one task"));
}
for task in &group.tasks {
if task.task.is_empty() {
errors.push(ValidationError::new("Task name cannot be empty"));
}
}
if errors.is_empty() {
Ok(())
} else {
Err(errors)
}
}
pub fn validate_chord(chord: &Chord) -> Result<(), Vec<ValidationError>> {
let mut errors = Vec::new();
if let Err(mut group_errors) = validate_group(&chord.header) {
errors.append(&mut group_errors);
}
if chord.body.task.is_empty() {
errors.push(ValidationError::with_task(
"Callback task name cannot be empty",
"body",
));
}
if errors.is_empty() {
Ok(())
} else {
Err(errors)
}
}
pub fn check_performance_concerns_group(group: &Group) -> Option<Vec<String>> {
let mut warnings = Vec::new();
if group.tasks.len() > 100 {
warnings.push(format!(
"Group contains {} tasks, which may cause performance issues. Consider batching.",
group.tasks.len()
));
}
if warnings.is_empty() {
None
} else {
Some(warnings)
}
}
pub fn check_performance_concerns_chain(chain: &Chain) -> Option<Vec<String>> {
let mut warnings = Vec::new();
if chain.tasks.len() > 50 {
warnings.push(format!(
"Chain contains {} sequential tasks, which may cause long latency. Consider parallelizing.",
chain.tasks.len()
));
}
if warnings.is_empty() {
None
} else {
Some(warnings)
}
}