Skip to content

Commit

Permalink
Constrain on Stater type, instead of any, no need for generic on Tran…
Browse files Browse the repository at this point in the history
…sition and Stater
  • Loading branch information
daegalus committed Feb 8, 2023
1 parent 10e6d4a commit 17a11ed
Show file tree
Hide file tree
Showing 3 changed files with 32 additions and 32 deletions.
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
module github.com/daegalus/transition

go 1.19
go 1.20
36 changes: 18 additions & 18 deletions transition.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,36 +5,36 @@ import (
)

// Transition is a struct, embed it in your struct to enable state machine for the struct
type Transition[T any] struct {
type Transition struct {
State string
}

// SetState set state to Stater, just set, won't save it into database
func (transition *Transition[T]) SetState(name string) {
func (transition *Transition) SetState(name string) {
transition.State = name
}

// GetState get current state from
func (transition Transition[T]) GetState() string {
func (transition Transition) GetState() string {
return transition.State
}

// Stater is a interface including methods `GetState`, `SetState`
type Stater[T any] interface {
type Stater interface {
SetState(name string)
GetState() string
}

// New initialize a new StateMachine that hold states, events definitions
func New[T any](_ T) *StateMachine[T] {
func New[T Stater](_ T) *StateMachine[T] {
return &StateMachine[T]{
states: map[string]*State[T]{},
events: map[string]*Event[T]{},
}
}

// StateMachine a struct that hold states, events definitions
type StateMachine[T any] struct {
type StateMachine[T Stater] struct {
initialState string
states map[string]*State[T]
events map[string]*Event[T]
Expand Down Expand Up @@ -67,7 +67,7 @@ func (sm *StateMachine[T]) Event(name string) *Event[T] {
}

// Trigger trigger an event
func (sm *StateMachine[T]) Trigger(name string, value Stater[T]) error {
func (sm *StateMachine[T]) Trigger(name string, value T) error {
stateWas := value.GetState()

if stateWas == "" {
Expand Down Expand Up @@ -138,26 +138,26 @@ func (sm *StateMachine[T]) Trigger(name string, value Stater[T]) error {
}

// State contains State information, including enter, exit hooks
type State[T any] struct {
type State[T Stater] struct {
Name string
enters []func(value Stater[T]) error
exits []func(value Stater[T]) error
enters []func(value T) error
exits []func(value T) error
}

// Enter register an enter hook for State
func (state *State[T]) Enter(fc func(value Stater[T]) error) *State[T] {
func (state *State[T]) Enter(fc func(value T) error) *State[T] {
state.enters = append(state.enters, fc)
return state
}

// Exit register an exit hook for State
func (state *State[T]) Exit(fc func(value Stater[T]) error) *State[T] {
func (state *State[T]) Exit(fc func(value T) error) *State[T] {
state.exits = append(state.exits, fc)
return state
}

// Event contains Event information, including transition hooks
type Event[T any] struct {
type Event[T Stater] struct {
Name string
transitions map[string]*EventTransition[T]
}
Expand All @@ -177,11 +177,11 @@ func (event *Event[T]) To(name string) *EventTransition[T] {
}

// EventTransition hold event's to/froms states, also including befores, afters hooks
type EventTransition[T any] struct {
type EventTransition[T Stater] struct {
to string
froms []string
befores []func(value Stater[T]) error
afters []func(value Stater[T]) error
befores []func(value T) error
afters []func(value T) error
}

// From used to define from states
Expand All @@ -192,13 +192,13 @@ func (transition *EventTransition[T]) From(states ...string) *EventTransition[T]
}

// Before register before hooks
func (transition *EventTransition[T]) Before(fc func(value Stater[T]) error) *EventTransition[T] {
func (transition *EventTransition[T]) Before(fc func(value T) error) *EventTransition[T] {
transition.befores = append(transition.befores, fc)
return transition
}

// After register after hooks
func (transition *EventTransition[T]) After(fc func(value Stater[T]) error) *EventTransition[T] {
func (transition *EventTransition[T]) After(fc func(value T) error) *EventTransition[T] {
transition.afters = append(transition.afters, fc)
return transition
}
Expand Down
26 changes: 13 additions & 13 deletions transition_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ type Order struct {
Id int
Address string

Transition[Order]
Transition
}

func getStateMachine() *StateMachine[*Order] {
Expand Down Expand Up @@ -90,11 +90,11 @@ func TestStateCallbacks(t *testing.T) {

address1 := "I'm an address should be set when enter checkout"
address2 := "I'm an address should be set when exit checkout"
orderStateMachine.State("checkout").Enter(func(order Stater[*Order]) error {
order.(*Order).Address = address1
orderStateMachine.State("checkout").Enter(func(order *Order) error {
order.Address = address1
return nil
}).Exit(func(order Stater[*Order]) error {
order.(*Order).Address = address2
}).Exit(func(order *Order) error {
order.Address = address2
return nil
})

Expand Down Expand Up @@ -122,11 +122,11 @@ func TestEventCallbacks(t *testing.T) {
prevState, afterState string
)

orderStateMachine.Event("checkout").To("checkout").From("draft").Before(func(order Stater[*Order]) error {
prevState = order.(*Order).State
orderStateMachine.Event("checkout").To("checkout").From("draft").Before(func(order *Order) error {
prevState = order.State
return nil
}).After(func(order Stater[*Order]) error {
afterState = order.(*Order).State
}).After(func(order *Order) error {
afterState = order.State
return nil
})

Expand All @@ -150,7 +150,7 @@ func TestTransitionOnEnterCallbackError(t *testing.T) {
orderStateMachine = getStateMachine()
)

orderStateMachine.State("checkout").Enter(func(order Stater[*Order]) (err error) {
orderStateMachine.State("checkout").Enter(func(order *Order) (err error) {
return errors.New("intentional error")
})

Expand All @@ -169,7 +169,7 @@ func TestTransitionOnExitCallbackError(t *testing.T) {
orderStateMachine = getStateMachine()
)

orderStateMachine.State("checkout").Exit(func(order Stater[*Order]) (err error) {
orderStateMachine.State("checkout").Exit(func(order *Order) (err error) {
return errors.New("intentional error")
})

Expand All @@ -192,7 +192,7 @@ func TestEventOnBeforeCallbackError(t *testing.T) {
orderStateMachine = getStateMachine()
)

orderStateMachine.Event("checkout").To("checkout").From("draft").Before(func(order Stater[*Order]) error {
orderStateMachine.Event("checkout").To("checkout").From("draft").Before(func(order *Order) error {
return errors.New("intentional error")
})

Expand All @@ -211,7 +211,7 @@ func TestEventOnAfterCallbackError(t *testing.T) {
orderStateMachine = getStateMachine()
)

orderStateMachine.Event("checkout").To("checkout").From("draft").After(func(order Stater[*Order]) error {
orderStateMachine.Event("checkout").To("checkout").From("draft").After(func(order *Order) error {
return errors.New("intentional error")
})

Expand Down

0 comments on commit 17a11ed

Please sign in to comment.