use crate::branch_state::BranchState;
use crate::event::FlowEvent;
use crate::state::State;
use crate::stream_emitter::StreamEmitter;
use crate::workflow_state::WorkflowState;
#[derive(Debug, Clone)]
pub enum ExecutionSignal {
Pause {
barrier_id: crate::event::BarrierId,
timeout: Option<std::time::Duration>,
},
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum NextAction {
Next,
Goto(String),
End,
}
#[derive(Debug, Default)]
pub struct ExecutionControl {
next: Option<NextAction>,
signal: Option<ExecutionSignal>,
}
impl ExecutionControl {
pub fn new() -> Self {
Self::default()
}
pub fn goto(&mut self, target: impl Into<String>) {
self.next = Some(NextAction::Goto(target.into()));
}
pub fn end(&mut self) {
self.next = Some(NextAction::End);
}
pub fn pause(
&mut self,
barrier_id: crate::event::BarrierId,
timeout: Option<std::time::Duration>,
) {
self.signal = Some(ExecutionSignal::Pause {
barrier_id,
timeout,
});
}
pub fn take(&mut self) -> (NextAction, Option<ExecutionSignal>) {
let next = self.next.take().unwrap_or(NextAction::Next);
let signal = self.signal.take();
(next, signal)
}
}
#[derive(Debug, Clone, Default)]
pub struct NodeMetadata {
pub token_cost: f64,
pub has_side_effects: bool,
}
pub struct NodeContext<'a, S: WorkflowState = State> {
state: &'a mut S,
branch: &'a mut BranchState,
stream: Option<&'a StreamEmitter>,
control: ExecutionControl,
metadata: NodeMetadata,
effects: Vec<S::Effect>,
flow_events: Vec<FlowEvent>,
}
impl<'a, S: WorkflowState> NodeContext<'a, S> {
pub fn new(
state: &'a mut S,
branch: &'a mut BranchState,
stream: Option<&'a StreamEmitter>,
) -> Self {
Self {
state,
branch,
stream,
control: ExecutionControl::new(),
metadata: NodeMetadata::default(),
effects: Vec::new(),
flow_events: Vec::new(),
}
}
pub fn state(&self) -> &S {
self.state
}
pub fn state_mut(&mut self) -> &mut S {
self.state
}
pub fn branch(&self) -> &BranchState {
self.branch
}
pub fn branch_mut(&mut self) -> &mut BranchState {
self.branch
}
pub fn emit(&self, chunk: crate::stream_chunk::StreamChunk) {
if let Some(stream) = &self.stream {
stream.emit(chunk);
}
}
pub fn emit_flow_event(&mut self, event: FlowEvent) {
self.flow_events.push(event);
}
pub fn goto(&mut self, target: impl Into<String>) {
self.control.goto(target);
}
pub fn end(&mut self) {
self.control.end();
}
pub fn pause(
&mut self,
barrier_id: crate::event::BarrierId,
timeout: Option<std::time::Duration>,
) {
self.control.pause(barrier_id, timeout);
}
pub fn set_token_cost(&mut self, cost: f64) {
self.metadata.token_cost = cost;
}
pub fn set_has_side_effects(&mut self) {
self.metadata.has_side_effects = true;
}
pub fn emit_effect(&mut self, effect: S::Effect) {
self.effects.push(effect);
}
pub fn consume_effects(&mut self) -> Vec<S::Effect> {
std::mem::take(&mut self.effects)
}
pub fn effects_len(&self) -> usize {
self.effects.len()
}
pub fn take_control(&mut self) -> (NextAction, Option<ExecutionSignal>) {
self.control.take()
}
pub fn take_metadata(&mut self) -> NodeMetadata {
std::mem::take(&mut self.metadata)
}
pub fn stream(&self) -> Option<&'a StreamEmitter> {
self.stream
}
pub fn take_flow_events(&mut self) -> Vec<FlowEvent> {
std::mem::take(&mut self.flow_events)
}
}