-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathstep.go
More file actions
136 lines (116 loc) · 3.17 KB
/
Copy pathstep.go
File metadata and controls
136 lines (116 loc) · 3.17 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
package workflow
import (
"context"
"fmt"
"log"
"time"
)
// StepMode determines how a step processes items.
type StepMode string
const (
// Concurrent runs the step per-item, many in parallel.
Concurrent StepMode = "concurrent"
// Collective waits for all items, runs once with the full set.
Collective StepMode = "collective"
)
// Step is a named unit of work in a pipeline.
// Concurrent steps receive a single item's data.
// Collective steps receive a []CollectiveItem slice.
type Step interface {
Name() string
Mode() StepMode
Run(input any, ctx *StepContext) (any, error)
}
// CollectiveItem wraps an item ID and its data for collective steps.
type CollectiveItem struct {
ID string
Data any
}
// StepContext is passed to each step's Run function.
type StepContext struct {
ItemID string
Resources map[string]any
Log Logger
GetCache func(stepName string) (any, error)
Ctx context.Context
}
// Logger provides scoped logging for a step execution.
type Logger struct {
prefix string
}
// NewLogger creates a logger scoped to an item and step.
func NewLogger(itemID, stepName string) Logger {
return Logger{prefix: fmt.Sprintf("[%s:%s]", itemID, stepName)}
}
// Info logs an informational message.
func (l Logger) Info(msg string) {
log.Printf("%s %s", l.prefix, msg)
}
// Warn logs a warning message.
func (l Logger) Warn(msg string) {
log.Printf("%s WARN: %s", l.prefix, msg)
}
// Error logs an error message.
func (l Logger) Error(msg string) {
log.Printf("%s ERROR: %s", l.prefix, msg)
}
// WorkItem is an item flowing through the pipeline.
type WorkItem struct {
ID string
Data any
}
// ItemStatus represents the state of an item in the pipeline.
type ItemStatus string
const (
StatusPending ItemStatus = "pending"
StatusRunning ItemStatus = "running"
StatusCompleted ItemStatus = "completed"
StatusFailed ItemStatus = "failed"
)
// ItemState tracks the state of a single item in the workflow.
type ItemState struct {
ID string `json:"id"`
CurrentStep string `json:"currentStep"`
Status ItemStatus `json:"status"`
StepOutputs map[string]any `json:"stepOutputs"`
Error string `json:"error,omitempty"`
Attempts int `json:"attempts"`
CreatedAt string `json:"createdAt"`
UpdatedAt string `json:"updatedAt"`
}
// newItemState creates a fresh ItemState for an item.
func newItemState(id, firstStep string) *ItemState {
now := time.Now().UTC().Format(time.RFC3339)
return &ItemState{
ID: id,
CurrentStep: firstStep,
Status: StatusPending,
StepOutputs: make(map[string]any),
Attempts: 0,
CreatedAt: now,
UpdatedAt: now,
}
}
// WorkflowProgress reports progress during execution.
type WorkflowProgress struct {
Total int
Completed int
Failed int
Running int
CurrentStep string
}
// Options configures a workflow run.
type Options struct {
Concurrency int
MaxRetries int
OnProgress func(WorkflowProgress)
}
// applyDefaults fills in zero-value options with defaults.
func (o *Options) applyDefaults() {
if o.Concurrency <= 0 {
o.Concurrency = 5
}
if o.MaxRetries < 0 {
o.MaxRetries = 2
}
}