Documentation
¶
Index ¶
- Variables
- func NormalizePassRatio(ratio float64) float64
- func ResolveCCUserIDs(cfg approval.FlowNodeCC, formData approval.FormData) ([]string, error)
- type ApprovalProcessor
- type CCProcessor
- type ConditionProcessor
- type EndProcessor
- type FlowEngine
- func (e *FlowEngine) AdvanceToNextNode(ctx context.Context, db orm.DB, instance *approval.Instance, ...) error
- func (e *FlowEngine) EvaluateNodeCompletion(ctx context.Context, db orm.DB, instance *approval.Instance, ...) (approval.PassRuleResult, error)
- func (e *FlowEngine) EvaluatePassRuleWithTasks(node *approval.FlowNode, tasks []approval.Task) (approval.PassRuleResult, error)
- func (e *FlowEngine) ProcessNode(ctx context.Context, db orm.DB, instance *approval.Instance, ...) error
- func (e *FlowEngine) StartProcess(ctx context.Context, db orm.DB, instance *approval.Instance) error
- type HandleProcessor
- type NodeAction
- type NodeProcessor
- type ProcessContext
- type ProcessResult
- type StartProcessor
- type State
- type StateMachine
- type Transition
Constants ¶
This section is empty.
Variables ¶
var ( // Engine errors. ErrNoMatchingEdge = errors.New("no matching outgoing edge for node") ErrProcessorNotFound = errors.New("node processor not found for node kind") ErrMaxNodeDepth = errors.New("max node processing depth exceeded") // Approval node errors. ErrNoAssignee = errors.New("no assignee resolved for node") ErrAssigneeServiceNotConfigured = errors.New("assignee service is not configured") // Condition node errors. ErrNoBranches = errors.New("condition node has no branches") ErrNoMatchingBranch = errors.New("no matching branch and no default branch") )
var InstanceStateMachine = buildInstanceStateMachine()
InstanceStateMachine defines valid instance state transitions.
var Module = fx.Module( "vef:approval:engine", fx.Provide( fx.Annotate(NewStartProcessor, fx.ResultTags(`group:"vef:approval:node_processors"`)), fx.Annotate(NewEndProcessor, fx.ResultTags(`group:"vef:approval:node_processors"`)), fx.Annotate(NewConditionProcessor, fx.ResultTags(`group:"vef:approval:node_processors"`)), fx.Annotate(NewApprovalProcessor, fx.As(new(NodeProcessor)), fx.ResultTags(`group:"vef:approval:node_processors"`)), fx.Annotate(NewHandleProcessor, fx.As(new(NodeProcessor)), fx.ResultTags(`group:"vef:approval:node_processors"`)), fx.Annotate(NewCCProcessor, fx.As(new(NodeProcessor)), fx.ResultTags(`group:"vef:approval:node_processors"`)), fx.Annotate( NewFlowEngine, fx.ParamTags(``, `group:"vef:approval:node_processors"`, ``, ``), ), ), )
Module provides the flow engine and node processors.
var TaskStateMachine = buildTaskStateMachine()
TaskStateMachine defines valid task state transitions.
Functions ¶
func NormalizePassRatio ¶
NormalizePassRatio normalizes pass ratio to 0-100 scale. Values in (0, 1] range are treated as proportions and converted to percentage. E.g., 0.6 → 60, 1.0 → 100. Values > 1 are kept as-is (already percentage). Negative values are clamped to 0, values above 100 are clamped to 100.
func ResolveCCUserIDs ¶
ResolveCCUserIDs resolves CC recipients from static IDs or form fields.
Types ¶
type ApprovalProcessor ¶
type ApprovalProcessor struct {
// contains filtered or unexported fields
}
ApprovalProcessor handles approval nodes.
func NewApprovalProcessor ¶
func NewApprovalProcessor(assigneeService approval.AssigneeService) *ApprovalProcessor
NewApprovalProcessor creates a new approval processor.
func (*ApprovalProcessor) NodeKind ¶
func (*ApprovalProcessor) NodeKind() approval.NodeKind
func (*ApprovalProcessor) Process ¶
func (p *ApprovalProcessor) Process(ctx context.Context, pc *ProcessContext) (*ProcessResult, error)
type CCProcessor ¶
type CCProcessor struct{}
CCProcessor handles CC (carbon copy) notification nodes.
func (*CCProcessor) NodeKind ¶
func (*CCProcessor) NodeKind() approval.NodeKind
func (*CCProcessor) Process ¶
func (p *CCProcessor) Process(ctx context.Context, pc *ProcessContext) (*ProcessResult, error)
type ConditionProcessor ¶
type ConditionProcessor struct{}
ConditionProcessor evaluates condition branches and selects the matching branch.
func (*ConditionProcessor) NodeKind ¶
func (*ConditionProcessor) NodeKind() approval.NodeKind
func (*ConditionProcessor) Process ¶
func (*ConditionProcessor) Process(ctx context.Context, pc *ProcessContext) (*ProcessResult, error)
type EndProcessor ¶
type EndProcessor struct{}
EndProcessor handles end nodes by completing the flow as approved.
func (*EndProcessor) NodeKind ¶
func (*EndProcessor) NodeKind() approval.NodeKind
func (*EndProcessor) Process ¶
func (*EndProcessor) Process(context.Context, *ProcessContext) (*ProcessResult, error)
type FlowEngine ¶
type FlowEngine struct {
// contains filtered or unexported fields
}
FlowEngine is the core engine for processing approval workflows.
func NewFlowEngine ¶
func NewFlowEngine(registry *strategy.StrategyRegistry, processors []NodeProcessor, pub *dispatcher.EventPublisher, userResolver approval.UserInfoResolver) *FlowEngine
NewFlowEngine creates a new flow engine.
func (*FlowEngine) AdvanceToNextNode ¶
func (e *FlowEngine) AdvanceToNextNode(ctx context.Context, db orm.DB, instance *approval.Instance, fromNode *approval.FlowNode, branchID *string) error
AdvanceToNextNode finds the matching edge from the current node and advances to the next one. BranchID is used by condition nodes to select the edge matching the branch.
func (*FlowEngine) EvaluateNodeCompletion ¶
func (e *FlowEngine) EvaluateNodeCompletion(ctx context.Context, db orm.DB, instance *approval.Instance, node *approval.FlowNode) (approval.PassRuleResult, error)
EvaluateNodeCompletion evaluates whether a node is complete based on its tasks and pass rule.
func (*FlowEngine) EvaluatePassRuleWithTasks ¶
func (e *FlowEngine) EvaluatePassRuleWithTasks(node *approval.FlowNode, tasks []approval.Task) (approval.PassRuleResult, error)
EvaluatePassRuleWithTasks evaluates the pass rule for a node using the provided tasks. This is used for simulation (e.g., checking if removing an assignee would deadlock the node).
func (*FlowEngine) ProcessNode ¶
func (e *FlowEngine) ProcessNode(ctx context.Context, db orm.DB, instance *approval.Instance, node *approval.FlowNode) error
ProcessNode dispatches a node to the appropriate processor.
func (*FlowEngine) StartProcess ¶
func (e *FlowEngine) StartProcess(ctx context.Context, db orm.DB, instance *approval.Instance) error
StartProcess starts a flow process by finding the start node and processing it.
type HandleProcessor ¶
type HandleProcessor struct {
// contains filtered or unexported fields
}
HandleProcessor handles handle nodes (claim mode). Unlike approval nodes, handle nodes create all tasks with sortOrder=0, allowing any candidate to claim and complete the task.
func NewHandleProcessor ¶
func NewHandleProcessor(assigneeService approval.AssigneeService) *HandleProcessor
NewHandleProcessor creates a new handle processor.
func (*HandleProcessor) NodeKind ¶
func (*HandleProcessor) NodeKind() approval.NodeKind
func (*HandleProcessor) Process ¶
func (p *HandleProcessor) Process(ctx context.Context, pc *ProcessContext) (*ProcessResult, error)
type NodeAction ¶
type NodeAction int
NodeAction represents the result action of node processing.
const ( NodeActionWait NodeAction = iota // Wait for user action NodeActionContinue // Auto-advance to next node NodeActionComplete // Flow ends )
type NodeProcessor ¶
type NodeProcessor interface {
// NodeKind returns the node kind this processor handles (approval, handle, cc, condition, etc.).
NodeKind() approval.NodeKind
// Process executes the node logic and returns the action to take (wait, continue, or complete).
Process(ctx context.Context, pc *ProcessContext) (*ProcessResult, error)
}
NodeProcessor processes a specific node kind.
func NewConditionProcessor ¶
func NewConditionProcessor() NodeProcessor
NewConditionProcessor creates a ConditionProcessor.
func NewEndProcessor ¶
func NewEndProcessor() NodeProcessor
NewEndProcessor creates an EndProcessor.
func NewStartProcessor ¶
func NewStartProcessor() NodeProcessor
NewStartProcessor creates a StartProcessor.
type ProcessContext ¶
type ProcessContext struct {
DB orm.DB
Instance *approval.Instance
Node *approval.FlowNode
FormData approval.FormData
ApplicantID string
ApplicantName string
UserResolver approval.UserInfoResolver
Registry *strategy.StrategyRegistry
}
ProcessContext provides context for node processing.
type ProcessResult ¶
type ProcessResult struct {
Action NodeAction
FinalStatus *approval.InstanceStatus // Only set when Action == NodeActionComplete
BranchID *string // Only set when Action == NodeActionContinue (condition node)
Events []approval.DomainEvent // Events to publish after processing
}
ProcessResult contains the outcome of node processing.
type StartProcessor ¶
type StartProcessor struct{}
StartProcessor handles start nodes by auto-advancing to the next node.
func (*StartProcessor) NodeKind ¶
func (*StartProcessor) NodeKind() approval.NodeKind
func (*StartProcessor) Process ¶
func (*StartProcessor) Process(context.Context, *ProcessContext) (*ProcessResult, error)
type State ¶
type State interface {
comparable
// String returns the string representation of this state.
String() string
// IsFinal returns true if this is a terminal state with no further transitions.
IsFinal() bool
}
State represents a state that can be used in a state machine.
type StateMachine ¶
type StateMachine[S State] struct { // contains filtered or unexported fields }
StateMachine manages state transitions.
func NewStateMachine ¶
func NewStateMachine[S State](name string) *StateMachine[S]
NewStateMachine creates a new state machine with the given name.
func (*StateMachine[S]) AddTransition ¶
func (sm *StateMachine[S]) AddTransition(from, to S, event string) *StateMachine[S]
AddTransition registers a valid state transition.
func (*StateMachine[S]) AvailableTransitions ¶
func (sm *StateMachine[S]) AvailableTransitions(from S) []S
AvailableTransitions returns all valid target states from the given state.
func (*StateMachine[S]) CanTransition ¶
func (sm *StateMachine[S]) CanTransition(from, to S) bool
CanTransition checks if a transition from one state to another is valid.
func (*StateMachine[S]) Transition ¶
func (sm *StateMachine[S]) Transition(from, to S) error
Transition performs a state transition, returning an error if invalid.
type Transition ¶
Transition defines a state transition.