use tokio::fs;
use tracing::info;
use crate::error::{Result, TaskFlowError};
use crate::task::{Task, TaskHandler, TaskResult};
pub struct FileTaskHandler;
impl FileTaskHandler {
pub fn new() -> Self {
Self
}
}
#[async_trait::async_trait]
impl TaskHandler for FileTaskHandler {
fn task_type(&self) -> &'static str {
"file_operation"
}
async fn execute(&self, task: &Task) -> Result<TaskResult> {
let operation = task
.definition
.payload
.get("operation")
.and_then(|v| v.as_str())
.ok_or_else(|| {
TaskFlowError::InvalidConfiguration("Missing operation type".to_string())
})?;
let path = task
.definition
.payload
.get("path")
.and_then(|v| v.as_str())
.ok_or_else(|| TaskFlowError::InvalidConfiguration("Missing file path".to_string()))?;
info!("Performing file operation {} on: {}", operation, path);
match operation {
"read" => self.read_file(path).await,
"write" => self.write_file(task, path).await,
"delete" => self.delete_file(path).await,
"copy" => self.copy_file(task, path).await,
"move" => self.move_file(task, path).await,
op => Err(TaskFlowError::InvalidConfiguration(format!(
"Unknown file operation: {}",
op
))),
}
}
}
impl FileTaskHandler {
async fn read_file(&self, path: &str) -> Result<TaskResult> {
let content = fs::read_to_string(path)
.await
.map_err(|e| TaskFlowError::ExecutionError(e.to_string()))?;
Ok(TaskResult {
success: true,
output: Some(content),
error: None,
execution_time_ms: 0,
metadata: Default::default(),
})
}
async fn write_file(&self, task: &Task, path: &str) -> Result<TaskResult> {
let content = task
.definition
.payload
.get("content")
.and_then(|v| v.as_str())
.ok_or_else(|| TaskFlowError::InvalidConfiguration("Missing content".to_string()))?;
fs::write(path, content)
.await
.map_err(|e| TaskFlowError::ExecutionError(e.to_string()))?;
Ok(TaskResult {
success: true,
output: Some(format!("File written successfully: {}", path)),
error: None,
execution_time_ms: 0,
metadata: Default::default(),
})
}
async fn delete_file(&self, path: &str) -> Result<TaskResult> {
fs::remove_file(path)
.await
.map_err(|e| TaskFlowError::ExecutionError(e.to_string()))?;
Ok(TaskResult {
success: true,
output: Some(format!("File deleted: {}", path)),
error: None,
execution_time_ms: 0,
metadata: Default::default(),
})
}
async fn copy_file(&self, task: &Task, source_path: &str) -> Result<TaskResult> {
let dest_path = task
.definition
.payload
.get("destination")
.and_then(|v| v.as_str())
.ok_or_else(|| {
TaskFlowError::InvalidConfiguration("Missing destination path".to_string())
})?;
fs::copy(source_path, dest_path)
.await
.map_err(|e| TaskFlowError::ExecutionError(e.to_string()))?;
Ok(TaskResult {
success: true,
output: Some(format!("File copied from {} to {}", source_path, dest_path)),
error: None,
execution_time_ms: 0,
metadata: Default::default(),
})
}
async fn move_file(&self, task: &Task, source_path: &str) -> Result<TaskResult> {
let dest_path = task
.definition
.payload
.get("destination")
.and_then(|v| v.as_str())
.ok_or_else(|| {
TaskFlowError::InvalidConfiguration("Missing destination path".to_string())
})?;
fs::rename(source_path, dest_path)
.await
.map_err(|e| TaskFlowError::ExecutionError(e.to_string()))?;
Ok(TaskResult {
success: true,
output: Some(format!("File moved from {} to {}", source_path, dest_path)),
error: None,
execution_time_ms: 0,
metadata: Default::default(),
})
}
}