The finite state machine is a very classical model. Usually, a finite state machine is manipulated in-memory, so that it requires extra efforts when horizontally scaling. To solve this problem, go-mysql-fsm/fsm
is developed, storing and updating the FSM states in MySQL. See docs for more information.
A MySQL database and a table should be accessible from the environment. For example, we are using the table described below.
mysql> describe fsm.task;
+-------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| id | varchar(64) | NO | PRI | NULL | |
| state | varchar(64) | NO | | | |
+-------+-------------+------+-----+---------+-------+
Using go-sql-driver/mysql to setup the database connection.
import (
"database/sql"
_ "github.com/go-sql-driver/mysql"
"github.com/imnnsu/go-mysql-fsm/fsm"
)
db, err := sql.Open("mysql", "user:password@tcp(127.0.0.1:3306)/fsm")
if err != nil {
panic(err)
}
defer db.Close()
Please see DSN (Data Source Name) for the reference of uri.
Create the Finite State Machine with an ID.
events := []fsm.Event{
{Name: "NotReady", Src: []string{"Running"}, Dst: "Error"},
{Name: "Ready", Src: []string{"Initializing", "Error"}, Dst: "Running"},
{Name: "Stop", Src: []string{"Initializing", "Running", "Error"}, Dst: "Stopped"},
{Name: "Delete", Src: []string{"Stopped"}, Dst: "Deleted"},
}
config := fsm.NewConfig(db, "task", "state", "Initializing", events)
f1 := fsm.NewFSM(config, "1")
f2 := fsm.NewFSM(config, "2")
Then we can set or get the states of multiple finite state machines with the same transition rule, identified by different ID's.
f1.Initialize()
f2.Initialize()
state, _ := f1.Current()
state, _ := f2.Current()
f1.Event("Ready")
f2.Event("NotReady")
state, _ = f1.Current()
state, _ = f2.Current()
Please check the example that updates the finite state machine in multiple go-routines.