Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/gebv/ffsm
Finite State Machine for Go with transition handlers
https://github.com/gebv/ffsm
finite-state-machine fsm go
Last synced: 3 days ago
JSON representation
Finite State Machine for Go with transition handlers
- Host: GitHub
- URL: https://github.com/gebv/ffsm
- Owner: gebv
- License: mit
- Created: 2019-05-08T12:41:42.000Z (almost 6 years ago)
- Default Branch: master
- Last Pushed: 2021-09-08T19:20:34.000Z (over 3 years ago)
- Last Synced: 2024-12-17T01:28:24.080Z (about 2 months ago)
- Topics: finite-state-machine, fsm, go
- Language: Go
- Homepage:
- Size: 554 KB
- Stars: 0
- Watchers: 3
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: LICENSE
Awesome Lists containing this project
README
# FFSM
![CI Status](https://github.com/gebv/ffsm/workflows/Go/badge.svg)
[![Go Report Card](https://goreportcard.com/badge/github.com/gebv/ffsm)](https://goreportcard.com/report/github.com/gebv/ffsm)
[![codecov](https://codecov.io/gh/gebv/ffsm/branch/master/graph/badge.svg)](https://codecov.io/gh/gebv/ffsm)Finite State Machine (or FSM) written in Go. It is a low-level primitive for more complex solutions. Supported (optional) transition handler for advanced logic.
What is a finite state machine (or FSM)? TODO
* [Features](#features)
* [Quickstart](#quickstart)
* [Example code](#examples)
* [Additional packages](#additional-packages)
* [Licence](#license)## Features
* use as [simple FSM](#simple-FSM) or with [transition handlers](#fsm-with-transition-handlers) for advanced logic
* dispatcher is thread-safe
* implemented `prometheus.Collector` for monitoring## Quickstart
Install or update `ffsm` package.
```
go get -u github.com/gebv/ffsm
```Simple example:
```golang
// enum of states
var (
OpenDoor = "open"
CloseDoor = "close"
)// setup of state transition diagram
wf := make(ffsm.Stack).Add(OpenDoor, CloseDoor).Add(CloseDoor, OpenDoor)// init FSM with initial state CloseDoor
fsm := ffsm.NewFSM(wf, CloseDoor)// to opens the door
err := fsm.Dispatch(context.Background(), OpenDoor)if err != nil {
// handler errors
}fsm.State() // end state
```## Examples
Finite state machine example
### Simple FSM
Can open door and close door. Opened door can not open. And closed door can not close.
Follow state transition diagram in image
On the playground https://play.golang.org/p/J8Cej99Rp-J
Listing code
```golang
package mainimport (
"context"
"fmt""github.com/gebv/ffsm"
)func main() {
// setup state transition diagram
wf := make(ffsm.Stack).Add(OpenDoor, CloseDoor).Add(CloseDoor, OpenDoor)// init FSM with initial state CloseDoor
fsm := ffsm.NewFSM(wf, CloseDoor)
fmt.Println("initial state:", fsm.State())
fmt.Println()fmt.Println("to open door")
fmt.Println("----------------------------")
fmt.Println("before:", fsm.State())
err := fsm.Dispatch(context.Background(), OpenDoor)
if err != nil {
fmt.Println("failed:", err)
}
fmt.Println("after:", fsm.State())
fmt.Println()fmt.Println("to open door for opened door")
fmt.Println("----------------------------")
fmt.Println("before:", fsm.State())
err = fsm.Dispatch(context.Background(), OpenDoor)
if err != nil {
fmt.Println("failed:", err)
}
fmt.Println("after:", fsm.State())
fmt.Println()fmt.Println("to close door")
fmt.Println("----------------------------")
fmt.Println("before:", fsm.State())
err = fsm.Dispatch(context.Background(), CloseDoor)
if err != nil {
fmt.Println("failed:", err)
}
fmt.Println("after:", fsm.State())
}const (
OpenDoor = "open"
CloseDoor = "close"
)
```### FSM with transition handlers
Only Bob can open door. Anyone can close the door. And also opened door can not open and closed door can not close.
Follow state transition diagram in image
On the playground https://play.golang.org/p/M5JiBwUycnx
Listing code
```golang
package mainimport (
"context"
"fmt"
"errors""github.com/gebv/ffsm"
)func main() {
// handler for CloseDoor to OpenDoor transition
onlyBobHandler := func(ctx context.Context) (context.Context, error) {
name, ok := ctx.Value("__name").(string)
if !ok {
return ctx, errors.New("forbidden - only for Bob")
}
if name != "bob" {
return ctx, errors.New("forbidden - only for Bob")
}
return ctx, nil
}
// setup state transition diagram
wf := make(ffsm.Stack).Add(OpenDoor, CloseDoor).Add(CloseDoor, OpenDoor, onlyBobHandler)// init FSM with initial state CloseDoor
fsm := ffsm.NewFSM(wf, CloseDoor)
fmt.Println("initial state:", fsm.State())
fmt.Println()fmt.Println("anonymous opens door")
fmt.Println("----------------------------")
fmt.Println("before:", fsm.State())
err := fsm.Dispatch(context.Background(), OpenDoor)
if err != nil {
fmt.Println("failed:", err)
}
fmt.Println("after:", fsm.State())
fmt.Println()fmt.Println("Bob opens door")
fmt.Println("----------------------------")
fmt.Println("before:", fsm.State())
bobCtx := context.WithValue(context.Background(), "__name", "bob")
err = fsm.Dispatch(bobCtx, OpenDoor)
if err != nil {
fmt.Println("failed:", err)
}
fmt.Println("after:", fsm.State())
fmt.Println()fmt.Println("to open door for opened door")
fmt.Println("----------------------------")
fmt.Println("before:", fsm.State())
err = fsm.Dispatch(context.Background(), OpenDoor)
if err != nil {
fmt.Println("failed:", err)
}
fmt.Println("after:", fsm.State())
fmt.Println()fmt.Println("to close door")
fmt.Println("----------------------------")
fmt.Println("before:", fsm.State())
err = fsm.Dispatch(context.Background(), CloseDoor)
if err != nil {
fmt.Println("failed:", err)
}
fmt.Println("after:", fsm.State())
}const (
OpenDoor = "open"
CloseDoor = "close"
)
```### More examples
[See more in tests](fsm_test.go)
# Additional packages
* [github.com/prometheus/client_golang](https://github.com/prometheus/client_golang) prometheus client for golang
* [github.com/stretchr/testify](https://github.com/stretchr/testify) helper package for testing# Version Policy
`ffsm` follows semantic versioning for the documented public API on stable releases. v1.2 is the latest stable version. Follows [changelog](./CHANGELOG.md).
# License
MIT, see [LICENSE](./LICENSE).