fluo

package module
v1.0.0 Latest Latest
Warning

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

Go to latest
Published: Oct 4, 2025 License: MIT Imports: 9 Imported by: 0

README

Fluo - Hierarchical State Machine Library for Go

Fluo is a flexible hierarchical state machine library for Go. It features a fluent builder for creating statecharts with atomic, composite, and parallel states, along with comprehensive support for UML pseudostates.

Key Features

  • Hierarchical State Machines: Atomic, composite, and parallel states
  • Fluent Builder API: Method chaining for state machine construction
  • Thread Safe: Concurrent-safe operations with internal synchronization
  • Observer Pattern: Monitor transitions and state changes
  • Visualization: DOT and SVG generation for state machine diagrams
  • Zero Dependencies: No external dependencies required (Graphviz optional for SVG)

Installation

go get github.com/anggasct/fluo

Requirements:

  • Go 1.21+

Quick Start

package main

import (
    "fmt"
    "github.com/anggasct/fluo"
)

func main() {
    // Build state machine
    definition := fluo.NewMachine().
        State("red").Initial().
            To("green").On("timer").
        State("green").
            To("yellow").On("timer").
        State("yellow").
            To("red").On("timer").
        Build()

    // Create and start machine
    machine := definition.CreateInstance()
    machine.Start()
    
    // Send events
    machine.SendEvent("timer", nil) // red -> green
    machine.SendEvent("timer", nil) // green -> yellow  
    machine.SendEvent("timer", nil) // yellow -> red
    
    fmt.Printf("Current state: %s\n", machine.CurrentState())
}

Core Concepts

MachineDefinition vs Machine
  • MachineDefinition: Immutable configuration created by the builder
  • Machine: Runtime instance with current state, context, and observers
// Build definition (immutable)
definition := fluo.NewMachine().
    State("idle").Initial().
        To("working").On("start").
    Build()

// Create runtime instances (can have multiple)
machine1 := definition.CreateInstance()
machine2 := definition.CreateInstance()
Context and Events

Context carries machine state, event metadata, and user data:

// Send event with data
machine.SendEvent("process", map[string]interface{}{
    "input": "data",
    "priority": 1,
})

// Access context in actions
.To("completed").On("finish").Do(func(ctx fluo.Context) error {
    if data, exists := ctx.Get("input"); exists {
        fmt.Printf("Processing: %v\n", data)
    }
    return nil
})

State Types and Examples

Element Description Use Case
AtomicState Simple state with no substates Basic workflow steps
CompositeState Hierarchical state with substates Complex nested behaviors
ParallelState Concurrent regions executing simultaneously Parallel processing, multi-tasking
FinalState Marks completion of a state or region Workflow termination, region completion
ChoiceState Dynamic conditional branching Runtime decision points
JunctionState Static merge point for transitions Multiple path convergence
ForkState Split execution into parallel states Concurrent workflow initiation
JoinState Synchronize parallel execution paths Barrier synchronization
HistoryState Remember last state at current level Resume interrupted workflows
DeepHistoryState Remember complete state hierarchy Restore nested state configurations
Atomic State

Simple state with no substates:

builder.State("idle").Initial().
    OnEntry(func(ctx fluo.Context) error {
        fmt.Println("Entered idle state")
        return nil
    }).
    To("working").On("start")
Composite State

Hierarchical state containing substates:

composite := builder.CompositeState("order_processing")

composite.State("validation").Initial().
    OnEntry(func(ctx fluo.Context) error {
        fmt.Println("Validating order")
        return nil
    }).
    To("payment").On("valid")

composite.State("payment").
    To("shipping").On("paid")

composite.State("shipping").
    To("complete").On("delivered")

composite.State("complete").Final()

// The composite state itself can have transitions
builder.CompositeState("order_processing").
    To("canceled").On("cancel")  // Can exit from any substate
Parallel State

Concurrent regions executing simultaneously:

parallel := builder.ParallelState("parallel_work")

taskA := parallel.Region("task_a")
taskA.State("start").Initial().
    To("done").On("a_complete")
taskA.State("done").Final()

taskB := parallel.Region("task_b")
taskB.State("start").Initial().
    To("done").On("b_complete")
taskB.State("done").Final()

parallel.End()

// Transition when all regions complete
builder.ParallelState("parallel_work").
    To("next_state").OnCompletion()
Choice Pseudostate

Dynamic conditional branching:

builder.Choice("payment_router").
    When(func(ctx fluo.Context) bool {
        if amount, exists := ctx.Get("amount"); exists {
            if amt, ok := amount.(int); ok {
                return amt < 100
            }
        }
        return false
    }).To("fast_payment").
    When(func(ctx fluo.Context) bool {
        if amount, exists := ctx.Get("amount"); exists {
            if amt, ok := amount.(int); ok {
                return amt >= 100
            }
        }
        return false
    }).To("secure_payment")
Final State

Mark states as final to indicate completion:

builder.State("processing").
    OnEntry(func(ctx fluo.Context) error {
        fmt.Println("Processing data")
        return nil
    }).
    To("completed").On("finish")

builder.State("completed").Final().
    OnEntry(func(ctx fluo.Context) error {
        fmt.Println("Process completed")
        return nil
    })

// In parallel regions, final states trigger OnCompletion
region.State("task_done").Final()
Junction Pseudostate

Static merge point for multiple transitions:

// Multiple paths converge at junction
builder.State("path1").
    To("merge_point").On("complete")

builder.State("path2").
    To("merge_point").On("complete")

builder.State("path3").
    To("merge_point").On("complete")

builder.Junction("merge_point").
    To("consolidated_result").
    Do(func(ctx fluo.Context) error {
        fmt.Println("Merging results from multiple paths")
        return nil
    })

builder.State("consolidated_result")
Fork and Join Pseudostates

Split and synchronize parallel execution:

builder.State("start").
    To("fork_parallel").On("begin")

// Fork splits execution to multiple states simultaneously
builder.Fork("fork_parallel").
    To("task1", "task2", "task3").
    Do(func(ctx fluo.Context) error {
        fmt.Println("Starting parallel tasks")
        return nil
    })

builder.State("task1").
    To("join_tasks").On("done")

builder.State("task2").
    To("join_tasks").On("done")

builder.State("task3").
    To("join_tasks").On("done")

// Join waits for all source states before proceeding
builder.Join("join_tasks").
    From("task1", "task2", "task3").
    To("all_complete").
    Do(func(ctx fluo.Context) error {
        fmt.Println("All parallel tasks completed")
        return nil
    })

builder.State("all_complete").Final()
History State

Shallow history - remember last state at current level:

composite := builder.CompositeState("workflow")

composite.State("step1").Initial().
    To("step2").On("next")

composite.State("step2").
    To("step3").On("next")

composite.State("step3")

// Shallow history remembers the last active substate
composite.History("memory").Default("step1")

// Can interrupt and resume workflow
builder.CompositeState("workflow").
    To("paused").On("pause")

builder.State("paused").
    To("workflow.memory").On("resume")  // Returns to last active state
Deep History State

Deep history - remember state including nested substates:

outer := builder.CompositeState("multi_level")

nested := outer.CompositeState("nested")
nested.State("sub1").Initial().
    To("sub2").On("next")
nested.State("sub2")

outer.State("other_state")

// Deep history remembers state at all nesting levels
outer.DeepHistory("deep_memory").Default("nested.sub1")

builder.CompositeState("multi_level").
    To("suspended").On("suspend")

builder.State("suspended").
    To("multi_level.deep_memory").On("restore")  // Restores complete state hierarchy

Observer Pattern

Monitor state machine lifecycle events:

type DebugObserver struct {
    fluo.BaseObserver
}

func (o *DebugObserver) OnTransition(from, to string, event fluo.Event, ctx fluo.Context) {
    fmt.Printf("Transition: %s -> %s (event: %s)\n", from, to, event.GetName())
}

func (o *DebugObserver) OnStateEnter(state string, ctx fluo.Context) {
    fmt.Printf("Entering state: %s\n", state)
}

func (o *DebugObserver) OnStateExit(state string, ctx fluo.Context) {
    fmt.Printf("Exiting state: %s\n", state)
}

// Add observer to machine
machine := definition.CreateInstance()
machine.AddObserver(&DebugObserver{})
Extended Observer

For more comprehensive monitoring:

type ExtendedObserver struct {
    fluo.BaseObserver
}

func (o *ExtendedObserver) OnGuardEvaluation(from, to string, event fluo.Event, result bool, ctx fluo.Context) {
    fmt.Printf("Guard %s -> %s: %v\n", from, to, result)
}

func (o *ExtendedObserver) OnEventRejected(event fluo.Event, reason string, ctx fluo.Context) {
    fmt.Printf("Event rejected: %s (%s)\n", event.GetName(), reason)
}

func (o *ExtendedObserver) OnError(err error, ctx fluo.Context) {
    fmt.Printf("Error: %v\n", err)
}

func (o *ExtendedObserver) OnActionExecution(actionType, state string, event fluo.Event, ctx fluo.Context) {
    fmt.Printf("Action '%s' in state '%s'\n", actionType, state)
}

Visualization

Generate DOT and SVG diagrams of your state machines:

import "github.com/anggasct/fluo/visualization"

// Create DOT generator
dotGen := visualization.NewDOTGenerator(definition)

// Generate DOT format
dotContent, err := dotGen.Generate()
if err != nil {
    panic(err)
}
fmt.Println(dotContent)

// Generate SVG (requires Graphviz)
svgGen := visualization.NewSVGGenerator(definition)
svgContent, err := svgGen.Generate()
if err != nil {
    panic(err)
}
fmt.Println(svgContent)

// Save to file
err = dotGen.GenerateToFile("machine.dot")
if err != nil {
    panic(err)
}
Custom Visualization Options
options := visualization.DefaultDOTOptions()
options.ShowGuardConditions = true
options.ShowActions = true
options.CompactMode = false
options.RankDirection = "LR"  // Left to right
options.NodeShape = "ellipse"
options.CompositeStateStyle = "rounded,filled"

dotGen := visualization.NewDOTGenerator(definition, options)

Concurrency and Thread Safety

Fluo provides thread-safe operations with internal synchronization:

// Safe to call from multiple goroutines
go func() {
    machine.SendEvent("event1", data)
}()

go func() {
    machine.SendEvent("event2", data)
}()

// Query current state safely
currentState := machine.CurrentState()
activeStates := machine.GetActiveStates()
Parallel State Execution

Parallel states execute concurrently with proper synchronization:

// Parallel regions run simultaneously
parallel := builder.ParallelState("data_processing")

region1 := parallel.Region("validation")
region1.State("validate").Initial().
    To("validated").On("complete")

region2 := parallel.Region("transformation")
region2.State("transform").Initial().
    To("transformed").On("complete")

// Both regions execute in parallel
// Transition occurs when both reach final states
parallel.To("next_phase").OnCompletion()

Examples

The project includes several comprehensive examples:

  • Traffic Light (examples/traffic-light/) - Basic state machine with composite states
  • Document Approval (examples/document-approval/) - Complex workflow with parallel states and choice logic
  • Order Pipeline (examples/order-pipeline/) - Business process with fork/join patterns
  • Smart Home (examples/smart-home/) - IoT device control with hierarchical states

Run examples:

# Run traffic light example
cd examples/traffic-light
go run main.go

# Run document approval example
cd examples/document-approval
go run main.go

# Run order pipeline example
cd examples/order-pipeline
go run main.go

# Run smart home example
cd examples/smart-home
go run main.go

API Reference

Core Interfaces
Machine
type Machine interface {
    Start() error
    Stop() error
    Reset() error
    
    CurrentState() string
    SetState(state string) error
    SetRegionState(regionID string, stateID string) error
    RegionState(regionID string) string
    GetStateHierarchy() []string
    IsInState(stateID string) bool
    GetActiveStates() []string
    IsStateActive(stateID string) bool
    GetParallelRegions() map[string][]string
    
    SendEvent(eventName string, eventData any) *EventResult
    SendEventWithContext(ctx context.Context, eventName string, eventData any) *EventResult
    HandleEvent(eventName string, eventData any) *EventResult
    HandleEventWithContext(ctx context.Context, eventName string, eventData any) *EventResult
    
    AddObserver(observer Observer)
    RemoveObserver(observer Observer)
    
    Context() Context
    WithContext(ctx Context) Machine
    
    MarshalJSON() ([]byte, error)
    UnmarshalJSON(data []byte) error
}
MachineDefinition
type MachineDefinition interface {
    CreateInstance() Machine
    Build() MachineDefinition
    
    GetInitialState() string
    GetStates() map[string]State
    GetTransitions() map[string][]Transition
}
Observer
type Observer interface {
    OnTransition(from string, to string, event Event, ctx Context)
    OnStateEnter(state string, ctx Context)
}

type ExtendedObserver interface {
    Observer
    OnStateExit(state string, ctx Context)
    OnGuardEvaluation(from string, to string, event Event, result bool, ctx Context)
    OnEventRejected(event Event, reason string, ctx Context)
    OnError(err error, ctx Context)
    OnActionExecution(actionType string, state string, event Event, ctx Context)
    OnMachineStarted(ctx Context)
    OnMachineStopped(ctx Context)
}

Testing

Test your state machines with the provided utilities:

func TestStateMachine(t *testing.T) {
    definition := BuildTestMachine()
    machine := definition.CreateInstance()
    
    // Start machine
    err := machine.Start()
    assert.NoError(t, err)
    assert.Equal(t, "initial", machine.CurrentState())
    
    // Send event and verify transition
    result := machine.SendEvent("test", nil)
    assert.True(t, result.Success())
    assert.Equal(t, "next", machine.CurrentState())
}

Development

Build Commands
# Build the library
make build

# Run tests
make test

# Run tests with coverage
make test-coverage

# Clean build artifacts
make clean

# Lint the code
make lint

# Format code
make fmt

# Vet code
make vet

# Install dependencies
make deps

# Run all checks
make check
Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

Reporting Issues

When reporting issues, please include:

  • Go version
  • Operating system
  • Minimal code example that reproduces the issue
  • Expected vs actual behavior

License

MIT License - see LICENSE file.

Documentation

Index

Constants

This section is empty.

Variables

View Source
var TestActionCalled bool

Test action functions for testing

View Source
var TestActionError error
View Source
var TestGuardResult bool

Test guard functions for testing

Functions

func AssertContextValue

func AssertContextValue(t *testing.T, ctx Context, key string, expected interface{})

AssertContextValue checks if context contains expected value

func AssertEventProcessed

func AssertEventProcessed(t *testing.T, result *EventResult, shouldProcess bool)

AssertEventProcessed checks if event was processed successfully

func AssertGuardEvaluationCount

func AssertGuardEvaluationCount(t *testing.T, count int, expected int)

AssertGuardEvaluationCount checks if guard was evaluated expected number of times

func AssertObserverCalled

func AssertObserverCalled(t *testing.T, observer *TestObserver, transitions, enters, exits int)

AssertObserverCalled checks if observer methods were called expected number of times

func AssertState

func AssertState(t *testing.T, machine Machine, expectedState string)

AssertState checks if machine is in expected state

func AssertStateChanged

func AssertStateChanged(t *testing.T, result *EventResult, expectedPrevious, expectedCurrent string)

AssertStateChanged checks if state transition occurred

func AssertTransitionSequence

func AssertTransitionSequence(t *testing.T, machine Machine, expectedStates []string)

AssertTransitionSequence checks if machine followed expected state sequence

func ConcurrentEventSender

func ConcurrentEventSender(machine Machine, eventName string, count int, done chan bool)

ConcurrentEventSender sends events concurrently for testing thread safety

func ConcurrentStateChecker

func ConcurrentStateChecker(machine Machine, checks int, results chan string)

ConcurrentStateChecker checks states concurrently for testing thread safety

func IsActionError

func IsActionError(err error) bool

IsActionError checks if an error is an ActionError

func IsConfigurationError

func IsConfigurationError(err error) bool

IsConfigurationError checks if an error is a ConfigurationError

func IsGuardError

func IsGuardError(err error) bool

IsGuardError checks if an error is a GuardError

func IsMachineError

func IsMachineError(err error) bool

IsMachineError checks if an error is a MachineError

func IsStateError

func IsStateError(err error) bool

IsStateError checks if an error is a StateError

func IsTransitionError

func IsTransitionError(err error) bool

IsTransitionError checks if an error is a TransitionError

func ResetTestAction

func ResetTestAction()

func SetTestGuard

func SetTestGuard(result bool)

func TestAction

func TestAction(ctx Context) error

func TestGuard

func TestGuard(ctx Context) bool

Types

type ActionError

type ActionError struct {
	Action      string
	State       string
	OriginalErr error
}

ActionError represents action execution errors

func NewActionError

func NewActionError(action, state string, err error) *ActionError

NewActionError creates a new action execution error

func (*ActionError) Error

func (e *ActionError) Error() string

func (*ActionError) Unwrap

func (e *ActionError) Unwrap() error

type ActionEvent

type ActionEvent struct {
	ActionType string
	State      string
	Event      Event
	Ctx        Context
}

type ActionFunc

type ActionFunc func(ctx Context) error

ActionFunc represents an enhanced action function with error support

type AtomicState

type AtomicState interface {
	State
}

AtomicState represents a simple state

type AtomicStateImpl

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

AtomicStateImpl implements the AtomicState interface

func NewAtomicState

func NewAtomicState(id string) *AtomicStateImpl

NewAtomicState creates a new atomic state

func NewFinalState

func NewFinalState(id string) *AtomicStateImpl

NewFinalState creates a new final state

func (*AtomicStateImpl) Enter

func (s *AtomicStateImpl) Enter(ctx Context)

Enter executes the entry action

func (*AtomicStateImpl) Exit

func (s *AtomicStateImpl) Exit(ctx Context)

Exit executes the exit action

func (*AtomicStateImpl) ID

func (s *AtomicStateImpl) ID() string

ID returns the state identifier

func (*AtomicStateImpl) IsComposite

func (s *AtomicStateImpl) IsComposite() bool

IsComposite returns false for atomic states

func (*AtomicStateImpl) IsFinal

func (s *AtomicStateImpl) IsFinal() bool

IsFinal returns whether this is a final state

func (*AtomicStateImpl) IsParallel

func (s *AtomicStateImpl) IsParallel() bool

IsParallel returns false for atomic states

func (*AtomicStateImpl) IsPseudo

func (s *AtomicStateImpl) IsPseudo() bool

IsPseudo returns false for atomic states

func (*AtomicStateImpl) Parent

func (s *AtomicStateImpl) Parent() State

Parent returns the parent state

func (*AtomicStateImpl) WithEntryAction

func (s *AtomicStateImpl) WithEntryAction(action ActionFunc) *AtomicStateImpl

WithEntryAction sets the entry action for the state

func (*AtomicStateImpl) WithExitAction

func (s *AtomicStateImpl) WithExitAction(action ActionFunc) *AtomicStateImpl

WithExitAction sets the exit action for the state

func (*AtomicStateImpl) WithParent

func (s *AtomicStateImpl) WithParent(parent State) *AtomicStateImpl

WithParent sets the parent state

type BaseEvent

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

BaseEvent provides a basic implementation of the Event interface

func (*BaseEvent) GetData

func (e *BaseEvent) GetData() any

GetData returns the event data

func (*BaseEvent) GetMetadata

func (e *BaseEvent) GetMetadata() map[string]any

GetMetadata returns the event metadata

func (*BaseEvent) GetName

func (e *BaseEvent) GetName() string

GetName returns the event name

func (*BaseEvent) GetTimestamp

func (e *BaseEvent) GetTimestamp() time.Time

GetTimestamp returns the event timestamp

type BaseObserver

type BaseObserver struct{}

BaseObserver provides a default implementation with no-op methods

func (*BaseObserver) OnActionExecution

func (o *BaseObserver) OnActionExecution(actionType string, state string, event Event, ctx Context)

OnActionExecution implements the optional ExtendedObserver method

func (*BaseObserver) OnError

func (o *BaseObserver) OnError(err error, ctx Context)

OnError implements the optional ExtendedObserver method

func (*BaseObserver) OnEventRejected

func (o *BaseObserver) OnEventRejected(event Event, reason string, ctx Context)

OnEventRejected implements the optional ExtendedObserver method

func (*BaseObserver) OnGuardEvaluation

func (o *BaseObserver) OnGuardEvaluation(from string, to string, event Event, result bool, ctx Context)

OnGuardEvaluation implements the optional ExtendedObserver method

func (*BaseObserver) OnMachineStarted

func (o *BaseObserver) OnMachineStarted(ctx Context)

OnMachineStarted implements the optional ExtendedObserver method

func (*BaseObserver) OnMachineStopped

func (o *BaseObserver) OnMachineStopped(ctx Context)

OnMachineStopped implements the optional ExtendedObserver method

func (*BaseObserver) OnStateEnter

func (o *BaseObserver) OnStateEnter(state string, ctx Context)

OnStateEnter implements the required Observer method

func (*BaseObserver) OnStateExit

func (o *BaseObserver) OnStateExit(state string, ctx Context)

OnStateExit implements the optional ExtendedObserver method

func (*BaseObserver) OnTransition

func (o *BaseObserver) OnTransition(from string, to string, event Event, ctx Context)

OnTransition implements the required Observer method

type ChoiceBuilder

type ChoiceBuilder interface {
	When(condition GuardFunc) ChoiceTransitionBuilder
	Otherwise(target string) ChoiceBuilder
	Do(action ActionFunc) ChoiceBuilder
	OnEntry(action ActionFunc) ChoiceBuilder

	// Navigation back
	State(id string) StateBuilder
	Build() MachineDefinition
}

ChoiceBuilder handles choice pseudostate with conditions

type ChoiceCondition

type ChoiceCondition struct {
	// Guard condition for this choice branch
	Guard GuardFunc
	// Target state for this choice branch
	Target string
	// Action to execute for this specific branch
	Action ActionFunc
}

ChoiceCondition represents a condition and target for a choice pseudostate

type ChoiceTransitionBuilder

type ChoiceTransitionBuilder interface {
	To(target string) ChoiceBuilder
	Do(action ActionFunc) ChoiceTransitionBuilder
}

ChoiceTransitionBuilder handles conditional transitions from choice

type CompositeState

type CompositeState interface {
	State
	InitialState() State
	Substates() []State
	AddSubstate(state State)
}

CompositeState represents a state with substates

type CompositeStateBuilder

type CompositeStateBuilder interface {
	// Child states
	State(id string) StateBuilder
	CompositeState(id string) CompositeStateBuilder

	// Child pseudostates
	Choice(id string) ChoiceBuilder
	Junction(id string) JunctionBuilder
	Fork(id string) ForkBuilder
	Join(id string) JoinBuilder
	History(id string) HistoryBuilder
	DeepHistory(id string) HistoryBuilder

	// State actions
	OnEntry(action ActionFunc) CompositeStateBuilder
	OnExit(action ActionFunc) CompositeStateBuilder

	// Transitions from this composite state
	To(target string) TransitionBuilder
	ToParent(target string) TransitionBuilder

	// Navigation back to parent
	End() MachineBuilder
	Build() MachineDefinition
}

CompositeStateBuilder handles hierarchical states

type CompositeStateImpl

type CompositeStateImpl struct {
	AtomicStateImpl
	// contains filtered or unexported fields
}

CompositeStateImpl implements the CompositeState interface

func NewCompositeState

func NewCompositeState(id string) *CompositeStateImpl

NewCompositeState creates a new composite state

func (*CompositeStateImpl) AddSubstate

func (s *CompositeStateImpl) AddSubstate(state State)

AddSubstate adds a substate to the composite state

func (*CompositeStateImpl) InitialState

func (s *CompositeStateImpl) InitialState() State

InitialState returns the initial substate

func (*CompositeStateImpl) IsComposite

func (s *CompositeStateImpl) IsComposite() bool

IsComposite returns true for composite states

func (*CompositeStateImpl) Substates

func (s *CompositeStateImpl) Substates() []State

Substates returns all substates

func (*CompositeStateImpl) WithInitialState

func (s *CompositeStateImpl) WithInitialState(state State) *CompositeStateImpl

WithInitialState sets the initial substate

func (*CompositeStateImpl) WithParent

func (s *CompositeStateImpl) WithParent(parent State) *CompositeStateImpl

WithParent sets the parent state

type ConfigurationError

type ConfigurationError struct {
	Component string
	Issue     string
}

ConfigurationError represents machine configuration issues

func NewConfigurationError

func NewConfigurationError(component, issue string) *ConfigurationError

NewConfigurationError creates a new configuration error

func (*ConfigurationError) Error

func (e *ConfigurationError) Error() string

type Context

type Context interface {
	context.Context

	Get(key string) (any, bool)
	Set(key string, value any)
	GetAll() map[string]any

	GetMachine() Machine
	GetCurrentState() string
	GetSourceState() string
	GetTargetState() string

	GetCurrentEvent() Event
	GetEventName() string
	GetEventData() any
	GetEventDataAs(target any) bool

	GetPreviousState() string

	WithValue(key string, value any) Context
	Fork() Context
}

Context provides access to data and information during state machine execution

func CreateTestContext

func CreateTestContext() Context

CreateTestContext creates a simple test context

func NewContext

func NewContext(parent context.Context, machine Machine) Context

NewContext creates a new state machine context

func NewSimpleContext

func NewSimpleContext() Context

NewSimpleContext creates a simple context for testing

type ContextEvent

type ContextEvent struct {
	Ctx Context
}

type ErrorCode

type ErrorCode int

ErrorCode represents specific error conditions in the state machine

const (
	// No error occurred
	ErrCodeNone ErrorCode = iota
	// State was not found in the machine
	ErrCodeStateNotFound
	// Transition is not allowed from current state
	ErrCodeTransitionNotAllowed
	// Guard condition rejected the transition
	ErrCodeGuardRejected
	// Event is invalid for current context
	ErrCodeInvalidEvent
	// Machine is not in started state
	ErrCodeMachineNotStarted
	// Action execution failed
	ErrCodeActionFailed
	// Machine configuration is invalid
	ErrCodeInvalidConfiguration
	// State is in invalid condition
	ErrCodeInvalidState
	// Concurrent modification detected
	ErrCodeConcurrentModification
)

func GetErrorCode

func GetErrorCode(err error) ErrorCode

GetErrorCode returns the error code for known error types

type ErrorEvent

type ErrorEvent struct {
	Error error
	Ctx   Context
}

type Event

type Event interface {
	GetName() string
	GetData() any
	GetTimestamp() time.Time
	GetMetadata() map[string]any
}

Event represents a trigger for transitions in the state machine

func CreateTestEvent

func CreateTestEvent(name string, data any) Event

CreateTestEvent creates a test event

func NewEvent

func NewEvent(name string, data any) Event

NewEvent creates a new basic event

func NewEventWithMetadata

func NewEventWithMetadata(name string, data any, metadata map[string]any) Event

NewEventWithMetadata creates a new event with metadata

func NewTypedEvent

func NewTypedEvent(name string, data any) Event

NewTypedEvent creates a new event with typed data

type EventRejectEvent

type EventRejectEvent struct {
	Event  Event
	Reason string
	Ctx    Context
}

type EventResult

type EventResult struct {
	Processed       bool
	StateChanged    bool
	PreviousState   string
	CurrentState    string
	Error           error
	RejectionReason string
}

EventResult represents the result of processing an event

func NewEventResult

func NewEventResult(processed, stateChanged bool, prevState, currentState string) *EventResult

NewEventResult creates a new event result

func (*EventResult) Success

func (r *EventResult) Success() bool

Success returns true if the event was processed successfully

func (*EventResult) WithError

func (r *EventResult) WithError(err error) *EventResult

WithError adds an error to the event result

func (*EventResult) WithRejection

func (r *EventResult) WithRejection(reason string) *EventResult

WithRejection adds a rejection reason to the event result

type ExtendedObserver

type ExtendedObserver interface {
	Observer

	// OnStateExit is called when exiting a state
	OnStateExit(state string, ctx Context)

	// OnGuardEvaluation is called when a guard condition is evaluated
	OnGuardEvaluation(from string, to string, event Event, result bool, ctx Context)

	// OnEventRejected is called when an event is rejected (no valid transition)
	OnEventRejected(event Event, reason string, ctx Context)

	// OnError is called when an error occurs during processing
	OnError(err error, ctx Context)

	// OnActionExecution is called when an action is executed
	OnActionExecution(actionType string, state string, event Event, ctx Context)

	// OnMachineStarted is called when the state machine starts
	OnMachineStarted(ctx Context)

	// OnMachineStopped is called when the state machine stops
	OnMachineStopped(ctx Context)
}

ExtendedObserver provides additional optional observation methods

type ForkBuilder

type ForkBuilder interface {
	To(targets ...string) ForkBuilder
	Do(action ActionFunc) ForkBuilder
	OnEntry(action ActionFunc) ForkBuilder

	// Navigation back
	State(id string) StateBuilder
	Build() MachineDefinition
}

ForkBuilder handles splitting to parallel targets

type GuardError

type GuardError struct {
	From  string
	To    string
	Event string
	Guard string
}

GuardError represents guard condition failures

func NewGuardRejectedError

func NewGuardRejectedError(from, to, event string, guardName string) *GuardError

NewGuardRejectedError creates a new guard rejected error

func (*GuardError) Error

func (e *GuardError) Error() string

type GuardEvent

type GuardEvent struct {
	From   string
	To     string
	Event  Event
	Result bool
	Ctx    Context
}

type GuardFunc

type GuardFunc func(ctx Context) bool

GuardFunc represents a guard condition function

type HistoryBuilder

type HistoryBuilder interface {
	Default(target string) HistoryBuilder
	Do(action ActionFunc) HistoryBuilder
	OnEntry(action ActionFunc) HistoryBuilder

	// Navigation back
	State(id string) StateBuilder
	Build() MachineDefinition
}

HistoryBuilder handles history pseudostates

type JoinBuilder

type JoinBuilder interface {
	From(sources ...string) JoinBuilder
	To(target string) JoinBuilder
	Do(action ActionFunc) JoinBuilder
	OnEntry(action ActionFunc) JoinBuilder

	// Navigation back
	State(id string) StateBuilder
	Build() MachineDefinition
}

JoinBuilder handles synchronization from multiple sources

type JunctionBuilder

type JunctionBuilder interface {
	To(target string) JunctionBuilder
	Do(action ActionFunc) JunctionBuilder
	OnEntry(action ActionFunc) JunctionBuilder

	// Navigation back
	State(id string) StateBuilder
	Build() MachineDefinition
}

JunctionBuilder handles simple merge points

type Machine

type Machine interface {
	Start() error
	Stop() error
	Reset() error

	CurrentState() string
	SetState(state string) error

	SetRegionState(regionID string, stateID string) error
	RegionState(regionID string) string
	GetStateHierarchy() []string
	IsInState(stateID string) bool
	GetActiveStates() []string
	IsStateActive(stateID string) bool
	GetParallelRegions() map[string][]string

	SendEvent(eventName string, eventData any) *EventResult
	SendEventWithContext(ctx context.Context, eventName string, eventData any) *EventResult
	HandleEvent(eventName string, eventData any) *EventResult
	HandleEventWithContext(ctx context.Context, eventName string, eventData any) *EventResult

	AddObserver(observer Observer)
	RemoveObserver(observer Observer)

	Context() Context
	WithContext(ctx Context) Machine

	MarshalJSON() ([]byte, error)
	UnmarshalJSON(data []byte) error
}

Machine represents a state machine instance

func CreateEdgeCaseMachine

func CreateEdgeCaseMachine() Machine

CreateEdgeCaseMachine creates a machine configured for edge case testing

func CreateHierarchicalMachine

func CreateHierarchicalMachine() Machine

CreateHierarchicalMachine creates a hierarchical state machine for testing

func CreateParallelMachine

func CreateParallelMachine() Machine

CreateParallelMachine creates a parallel state machine for testing

func CreatePseudostateMachine

func CreatePseudostateMachine() Machine

CreatePseudostateMachine creates a machine with pseudostates for testing

func CreateSimpleMachine

func CreateSimpleMachine() Machine

CreateSimpleMachine creates a basic state machine for testing

type MachineBuilder

type MachineBuilder interface {
	State(id string) StateBuilder
	CompositeState(id string) CompositeStateBuilder
	ParallelState(id string) ParallelStateBuilder

	Choice(id string) ChoiceBuilder
	Junction(id string) JunctionBuilder
	Fork(id string) ForkBuilder
	Join(id string) JoinBuilder
	History(id string) HistoryBuilder
	DeepHistory(id string) HistoryBuilder

	Build() MachineDefinition
}

MachineBuilder provides the main entry point for building state machines

func NewMachine

func NewMachine() MachineBuilder

NewMachine creates a new machine builder with the new fluent API

func NewMachineDefinition

func NewMachineDefinition() MachineBuilder

NewMachineDefinition creates a new machine definition builder

type MachineDefinition

type MachineDefinition interface {
	CreateInstance() Machine
	Build() MachineDefinition

	GetInitialState() string
	GetStates() map[string]State
	GetTransitions() map[string][]Transition
}

MachineDefinition represents the configuration of a state machine

type MachineError

type MachineError struct {
	Code      ErrorCode
	Operation string
	Message   string
}

MachineError represents state machine operation errors

func NewMachineError

func NewMachineError(code ErrorCode, operation string, message string) *MachineError

NewMachineError creates a new machine error

func NewMachineNotStartedError

func NewMachineNotStartedError(operation string) *MachineError

NewMachineNotStartedError creates a new machine not started error

func (*MachineError) Error

func (e *MachineError) Error() string

type MachineState

type MachineState int

MachineState represents the current state of the machine

const (
	// Machine is stopped and not processing events
	MachineStateStopped MachineState = iota
	// Machine is running and processing events
	MachineStateStarted
	// Machine is in error state
	MachineStateError
)

type Observer

type Observer interface {

	// OnTransition is called when a state transition occurs
	OnTransition(from string, to string, event Event, ctx Context)

	// OnStateEnter is called when entering a new state
	OnStateEnter(state string, ctx Context)
}

Observer represents an entity that observes state machine lifecycle

type ObserverManager

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

ObserverManager manages a collection of observers

func NewObserverManager

func NewObserverManager() *ObserverManager

NewObserverManager creates a new observer manager

func (*ObserverManager) AddObserver

func (om *ObserverManager) AddObserver(observer Observer)

AddObserver adds an observer to the manager

func (*ObserverManager) NotifyActionExecution

func (om *ObserverManager) NotifyActionExecution(actionType string, state string, event Event, ctx Context)

NotifyActionExecution notifies all observers of action execution

func (*ObserverManager) NotifyError

func (om *ObserverManager) NotifyError(err error, ctx Context)

NotifyError notifies all observers of errors

func (*ObserverManager) NotifyEventRejected

func (om *ObserverManager) NotifyEventRejected(event Event, reason string, ctx Context)

NotifyEventRejected notifies all observers of event rejection

func (*ObserverManager) NotifyGuardEvaluation

func (om *ObserverManager) NotifyGuardEvaluation(from string, to string, event Event, result bool, ctx Context)

NotifyGuardEvaluation notifies all observers of guard evaluation

func (*ObserverManager) NotifyMachineStarted

func (om *ObserverManager) NotifyMachineStarted(ctx Context)

NotifyMachineStarted notifies all observers that the machine has started

func (*ObserverManager) NotifyMachineStopped

func (om *ObserverManager) NotifyMachineStopped(ctx Context)

NotifyMachineStopped notifies all observers that the machine has stopped

func (*ObserverManager) NotifyStateEnter

func (om *ObserverManager) NotifyStateEnter(state string, ctx Context)

NotifyStateEnter notifies all observers of state entry

func (*ObserverManager) NotifyStateExit

func (om *ObserverManager) NotifyStateExit(state string, ctx Context)

NotifyStateExit notifies all observers of state exit

func (*ObserverManager) NotifyTransition

func (om *ObserverManager) NotifyTransition(from string, to string, event Event, ctx Context)

NotifyTransition notifies all observers of a state transition

func (*ObserverManager) RemoveObserver

func (om *ObserverManager) RemoveObserver(observer Observer)

RemoveObserver removes an observer from the manager

type ParallelState

type ParallelState interface {
	CompositeState
	Regions() []Region
	AddRegion(region Region)
}

ParallelState represents a parallel composite state

type ParallelStateBuilder

type ParallelStateBuilder interface {
	// Regions
	Region(id string) RegionBuilder

	// State actions
	OnEntry(action ActionFunc) ParallelStateBuilder
	OnExit(action ActionFunc) ParallelStateBuilder

	// Transitions from this parallel state
	To(target string) TransitionBuilder
	ToParent(target string) TransitionBuilder

	// Navigation back
	End() MachineBuilder
	Build() MachineDefinition
}

ParallelStateBuilder handles parallel regions

type ParallelStateImpl

type ParallelStateImpl struct {
	CompositeStateImpl
	// contains filtered or unexported fields
}

ParallelStateImpl implements the ParallelState interface

func NewParallelState

func NewParallelState(id string) *ParallelStateImpl

NewParallelState creates a new parallel composite state

func (*ParallelStateImpl) AddRegion

func (s *ParallelStateImpl) AddRegion(region Region)

AddRegion adds a parallel region

func (*ParallelStateImpl) IsParallel

func (s *ParallelStateImpl) IsParallel() bool

IsParallel returns true for parallel states

func (*ParallelStateImpl) Regions

func (s *ParallelStateImpl) Regions() []Region

Regions returns all parallel regions

type PseudoState

type PseudoState interface {
	State
	Kind() PseudoStateKind
}

PseudoState represents a transient state

type PseudoStateImpl

type PseudoStateImpl struct {
	AtomicStateImpl
	// contains filtered or unexported fields
}

PseudoStateImpl implements the PseudoState interface

func NewHistoryState

func NewHistoryState(id string, deep bool) *PseudoStateImpl

NewHistoryState creates a new history pseudostate

func NewPseudoState

func NewPseudoState(id string, kind PseudoStateKind) *PseudoStateImpl

NewPseudoState creates a new pseudostate

func (*PseudoStateImpl) AddChoiceCondition

func (s *PseudoStateImpl) AddChoiceCondition(guard GuardFunc, target string, action ActionFunc)

AddChoiceCondition adds a condition for Choice pseudostates

func (*PseudoStateImpl) AddForkTarget

func (s *PseudoStateImpl) AddForkTarget(target string)

AddForkTarget adds a target state for Fork pseudostates

func (*PseudoStateImpl) IsPseudo

func (s *PseudoStateImpl) IsPseudo() bool

IsPseudo returns true for pseudostates

func (*PseudoStateImpl) Kind

func (s *PseudoStateImpl) Kind() PseudoStateKind

Kind returns the pseudostate kind

func (*PseudoStateImpl) SetDefaultTarget

func (s *PseudoStateImpl) SetDefaultTarget(target string)

SetDefaultTarget sets the default target for Choice/Junction pseudostates

func (*PseudoStateImpl) SetForkTargets

func (s *PseudoStateImpl) SetForkTargets(targets []string)

SetForkTargets sets the target states for Fork pseudostates

func (*PseudoStateImpl) SetHistoryDefault

func (s *PseudoStateImpl) SetHistoryDefault(target string)

SetHistoryDefault sets the default target for History pseudostates

func (*PseudoStateImpl) SetJoinSources

func (s *PseudoStateImpl) SetJoinSources(sources []string)

SetJoinSources adds a combination of source states for Join pseudostates Each call to this method represents one valid source combination

func (*PseudoStateImpl) SetJoinTarget

func (s *PseudoStateImpl) SetJoinTarget(target string)

SetJoinTarget sets the target state for Join pseudostates

type PseudoStateKind

type PseudoStateKind int

PseudoStateKind enumerates the types of pseudostates

const (
	// Initial pseudostate marks the starting point
	Initial PseudoStateKind = iota
	// Choice pseudostate for conditional branching
	Choice
	// Junction pseudostate for merge points
	Junction
	// Fork pseudostate for parallel splitting
	Fork
	// Join pseudostate for parallel synchronization
	Join
	// Terminate pseudostate for machine termination
	Terminate
	// History pseudostate for shallow history
	History
	// DeepHistory pseudostate for deep history
	DeepHistory
)

type Region

type Region interface {
	ID() string
	ParentState() ParallelState
	CurrentState() State
	InitialState() State
	States() []State
	IsComplete() bool    // Check if region has reached final state
	HasFinalState() bool // Check if region contains a final state
}

Region represents a parallel region

type RegionBuilder

type RegionBuilder interface {
	// States within this region
	State(id string) StateBuilder
	CompositeState(id string) CompositeStateBuilder

	// Pseudostates within this region
	Choice(id string) ChoiceBuilder
	Junction(id string) JunctionBuilder
	Fork(id string) ForkBuilder
	Join(id string) JoinBuilder
	History(id string) HistoryBuilder
	DeepHistory(id string) HistoryBuilder

	// Navigation
	Region(id string) RegionBuilder // Sibling region
	End() ParallelStateBuilder      // Back to parallel state
	Build() MachineDefinition
}

RegionBuilder handles parallel region configuration

type RegionImpl

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

RegionImpl implements the Region interface

func NewRegion

func NewRegion(id string, parentState ParallelState) *RegionImpl

NewRegion creates a new parallel region

func (*RegionImpl) AddState

func (r *RegionImpl) AddState(state State)

AddState adds a state to this region

func (*RegionImpl) CurrentState

func (r *RegionImpl) CurrentState() State

CurrentState returns the current state in this region

func (*RegionImpl) HasFinalState

func (r *RegionImpl) HasFinalState() bool

HasFinalState checks if this region contains at least one final state

func (*RegionImpl) ID

func (r *RegionImpl) ID() string

ID returns the region identifier

func (*RegionImpl) InitialState

func (r *RegionImpl) InitialState() State

InitialState returns the initial state of this region

func (*RegionImpl) IsComplete

func (r *RegionImpl) IsComplete() bool

IsComplete checks if this region has reached a final state

func (*RegionImpl) ParentState

func (r *RegionImpl) ParentState() ParallelState

ParentState returns the parent parallel state

func (*RegionImpl) States

func (r *RegionImpl) States() []State

States returns all states in this region

func (*RegionImpl) WithInitialState

func (r *RegionImpl) WithInitialState(state State) *RegionImpl

WithInitialState sets the initial state for this region

type SequentialState

type SequentialState interface {
	CompositeState
}

SequentialState represents a sequential composite state

type SequentialStateImpl

type SequentialStateImpl struct {
	CompositeStateImpl
}

SequentialStateImpl implements the SequentialState interface

func NewSequentialState

func NewSequentialState(id string) *SequentialStateImpl

NewSequentialState creates a new sequential composite state

type State

type State interface {
	ID() string
	Enter(ctx Context)
	Exit(ctx Context)
	Parent() State
	IsComposite() bool
	IsParallel() bool
	IsPseudo() bool
	IsFinal() bool
}

State represents a state in the state machine

type StateBuilder

type StateBuilder interface {
	To(target string) TransitionBuilder
	ToSelf() TransitionBuilder
	ToParent(target string) TransitionBuilder

	OnEntry(action ActionFunc) StateBuilder
	OnExit(action ActionFunc) StateBuilder
	Final() StateBuilder
	Initial() StateBuilder

	State(id string) StateBuilder
	CompositeState(id string) CompositeStateBuilder
	ParallelState(id string) ParallelStateBuilder
	Choice(id string) ChoiceBuilder
	Junction(id string) JunctionBuilder
	Fork(id string) ForkBuilder
	Join(id string) JoinBuilder
	History(id string) HistoryBuilder
	DeepHistory(id string) HistoryBuilder
	Build() MachineDefinition
}

StateBuilder handles regular atomic state configuration

type StateError

type StateError struct {
	Code    ErrorCode
	StateID string
	Message string
}

StateError represents state-related errors

func NewInvalidStateError

func NewInvalidStateError(stateID string, reason string) *StateError

NewInvalidStateError creates a new invalid state error

func NewStateError

func NewStateError(code ErrorCode, stateID string, message string) *StateError

NewStateError creates a new state error with custom values

func NewStateNotFoundError

func NewStateNotFoundError(stateID string) *StateError

NewStateNotFoundError creates a new state not found error

func (*StateError) Error

func (e *StateError) Error() string

type StateEvent

type StateEvent struct {
	State string
	Ctx   Context
}

type StateMachine

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

StateMachine implements the Machine interface

func (*StateMachine) AddObserver

func (sm *StateMachine) AddObserver(observer Observer)

AddObserver adds an observer to the machine

func (*StateMachine) Context

func (sm *StateMachine) Context() Context

Context returns the machine's context

func (*StateMachine) CurrentState

func (sm *StateMachine) CurrentState() string

CurrentState returns the current state

func (*StateMachine) GetActiveStates

func (sm *StateMachine) GetActiveStates() []string

GetActiveStates returns all currently active states (including parallel regions)

func (*StateMachine) GetParallelRegions

func (sm *StateMachine) GetParallelRegions() map[string][]string

GetParallelRegions returns the current parallel regions and their active states

func (*StateMachine) GetStateHierarchy

func (sm *StateMachine) GetStateHierarchy() []string

GetStateHierarchy returns the full hierarchical path of the current state

func (*StateMachine) HandleEvent

func (sm *StateMachine) HandleEvent(eventName string, eventData any) *EventResult

HandleEvent handles an event synchronously

func (*StateMachine) HandleEventWithContext

func (sm *StateMachine) HandleEventWithContext(ctx context.Context, eventName string, eventData any) *EventResult

HandleEventWithContext handles an event synchronously with context

func (*StateMachine) IsInState

func (sm *StateMachine) IsInState(stateID string) bool

IsInState checks if the machine is currently in the specified state or any of its substates

func (*StateMachine) IsStateActive

func (sm *StateMachine) IsStateActive(stateID string) bool

IsStateActive checks if a specific state is currently active

func (*StateMachine) MarshalJSON

func (sm *StateMachine) MarshalJSON() ([]byte, error)

MarshalJSON serializes the machine state to JSON

func (*StateMachine) RegionState

func (sm *StateMachine) RegionState(regionID string) string

RegionState returns the current state of a specific region

func (*StateMachine) RemoveObserver

func (sm *StateMachine) RemoveObserver(observer Observer)

RemoveObserver removes an observer from the machine

func (*StateMachine) Reset

func (sm *StateMachine) Reset() error

Reset resets the state machine

func (*StateMachine) SendEvent

func (sm *StateMachine) SendEvent(eventName string, eventData any) *EventResult

SendEvent sends an event asynchronously

func (*StateMachine) SendEventWithContext

func (sm *StateMachine) SendEventWithContext(ctx context.Context, eventName string, eventData any) *EventResult

SendEventWithContext sends an event asynchronously with context

func (*StateMachine) SetRegionState

func (sm *StateMachine) SetRegionState(regionID string, stateID string) error

SetRegionState sets the state of a specific region in a parallel state

func (*StateMachine) SetState

func (sm *StateMachine) SetState(state string) error

SetState sets the current state

func (*StateMachine) Start

func (sm *StateMachine) Start() error

Start starts the state machine

func (*StateMachine) Stop

func (sm *StateMachine) Stop() error

Stop stops the state machine

func (*StateMachine) UnmarshalJSON

func (sm *StateMachine) UnmarshalJSON(data []byte) error

UnmarshalJSON deserializes the machine state from JSON

func (*StateMachine) WithContext

func (sm *StateMachine) WithContext(ctx Context) Machine

WithContext sets the machine's context

type StateMachineContext

type StateMachineContext struct {
	context.Context
	// contains filtered or unexported fields
}

StateMachineContext implements the Context interface

func (*StateMachineContext) Fork

func (ctx *StateMachineContext) Fork() Context

Fork creates a new context with copied data

func (*StateMachineContext) Get

func (ctx *StateMachineContext) Get(key string) (any, bool)

Get retrieves a value from the context

func (*StateMachineContext) GetAll

func (ctx *StateMachineContext) GetAll() map[string]any

GetAll returns all context data

func (*StateMachineContext) GetCurrentEvent

func (ctx *StateMachineContext) GetCurrentEvent() Event

GetCurrentEvent returns the current event being processed

func (*StateMachineContext) GetCurrentState

func (ctx *StateMachineContext) GetCurrentState() string

GetCurrentState returns the current state ID

func (*StateMachineContext) GetEventData

func (ctx *StateMachineContext) GetEventData() any

GetEventData returns the data of the current event

func (*StateMachineContext) GetEventDataAs

func (ctx *StateMachineContext) GetEventDataAs(target any) bool

GetEventDataAs attempts to cast event data to the target type

func (*StateMachineContext) GetEventName

func (ctx *StateMachineContext) GetEventName() string

GetEventName returns the name of the current event

func (*StateMachineContext) GetMachine

func (ctx *StateMachineContext) GetMachine() Machine

GetMachine returns the associated state machine

func (*StateMachineContext) GetPreviousState

func (ctx *StateMachineContext) GetPreviousState() string

GetPreviousState returns the previous state

func (*StateMachineContext) GetSourceState

func (ctx *StateMachineContext) GetSourceState() string

GetSourceState returns the source state of the current transition

func (*StateMachineContext) GetTargetState

func (ctx *StateMachineContext) GetTargetState() string

GetTargetState returns the target state of the current transition

func (*StateMachineContext) Set

func (ctx *StateMachineContext) Set(key string, value any)

Set stores a value in the context

func (*StateMachineContext) WithValue

func (ctx *StateMachineContext) WithValue(key string, value any) Context

WithValue creates a new context with an additional key-value pair

type TestObserver

type TestObserver struct {
	Transitions  []TransitionEvent
	StateEnters  []StateEvent
	StateExits   []StateEvent
	EventRejects []EventRejectEvent
	Errors       []ErrorEvent
	Actions      []ActionEvent
	Started      []ContextEvent
	Stopped      []ContextEvent
	Guards       []GuardEvent
	// contains filtered or unexported fields
}

TestObserver is a mock observer for testing that captures all observer events

func NewTestObserver

func NewTestObserver() *TestObserver

NewTestObserver creates a new test observer

func (*TestObserver) LastStateEnter

func (o *TestObserver) LastStateEnter() *StateEvent

func (*TestObserver) LastTransition

func (o *TestObserver) LastTransition() *TransitionEvent

func (*TestObserver) OnActionExecution

func (o *TestObserver) OnActionExecution(actionType string, state string, event Event, ctx Context)

func (*TestObserver) OnError

func (o *TestObserver) OnError(err error, ctx Context)

func (*TestObserver) OnEventRejected

func (o *TestObserver) OnEventRejected(event Event, reason string, ctx Context)

func (*TestObserver) OnGuardEvaluation

func (o *TestObserver) OnGuardEvaluation(from string, to string, event Event, result bool, ctx Context)

func (*TestObserver) OnMachineStarted

func (o *TestObserver) OnMachineStarted(ctx Context)

func (*TestObserver) OnMachineStopped

func (o *TestObserver) OnMachineStopped(ctx Context)

func (*TestObserver) OnStateEnter

func (o *TestObserver) OnStateEnter(state string, ctx Context)

func (*TestObserver) OnStateExit

func (o *TestObserver) OnStateExit(state string, ctx Context)

ExtendedObserver interface implementations

func (*TestObserver) OnTransition

func (o *TestObserver) OnTransition(from string, to string, event Event, ctx Context)

Observer interface implementations

func (*TestObserver) Reset

func (o *TestObserver) Reset()

Helper methods for test assertions

func (*TestObserver) StateEnterCount

func (o *TestObserver) StateEnterCount() int

func (*TestObserver) StateExitCount

func (o *TestObserver) StateExitCount() int

func (*TestObserver) TransitionCount

func (o *TestObserver) TransitionCount() int

type Transition

type Transition struct {
	SourceState string
	TargetState string
	EventName   string
	Guard       GuardFunc
	Action      ActionFunc
}

Transition represents a state transition

func NewTransition

func NewTransition(sourceState, targetState, eventName string) *Transition

NewTransition creates a new transition

func (*Transition) WithAction

func (t *Transition) WithAction(action ActionFunc) *Transition

WithAction adds an action to the transition

func (*Transition) WithGuard

func (t *Transition) WithGuard(guard GuardFunc) *Transition

WithGuard adds a guard condition to the transition

type TransitionBuilder

type TransitionBuilder interface {
	// Event binding
	On(event string) TransitionBuilder
	OnCompletion() TransitionBuilder // Completion transition (automatic when state completes)

	// Conditions
	When(guard GuardFunc) TransitionBuilder
	Unless(guard GuardFunc) TransitionBuilder

	// Actions
	Do(action ActionFunc) TransitionBuilder
	DoIf(condition GuardFunc, action ActionFunc) TransitionBuilder
	DoAsync(action ActionFunc) TransitionBuilder

	// Error handling
	OnError(errorState string) TransitionBuilder
	OnTimeout(timeoutState string) TransitionBuilder

	// Multiple transitions from same state
	To(target string) TransitionBuilder
	ToSelf() TransitionBuilder
	ToParent(target string) TransitionBuilder

	// Navigation back
	State(id string) StateBuilder
	CompositeState(id string) CompositeStateBuilder
	Build() MachineDefinition
}

TransitionBuilder handles transition configuration with inline actions

type TransitionError

type TransitionError struct {
	Code   ErrorCode
	From   string
	To     string
	Event  string
	Reason string
}

TransitionError represents transition-related errors

func NewNoTransitionError

func NewNoTransitionError(from, event string) *TransitionError

NewNoTransitionError creates a new no transition found error

func NewTransitionError

func NewTransitionError(code ErrorCode, from, to, event, reason string) *TransitionError

NewTransitionError creates a new transition error with custom values

func NewTransitionNotAllowedError

func NewTransitionNotAllowedError(from, to, event string) *TransitionError

NewTransitionNotAllowedError creates a new transition not allowed error

func (*TransitionError) Error

func (e *TransitionError) Error() string

type TransitionEvent

type TransitionEvent struct {
	From  string
	To    string
	Event Event
	Ctx   Context
}

Directories

Path Synopsis
examples
order-pipeline command
smart-home command
traffic-light command

Jump to

Keyboard shortcuts

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