Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for metadata #63

Merged
merged 8 commits into from
Dec 23, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 49 additions & 0 deletions examples/data.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// +build ignore

package main

import (
"fmt"

"github.com/looplab/fsm"
)

func main() {
fsm := fsm.NewFSM(
"idle",
fsm.Events{
{Name: "produce", Src: []string{"idle"}, Dst: "idle"},
{Name: "consume", Src: []string{"idle"}, Dst: "idle"},
},
fsm.Callbacks{
"produce": func(e *fsm.Event) {
e.FSM.SetMetadata("message", "hii")
fmt.Println("produced data")
},
"consume": func(e *fsm.Event) {
message, ok := e.FSM.Metadata("message")
if ok {
fmt.Println("message = " + message.(string))
}

},
},
)

fmt.Println(fsm.Current())

err := fsm.Event("produce")
if err != nil {
fmt.Println(err)
}

fmt.Println(fsm.Current())

err = fsm.Event("consume")
if err != nil {
fmt.Println(err)
}

fmt.Println(fsm.Current())

}
25 changes: 23 additions & 2 deletions fsm.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ type FSM struct {
// transitions maps events and source states to destination states.
transitions map[eKey]string

// callbacks maps events and targers to callback functions.
// callbacks maps events and targets to callback functions.
callbacks map[cKey]Callback

// transition is the internal transition functions used either directly
Expand All @@ -57,6 +57,11 @@ type FSM struct {
stateMu sync.RWMutex
// eventMu guards access to Event() and Transition().
eventMu sync.Mutex
// metadata can be used to store and load data that maybe used across events
// use methods SetMetadata() and Metadata() to store and load data
metadata map[string]interface{}

metadataMu sync.RWMutex
}

// EventDesc represents an event when initializing the FSM.
Expand Down Expand Up @@ -129,6 +134,7 @@ func NewFSM(initial string, events []EventDesc, callbacks map[string]Callback) *
current: initial,
transitions: make(map[eKey]string),
callbacks: make(map[cKey]Callback),
metadata: make(map[string]interface{}),
}

// Build transition map and store sets of all events and states.
Expand Down Expand Up @@ -229,7 +235,7 @@ func (f *FSM) Can(event string) bool {
return ok && (f.transition == nil)
}

// AvailableTransitions returns a list of transitions avilable in the
// AvailableTransitions returns a list of transitions available in the
// current state.
func (f *FSM) AvailableTransitions() []string {
f.stateMu.RLock()
Expand All @@ -249,6 +255,21 @@ func (f *FSM) Cannot(event string) bool {
return !f.Can(event)
}

// Metadata returns the value stored in metadata
func (f *FSM) Metadata(key string) (interface{}, bool) {
f.metadataMu.RLock()
defer f.metadataMu.RUnlock()
dataElement, ok := f.metadata[key]
maxekman marked this conversation as resolved.
Show resolved Hide resolved
return dataElement, ok
}

// SetMetadata stores the dataValue in metadata indexing it with key
func (f *FSM) SetMetadata(key string, dataValue interface{}) {
f.metadataMu.Lock()
defer f.metadataMu.Unlock()
f.metadata[key] = dataValue
}

// Event initiates a state transition with the named event.
//
// The call takes a variable number of arguments that will be passed to the
Expand Down
4 changes: 2 additions & 2 deletions visualizer.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@ const (
GRAPHVIZ VisualizeType = "graphviz"
// MERMAID the type for mermaid output (https://mermaid-js.github.io/mermaid/#/stateDiagram) in the stateDiagram form
MERMAID VisualizeType = "mermaid"
// MERMAID the type for mermaid output (https://mermaid-js.github.io/mermaid/#/stateDiagram) in the stateDiagram form
// MermaidStateDiagram the type for mermaid output (https://mermaid-js.github.io/mermaid/#/stateDiagram) in the stateDiagram form
MermaidStateDiagram VisualizeType = "mermaid-state-diagram"
// MERMAID the type for mermaid output (https://mermaid-js.github.io/mermaid/#/flowchart) in the flow chart form
// MermaidFlowChart the type for mermaid output (https://mermaid-js.github.io/mermaid/#/flowchart) in the flow chart form
MermaidFlowChart VisualizeType = "mermaid-flow-chart"
)

Expand Down