Documentation
¶
Overview ¶
Package fsm provides a thread-safe finite state machine implementation. It allows defining custom states and transitions, managing state changes, subscribing to state updates via channels, and persisting/restoring state via JSON.
Example usage:
logger := slog.Default() machine, err := fsm.New(logger.Handler(), fsm.StatusNew, fsm.TypicalTransitions) if err != nil { logger.Error("Failed to create FSM", "error", err) return } err = machine.Transition(fsm.StatusRunning) if err != nil { logger.Error("Transition failed", "error", err) }
// Persist state jsonData, err := json.Marshal(machine)
if err != nil { logger.Error("Failed to marshal FSM state", "error", err) }
// Restore state restoredMachine, err := fsm.NewFromJSON(logger.Handler(), jsonData, fsm.TypicalTransitions)
if err != nil { logger.Error("Failed to restore FSM from JSON", "error", err) } else { logger.Info("Restored FSM state", "state", restoredMachine.GetState()) }
Index ¶
- Constants
- Variables
- type Machine
- func (fsm *Machine) AddSubscriber(ch chan string) func()
- func (fsm *Machine) GetState() string
- func (fsm *Machine) GetStateChan(ctx context.Context) <-chan string
- func (fsm *Machine) MarshalJSON() ([]byte, error)
- func (fsm *Machine) SetState(state string) error
- func (fsm *Machine) Transition(toState string) error
- func (fsm *Machine) TransitionBool(toState string) bool
- func (fsm *Machine) TransitionIfCurrentState(fromState, toState string) error
- type TransitionsConfig
Constants ¶
const ( StatusNew = "New" StatusBooting = "Booting" StatusRunning = "Running" StatusReloading = "Reloading" StatusStopping = "Stopping" StatusStopped = "Stopped" StatusError = "Error" StatusUnknown = "Unknown" )
Collection of common statuses
Variables ¶
var ErrAvailableStateData = errors.New("available state data is malformed")
ErrAvailableStateData is returned when the available state data is not correctly formatted
var ErrCurrentStateIncorrect = errors.New("current state is incorrect")
ErrCurrentStateIncorrect is returned when the current state does not match with expectations
var ErrInvalidState = errors.New("state is invalid")
ErrInvalidState is returned when the state is somehow invalid
var ErrInvalidStateTransition = errors.New("state transition is invalid")
ErrInvalidStateTransition is returned when the state transition is invalid
var TypicalTransitions = TransitionsConfig{ StatusNew: {StatusBooting, StatusError}, StatusBooting: {StatusRunning, StatusError}, StatusRunning: {StatusReloading, StatusStopping, StatusError}, StatusReloading: {StatusRunning, StatusError}, StatusStopping: {StatusStopped, StatusError}, StatusStopped: {StatusNew, StatusError}, StatusError: {StatusError, StatusStopping, StatusStopped}, StatusUnknown: {StatusUnknown}, }
TypicalTransitions is a common set of transitions, useful as a guide. Each key is the current state, and the value is a list of valid next states the FSM can transition to.
Functions ¶
This section is empty.
Types ¶
type Machine ¶
type Machine struct {
// contains filtered or unexported fields
}
Machine represents a finite state machine that tracks its current state and manages state transitions.
func New ¶
func New( handler slog.Handler, initialState string, allowedTransitions TransitionsConfig, ) (*Machine, error)
New initializes a new finite state machine with the specified initial state and allowed state transitions.
Example of allowedTransitions:
allowedTransitions := TransitionsConfig{ StatusNew: {StatusBooting, StatusError}, StatusBooting: {StatusRunning, StatusError}, StatusRunning: {StatusReloading, StatusExited, StatusError}, StatusReloading: {StatusRunning, StatusError}, StatusError: {StatusNew, StatusExited}, StatusExited: {StatusNew}, }
func NewFromJSON ¶ added in v1.1.0
func NewFromJSON( handler slog.Handler, jsonData []byte, allowedTransitions TransitionsConfig, ) (*Machine, error)
NewFromJSON creates a new finite state machine by unmarshaling JSON data. It requires the logging handler and the original transitions configuration used when the state was marshaled.
func (*Machine) AddSubscriber ¶
AddSubscriber adds your channel to the internal list of broadcast targets. It will receive the current state if the channel (if possible), and will also receive future state changes when the FSM state is updated. A callback function is returned that should be called to remove the channel from the list of subscribers when this is no longer needed.
func (*Machine) GetState ¶
GetState returns the current state of the finite state machine. This read is lock-free due to the use of atomic.Value.
func (*Machine) GetStateChan ¶
GetStateChan returns a channel that will receive the current state of the FSM immediately.
func (*Machine) MarshalJSON ¶ added in v1.1.0
MarshalJSON implements the json.Marshaler interface. It returns the current state of the FSM as a JSON object: {"state": "CURRENT_STATE"}.
func (*Machine) SetState ¶
SetState updates the FSM's state to the provided state, bypassing the usual transition rules. It only succeeds if the requested state is defined as a valid *source* state in the allowedTransitions configuration.
func (*Machine) Transition ¶
Transition changes the FSM's state to toState. It ensures that the transition adheres to the allowed transitions defined during initialization. Returns ErrInvalidState if the current state is somehow invalid or ErrInvalidStateTransition if the transition is not allowed.
func (*Machine) TransitionBool ¶
TransitionBool is similar to Transition, but returns a boolean indicating whether the transition was successful. It suppresses the specific error reason.
func (*Machine) TransitionIfCurrentState ¶
TransitionIfCurrentState changes the FSM's state to toState only if the current state matches fromState. This returns an error if the current state does not match or if the transition is not allowed from fromState to toState.
type TransitionsConfig ¶
TransitionsConfig represents a configuration for allowed transitions the FSM.