Demos & Examples
-> go back to monorepo /
ProcessingFile to FileProcessed
package main
import (
"context"
"time"
am "github.com/pancsta/asyncmachine-go/pkg/machine"
)
func main() {
// init the state machine
mach := am.New(nil, am.Struct{
"ProcessingFile": {
Add: am.S{"InProgress"},
Remove: am.S{"FileProcessed"},
},
"FileProcessed": {
Remove: am.S{"ProcessingFile", "InProgress"},
},
"InProgress": {},
}, nil)
mach.BindHandlers(&Handlers{
Filename: "README.md",
})
// change the state
mach.Add1("ProcessingFile", nil)
// wait for completed
select {
case <-time.After(5 * time.Second):
println("timeout")
case <-mach.WhenErr(nil):
println("err:", mach.Err())
case <-mach.When1("FileProcessed", nil):
println("done")
}
}
type Handlers struct {
Filename string
}
// negotiation handler
func (h *Handlers) ProcessingFileEnter(e *am.Event) bool {
// read-only ops
// decide if moving fwd is ok
// no blocking
// lock-free critical zone
return true
}
// final handler
func (h *Handlers) ProcessingFileState(e *am.Event) {
// read & write ops
// no blocking
// lock-free critical zone
mach := e.Machine
// tick-based context
stateCtx := mach.NewStateCtx("ProcessingFile")
go func() {
// block in the background, locks needed
if stateCtx.Err() != nil {
return // expired
}
// blocking call
err := processFile(h.Filename, stateCtx)
if err != nil {
mach.AddErr(err, nil)
return
}
// re-check the tick ctx after a blocking call
if stateCtx.Err() != nil {
return // expired
}
// move to the next state in the flow
mach.Add1("FileProcessed", nil)
}()
}
func processFile(name string, ctx context.Context) error {
time.Sleep(3 * time.Second)
return nil
}
Live Debugging Sessions
Interactively use the TUI debugger with data pre-generated by libp2p-pubsub-simulator in:
Interactively use the TUI debugger with data pre-generated by remote integration tests in:
States structure
var (
states = am.Struct{
// input states
InputPush: {},
InputCoin: {},
// "state" states
Locked: {
Auto: true,
Remove: groupUnlocked,
},
Unlocked: {Remove: groupUnlocked},
}
)
States structure
var (
states = am.Struct{
// input states
Input: {Multi: true},
// action states
Start: {Add: am.S{StepX}},
// "state" states
StepX: {Remove: groupSteps},
Step0: {Remove: groupSteps},
Step1: {Remove: groupSteps},
Step2: {Remove: groupSteps},
Step3: {Remove: groupSteps},
}
)
States structure
// States map defines relations and properties of states (for files).
var States = am.Struct{
Init: {Add: S{Watching}},
Watching: {
Add: S{Init},
After: S{Init},
},
ChangeEvent: {
Multi: true,
Require: S{Watching},
},
Refreshing: {
Multi: true,
Remove: S{AllRefreshed},
},
Refreshed: {Multi: true},
AllRefreshed: {},
}
// StatesDir map defines relations and properties of states (for directories).
var StatesDir = am.Struct{
Refreshing: {Remove: groupRefreshed},
Refreshed: {Remove: groupRefreshed},
DirDebounced: {Remove: groupRefreshed},
DirCached: {},
}
// Groups of mutually exclusive states.
var groupRefreshed = S{Refreshing, Refreshed, DirDebounced}
States structure
// States map defines relations and properties of states.
var States = am.Struct{
CreatingExpense: {Remove: GroupExpense},
ExpenseCreated: {Remove: GroupExpense},
WaitingForApproval: {
Auto: true,
Remove: GroupApproval,
},
ApprovalGranted: {Remove: GroupApproval},
PaymentInProgress: {
Auto: true,
Remove: GroupPayment,
},
PaymentCompleted: {Remove: GroupPayment},
}
States structure
// States map defines relations and properties of states.
var States = am.Struct{
DownloadingFile: {Remove: GroupFileDownloaded},
FileDownloaded: {Remove: GroupFileDownloaded},
ProcessingFile: {
Auto: true,
Require: S{FileDownloaded},
Remove: GroupFileProcessed,
},
FileProcessed: {Remove: GroupFileProcessed},
UploadingFile: {
Auto: true,
Require: S{FileProcessed},
Remove: GroupFileUploaded,
},
FileUploaded: {Remove: GroupFileUploaded},
}
// Groups of mutually exclusive states.
var (
GroupFileDownloaded = S{DownloadingFile, FileDownloaded}
GroupFileProcessed = S{ProcessingFile, FileProcessed}
GroupFileUploaded = S{UploadingFile, FileUploaded}
)
Case Studies
Several case studies are available to show how to implement various types of state machines, measure performance and produce
a lot of inspectable data.
monorepo
Go back to the monorepo root to continue reading.