asyncmachine-go

module
v0.10.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 25, 2025 License: MIT

README

asyncmachine-go

[!NOTE] State machines communicate through states (mutations, checking, and waiting).

asyncmachine-go is a declarative control flow library implementing AOP and Actor Model through a clock-based state machine. It offers atomic consensus, transparent RPC, TUI debugger, telemetry, REPL, workers, and soon diagrams.

Its main purpose is workflows (in-process / distributed / decentralized), although it can be used for a wide range of stateful applications - daemons, UIs, configs, bots, agents, firewalls, consensus algos, smart graphs, etc. asyncmachine can precisely (and transparently) target a specific point in a scenario and easily bring structure to event-based systems. It takes care of most contexts, select statements, and panics.

It aims at creating autonomous workflows with organic control flow and stateful APIs:

  • autonomous - automatic states, relations, context-based decisions
  • organic - relations, negotiation, cancellation
  • stateful - maintaing context, responsive, atomic

diagram

Stack

Top layers depend on the bottom ones.

. . . . . . PubSub . . . . . .
. . . . . Workers . . . . .
. . . . RPC . . . .
. . . Handlers . . .
. . 🦾 Machine API . .
. Relations .
States

Samples

Minimal - an untyped definition of 2 states and 1 relation, then 1 mutation and a check.

import am "github.com/pancsta/asyncmachine-go/pkg/machine"
// ...
mach := am.New(nil, am.Struct{
    "Foo": {Require: am.S{"Bar"}},
    "Bar": {},
}, nil)
mach.Add1("Foo", nil)
mach.Is1("Foo") // false

Complicated - wait on a multi state (event) and the Ready state with a 1s timeout, then mutate with typed args, on top of a state context.

// state ctx is an expiration ctx
ctx := client.Mach.NewStateCtx(ssC.WorkerReady)
// clock-based subscription
whenPayload := client.Mach.WhenTicks(ssC.WorkerPayload, 1, ctx)
// state mutation
client.WorkerRpc.Worker.Add1(ssW.WorkRequested, Pass(&A{
    Input: 2}))
// WaitFor* wraps select statements
err := amhelp.WaitForAll(ctx, time.Second,
    // post-mutation subscription
    mach2.When1(ss.BasicStatesDef.Ready, nil),
    // pre-mutation subscription
    whenPayload)
// check cancellation
if ctx.Err() != nil {
    return // state ctx expired
}
// check error
if err != nil {
    // err state mutation
    client.Mach.AddErr(err, nil)
    return // no err required
}
// client/WorkerPayload and mach2/Ready activated

Handlers - Aspect Oriented transition handlers.

// can Foo activate?
func (h *Handlers) FooEnter(e *am.Event) bool {
    return true
}
// with Foo active, can Bar activate?
func (h *Handlers) FooBar(e *am.Event) bool {
    return true
}
// Foo activates
func (h *Handlers) FooState(e *am.Event) {
    h.foo = NewConn()
}
// Foo de-activates
func (h *Handlers) FooEnd(e *am.Event) {
    h.foo.Close()
}

Schema - states of a node worker.

type WorkerStatesDef struct {
    ErrWork        string
    ErrWorkTimeout string
    ErrClient      string
    ErrSupervisor  string

    LocalRpcReady     string
    PublicRpcReady    string
    RpcReady          string
    SuperConnected    string
    ServeClient       string
    ClientConnected   string
    ClientSendPayload string
    SuperSendPayload  string

    Idle          string
    WorkRequested string
    Working       string
    WorkReady     string

    // inherit from rpc worker
    *ssrpc.WorkerStatesDef
}

All examples and benchmarks can be found in /examples.

Getting Started

🦾 /pkg/machine is the main package, while /pkg/node shows a high-level usage. Examples in /examples are good for a general grasp, while /docs/manual.md and /docs/diagrams.md go deeper into implementation details. /tools/cmd/am-gen can kick it off, while /examples/mach_template is the ultimate copy-pasta, and /tools/cmd/am-dbg records every detail. Reading tests is always a good idea...

Packages

This monorepo offers the following importable packages and runnable tools:

dashboard

Apps

Documentation

Community

Status

Under development, status depends on each package. The bottom layers seem prod grade, the top ones are alpha or testing.

Development

  • all PRs welcome
  • before
    • ./scripts/dep-taskfile.sh
    • task install-deps
  • after
    • task test
    • task format
    • task lint
TUI Debugger

FAQ

How does asyncmachine work?

It calls struct methods according to conventions and currently active states.

What is a "state" in asyncmachine?

State as in status / switch / flag, eg "process RUNNING" or "car BROKEN".

What does "clock-based" mean?

Each state has a counter of activations & de-activations, and all state counters create "machine time".

What's the difference between states and events?

Same event happening many times will cause only 1 state activation, until the state becomes inactive.

Changes

Directories

Path Synopsis
examples
mach_template/states
Package states contains a stateful schema-v2 for MachTemplate.
Package states contains a stateful schema-v2 for MachTemplate.
internal
testing/cmd/am-dbg-worker
AM_DBG_WORKER_ADDR AM_DBG_ADDR
AM_DBG_WORKER_ADDR AM_DBG_ADDR
pkg
helpers
Package helpers is a set of useful functions when working with async state machines.
Package helpers is a set of useful functions when working with async state machines.
helpers/testing
Package testing provides testing helpers for state machines using testify.
Package testing provides testing helpers for state machines using testify.
history
Package history provides mutation history tracking and traversal.
Package history provides mutation history tracking and traversal.
machine
Package machine is a nondeterministic, multi-state, clock-based, relational, optionally-accepting, and non-blocking state machine.
Package machine is a nondeterministic, multi-state, clock-based, relational, optionally-accepting, and non-blocking state machine.
node
Package node provides distributed worker pools with supervisors.
Package node provides distributed worker pools with supervisors.
pubsub/states
Package states contains a stateful schema-v2 for Topic.
Package states contains a stateful schema-v2 for Topic.
rpc
Package rpc is a transparent RPC for state machines.
Package rpc is a transparent RPC for state machines.
states
Package states provides reusable state definitions.
Package states provides reusable state definitions.
states/pipes
Package pipe provide helpers to pipe states from one machine to another.
Package pipe provide helpers to pipe states from one machine to another.
telemetry
Package telemetry provides telemetry exporters for asyncmachine: am-dbg, Prometheus, and OpenTelemetry.
Package telemetry provides telemetry exporters for asyncmachine: am-dbg, Prometheus, and OpenTelemetry.
telemetry/prometheus
Package prometheus provides Prometheus metrics for asyncmachine.
Package prometheus provides Prometheus metrics for asyncmachine.
x/helpers
Package helpers provides some utility functions for asyncmachine, which are out of scope of the main package.
Package helpers provides some utility functions for asyncmachine, which are out of scope of the main package.
scripts
tools
cmd/am-dbg
am-dbg is a lightweight, multi-client debugger for asyncmachine-go.
am-dbg is a lightweight, multi-client debugger for asyncmachine-go.
cmd/am-dbg-ssh
am-dbg-ssh is an SSH version of asyncmachine-go debugger.
am-dbg-ssh is an SSH version of asyncmachine-go debugger.
cmd/am-gen
am-gen generates states files and Grafana dashboards.
am-gen generates states files and Grafana dashboards.
debugger
Package debugger provides a TUI debugger with multi-client support.
Package debugger provides a TUI debugger with multi-client support.
repl
Package repl provides a REPL and CLI functionality for aRPC connections.
Package repl provides a REPL and CLI functionality for aRPC connections.
repl/states
Package states contains a stateful schema-v2 for Repl.
Package states contains a stateful schema-v2 for Repl.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL