70 lines
2.6 KiB
Go
70 lines
2.6 KiB
Go
// Package flow is a generic, JSON-configurable orchestration engine. A flow is a
|
|
// sequence of named steps; each step runs a registered action, may be gated by a
|
|
// registered predicate, can fire registered hooks (before/after/on-error), and
|
|
// may declare a compensating action used to roll back on failure (the saga
|
|
// pattern). Actions, predicates and hooks are registered by name — the same
|
|
// "interface + interchangeable impls, wired in one place" seam the CMS uses for
|
|
// its event listeners. The flow definition itself is plain JSON, so flows live
|
|
// alongside the app's other JSON config (schemas, blueprints) and can be edited
|
|
// without code changes.
|
|
package flow
|
|
|
|
import "encoding/json"
|
|
|
|
// Definition is a whole flow, loadable from JSON.
|
|
type Definition struct {
|
|
Name string `json:"name"`
|
|
Description string `json:"description,omitempty"`
|
|
Steps []Step `json:"steps"`
|
|
}
|
|
|
|
// Step is one unit of work in a flow.
|
|
type Step struct {
|
|
// Name identifies the step in logs, hooks and results.
|
|
Name string `json:"name"`
|
|
// Action is the registered action to run.
|
|
Action string `json:"action"`
|
|
// Params is opaque JSON passed to the action.
|
|
Params json.RawMessage `json:"params,omitempty"`
|
|
// When, if set, names a registered predicate; the step is skipped when it
|
|
// returns false.
|
|
When string `json:"when,omitempty"`
|
|
// Hooks fire around the action.
|
|
Hooks Hooks `json:"hooks,omitempty"`
|
|
// Compensate, if set, is the action used to undo this step when a later step
|
|
// fails (executed in reverse order during rollback).
|
|
Compensate *ActionRef `json:"compensate,omitempty"`
|
|
// ContinueOnError records the error and proceeds instead of rolling back.
|
|
ContinueOnError bool `json:"continueOnError,omitempty"`
|
|
}
|
|
|
|
// ActionRef names an action and its params (used for compensation).
|
|
type ActionRef struct {
|
|
Action string `json:"action"`
|
|
Params json.RawMessage `json:"params,omitempty"`
|
|
}
|
|
|
|
// Hooks groups the hook references that fire at each phase of a step.
|
|
type Hooks struct {
|
|
Before []HookRef `json:"before,omitempty"`
|
|
After []HookRef `json:"after,omitempty"`
|
|
OnError []HookRef `json:"onError,omitempty"`
|
|
}
|
|
|
|
// HookRef names a registered hook and its params. When, if set, names a
|
|
// registered predicate; the hook is skipped when it returns false.
|
|
type HookRef struct {
|
|
Type string `json:"type"`
|
|
When string `json:"when,omitempty"`
|
|
Params json.RawMessage `json:"params,omitempty"`
|
|
}
|
|
|
|
// Parse loads a flow definition from JSON bytes.
|
|
func Parse(data []byte) (*Definition, error) {
|
|
var d Definition
|
|
if err := json.Unmarshal(data, &d); err != nil {
|
|
return nil, err
|
|
}
|
|
return &d, nil
|
|
}
|