pub struct DependencyGraph { /* private fields */ }Expand description
A directed-acyclic graph (DAG) of tasks with metadata only.
Stores nodes, edges, and scheduling hints without holding compute closures. Use this for planning, critical-path analysis, and dependency validation.
Implementations§
Source§impl DependencyGraph
impl DependencyGraph
Sourcepub fn new(config: DependencyGraphConfig) -> Self
pub fn new(config: DependencyGraphConfig) -> Self
Create an empty graph with the given configuration.
Sourcepub fn add_task(&mut self, name: &str, priority: i32) -> TaskId
pub fn add_task(&mut self, name: &str, priority: i32) -> TaskId
Add a task with name and priority. Returns the new task’s TaskId.
Sourcepub fn add_task_with_cost(
&mut self,
name: &str,
priority: i32,
cost: f64,
) -> TaskId
pub fn add_task_with_cost( &mut self, name: &str, priority: i32, cost: f64, ) -> TaskId
Add a task with name, priority, and estimated cost. Returns the task’s TaskId.
Sourcepub fn add_dependency(&mut self, task: TaskId, dep: TaskId) -> CoreResult<()>
pub fn add_dependency(&mut self, task: TaskId, dep: TaskId) -> CoreResult<()>
Declare that task depends on dep — dep must complete before task.
When enable_cycle_detection is set, this checks for cycles before adding the edge.
§Errors
Returns CoreError::InvalidInput if either ID is unknown, if this is a self-loop,
or if adding the edge would create a cycle (when cycle detection is enabled).
Sourcepub fn get_task(&self, id: TaskId) -> Option<&DepTaskNode>
pub fn get_task(&self, id: TaskId) -> Option<&DepTaskNode>
Return a reference to the task node for id, or None if not found.
Sourcepub fn dependencies(&self, id: TaskId) -> &[TaskId] ⓘ
pub fn dependencies(&self, id: TaskId) -> &[TaskId] ⓘ
Return the list of tasks that id directly depends on.
Sourcepub fn dependents(&self, id: TaskId) -> Vec<TaskId> ⓘ
pub fn dependents(&self, id: TaskId) -> Vec<TaskId> ⓘ
Compute the list of tasks that directly depend on id (reverse edges).
Sourcepub fn is_ready(&self, id: TaskId, completed: &HashSet<TaskId>) -> bool
pub fn is_ready(&self, id: TaskId, completed: &HashSet<TaskId>) -> bool
Return true if id is ready to run (all direct dependencies are in completed).
Sourcepub fn topological_sort(&self) -> CoreResult<Vec<TaskId>>
pub fn topological_sort(&self) -> CoreResult<Vec<TaskId>>
Compute a topological ordering using the algorithm specified in the config.
Returns Err if the graph contains a cycle.
Sourcepub fn topological_sort_kahn(&self) -> CoreResult<Vec<TaskId>>
pub fn topological_sort_kahn(&self) -> CoreResult<Vec<TaskId>>
Kahn’s algorithm (BFS-based topological sort).
Returns Err if a cycle is detected.
Sourcepub fn topological_sort_dfs(&self) -> CoreResult<Vec<TaskId>>
pub fn topological_sort_dfs(&self) -> CoreResult<Vec<TaskId>>
DFS-based topological sort (finishing-time approach, Tarjan 1976).
Follows the forward dependency direction (from predecessors to dependents) in DFS post-order. Emitting tasks in post-order and reversing produces a valid topological ordering where all predecessors appear before their dependents.
Returns Err if a cycle is detected.
Sourcepub fn find_cycles(&self) -> Vec<Vec<TaskId>>
pub fn find_cycles(&self) -> Vec<Vec<TaskId>>
Find all simple cycles in the graph.
Returns each cycle as a Vec<TaskId> listing the nodes in cycle order.
Returns an empty Vec if the graph is acyclic.
Sourcepub fn critical_path(&self) -> Vec<TaskId> ⓘ
pub fn critical_path(&self) -> Vec<TaskId> ⓘ
Compute the critical path — the longest chain from a source to a sink,
weighted by estimated_cost.
Returns the ordered sequence of task IDs along that path.
Returns an empty Vec if the graph is empty or contains a cycle.
Sourcepub fn execution_layers(&self) -> CoreResult<Vec<Vec<TaskId>>>
pub fn execution_layers(&self) -> CoreResult<Vec<Vec<TaskId>>>
Group tasks into execution layers.
Layer 0 contains all tasks with no dependencies.
Layer k contains all tasks whose dependencies are in layers < k.
Returns Err if the graph contains a cycle.
Sourcepub fn parallel_schedule(
&self,
n_workers: usize,
) -> CoreResult<Vec<Vec<TaskId>>>
pub fn parallel_schedule( &self, n_workers: usize, ) -> CoreResult<Vec<Vec<TaskId>>>
Assign tasks to n_workers workers respecting dependencies.
Returns schedule[worker_id] = [task_id, ...]. Uses a greedy list-scheduling
heuristic: assign the longest remaining task to the worker that becomes free first.
Returns Err if the graph contains a cycle.
Auto Trait Implementations§
impl Freeze for DependencyGraph
impl RefUnwindSafe for DependencyGraph
impl Send for DependencyGraph
impl Sync for DependencyGraph
impl Unpin for DependencyGraph
impl UnsafeUnpin for DependencyGraph
impl UnwindSafe for DependencyGraph
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CheckedAs for T
impl<T> CheckedAs for T
Source§fn checked_as<Dst>(self) -> Option<Dst>where
T: CheckedCast<Dst>,
fn checked_as<Dst>(self) -> Option<Dst>where
T: CheckedCast<Dst>,
Source§impl<Src, Dst> CheckedCastFrom<Src> for Dstwhere
Src: CheckedCast<Dst>,
impl<Src, Dst> CheckedCastFrom<Src> for Dstwhere
Src: CheckedCast<Dst>,
Source§fn checked_cast_from(src: Src) -> Option<Dst>
fn checked_cast_from(src: Src) -> Option<Dst>
Source§impl<T> FutureExt for T
impl<T> FutureExt for T
Source§fn with_context(self, otel_cx: Context) -> WithContext<Self>
fn with_context(self, otel_cx: Context) -> WithContext<Self>
Source§fn with_current_context(self) -> WithContext<Self>
fn with_current_context(self) -> WithContext<Self>
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§impl<T> IntoRequest<T> for T
impl<T> IntoRequest<T> for T
Source§fn into_request(self) -> Request<T>
fn into_request(self) -> Request<T>
T in a tonic::RequestSource§impl<Src, Dst> LosslessTryInto<Dst> for Srcwhere
Dst: LosslessTryFrom<Src>,
impl<Src, Dst> LosslessTryInto<Dst> for Srcwhere
Dst: LosslessTryFrom<Src>,
Source§fn lossless_try_into(self) -> Option<Dst>
fn lossless_try_into(self) -> Option<Dst>
Source§impl<Src, Dst> LossyInto<Dst> for Srcwhere
Dst: LossyFrom<Src>,
impl<Src, Dst> LossyInto<Dst> for Srcwhere
Dst: LossyFrom<Src>,
Source§fn lossy_into(self) -> Dst
fn lossy_into(self) -> Dst
Source§impl<T> OverflowingAs for T
impl<T> OverflowingAs for T
Source§fn overflowing_as<Dst>(self) -> (Dst, bool)where
T: OverflowingCast<Dst>,
fn overflowing_as<Dst>(self) -> (Dst, bool)where
T: OverflowingCast<Dst>,
Source§impl<Src, Dst> OverflowingCastFrom<Src> for Dstwhere
Src: OverflowingCast<Dst>,
impl<Src, Dst> OverflowingCastFrom<Src> for Dstwhere
Src: OverflowingCast<Dst>,
Source§fn overflowing_cast_from(src: Src) -> (Dst, bool)
fn overflowing_cast_from(src: Src) -> (Dst, bool)
Source§impl<T> Pointable for T
impl<T> Pointable for T
Source§impl<T> PolicyExt for Twhere
T: ?Sized,
impl<T> PolicyExt for Twhere
T: ?Sized,
Source§impl<T> SaturatingAs for T
impl<T> SaturatingAs for T
Source§fn saturating_as<Dst>(self) -> Dstwhere
T: SaturatingCast<Dst>,
fn saturating_as<Dst>(self) -> Dstwhere
T: SaturatingCast<Dst>,
Source§impl<Src, Dst> SaturatingCastFrom<Src> for Dstwhere
Src: SaturatingCast<Dst>,
impl<Src, Dst> SaturatingCastFrom<Src> for Dstwhere
Src: SaturatingCast<Dst>,
Source§fn saturating_cast_from(src: Src) -> Dst
fn saturating_cast_from(src: Src) -> Dst
Source§impl<T> StrictAs for T
impl<T> StrictAs for T
Source§fn strict_as<Dst>(self) -> Dstwhere
T: StrictCast<Dst>,
fn strict_as<Dst>(self) -> Dstwhere
T: StrictCast<Dst>,
Source§impl<Src, Dst> StrictCastFrom<Src> for Dstwhere
Src: StrictCast<Dst>,
impl<Src, Dst> StrictCastFrom<Src> for Dstwhere
Src: StrictCast<Dst>,
Source§fn strict_cast_from(src: Src) -> Dst
fn strict_cast_from(src: Src) -> Dst
Source§impl<SS, SP> SupersetOf<SS> for SPwhere
SS: SubsetOf<SP>,
impl<SS, SP> SupersetOf<SS> for SPwhere
SS: SubsetOf<SP>,
Source§fn to_subset(&self) -> Option<SS>
fn to_subset(&self) -> Option<SS>
self from the equivalent element of its
superset. Read moreSource§fn is_in_subset(&self) -> bool
fn is_in_subset(&self) -> bool
self is actually part of its subset T (and can be converted to it).Source§fn to_subset_unchecked(&self) -> SS
fn to_subset_unchecked(&self) -> SS
self.to_subset but without any property checks. Always succeeds.Source§fn from_subset(element: &SS) -> SP
fn from_subset(element: &SS) -> SP
self to the equivalent element of its superset.