You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
obsidian-pipeline/fsm/fsm.go

72 lines
1.2 KiB
Go

package fsm
import (
"context"
"fmt"
)
type State string
type Event string
type Action func(ctx context.Context) error
type Node struct {
State
Transitions map[Event]*Transition
}
type Transition struct {
*Node
Action
}
type StateMachine struct {
initialNode *Node
CurrentNode *Node
}
func (m *StateMachine) getCurrentNode() *Node {
return m.CurrentNode
}
func (m *StateMachine) getNextNode(event Event) (*Node, error) {
if m.CurrentNode == nil {
return nil, fmt.Errorf("nowhere to go anymore!\n")
}
transition, ok := m.CurrentNode.Transitions[event]
if !ok {
return nil, fmt.Errorf("invalid event: %v", event)
}
return transition.Node, nil
}
func (m *StateMachine) Transition(ctx context.Context, event Event) (*Node, error) {
node, err := m.getNextNode(event) // gets current node
if err != nil {
return nil, fmt.Errorf(err.Error())
}
err = m.CurrentNode.Transitions[event].Action(ctx)
if err != nil {
return nil, fmt.Errorf(err.Error())
}
m.CurrentNode = node
return m.CurrentNode, nil
}
func NewStateMachine(initialNode *Node) *StateMachine {
if initialNode == nil {
return &StateMachine{}
}
return &StateMachine{
initialNode: initialNode,
CurrentNode: initialNode,
}
}