Skip to content

Commit

Permalink
chore: fix readme, typos
Browse files Browse the repository at this point in the history
  • Loading branch information
pancsta committed Jun 14, 2024
1 parent 28d9740 commit a69ef67
Show file tree
Hide file tree
Showing 6 changed files with 52 additions and 44 deletions.
51 changes: 28 additions & 23 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.

<details>

<summary>See am-dbg's states structure and relations</summary>
<summary>Check am-dbg's states structure and relations</summary>

```go
// States map defines relations and properties of states.
var States = am.Struct{

///// Input events

ClientMsg: {Multi: true},
Expand Down Expand Up @@ -47,13 +47,16 @@ var States = am.Struct{

///// External state (eg UI)

// focus group

TreeFocused: {Remove: GroupFocused},
LogFocused: {Remove: GroupFocused},
SidebarFocused: {Remove: GroupFocused},
TimelineTxsFocused: {Remove: GroupFocused},
TimelineStepsFocused: {Remove: GroupFocused},
MatrixFocused: {Remove: GroupFocused},
DialogFocused: {Remove: GroupFocused},

StateNameSelected: {Require: S{ClientSelected}},
HelpDialog: {Remove: GroupDialog},
ExportDialog: {
Expand Down Expand Up @@ -87,6 +90,7 @@ var States = am.Struct{
},

// tx / steps back / fwd

Fwd: {
Require: S{ClientSelected},
Remove: S{Playing},
Expand All @@ -106,7 +110,8 @@ var States = am.Struct{

ScrollToTx: {Require: S{ClientSelected}},

// client
// client selection

SelectingClient: {Remove: S{ClientSelected}},
ClientSelected: {
Remove: S{SelectingClient, LogUserScrolled},
Expand All @@ -117,16 +122,17 @@ var States = am.Struct{

</details>

## Comparison
## Manifesto

Common differences with other state machines:

- many states can be active at the same time
- 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

Expand Down Expand Up @@ -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
Expand All @@ -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
}
Expand Down Expand Up @@ -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)

<details>

Expand Down Expand Up @@ -398,8 +407,6 @@ var States = am.Struct{

</details>

### [AM as an Asynq worker](examples/asynq-fileprocessing/fileprocessing_task.go)

## Documentation

- [godoc](https://godoc.org/github.com/pancsta/asyncmachine-go/pkg/machine)
Expand All @@ -423,7 +430,7 @@ var States = am.Struct{

<details>

<summary>Example template for Foo and Bar</summary>
<summary>Check the example template for Foo and Bar</summary>

```go
package states
Expand Down Expand Up @@ -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

Expand All @@ -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.
Expand Down Expand Up @@ -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)
Expand All @@ -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)
Expand Down
Binary file modified assets/prometheus-grafana.light.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 2 additions & 4 deletions pkg/machine/machine_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}

Expand Down
4 changes: 2 additions & 2 deletions pkg/machine/misc.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
Expand Down
8 changes: 4 additions & 4 deletions pkg/machine/transition.go
Original file line number Diff line number Diff line change
Expand Up @@ -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).
Expand All @@ -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
Expand Down
27 changes: 16 additions & 11 deletions tools/debugger/states/ss_dbg.go
Original file line number Diff line number Diff line change
Expand Up @@ -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},
Expand All @@ -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},
Expand All @@ -43,16 +45,17 @@ 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,
},
LogUserScrolled: {},
Ready: {Require: S{Start}},

///// Actions
// /// Actions

Start: {},
TreeLogView: {
Expand All @@ -76,6 +79,7 @@ var States = am.Struct{
},

// tx / steps back / fwd

Fwd: {
Require: S{ClientSelected},
Remove: S{Playing},
Expand All @@ -95,7 +99,8 @@ var States = am.Struct{

ScrollToTx: {Require: S{ClientSelected}},

// client
// client selection

SelectingClient: {Remove: S{ClientSelected}},
ClientSelected: {
Remove: S{SelectingClient, LogUserScrolled},
Expand All @@ -121,7 +126,7 @@ var (
}
)

//#region boilerplate defs
// #region boilerplate defs

// Names of all the states (pkg enum).

Expand Down Expand Up @@ -176,7 +181,7 @@ const (
// Names is an ordered list of all the state names.
var Names = S{

///// Input events
// /// Input events

ClientMsg,
ConnectEvent,
Expand All @@ -188,7 +193,7 @@ var Names = S{
UserFwdStep,
UserBackStep,

///// External state (eg UI)
// /// External state (eg UI)

TreeFocused,
LogFocused,
Expand All @@ -203,7 +208,7 @@ var Names = S{
LogUserScrolled,
Ready,

///// Actions
// /// Actions

Start,
TreeLogView,
Expand All @@ -229,4 +234,4 @@ var Names = S{
am.Exception,
}

//#endregion
// #endregion

0 comments on commit a69ef67

Please sign in to comment.