Documentation
¶
Overview ¶
Package machine is a nondeterministic, multi-state, clock-based, relational, optionally-accepting, and non-blocking state machine.
Index ¶
- Constants
- Variables
- func AMerge[K comparable, V any](maps ...map[K]V) map[K]V
- func IsActiveTick(tick uint64) bool
- func IsHandler(states S, method string) (string, string)
- func IsTimeAfter(time1, time2 Time) bool
- func ListHandlers(handlers any, states S) ([]string, error)
- func MockClock(mach *Machine, clock Clock)
- func NewArgsMapper(names []string, maxLen int) func(args A) map[string]string
- func NewStateGroups[G any](groups G, mixins ...any) G
- func NewStates[G States](states G) G
- func StatesEqual(states1 S, states2 S) bool
- func StatesToIndex(index S, states S) []int
- func TruncateStr(s string, maxLength int) string
- type A
- type AT
- type Api
- type Clock
- type CtxBinding
- type CtxKeyName
- type CtxValue
- type DefaultRelationsResolver
- func (rr *DefaultRelationsResolver) InboundRelationsOf(toState string) (S, error)
- func (rr *DefaultRelationsResolver) NewAutoMutation() (*Mutation, S)
- func (rr *DefaultRelationsResolver) NewSchema(schema Schema, states S)
- func (rr *DefaultRelationsResolver) RelationsBetween(fromState, toState string) ([]Relation, error)
- func (rr *DefaultRelationsResolver) RelationsOf(fromState string) ([]Relation, error)
- func (rr *DefaultRelationsResolver) SortStates(states S)
- func (rr *DefaultRelationsResolver) TargetStates(t *Transition, statesToSet, index S) S
- type Event
- type ExceptionArgsPanic
- type ExceptionHandler
- type HandlerDispose
- type HandlerFinal
- type HandlerNegotiation
- type IndexStateCtx
- type IndexWhen
- type IndexWhenArgs
- type IndexWhenTime
- type LastTxTracer
- type LogArgsMapper
- type LogEntry
- type LogLevel
- type Logger
- type Machine
- func (m *Machine) ActiveStates() S
- func (m *Machine) Add(states S, args A) Result
- func (m *Machine) Add1(state string, args A) Result
- func (m *Machine) AddBreakpoint(added S, removed S)
- func (m *Machine) AddErr(err error, args A) Result
- func (m *Machine) AddErrState(state string, err error, args A) Result
- func (m *Machine) Any(states ...S) bool
- func (m *Machine) Any1(states ...string) bool
- func (m *Machine) BindHandlers(handlers any) error
- func (m *Machine) BindTracer(tracer Tracer) error
- func (m *Machine) Clock(states S) Clock
- func (m *Machine) CountActive(states S) int
- func (m *Machine) Ctx() context.Context
- func (m *Machine) DetachHandlers(handlers any) error
- func (m *Machine) DetachTracer(tracer Tracer) error
- func (m *Machine) Dispose()
- func (m *Machine) DisposeForce()
- func (m *Machine) Err() error
- func (m *Machine) EvAdd(event *Event, states S, args A) Result
- func (m *Machine) EvAdd1(event *Event, state string, args A) Result
- func (m *Machine) EvAddErr(event *Event, err error, args A) Result
- func (m *Machine) EvAddErrState(event *Event, state string, err error, args A) Result
- func (m *Machine) EvRemove(event *Event, states S, args A) Result
- func (m *Machine) EvRemove1(event *Event, state string, args A) Result
- func (m *Machine) Eval(source string, fn func(), ctx context.Context) bool
- func (m *Machine) Export() *Serialized
- func (m *Machine) GetLogArgs() LogArgsMapper
- func (m *Machine) GetLogId() bool
- func (m *Machine) HandleDispose(fn HandlerDispose)
- func (m *Machine) Has(states S) bool
- func (m *Machine) Has1(state string) bool
- func (m *Machine) HasHandlers() bool
- func (m *Machine) Id() string
- func (m *Machine) Import(data *Serialized) error
- func (m *Machine) Index(states S) []int
- func (m *Machine) Index1(state string) int
- func (m *Machine) Inspect(states S) string
- func (m *Machine) InternalLog(lvl LogLevel, msg string, args ...any)
- func (m *Machine) Is(states S) bool
- func (m *Machine) Is1(state string) bool
- func (m *Machine) IsClock(clock Clock) bool
- func (m *Machine) IsDisposed() bool
- func (m *Machine) IsErr() bool
- func (m *Machine) IsQueued(mutationType MutationType, states S, withoutArgsOnly bool, ...) int
- func (m *Machine) IsTime(t Time, states S) bool
- func (m *Machine) Log(msg string, args ...any)
- func (m *Machine) LogLevel() LogLevel
- func (m *Machine) Logger() Logger
- func (m *Machine) MustBindHandlers(handlers any)
- func (m *Machine) MustParseStates(states S) S
- func (m *Machine) NewStateCtx(state string) context.Context
- func (m *Machine) Not(states S) bool
- func (m *Machine) Not1(state string) bool
- func (m *Machine) PanicToErr(args A)
- func (m *Machine) PanicToErrState(state string, args A)
- func (m *Machine) ParentId() string
- func (m *Machine) Queue() []*Mutation
- func (m *Machine) Remove(states S, args A) Result
- func (m *Machine) Remove1(state string, args A) Result
- func (m *Machine) Resolver() RelationsResolver
- func (m *Machine) Schema() Schema
- func (m *Machine) SchemaVer() int
- func (m *Machine) Set(states S, args A) Result
- func (m *Machine) SetLogArgs(mapper LogArgsMapper)
- func (m *Machine) SetLogId(val bool)
- func (m *Machine) SetLogLevel(level LogLevel)
- func (m *Machine) SetLogger(fn Logger)
- func (m *Machine) SetLoggerEmpty(level LogLevel)
- func (m *Machine) SetLoggerSimple(logf func(format string, args ...any), level LogLevel)
- func (m *Machine) SetSchema(newSchema Schema, names S) error
- func (m *Machine) SetTags(tags []string)
- func (m *Machine) StateNames() S
- func (m *Machine) StateNamesMatch(re *regexp.Regexp) S
- func (m *Machine) StatesVerified() bool
- func (m *Machine) String() string
- func (m *Machine) StringAll() string
- func (m *Machine) Switch(groups ...S) string
- func (m *Machine) Tags() []string
- func (m *Machine) Tick(state string) uint64
- func (m *Machine) Time(states S) Time
- func (m *Machine) TimeSum(states S) uint64
- func (m *Machine) Toggle(states S, args A) Result
- func (m *Machine) Toggle1(state string, args A) Result
- func (m *Machine) Tracers() []Tracer
- func (m *Machine) Transition() *Transition
- func (m *Machine) VerifyStates(states S) error
- func (m *Machine) WasClock(clock Clock) bool
- func (m *Machine) WasTime(t Time, states S) bool
- func (m *Machine) When(states S, ctx context.Context) <-chan struct{}
- func (m *Machine) When1(state string, ctx context.Context) <-chan struct{}
- func (m *Machine) WhenArgs(state string, args A, ctx context.Context) <-chan struct{}
- func (m *Machine) WhenDisposed() <-chan struct{}
- func (m *Machine) WhenErr(disposeCtx context.Context) <-chan struct{}
- func (m *Machine) WhenNot(states S, ctx context.Context) <-chan struct{}
- func (m *Machine) WhenNot1(state string, ctx context.Context) <-chan struct{}
- func (m *Machine) WhenQueueEnds(ctx context.Context) <-chan struct{}
- func (m *Machine) WhenTicks(state string, ticks int, ctx context.Context) <-chan struct{}
- func (m *Machine) WhenTime(states S, times Time, ctx context.Context) <-chan struct{}
- func (m *Machine) WhenTime1(state string, ticks uint64, ctx context.Context) <-chan struct{}
- func (m *Machine) WillBe(states S) bool
- func (m *Machine) WillBe1(state string) bool
- func (m *Machine) WillBeRemoved(states S) bool
- func (m *Machine) WillBeRemoved1(state string) bool
- type MutSource
- type Mutation
- type MutationType
- type NoOpTracer
- func (t *NoOpTracer) HandlerEnd(transition *Transition, emitter string, handler string)
- func (t *NoOpTracer) HandlerStart(transition *Transition, emitter string, handler string)
- func (t *NoOpTracer) Inheritable() bool
- func (t *NoOpTracer) MachineDispose(machID string)
- func (t *NoOpTracer) MachineInit(machine Api) context.Context
- func (t *NoOpTracer) NewSubmachine(parent, machine Api)
- func (t *NoOpTracer) QueueEnd(machine Api)
- func (t *NoOpTracer) SchemaChange(machine Api, old Schema)
- func (t *NoOpTracer) TransitionEnd(transition *Transition)
- func (t *NoOpTracer) TransitionInit(transition *Transition)
- func (t *NoOpTracer) TransitionStart(transition *Transition)
- func (t *NoOpTracer) VerifyStates(machine Api)
- type Opts
- type Relation
- type RelationsResolver
- type Result
- type S
- type Schema
- type Serialized
- type State
- type StateIsActive
- type States
- type StatesBase
- type Step
- type StepType
- type Time
- func (t Time) ActiveIndex() []int
- func (t Time) ActiveStates(index S) S
- func (t Time) Add(t2 Time) Time
- func (t Time) Any1(idxs ...int) bool
- func (t Time) DiffSince(before Time) Time
- func (t Time) Get(idx int) uint64
- func (t Time) Is(idxs []int) bool
- func (t Time) Is1(idx int) bool
- func (t Time) Not(idxs []int) bool
- func (t Time) Not1(idx int) bool
- func (t Time) String() string
- func (t Time) Sum() uint64
- func (t Time) TimeSum(idxs []int) uint64
- type TimeIndex
- func (t TimeIndex) ActiveStates() S
- func (t TimeIndex) Any1(states ...string) bool
- func (t TimeIndex) Is(states S) bool
- func (t TimeIndex) Is1(state string) bool
- func (t TimeIndex) Not(states S) bool
- func (t TimeIndex) Not1(state string) bool
- func (t TimeIndex) StateName(idx int) string
- func (t TimeIndex) String() string
- func (t TimeIndex) TimeSum(states S) uint64
- type Tracer
- type Transition
- func (t *Transition) Args() A
- func (t *Transition) CalledStates() S
- func (t *Transition) ClockAfter() Clock
- func (t *Transition) ClockBefore() Clock
- func (t *Transition) IsAuto() bool
- func (t *Transition) LogArgs() string
- func (t *Transition) StatesBefore() S
- func (t *Transition) String() string
- func (t *Transition) TargetStates() S
- func (t *Transition) Type() MutationType
- type WhenArgsBinding
- type WhenBinding
- type WhenTimeBinding
Examples ¶
Constants ¶
const ( // EnvAmDebug enables a simple debugging mode (eg long timeouts). // "2" logs to stdout (where applicable) // "1" | "2" | "" (default) EnvAmDebug = "AM_DEBUG" // EnvAmLog sets the log level. // "1" | "2" | "3" | "4" | "" (default) EnvAmLog = "AM_LOG" // EnvAmLogFile enables file logging (using machine ID as the name). // "1" | "" (default) EnvAmLogFile = "AM_LOG_FILE" // EnvAmDetectEval detects evals directly in handlers (use in tests). EnvAmDetectEval = "AM_DETECT_EVAL" // EnvAmTraceFilter will remove its contents from stack traces, shortening // them . EnvAmTraceFilter = "AM_TRACE_FILTER" // EnvAmTestDebug activates debugging in tests. EnvAmTestDebug = "AM_TEST_DEBUG" // HandlerGlobal is the name of a global transition handler. HandlerGlobal = "AnyEnter" // Any is a name of a meta-state used in catch-all handlers. Any = "Any" SuffixEnter = "Enter" SuffixExit = "Exit" SuffixState = "State" SuffixEnd = "End" PrefixErr = "Err" )
const (
// Exception is the name of the Exception state.
Exception = "Exception"
)
Variables ¶
var ( // ErrStateUnknown indicates that the state is unknown. ErrStateUnknown = errors.New("state unknown") // ErrStateInactive indicates that a necessary state isn't active. ErrStateInactive = errors.New("state not active") // ErrCanceled indicates that a transition was canceled. ErrCanceled = errors.New("transition canceled") // ErrQueued indicates that a transition was queued. ErrQueued = errors.New("transition queued") // ErrInvalidArgs indicates that arguments are invalid. ErrInvalidArgs = errors.New("invalid arguments") // ErrHandlerTimeout indicates that a mutation timed out. ErrHandlerTimeout = errors.New("handler timeout") // ErrEvalTimeout indicates that an eval func timed out. ErrEvalTimeout = errors.New("eval timeout") // ErrTimeout indicates that a generic timeout occurred. ErrTimeout = errors.New("timeout") // ErrStateMissing indicates that states are missing. ErrStateMissing = errors.New("missing states") // ErrRelation indicates that a relation definition is invalid. ErrRelation = errors.New("relation error") // ErrDisposed indicates that the machine has been disposed. ErrDisposed = errors.New("machine disposed") // ErrSchema indicates an issue with the machine schema. ErrSchema = errors.New("schema error") )
var CtxKey = &CtxKeyName{}
var LogArgs = []string{"name", "id", "port", "addr", "err"}
LogArgs is a list of common argument names to be logged. Useful for debugging.
var LogArgsMaxLen = 20
LogArgsMaxLen is the default maximum length of the arg's string representation.
Functions ¶
func AMerge ¶ added in v0.9.0
func AMerge[K comparable, V any](maps ...map[K]V) map[K]V
AMerge merges 2 or more maps into 1. Useful for passing args from many packages.
func IsActiveTick ¶ added in v0.5.0
IsActiveTick returns true if the tick represents an active state (odd number).
func IsHandler ¶ added in v0.8.0
IsHandler checks if a method name is a handler method, by returning a state name.
func IsTimeAfter ¶
IsTimeAfter checks if time1 is after time2. Requires a deterministic states order, e.g. by using Machine.VerifyStates.
func ListHandlers ¶ added in v0.8.0
ListHandlers returns a list of handler method names from a handlers struct.
func MockClock ¶ added in v0.7.0
MockClock mocks the internal clock of the machine. Only for testing.
func NewArgsMapper ¶ added in v0.5.0
NewArgsMapper returns a matcher function for LogArgs. Useful for debugging untyped argument maps.
maxLen: maximum length of the arg's string representation). Default to LogArgsMaxLen,
func NewStateGroups ¶ added in v0.8.0
func StatesEqual ¶ added in v0.8.0
func StatesToIndex ¶ added in v0.12.0
StatesToIndex returns a subset of [index] that matches [states]. Unknown states are represented by -1.
func TruncateStr ¶ added in v0.12.0
TruncateStr with shorten the string and leave a tripedot suffix.
Types ¶
type A ¶
A (arguments) is a map of named arguments for a Mutation.
type AT ¶ added in v0.8.0
type AT struct {
Err error
ErrTrace string
Panic *ExceptionArgsPanic
TargetStates S
CalledStates S
TimeBefore Time
TimeAfter Time
Event *Event
}
AT represents typed arguments of pkg/machine, extracted from Event.Args via ParseArgs, or created manually to for Pass.
type Api ¶ added in v0.8.0
type Api interface {
Add1(state string, args A) Result
Add(states S, args A) Result
Remove1(state string, args A) Result
Remove(states S, args A) Result
Set(states S, args A) Result
AddErr(err error, args A) Result
AddErrState(state string, err error, args A) Result
EvAdd1(event *Event, state string, args A) Result
EvAdd(event *Event, states S, args A) Result
EvRemove1(event *Event, state string, args A) Result
EvRemove(event *Event, states S, args A) Result
EvAddErr(event *Event, err error, args A) Result
EvAddErrState(event *Event, state string, err error, args A) Result
WhenArgs(state string, args A, ctx context.Context) <-chan struct{}
Err() error
IsErr() bool
Is(states S) bool
Is1(state string) bool
Any(states ...S) bool
Any1(state ...string) bool
Not(states S) bool
Not1(state string) bool
IsTime(time Time, states S) bool
WasTime(time Time, states S) bool
IsClock(clock Clock) bool
WasClock(clock Clock) bool
Has(states S) bool
Has1(state string) bool
When(states S, ctx context.Context) <-chan struct{}
When1(state string, ctx context.Context) <-chan struct{}
WhenNot(states S, ctx context.Context) <-chan struct{}
WhenNot1(state string, ctx context.Context) <-chan struct{}
WhenTime(
states S, times Time, ctx context.Context) <-chan struct{}
WhenTime1(state string, tick uint64, ctx context.Context) <-chan struct{}
WhenTicks(state string, ticks int, ctx context.Context) <-chan struct{}
WhenErr(ctx context.Context) <-chan struct{}
StateNames() S
StateNamesMatch(re *regexp.Regexp) S
ActiveStates() S
Tick(state string) uint64
Clock(states S) Clock
Time(states S) Time
TimeSum(states S) uint64
NewStateCtx(state string) context.Context
Export() *Serialized
Schema() Schema
Switch(groups ...S) string
Log(msg string, args ...any)
Id() string
ParentId() string
Tags() []string
SetLogId(val bool)
GetLogId() bool
SetLogger(logger Logger)
SetLogLevel(lvl LogLevel)
SetLoggerEmpty(lvl LogLevel)
SetLoggerSimple(logf func(format string, args ...any), level LogLevel)
Ctx() context.Context
String() string
StringAll() string
Inspect(states S) string
Index(states S) []int
Index1(state string) int
BindHandlers(handlers any) error
DetachHandlers(handlers any) error
HasHandlers() bool
StatesVerified() bool
Tracers() []Tracer
DetachTracer(tracer Tracer) error
BindTracer(tracer Tracer) error
AddBreakpoint(added S, removed S)
Dispose()
WhenDisposed() <-chan struct{}
IsDisposed() bool
}
Api is a subset of Machine for alternative implementations. TODO copy docs from Machine.
type Clock ¶ added in v0.7.0
Clock is a map of state names to their tick values. It's like Time but indexed by string, instead of int.
type CtxBinding ¶ added in v0.8.0
type CtxBinding struct {
Ctx context.Context
Cancel context.CancelFunc
}
type CtxKeyName ¶ added in v0.8.0
type CtxKeyName struct{}
type DefaultRelationsResolver ¶
type DefaultRelationsResolver struct {
Machine *Machine
Transition *Transition
Index S
// contains filtered or unexported fields
}
DefaultRelationsResolver is the default implementation of the RelationsResolver with Add, Remove, Require and After. It can be overridden using Opts.Resolver.
func (*DefaultRelationsResolver) InboundRelationsOf ¶ added in v0.12.0
func (rr *DefaultRelationsResolver) InboundRelationsOf(toState string) ( S, error, )
InboundRelationsOf returns a list of states pointing to [toState]. Not thread safe.
func (*DefaultRelationsResolver) NewAutoMutation ¶ added in v0.12.0
func (rr *DefaultRelationsResolver) NewAutoMutation() (*Mutation, S)
GetAutoMutation implements RelationsResolver.GetAutoMutation.
func (*DefaultRelationsResolver) NewSchema ¶ added in v0.12.0
func (rr *DefaultRelationsResolver) NewSchema(schema Schema, states S)
func (*DefaultRelationsResolver) RelationsBetween ¶ added in v0.12.0
func (rr *DefaultRelationsResolver) RelationsBetween( fromState, toState string, ) ([]Relation, error)
GetRelationsBetween returns a list of outbound relations between fromState -> toState. Not thread safe.
func (*DefaultRelationsResolver) RelationsOf ¶ added in v0.12.0
func (rr *DefaultRelationsResolver) RelationsOf(fromState string) ( []Relation, error, )
GetRelationsOf returns a list of relation types of the given state. Not thread safe.
func (*DefaultRelationsResolver) SortStates ¶
func (rr *DefaultRelationsResolver) SortStates(states S)
SortStates implements RelationsResolver.SortStates.
func (*DefaultRelationsResolver) TargetStates ¶ added in v0.12.0
func (rr *DefaultRelationsResolver) TargetStates( t *Transition, statesToSet, index S, ) S
GetTargetStates implements RelationsResolver.GetTargetStates.
type Event ¶
type Event struct {
// Name of the event / handler
Name string
// MachineId is the ID of the parent machine.
MachineId string
// TransitionId is the ID of the parent transition.
TransitionId string
// Args is a map of named arguments for a Mutation.
Args A
// IsCheck is true if this event is a check event, fired by one of Can*()
// methods. Useful for avoiding flooding the log with errors.
IsCheck bool
// contains filtered or unexported fields
}
Event struct represents a single event of a Mutation within a Transition. One event can have 0-n handlers.
func (*Event) AcceptTimeout ¶ added in v0.10.1
AcceptTimeout is like IsValid, but requires the handler to stop executing after receiving [true].
func (*Event) Clone ¶ added in v0.9.0
Clone clones only the essential data of the Event. Useful for tracing vs GC.
func (*Event) IsValid ¶ added in v0.10.1
IsValid confirm this event should still be processed. Useful for negotiation handlers, which can't use state context.
func (*Event) Transition ¶ added in v0.5.0
func (e *Event) Transition() *Transition
Transition returns the Transition of an Event.
type ExceptionArgsPanic ¶
type ExceptionArgsPanic struct {
CalledStates S
StatesBefore S
Transition *Transition
LastStep *Step
StackTrace string
}
ExceptionArgsPanic is an optional argument ["panic"] for the Exception state which describes a panic within a Transition handler.
type ExceptionHandler ¶
type ExceptionHandler struct{}
ExceptionHandler provide a basic Exception state support, as should be embedded into handler structs in most of the cases.
func (*ExceptionHandler) ExceptionState ¶
func (eh *ExceptionHandler) ExceptionState(e *Event)
ExceptionState is a final entry handler for the Exception state. Args: - err error: The error that caused the Exception state. - panic *ExceptionArgsPanic: Optional details about the panic.
type HandlerDispose ¶ added in v0.9.0
HandlerDispose is a machine disposal handler func signature.
type HandlerFinal ¶ added in v0.8.0
type HandlerFinal func(e *Event)
HandlerFinal is a final transition handler func signature.
type HandlerNegotiation ¶ added in v0.8.0
HandlerNegotiation is a negotiation transition handler func signature.
type IndexStateCtx ¶ added in v0.7.0
type IndexStateCtx map[string]*CtxBinding
IndexStateCtx is a map of (single) state names to a context cancel function
type IndexWhen ¶ added in v0.7.0
type IndexWhen map[string][]*WhenBinding
IndexWhen is a map of (single) state names to a list of activation or de-activation bindings
type IndexWhenArgs ¶ added in v0.7.0
type IndexWhenArgs map[string][]*WhenArgsBinding
IndexWhenArgs is a map of (single) state names to a list of args value bindings
type IndexWhenTime ¶ added in v0.7.0
type IndexWhenTime map[string][]*WhenTimeBinding
IndexWhenTime is a map of (single) state names to a list of time bindings
type LastTxTracer ¶ added in v0.12.0
type LastTxTracer struct {
*NoOpTracer
// contains filtered or unexported fields
}
TODO add TTL, ctx
func NewLastTxTracer ¶ added in v0.12.0
func NewLastTxTracer() *LastTxTracer
NewLastTxTracer returns a Tracer that logs the last transition.
func (*LastTxTracer) Load ¶ added in v0.12.0
func (t *LastTxTracer) Load() *Transition
Load returns the last transition.
func (*LastTxTracer) String ¶ added in v0.12.0
func (t *LastTxTracer) String() string
func (*LastTxTracer) TransitionEnd ¶ added in v0.12.0
func (t *LastTxTracer) TransitionEnd(transition *Transition)
type LogArgsMapper ¶ added in v0.8.0
LogArgsMapper is a function that maps arguments to be logged. Useful for debugging.
type LogLevel ¶
type LogLevel int
LogLevel enum
const ( // LogNothing means no logging, including external msgs. LogNothing LogLevel = iota // LogChanges means logging state changes and external msgs. LogChanges // LogOps means LogChanges + logging all the operations. LogOps // LogDecisions means LogOps + logging all the decisions behind them. LogDecisions // LogEverything means LogDecisions + all event and handler names, and more. LogEverything )
TODO add LogOpsSubs (30), spread log level 0 - 10 - 20 - 30 - 40
func EnvLogLevel ¶ added in v0.7.0
EnvLogLevel returns a log level from an environment variable, AM_LOG by default.
type Machine ¶
type Machine struct {
// Maximum number of mutations that can be queued. Default: 1000.
QueueLimit int
// HandlerTimeout defined the time for a handler to execute before it causes
// an Exception. Default: 1s. See also Opts.HandlerTimeout.
// Using HandlerTimeout can cause race conditions, see Event.IsValid().
HandlerTimeout time.Duration
// EvalTimeout is the time the machine will try to execute an eval func.
// Like any other handler, eval func also has HandlerTimeout. Default: 1s.
EvalTimeout time.Duration
// If true, the machine will print all exceptions to stdout. Default: true.
// Requires an ExceptionHandler binding and Machine.PanicToException set.
LogStackTrace bool
// If true, the machine will catch panic and trigger the Exception state.
// Default: true.
PanicToException bool
// DisposeTimeout specifies the duration to wait for the queue to drain during
// disposal. Default 1s.
DisposeTimeout time.Duration
// contains filtered or unexported fields
}
Machine provides a state machine API with mutations, state schema, handlers, subscriptions, tracers, and helpers methods. It also holds a queue of mutations to execute.
func New ¶
New creates a new Machine instance, bound to context and modified with optional Opts.
Example ¶
ctx := context.TODO()
mach := New(ctx, Schema{
"Foo": {Require: S{"Bar"}},
"Bar": {},
}, nil)
mach.Add1("Foo", nil)
mach.Is1("Foo") // false
func NewCommon ¶ added in v0.5.0
func NewCommon( ctx context.Context, id string, stateSchema Schema, stateNames S, handlers any, parent Api, opts *Opts, ) (*Machine, error)
NewCommon creates a new Machine instance with all the common options set.
Example ¶
// define (tip: use am-gen instead)
stateStruct := Schema{
"Foo": {Require: S{"Bar"}},
"Bar": {},
}
stateNames := []string{"Foo", "Bar"}
type Handlers struct{}
// func (h *Handlers) FooState(e *Event) {
// args := e.Args
// mach := e.Machine()
// ctx := mach.NewStateCtx("Foo")
// // unblock
// go func() {
// if ctx.Err() != nil {
// return // expired
// }
// // blocking calls...
// if ctx.Err() != nil {
// return // expired
// }
// mach.Add1("Bar", nil)
// }()
// }
// init
ctx := context.TODO()
mach, err := NewCommon(ctx, "mach-id",
stateStruct, stateNames,
&Handlers{}, nil, nil)
if err != nil {
panic(err)
}
mach.SetLogLevel(LogOps)
// debug
// import amhelp "github.com/pancsta/asyncmachine-go/pkg/helpers"
// amhelp.EnableDebugging(false)
// amhelp.MachDebugEnv(mach)
func (*Machine) ActiveStates ¶
ActiveStates returns a copy of the currently active states.
func (*Machine) Add ¶
Add activates a list of states in the machine, returning the result of the transition (Executed, Queued, Canceled). Like every mutation method, it will resolve relations and trigger handlers.
func (*Machine) Add1 ¶ added in v0.5.0
Add1 is a shorthand method to add a single state with the passed args.
func (*Machine) AddBreakpoint ¶ added in v0.8.0
AddBreakpoint adds a breakpoint for an outcome of mutation (added and removed states). Once such mutation happens, a log message will be printed out. You can set an IDE's breakpoint on this line and see the mutation's sync stack trace. When Machine.LogStackTrace is set, the stack trace will be printed out as well. Many breakpoints can be added, but none removed.
func (*Machine) AddErr ¶
AddErr is a dedicated method to add the Exception state with the passed error and optional arguments. Like every mutation method, it will resolve relations and trigger handlers. AddErr produces a stack trace of the error, if LogStackTrace is enabled.
func (*Machine) AddErrState ¶ added in v0.7.0
AddErrState adds a dedicated error state, along with the build in Exception state. Like every mutation method, it will resolve relations and trigger handlers. AddErrState produces a stack trace of the error, if LogStackTrace is enabled.
func (*Machine) Any ¶
Any a is group call to Is, returns true if any of the params return true from Is.
machine.StringAll() // ()[Foo:0 Bar:0 Baz:0]
machine.Add(S{"Foo"})
// is(Foo, Bar) or is(Bar)
machine.Any(S{"Foo", "Bar"}, S{"Bar"}) // false
// is(Foo) or is(Bar)
machine.Any(S{"Foo"}, S{"Bar"}) // true
func (*Machine) Any1 ¶ added in v0.5.0
Any1 is group call to Is1(), returns true if any of the params return true from Is1().
func (*Machine) BindHandlers ¶
BindHandlers binds a struct of handler methods to machine's states, based on the naming convention, eg `FooState(e *Event)`. Negotiation handlers can optionally return bool.
func (*Machine) BindTracer ¶ added in v0.8.0
BindTracer binds a Tracer to the machine. Tracers can cause Exception in submachines, before any handlers are bound. Use the Err() getter to examine such errors.
func (*Machine) Clock ¶
Clock returns current machine's clock, a state-keyed map of ticks. If states are passed, only the ticks of the passed states are returned.
func (*Machine) CountActive ¶ added in v0.8.0
CountActive returns the amount of active states from a passed list. Useful for state groups.
func (*Machine) DetachHandlers ¶ added in v0.8.0
DetachHandlers detaches previously bound machine handlers.
func (*Machine) DetachTracer ¶ added in v0.8.0
DetachTracer tries to remove a tracer from the machine. Returns an error in case the tracer wasn't bound.
func (*Machine) Dispose ¶
func (m *Machine) Dispose()
Dispose disposes the machine and all its emitters. You can wait for the completion of the disposal with `<-mach.WhenDisposed`.
func (*Machine) DisposeForce ¶ added in v0.5.0
func (m *Machine) DisposeForce()
DisposeForce disposes the machine and all its emitters, without waiting for the queue to drain. Will cause panics.
func (*Machine) EvAdd ¶ added in v0.9.0
EvAdd is like Add, but passed the source event as the 1st param, which results in traceable transitions.
func (*Machine) EvAdd1 ¶ added in v0.9.0
EvAdd1 is like Add1 but passed the source event as the 1st param, which results in traceable transitions.
func (*Machine) EvAddErr ¶ added in v0.9.0
EvAddErr is like AddErr, but passed the source event as the 1st param, which results in traceable transitions.
func (*Machine) EvAddErrState ¶ added in v0.9.0
EvAddErrState is like AddErrState, but passed the source event as the 1st param, which results in traceable transitions.
func (*Machine) EvRemove ¶ added in v0.9.0
EvRemove is like Remove but passed the source event as the 1st param, which results in traceable transitions.
func (*Machine) EvRemove1 ¶ added in v0.9.0
EvRemove1 is like Remove1, but passed the source event as the 1st param, which results in traceable transitions.
func (*Machine) Eval ¶ added in v0.5.0
Eval executes a function on the machine's queue, allowing to avoid using locks for non-handler code. Blocking code should NOT be scheduled here. Eval cannot be called within a handler's critical section, as both are using the same serial queue and will deadlock. Eval has a timeout of HandlerTimeout/2 and will return false in case it happens.
ctx: nil context defaults to machine's context.
Note: usage of Eval is discouraged. But if you have to, use AM_DETECT_EVAL in tests for deadlock detection. Most usages of eval can be replaced with atomics or returning from mutation via channels.
func (*Machine) Export ¶ added in v0.6.4
func (m *Machine) Export() *Serialized
Export exports the machine state as Serialized: ID, machine time, and state names.
func (*Machine) GetLogArgs ¶ added in v0.5.0
func (m *Machine) GetLogArgs() LogArgsMapper
GetLogArgs returns the current log args function.
func (*Machine) GetLogId ¶ added in v0.8.0
GetLogId returns the current state of the log ID setting.
func (*Machine) HandleDispose ¶ added in v0.9.0
func (m *Machine) HandleDispose(fn HandlerDispose)
HandleDispose adds a function to be called after the machine gets disposed. These functions will run synchronously just before WhenDisposed() channel gets closed. Considering it's a low-level feature, its advaised to handle disposal via dedicated states.
func (*Machine) Has ¶
Has return true is passed states are registered in the machine. Useful for checking if a machine implements a specific state set.
func (*Machine) Has1 ¶ added in v0.5.0
Has1 is a shorthand for Has. It returns true if the passed state is registered in the machine.
func (*Machine) HasHandlers ¶ added in v0.12.0
HasHandlers returns true if this machine has bound handlers, and thus an allocated goroutine. It also makes it nondeterministic.
func (*Machine) Import ¶ added in v0.6.4
func (m *Machine) Import(data *Serialized) error
Import imports the machine state from Serialized. It's not safe to import into a machine which has already produces transitions and/or has telemetry connected.
func (*Machine) Index ¶ added in v0.7.0
Index returns a list of state indexes in the machine's StateNames() list, with -1s for missing ones.
func (*Machine) Index1 ¶ added in v0.12.0
Index1 returns the index of a state in the machine's StateNames() list, or -1 when not found or machine has been disposed.
func (*Machine) Inspect ¶
Inspect returns a multi-line string representation of the machine (states, relations, clocks). states: param for ordered or partial results.
func (*Machine) InternalLog ¶ added in v0.12.0
InternalLog adds an internal log entry from the outside. It should be used only by packages extending pkg/machine. Use Log instead.
func (*Machine) Is ¶
Is checks if all the passed states are currently active.
machine.StringAll() // ()[Foo:0 Bar:0 Baz:0]
machine.Add(S{"Foo"})
machine.Is(S{"Foo"}) // true
machine.Is(S{"Foo", "Bar"}) // false
func (*Machine) Is1 ¶ added in v0.5.0
Is1 is a shorthand method to check if a single state is currently active. See Is().
func (*Machine) IsClock ¶
IsClock checks if the machine has changed since the passed clock. Returns true if at least one state has changed.
func (*Machine) IsDisposed ¶ added in v0.8.0
IsDisposed returns true if the machine has been disposed.
func (*Machine) IsQueued ¶
func (m *Machine) IsQueued(mutationType MutationType, states S, withoutArgsOnly bool, statesStrictEqual bool, startIndex int, ) int
IsQueued checks if a particular mutation has been queued. Returns an index of the match or -1 if not found.
mutationType: add, remove, set
states: list of states used in the mutation
withoutParamsOnly: matches only mutation without the arguments object
statesStrictEqual: states of the mutation have to be exactly like `states` and not a superset.
func (*Machine) IsTime ¶ added in v0.7.0
IsTime checks if the machine has changed since the passed time (list of ticks). Returns true if at least one state has changed. The states param is optional and can be used to check only a subset of states.
func (*Machine) Log ¶
Log logs an [extern] message unless LogNothing is set (default). Optionally redirects to a custom logger from SetLogger.
func (*Machine) Logger ¶ added in v0.12.0
Logger returns the current custom logger function, or nil.
func (*Machine) MustBindHandlers ¶ added in v0.8.0
MustBindHandlers is a panicking version of BindHandlers, useful in tests.
func (*Machine) MustParseStates ¶
MustParseStates parses the states and returns them as a list. Panics when a state is not defined. It's an usafe equivalent of VerifyStates.
func (*Machine) NewStateCtx ¶ added in v0.5.0
NewStateCtx returns a new sub-context, bound to the current clock's tick of the passed state.
Context cancels when the state has been deactivated, or right away, if it isn't currently active.
State contexts are used to check state expirations and should be checked often inside goroutines.
func (*Machine) Not ¶
Not checks if **none** of the passed states are currently active.
machine.StringAll()
// -> ()[A:0 B:0 C:0 D:0]
machine.Add(S{"A", "B"})
// not(A) and not(C)
machine.Not(S{"A", "C"})
// -> false
// not(C) and not(D)
machine.Not(S{"C", "D"})
// -> true
func (*Machine) Not1 ¶ added in v0.5.0
Not1 is a shorthand method to check if a single state is currently inactive. See Not().
func (*Machine) PanicToErr ¶ added in v0.7.0
PanicToErr will catch a panic and add the Exception state. Needs to be called in a defer statement, just like a recover() call.
func (*Machine) PanicToErrState ¶ added in v0.7.0
PanicToErrState will catch a panic and add the Exception state, along with the passed state. Needs to be called in a defer statement, just like a recover() call.
func (*Machine) Remove ¶
Remove deactivates a list of states in the machine, returning the result of the transition (Executed, Queued, Canceled). Like every mutation method, it will resolve relations and trigger handlers.
func (*Machine) Remove1 ¶ added in v0.5.0
Remove1 is a shorthand method to remove a single state with the passed args. See Remove().
func (*Machine) Resolver ¶
func (m *Machine) Resolver() RelationsResolver
Resolver returns the relation resolver, used to produce target states of transitions.
func (*Machine) Set ¶
Set deactivates a list of states in the machine, returning the result of the transition (Executed, Queued, Canceled). Like every mutation method, it will resolve relations and trigger handlers.
func (*Machine) SetLogArgs ¶ added in v0.5.0
func (m *Machine) SetLogArgs(mapper LogArgsMapper)
SetLogArgs accepts a function which decides which mutation arguments to log. See NewArgsMapper or create your own manually.
func (*Machine) SetLogId ¶ added in v0.8.0
SetLogId enables or disables the logging of the machine's ID in log messages.
func (*Machine) SetLogLevel ¶
SetLogLevel sets the log level of the machine.
func (*Machine) SetLoggerEmpty ¶ added in v0.7.0
SetLoggerEmpty creates an empty logger that does nothing and sets the log level in one call. Useful when combined with am-dbg. Requires LogChanges log level to produce any output.
func (*Machine) SetLoggerSimple ¶ added in v0.7.0
SetLoggerSimple takes log.Printf and sets the log level in one call. Useful for testing. Requires LogChanges log level to produce any output.
func (*Machine) SetSchema ¶ added in v0.11.0
SetSchema sets the machine's schema. It will automatically call VerifyStates with the names param and handle EventSchemaChange if successful. The new schema has to be longer than the previous one (no relations-only changes). The length of the schema is also the version of the schema.
func (*Machine) SetTags ¶ added in v0.10.1
SetTags updates the machine's tags with the provided slice of strings.
func (*Machine) StateNames ¶
StateNames returns a copy of all the state names.
func (*Machine) StateNamesMatch ¶ added in v0.12.0
TODO docs
func (*Machine) StatesVerified ¶ added in v0.5.0
StatesVerified returns true if the state names have been ordered using VerifyStates.
func (*Machine) String ¶
String returns a one line representation of the currently active states, with their clock values. Inactive states are omitted. Eg: (Foo:1 Bar:3)
func (*Machine) StringAll ¶
StringAll returns a one line representation of all the states, with their clock values. Inactive states are in square brackets.
(Foo:1 Bar:3) [Baz:2]
func (*Machine) Switch ¶ added in v0.3.0
Switch returns the first state from the passed list that is currently active, making it handy for switch statements. Useful for state groups.
switch mach.Switch(ss.GroupPlaying) {
case "Playing":
case "Paused":
case "Stopped":
}
func (*Machine) Tags ¶ added in v0.5.0
Tags returns machine's tags, a list of unstructured strings without spaces.
func (*Machine) Time ¶
Time returns machine's time, a list of ticks per state. Returned value includes the specified states, or all the states if nil.
func (*Machine) TimeSum ¶
TimeSum returns the sum of machine's time (ticks per state). Returned value includes the specified states, or all the states if nil. It's a very inaccurate, yet simple way to measure the machine's time.
func (*Machine) Toggle ¶ added in v0.10.1
Toggle deactivates a list of states in case all are active, or activates all otherwise. Returns the result of the transition (Executed, Queued, Canceled).
func (*Machine) Toggle1 ¶ added in v0.8.0
Toggle1 activates or deactivates a single state, depending on its current state. Returns the result of the transition (Executed, Queued, Canceled).
func (*Machine) Transition ¶
func (m *Machine) Transition() *Transition
Transition returns the current transition, if any.
func (*Machine) VerifyStates ¶ added in v0.3.0
VerifyStates verifies an array of state names and returns an error in case at least one isn't defined. It also retains the order and uses it for StateNames. Verification can be checked via Machine.StatesVerified.
func (*Machine) WasClock ¶ added in v0.12.0
WasClock checks if the passed time has happened (or happening right now). Returns false if at least one state is too early.
func (*Machine) WasTime ¶ added in v0.12.0
WasTime checks if the passed time has happened (or happening right now). Returns false if at least one state is too early. The states param is optional and can be used to check only a subset of states.
func (*Machine) When ¶
When returns a channel that will be closed when all the passed states become active or the machine gets disposed.
ctx: optional context that will close the channel when handlerLoopDone.
func (*Machine) WhenArgs ¶ added in v0.5.0
WhenArgs returns a channel that will be closed when the passed state becomes active with all the passed args. Args are compared using the native '=='. It's meant to be used with async Multi states, to filter out a specific call.
ctx: optional context that will close the channel when handler loop ends.
func (*Machine) WhenDisposed ¶ added in v0.5.0
func (m *Machine) WhenDisposed() <-chan struct{}
WhenDisposed returns a channel that will be closed when the machine is disposed. Requires bound handlers. Use Machine.disposed in case no handlers have been bound.
func (*Machine) WhenErr ¶
WhenErr returns a channel that will be closed when the machine is in the Exception state.
ctx: optional context that will close the channel when handlerLoopDone.
func (*Machine) WhenNot ¶
WhenNot returns a channel that will be closed when all the passed states become inactive or the machine gets disposed.
ctx: optional context that will close the channel when handlerLoopDone.
func (*Machine) WhenNot1 ¶ added in v0.5.0
WhenNot1 is an alias to WhenNot() for a single state. See WhenNot.
func (*Machine) WhenQueueEnds ¶ added in v0.5.0
WhenQueueEnds closes every time the queue ends, or the optional ctx expires.
ctx: optional context that will close the channel when handlerLoopDone.
func (*Machine) WhenTicks ¶ added in v0.5.0
WhenTicks waits N ticks of a single state (relative to now). Uses WhenTime underneath.
ctx: optional context that will close the channel when handlerLoopDone.
func (*Machine) WhenTime ¶ added in v0.5.0
WhenTime returns a channel that will be closed when all the passed states have passed the specified time. The time is a logical clock of the state. Machine time can be sourced from Machine.Time(), or Machine.Clock().
ctx: optional context that will close the channel when handlerLoopDone.
func (*Machine) WhenTime1 ¶ added in v0.11.0
WhenTime1 waits till ticks for a single state equal the given value (or more).
ctx: optional context that will close the channel when handlerLoopDone.
func (*Machine) WillBe ¶ added in v0.8.0
WillBe returns true if the passed states are scheduled to be activated. See IsQueued to perform more detailed queries.
func (*Machine) WillBe1 ¶ added in v0.8.0
WillBe1 returns true if the passed state is scheduled to be activated. See IsQueued to perform more detailed queries.
func (*Machine) WillBeRemoved ¶ added in v0.8.0
WillBeRemoved returns true if the passed states are scheduled to be deactivated. See IsQueued to perform more detailed queries.
func (*Machine) WillBeRemoved1 ¶ added in v0.8.0
WillBeRemoved1 returns true if the passed state is scheduled to be deactivated. See IsQueued to perform more detailed queries.
type Mutation ¶
type Mutation struct {
// add, set, remove
Type MutationType
// States explicitly passed to the mutation method, as their indexes. Use
// Transition.CalledStates or IndexToStates to get the actual state names.
Called []int
// argument map passed to the mutation method (if any).
Args A
// this mutation has been triggered by an auto state
Auto bool
// Source is the source event for this mutation.
Source *MutSource
// contains filtered or unexported fields
}
Mutation represents an atomic change (or an attempt) of machine's active states. Mutation causes a Transition.
func (Mutation) CalledIndex ¶ added in v0.12.0
func (Mutation) StringFromIndex ¶ added in v0.12.0
type MutationType ¶
type MutationType int
MutationType enum
const ( MutationAdd MutationType = iota MutationRemove MutationSet )
func (MutationType) String ¶
func (m MutationType) String() string
type NoOpTracer ¶ added in v0.6.0
type NoOpTracer struct{}
NoOpTracer is a no-op implementation of Tracer, used for embedding.
func (*NoOpTracer) HandlerEnd ¶ added in v0.6.0
func (t *NoOpTracer) HandlerEnd( transition *Transition, emitter string, handler string)
func (*NoOpTracer) HandlerStart ¶ added in v0.6.0
func (t *NoOpTracer) HandlerStart( transition *Transition, emitter string, handler string)
func (*NoOpTracer) Inheritable ¶ added in v0.6.0
func (t *NoOpTracer) Inheritable() bool
func (*NoOpTracer) MachineDispose ¶ added in v0.6.0
func (t *NoOpTracer) MachineDispose(machID string)
func (*NoOpTracer) MachineInit ¶ added in v0.6.0
func (t *NoOpTracer) MachineInit(machine Api) context.Context
func (*NoOpTracer) NewSubmachine ¶ added in v0.6.0
func (t *NoOpTracer) NewSubmachine(parent, machine Api)
func (*NoOpTracer) QueueEnd ¶ added in v0.6.0
func (t *NoOpTracer) QueueEnd(machine Api)
func (*NoOpTracer) SchemaChange ¶ added in v0.11.0
func (t *NoOpTracer) SchemaChange(machine Api, old Schema)
func (*NoOpTracer) TransitionEnd ¶ added in v0.6.0
func (t *NoOpTracer) TransitionEnd(transition *Transition)
func (*NoOpTracer) TransitionInit ¶ added in v0.6.0
func (t *NoOpTracer) TransitionInit(transition *Transition)
func (*NoOpTracer) TransitionStart ¶ added in v0.7.0
func (t *NoOpTracer) TransitionStart(transition *Transition)
func (*NoOpTracer) VerifyStates ¶ added in v0.7.0
func (t *NoOpTracer) VerifyStates(machine Api)
type Opts ¶
type Opts struct {
// Unique ID of this machine. Default: random ID.
Id string
// Time for a handler to execute. Default: time.Second
HandlerTimeout time.Duration
// If true, the machine will NOT print all exceptions to stdout.
DontLogStackTrace bool
// If true, the machine will die on panics.
DontPanicToException bool
// If true, the machine will NOT prefix its logs with its ID.
// TODO refac to DontLogId
DontLogID bool
// Custom relations resolver. Default: *DefaultRelationsResolver.
Resolver RelationsResolver
// Log level of the machine. Default: LogNothing.
LogLevel LogLevel
// Tracer for the machine. Default: nil.
Tracers []Tracer
// LogArgs matching function for the machine. Default: nil.
LogArgs func(args A) map[string]string
// Parent machine, used to inherit certain properties, e.g. tracers.
// Overrides ParentID. Default: nil.
Parent Api
// ParentID is the ID of the parent machine. Default: "".
ParentId string
// Tags is a list of tags for the machine. Default: nil.
Tags []string
// QueueLimit is the maximum number of mutations that can be queued.
// Default: 1000.
// TODO per-state QueueLimit
QueueLimit int
// DetectEval will detect Eval calls directly in handlers, which causes a
// deadlock. It works in similar way as -race flag in Go and can also be
// triggered by setting either env var: AM_DEBUG=1 or AM_DETECT_EVAL=1.
// Default: false.
DetectEval bool
}
Opts struct is used to configure a new Machine.
func OptsWithDebug ¶ added in v0.5.0
OptsWithDebug returns Opts with debug settings (DontPanicToException, long HandlerTimeout).
func OptsWithTracers ¶ added in v0.5.0
OptsWithTracers returns Opts with the given tracers. Tracers are inherited by submachines (via Opts.Parent) when env.AM_DEBUG is set.
type RelationsResolver ¶
type RelationsResolver interface {
// TargetStates returns the target states after parsing the relations.
TargetStates(t *Transition, calledStates, index S) S
// NewAutoMutation returns an (optional) auto mutation which is appended to
// the queue after the transition is executed. It also returns the names of
// the called states.
NewAutoMutation() (*Mutation, S)
// SortStates sorts the states in the order their handlers should be
// executed.
SortStates(states S)
// RelationsOf returns a list of relation types of the given state.
RelationsOf(fromState string) ([]Relation, error)
// RelationsBetween returns a list of relation types between the given
// states.
RelationsBetween(fromState, toState string) ([]Relation, error)
InboundRelationsOf(toState string) (S, error)
// NewSchema runs when Machine receives a new struct.
NewSchema(schema Schema, states S)
}
RelationsResolver is an interface for parsing relations between states. Not thread-safe. TODO support custom relation types and additional state properties.
type Result ¶
type Result int8
Result enum is the result of a state Transition.
const ( // Executed means that the transition was executed immediately and not // canceled. Executed Result = 1 << iota // Canceled means that the transition was canceled, by either relations or a // handler. Canceled // Queued means that the transition was queued for later execution. The // following methods can be used to wait for the results: // - Machine.When // - Machine.WhenNot // - Machine.WhenArgs // - Machine.WhenTime // - Machine.WhenTicks // - Machine.WhenTicksEq Queued // ResultNoOp means that the transition was a no-op, i.e. the state was // already active. ResultNoOp is only used by helpers, and never returned by // the machine itself. ResultNoOp )
type S ¶
type S []string
S (state names) is a string list of state names.
func DiffStates ¶
DiffStates returns the states that are in states1 but not in states2.
func IndexToStates ¶ added in v0.12.0
IndexToStates decodes state indexes based on the provided index.
type Schema ¶ added in v0.10.2
Schema is a map of state names to state definitions.
func CloneSchema ¶ added in v0.12.0
CloneSchema deep clones the states struct and returns a copy.
func ParseSchema ¶ added in v0.12.0
func SchemaMerge ¶ added in v0.10.3
SchemaMerge merges multiple state structs into one, overriding the previous state definitions. No relation-level merging takes place.
type Serialized ¶ added in v0.7.0
type Serialized struct {
// ID is the ID of a state machine.
ID string `json:"id" yaml:"id" toml:"id"`
// Time represents machine time - a list of state activation counters.
Time Time `json:"time" yaml:"time" toml:"time"`
// StateNames is an ordered list of state names.
StateNames S `json:"state_names" yaml:"state_names" toml:"state_names"`
}
Serialized is a machine state serialized to a JSON/YAML/TOML compatible struct. One also needs the state Struct to re-create a state machine.
type State ¶
type State struct {
Auto bool `json:"auto,omitempty"`
Multi bool `json:"multi,omitempty"`
Require S `json:"require,omitempty"`
Add S `json:"add,omitempty"`
Remove S `json:"remove,omitempty"`
After S `json:"after,omitempty"`
Tags []string `json:"tags,omitempty"`
}
State defines a single state of a machine, its properties and relations.
func StateAdd ¶ added in v0.7.0
StateAdd adds new states to relations of the source state, without removing existing ones. Useful for adjusting shared stated to a specific machine. Only "true" values for Auto and Multi are applied from [overlay].
type StatesBase ¶ added in v0.8.0
type StatesBase struct {
// Exception is the only built-in state and mean a global error. All errors
// have to [State.Require] the Exception state. If [Machine.PanicToErr] is
// true, Exception will receive it.
Exception string
// contains filtered or unexported fields
}
func (*StatesBase) Names ¶ added in v0.8.0
func (b *StatesBase) Names() S
func (*StatesBase) SetNames ¶ added in v0.8.0
func (b *StatesBase) SetNames(names S)
type Step ¶ added in v0.5.0
type Step struct {
Type StepType
// Only for Type == StepRelation.
RelType Relation
// marks a final handler (FooState, FooEnd)
IsFinal bool
// marks a self handler (FooFoo)
IsSelf bool
// marks an enter handler (FooState, but not FooEnd). Requires IsFinal.
IsEnter bool
// Deprecated, use GetFromState(). TODO remove
FromState string
// TODO implement
FromStateIdx int
// Deprecated, use GetToState(). TODO remove
ToState string
// TODO implement
ToStateIdx int
// Deprecated, use RelType. TODO remove
Data any
}
Step struct represents a single step within a Transition, either a relation resolving step or a handler call.
func (*Step) GetFromState ¶ added in v0.9.0
GetFromState returns the source state of a step. Optional, unless no GetToState().
func (*Step) GetToState ¶ added in v0.9.0
GetToState returns the target state of a step. Optional, unless no GetFromState().
func (*Step) StringFromIndex ¶ added in v0.12.0
type StepType ¶ added in v0.5.0
type StepType int8
StepType enum
const ( StepRelation StepType = 1 << iota StepHandler // TODO rename to StepActivate StepSet // StepRemove indicates a step where a state goes active->inactive // TODO rename to StepDeactivate StepRemove // StepRemoveNotActive indicates a step where a state goes inactive->inactive // TODO rename to StepDeactivatePassive StepRemoveNotActive StepRequested StepCancel )
type Time ¶ added in v0.7.0
type Time []uint64
Time is machine time, an ordered list of state ticks. It's like Clock, but indexed by int, instead of string. TODO use math/big?
func IndexToTime ¶ added in v0.12.0
IndexToTime returns "virtual time" with selected states active. It's useful to use time methods on a list of states, eg the called ones.
func (Time) ActiveIndex ¶ added in v0.12.0
ActiveIndex returns a list of active state indexes in this machine time slice.
func (Time) ActiveStates ¶ added in v0.12.0
ActiveStates returns a list of active state names in this machine time slice.
func (Time) DiffSince ¶ added in v0.10.3
DiffSince returns the number of ticks for each state in Time since the passed machine time.
func (Time) Get ¶ added in v0.12.0
Get returns the tick at the given index, or 0 if out of bounds (for old schemas).
func (Time) Is ¶ added in v0.7.0
Is checks if all the passed states were active at a given time, via indexes. See Machine.Index().
func (Time) Is1 ¶ added in v0.7.0
Is1 checks if a state is active at a given time, via its index. See Machine.Index().
type TimeIndex ¶ added in v0.12.0
TimeIndex is Time with a bound state index (list of state names). It's not suitable for storage, use Time instead.
func NewTimeIndex ¶ added in v0.12.0
func (TimeIndex) ActiveStates ¶ added in v0.12.0
type Tracer ¶ added in v0.5.0
type Tracer interface {
TransitionInit(transition *Transition)
TransitionStart(transition *Transition)
TransitionEnd(transition *Transition)
HandlerStart(transition *Transition, emitter string, handler string)
HandlerEnd(transition *Transition, emitter string, handler string)
// MachineInit is called only for machines with tracers added via
// Opts.Tracers.
MachineInit(machine Api) context.Context
MachineDispose(machID string)
NewSubmachine(parent, machine Api)
Inheritable() bool
QueueEnd(machine Api)
SchemaChange(machine Api, old Schema)
VerifyStates(machine Api)
}
Tracer is an interface for logging machine transitions and events, used by Opts.Tracers and Machine.BindTracer.
type Transition ¶
type Transition struct {
// ID is a unique identifier of the transition.
// TODO refac to Id() with the new dbg protocol
ID string
// Steps is a list of steps taken by this transition (so far).
Steps []*Step
// TimeBefore is the machine time from before the transition.
TimeBefore Time
// TimeAfter is the machine time from after the transition. If the transition
// has been canceled, this will be the same as TimeBefore. This field is nil
// until the negotiation phase finishes.
TimeAfter Time
// TargetIndexes is a list of indexes of the target states.
TargetIndexes []int
// Enters is a list of states with enter handlers in this transition.
Enters S
// Enters is a list of states with exit handlers in this transition.
Exits S
// Mutation call which caused this transition
Mutation *Mutation
// Machine is the parent machine of this transition.
Machine *Machine
// Api is a subset of Machine.
// TODO call when applicable instead of calling Machine
// TODO rename to MachApi
Api Api
// LogEntries are log msgs produced during the transition.
LogEntries []*LogEntry
// PreLogEntries are log msgs produced before during the transition.
PreLogEntries []*LogEntry
// QueueLen is the length of the queue after the transition.
QueueLen int
// LogEntriesLock is used to lock the logs to be collected by a Tracer.
LogEntriesLock sync.Mutex
// IsCompleted returns true when the execution of the transition has been
// fully completed.
IsCompleted atomic.Bool
// IsAccepted returns true if the transition has been accepted, which can
// change during the transition's negotiation phase and while resolving
// relations.
IsAccepted atomic.Bool
// contains filtered or unexported fields
}
Transition represents processing of a single mutation within a machine.
func (*Transition) Args ¶
func (t *Transition) Args() A
Args returns the argument map passed to the mutation method (or an empty one).
func (*Transition) CalledStates ¶
func (t *Transition) CalledStates() S
CalledStates return explicitly called / requested states of the transition.
func (*Transition) ClockAfter ¶ added in v0.7.0
func (t *Transition) ClockAfter() Clock
ClockAfter return the Clock from before the transition.
func (*Transition) ClockBefore ¶ added in v0.7.0
func (t *Transition) ClockBefore() Clock
ClockBefore return the Clock from before the transition.
func (*Transition) IsAuto ¶
func (t *Transition) IsAuto() bool
IsAuto returns true if the transition was triggered by an auto state. Thus, it cant trigger any other auto state mutations.
func (*Transition) LogArgs ¶ added in v0.5.0
func (t *Transition) LogArgs() string
LogArgs returns a text snippet with arguments which should be logged for this Mutation.
func (*Transition) StatesBefore ¶
func (t *Transition) StatesBefore() S
StatesBefore is a list of states before the transition.
func (*Transition) String ¶
func (t *Transition) String() string
String representation of the transition and the steps taken so far.
func (*Transition) TargetStates ¶
func (t *Transition) TargetStates() S
TargetStates is a list of states after parsing the relations.
func (*Transition) Type ¶
func (t *Transition) Type() MutationType
Type returns the type of the mutation (add, remove, set).
type WhenArgsBinding ¶ added in v0.7.0
type WhenArgsBinding struct {
// contains filtered or unexported fields
}
type WhenBinding ¶ added in v0.7.0
type WhenBinding struct {
Ch chan struct{}
// means states are required to NOT be active
Negation bool
States StateIsActive
Matched int
Total int
}
type WhenTimeBinding ¶ added in v0.7.0
type WhenTimeBinding struct {
Ch chan struct{}
// map of completed to their index positions
// TODO optimize indexes
Index map[string]int
// number of matches so far
Matched int
// number of total matches needed
Total int
// optional Time to match for completed from Index
Times Time
Completed StateIsActive
}
