nexus package - github.com/IbrahimShahzad/nexus - Go Packages

nexus

package module
v0.0.0-...-89042fa Latest Latest
Warning

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

Go to latest
Published: Dec 30, 2025 License: MIT Imports: 7 Imported by: 0

README

nexus

An event-driven finite state machine library.

Usage Steps

  1. Define States
  2. Define Actions
  3. Define Event
  4. Add transitions
  5. Trigger events

see examples

States

  • The "initial" state is provided when calling New and is registered automatically.
  • You need to register any other states you want to use.
machine := nexus.New[YourType]("initial_state")
_ = machine.RegisterState("state_name")

Actions

Functions that run when a transition happens. Each action gets the context and your data, can modify the data, and should return an error if something goes wrong.

action := nexus.Action[YourType]{
	Name: "descriptive_name",
	Fn: func(ctx context.Context, data *YourType) (*YourType, error) {
		// Do your work here
		return data, nil
	},
}

Transitions

The rules: "when in state X and event Y happens, run these actions and go to state Z".

machine.AddTransition("state_x", "state_z", "event_y", []nexus.Action[YourType]{action1, action2})

Logging

Change the log level anytime:

machine.SetLogLevel(slog.LevelDebug)

Or set it on creation:

machine := nexus.New[MyType]("initial",
	nexus.WithLogLevel(slog.LevelDebug),
	nexus.WithLogger(myCustomLogger))

Error Handling

You can set up a global error handler that catches any action failures:

machine := nexus.New[MyType]("start")
machine.SetErrorHandler("error_state", func(ctx context.Context, data *MyType) (*MyType, error) {
	// Log it, clean up, panic, whatever floats your boat
	return data, nil
})

When any action fails, this handler runs and the FSM moves to the error state.

Context

Actions receive context, so you can pass values or handle cancellation:

action := nexus.Action[Request]{
	Name: "check_user",
	Fn: func(ctx context.Context, req *Request) (*Request, error) {
		userID := ctx.Value("user_id").(string)
		// Use userID for something
		return req, nil
	},
}

ctx := context.WithValue(context.Background(), "user_id", "12345")
machine.Trigger(ctx, "authenticate", req)

API Reference

Creating an FSM
New[T any](initialState State, options ...OptionFunc) *FSM[T]
  • WithLogLevel(level zerolog.Level) - log level for the lib
  • WithLogOutput(w io.Writer) - output
  • WithLogConsole() - whether to use console writer or not. if not used, logs in json format
  • WithMaxStates(max int) - Maximum number of states allowed (default 0 = unlimited)
Core Methods
RegisterState(state State)
  • Add a state. You need to register all states before using them.
  • The initial state is auto-registered when creating the FSM by calling New()
  • You cannot register the same state twice.
  • You cannot remove state after registering.
AddTransition(from, to State, event Event, actions []Action[T])
  • Define a transition. Actions can be empty if you just want state changes.
Trigger(ctx context.Context, event Event, args *T) (*T, error)
  • Fire an event. Returns modified args and any error from actions.
  • The return value is argument to the next action in the chain.
GetState() State
  • Current state
SetState(s State)
  • Manually set state (by Force). Use with caution.
  • better to use ErrorHandler to get to known states.

[!WARNING] Bypasses the state machine

SetErrorHandler(errorState State, handler ActionFunc[T])
  • Set up error handler function to be used if an error occurs during transition.
SetLogLevel(level zerolog.Level)
  • Change logging verbosity at runtime.

License

See LICENSE

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	ErrInvalidState       = errors.New("invalid state")
	ErrInvalidEvent       = errors.New("invalid event")
	ErrNoTransition       = errors.New("no transition registered for state and event")
	ErrStateNotRegistered = errors.New("state not registered")
	ErrStateAlreadyExists = errors.New("state already exists")
	ErrStateSizeExceeded  = errors.New("maximum number of states exceeded")
)

FSM operation errors

View Source
var (
	ErrActionNil       = errors.New("action function is nil")
	ErrActionFailed    = errors.New("action execution failed")
	ErrNoActionDefined = errors.New("no action function defined")
)

Action errors

View Source
var (
	ErrTransitionFailed        = errors.New("state transition failed")
	ErrInvalidTransition       = errors.New("invalid state transition")
	ErrTransitionAlreadyExists = errors.New("transition already exists")
)

State transition errors

View Source
var (
	ErrFSMNotInitialized = errors.New("FSM not initialized")
	ErrFSMAlreadyRunning = errors.New("FSM already running")
	ErrFSMStopped        = errors.New("FSM has been stopped")
)

FSM lifecycle errors

Functions

This section is empty.

Types

type Action

type Action[T any] struct {
	Name string
	Fn   ActionFunc[T]
}

Action that can be executed during a state transition.

type ActionError

type ActionError struct {
	ActionName string
	State      string
	Event      string
	Err        error
}

func (*ActionError) Error

func (e *ActionError) Error() string

func (*ActionError) Unwrap

func (e *ActionError) Unwrap() error

type ActionFunc

type ActionFunc[T any] func(ctx context.Context, args *T) (*T, error)

ActionFunc is a function that performs an action during a state transition.

type Event

type Event string

Event represents an event that triggers a state transition.

type EventError

type EventError struct {
	Event string
	State string
	Err   error
}

func (*EventError) Error

func (e *EventError) Error() string

func (*EventError) Unwrap

func (e *EventError) Unwrap() error

type FSM

type FSM[T any] struct {
	FSMOptions
	// contains filtered or unexported fields
}

FSM is the Finite State Machine

func New

func New[T any](initialState State, options ...FSMOptionFunc) *FSM[T]

New creates a new FSM instance

func (*FSM[T]) AddTransition

func (f *FSM[T]) AddTransition(from, to State, event Event, actions []Action[T])

AddTransition registers a new transition in the FSM from one state to another on a given event.

func (*FSM[T]) GetState

func (f *FSM[T]) GetState() State

GetState returns the current state of the FSM.

func (*FSM[T]) RegisterState

func (f *FSM[T]) RegisterState(state State) error

RegisterState adds a new state to the FSM.

func (*FSM[T]) SetErrorHandler

func (f *FSM[T]) SetErrorHandler(errorState State, handler ActionFunc[T])

SetErrorHandler configures an error handler and error state. When a transition error occurs, the error handler will be called and the FSM will transition to the error state.

func (*FSM[T]) SetLogLevel

func (f *FSM[T]) SetLogLevel(level zerolog.Level)

SetLogLevel updates the log level at runtime.

func (*FSM[T]) SetState

func (f *FSM[T]) SetState(s State)

SetState sets the current state of the FSM.

WARN: This bypasses the normal transition mechanism.

func (*FSM[T]) Trigger

func (f *FSM[T]) Trigger(ctx context.Context, event Event, args *T) (*T, error)

Trigger attempts to transition the FSM to a new state based on the given event.

Returns an error if no transition is registered for the current state or event, or if the action fails. If an error occurs and an error handler is configured, it will be called and the FSM will transition to the error state before returning the error.

type FSMOptionFunc

type FSMOptionFunc func(*FSMOptions)

func WithLogConsole

func WithLogConsole() FSMOptionFunc

WithLogConsole switches the FSM logger to human-friendly console output.

func WithLogLevel

func WithLogLevel(level zerolog.Level) FSMOptionFunc

WithLogLevel sets the log level for the FSM.

func WithLogOutput

func WithLogOutput(w io.Writer) FSMOptionFunc

WithLogOutput sets the writer where logs will be written.

func WithMaxStates

func WithMaxStates(max int) FSMOptionFunc

WithMaxStates sets the maximum number of states allowed in the FSM.

type FSMOptions

type FSMOptions struct {
	LogLevel  zerolog.Level
	LogOutput io.Writer

	UseStdOut bool
	// contains filtered or unexported fields
}

FSMOptions holds configuration options for the FSM.

func DefaultOptions

func DefaultOptions() FSMOptions

DefaultOptions returns the default FSM configuration.

type State

type State string

State represents a state in the finite state machine.

type StateError

type StateError struct {
	State State
	Op    string
	Err   error
}

func (*StateError) Error

func (e *StateError) Error() string

func (*StateError) Unwrap

func (e *StateError) Unwrap() error

type States

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

States manages a collection of unique states.

func NewStates

func NewStates(size int) *States

NewStates creates a new States collection with maximum size.

func (*States) Add

func (s *States) Add(state State) error

Add adds a new state to the collection.

func (*States) Exists

func (s *States) Exists(state State) bool

Exists checks if a state exists in the collection.

func (*States) Keys

func (s *States) Keys() []State

Keys returns a slice of all registered states.

type Transition

type Transition[T any] struct {
	From   State
	To     State
	Event  Event
	Action []Action[T]
}

Transition triggered by an event.

type TransitionError

type TransitionError struct {
	Message string
	State   State
	Event   Event
	Err     error
}

func (*TransitionError) Error

func (e *TransitionError) Error() string

func (*TransitionError) Unwrap

func (e *TransitionError) Unwrap() error

Directories

Path Synopsis
examples
simple_fsm command

Jump to

Keyboard shortcuts

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