Documentation
¶
Overview ¶
Package machine is a minimal implementation of AsyncMachine 1 in Golang using channels and context. It aims at simplicity and speed.
It can be used as a lightweight in-memory Temporal 2 alternative, worker for Asynq 3, or to write simple consensus engines, stateful firewalls, telemetry, bots, etc.
AsyncMachine is a relational state machine which never blocks.
Index ¶
- Constants
- func IsTimeAfter(time1, time2 T) bool
- type A
- type Clocks
- type DefaultRelationsResolver
- type Event
- type ExceptionArgsPanic
- type ExceptionHandler
- type HandlerBinding
- type LogLevel
- type Logger
- type Machine
- func (m *Machine) Add(states S, args A) Result
- func (m *Machine) AddErr(err error) Result
- func (m *Machine) AddErrStr(err string) Result
- func (m *Machine) Any(states ...S) bool
- func (m *Machine) BindHandlers(handlers any) error
- func (m *Machine) Clock(state string) uint64
- func (m *Machine) Dispose()
- func (m *Machine) DuringTransition() bool
- func (m *Machine) From() S
- func (m *Machine) GetLogLevel() LogLevel
- func (m *Machine) GetLogger() Logger
- func (m *Machine) GetRelationsBetween(fromState, toState string) []Relation
- func (m *Machine) GetRelationsOf(fromState string) []Relation
- func (m *Machine) GetStateCtx(state string) context.Context
- func (m *Machine) Has(states S) bool
- func (m *Machine) HasStateChanged(before S, clocks Clocks) bool
- func (m *Machine) Inspect(states S) string
- func (m *Machine) Is(states S) bool
- func (m *Machine) IsClock(state string, tick uint64) bool
- func (m *Machine) IsErr() bool
- func (m *Machine) IsQueued(mutationType MutationType, states S, withoutArgsOnly bool, ...) int
- func (m *Machine) Log(msg string, args ...any)
- func (m *Machine) MustParseStates(states S) S
- func (m *Machine) Not(states S) bool
- func (m *Machine) On(events []string, ctx context.Context) chan *Event
- func (m *Machine) Remove(states S, args A) Result
- func (m *Machine) Set(states S, args A) Result
- func (m *Machine) SetLogLevel(level LogLevel)
- func (m *Machine) SetLogger(fn Logger)
- func (m *Machine) String() string
- func (m *Machine) StringAll() string
- func (m *Machine) Switch(states ...string) string
- func (m *Machine) Time(states S) T
- func (m *Machine) TimeSum(states S) uint64
- func (m *Machine) To() S
- func (m *Machine) VerifyStates(states S) error
- func (m *Machine) When(states []string, ctx context.Context) chan struct{}
- func (m *Machine) WhenErr(ctx context.Context) chan struct{}
- func (m *Machine) WhenNot(states []string, ctx context.Context) chan struct{}
- type Mutation
- type MutationType
- type Opts
- type Relation
- type RelationsResolver
- type Result
- type S
- type State
- type States
- type T
- type Transition
- type TransitionStep
- type TransitionStepType
Constants ¶
Variables ¶
This section is empty.
Functions ¶
func IsTimeAfter ¶
IsTimeAfter checks if time1 is after time2. Requires ordered results from Machine.Time() (with specified states).
Types ¶
type DefaultRelationsResolver ¶
type DefaultRelationsResolver struct { Machine *Machine Transition *Transition }
DefaultRelationsResolver is the default implementation of the RelationsResolver.
func (*DefaultRelationsResolver) GetAutoMutation ¶
func (rr *DefaultRelationsResolver) GetAutoMutation() *Mutation
func (*DefaultRelationsResolver) GetTargetStates ¶
func (rr *DefaultRelationsResolver) GetTargetStates( t *Transition, calledStates S, ) S
func (*DefaultRelationsResolver) SortStates ¶
func (rr *DefaultRelationsResolver) SortStates(states S)
type ExceptionArgsPanic ¶
type ExceptionArgsPanic struct { CalledStates S StatesBefore S Transition *Transition LastStep *TransitionStep StackTrace []byte }
ExceptionArgsPanic is an optional argument for the Exception state which describes a panic within a transition handler.
type ExceptionHandler ¶
type ExceptionHandler struct{}
ExceptionHandler provide basic Exception state support.
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 HandlerBinding ¶
type HandlerBinding struct {
Ready chan struct{}
}
type Machine ¶
type Machine struct { // Unique ID of this machine. Default: random UUID. ID string // Time for a handler to execute. Default: time.Second // TODO support HandlerTimeout time.Duration // If true, the machine will print all exceptions to stdout. Default: true. // Requires an ExceptionHandler binding and Machine.PanicToException set. PrintExceptions bool // If true, the machine will catch panic and trigger the Exception state. // Default: true. PanicToException bool // If true, the machine will prefix its logs with the machine ID (5 chars). // Default: true. LogID bool // Relations resolver, used to produce target states of a transition. // Default: *DefaultRelationsResolver. Resolver RelationsResolver // Ctx is the context of the machine. Ctx context.Context // Err is the last error that occurred. Err error // States is a map of state names to state definitions. States States // Queue of mutations to be executed. Queue []Mutation // Currently executing transition (if any). Transition *Transition // All states that are currently active. ActiveStates S // List of all the registered state names. StateNames S // contains filtered or unexported fields }
Machine represent states, provides mutation methods, helpers methods and info about the current and scheduled transitions (if any). See https://github.com/pancsta/asyncmachine-go/blob/main/docs/manual.md
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) AddErr ¶
AddErr is a shorthand method to add the Exception state with the passed error. Like every mutation method, it will resolve relations and trigger handlers.
func (*Machine) AddErrStr ¶
AddErrStr is a shorthand method to add the Exception state with the passed error string. Like every mutation method, it will resolve relations and trigger handlers.
func (*Machine) Any ¶
Any 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) BindHandlers ¶
BindHandlers binds a struct of handler methods to the machine's states. Returns a HandlerBinding object, which signals when the binding is ready.
func (*Machine) Dispose ¶
func (m *Machine) Dispose()
Dispose disposes the machine and all its emitters.
func (*Machine) DuringTransition ¶
DuringTransition checks if the machine is currently during a transition.
func (*Machine) From ¶
From returns the states from before the transition. Assumes DuringTransition.
func (*Machine) GetLogLevel ¶ added in v0.3.0
func (*Machine) GetLogger ¶ added in v0.3.0
GetLogger returns the current custom logger function, or nil.
func (*Machine) GetRelationsBetween ¶
GetRelationsBetween returns a list of relation types between the given states.
func (*Machine) GetRelationsOf ¶
GetRelationsOf returns a list of relation types of the given state.
func (*Machine) GetStateCtx ¶
GetStateCtx returns a context, bound to the current clock tick of the passed state.
Context cancels when the state has been de-activated, or right away, if it isn't currently active.
func (*Machine) HasStateChanged ¶
HasStateChanged checks current active states have changed from the passed ones. Optionally also compares clock ticks.
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) 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) IsClock ¶
IsClock checks if the passed state's clock equals the passed tick.
``` tick := m.Clock("A") m.Remove("A") m.Add("A") m.Is("A", tick) // -> false ```
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) Log ¶
Log logs an [external] message with the LogChanges level (highest one). Optionally redirects to a custom logger from SetLogger.
func (*Machine) MustParseStates ¶
MustParseStates parses the states and returns them as a list. Panics when a state is not defined.
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) On ¶
On returns a channel that will be notified with *Event, when any of the passed events happen. It's quick substitute for a predefined transition handler, although it does not guarantee a deterministic order of execution. ctx: optional context to dispose the emitter earlier. It's not supported to nest On() calls, as it would cause a deadlock.
func (*Machine) Remove ¶
Remove de-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) Set ¶
Set de-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) SetLogLevel ¶
SetLogLevel sets the log level of the machine.
func (*Machine) String ¶
String returns a one line representation of the currently active states, with their clock values. Inactive states are omitted. Eg: (Foo:2 Bar:1)
func (*Machine) StringAll ¶
StringAll returns a one line representation of all the states, with their clock values. Inactive states are in square brackets. Eg: (Foo:2 Bar:1)[Baz:0]
func (*Machine) Switch ¶ added in v0.3.0
Switch returns the first state from the passed list that is currently active, making it useful for switch statements.
func (*Machine) Time ¶
Time returns a list of logical clocks of specified states (or all the states if nil). states: optionally passing a list of states param guarantees a deterministic order of the result.
func (*Machine) TimeSum ¶
TimeSum returns the sum of logical clocks of specified states (or all states if nil). It's a very inaccurate, yet simple way to measure the machine's time.
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 (only if all states have been passed).
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 done. Useful when listening on 2 When() channels within the same `select` to GC the 2nd one.
func (*Machine) WhenErr ¶
WhenErr returns a channel that will be closed when the machine is in the Exception state. ctx: optional context defaults to the machine's context.
type Mutation ¶
type Mutation struct { Type MutationType CalledStates S Args A // this mutation has been triggered by an auto state Auto bool }
type MutationType ¶
type MutationType int
MutationType enum
const ( MutationTypeAdd MutationType = iota MutationTypeRemove MutationTypeSet )
func (MutationType) String ¶
func (m MutationType) String() string
type Opts ¶
type Opts struct { // Unique ID of this machine. Default: random UUID. 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. DontPrintExceptions bool // If true, the machine will die on panics. DontPanicToException bool // If true, the machine will NOT prefix its logs with its ID. DontLogID bool // Custom relations resolver. Default: *DefaultRelationsResolver. Resolver RelationsResolver // Log level of the machine. Default: LogNothing. LogLevel LogLevel }
type RelationsResolver ¶
type RelationsResolver interface { // GetTargetStates returns the target states after parsing the relations. GetTargetStates(t *Transition, calledStates S) S // GetAutoMutation returns an (optional) auto mutation which is appended to // the queue after the transition is executed. GetAutoMutation() *Mutation // SortStates sorts the states in the order their handlers should be // executed. SortStates(states S) }
RelationsResolver is an interface for parsing relations between states. TODO support custom relation types
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.
type Transition ¶
type Transition struct { ID string // List of steps taken by this transition (so far). Steps []*TransitionStep // When true, execution of the transition has been completed. IsCompleted bool // states before the transition StatesBefore S // clocks of the states from before the transition ClocksBefore Clocks // States with "enter" handlers to execute Enters S // States 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 *Mutation // Parent machine Machine *Machine // Log entries produced during the transition LogEntries []string // contains filtered or unexported fields }
Transition represents processing of a single mutation withing a machine.
func (*Transition) Args ¶
func (t *Transition) Args() A
Args returns the argument object passed to the mutation method (if any).
func (*Transition) CalledStates ¶
func (t *Transition) CalledStates() S
CalledStates return explicitly called / requested states of 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) String ¶
func (t *Transition) String() string
String representation of the transition and the steps taken so far. TODO: implement, test
func (*Transition) Type ¶
func (t *Transition) Type() MutationType
Type returns the type of the mutation (add, remove, set).
type TransitionStep ¶
type TransitionStep struct { ID string FromState string ToState string Type TransitionStepType // eg a transition method name, relation type Data any // marks a final handler (FooState, FooEnd) IsFinal bool // marks a self handler (FooFoo) IsSelf bool // marks an enter handler (FooEnter). Requires IsFinal. IsEnter bool }
type TransitionStepType ¶
type TransitionStepType int
TransitionStepType enum TODO rename to StepType
const ( TransitionStepTypeRelation TransitionStepType = 1 << iota TransitionStepTypeTransition TransitionStepTypeSet TransitionStepTypeRemove // TODO rename to StepTypeRemoveNotSet TransitionStepTypeNoSet TransitionStepTypeRequested TransitionStepTypeCancel )
func (TransitionStepType) String ¶
func (tt TransitionStepType) String() string