use std::collections::HashMap;
pub type NodeId = &'static str;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum InstanceState {
Running,
Completed,
Terminated,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum TokenStatus {
Created,
Ready,
Executing,
Waiting,
Suspended,
Completed,
Terminated,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum TokenMode {
Forward,
Compensation,
}
#[derive(Debug, Clone)]
pub enum EdgeCondition {
VariableEq { key: String, value: String },
Expression(String),
Default,
}
#[derive(Debug, Clone)]
pub struct OutgoingEdge {
pub target: NodeId,
pub condition: Option<EdgeCondition>,
}
#[derive(Debug, Clone)]
pub enum NodeType {
Start,
End,
ServiceTask(fn(&mut ProcessInstance)),
UserTask,
ExclusiveGateway,
ParallelFork,
ParallelJoin { expected: usize },
}
#[derive(Debug, Clone)]
pub struct Node {
pub id: NodeId,
pub node_type: NodeType,
pub outgoing_edges: Vec<OutgoingEdge>,
}
#[derive(Debug, Clone)]
pub struct ProcessDefinition {
pub id: &'static str,
pub nodes: HashMap<NodeId, Node>,
pub start: NodeId,
}
#[derive(Debug, Clone)]
pub struct Token {
pub id: String,
pub node_id: String,
pub status: TokenStatus,
pub mode: TokenMode,
pub version: u32,
pub attempt: u32,
pub parallel_group_id: Option<String>,
pub updated_at: Option<String>,
}
impl Token {
pub fn waiting(&self) -> bool {
self.status == TokenStatus::Waiting
}
}
#[derive(Debug)]
pub struct ProcessInstance {
pub id: String,
pub process_def_id: String,
pub tokens: Vec<Token>,
pub variables: HashMap<String, String>,
pub state: InstanceState,
pub version: u32,
}
impl ProcessInstance {
pub fn completed(&self) -> bool {
self.state == InstanceState::Completed
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn token_waiting_only_when_waiting_status() {
let t_waiting = Token {
id: "1".into(),
node_id: "n".into(),
status: TokenStatus::Waiting,
mode: TokenMode::Forward,
version: 0,
attempt: 0,
parallel_group_id: None,
updated_at: None,
};
assert!(t_waiting.waiting());
let t_ready = Token {
id: "2".into(),
node_id: "n".into(),
status: TokenStatus::Ready,
mode: TokenMode::Forward,
version: 0,
attempt: 0,
parallel_group_id: None,
updated_at: None,
};
assert!(!t_ready.waiting());
}
#[test]
fn instance_completed_only_when_completed_state() {
let inst_running = ProcessInstance {
id: "i".into(),
process_def_id: "p".into(),
tokens: vec![],
variables: HashMap::new(),
state: InstanceState::Running,
version: 0,
};
assert!(!inst_running.completed());
let inst_done = ProcessInstance {
id: "i".into(),
process_def_id: "p".into(),
tokens: vec![],
variables: HashMap::new(),
state: InstanceState::Completed,
version: 0,
};
assert!(inst_done.completed());
}
}