Documentation
¶
Overview ¶
Package flow provides structured concurrency and workflow pipelines for flow.
Package flow provides structured concurrency and workflow pipelines for flow.
Package flow provides structured concurrency and workflow pipelines for flow.
Package flow provides structured concurrency and workflow pipelines for flow.
Package flow provides structured concurrency and workflow pipelines for flow.
Index ¶
- Variables
- func DAGEdgesNWithReport[T context.Context](limit int, connections ...DAGConnection[T]) func(ctx T) (*DAGReport, error)
- func DAGEdgesToMermaid[T context.Context](connections ...DAGConnection[T]) (string, error)
- func DAGEdgesWithReport[T context.Context](connections ...DAGConnection[T]) func(ctx T) (*DAGReport, error)
- func DAGNWithReport[T context.Context](limit int, nodes ...*DAGNode[T]) func(ctx T) (*DAGReport, error)
- func DAGToMermaid[T context.Context](nodes ...*DAGNode[T]) (string, error)
- func DAGWithReport[T context.Context](nodes ...*DAGNode[T]) func(ctx T) (*DAGReport, error)
- func Pipe2[T context.Context, A, B, C any](f1 func(ctx T, a A) (B, error), f2 func(ctx T, b B) (C, error)) func(ctx T, a A) (C, error)
- func Pipe3[T context.Context, A, B, C, D any](f1 func(ctx T, a A) (B, error), f2 func(ctx T, b B) (C, error), ...) func(ctx T, a A) (D, error)
- type DAGConnection
- type DAGEdgeBuilder
- type DAGNode
- func (n *DAGNode[T]) After(deps ...string) *DAGNode[T]
- func (n *DAGNode[T]) Unless(predicate func(ctx T) bool) *DAGNode[T]
- func (n *DAGNode[T]) When(predicate func(ctx T) bool) *DAGNode[T]
- func (n *DAGNode[T]) WithFallback(fallback Step[T]) *DAGNode[T]
- func (n *DAGNode[T]) WithRetry(attempts int, delay ...time.Duration) *DAGNode[T]
- func (n *DAGNode[T]) WithTimeout(d time.Duration) *DAGNode[T]
- type DAGPlan
- func (p *DAGPlan[T]) ExecNWithReport(limit int, ctx T) (*DAGReport, error)
- func (p *DAGPlan[T]) ExecWithReport(ctx T) (*DAGReport, error)
- func (p *DAGPlan[T]) Step() Step[T]
- func (p *DAGPlan[T]) StepN(limit int) Step[T]
- func (p *DAGPlan[T]) StepNWithReport(limit int) func(ctx T) (*DAGReport, error)
- func (p *DAGPlan[T]) StepWithReport() func(ctx T) (*DAGReport, error)
- func (p *DAGPlan[T]) ToMermaid() (string, error)
- func (p *DAGPlan[T]) Validate() error
- type DAGReport
- type Middleware
- type NodeReport
- type NodeStatus
- type Step
- func Branch[T context.Context](condition func(ctx T) bool, ifBranch, elseBranch Step[T]) Step[T]
- func Chunk[T context.Context, V any](seq iter.Seq[V], size int, step func(ctx T, batch []V) error) Step[T]
- func Chunk2[T context.Context, K, V any](seq iter.Seq2[K, V], size int, step func(ctx T, keys []K, vals []V) error) Step[T]
- func DAG[T context.Context](nodes ...*DAGNode[T]) Step[T]
- func DAGEdges[T context.Context](connections ...DAGConnection[T]) Step[T]
- func DAGEdgesN[T context.Context](limit int, connections ...DAGConnection[T]) Step[T]
- func DAGN[T context.Context](limit int, nodes ...*DAGNode[T]) Step[T]
- func Dynamic[T context.Context](fn func(ctx T) Step[T]) Step[T]
- func Each[T context.Context, V any](seq iter.Seq[V], step func(ctx T, item V) error) Step[T]
- func Each2[T context.Context, K, V any](seq iter.Seq2[K, V], step func(ctx T, key K, val V) error) Step[T]
- func Go[T context.Context](steps ...Step[T]) Step[T]
- func GoN[T context.Context](limit int, steps ...Step[T]) Step[T]
- func Once[T context.Context](step Step[T]) Step[T]
- func Pipe[T context.Context, In, Out any](fn func(ctx T, in In) (Out, error), get func(ctx T) In, ...) Step[T]
- func PipeSeq[T context.Context, In, Out any](seq iter.Seq[In], transform func(ctx T, item In) (Out, error), ...) Step[T]
- func PipeSeq2[T context.Context, K, V, Out any](seq iter.Seq2[K, V], transform func(ctx T, key K, val V) (Out, error), ...) Step[T]
- func Race[T context.Context](steps ...Step[T]) Step[T]
- func Seq[T context.Context](steps ...Step[T]) Step[T]
- func (s Step[T]) Branch(condition func(ctx T) bool, ifBranch, elseBranch Step[T]) Step[T]
- func (s Step[T]) Dynamic(fn func(ctx T) Step[T]) Step[T]
- func (s Step[T]) Exec(ctx T) error
- func (s Step[T]) Fallback(fallback Step[T]) Step[T]
- func (s Step[T]) Go(steps ...Step[T]) Step[T]
- func (s Step[T]) GoN(limit int, steps ...Step[T]) Step[T]
- func (s Step[T]) Once() Step[T]
- func (s Step[T]) Race(steps ...Step[T]) Step[T]
- func (s Step[T]) Retry(attempts int, delay time.Duration) Step[T]
- func (s Step[T]) Timeout(d time.Duration) Step[T]
- func (s Step[T]) Unless(predicate func(ctx T) bool) Step[T]
- func (s Step[T]) When(predicate func(ctx T) bool) Step[T]
- func (s Step[T]) Wrap(middlewares ...Middleware[T]) Step[T]
Examples ¶
Constants ¶
This section is empty.
Variables ¶
var ( // ErrDAGCycle defines ErrDAGCycle. ErrDAGCycle = errors.New("cycle detected in DAG") // ErrDAGUnknownDependency defines ErrDAGUnknownDependency. ErrDAGUnknownDependency = errors.New("unknown dependency in DAG") // ErrDAGDuplicateNode defines ErrDAGDuplicateNode. ErrDAGDuplicateNode = errors.New("duplicate node name in DAG") // ErrDAGNilNode defines ErrDAGNilNode. ErrDAGNilNode = errors.New("nil node in DAG") // ErrDAGEmptyNodeName defines ErrDAGEmptyNodeName. ErrDAGEmptyNodeName = errors.New("empty node name in DAG") )
Functions ¶
func DAGEdgesNWithReport ¶ added in v0.6.0
func DAGEdgesNWithReport[T context.Context](limit int, connections ...DAGConnection[T]) func(ctx T) (*DAGReport, error)
DAGEdgesNWithReport performs the DAGEdgesNWithReport operation.
func DAGEdgesToMermaid ¶ added in v0.4.0
func DAGEdgesToMermaid[T context.Context](connections ...DAGConnection[T]) (string, error)
DAGEdgesToMermaid performs the DAGEdgesToMermaid operation.
func DAGEdgesWithReport ¶ added in v0.6.0
func DAGEdgesWithReport[T context.Context](connections ...DAGConnection[T]) func(ctx T) (*DAGReport, error)
DAGEdgesWithReport performs the DAGEdgesWithReport operation.
func DAGNWithReport ¶ added in v0.6.0
func DAGNWithReport[T context.Context](limit int, nodes ...*DAGNode[T]) func(ctx T) (*DAGReport, error)
DAGNWithReport performs the DAGNWithReport operation.
func DAGToMermaid ¶ added in v0.4.0
DAGToMermaid performs the DAGToMermaid operation.
Example ¶
package main
import (
"context"
"fmt"
"github.com/ntkwan/go-flow"
)
func main() {
user := flow.Node("user", func(ctx context.Context) error { return nil })
payment := flow.Node("payment", func(ctx context.Context) error { return nil }).After("user")
mermaid, err := flow.DAGToMermaid(user, payment)
if err != nil {
panic(err)
}
fmt.Println(len(mermaid) > 0)
}
Output:
func DAGWithReport ¶ added in v0.6.0
DAGWithReport performs the DAGWithReport operation.
Example ¶
package main
import (
"context"
"fmt"
"github.com/ntkwan/go-flow"
)
func main() {
user := flow.Node("user", func(ctx context.Context) error { return nil })
payment := flow.Node("payment", func(ctx context.Context) error { return nil }).After("user")
exec := flow.DAGWithReport(user, payment)
report, err := exec(context.Background())
if err != nil {
panic(err)
}
for _, n := range report.Nodes {
fmt.Printf("%s: %s\n", n.Name, n.Status)
}
}
Output:
Types ¶
type DAGConnection ¶
DAGConnection represents DAGConnection.
type DAGEdgeBuilder ¶
DAGEdgeBuilder represents DAGEdgeBuilder.
func From ¶
func From[T context.Context](from Step[T]) DAGEdgeBuilder[T]
From performs the From operation.
func (DAGEdgeBuilder[T]) To ¶
func (b DAGEdgeBuilder[T]) To(to ...Step[T]) DAGConnection[T]
To executes the To operation.
type DAGNode ¶
DAGNode represents DAGNode.
func (*DAGNode[T]) WithFallback ¶ added in v0.6.0
WithFallback executes the WithFallback operation.
type DAGPlan ¶ added in v0.4.0
DAGPlan represents DAGPlan.
func NewDAG ¶ added in v0.4.0
NewDAG performs the NewDAG operation.
Example ¶
package main
import (
"context"
"github.com/ntkwan/go-flow"
)
func main() {
user := flow.Node("user", func(ctx context.Context) error { return nil })
payment := flow.Node("payment", func(ctx context.Context) error { return nil }).After("user")
plan := flow.NewDAG(user, payment)
if err := plan.Validate(); err != nil {
panic(err)
}
step := plan.Step()
_ = step(context.Background())
}
Output:
func NewDAGEdges ¶ added in v0.4.0
func NewDAGEdges[T context.Context](connections ...DAGConnection[T]) (*DAGPlan[T], error)
NewDAGEdges performs the NewDAGEdges operation.
func (*DAGPlan[T]) ExecNWithReport ¶ added in v0.6.0
ExecNWithReport executes the ExecNWithReport operation.
func (*DAGPlan[T]) ExecWithReport ¶ added in v0.6.0
ExecWithReport executes the ExecWithReport operation.
func (*DAGPlan[T]) StepNWithReport ¶ added in v0.6.0
StepNWithReport executes the StepNWithReport operation.
func (*DAGPlan[T]) StepWithReport ¶ added in v0.6.0
StepWithReport executes the StepWithReport operation.
type DAGReport ¶ added in v0.6.0
type DAGReport struct {
Duration time.Duration
StartTime time.Time
EndTime time.Time
Nodes []NodeReport
// contains filtered or unexported fields
}
DAGReport represents DAGReport.
func (*DAGReport) Failed ¶ added in v0.6.0
func (r *DAGReport) Failed() []NodeReport
Failed executes the Failed operation.
func (*DAGReport) Node ¶ added in v0.6.0
func (r *DAGReport) Node(name string) *NodeReport
Node executes the Node operation.
func (*DAGReport) Skipped ¶ added in v0.6.0
func (r *DAGReport) Skipped() []NodeReport
Skipped executes the Skipped operation.
func (*DAGReport) Successful ¶ added in v0.6.0
func (r *DAGReport) Successful() []NodeReport
Successful executes the Successful operation.
type Middleware ¶
Middleware represents Middleware.
func Recovery ¶ added in v0.8.0
func Recovery[T context.Context]() Middleware[T]
Recovery performs the Recovery operation.
Example ¶
package main
import (
"context"
"fmt"
"github.com/ntkwan/go-flow"
)
func main() {
riskyStep := flow.Step[context.Context](func(ctx context.Context) error {
panic("database connection lost")
})
guarded := riskyStep.Wrap(flow.Recovery[context.Context]())
err := guarded.Exec(context.Background())
fmt.Println("Recovered from panic:", err != nil)
}
Output:
type NodeReport ¶ added in v0.6.0
type NodeReport struct {
Name string
Status NodeStatus
Duration time.Duration
StartTime time.Time
EndTime time.Time
Err error
}
NodeReport represents NodeReport.
type NodeStatus ¶ added in v0.6.0
type NodeStatus string
NodeStatus represents NodeStatus.
const ( // NodeStatusSuccess defines NodeStatusSuccess. NodeStatusSuccess NodeStatus = "SUCCESS" // NodeStatusFailed defines NodeStatusFailed. NodeStatusFailed NodeStatus = "FAILED" // NodeStatusSkipped defines NodeStatusSkipped. NodeStatusSkipped NodeStatus = "SKIPPED" )
type Step ¶
Step represents Step.
func Branch ¶ added in v0.3.0
Branch performs the Branch operation.
Example ¶
package main
import (
"context"
"fmt"
"github.com/ntkwan/go-flow"
)
func main() {
type RequestContext struct {
context.Context
IsAdmin bool
}
adminStep := func(ctx *RequestContext) error {
fmt.Println("Admin flow")
return nil
}
userStep := func(ctx *RequestContext) error {
fmt.Println("User flow")
return nil
}
route := flow.Branch(
func(ctx *RequestContext) bool { return ctx.IsAdmin },
adminStep,
userStep,
)
ctx := &RequestContext{Context: context.Background(), IsAdmin: true}
_ = route(ctx)
}
Output:
func Chunk ¶
func Chunk[T context.Context, V any](seq iter.Seq[V], size int, step func(ctx T, batch []V) error) Step[T]
Chunk performs the Chunk operation.
Example ¶
package main
import (
"context"
"fmt"
"slices"
"github.com/ntkwan/go-flow"
)
func main() {
numbers := []int{1, 2, 3, 4, 5, 6, 7}
batchProcess := flow.Chunk(slices.Values(numbers), 3, func(ctx context.Context, batch []int) error {
fmt.Printf("Batch of %d items: %v\n", len(batch), batch)
return nil
})
_ = batchProcess(context.Background())
}
Output:
func Chunk2 ¶
func Chunk2[T context.Context, K, V any](seq iter.Seq2[K, V], size int, step func(ctx T, keys []K, vals []V) error) Step[T]
Chunk2 performs the Chunk2 operation.
func DAG ¶
DAG performs the DAG operation.
Example ¶
package main
import (
"context"
"fmt"
"github.com/ntkwan/go-flow"
)
func main() {
user := flow.Node("user", func(ctx context.Context) error {
fmt.Println("User loaded")
return nil
})
inventory := flow.Node("inventory", func(ctx context.Context) error {
fmt.Println("Inventory reserved")
return nil
})
payment := flow.Node("payment", func(ctx context.Context) error {
fmt.Println("Payment charged")
return nil
}).After("user", "inventory")
graph := flow.DAG(user, inventory, payment)
_ = graph(context.Background())
}
Output:
Example (Conditional) ¶
package main
import (
"context"
"github.com/ntkwan/go-flow"
)
func main() {
type userContext struct {
context.Context
isPremium bool
}
baseTask := flow.Node("base", func(ctx *userContext) error { return nil })
bonusTask := flow.Node("bonus", func(ctx *userContext) error { return nil }).
After("base").
When(func(ctx *userContext) bool { return ctx.isPremium })
graph := flow.DAG(baseTask, bonusTask)
_ = graph(&userContext{Context: context.Background(), isPremium: false})
}
Output:
func DAGEdges ¶
func DAGEdges[T context.Context](connections ...DAGConnection[T]) Step[T]
DAGEdges performs the DAGEdges operation.
Example ¶
package main
import (
"context"
"fmt"
"github.com/ntkwan/go-flow"
)
func main() {
fetchUser := func(ctx context.Context) error {
fmt.Println("Fetch user")
return nil
}
chargePayment := func(ctx context.Context) error {
fmt.Println("Charge payment")
return nil
}
graph := flow.DAGEdges(
flow.From(fetchUser).To(chargePayment),
)
_ = graph(context.Background())
}
Output:
func DAGEdgesN ¶
func DAGEdgesN[T context.Context](limit int, connections ...DAGConnection[T]) Step[T]
DAGEdgesN performs the DAGEdgesN operation.
func DAGN ¶
DAGN performs the DAGN operation.
Example ¶
package main
import (
"context"
"github.com/ntkwan/go-flow"
)
func main() {
n1 := flow.Node("task1", func(ctx context.Context) error { return nil })
n2 := flow.Node("task2", func(ctx context.Context) error { return nil })
n3 := flow.Node("task3", func(ctx context.Context) error { return nil })
boundedGraph := flow.DAGN(2, n1, n2, n3)
_ = boundedGraph(context.Background())
}
Output:
func Each ¶
Each performs the Each operation.
Example ¶
package main
import (
"context"
"fmt"
"slices"
"github.com/ntkwan/go-flow"
)
func main() {
items := slices.Values([]string{"apple", "banana", "cherry"})
process := flow.Each(items, func(ctx context.Context, item string) error {
fmt.Println("Processing:", item)
return nil
})
_ = process(context.Background())
}
Output:
func Each2 ¶
func Each2[T context.Context, K, V any](seq iter.Seq2[K, V], step func(ctx T, key K, val V) error) Step[T]
Each2 performs the Each2 operation.
func Go ¶
Go performs the Go operation.
Example ¶
package main
import (
"context"
"fmt"
"github.com/ntkwan/go-flow"
)
func main() {
stepA := func(ctx context.Context) error {
fmt.Println("Task A")
return nil
}
stepB := func(ctx context.Context) error {
fmt.Println("Task B")
return nil
}
parallel := flow.Go(stepA, stepB)
_ = parallel(context.Background())
}
Output:
func GoN ¶
GoN performs the GoN operation.
Example ¶
package main
import (
"context"
"fmt"
"github.com/ntkwan/go-flow"
)
func main() {
tasks := make([]flow.Step[context.Context], 5)
for i := range tasks {
idx := i
tasks[i] = func(ctx context.Context) error {
fmt.Printf("Worker task %d\n", idx)
return nil
}
}
bounded := flow.GoN(2, tasks...)
_ = bounded(context.Background())
}
Output:
func Once ¶
Once performs the Once operation.
Example ¶
package main
import (
"context"
"fmt"
"github.com/ntkwan/go-flow"
)
func main() {
initDB := flow.Once(func(ctx context.Context) error {
fmt.Println("Database initialized once")
return nil
})
step1 := flow.Seq(initDB, func(ctx context.Context) error { return nil })
step2 := flow.Seq(initDB, func(ctx context.Context) error { return nil })
pipeline := flow.Go(step1, step2)
_ = pipeline(context.Background())
}
Output:
func Pipe ¶ added in v0.3.0
func Pipe[T context.Context, In, Out any]( fn func(ctx T, in In) (Out, error), get func(ctx T) In, set func(ctx T, out Out), ) Step[T]
Pipe performs the Pipe operation.
Example ¶
package main
import (
"context"
"fmt"
"github.com/ntkwan/go-flow"
)
func main() {
type State struct {
Count int
}
st := &State{Count: 5}
doubleCount := flow.Pipe(
func(ctx context.Context, in int) (int, error) {
return in * 2, nil
},
func(ctx context.Context) int {
return st.Count
},
func(ctx context.Context, out int) {
st.Count = out
},
)
_ = doubleCount(context.Background())
fmt.Printf("Result: %d\n", st.Count)
}
Output:
func PipeSeq ¶ added in v0.3.0
func PipeSeq[T context.Context, In, Out any]( seq iter.Seq[In], transform func(ctx T, item In) (Out, error), sink func(ctx T, item Out) error, ) Step[T]
PipeSeq performs the PipeSeq operation.
Example ¶
package main
import (
"context"
"fmt"
"slices"
"github.com/ntkwan/go-flow"
)
func main() {
numbers := slices.Values([]int{1, 2, 3})
stream := flow.PipeSeq(
numbers,
func(ctx context.Context, in int) (string, error) {
return fmt.Sprintf("val-%d", in*10), nil
},
func(ctx context.Context, out string) error {
fmt.Println(out)
return nil
},
)
_ = stream(context.Background())
}
Output:
func PipeSeq2 ¶ added in v0.3.0
func PipeSeq2[T context.Context, K, V, Out any]( seq iter.Seq2[K, V], transform func(ctx T, key K, val V) (Out, error), sink func(ctx T, item Out) error, ) Step[T]
PipeSeq2 performs the PipeSeq2 operation.
func Race ¶
Race performs the Race operation.
Example ¶
package main
import (
"context"
"fmt"
"time"
"github.com/ntkwan/go-flow"
)
func main() {
server1 := func(ctx context.Context) error {
time.Sleep(10 * time.Millisecond)
fmt.Println("Server 1 responded")
return nil
}
server2 := func(ctx context.Context) error {
fmt.Println("Server 2 responded fastest")
return nil
}
fastest := flow.Race(server1, server2)
_ = fastest(context.Background())
}
Output:
func Seq ¶
Seq performs the Seq operation.
Example ¶
package main
import (
"context"
"fmt"
"github.com/ntkwan/go-flow"
)
func main() {
step1 := func(ctx context.Context) error {
fmt.Println("Step 1")
return nil
}
step2 := func(ctx context.Context) error {
fmt.Println("Step 2")
return nil
}
pipeline := flow.Seq(step1, step2)
_ = pipeline(context.Background())
}
Output:
func (Step[T]) Fallback ¶
Fallback executes the Fallback operation.
Example ¶
package main
import (
"context"
"fmt"
"github.com/ntkwan/go-flow"
)
func main() {
failingPrimary := flow.Step[context.Context](func(ctx context.Context) error {
return fmt.Errorf("primary service down")
})
backupService := flow.Step[context.Context](func(ctx context.Context) error {
fmt.Println("Backup service handled request")
return nil
})
protected := failingPrimary.Fallback(backupService)
_ = protected.Exec(context.Background())
}
Output:
func (Step[T]) Retry ¶
Retry executes the Retry operation.
Example ¶
package main
import (
"context"
"fmt"
"time"
"github.com/ntkwan/go-flow"
)
func main() {
attempts := 0
flaky := flow.Step[context.Context](func(ctx context.Context) error {
attempts++
if attempts < 3 {
return fmt.Errorf("temporary failure %d", attempts)
}
fmt.Println("Succeeded on attempt 3")
return nil
})
resilient := flaky.Retry(3, 10*time.Millisecond)
_ = resilient.Exec(context.Background())
}
Output:
func (Step[T]) Timeout ¶
Timeout executes the Timeout operation.
Example ¶
package main
import (
"context"
"fmt"
"time"
"github.com/ntkwan/go-flow"
)
func main() {
slow := flow.Step[context.Context](func(ctx context.Context) error {
time.Sleep(50 * time.Millisecond)
return nil
})
timed := slow.Timeout(10 * time.Millisecond)
err := timed.Exec(context.Background())
fmt.Println("Error:", err != nil)
}
Output:
func (Step[T]) When ¶
When executes the When operation.
Example ¶
package main
import (
"context"
"fmt"
"github.com/ntkwan/go-flow"
)
func main() {
type OrderContext struct {
context.Context
IsVIP bool
}
vipGift := flow.Step[*OrderContext](func(ctx *OrderContext) error {
fmt.Println("VIP gift applied")
return nil
}).When(func(ctx *OrderContext) bool {
return ctx.IsVIP
})
ctx := &OrderContext{Context: context.Background(), IsVIP: true}
_ = vipGift.Exec(ctx)
}
Output:
func (Step[T]) Wrap ¶
func (s Step[T]) Wrap(middlewares ...Middleware[T]) Step[T]
Wrap executes the Wrap operation.
Example ¶
package main
import (
"context"
"fmt"
"github.com/ntkwan/go-flow"
)
func main() {
base := flow.Step[context.Context](func(ctx context.Context) error {
fmt.Println("Core logic")
return nil
})
loggingMiddleware := func(next flow.Step[context.Context]) flow.Step[context.Context] {
return func(ctx context.Context) error {
fmt.Println("Before step")
err := next(ctx)
fmt.Println("After step")
return err
}
}
wrapped := base.Wrap(loggingMiddleware)
_ = wrapped.Exec(context.Background())
}
Output:
Directories
¶
| Path | Synopsis |
|---|---|
|
cmd
|
|
|
godoc-scaffold
command
Package main provides a tool to inspect and scaffold missing GoDoc comments across the codebase.
|
Package main provides a tool to inspect and scaffold missing GoDoc comments across the codebase. |