exegraph

package
v1.25.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 9, 2026 License: MIT Imports: 13 Imported by: 0

Documentation

Overview

Package exegraph provides an execution graph engine for running named steps with explicit dependencies and maximum parallelism.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func IsStepSkipped

func IsStepSkipped(err error) bool

IsStepSkipped returns true if the error (or any error in its chain) is a StepSkippedError.

func Run

func Run(ctx context.Context, g *Graph, opts RunOptions) (err error)

Run executes all steps in the graph respecting dependency order, with bounded concurrency. It returns nil if all steps succeed, or a combined error describing all failures.

The returned error may contain both genuine step failures and StepSkippedError values (for steps whose dependencies failed). Use RunWithResult when you need to distinguish failures from transitive skips via [RunResult.Steps].

Types

type ErrorPolicy

type ErrorPolicy int

ErrorPolicy controls how the scheduler handles step failures.

const (
	// FailFast cancels all in-flight steps when the first step fails.
	FailFast ErrorPolicy = iota

	// ContinueOnError lets all independent steps run to completion and
	// aggregates errors at the end. Steps whose dependencies failed are skipped.
	ContinueOnError
)

func (ErrorPolicy) String

func (p ErrorPolicy) String() string

String returns the string representation of the ErrorPolicy.

type Graph

type Graph struct {
	// contains filtered or unexported fields
}

Graph holds a set of named steps with dependency edges. Steps are added via [AddStep] and the graph is validated via [Validate] before execution. Graph is not safe for concurrent use during construction; build it in a single goroutine, then pass it to Run.

func NewGraph

func NewGraph() *Graph

NewGraph creates an empty graph.

func (*Graph) AddStep

func (g *Graph) AddStep(s *Step) error

AddStep registers a step. Returns an error if the step is nil, the name is empty, the Action is nil, or a step with the same name already exists.

func (*Graph) Len

func (g *Graph) Len() int

Len returns the number of steps in the graph.

func (*Graph) Priority

func (g *Graph) Priority(name string) int

Priority returns the transitive dependent count for the given step. Steps with a higher count sit on wider critical paths and should be started first. The result is cached and computed once across all steps on first call.

func (*Graph) Steps

func (g *Graph) Steps() []*Step

Steps returns all registered steps in insertion order. The returned slice is a new allocation, but the Step pointers are shared with the graph's internals. Callers must not modify the returned Step values.

func (*Graph) Validate

func (g *Graph) Validate() error

Validate checks the graph for missing dependency references and cycles. It returns a descriptive error if any problems are found.

type RunOptions

type RunOptions struct {
	// MaxConcurrency limits the number of steps running simultaneously.
	// Zero (the default) caps at GOMAXPROCS×2; a positive value is honored
	// as the upper bound (useful to bump or cap for IO-bound workloads).
	// Negative values are treated as zero.
	MaxConcurrency int

	// ErrorPolicy determines behavior on step failure.
	ErrorPolicy ErrorPolicy

	// StepTimeout imposes a per-step deadline. When positive, each step's
	// context is wrapped with context.WithTimeout before execution. If the
	// step does not complete within the duration the context expires with
	// context.DeadlineExceeded, which the scheduler treats as a normal step
	// failure (respecting ErrorPolicy). Zero (the default) means no per-step
	// timeout is applied.
	StepTimeout time.Duration

	// OnStepStart is called (if non-nil) when a step begins execution.
	// It is invoked from worker goroutines and must be safe for concurrent use.
	OnStepStart func(stepName string)

	// OnStepDone is called (if non-nil) when a step finishes, with a nil error on success.
	// It is invoked from worker goroutines and must be safe for concurrent use.
	OnStepDone func(stepName string, err error)
}

RunOptions configures the execution graph scheduler.

type RunResult

type RunResult struct {
	// Steps contains timing for every step in execution order (by completion time).
	Steps []StepTiming

	// TotalDuration is the wall-clock time from the first step starting to the
	// last step completing.
	TotalDuration time.Duration

	// Error is the combined error from all failed/skipped steps (same as Run returns).
	Error error
}

RunResult captures the outcome of a graph execution including per-step timing.

func RunWithResult

func RunWithResult(ctx context.Context, g *Graph, opts RunOptions) (result *RunResult)

RunWithResult executes all steps in the graph and returns a RunResult containing per-step timing, status, and aggregate error. This is the instrumented variant of Run for callers that need execution telemetry.

type Step

type Step struct {
	// Name uniquely identifies the step within a graph (e.g., "provision-networking").
	Name string

	// DependsOn lists the names of steps that must complete successfully before
	// this step can start.
	DependsOn []string

	// Tags are optional labels for querying related steps (e.g., "provision", "deploy").
	Tags []string

	// Action is the function to execute when all dependencies are satisfied.
	Action StepFunc
}

Step is a named unit of work with explicit dependencies on other steps.

type StepFunc

type StepFunc func(ctx context.Context) error

StepFunc is the function a step executes. It receives a context that is canceled when the scheduler shuts down (FailFast policy) or the parent context is canceled.

type StepSkippedError

type StepSkippedError struct {
	StepName string
}

StepSkippedError indicates a step was not executed because one of its dependencies failed. Consumers can check for this with errors.As to distinguish "skipped due to dependency failure" from "step itself failed."

func (*StepSkippedError) Error

func (e *StepSkippedError) Error() string

type StepStatus

type StepStatus int

StepStatus represents the lifecycle state of a step during execution.

const (
	StepPending StepStatus = iota // StepPending means the step has not yet started.
	StepRunning                   // StepRunning means the step is currently executing.
	StepDone                      // StepDone means the step completed successfully.
	StepFailed                    // StepFailed means the step completed with an error.
	StepSkipped                   // StepSkipped means the step was not executed (e.g. due to upstream failure).
)

func (StepStatus) String

func (s StepStatus) String() string

String returns the string representation of the StepStatus.

type StepTiming

type StepTiming struct {
	Name     string
	Status   StepStatus
	Start    time.Time
	End      time.Time
	Duration time.Duration
	Tags     []string
	Err      error
}

StepTiming captures wall-clock timing for a single step.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL