kotoba_workflow_core/
lib.rs1pub mod engine;
7pub mod types;
8
9pub use engine::WorkflowEngine;
10pub use types::*;
11
12pub mod prelude {
14 pub use super::{
15 WorkflowEngine,
16 WorkflowIR,
17 WorkflowExecution,
18 WorkflowExecutionId,
19 ExecutionStatus,
20 StartWorkflowResponse,
21 WorkflowError,
22 };
23}
24
25use async_trait::async_trait;
26use serde::{Deserialize, Serialize};
27use std::fmt;
28
29#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
31pub struct WorkflowExecutionId(pub String);
32
33impl fmt::Display for WorkflowExecutionId {
34 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
35 write!(f, "{}", self.0)
36 }
37}
38
39impl From<String> for WorkflowExecutionId {
40 fn from(s: String) -> Self {
41 Self(s)
42 }
43}
44
45impl From<&str> for WorkflowExecutionId {
46 fn from(s: &str) -> Self {
47 Self(s.to_string())
48 }
49}
50
51#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
53pub enum ExecutionStatus {
54 Pending,
55 Running,
56 Completed,
57 Failed,
58 Cancelled,
59}
60
61#[derive(Debug, Clone, Serialize, Deserialize)]
63pub struct WorkflowExecution {
64 pub execution_id: WorkflowExecutionId,
65 pub workflow_id: String,
66 pub status: ExecutionStatus,
67 pub created_at: chrono::DateTime<chrono::Utc>,
68 pub updated_at: chrono::DateTime<chrono::Utc>,
69 pub result: Option<serde_json::Value>,
70 pub error: Option<String>,
71}
72
73#[derive(Debug, Clone, Serialize, Deserialize)]
75pub struct StartWorkflowResponse {
76 pub execution_id: String,
77}
78
79#[derive(Debug, Clone, Serialize, Deserialize)]
81pub struct WorkflowIR {
82 pub id: String,
83 pub name: String,
84 pub description: Option<String>,
85 pub activities: Vec<ActivityIR>,
86 pub connections: Vec<Connection>,
87}
88
89#[derive(Debug, Clone, Serialize, Deserialize)]
91pub struct ActivityIR {
92 pub id: String,
93 pub name: String,
94 pub activity_type: String,
95 pub config: serde_json::Value,
96}
97
98#[derive(Debug, Clone, Serialize, Deserialize)]
100pub struct Connection {
101 pub from: String,
102 pub to: String,
103 pub condition: Option<String>,
104}
105
106#[async_trait]
108pub trait WorkflowEngineInterface: Send + Sync {
109 async fn start_workflow(
110 &self,
111 workflow: &WorkflowIR,
112 context: serde_json::Value,
113 ) -> Result<WorkflowExecutionId, WorkflowError>;
114
115 async fn get_execution(
116 &self,
117 execution_id: &WorkflowExecutionId,
118 ) -> Result<Option<WorkflowExecution>, WorkflowError>;
119
120 async fn list_executions(&self) -> Result<Vec<WorkflowExecution>, WorkflowError>;
121
122 async fn cancel_execution(
123 &self,
124 execution_id: &WorkflowExecutionId,
125 ) -> Result<(), WorkflowError>;
126}
127
128#[derive(Debug, thiserror::Error)]
130pub enum WorkflowError {
131 #[error("Workflow not found: {0}")]
132 NotFound(String),
133
134 #[error("Workflow validation failed: {0}")]
135 Validation(String),
136
137 #[error("Workflow execution failed: {0}")]
138 Execution(String),
139
140 #[error("Storage error: {0}")]
141 Storage(String),
142
143 #[error("Serialization error: {0}")]
144 Serialization(#[from] serde_json::Error),
145
146 #[error("Unknown error: {0}")]
147 Unknown(String),
148}
149
150impl From<kotoba_errors::KotobaError> for WorkflowError {
151 fn from(err: kotoba_errors::KotobaError) -> Self {
152 match err {
153 kotoba_errors::KotobaError::NotFound(msg) => WorkflowError::NotFound(msg),
154 kotoba_errors::KotobaError::Validation(msg) => WorkflowError::Validation(msg),
155 _ => WorkflowError::Unknown(err.to_string()),
156 }
157 }
158}
159