diff --git a/README.md b/README.md
index 3c7a6db..486fea9 100644
--- a/README.md
+++ b/README.md
@@ -2,23 +2,23 @@
![TUI Debugger](assets/am-dbg.gif)
-**asyncmachine-go** is a minimal implementation of [AsyncMachine](https://github.com/TobiaszCudnik/asyncmachine) in
-Golang using **channels and context**. It aims at simplicity and speed.
+> **asyncmachine-go** is a general purpose state machine for managing complex asynchronous workflows in a safe and
+> structured way
-It can be used as a lightweight in-memory [Temporal](https://github.com/temporalio/temporal) alternative, worker for
-[Asynq](https://github.com/hibiken/asynq), or to create simple consensus engines, stateful firewalls, telemetry, bots,
-etc.
+**asyncmachine-go** can be used as a lightweight in-memory [Temporal](https://github.com/temporalio/temporal)
+alternative, worker for [Asynq](https://github.com/hibiken/asynq), or to create simple consensus engines, stateful
+firewalls, telemetry, bots, etc.
-> **asyncmachine-go** is a general purpose state machine for managing complex asynchronous workflows in a safe and
-> structured way.
+The project itself is a minimal implementation of [AsyncMachine](https://github.com/TobiaszCudnik/asyncmachine)
+in Golang using **channels and context**. It aims at simplicity and speed.
-See am-dbg's states structure and relations
+Check am-dbg's states structure and relations
```go
+// States map defines relations and properties of states.
var States = am.Struct{
-
///// Input events
ClientMsg: {Multi: true},
@@ -47,6 +47,8 @@ var States = am.Struct{
///// External state (eg UI)
+ // focus group
+
TreeFocused: {Remove: GroupFocused},
LogFocused: {Remove: GroupFocused},
SidebarFocused: {Remove: GroupFocused},
@@ -54,6 +56,7 @@ var States = am.Struct{
TimelineStepsFocused: {Remove: GroupFocused},
MatrixFocused: {Remove: GroupFocused},
DialogFocused: {Remove: GroupFocused},
+
StateNameSelected: {Require: S{ClientSelected}},
HelpDialog: {Remove: GroupDialog},
ExportDialog: {
@@ -87,6 +90,7 @@ var States = am.Struct{
},
// tx / steps back / fwd
+
Fwd: {
Require: S{ClientSelected},
Remove: S{Playing},
@@ -106,7 +110,8 @@ var States = am.Struct{
ScrollToTx: {Require: S{ClientSelected}},
- // client
+ // client selection
+
SelectingClient: {Remove: S{ClientSelected}},
ClientSelected: {
Remove: S{SelectingClient, LogUserScrolled},
@@ -117,7 +122,7 @@ var States = am.Struct{
-## Comparison
+## Manifesto
Common differences with other state machines:
@@ -125,8 +130,9 @@ Common differences with other state machines:
- transitions between all the states are allowed
- unless constrained
- states are connected by relations
-- every mutation can be rejected
+- every transition can be rejected
- error is a state
+ - including `panic()`
## Usage
@@ -176,13 +182,15 @@ type Handlers struct {
// 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 (but no blocking)
+ // read & write ops
+ // no blocking
// lock-free critical zone
mach := e.Machine
// tick-based context
@@ -198,7 +206,7 @@ func (h *Handlers) ProcessingFileState(e *am.Event) {
mach.AddErr(err)
return
}
- // re-check the ctx after a blocking call
+ // re-check the tick ctx after a blocking call
if stateCtx.Err() != nil {
return // expired
}
@@ -371,6 +379,7 @@ var States = am.Struct{
### [Temporal FileProcessing workflow](/examples/temporal-fileprocessing/fileprocessing.go)
- [origin](https://github.com/temporalio/samples-go/blob/main/fileprocessing/)
+- [Asynq worker version](examples/asynq-fileprocessing/fileprocessing_task.go)
@@ -398,8 +407,6 @@ var States = am.Struct{
-### [AM as an Asynq worker](examples/asynq-fileprocessing/fileprocessing_task.go)
-
## Documentation
- [godoc](https://godoc.org/github.com/pancsta/asyncmachine-go/pkg/machine)
@@ -423,7 +430,7 @@ var States = am.Struct{
-Example template for Foo and Bar
+Check the example template for Foo and Bar
```go
package states
@@ -555,8 +562,8 @@ or the [pdf results](https://github.com/pancsta/go-libp2p-pubsub-benchmark/raw/m
State-only machine (no handlers, no goroutine). States represent correlations with peer machines.
See
-[github.com/pancsta/**go-libp2p-pubsub-benchmark**](https://github.com/pancsta/go-libp2p-pubsub-benchmark/tree/main/internal/sim)
-and the [pubsub machines](https://github.com/pancsta/go-libp2p-pubsub/tree/psmon-states/states) for more info.
+[github.com/pancsta/**go-libp2p-pubsub-benchmark**](https://github.com/pancsta/go-libp2p-pubsub-benchmark?tab=readme-ov-file#libp2p-pubsub-simulator)
+for more info.
### am-dbg
@@ -566,7 +573,7 @@ am-dbg is a [tview](https://github.com/rivo/tview/) TUI app with a single machin
- external state (11 states)
- actions (14 states)
-This machine features a decent amount of relations within a large number od states and 4 state groups. It's also a good
+This machine features a decent amount of relations within a large number of states and 4 state groups. It's also a good
example to see how easily an AM-based program can be controller with a script in [tools/cmd/am-dbg-demo](tools/cmd/am-dbg-demo/main.go#L68).
See [tools/debugger/states](tools/debugger/states) for more info.
@@ -599,8 +606,6 @@ See also [issues](https://github.com/pancsta/asyncmachine-go/issues).
Latest release: `v0.5.0`
-## [v0.5.0](https://github.com/pancsta/asyncmachine-go/tree/v0.5.0) (2024-06-06)
-
- feat: add tools/cmd/am-gen [\#63](https://github.com/pancsta/asyncmachine-go/pull/63) (@pancsta)
- feat\(am-dbg\): add `--select-connected` and `--clean-on-connect`
[\#62](https://github.com/pancsta/asyncmachine-go/pull/62) (@pancsta)
@@ -613,7 +618,7 @@ Latest release: `v0.5.0`
- feat\(machine\): add empty roadmap methods [\#55](https://github.com/pancsta/asyncmachine-go/pull/55) (@pancsta)
- feat\(machine\): add Eval [\#54](https://github.com/pancsta/asyncmachine-go/pull/54) (@pancsta)
- refac\(pkg/machine\): rename many identifiers, shorten [\#53](https://github.com/pancsta/asyncmachine-go/pull/53) (@pancsta)
-- feat\(machine\): drop add dependencies \(lo, uuid\) [\#52](https://github.com/pancsta/asyncmachine-go/pull/52) (@pancsta)
+- feat\(machine\): drop all dependencies \(lo, uuid\) [\#52](https://github.com/pancsta/asyncmachine-go/pull/52) (@pancsta)
- feat\(machine\): alloc handler goroutine on demand [\#51](https://github.com/pancsta/asyncmachine-go/pull/51) (@pancsta)
- feat\(machine\): add Transition.ClocksAfter [\#50](https://github.com/pancsta/asyncmachine-go/pull/50) (@pancsta)
- feat\(machine\): add HasStateChangedSince [\#49](https://github.com/pancsta/asyncmachine-go/pull/49) (@pancsta)
diff --git a/assets/prometheus-grafana.light.png b/assets/prometheus-grafana.light.png
index 71fd714..07cf91d 100644
Binary files a/assets/prometheus-grafana.light.png and b/assets/prometheus-grafana.light.png differ
diff --git a/pkg/machine/machine_test.go b/pkg/machine/machine_test.go
index 1d62c02..1ba9ee8 100644
--- a/pkg/machine/machine_test.go
+++ b/pkg/machine/machine_test.go
@@ -10,25 +10,23 @@ import (
"github.com/stretchr/testify/assert"
)
-// TODO ExampleNew
func ExampleNew() {
t := &testing.T{} // Replace this with actual *testing.T in real test cases
initialState := S{"A"}
mach := NewNoRels(t, initialState)
- // Use the machine m here
+ // machine mach ready
_ = mach
}
-// TODO ExampleNewCommon
func ExampleNewCommon() {
t := &testing.T{} // Replace this with actual *testing.T in real test cases
initialState := S{"A"}
mach := NewNoRels(t, initialState)
- // Use the machine m here
+ // machine mach ready
_ = mach
}
diff --git a/pkg/machine/misc.go b/pkg/machine/misc.go
index 4e3ef24..48ea8f0 100644
--- a/pkg/machine/misc.go
+++ b/pkg/machine/misc.go
@@ -217,8 +217,8 @@ type Mutation struct {
Eval func()
}
-// StateWasCalled returns true if the Mutation was called with the passed
-// state (or does it come from relations).
+// StateWasCalled returns true if the Mutation was called (directly) with the
+// passed state (in opposite to it coming from an `Add` relation).
func (m Mutation) StateWasCalled(state string) bool {
return slices.Contains(m.CalledStates, state)
}
diff --git a/pkg/machine/transition.go b/pkg/machine/transition.go
index 3edf1ba..52f41d8 100644
--- a/pkg/machine/transition.go
+++ b/pkg/machine/transition.go
@@ -26,7 +26,7 @@ func newSteps(from string, toStates S, stepType StepType,
return ret
}
-// Transition represents processing of a single mutation withing a machine.
+// Transition represents processing of a single mutation within a machine.
type Transition struct {
ID string
// List of steps taken by this transition (so far).
@@ -41,15 +41,15 @@ type Transition struct {
// clocks of the states from after the transition
// TODO timeAfter, produce Clocks via ClockAfter(), add index diffs
ClocksAfter Clocks
- // Struct with "enter" handlers to execute
+ // State names with "enter" handlers to execute
Enters S
- // Struct with "exit" handlers to executed
+ // State names with "exit" handlers to executed
Exits S
// target states after parsing the relations
TargetStates S
// was the transition accepted (during the negotiation phase)
Accepted bool
- // Mutation call which cased this transition
+ // Mutation call which caused this transition
Mutation *Mutation
// Parent machine
Machine *Machine
diff --git a/tools/debugger/states/ss_dbg.go b/tools/debugger/states/ss_dbg.go
index c5e1d00..426cf1e 100644
--- a/tools/debugger/states/ss_dbg.go
+++ b/tools/debugger/states/ss_dbg.go
@@ -8,7 +8,7 @@ type S = am.S
// States map defines relations and properties of states.
var States = am.Struct{
- ///// Input events
+ // /// Input events
ClientMsg: {Multi: true},
ConnectEvent: {Multi: true},
@@ -34,7 +34,9 @@ var States = am.Struct{
Remove: am.SMerge(GroupPlaying, S{LogUserScrolled}),
},
- ///// External state (eg UI)
+ // /// External state (eg UI)
+
+ // focus group
TreeFocused: {Remove: GroupFocused},
LogFocused: {Remove: GroupFocused},
@@ -43,8 +45,9 @@ var States = am.Struct{
TimelineStepsFocused: {Remove: GroupFocused},
MatrixFocused: {Remove: GroupFocused},
DialogFocused: {Remove: GroupFocused},
- StateNameSelected: {Require: S{ClientSelected}},
- HelpDialog: {Remove: GroupDialog},
+
+ StateNameSelected: {Require: S{ClientSelected}},
+ HelpDialog: {Remove: GroupDialog},
ExportDialog: {
Require: S{ClientSelected},
Remove: GroupDialog,
@@ -52,7 +55,7 @@ var States = am.Struct{
LogUserScrolled: {},
Ready: {Require: S{Start}},
- ///// Actions
+ // /// Actions
Start: {},
TreeLogView: {
@@ -76,6 +79,7 @@ var States = am.Struct{
},
// tx / steps back / fwd
+
Fwd: {
Require: S{ClientSelected},
Remove: S{Playing},
@@ -95,7 +99,8 @@ var States = am.Struct{
ScrollToTx: {Require: S{ClientSelected}},
- // client
+ // client selection
+
SelectingClient: {Remove: S{ClientSelected}},
ClientSelected: {
Remove: S{SelectingClient, LogUserScrolled},
@@ -121,7 +126,7 @@ var (
}
)
-//#region boilerplate defs
+// #region boilerplate defs
// Names of all the states (pkg enum).
@@ -176,7 +181,7 @@ const (
// Names is an ordered list of all the state names.
var Names = S{
- ///// Input events
+ // /// Input events
ClientMsg,
ConnectEvent,
@@ -188,7 +193,7 @@ var Names = S{
UserFwdStep,
UserBackStep,
- ///// External state (eg UI)
+ // /// External state (eg UI)
TreeFocused,
LogFocused,
@@ -203,7 +208,7 @@ var Names = S{
LogUserScrolled,
Ready,
- ///// Actions
+ // /// Actions
Start,
TreeLogView,
@@ -229,4 +234,4 @@ var Names = S{
am.Exception,
}
-//#endregion
+// #endregion