use super::{ProdigyError, ErrorCode, ErrorExt, common};
use std::path::Path;
pub fn load_config_old(path: &Path) -> Result<String, String> {
std::fs::read_to_string(path)
.map_err(|e| format!("Failed to read config: {}", e))
}
pub fn load_config_new(path: &Path) -> Result<String, ProdigyError> {
std::fs::read_to_string(path)
.map_err(|e| {
ProdigyError::config_with_code(
ErrorCode::CONFIG_NOT_FOUND,
format!("Cannot read config file: {}", path.display())
).with_source(e)
})
}
pub fn load_config_with_trait(path: &Path) -> Result<String, ProdigyError> {
std::fs::read_to_string(path)
.to_config_error(format!("Cannot read config file: {}", path.display()))
}
pub fn process_workflow_old(name: &str) -> anyhow::Result<()> {
anyhow::bail!("Workflow {} not found", name)
}
pub fn process_workflow_new(name: &str) -> Result<(), ProdigyError> {
Err(ProdigyError::workflow_with_code(
ErrorCode::WORKFLOW_NOT_FOUND,
format!("Workflow '{}' not found", name),
Some(name.to_string())
))
}
pub fn find_session(session_id: &str) -> Result<String, ProdigyError> {
if session_id.is_empty() {
return Err(common::session_not_found(session_id));
}
Ok(session_id.to_string())
}
pub fn execute_with_recovery(command: &str) -> Result<String, ProdigyError> {
match execute_command(command) {
Ok(output) => Ok(output),
Err(e) if e.is_recoverable() => {
tracing::warn!("Command failed, attempting recovery: {}", e);
execute_command_with_fallback(command)
.map_err(|recovery_err| {
ProdigyError::execution("Recovery failed after initial failure")
.with_source(recovery_err)
})
}
Err(e) => Err(e),
}
}
pub fn complex_operation(data: &str) -> Result<String, ProdigyError> {
validate_data(data)
.context("Failed to validate data")?;
transform_data(data)
.context("Failed to transform data")?;
save_data(data)
.context("Failed to save data")
}
pub fn macro_example() -> Result<(), ProdigyError> {
use crate::prodigy_error;
let _err = prodigy_error!(config: "Configuration is invalid");
let io_err = std::io::Error::new(std::io::ErrorKind::NotFound, "file");
let _err_with_source = prodigy_error!(storage: "Cannot save file", io_err);
Ok(())
}
pub fn cli_command_handler() -> anyhow::Result<()> {
let result = internal_operation()?;
external_library_call()
.context("Failed to call external library")?;
Ok(result)
}
pub fn process_workflow_file(workflow_path: &Path) -> Result<(), ProdigyError> {
let content = std::fs::read_to_string(workflow_path)
.map_err(ProdigyError::from)
.context(format!("Failed to read workflow file at {}", workflow_path.display()))?;
let workflow: WorkflowConfig = serde_json::from_str(&content)
.map_err(ProdigyError::from)
.context("Failed to parse workflow JSON")?;
validate_workflow(&workflow)
.context(format!("Validation failed for workflow '{}'", workflow.name))?;
execute_setup_commands(&workflow.setup)
.context("Failed to execute setup commands")?;
save_workflow_state(&workflow)
.context("Failed to persist workflow state")?;
Ok(())
}
pub fn process_multiple_items(items: Vec<WorkItem>) -> Result<Vec<String>, ProdigyError> {
items.iter()
.map(|item| {
process_single_item(item)
.with_context(|| format!("Failed to process item {}", item.id))
})
.collect::<Result<Vec<_>, _>>()
.context("Failed to process work items batch")
}
mod before_migration {
use super::*;
pub fn deploy_workflow_old(path: &Path) -> Result<(), ProdigyError> {
let workflow = std::fs::read_to_string(path)
.map_err(ProdigyError::from)?;
let parsed: WorkflowConfig = serde_json::from_str(&workflow)
.map_err(ProdigyError::from)?;
validate_workflow(&parsed)?;
execute_setup_commands(&parsed.setup)?;
Ok(())
}
}
mod after_migration {
use super::*;
pub fn deploy_workflow_new(path: &Path) -> Result<(), ProdigyError> {
let workflow = std::fs::read_to_string(path)
.map_err(ProdigyError::from)
.context(format!("Failed to read workflow from {}", path.display()))?;
let parsed: WorkflowConfig = serde_json::from_str(&workflow)
.map_err(ProdigyError::from)
.context("Failed to parse workflow YAML")?;
validate_workflow(&parsed)
.context(format!("Validation failed for workflow '{}'", parsed.name))?;
execute_setup_commands(&parsed.setup)
.context("Failed during workflow setup phase")?;
Ok(())
}
}
#[allow(dead_code)]
struct WorkflowConfig {
name: String,
setup: Vec<String>,
}
#[allow(dead_code)]
struct WorkItem {
id: String,
data: String,
}
fn execute_command(_cmd: &str) -> Result<String, ProdigyError> {
Err(ProdigyError::execution("Command failed").with_exit_code(1))
}
fn execute_command_with_fallback(_cmd: &str) -> Result<String, ProdigyError> {
Ok("fallback output".to_string())
}
fn validate_data(_data: &str) -> Result<(), ProdigyError> {
Ok(())
}
fn transform_data(_data: &str) -> Result<String, ProdigyError> {
Ok("transformed".to_string())
}
fn save_data(_data: &str) -> Result<String, ProdigyError> {
Ok("saved".to_string())
}
fn internal_operation() -> Result<(), ProdigyError> {
Ok(())
}
fn external_library_call() -> anyhow::Result<()> {
Ok(())
}
fn validate_workflow(_workflow: &WorkflowConfig) -> Result<(), ProdigyError> {
Ok(())
}
fn execute_setup_commands(_commands: &[String]) -> Result<(), ProdigyError> {
Ok(())
}
fn save_workflow_state(_workflow: &WorkflowConfig) -> Result<(), ProdigyError> {
Ok(())
}
fn process_single_item(_item: &WorkItem) -> Result<String, ProdigyError> {
Ok("processed".to_string())
}
use anyhow::Context;
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_error_migration() {
let err = process_workflow_new("test").unwrap_err();
assert_eq!(err.code(), ErrorCode::WORKFLOW_NOT_FOUND);
assert!(err.user_message().contains("Workflow error"));
}
#[test]
fn test_error_recovery() {
let result = execute_with_recovery("test");
assert!(result.is_ok());
}
#[test]
fn test_error_context() {
let result = complex_operation("test");
assert!(result.is_ok());
}
}