all repos — erl @ c8ab7c849959313a035bf9e448d110e794190a4f

Execute Reload Loop

initial commit

Alan Pearce
commit

c8ab7c849959313a035bf9e448d110e794190a4f

1 file changed, 133 insertions(+), 0 deletions(-)

changed files
A state/state.go
@@ -0,0 +1,133 @@
+package state + +import ( + "log" + + "alin.ovh/erl/command" +) + +type State int + +const ( + NotStarted State = iota + Running + Exited +) + +func (s State) String() string { + switch s { + case NotStarted: + return "NotStarted" + case Running: + return "Running" + case Exited: + return "Exited" + default: + return "Unknown" + } +} + +type Event int + +const ( + Start Event = iota + Signal + Exit + Restart +) + +func (e Event) String() string { + switch e { + case Start: + return "Start" + case Signal: + return "Shutdown" + case Exit: + return "Stopped" + case Restart: + return "Restart" + default: + return "Unknown" + } +} + +type Action func() + +type StateMachine struct { + log *log.Logger + currentState State + transitions map[State]map[Event]State + actions map[State]map[Event]Action +} + +func New(cmd command.Command, log *log.Logger) *StateMachine { + sm := &StateMachine{ + log: log, + currentState: NotStarted, + transitions: make(map[State]map[Event]State), + actions: make(map[State]map[Event]Action), + } + + sm.transitions[NotStarted] = map[Event]State{ + Start: Running, + } + sm.transitions[Running] = map[Event]State{ + Signal: Exited, + Exit: Exited, + Restart: Running, + } + sm.transitions[Exited] = map[Event]State{ + Start: Running, + Restart: Running, + } + + wait := func(cmd command.Command) { + err := cmd.Wait() + if err != nil { + log.Printf("Error waiting for command: %v\n", err) + } + sm.SendEvent(Exit) + } + start := func() { + err := cmd.Start() + if err != nil { + log.Printf("Failed to start command: %v", err) + } + + go wait(cmd) + } + stop := func() { + err := cmd.Stop() + if err != nil { + log.Printf("Error stopping command: %v\n", err) + } + } + restart := func() { + stop() + start() + } + + sm.actions[NotStarted] = map[Event]Action{ + Start: start, + } + sm.actions[Running] = map[Event]Action{ + Signal: stop, + Restart: restart, + } + sm.actions[Exited] = map[Event]Action{ + Start: start, + Restart: start, + } + + return sm +} + +func (sm *StateMachine) SendEvent(ev Event) { + currentState := sm.currentState + if nextState, ok := sm.transitions[currentState][ev]; ok { + sm.currentState = nextState + if action, ok := sm.actions[currentState][ev]; ok { + action() + } + } +}