hsm

package module
v1.0.5 Latest Latest
Warning

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

Go to latest
Published: Feb 3, 2026 License: MIT Imports: 16 Imported by: 0

README

package hsm

import "github.com/stateforward/hsm.go"

Package hsm provides a powerful hierarchical state machine (HSM) implementation for Go.

Overview

It enables modeling complex state-driven systems with features like hierarchical states, entry/exit actions, guard conditions, and event-driven transitions. The implementation follows the Unified DSK (Domain Specific Kit) specification, ensuring consistency across platforms.

Features

  • Hierarchical States: Support for nested states and regions.
  • Event-Driven: Asynchronous event processing with context propagation.
  • Guards & Actions: Flexible functional definitions for transition guards and state actions.
  • Type Safe: Generics-based implementation for state context.

Usage

Define your state machine structure and behavior using the declarative builder pattern:

type MyHSM struct {
    hsm.HSM
    counter int
}

model := hsm.Define(
    "example",
    hsm.State("foo"),
    hsm.State("bar"),
    hsm.Transition(
        hsm.Trigger("moveToBar"),
        hsm.Source("foo"),
        hsm.Target("bar"),
    ),
    hsm.Initial("foo"),
)

// Start the state machine
sm := hsm.Start(context.Background(), &MyHSM{}, &model)
sm.Dispatch(hsm.Event{Name: "moveToBar"})
  • ErrNilHSM, ErrInvalidState, ErrMissingHSM, ErrMissingOperation, ErrInvalidOperation — Error variables for common HSM error conditions.
  • InitialEvent, ErrorEvent, AnyEvent, FinalEvent, InfiniteDuration — Built-in event types and special duration constants used by the HSM runtime.
  • Keys
  • NullKind, ElementKind, NamespaceKind, VertexKind, ConstraintKind, BehaviorKind, ConcurrentKind, StateMachineKind, StateKind, RegionKind, TransitionKind, InternalKind, ExternalKind, LocalKind, SelfKind, EventKind, TimeEventKind, CompletionEventKind, ChangeEventKind, CallEventKind, ErrorEventKind, PseudostateKind, InitialKind, FinalStateKind, ChoiceKind, ShallowHistoryKind, DeepHistoryKind, CustomKind — Kind constants define the HSM type hierarchy using bit-packed inheritance.
  • Version — Version is the current semantic version of the hsm package.
  • func AfterDispatch(ctx context.Context, hsm Instance, event Event) <-chan struct{} — AfterDispatch returns a channel that closes when the specified event is dispatched.
  • func AfterEntry(ctx context.Context, hsm Instance, state string) <-chan struct{} — AfterEntry returns a channel that closes when the specified state is entered.
  • func AfterExecuted(ctx context.Context, hsm Instance, state string) <-chan struct{} — AfterExecuted returns a channel that closes when the specified state's do-activity has completed execution.
  • func AfterExit(ctx context.Context, hsm Instance, state string) <-chan struct{} — AfterExit returns a channel that closes when the specified state is exited.
  • func AfterProcess(ctx context.Context, hsm Instance, maybeEvent ...Event) <-chan struct{} — AfterProcess returns a channel that closes when event processing completes.
  • func Call(ctx context.Context, hsm Instance, name string, args ...any) (any, error) — Call dispatches an OnCall event and invokes the named operation.
  • func DispatchAll(ctx context.Context, event Event) <-chan struct{} — DispatchAll sends an event to all state machine instances in the current context.
  • func DispatchTo(ctx context.Context, event Event, maybeIds ...string) <-chan struct{}
  • func Dispatch[T context.Context](ctx T, hsm Instance, event Event) <-chan struct{} — Dispatch sends an event to a specific state machine instance.
  • func Get(ctx context.Context, hsm Instance, name string) (any, bool) — Get reads an attribute value from the given state machine or from context.
  • func ID(hsm Instance) string — ID returns the unique identifier of a state machine instance.
  • func IsAncestor(current, target string) bool — IsAncestor checks whether current is an ancestor of target in the state hierarchy.
  • func LCA(a, b string) string — LCA finds the Lowest Common Ancestor between two qualified state names in a hierarchical state machine.
  • func Match(value string, patterns ...string) bool — Match provides a simple interface, handling basic cases directly and delegating complex matching to the match function.
  • func Name(hsm Instance) string — Name returns the simple name of a state machine instance (without path prefix).
  • func New[T Instance](sm T, model *Model, maybeConfig ...Config) T
  • func QualifiedName(hsm Instance) string — QualifiedName returns the fully qualified name of a state machine instance.
  • func Restart(ctx context.Context, hsm Instance, maybeData ...any) <-chan struct{} — Restart stops a state machine and restarts it from the initial state.
  • func Set(ctx context.Context, hsm Instance, name string, value any) <-chan struct{} — Set updates an attribute value and emits an OnSet change event.
  • func Start[T Instance](ctx context.Context, sm T, maybeData ...any) T
  • func Started[T Instance](ctx context.Context, sm T, model *Model, maybeConfig ...Config) T — Started creates and starts a new state machine instance with the given model and configuration.
  • func Stop(ctx context.Context, hsm Instance) <-chan struct{} — Stop gracefully stops a state machine instance.
  • type AttributeChange — AttributeChange is the payload for attribute change events.
  • type CallData — CallData is the payload for call events.
  • type Config — Config provides configuration options for state machine initialization.
  • type Element
  • type EventDetail
  • type Event
  • type Expression — Expression is a function type that evaluates a condition on a state machine.
  • type HSM
  • type Instance — Instance represents an active state machine instance that can process events and track state.
  • type Model — Model represents the complete state machine model definition.
  • type Operation — Operation is a function type that performs an action on a state machine.
  • type RedefinableElement — RedefinableElement is a function type that modifies a Model by adding or updating elements.
  • type Snapshot

Documentation

Overview

Package hsm provides a powerful hierarchical state machine (HSM) implementation for Go.

Overview

It enables modeling complex state-driven systems with features like hierarchical states, entry/exit actions, guard conditions, and event-driven transitions. The implementation follows the Unified DSK (Domain Specific Kit) specification, ensuring consistency across platforms.

Features

  • **Hierarchical States**: Support for nested states and regions.
  • **Event-Driven**: Asynchronous event processing with context propagation.
  • **Guards & Actions**: Flexible functional definitions for transition guards and state actions.
  • **Type Safe**: Generics-based implementation for state context.

Usage

Define your state machine structure and behavior using the declarative builder pattern:

type MyHSM struct {
    hsm.HSM
    counter int
}

model := hsm.Define(
    "example",
    hsm.State("foo"),
    hsm.State("bar"),
    hsm.Transition(
        hsm.Trigger("moveToBar"),
        hsm.Source("foo"),
        hsm.Target("bar"),
    ),
    hsm.Initial("foo"),
)

// Start the state machine
sm := hsm.Start(context.Background(), &MyHSM{}, &model)
sm.Dispatch(hsm.Event{Name: "moveToBar"})

Index

Constants

View Source
const Version = "v1.0.5"

Version is the current semantic version of the hsm package.

Variables

View Source
var (
	// NullKind represents the absence of a kind or an uninitialized kind value.
	NullKind = kind.Make()
	// ElementKind is the base kind for all HSM elements. Every structural
	// component in the state machine hierarchy derives from ElementKind.
	ElementKind = kind.Make()
	// NamespaceKind represents elements that can contain named children,
	// enabling hierarchical name resolution for states and state machines.
	NamespaceKind = kind.Make(ElementKind)
	// VertexKind is the base kind for nodes in the state graph that can be
	// sources or targets of transitions, including states and pseudostates.
	VertexKind = kind.Make(ElementKind)
	// ConstraintKind represents guard conditions that control transition firing.
	ConstraintKind = kind.Make(ElementKind)
	// BehaviorKind represents executable behaviors such as entry, exit, and
	// transition effects that run during state machine execution.
	BehaviorKind = kind.Make(ElementKind)
	// ConcurrentKind represents behaviors that support concurrent execution
	// of multiple orthogonal regions.
	ConcurrentKind = kind.Make(BehaviorKind)
	// StateMachineKind represents the top-level state machine container that
	// owns regions, states, and transitions. Inherits from both ConcurrentKind
	// (for orthogonal regions) and NamespaceKind (for named child lookup).
	StateMachineKind = kind.Make(ConcurrentKind, NamespaceKind)
	// StateKind represents a state vertex that can contain nested regions,
	// entry/exit behaviors, and internal transitions. Inherits from VertexKind
	// (as a graph node) and NamespaceKind (as a container for child elements).
	StateKind = kind.Make(VertexKind, NamespaceKind)
	// RegionKind represents an orthogonal region within a composite state or
	// state machine, containing vertices and transitions.
	RegionKind = kind.Make(ElementKind)
	// TransitionKind is the base kind for all transitions between vertices,
	// representing edges in the state graph.
	TransitionKind = kind.Make(ElementKind)
	// InternalKind represents internal transitions that execute without
	// exiting or re-entering the containing state.
	InternalKind = kind.Make(TransitionKind)
	// ExternalKind represents external transitions that exit the source state
	// and enter the target state, triggering exit and entry behaviors.
	ExternalKind = kind.Make(TransitionKind)
	// LocalKind represents local transitions that do not exit the containing
	// composite state when transitioning between its substates.
	LocalKind = kind.Make(TransitionKind)
	// SelfKind represents self-transitions where the source and target are
	// the same state, triggering exit and re-entry of that state.
	SelfKind = kind.Make(TransitionKind)
	// EventKind is the base kind for all events that can trigger transitions
	// in the state machine.
	EventKind = kind.Make(ElementKind)
	// TimeEventKind represents events triggered after a specified duration,
	// used for timeout-based transitions.
	TimeEventKind = kind.Make(EventKind)
	// CompletionEventKind represents events automatically generated when a
	// state completes all its internal activities or reaches a final state.
	CompletionEventKind = kind.Make(EventKind)
	// ChangeEventKind represents events triggered when a boolean condition
	// becomes true, enabling data-driven transitions.
	ChangeEventKind = kind.Make(EventKind)
	// CallEventKind represents events triggered by method calls on the state
	// machine, enabling synchronous event dispatch.
	CallEventKind = kind.Make(EventKind)
	// ErrorEventKind represents events generated when an error occurs during
	// state machine execution. Inherits from CompletionEventKind as errors
	// typically complete the current processing.
	ErrorEventKind = kind.Make(CompletionEventKind)
	// PseudostateKind is the base kind for transient vertices that perform
	// control flow logic without representing stable states.
	PseudostateKind = kind.Make(VertexKind)
	// InitialKind represents the initial pseudostate that indicates the
	// default starting state when entering a region.
	InitialKind = kind.Make(PseudostateKind)
	// FinalStateKind represents a final state indicating that the enclosing
	// region has completed its execution.
	FinalStateKind = kind.Make(StateKind)
	// ChoiceKind represents a choice pseudostate that evaluates guards to
	// select among multiple outgoing transitions dynamically.
	ChoiceKind = kind.Make(PseudostateKind)
	// ShallowHistoryKind represents a shallow history pseudostate that
	// remembers the most recently active direct substate of its region.
	ShallowHistoryKind = kind.Make(PseudostateKind)
	// DeepHistoryKind represents a deep history pseudostate that remembers
	// the full active state configuration within its region recursively.
	DeepHistoryKind = kind.Make(PseudostateKind)
	// CustomKind represents user-defined element types for extending the
	// HSM framework with application-specific constructs.
	CustomKind = kind.Make(ElementKind)
)

Kind constants define the HSM type hierarchy using bit-packed inheritance. Each Kind encodes its own ID and the IDs of its ancestor types, enabling efficient type checking via kind.Is(). The hierarchy follows UML state machine concepts where elements can inherit from multiple parent kinds.

View Source
var (
	// ErrNilHSM is returned when an operation is attempted on a nil state machine.
	ErrNilHSM = errors.New("hsm is nil")
	// ErrInvalidState is returned when attempting to access or transition to an invalid state.
	ErrInvalidState = errors.New("invalid state")
	// ErrMissingHSM is returned when the HSM instance cannot be found in the context.
	ErrMissingHSM = errors.New("missing hsm in context")
	// ErrMissingOperation is returned when an operation callback is required but not provided.
	ErrMissingOperation = errors.New("missing operation")
	// ErrInvalidOperation is returned when an operation callback has an unsupported function signature.
	ErrInvalidOperation = errors.New("invalid operation")
)

Error variables for common HSM error conditions. These sentinel errors can be checked using errors.Is for specific error handling.

View Source
var (
	// InitialEvent is the completion event dispatched when a state machine starts.
	// It triggers the initial transition from the initial pseudostate to the first active state.
	InitialEvent = Event{
		Name: "hsm_initial",
		Kind: CompletionEventKind,
	}
	// ErrorEvent is dispatched when an error occurs during state machine execution,
	// such as panics in concurrent behaviors or timeout errors. Use On(ErrorEvent) to handle errors.
	ErrorEvent = Event{
		Name: "hsm_error",
		Kind: ErrorEventKind,
	}
	// AnyEvent is a wildcard event that matches any event not explicitly handled.
	// Transitions using On(AnyEvent) are only taken when no specific event transition matches.
	AnyEvent = Event{
		Name: "*",
		Kind: EventKind,
	}
	// FinalEvent is the completion event dispatched when a state reaches its final state.
	// It triggers exit behaviors and propagates completion to parent regions.
	FinalEvent = Event{
		Name: "hsm_final",
		Kind: CompletionEventKind,
	}
	// InfiniteDuration represents an unbounded duration for timeout operations.
	// Use this when a behavior should run indefinitely without timing out.
	InfiniteDuration = time.Duration(-1)
)

Built-in event types and special duration constants used by the HSM runtime.

View Source
var Keys = struct {
	Instances key[*atomic.Pointer[[]Instance]]
	Owner     key[Instance]
	HSM       key[HSM]
}{
	Instances: key[*atomic.Pointer[[]Instance]]{},
	Owner:     key[Instance]{},
	HSM:       key[HSM]{},
}

Functions

func AfterDispatch

func AfterDispatch(ctx context.Context, hsm Instance, event Event) <-chan struct{}

AfterDispatch returns a channel that closes when the specified event is dispatched. Unlike AfterProcess, this signals when the event is added to the queue, not when processing completes. Useful for confirming event delivery before processing begins.

func AfterEntry

func AfterEntry(ctx context.Context, hsm Instance, state string) <-chan struct{}

AfterEntry returns a channel that closes when the specified state is entered. The state parameter should be the fully qualified state path (e.g., "/parent/child"). Useful for waiting until a particular state becomes active.

func AfterExecuted

func AfterExecuted(ctx context.Context, hsm Instance, state string) <-chan struct{}

AfterExecuted returns a channel that closes when the specified state's do-activity has completed execution. The state parameter should be the fully qualified state path. Useful for waiting until a state's background activity finishes.

func AfterExit

func AfterExit(ctx context.Context, hsm Instance, state string) <-chan struct{}

AfterExit returns a channel that closes when the specified state is exited. The state parameter should be the fully qualified state path (e.g., "/parent/child"). Useful for waiting until a particular state is no longer active.

func AfterProcess

func AfterProcess(ctx context.Context, hsm Instance, maybeEvent ...Event) <-chan struct{}

AfterProcess returns a channel that closes when event processing completes. If an event is provided, the channel closes after that specific event is processed. If no event is provided, the channel closes after the next processing cycle completes. This is useful for synchronizing with state machine execution in tests or when coordinating external operations with state transitions.

func Call added in v1.0.3

func Call(ctx context.Context, hsm Instance, name string, args ...any) (any, error)

Call dispatches an OnCall event and invokes the named operation.

func Dispatch

func Dispatch[T context.Context](ctx T, hsm Instance, event Event) <-chan struct{}

Dispatch sends an event to a specific state machine instance. Returns a channel that closes when the event has been fully processed.

Example:

sm := hsm.Start(...)
done := sm.Dispatch(hsm.Event{Name: "start"})
<-done // Wait for event processing to complete

func DispatchAll

func DispatchAll(ctx context.Context, event Event) <-chan struct{}

DispatchAll sends an event to all state machine instances in the current context. Returns a channel that closes when all instances have processed the event. DispatchAll sends an event to all state machine instances in the current context. Returns a channel that closes when all instances have processed the event.

Example:

sm1 := hsm.Start(...)
sm2 := hsm.Start(...)
done := hsm.DispatchAll(context.Background(), hsm.Event{Name: "globalEvent"})
<-done // Wait for all instances to process the event

func DispatchTo

func DispatchTo(ctx context.Context, event Event, maybeIds ...string) <-chan struct{}

func Get added in v1.0.3

func Get(ctx context.Context, hsm Instance, name string) (any, bool)

Get reads an attribute value from the given state machine or from context.

func ID

func ID(hsm Instance) string

ID returns the unique identifier of a state machine instance. The ID is assigned when the state machine is created and remains constant throughout its lifecycle.

func IsAncestor

func IsAncestor(current, target string) bool

IsAncestor checks whether current is an ancestor of target in the state hierarchy. It returns true if current appears in the path from the root to target's parent. Returns false if current equals target, or if either path is "." (relative root). The root path "/" is considered an ancestor of all other paths.

func LCA

func LCA(a, b string) string

LCA finds the Lowest Common Ancestor between two qualified state names in a hierarchical state machine. It takes two qualified names 'a' and 'b' as strings and returns their closest common ancestor.

For example: - LCA("/s/s1", "/s/s2") returns "/s" - LCA("/s/s1", "/s/s1/s11") returns "/s/s1" - LCA("/s/s1", "/s/s1") returns "/s/s1"

func Match

func Match(value string, patterns ...string) bool

Match provides a simple interface, handling basic cases directly and delegating complex matching to the match function.

func Name

func Name(hsm Instance) string

Name returns the simple name of a state machine instance (without path prefix). This extracts the base name from the qualified name, e.g., "child" from "/parent/child".

func New

func New[T Instance](sm T, model *Model, maybeConfig ...Config) T

func QualifiedName

func QualifiedName(hsm Instance) string

QualifiedName returns the fully qualified name of a state machine instance. For nested state machines, this includes the parent path (e.g., "/parent/child"). For top-level state machines, this is typically just the name with a leading slash.

func Restart

func Restart(ctx context.Context, hsm Instance, maybeData ...any) <-chan struct{}

Restart stops a state machine and restarts it from the initial state. Optional data can be passed to reinitialize the state machine's data field. Returns a channel that closes when the restart completes.

func Set added in v1.0.3

func Set(ctx context.Context, hsm Instance, name string, value any) <-chan struct{}

Set updates an attribute value and emits an OnSet change event.

func Start

func Start[T Instance](ctx context.Context, sm T, maybeData ...any) T

func Started

func Started[T Instance](ctx context.Context, sm T, model *Model, maybeConfig ...Config) T

Started creates and starts a new state machine instance with the given model and configuration. The state machine will begin executing from its initial state.

Example:

model := hsm.Define(...)
sm := hsm.Started(context.Background(), &MyHSM{}, &model, hsm.Config{
    Trace: func(ctx context.Context, step string, data ...any) (context.Context, func(...any)) {
        log.Printf("Step: %s, Data: %v", step, data)
        return ctx, func(...any) {}
    },
    Id: "my-hsm-1",
})

func Stop

func Stop(ctx context.Context, hsm Instance) <-chan struct{}

Stop gracefully stops a state machine instance. It cancels any running activities and prevents further event processing.

Example:

sm := hsm.Start(...)
// ... use state machine ...
hsm.Stop(sm)

Types

type AttributeChange added in v1.0.3

type AttributeChange struct {
	Name string
	Old  any
	New  any
}

AttributeChange is the payload for attribute change events.

type CallData added in v1.0.3

type CallData struct {
	Name string
	Args []any
}

CallData is the payload for call events.

type Config

type Config struct {
	// ID is a unique identifier for the state machine instance.
	ID string
	// ActivityTimeout is the timeout for the state activity to terminate.
	ActivityTimeout time.Duration
	// Name is the name of the state machine.
	Name string
	// Data to be passed during initialization
	Data any
}

Config provides configuration options for state machine initialization.

type Element

type Element interface {
	Id() string
	Kind() uint64
	Owner() string
	QualifiedName() string
	Name() string
}

type Event

type Event struct {
	Kind   uint64 `xml:"kind,attr" json:"kind"`
	Name   string `xml:"name,attr" json:"name"`
	ID     string `xml:"id,attr" json:"id"`
	Source string `xml:"source,attr,omitempty" json:"source,omitempty"`
	Target string `xml:"target,attr,omitempty" json:"target,omitempty"`
	Data   any    `xml:"data" json:"data"`
	Schema any    `xml:"schema" json:"schema"`
}

func (Event) WithData

func (e Event) WithData(data any) Event

func (Event) WithDataAndID

func (e Event) WithDataAndID(data any, id string) Event

type EventDetail

type EventDetail struct {
	Event  string
	Target string
	Guard  bool
	Schema any
}

type Expression

type Expression[T Instance] func(ctx context.Context, hsm T, event Event) bool

Expression is a function type that evaluates a condition on a state machine. Expressions are used for transition guards to determine whether a transition should be taken. They receive the current context, state machine instance, and the triggering event, returning true if the condition is satisfied.

type HSM

type HSM struct {
	// contains filtered or unexported fields
}

type Instance

type Instance interface {
	// State returns the current state's qualified name.
	State() string
	Context() context.Context
	Get(name string) (any, bool)
	Set(ctx context.Context, name string, value any) <-chan struct{}
	Call(ctx context.Context, name string, args ...any) (any, error)
	// contains filtered or unexported methods
}

Instance represents an active state machine instance that can process events and track state. It provides methods for event dispatch and state management.

func FromContext

func FromContext(ctx context.Context) (Instance, bool)

FromContext retrieves a state machine instance from a context. Returns the instance and a boolean indicating whether it was found.

Example:

if sm, ok := hsm.FromContext(ctx); ok {
    log.Printf("Current state: %s", sm.State())
}

func InstancesFromContext

func InstancesFromContext(ctx context.Context) ([]Instance, bool)

InstancesFromContext retrieves all state machine instances from a context. Returns a slice of instances and a boolean indicating whether any were found. This is useful when multiple state machines share a context and you need to access or iterate over all of them.

type Model

type Model struct {

	// TransitionMap provides fast lookup of transitions by state and event name
	TransitionMap map[string]map[string][]*transition // stateQualifiedName -> eventName -> transitions
	// DeferredMap provides fast lookup of deferred events by state
	DeferredMap map[string]map[string]struct{} // stateQualifiedName -> Set<deferredEventNames>
	// contains filtered or unexported fields
}

Model represents the complete state machine model definition. It contains the root state and maintains a namespace of all elements.

func Define

func Define(name string, redefinableElements ...RedefinableElement) Model

Define creates a new state machine model with the given name and elements. The first argument can be either a string name or a RedefinableElement. Additional elements are added to the model in the order they are specified.

Example:

model := hsm.Define(
    "traffic_light",
    hsm.State("red"),
    hsm.State("yellow"),
    hsm.State("green"),
    hsm.Initial("red")
)

func (*Model) Activities

func (state *Model) Activities() []string

func (*Model) Entry

func (state *Model) Entry() []string

func (*Model) Exit

func (state *Model) Exit() []string

func (*Model) Members

func (model *Model) Members() map[string]Element

type Operation

type Operation[T Instance] func(ctx context.Context, hsm T, event Event)

Operation is a function type that performs an action on a state machine. Operations are used for state entry/exit behaviors, transition effects, and activity functions. They receive the current context, state machine instance, and the triggering event.

type RedefinableElement

type RedefinableElement = func(model *Model, stack []Element) Element

RedefinableElement is a function type that modifies a Model by adding or updating elements. It's used to build the state machine structure in a declarative way.

func Activity

func Activity[T Instance](funcs ...func(ctx context.Context, hsm T, event Event)) RedefinableElement

Activity defines a long-running action that is executed while in a state. The activity is started after the entry action and stopped before the exit action.

Example:

hsm.Activity(func(ctx context.Context, hsm *MyHSM, event Event) {
    for {
        select {
        case <-ctx.Done():
            return
        case <-time.After(time.Second):
            log.Println("Activity tick")
        }
    }
})

func After

func After[T Instance](expr func(ctx context.Context, hsm T, event Event) time.Duration) RedefinableElement

After creates a time-based transition that occurs after a specified duration. The duration can be dynamically computed based on the state machine's context.

Example:

hsm.Transition(
    hsm.After(func(ctx context.Context, hsm *MyHSM, event Event) time.Duration {
        return time.Second * 30
    }),
    hsm.Source("active"),
    hsm.Target("timeout")
)

func Attribute added in v1.0.3

func Attribute(name string, maybeDefault ...any) RedefinableElement

Attribute declares a model-level attribute with an optional default value. Attributes can be observed via OnSet("name") transitions and updated at runtime via Set / Instance.Set.

func Choice

func Choice[T interface{ RedefinableElement | string }](elementOrName T, partialElements ...RedefinableElement) RedefinableElement

Choice creates a pseudo-state that enables dynamic branching based on guard conditions. The first transition with a satisfied guard condition is taken.

Example:

hsm.Choice(
    hsm.Transition(
        hsm.Target("approved"),
        hsm.Guard(func(ctx context.Context, hsm *MyHSM, event Event) bool {
            return hsm.score > 700
        })
    ),
    hsm.Transition(
        hsm.Target("rejected")
    )
)

func DeepHistory added in v1.0.3

func DeepHistory[T interface{ RedefinableElement | string }](elementOrName T, partialElements ...RedefinableElement) RedefinableElement

DeepHistory creates a deep history pseudostate within a composite state. If no history is available, any transitions defined on this pseudostate are used; otherwise the parent state's initial is used.

func Defer

func Defer[T interface {
	string | *Event | Event
}](events ...T) RedefinableElement

Defer schedules events to be processed after the current state is exited.

Example:

hsm.Defer(hsm.Event{Name: "event_name"})

func Effect

func Effect[T Instance](funcs ...func(ctx context.Context, hsm T, event Event)) RedefinableElement

Effect defines an action to be executed during a transition. The effect function is called after exiting the source state and before entering the target state.

Example:

hsm.Effect(func(ctx context.Context, hsm *MyHSM, event Event) {
    log.Printf("Transitioning with event: %s", event.Name)
})

func Entry

func Entry[T Instance](funcs ...func(ctx context.Context, hsm T, event Event)) RedefinableElement

Entry defines an action to be executed when entering a state. The entry action is executed before any internal activities are started.

Example:

hsm.Entry(func(ctx context.Context, hsm *MyHSM, event Event) {
    log.Printf("Entering state with event: %s", event.Name)
})

func Every

func Every[T Instance](expr func(ctx context.Context, hsm T, event Event) time.Duration) RedefinableElement

Every schedules events to be processed on an interval.

Example:

hsm.Every(func(ctx context.Context, hsm T, event Event) time.Duration {
    return time.Second * 30
})

func Exit

func Exit[T Instance](funcs ...func(ctx context.Context, hsm T, event Event)) RedefinableElement

Exit defines an action to be executed when exiting a state. The exit action is executed after any internal activities are stopped.

Example:

hsm.Exit(func(ctx context.Context, hsm *MyHSM, event Event) {
    log.Printf("Exiting state with event: %s", event.Name)
})

func Final

func Final(name string) RedefinableElement

Final creates a final state that represents the completion of a composite state or the entire state machine. When a final state is entered, a completion event is generated.

Example:

hsm.State("process",
    hsm.State("working"),
    hsm.Final("done"),
    hsm.Transition(
        hsm.Source("working"),
        hsm.Target("done")
    )
)

func Guard

func Guard[T Instance](fn func(ctx context.Context, hsm T, event Event) bool) RedefinableElement

Guard defines a condition that must be true for a transition to be taken. If multiple transitions are possible, the first one with a satisfied guard is chosen.

Example:

hsm.Guard(func(ctx context.Context, hsm *MyHSM, event Event) bool {
    return hsm.counter > 10
})

func Initial

func Initial(partialElements ...RedefinableElement) RedefinableElement

Initial defines the initial state for a composite state or the entire state machine. When a composite state is entered, its initial state is automatically entered.

Example:

hsm.State("operational",
    hsm.State("idle"),
    hsm.State("running"),
    hsm.Initial("idle")
)

func On

func On[T interface{ *Event | Event }](events ...T) RedefinableElement

On defines the events that can cause a transition. Multiple events can be specified for a single transition.

Example:

hsm.Transition(
    hsm.On("start", "resume"),
    hsm.Source("idle"),
    hsm.Target("running")
)

func OnCall added in v1.0.3

func OnCall(name string) RedefinableElement

OnCall creates a trigger for Call() invocations of the named operation.

func OnSet added in v1.0.3

func OnSet(name string) RedefinableElement

OnSet creates an attribute-change trigger for the given attribute name. It is the attribute-based equivalent of On(...) and is driven by Set.

func Op added in v1.0.3

func Op(name string, fn any) RedefinableElement

Op is a shorthand for OperationDef.

func OperationDef added in v1.0.3

func OperationDef(name string, fn any) RedefinableElement

OperationDef declares a named callable for Call()/OnCall(). Supported callables include function values and method expressions.

func ShallowHistory added in v1.0.3

func ShallowHistory[T interface{ RedefinableElement | string }](elementOrName T, partialElements ...RedefinableElement) RedefinableElement

ShallowHistory creates a shallow history pseudostate within a composite state. If no history is available, any transitions defined on this pseudostate are used; otherwise the parent state's initial is used.

func Source

func Source[T interface{ RedefinableElement | string }](nameOrPartialElement T) RedefinableElement

Source specifies the source state of a transition. It can be used within a Transition definition.

Example:

hsm.Transition(
    hsm.Source("idle"),
    hsm.Target("running")
)

func State

func State(name string, partialElements ...RedefinableElement) RedefinableElement

State creates a new state element with the given name and optional child elements. States can have entry/exit actions, activities, and transitions.

Example:

hsm.State("active",
    hsm.Entry(func(ctx context.Context, hsm *MyHSM, event Event) {
        log.Println("Entering active state")
    }),
    hsm.Activity(func(ctx context.Context, hsm *MyHSM, event Event) {
        // Long-running activity
    }),
    hsm.Exit(func(ctx context.Context, hsm *MyHSM, event Event) {
        log.Println("Exiting active state")
    })
)

func Target

func Target[T interface{ RedefinableElement | string }](nameOrPartialElement T) RedefinableElement

Target specifies the target state of a transition. It can be used within a Transition definition.

Example:

hsm.Transition(
    hsm.Source("idle"),
    hsm.Target("running")
)

func Transition

func Transition[T interface{ RedefinableElement | string }](nameOrPartialElement T, partialElements ...RedefinableElement) RedefinableElement

Transition creates a new transition between states. Transitions can have triggers, guards, and effects.

Example:

hsm.Transition(
    hsm.Trigger("submit"),
    hsm.Source("draft"),
    hsm.Target("review"),
    hsm.Guard(func(ctx context.Context, hsm *MyHSM, event Event) bool {
        return hsm.IsValid()
    }),
    hsm.Effect(func(ctx context.Context, hsm *MyHSM, event Event) {
        log.Println("Transitioning from draft to review")
    })
)

func When

func When[T Instance](expr func(ctx context.Context, hsm T, event Event) <-chan struct{}) RedefinableElement

type Snapshot

type Snapshot struct {
	ID            string
	QualifiedName string
	State         string
	Attributes    map[string]any
	QueueLen      int
	Events        []EventDetail
}

func TakeSnapshot

func TakeSnapshot(ctx context.Context, hsm Instance) Snapshot

TakeSnapshot captures the current state of a state machine instance. The returned Snapshot contains the ID, qualified name, current state, data, and other attributes representing the instance at this moment. Useful for debugging, logging, or persisting state machine state.

Directories

Path Synopsis
kind module
muid module

Jump to

Keyboard shortcuts

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