use std::collections::HashMap;
use std::future::Future;
use std::pin::Pin;
use std::sync::Arc;
use std::time::Duration;
use blazen_events::{InputRequestEvent, InputResponseEvent};
use crate::error::WorkflowError;
use crate::step::StepRegistration;
use crate::workflow::Workflow;
pub type InputHandlerFn = Arc<
dyn Fn(
InputRequestEvent,
)
-> Pin<Box<dyn Future<Output = Result<InputResponseEvent, WorkflowError>> + Send>>
+ Send
+ Sync,
>;
pub struct WorkflowBuilder {
name: String,
steps: Vec<StepRegistration>,
timeout: Option<Duration>,
input_handler: Option<InputHandlerFn>,
auto_publish_events: bool,
session_pause_policy: crate::session_ref::SessionPausePolicy,
#[cfg(feature = "persist")]
checkpoint_store: Option<Arc<dyn blazen_persist::CheckpointStore>>,
#[cfg(feature = "persist")]
checkpoint_after_step: bool,
#[cfg(feature = "telemetry")]
collect_history: bool,
}
impl WorkflowBuilder {
#[must_use]
pub fn new(name: impl Into<String>) -> Self {
Self {
name: name.into(),
steps: Vec::new(),
timeout: Some(Duration::from_secs(300)), input_handler: None,
auto_publish_events: false,
session_pause_policy: crate::session_ref::SessionPausePolicy::default(),
#[cfg(feature = "persist")]
checkpoint_store: None,
#[cfg(feature = "persist")]
checkpoint_after_step: false,
#[cfg(feature = "telemetry")]
collect_history: false,
}
}
#[must_use]
pub fn step(mut self, registration: StepRegistration) -> Self {
self.steps.push(registration);
self
}
#[must_use]
pub fn timeout(mut self, timeout: Duration) -> Self {
self.timeout = Some(timeout);
self
}
#[must_use]
pub fn no_timeout(mut self) -> Self {
self.timeout = None;
self
}
#[must_use]
pub fn input_handler(mut self, handler: InputHandlerFn) -> Self {
self.input_handler = Some(handler);
self
}
#[must_use]
pub fn auto_publish_events(mut self, enabled: bool) -> Self {
self.auto_publish_events = enabled;
self
}
#[must_use]
pub fn session_pause_policy(mut self, policy: crate::session_ref::SessionPausePolicy) -> Self {
self.session_pause_policy = policy;
self
}
#[cfg(feature = "telemetry")]
#[must_use]
pub fn with_history(mut self) -> Self {
self.collect_history = true;
self
}
#[cfg(feature = "persist")]
#[must_use]
pub fn checkpoint_store(mut self, store: Arc<dyn blazen_persist::CheckpointStore>) -> Self {
self.checkpoint_store = Some(store);
self
}
#[cfg(feature = "persist")]
#[must_use]
pub fn checkpoint_after_step(mut self, enabled: bool) -> Self {
self.checkpoint_after_step = enabled;
self
}
pub fn build(self) -> crate::error::Result<Workflow> {
if self.steps.is_empty() {
return Err(WorkflowError::ValidationFailed(
"workflow must have at least one step".into(),
));
}
let mut registry: HashMap<String, Vec<StepRegistration>> = HashMap::new();
for step in self.steps {
for &event_type in &step.accepts {
registry
.entry(event_type.to_owned())
.or_default()
.push(step.clone());
}
}
Ok(Workflow {
name: self.name,
step_registry: registry,
timeout: self.timeout,
input_handler: self.input_handler,
auto_publish_events: self.auto_publish_events,
session_pause_policy: self.session_pause_policy,
#[cfg(feature = "persist")]
checkpoint_store: self.checkpoint_store,
#[cfg(feature = "persist")]
checkpoint_after_step: self.checkpoint_after_step,
#[cfg(feature = "telemetry")]
collect_history: self.collect_history,
})
}
}