/docs/getting-started.md
Getting started with asyncmachine-go, in this tutorial we will:
- Define a state machine schema
- Generate a project boilerplate
- Run test cases
- Modify the state machine handlers
- Debug the machine
- Modify state via the command line
- Replace a relation with a negotiation handler
0. Prerequisites
We’ll use these tools in the tutorial:
go install github.com/pancsta/asyncmachine-go/tools/cmd/am-gen@latest
go install github.com/pancsta/asyncmachine-go/tools/cmd/am-dbg@latest
go install github.com/pancsta/asyncmachine-go/tools/cmd/arpc@latest
1. Define schema
We can define schemas using CLI params and add relations later, or using a simple YAML file.
Create schema.yml with a list of states and some relations:
Wet:
require: [ Water ]
Water:
remove: [ Dry ]
add: [ Wet ]
Dry:
auto: true
remove: [ Water ]
The same state schema without relations can be created via:
am-gen schema --name MyMach \
--state Wet --state Water --state Dry:auto \
--inherit basic --inherit disposed --inherit rpc/statesrc
2. Generate a project boilerplate
Now let’s generate the project’s starter kit via:
am-gen starter-kit schema.yml --name MyMach --uri mymach
This will create the following file structure (also available in here`:
$ tree my_mach
my_mach
├── go.mod
├── handlers.go
├── my_mach.go
├── my_mach_test.go
└── states
└── ss_my_mach.go
2 directories, 5 files
3. Run test cases
Run the provided test case for the Start state:
cd my_mach
go test -v .
4. Modify the state machine handlers
Replace the following final handlers in my_mach.go:
func (h *Handlers) WetState(e *am.Event) {
fmt.Println("it is wet now")
}
func (h *Handlers) DryState(e *am.Event) {
fmt.Println("it is dry now")
}
5. Debug the machine
Start am-dbg on the default port via am-dbg --output-diagrams 1 and change isDebug to true in my_mach.go, then
go test . again. We should see the machine with transitions, tailing the input. The transition step sequence for the
current transition is available at:
am-dbg/diagrams/am-vis-steps.d2.svg- localhost:6832/viewer/steps.svg
am-dbg/tx.md
6. Modify state via the command line
Create a simple program using the new machine by creating ./cmd/main.go:
package main
import (
"context"
"mymach"
"mymach/states"
)
var ss = states.MyMachStates
func main() {
ctx := context.Background()
h, _ := mymach.New(ctx)
h.Mach.Add1(ss.Start, nil)
<-h.Mach.WhenNot1(ss.Start, nil)
}
go run ./cmd and it should pop up in the debugger, this time in a live session.
Now let’s change the state manually via the CLI (or the REPL).
arpc -f my_mach.addr -- add . Water
arpc -f my_mach.addr -- remove . Water
# REPL via arpc -f my_mach.addr
7. Replace relation with a negotiation handler
Remove the Wet:Require relation in the schema file states/ss_my_mach.go, so the state looks like this:
ssM.Wet: {},
Replace the WetEnter negotiation handler in my_mach.go with:
func (h *Handlers) WetEnter(e *am.Event) bool {
return e.Transition().TimeIndexAfter().Is1(ss.Water)
}
Now go run . it and verify that points 3 and 6 give
the same result, but the transition step diagram differs. The transition cancelation causes also show up in the
“Log Reader” pane.
