[model-gateway] refactor: workflow engine cleanup and minor optimization (#15001)
This commit is contained in:
@@ -22,8 +22,6 @@ use super::{
|
|||||||
types::*,
|
types::*,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Consolidated step execution tracking to minimize lock contention.
|
|
||||||
/// Single lock instead of 4 separate locks.
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
struct StepTracker {
|
struct StepTracker {
|
||||||
completed: HashSet<StepId>,
|
completed: HashSet<StepId>,
|
||||||
@@ -213,24 +211,17 @@ impl WorkflowEngine {
|
|||||||
let start_time = std::time::Instant::now();
|
let start_time = std::time::Instant::now();
|
||||||
let step_count = definition.steps.len();
|
let step_count = definition.steps.len();
|
||||||
|
|
||||||
// Consolidated tracking state - single lock instead of 4
|
|
||||||
let tracker: Arc<RwLock<StepTracker>> = Arc::new(RwLock::new(StepTracker::default()));
|
let tracker: Arc<RwLock<StepTracker>> = Arc::new(RwLock::new(StepTracker::default()));
|
||||||
|
|
||||||
// Channel for step completion notifications
|
|
||||||
// Capacity equals step count to prevent blocking on send
|
|
||||||
let (tx, mut rx) = mpsc::channel::<(StepId, StepResult)>(step_count.max(1));
|
let (tx, mut rx) = mpsc::channel::<(StepId, StepResult)>(step_count.max(1));
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
// Check if workflow was cancelled
|
if self.state_store.is_cancelled(instance_id)? {
|
||||||
let state = self.state_store.load(instance_id)?;
|
|
||||||
if state.status == WorkflowStatus::Cancelled {
|
|
||||||
self.event_bus
|
self.event_bus
|
||||||
.publish(WorkflowEvent::WorkflowCancelled { instance_id })
|
.publish(WorkflowEvent::WorkflowCancelled { instance_id })
|
||||||
.await;
|
.await;
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Single lock acquisition for all tracking state reads
|
|
||||||
let (ready_step_indices, total_processed, running_count, blocked_by_failure) = {
|
let (ready_step_indices, total_processed, running_count, blocked_by_failure) = {
|
||||||
let t = tracker.read();
|
let t = tracker.read();
|
||||||
|
|
||||||
@@ -305,7 +296,6 @@ impl WorkflowEngine {
|
|||||||
.execute_step_with_retry(instance_id, step, &def)
|
.execute_step_with_retry(instance_id, step, &def)
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
// Single lock acquisition to update tracking state
|
|
||||||
{
|
{
|
||||||
let mut t = tracker.write();
|
let mut t = tracker.write();
|
||||||
t.running.remove(&step_id);
|
t.running.remove(&step_id);
|
||||||
@@ -339,7 +329,6 @@ impl WorkflowEngine {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send completion signal (result determines the message)
|
|
||||||
let signal = match result {
|
let signal = match result {
|
||||||
Ok(r) => r,
|
Ok(r) => r,
|
||||||
Err(_) => StepResult::Failure,
|
Err(_) => StepResult::Failure,
|
||||||
@@ -360,19 +349,19 @@ impl WorkflowEngine {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check final status - single lock read
|
let failed_step = {
|
||||||
let has_failures = !tracker.read().failed.is_empty();
|
let t = tracker.read();
|
||||||
|
t.failed.iter().next().cloned()
|
||||||
|
};
|
||||||
|
|
||||||
if has_failures {
|
if let Some(ref step) = failed_step {
|
||||||
self.state_store.update(instance_id, |s| {
|
self.state_store.update(instance_id, |s| {
|
||||||
s.status = WorkflowStatus::Failed;
|
s.status = WorkflowStatus::Failed;
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
let failed_step = tracker.read().failed.iter().next().cloned();
|
|
||||||
self.event_bus
|
self.event_bus
|
||||||
.publish(WorkflowEvent::WorkflowFailed {
|
.publish(WorkflowEvent::WorkflowFailed {
|
||||||
instance_id,
|
instance_id,
|
||||||
failed_step: failed_step.unwrap_or_else(|| StepId::new("unknown")),
|
failed_step: step.clone(),
|
||||||
error: "One or more steps failed".to_string(),
|
error: "One or more steps failed".to_string(),
|
||||||
})
|
})
|
||||||
.await;
|
.await;
|
||||||
@@ -413,7 +402,6 @@ impl WorkflowEngine {
|
|||||||
let mut backoff = Self::create_backoff(&retry_policy.backoff);
|
let mut backoff = Self::create_backoff(&retry_policy.backoff);
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
// Check for cancellation before starting/retrying step (optimized: no full state load)
|
|
||||||
if self.state_store.is_cancelled(instance_id)? {
|
if self.state_store.is_cancelled(instance_id)? {
|
||||||
return Err(WorkflowError::Cancelled(instance_id));
|
return Err(WorkflowError::Cancelled(instance_id));
|
||||||
}
|
}
|
||||||
@@ -441,7 +429,6 @@ impl WorkflowEngine {
|
|||||||
})
|
})
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
// Get current context (optimized: only clone context, not full state)
|
|
||||||
let mut context = self.state_store.get_context(instance_id)?;
|
let mut context = self.state_store.get_context(instance_id)?;
|
||||||
|
|
||||||
// Execute step with timeout
|
// Execute step with timeout
|
||||||
@@ -450,7 +437,6 @@ impl WorkflowEngine {
|
|||||||
|
|
||||||
let step_duration = step_start.elapsed();
|
let step_duration = step_start.elapsed();
|
||||||
|
|
||||||
// Save updated context (use std::mem::replace to avoid extra clone)
|
|
||||||
self.state_store.update(instance_id, |s| {
|
self.state_store.update(instance_id, |s| {
|
||||||
s.context = std::mem::replace(&mut context, WorkflowContext::new(instance_id));
|
s.context = std::mem::replace(&mut context, WorkflowContext::new(instance_id));
|
||||||
})?;
|
})?;
|
||||||
|
|||||||
@@ -89,6 +89,12 @@ impl Default for EventBus {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl std::fmt::Debug for EventBus {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
f.debug_struct("EventBus").finish_non_exhaustive()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Logging subscriber that logs events using tracing
|
/// Logging subscriber that logs events using tracing
|
||||||
pub struct LoggingSubscriber;
|
pub struct LoggingSubscriber;
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ mod executor;
|
|||||||
mod state;
|
mod state;
|
||||||
pub mod types;
|
pub mod types;
|
||||||
|
|
||||||
// Re-export main types
|
|
||||||
pub use definition::{StepDefinition, WorkflowDefinition};
|
pub use definition::{StepDefinition, WorkflowDefinition};
|
||||||
pub use engine::WorkflowEngine;
|
pub use engine::WorkflowEngine;
|
||||||
pub use event::{EventBus, EventSubscriber, LoggingSubscriber, WorkflowEvent};
|
pub use event::{EventBus, EventSubscriber, LoggingSubscriber, WorkflowEvent};
|
||||||
|
|||||||
Reference in New Issue
Block a user