mirror of
https://github.com/hasura/graphql-engine.git
synced 2024-12-15 17:31:56 +03:00
20f7c85382
GITHUB_PR_NUMBER: 7426 GITHUB_PR_URL: https://github.com/hasura/graphql-engine/pull/7426 PR-URL: https://github.com/hasura/graphql-engine-mono/pull/2173 Co-authored-by: Ajay Tripathi <24985760+atb00ker@users.noreply.github.com> Co-authored-by: Kali Vara Purushotham Santhati <72007599+purush7@users.noreply.github.com> Co-authored-by: Aravind K P <8335904+scriptonist@users.noreply.github.com> GitOrigin-RevId: 1030d24c9e6c7d0c7062b6f0e98f8464950529d3
75 lines
1.3 KiB
Go
75 lines
1.3 KiB
Go
package fsm
|
|
|
|
import (
|
|
"fmt"
|
|
"sync"
|
|
|
|
"github.com/pkg/errors"
|
|
)
|
|
|
|
var ErrEventRejected = errors.New("event rejected")
|
|
|
|
const (
|
|
Default StateType = ""
|
|
NoOp EventType = "NoOp"
|
|
)
|
|
|
|
type StateType string
|
|
type EventType string
|
|
type EventContext interface{}
|
|
|
|
type Action interface {
|
|
Execute(eventCtx EventContext) EventType
|
|
}
|
|
|
|
type Events map[EventType]StateType
|
|
|
|
type State struct {
|
|
Action Action
|
|
Events Events
|
|
}
|
|
|
|
type States map[StateType]State
|
|
|
|
type StateMachine struct {
|
|
Previous StateType
|
|
Current StateType
|
|
States States
|
|
mutex sync.Mutex
|
|
}
|
|
|
|
func (s *StateMachine) getNextState(event EventType) (StateType, error) {
|
|
if state, ok := s.States[s.Current]; ok {
|
|
if state.Events != nil {
|
|
if next, ok := state.Events[event]; ok {
|
|
return next, nil
|
|
}
|
|
}
|
|
}
|
|
|
|
return Default, fmt.Errorf("next state: %w: %s", ErrEventRejected, event)
|
|
}
|
|
|
|
func (s *StateMachine) SendEvent(event EventType, eventCtx EventContext) error {
|
|
s.mutex.Lock()
|
|
defer s.mutex.Unlock()
|
|
for {
|
|
nextState, err := s.getNextState(event)
|
|
if err != nil {
|
|
return fmt.Errorf("%w: %s", err, event)
|
|
}
|
|
state, ok := s.States[nextState]
|
|
if !ok || state.Action == nil {
|
|
return fmt.Errorf("config error")
|
|
}
|
|
s.Previous = s.Current
|
|
s.Current = nextState
|
|
|
|
nextEvent := state.Action.Execute(eventCtx)
|
|
if nextEvent == NoOp {
|
|
return nil
|
|
}
|
|
event = nextEvent
|
|
}
|
|
}
|