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 ¶
- func IsTimeAfter(time1, time2 T) bool
- type A
- 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) 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) 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) Time(states S) T
- func (m *Machine) TimeSum(states S) uint64
- func (m *Machine) To() S
- 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 ¶
This section is empty.
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 // Logging level of the machine. LogLevel LogLevel // 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) 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.
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) 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) 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 { // List of steps taken by this transition (so far). // TODO []*TransitionStep Steps []*TransitionStep // Index of added steps. StepIDs map[string]bool // When true, execution of the transition has been completed. IsCompleted bool // states before the transition StatesBefore S // 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 // 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
const ( TransitionStepTypeRelation TransitionStepType = 1 << iota TransitionStepTypeTransition TransitionStepTypeSet TransitionStepTypeRemove TransitionStepTypeNoSet TransitionStepTypeRequested TransitionStepTypeCancel )
func (TransitionStepType) String ¶
func (tt TransitionStepType) String() string