mirror of https://github.com/certusone/dc4bc.git
Merge branch 'master' into feat/client-http
# Conflicts: # fsm/cmd/test/test.go # fsm/fsm_pool/fsm_pool.go # fsm/state_machines/provider.go # fsm/state_machines/signature_proposal_fsm/actions.go # fsm/state_machines/signature_proposal_fsm/helpers.go # fsm/types/requests/signature_proposal.go # mocks/clientMocks/state_mock.go # mocks/storageMocks/storage_mock.go
This commit is contained in:
commit
533dc9375c
|
@ -19,33 +19,45 @@ import (
|
|||
|
||||
// Temporary global finish state for deprecating operations
|
||||
const (
|
||||
StateGlobalIdle = "__idle"
|
||||
StateGlobalDone = "__done"
|
||||
StateGlobalIdle = State("__idle")
|
||||
StateGlobalDone = State("__done")
|
||||
)
|
||||
|
||||
// FSMResponse returns result for processing with clientMocks events
|
||||
type FSMResponse struct {
|
||||
type State string
|
||||
|
||||
func (s *State) String() string {
|
||||
return string(*s)
|
||||
}
|
||||
|
||||
type Event string
|
||||
|
||||
func (e *Event) String() string {
|
||||
return string(*e)
|
||||
}
|
||||
|
||||
// Response returns result for processing with clientMocks events
|
||||
type Response struct {
|
||||
// Returns machine execution result state
|
||||
State string
|
||||
State State
|
||||
// Must be cast, according to mapper event_name->response_type
|
||||
Data interface{}
|
||||
}
|
||||
|
||||
type FSM struct {
|
||||
name string
|
||||
initialState string
|
||||
currentState string
|
||||
initialState State
|
||||
currentState State
|
||||
|
||||
// May be mapping must require pair source + event?
|
||||
transitions map[trKey]*trEvent
|
||||
|
||||
callbacks Callbacks
|
||||
|
||||
initialEvent string
|
||||
initialEvent Event
|
||||
|
||||
// Finish states, for switch machine or fin,
|
||||
// These states cannot be linked as SrcState in this machine
|
||||
finStates map[string]bool
|
||||
finStates map[State]bool
|
||||
|
||||
// stateMu guards access to the currentState state.
|
||||
stateMu sync.RWMutex
|
||||
|
@ -55,36 +67,36 @@ type FSM struct {
|
|||
|
||||
// Transition key source + dst
|
||||
type trKey struct {
|
||||
source string
|
||||
event string
|
||||
source State
|
||||
event Event
|
||||
}
|
||||
|
||||
// Transition lightweight event description
|
||||
type trEvent struct {
|
||||
dstState string
|
||||
dstState State
|
||||
isInternal bool
|
||||
}
|
||||
|
||||
type Event struct {
|
||||
Name string
|
||||
type EventDesc struct {
|
||||
Name Event
|
||||
|
||||
SrcState []string
|
||||
SrcState []State
|
||||
|
||||
// Dst state changes after callback
|
||||
DstState string
|
||||
DstState State
|
||||
|
||||
// Internal events, cannot be emitted from external call
|
||||
IsInternal bool
|
||||
}
|
||||
|
||||
type Callback func(event string, args ...interface{}) (interface{}, error)
|
||||
type Callback func(event Event, args ...interface{}) (interface{}, error)
|
||||
|
||||
type Callbacks map[string]Callback
|
||||
type Callbacks map[Event]Callback
|
||||
|
||||
// TODO: Exports
|
||||
func MustNewFSM(machineName, initialState string, events []Event, callbacks map[string]Callback) *FSM {
|
||||
func MustNewFSM(machineName string, initialState State, events []EventDesc, callbacks Callbacks) *FSM {
|
||||
machineName = strings.TrimSpace(machineName)
|
||||
initialState = strings.TrimSpace(initialState)
|
||||
initialState = State(strings.TrimSpace(initialState.String()))
|
||||
|
||||
if machineName == "" {
|
||||
panic("machine name cannot be empty")
|
||||
|
@ -104,20 +116,20 @@ func MustNewFSM(machineName, initialState string, events []Event, callbacks map[
|
|||
currentState: initialState,
|
||||
initialState: initialState,
|
||||
transitions: make(map[trKey]*trEvent),
|
||||
finStates: make(map[string]bool),
|
||||
callbacks: make(map[string]Callback),
|
||||
finStates: make(map[State]bool),
|
||||
callbacks: make(map[Event]Callback),
|
||||
}
|
||||
|
||||
allEvents := make(map[string]bool)
|
||||
allEvents := make(map[Event]bool)
|
||||
|
||||
// Required for find finStates
|
||||
allSources := make(map[string]bool)
|
||||
allStates := make(map[string]bool)
|
||||
allSources := make(map[State]bool)
|
||||
allStates := make(map[State]bool)
|
||||
|
||||
// Validate events
|
||||
for _, event := range events {
|
||||
event.Name = strings.TrimSpace(event.Name)
|
||||
event.DstState = strings.TrimSpace(event.DstState)
|
||||
event.Name = Event(strings.TrimSpace(event.Name.String()))
|
||||
event.DstState = State(strings.TrimSpace(event.DstState.String()))
|
||||
|
||||
if event.Name == "" {
|
||||
panic("cannot init empty event")
|
||||
|
@ -137,7 +149,7 @@ func MustNewFSM(machineName, initialState string, events []Event, callbacks map[
|
|||
trimmedSourcesCounter := 0
|
||||
|
||||
for _, sourceState := range event.SrcState {
|
||||
sourceState := strings.TrimSpace(sourceState)
|
||||
sourceState := State(strings.TrimSpace(sourceState.String()))
|
||||
|
||||
if sourceState == "" {
|
||||
continue
|
||||
|
@ -209,7 +221,7 @@ func MustNewFSM(machineName, initialState string, events []Event, callbacks map[
|
|||
return f
|
||||
}
|
||||
|
||||
func (f *FSM) Do(event string, args ...interface{}) (resp *FSMResponse, err error) {
|
||||
func (f *FSM) Do(event Event, args ...interface{}) (resp *Response, err error) {
|
||||
f.eventMu.Lock()
|
||||
defer f.eventMu.Unlock()
|
||||
|
||||
|
@ -221,7 +233,7 @@ func (f *FSM) Do(event string, args ...interface{}) (resp *FSMResponse, err erro
|
|||
return nil, errors.New("event is internal")
|
||||
}
|
||||
|
||||
resp = &FSMResponse{
|
||||
resp = &Response{
|
||||
State: f.State(),
|
||||
}
|
||||
|
||||
|
@ -238,7 +250,7 @@ func (f *FSM) Do(event string, args ...interface{}) (resp *FSMResponse, err erro
|
|||
}
|
||||
|
||||
// State returns the currentState state of the FSM.
|
||||
func (f *FSM) State() string {
|
||||
func (f *FSM) State() State {
|
||||
f.stateMu.RLock()
|
||||
defer f.stateMu.RUnlock()
|
||||
return f.currentState
|
||||
|
@ -246,7 +258,7 @@ func (f *FSM) State() string {
|
|||
|
||||
// setState allows the user to move to the given state from currentState state.
|
||||
// The call does not trigger any callbacks, if defined.
|
||||
func (f *FSM) setState(event string) error {
|
||||
func (f *FSM) setState(event Event) error {
|
||||
f.stateMu.Lock()
|
||||
defer f.stateMu.Unlock()
|
||||
|
||||
|
@ -264,12 +276,12 @@ func (f *FSM) Name() string {
|
|||
return f.name
|
||||
}
|
||||
|
||||
func (f *FSM) InitialState() string {
|
||||
func (f *FSM) InitialState() State {
|
||||
return f.initialState
|
||||
}
|
||||
|
||||
// Check entry event for available emitting as global entry event
|
||||
func (f *FSM) GlobalInitialEvent() (event string) {
|
||||
func (f *FSM) GlobalInitialEvent() (event Event) {
|
||||
if initialEvent, exists := f.transitions[trKey{StateGlobalIdle, f.initialEvent}]; exists {
|
||||
if !initialEvent.isInternal {
|
||||
event = f.initialEvent
|
||||
|
@ -278,7 +290,7 @@ func (f *FSM) GlobalInitialEvent() (event string) {
|
|||
return
|
||||
}
|
||||
|
||||
func (f *FSM) EntryEvent() (event string) {
|
||||
func (f *FSM) EntryEvent() (event Event) {
|
||||
if entryEvent, exists := f.transitions[trKey{f.initialState, f.initialEvent}]; exists {
|
||||
if !entryEvent.isInternal {
|
||||
event = f.initialEvent
|
||||
|
@ -287,8 +299,8 @@ func (f *FSM) EntryEvent() (event string) {
|
|||
return
|
||||
}
|
||||
|
||||
func (f *FSM) EventsList() (events []string) {
|
||||
var eventsMap = map[string]bool{}
|
||||
func (f *FSM) EventsList() (events []Event) {
|
||||
var eventsMap = map[Event]bool{}
|
||||
if len(f.transitions) > 0 {
|
||||
for trKey, trEvent := range f.transitions {
|
||||
if !trEvent.isInternal {
|
||||
|
@ -310,8 +322,8 @@ func (f *FSM) EventsList() (events []string) {
|
|||
return
|
||||
}
|
||||
|
||||
func (f *FSM) StatesSourcesList() (states []string) {
|
||||
var allStates = map[string]bool{}
|
||||
func (f *FSM) StatesSourcesList() (states []State) {
|
||||
var allStates = map[State]bool{}
|
||||
if len(f.transitions) > 0 {
|
||||
for trKey, _ := range f.transitions {
|
||||
allStates[trKey.source] = true
|
||||
|
@ -327,7 +339,7 @@ func (f *FSM) StatesSourcesList() (states []string) {
|
|||
return
|
||||
}
|
||||
|
||||
func (f *FSM) IsFinState(state string) bool {
|
||||
func (f *FSM) IsFinState(state State) bool {
|
||||
_, exists := f.finStates[state]
|
||||
return exists
|
||||
}
|
||||
|
|
|
@ -1,77 +1,66 @@
|
|||
package fsm
|
||||
|
||||
type testMachineFSM struct {
|
||||
*FSM
|
||||
}
|
||||
|
||||
const (
|
||||
FSM1Name = "fsm1"
|
||||
// Init process from global idle state
|
||||
FSM1StateInit = StateGlobalIdle
|
||||
// Set up data
|
||||
FSM1StateStage1 = "state_fsm1_stage1"
|
||||
FSM1StateStage1 = State("state_fsm1_stage1")
|
||||
// Process data
|
||||
FSM1StateStage2 = "state_fsm1_stage2"
|
||||
FSM1StateStage2 = State("state_fsm1_stage2")
|
||||
// Cancelled with internal event
|
||||
FSM1StateCanceledByInternal = "state_fsm1_canceled1"
|
||||
FSM1StateCanceledByInternal = State("state_fsm1_canceled")
|
||||
// Cancelled with external event
|
||||
FSM1StateCanceled2 = "state_fsm1_canceled2"
|
||||
FSM1StateCanceled2 = State("state_fsm1_canceled2")
|
||||
// Out endpoint to switch
|
||||
FSM1StateOutToFSM2 = "state_fsm1_out_to_fsm2"
|
||||
FSM1StateOutToFSM3 = "state_fsm1_out_to_fsm3"
|
||||
FSM1StateOutToFSM2 = State("state_fsm1_out_to_fsm2")
|
||||
FSM1StateOutToFSM3 = State("state_fsm1_out_to_fsm3")
|
||||
|
||||
// Events
|
||||
EventFSM1Init = "event_fsm1_init"
|
||||
EventFSM1Cancel = "event_fsm1_cancel"
|
||||
EventFSM1Process = "event_fsm1_process"
|
||||
EventFSM1Init = Event("event_fsm1_init")
|
||||
EventFSM1Cancel = Event("event_fsm1_cancel")
|
||||
EventFSM1Process = Event("event_fsm1_process")
|
||||
|
||||
// Internal events
|
||||
EventFSM1Internal = "event_internal_fsm1"
|
||||
EventFSM1CancelByInternal = "event_internal_fsm1_cancel"
|
||||
EventFSM1InternalOut2 = "event_internal_fsm1_out"
|
||||
EventFSM1Internal = Event("event_internal_fsm1")
|
||||
EventFSM1CancelByInternal = Event("event_internal_fsm1_cancel")
|
||||
EventFSM1InternalOut2 = Event("event_internal_fsm1_out")
|
||||
)
|
||||
|
||||
var (
|
||||
testingEvents = []Event{
|
||||
testing1Events = []EventDesc{
|
||||
// Init
|
||||
{Name: EventFSM1Init, SrcState: []string{FSM1StateInit}, DstState: FSM1StateStage1},
|
||||
{Name: EventFSM1Internal, SrcState: []string{FSM1StateStage1}, DstState: FSM1StateStage2, IsInternal: true},
|
||||
{Name: EventFSM1Init, SrcState: []State{FSM2StateInit}, DstState: FSM1StateStage1},
|
||||
{Name: EventFSM1Internal, SrcState: []State{FSM1StateStage1}, DstState: FSM1StateStage2, IsInternal: true},
|
||||
|
||||
// Cancellation events
|
||||
{Name: EventFSM1CancelByInternal, SrcState: []string{FSM1StateStage2}, DstState: FSM1StateCanceledByInternal, IsInternal: true},
|
||||
{Name: EventFSM1Cancel, SrcState: []string{FSM1StateStage2}, DstState: FSM1StateCanceled2},
|
||||
{Name: EventFSM1CancelByInternal, SrcState: []State{FSM1StateStage2}, DstState: FSM1StateCanceledByInternal, IsInternal: true},
|
||||
{Name: EventFSM1Cancel, SrcState: []State{FSM1StateStage2}, DstState: FSM1StateCanceled2},
|
||||
|
||||
// Out
|
||||
{Name: EventFSM1Process, SrcState: []string{FSM1StateStage2}, DstState: FSM1StateOutToFSM2},
|
||||
{Name: EventFSM1InternalOut2, SrcState: []string{FSM1StateStage2}, DstState: FSM1StateOutToFSM3, IsInternal: true},
|
||||
{Name: EventFSM1Process, SrcState: []State{FSM1StateStage2}, DstState: FSM1StateOutToFSM2},
|
||||
{Name: EventFSM1InternalOut2, SrcState: []State{FSM1StateStage2}, DstState: FSM1StateOutToFSM3, IsInternal: true},
|
||||
}
|
||||
|
||||
testingCallbacks = Callbacks{
|
||||
testing1Callbacks = Callbacks{
|
||||
EventFSM1Init: actionSetUpData,
|
||||
EventFSM1InternalOut2: actionEmitOut2,
|
||||
EventFSM1Process: actionProcessData,
|
||||
}
|
||||
)
|
||||
|
||||
type testMachineFSM struct {
|
||||
*FSM
|
||||
}
|
||||
|
||||
/*func new() fsm_pool.IStateMachine {
|
||||
machine := &testMachineFSM{}
|
||||
machine.FSM = MustNewFSM(
|
||||
FSM1Name,
|
||||
FSM1StateInit,
|
||||
testingEvents,
|
||||
testingCallbacks,
|
||||
)
|
||||
return machine
|
||||
}*/
|
||||
|
||||
func actionSetUpData(event string, args ...interface{}) (response interface{}, err error) {
|
||||
func actionSetUpData(event Event, args ...interface{}) (response interface{}, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func actionProcessData(event string, args ...interface{}) (response interface{}, err error) {
|
||||
func actionProcessData(event Event, args ...interface{}) (response interface{}, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func actionEmitOut2(event string, args ...interface{}) (response interface{}, err error) {
|
||||
func actionEmitOut2(event Event, args ...interface{}) (response interface{}, err error) {
|
||||
return
|
||||
}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package fsm
|
||||
|
||||
import (
|
||||
"log"
|
||||
"testing"
|
||||
)
|
||||
|
||||
|
@ -11,8 +10,8 @@ func init() {
|
|||
testingFSM = MustNewFSM(
|
||||
FSM1Name,
|
||||
FSM1StateInit,
|
||||
testingEvents,
|
||||
testingCallbacks,
|
||||
testing1Events,
|
||||
testing1Callbacks,
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -29,12 +28,38 @@ func compareRecoverStr(t *testing.T, r interface{}, assertion string) {
|
|||
}
|
||||
}
|
||||
|
||||
func compareArrays(src, dst []string) bool {
|
||||
func compareStatesArr(src, dst []State) bool {
|
||||
if len(src) != len(dst) {
|
||||
return false
|
||||
}
|
||||
// create a map of string -> int
|
||||
diff := make(map[string]int, len(src))
|
||||
diff := make(map[State]int, len(src))
|
||||
for _, _x := range src {
|
||||
// 0 value for int is 0, so just increment a counter for the string
|
||||
diff[_x]++
|
||||
}
|
||||
for _, _y := range dst {
|
||||
// If the string _y is not in diff bail out early
|
||||
if _, ok := diff[_y]; !ok {
|
||||
return false
|
||||
}
|
||||
diff[_y] -= 1
|
||||
if diff[_y] == 0 {
|
||||
delete(diff, _y)
|
||||
}
|
||||
}
|
||||
if len(diff) == 0 {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func compareEventsArr(src, dst []Event) bool {
|
||||
if len(src) != len(dst) {
|
||||
return false
|
||||
}
|
||||
// create a map of string -> int
|
||||
diff := make(map[Event]int, len(src))
|
||||
for _, _x := range src {
|
||||
// 0 value for int is 0, so just increment a counter for the string
|
||||
diff[_x]++
|
||||
|
@ -62,7 +87,7 @@ func TestMustNewFSM_Empty_Name_Panic(t *testing.T) {
|
|||
testingFSM = MustNewFSM(
|
||||
"",
|
||||
"init_state",
|
||||
[]Event{},
|
||||
[]EventDesc{},
|
||||
nil,
|
||||
)
|
||||
|
||||
|
@ -77,7 +102,7 @@ func TestMustNewFSM_Empty_Initial_State_Panic(t *testing.T) {
|
|||
testingFSM = MustNewFSM(
|
||||
"fsm",
|
||||
"",
|
||||
[]Event{},
|
||||
[]EventDesc{},
|
||||
nil,
|
||||
)
|
||||
|
||||
|
@ -92,7 +117,7 @@ func TestMustNewFSM_Empty_Events_Panic(t *testing.T) {
|
|||
testingFSM = MustNewFSM(
|
||||
"fsm",
|
||||
"init_state",
|
||||
[]Event{},
|
||||
[]EventDesc{},
|
||||
nil,
|
||||
)
|
||||
|
||||
|
@ -107,8 +132,8 @@ func TestMustNewFSM_Event_Empty_Name_Panic(t *testing.T) {
|
|||
testingFSM = MustNewFSM(
|
||||
"fsm",
|
||||
"init_state",
|
||||
[]Event{
|
||||
{Name: "", SrcState: []string{"init_state"}, DstState: StateGlobalDone},
|
||||
[]EventDesc{
|
||||
{Name: "", SrcState: []State{"init_state"}, DstState: StateGlobalDone},
|
||||
},
|
||||
nil,
|
||||
)
|
||||
|
@ -124,8 +149,8 @@ func TestMustNewFSM_Event_Empty_Source_Panic(t *testing.T) {
|
|||
testingFSM = MustNewFSM(
|
||||
"fsm",
|
||||
"init_state",
|
||||
[]Event{
|
||||
{Name: "event", SrcState: []string{}, DstState: StateGlobalDone},
|
||||
[]EventDesc{
|
||||
{Name: "event", SrcState: []State{}, DstState: StateGlobalDone},
|
||||
},
|
||||
nil,
|
||||
)
|
||||
|
@ -141,8 +166,8 @@ func TestMustNewFSM_States_Min_Panic(t *testing.T) {
|
|||
testingFSM = MustNewFSM(
|
||||
"fsm",
|
||||
"init_state",
|
||||
[]Event{
|
||||
{Name: "event", SrcState: []string{"init_state"}, DstState: StateGlobalDone},
|
||||
[]EventDesc{
|
||||
{Name: "event", SrcState: []State{"init_state"}, DstState: StateGlobalDone},
|
||||
},
|
||||
nil,
|
||||
)
|
||||
|
@ -158,9 +183,9 @@ func TestMustNewFSM_State_Entry_Conflict_Panic(t *testing.T) {
|
|||
testingFSM = MustNewFSM(
|
||||
"fsm",
|
||||
"init_state",
|
||||
[]Event{
|
||||
{Name: "event1", SrcState: []string{"init_state"}, DstState: "state"},
|
||||
{Name: "event2", SrcState: []string{"init_state"}, DstState: "state"},
|
||||
[]EventDesc{
|
||||
{Name: "event1", SrcState: []State{"init_state"}, DstState: "state"},
|
||||
{Name: "event2", SrcState: []State{"init_state"}, DstState: "state"},
|
||||
},
|
||||
nil,
|
||||
)
|
||||
|
@ -176,9 +201,9 @@ func TestMustNewFSM_State_Final_Not_Found_Panic(t *testing.T) {
|
|||
testingFSM = MustNewFSM(
|
||||
"fsm",
|
||||
"init_state",
|
||||
[]Event{
|
||||
{Name: "event1", SrcState: []string{"init_state"}, DstState: "state2"},
|
||||
{Name: "event2", SrcState: []string{"state2"}, DstState: "init_state"},
|
||||
[]EventDesc{
|
||||
{Name: "event1", SrcState: []State{"init_state"}, DstState: "state2"},
|
||||
{Name: "event2", SrcState: []State{"state2"}, DstState: "init_state"},
|
||||
},
|
||||
nil,
|
||||
)
|
||||
|
@ -199,27 +224,26 @@ func TestFSM_EntryEvent(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestFSM_EventsList(t *testing.T) {
|
||||
eventsList := []string{
|
||||
eventsList := []Event{
|
||||
EventFSM1Init,
|
||||
EventFSM1Cancel,
|
||||
EventFSM1Process,
|
||||
}
|
||||
|
||||
if !compareArrays(testingFSM.EventsList(), eventsList) {
|
||||
if !compareEventsArr(testingFSM.EventsList(), eventsList) {
|
||||
t.Error("expected public events", eventsList)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestFSM_StatesList(t *testing.T) {
|
||||
log.Println(testingFSM.StatesSourcesList())
|
||||
statesList := []string{
|
||||
statesList := []State{
|
||||
FSM1StateInit,
|
||||
FSM1StateStage1,
|
||||
FSM1StateStage2,
|
||||
}
|
||||
|
||||
if !compareArrays(testingFSM.StatesSourcesList(), statesList) {
|
||||
if !compareStatesArr(testingFSM.StatesSourcesList(), statesList) {
|
||||
t.Error("expected states", statesList)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,50 +6,52 @@ import (
|
|||
"github.com/depools/dc4bc/fsm/fsm"
|
||||
)
|
||||
|
||||
type IStateMachine interface {
|
||||
type MachineProvider interface {
|
||||
// Returns machine state from scope dump
|
||||
// For nil argument returns fsm with process initiation
|
||||
// Get() IStateMachine
|
||||
// Get() MachineProvider
|
||||
|
||||
Name() string
|
||||
|
||||
InitialState() string
|
||||
InitialState() fsm.State
|
||||
|
||||
// Process event
|
||||
Do(event string, args ...interface{}) (*fsm.FSMResponse, error)
|
||||
Do(event fsm.Event, args ...interface{}) (*fsm.Response, error)
|
||||
|
||||
GlobalInitialEvent() string
|
||||
GlobalInitialEvent() fsm.Event
|
||||
|
||||
EventsList() []string
|
||||
EventsList() []fsm.Event
|
||||
|
||||
StatesSourcesList() []string
|
||||
StatesSourcesList() []fsm.State
|
||||
|
||||
IsFinState(state string) bool
|
||||
IsFinState(state fsm.State) bool
|
||||
}
|
||||
|
||||
type FSMMapper map[string]IStateMachine
|
||||
type FSMMapper map[string]MachineProvider
|
||||
|
||||
type FSMRouteMapper map[string]string
|
||||
type FSMEventsMapper map[fsm.Event]string
|
||||
|
||||
type FSMPoolProvider struct {
|
||||
fsmInitialEvent string
|
||||
type FSMStatesMapper map[fsm.State]string
|
||||
|
||||
type FSMPool struct {
|
||||
fsmInitialEvent fsm.Event
|
||||
// Pool mapper by names
|
||||
mapper FSMMapper
|
||||
events FSMRouteMapper
|
||||
states FSMRouteMapper
|
||||
events FSMEventsMapper
|
||||
states FSMStatesMapper
|
||||
}
|
||||
|
||||
func Init(machines ...IStateMachine) *FSMPoolProvider {
|
||||
func Init(machines ...MachineProvider) *FSMPool {
|
||||
if len(machines) == 0 {
|
||||
panic("cannot initialize empty pool")
|
||||
}
|
||||
p := &FSMPoolProvider{
|
||||
p := &FSMPool{
|
||||
mapper: make(FSMMapper),
|
||||
events: make(FSMRouteMapper),
|
||||
states: make(FSMRouteMapper),
|
||||
events: make(FSMEventsMapper),
|
||||
states: make(FSMStatesMapper),
|
||||
}
|
||||
|
||||
allInitStatesMap := make(map[string]string)
|
||||
allInitStatesMap := make(map[fsm.State]string)
|
||||
|
||||
// Fill up mapper
|
||||
for _, machine := range machines {
|
||||
|
@ -99,7 +101,7 @@ func Init(machines ...IStateMachine) *FSMPoolProvider {
|
|||
if machine.IsFinState(state) {
|
||||
// If state is initial for another machine,
|
||||
if initMachineName, exists := allInitStatesMap[state]; exists {
|
||||
p.states[allInitStatesMap[state]] = initMachineName
|
||||
p.states[state] = initMachineName
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
@ -117,7 +119,7 @@ func Init(machines ...IStateMachine) *FSMPoolProvider {
|
|||
return p
|
||||
}
|
||||
|
||||
func (p *FSMPoolProvider) EntryPointMachine() (IStateMachine, error) {
|
||||
func (p *FSMPool) EntryPointMachine() (MachineProvider, error) {
|
||||
// StateGlobalIdle
|
||||
// TODO: Short code
|
||||
entryStateMachineName := p.events[p.fsmInitialEvent]
|
||||
|
@ -130,7 +132,7 @@ func (p *FSMPoolProvider) EntryPointMachine() (IStateMachine, error) {
|
|||
return machine, nil
|
||||
}
|
||||
|
||||
func (p *FSMPoolProvider) MachineByEvent(event string) (IStateMachine, error) {
|
||||
func (p *FSMPool) MachineByEvent(event fsm.Event) (MachineProvider, error) {
|
||||
eventMachineName := p.events[event]
|
||||
machine, exists := p.mapper[eventMachineName]
|
||||
|
||||
|
@ -140,7 +142,7 @@ func (p *FSMPoolProvider) MachineByEvent(event string) (IStateMachine, error) {
|
|||
return machine, nil
|
||||
}
|
||||
|
||||
func (p *FSMPoolProvider) MachineByState(state string) (IStateMachine, error) {
|
||||
func (p *FSMPool) MachineByState(state fsm.State) (MachineProvider, error) {
|
||||
eventMachineName := p.states[state]
|
||||
machine, exists := p.mapper[eventMachineName]
|
||||
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
package fsm_pool
|
||||
|
||||
/*
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
var (
|
||||
|
||||
)
|
||||
|
||||
func init() {
|
||||
|
||||
}
|
||||
|
||||
func Test_InitPool(t *testing.T) {
|
||||
|
||||
} */
|
|
@ -14,17 +14,17 @@ import (
|
|||
// Is machine state scope dump will be locked?
|
||||
type FSMDump struct {
|
||||
Id string
|
||||
State string
|
||||
State fsm.State
|
||||
Payload internal.MachineStatePayload
|
||||
}
|
||||
|
||||
type FSMInstance struct {
|
||||
machine fsm_pool.IStateMachine
|
||||
machine fsm_pool.MachineProvider
|
||||
dump *FSMDump
|
||||
}
|
||||
|
||||
var (
|
||||
fsmPoolProvider *fsm_pool.FSMPoolProvider
|
||||
fsmPoolProvider *fsm_pool.FSMPool
|
||||
)
|
||||
|
||||
func init() {
|
||||
|
@ -53,7 +53,7 @@ func New(data []byte) (*FSMInstance, error) {
|
|||
return i, err
|
||||
}
|
||||
|
||||
func (i *FSMInstance) Do(event string, args ...interface{}) (*fsm.FSMResponse, []byte, error) {
|
||||
func (i *FSMInstance) Do(event fsm.Event, args ...interface{}) (*fsm.Response, []byte, error) {
|
||||
// Provide payload as first argument ever
|
||||
result, err := i.machine.Do(event, append([]interface{}{i.dump.Payload}, args...)...)
|
||||
|
||||
|
|
|
@ -19,18 +19,18 @@ type SignatureConstructFSM struct {
|
|||
*fsm.FSM
|
||||
}
|
||||
|
||||
func New() fsm_pool.IStateMachine {
|
||||
func New() fsm_pool.MachineProvider {
|
||||
machine := &SignatureConstructFSM{}
|
||||
|
||||
machine.FSM = fsm.MustNewFSM(
|
||||
fsmName,
|
||||
stateConstructorEntryPoint,
|
||||
[]fsm.Event{
|
||||
[]fsm.EventDesc{
|
||||
// {Name: "", SrcState: []string{""}, DstState: ""},
|
||||
|
||||
// Init
|
||||
{Name: eventInitSignatureConstructor, SrcState: []string{stateConstructorEntryPoint}, DstState: awaitConstructor},
|
||||
{Name: eventInitSignatureFinishTmp, SrcState: []string{awaitConstructor}, DstState: "dkg_proposal_fsm"},
|
||||
{Name: eventInitSignatureConstructor, SrcState: []fsm.State{stateConstructorEntryPoint}, DstState: awaitConstructor},
|
||||
{Name: eventInitSignatureFinishTmp, SrcState: []fsm.State{awaitConstructor}, DstState: "dkg_proposal_fsm"},
|
||||
},
|
||||
fsm.Callbacks{},
|
||||
)
|
||||
|
|
|
@ -4,6 +4,7 @@ import (
|
|||
"errors"
|
||||
"log"
|
||||
|
||||
"github.com/depools/dc4bc/fsm/fsm"
|
||||
"github.com/depools/dc4bc/fsm/state_machines/internal"
|
||||
"github.com/depools/dc4bc/fsm/types/requests"
|
||||
"github.com/depools/dc4bc/fsm/types/responses"
|
||||
|
@ -11,7 +12,7 @@ import (
|
|||
|
||||
// init -> awaitingConfirmations
|
||||
// args: payload, signing id, participants list
|
||||
func (s *SignatureProposalFSM) actionInitProposal(event string, args ...interface{}) (response interface{}, err error) {
|
||||
func (s *SignatureProposalFSM) actionInitProposal(event fsm.Event, args ...interface{}) (response interface{}, err error) {
|
||||
var payload internal.MachineStatePayload
|
||||
// Init proposal
|
||||
log.Println("I'm actionInitProposal")
|
||||
|
@ -83,17 +84,17 @@ func (s *SignatureProposalFSM) actionInitProposal(event string, args ...interfac
|
|||
}
|
||||
|
||||
//
|
||||
func (s *SignatureProposalFSM) actionConfirmProposalByParticipant(event string, args ...interface{}) (response interface{}, err error) {
|
||||
func (s *SignatureProposalFSM) actionConfirmProposalByParticipant(event fsm.Event, args ...interface{}) (response interface{}, err error) {
|
||||
log.Println("I'm actionConfirmProposalByParticipant")
|
||||
return
|
||||
}
|
||||
|
||||
func (s *SignatureProposalFSM) actionDeclineProposalByParticipant(event string, args ...interface{}) (response interface{}, err error) {
|
||||
func (s *SignatureProposalFSM) actionDeclineProposalByParticipant(event fsm.Event, args ...interface{}) (response interface{}, err error) {
|
||||
log.Println("I'm actionDeclineProposalByParticipant")
|
||||
return
|
||||
}
|
||||
|
||||
func (s *SignatureProposalFSM) actionValidateProposal(event string, args ...interface{}) (response interface{}, err error) {
|
||||
func (s *SignatureProposalFSM) actionValidateProposal(event fsm.Event, args ...interface{}) (response interface{}, err error) {
|
||||
log.Println("I'm actionValidateProposal")
|
||||
return
|
||||
}
|
||||
|
|
|
@ -9,53 +9,53 @@ const (
|
|||
fsmName = "signature_proposal_fsm"
|
||||
signingIdLen = 32
|
||||
|
||||
stateAwaitProposalConfirmation = "validate_proposal" // waiting participants
|
||||
stateAwaitProposalConfirmation = fsm.State("validate_proposal") // waiting participants
|
||||
|
||||
stateValidationCanceledByParticipant = "validation_canceled_by_participant"
|
||||
stateValidationCanceledByTimeout = "validation_canceled_by_timeout"
|
||||
stateValidationCanceledByParticipant = fsm.State("validation_canceled_by_participant")
|
||||
stateValidationCanceledByTimeout = fsm.State("validation_canceled_by_timeout")
|
||||
|
||||
stateProposed = "proposed"
|
||||
|
||||
eventInitProposal = "proposal_init"
|
||||
eventConfirmProposal = "proposal_confirm_by_participant"
|
||||
eventDeclineProposal = "proposal_decline_by_participant"
|
||||
eventValidateProposal = "proposal_validate"
|
||||
eventSetProposalValidated = "proposal_set_validated"
|
||||
eventInitProposal = fsm.Event("proposal_init")
|
||||
eventConfirmProposal = fsm.Event("proposal_confirm_by_participant")
|
||||
eventDeclineProposal = fsm.Event("proposal_decline_by_participant")
|
||||
eventValidateProposal = fsm.Event("proposal_validate")
|
||||
eventSetProposalValidated = fsm.Event("proposal_set_validated")
|
||||
|
||||
eventSetValidationCanceledByTimeout = "proposal_canceled_timeout"
|
||||
eventSwitchProposedToSigning = "switch_state_to_signing"
|
||||
eventSetValidationCanceledByTimeout = fsm.Event("proposal_canceled_timeout")
|
||||
eventSwitchProposedToSigning = fsm.Event("switch_state_to_signing")
|
||||
)
|
||||
|
||||
type SignatureProposalFSM struct {
|
||||
*fsm.FSM
|
||||
}
|
||||
|
||||
func New() fsm_pool.IStateMachine {
|
||||
func New() fsm_pool.MachineProvider {
|
||||
machine := &SignatureProposalFSM{}
|
||||
|
||||
machine.FSM = fsm.MustNewFSM(
|
||||
fsmName,
|
||||
fsm.StateGlobalIdle,
|
||||
[]fsm.Event{
|
||||
[]fsm.EventDesc{
|
||||
// {Name: "", SrcState: []string{""}, DstState: ""},
|
||||
|
||||
// Init
|
||||
{Name: eventInitProposal, SrcState: []string{fsm.StateGlobalIdle}, DstState: stateAwaitProposalConfirmation},
|
||||
{Name: eventInitProposal, SrcState: []fsm.State{fsm.StateGlobalIdle}, DstState: stateAwaitProposalConfirmation},
|
||||
|
||||
// Validate by participants
|
||||
{Name: eventConfirmProposal, SrcState: []string{stateAwaitProposalConfirmation}, DstState: stateAwaitProposalConfirmation},
|
||||
{Name: eventConfirmProposal, SrcState: []fsm.State{stateAwaitProposalConfirmation}, DstState: stateAwaitProposalConfirmation},
|
||||
// Is decline event should auto change state to default, or it process will initiated by client (external emit)?
|
||||
// Now set for external emitting.
|
||||
{Name: eventDeclineProposal, SrcState: []string{stateAwaitProposalConfirmation}, DstState: stateValidationCanceledByParticipant},
|
||||
{Name: eventDeclineProposal, SrcState: []fsm.State{stateAwaitProposalConfirmation}, DstState: stateValidationCanceledByParticipant},
|
||||
|
||||
{Name: eventValidateProposal, SrcState: []string{stateAwaitProposalConfirmation}, DstState: stateAwaitProposalConfirmation},
|
||||
{Name: eventValidateProposal, SrcState: []fsm.State{stateAwaitProposalConfirmation}, DstState: stateAwaitProposalConfirmation},
|
||||
|
||||
// eventProposalValidate internal or from client?
|
||||
// yay
|
||||
// Exit point
|
||||
{Name: eventSetProposalValidated, SrcState: []string{stateAwaitProposalConfirmation}, DstState: "process_sig", IsInternal: true},
|
||||
{Name: eventSetProposalValidated, SrcState: []fsm.State{stateAwaitProposalConfirmation}, DstState: "process_sig", IsInternal: true},
|
||||
// nan
|
||||
{Name: eventSetValidationCanceledByTimeout, SrcState: []string{stateAwaitProposalConfirmation}, DstState: stateValidationCanceledByTimeout, IsInternal: true},
|
||||
{Name: eventSetValidationCanceledByTimeout, SrcState: []fsm.State{stateAwaitProposalConfirmation}, DstState: stateValidationCanceledByTimeout, IsInternal: true},
|
||||
},
|
||||
fsm.Callbacks{
|
||||
eventInitProposal: machine.actionInitProposal,
|
||||
|
|
1
go.mod
1
go.mod
|
@ -8,7 +8,6 @@ require (
|
|||
github.com/juju/fslock v0.0.0-20160525022230-4d5c94c67b4b
|
||||
github.com/looplab/fsm v0.1.0
|
||||
github.com/makiuchi-d/gozxing v0.0.0-20190830103442-eaff64b1ceb7
|
||||
github.com/mattn/go-pointer v0.0.0-20190911064623-a0a44394634f // indirect
|
||||
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e
|
||||
github.com/stretchr/testify v1.6.1
|
||||
github.com/syndtr/goleveldb v1.0.0
|
||||
|
|
6
go.sum
6
go.sum
|
@ -20,10 +20,6 @@ github.com/looplab/fsm v0.1.0 h1:Qte7Zdn/5hBNbXzP7yxVU4OIFHWXBovyTT2LaBTyC20=
|
|||
github.com/looplab/fsm v0.1.0/go.mod h1:m2VaOfDHxqXBBMgc26m6yUOwkFn8H2AlJDE+jd/uafI=
|
||||
github.com/makiuchi-d/gozxing v0.0.0-20190830103442-eaff64b1ceb7 h1:CfWnkHgRG8zmxQI7RAhLIUFPkg+RfDdWiEtoE3y1+4w=
|
||||
github.com/makiuchi-d/gozxing v0.0.0-20190830103442-eaff64b1ceb7/go.mod h1:WoI7z45M7ZNA5BJxiJHaB+x7+k8S/3phW5Y13IR4yWY=
|
||||
github.com/mattn/go-gtk v0.0.0-20191030024613-af2e013261f5 h1:GMB3MVJnxysGrSvjWGsgK8L3XGI3F4etQQq37Py6W5A=
|
||||
github.com/mattn/go-gtk v0.0.0-20191030024613-af2e013261f5/go.mod h1:PwzwfeB5syFHXORC3MtPylVcjIoTDT/9cvkKpEndGVI=
|
||||
github.com/mattn/go-pointer v0.0.0-20190911064623-a0a44394634f h1:QTRRO+ozoYgT3CQRIzNVYJRU3DB8HRnkZv6mr4ISmMA=
|
||||
github.com/mattn/go-pointer v0.0.0-20190911064623-a0a44394634f/go.mod h1:2zXcozF6qYGgmsG+SeTZz3oAbFLdD3OWqnUbNvJZAlc=
|
||||
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.7.0 h1:WSHQ+IS43OoUrWtD1/bbclrwK8TTH5hzp+umCiuxHgs=
|
||||
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
|
@ -51,9 +47,11 @@ golang.org/x/image v0.0.0-20200618115811-c13761719519 h1:1e2ufUJNM3lCHEY5jIgac/7
|
|||
golang.org/x/image v0.0.0-20200618115811-c13761719519/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd h1:nTDtHvHSdCn1m6ITfMRqtOd/9+7a3s8RBNOZ3eYZzJA=
|
||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a h1:oWX7TPOiFAMXLq8o0ikBYfCJVlRHBcsciT5bXOrH628=
|
||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f h1:wMNYb4v58l5UBM7MYRLPG6ZhfOqbKu7X5eyFl8ZhKvA=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEhagSSnXWGV915qUMm9mrU=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190124100055-b90733256f2e h1:3GIlrlVLfkoipSReOMNAgApI0ajnalyLa/EZHHca/XI=
|
||||
|
|
Loading…
Reference in New Issue