Documentation
¶
Overview ¶
Package flow runs durable multi-step jobs as Francis workflows inside coordinator runs. The run stays the source of truth for status, the Jobs UI, and Activity; the workflow instance is its execution graph.
Migrating a job:
- Write each step as a func(ctx context.Context, t flow.Task) (any, error), inline in the definition unless it is shared or too complex to inline. Return common.Classify(common.ErrUnavailable or common.ErrTimeout, err) to retry; other errors fail the task. Tasks run at least once, so confirm external effects before repeating them.
- Keep inputs and outputs small: keys, not lists of data, since Francis ships the instance input with every task. Keep data in domain tables and never put secrets in a payload.
- Define the workflow with Engine.Define in a RegisterWorkflows method called from the service's DI provider. The last step returns scheduler.Outcome.
- Register a flow.Job in place of the old job.
- Cover the definition with flowtest.AssertDefinitions. On any graph or policy change, bump Version and set Fingerprint to the value the test reports.
Index ¶
- Variables
- func Retryable(err error) bool
- type Activities
- type Binding
- type Definition
- type Engine
- func (e *Engine) Define(def Definition) (*Workflow, error)
- func (e *Engine) Handler(fn func(ctx context.Context, t Task) (any, error)) workflow.StepOption
- func (e *Engine) Ready()
- func (e *Engine) Resume(ctx context.Context, wf *Workflow, run scheduler.Run) (scheduler.Outcome, error)
- func (e *Engine) Retire(ctx context.Context, wf *Workflow, run scheduler.Run, reason string) (outcome scheduler.Outcome, finished bool, err error)
- func (e *Engine) Run(ctx context.Context, wf *Workflow, payload any, ...) (scheduler.Outcome, error)
- func (e *Engine) Standalone(ctx context.Context) ([]scheduler.Run, error)
- func (e *Engine) Start(ctx context.Context) error
- func (e *Engine) Stop(context.Context) error
- func (e *Engine) Submit(ctx context.Context, wf *Workflow, payload any, ...) (string, error)
- func (e *Engine) Wait(ctx context.Context, wf *Workflow, instanceID string) (scheduler.Outcome, error)
- func (e *Engine) Workflows() []*Workflow
- type Job
- func (j *Job) Name() string
- func (j *Job) Reconcile(ctx context.Context, previous scheduler.Run) (scheduler.Outcome, error)
- func (j *Job) Run(ctx context.Context) (scheduler.Outcome, error)
- func (j *Job) Schedule(ctx context.Context) string
- func (j *Job) ShouldSchedule(ctx context.Context) bool
- func (j *Job) ValidateRetry(ctx context.Context, run scheduler.Run) error
- type Result
- type Task
- type Workflow
Constants ¶
This section is empty.
Variables ¶
var ( // ErrNotResumable reports that a run has no workflow instance this host can serve. ErrNotResumable = errors.New("workflow instance cannot be resumed") )
Functions ¶
Types ¶
type Activities ¶
type Activities interface {
activitylib.Service
activitylib.MessageAppender
activitylib.Tracker
UpdateActivity(ctx context.Context, activityID string, req activitylib.UpdateRequest) (*activitytypes.Activity, error)
AwaitActivitySlotBounded(ctx context.Context, activityID, environmentID string) error
}
Activities is the activity service surface the engine drives.
type Binding ¶
type Binding struct {
EnvironmentID string `json:"environmentId,omitempty"`
JobID string `json:"jobId,omitempty"`
RunID string `json:"runId,omitempty"`
RootID string `json:"rootId"`
}
Binding ties an instance, and its children, to the run that started it.
type Definition ¶
type Definition struct {
Name string
Version int
Fingerprint string
Concurrency int
Timeout time.Duration
// Activity is the template for the activity each root instance owns; an empty Type means none.
Activity activitylib.StartRequest
// Labels name steps on the activity; steps without one show their name.
Labels map[string]string
// Steps use Francis step builders with handlers wrapped by Engine.Handler.
// The last step returns scheduler.Outcome.
Steps []workflow.StepSpec
Options []workflow.Option
}
Definition declares a workflow. Bump Version and update Fingerprint on any graph or policy change; flowtest.AssertDefinitions reports the new value.
type Engine ¶
type Engine struct {
// contains filtered or unexported fields
}
Engine defines workflows, runs them inside coordinator runs, and owns their activities.
func New ¶
func New(appCtx context.Context, runtime *francis.Runtime, coordinator *runs.Coordinator, activities Activities) (*Engine, error)
New builds an engine whose monitors live until appCtx ends or Stop is called.
func (*Engine) Define ¶
func (e *Engine) Define(def Definition) (*Workflow, error)
Define validates and registers a workflow. It must run before the host starts.
func (*Engine) Handler ¶
Handler wraps a step handler. Its ctx carries the bound run exactly as a job's Run does, is canceled when the user cancels the root activity, and its errors are classified for Francis retries.
func (*Engine) Ready ¶
func (e *Engine) Ready()
Ready lets standalone tasks run once startup recovery has protected the work Standalone reported.
func (*Engine) Resume ¶
func (e *Engine) Resume(ctx context.Context, wf *Workflow, run scheduler.Run) (scheduler.Outcome, error)
Resume attaches to the run's active instance, or reads the result of one that finished before the run saved it. When the instance is gone or belongs to a version this host no longer serves, a recorded non-failed result is returned; otherwise it returns ErrNotResumable so the job's fallback can run.
func (*Engine) Retire ¶
func (e *Engine) Retire(ctx context.Context, wf *Workflow, run scheduler.Run, reason string) (outcome scheduler.Outcome, finished bool, err error)
Retire cancels the run's unfinished instance without resuming it, such as for a job that was disabled. An instance that finished before the run saved its result reports that result instead, with finished set.
func (*Engine) Run ¶
func (e *Engine) Run(ctx context.Context, wf *Workflow, payload any, activity activitylib.StartRequest, output any) (scheduler.Outcome, error)
Run starts the workflow, or attaches to the run's active instance, and waits for its outcome. A run in ctx (jobcontext.Run) binds the instance to that run; set fields of activity override the definition's activity template; a non-nil output receives the last step's data alongside its scheduler.Outcome fields.
func (*Engine) Standalone ¶
Standalone lists unfinished instances started by Submit or an unbound Run as runs of the workflow's name, carrying the targets their tasks recorded, so startup recovery can protect their work.
func (*Engine) Start ¶
Start monitors every unfinished root instance so activities complete without a caller.
func (*Engine) Submit ¶
func (e *Engine) Submit(ctx context.Context, wf *Workflow, payload any, activity activitylib.StartRequest, evidence ...scheduler.TargetOutcome) (string, error)
Submit starts a standalone instance without waiting for it and returns its ID, which is also its activity's ID. Its tasks record target progress like a run's; evidence is recorded before the instance starts, such as the record it owns.
type Job ¶
type Job struct {
Engine *Engine
Workflow *Workflow
JobName string
// Payload is every instance's input, such as the entity a per-entity job runs for.
Payload any
// Activity overrides the definition's activity template, such as with the entity's name.
Activity activitylib.StartRequest
ScheduleFn func(ctx context.Context) string
ShouldRunFn func(ctx context.Context) bool
// FallbackFn recovers a run whose instance cannot resume; nil fails the run so
// a retry starts a fresh instance under a new attempt.
FallbackFn func(ctx context.Context, previous scheduler.Run) (scheduler.Outcome, error)
ValidateRetryFn func(ctx context.Context, run scheduler.Run) error
}
Job runs a workflow as a scheduler job. The coordinator's single flight per job and environment already prevents overlapping runs.
func (*Job) Reconcile ¶
Reconcile resumes an interrupted run's instance, falling back to FallbackFn when it cannot be resumed. A job disabled since the run started makes no further changes.
func (*Job) ShouldSchedule ¶
ShouldSchedule reports whether the job runs; a nil ShouldRunFn always does.
type Task ¶
Task is what an engine handler receives: the Francis task plus its binding.
func (Task) ActivityID ¶
ActivityID returns the activity owned by the task's root instance.
func (Task) ChildInput ¶
ChildInput returns the output for a step that precedes a Child step, so the child inherits this instance's run binding.
type Workflow ¶
type Workflow struct {
// contains filtered or unexported fields
}
Workflow is a defined workflow registered on the engine's host.
func (*Workflow) Fingerprint ¶
Fingerprint is the graph hash the definition declares for its version.