Help us shape the future of Go! Take the 2026 Go Developer Survey

statemachine

package module
v1.0.3 Latest Latest
Warning

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

Go to latest
Published: Oct 8, 2022 License: Apache-2.0, MIT Imports: 11 Imported by: 22

README

go-statemachine

A generic state machine

Table of Contents

Description

The module provides tools for defining and tracking generic state machines. For a more specific implementation that specifically defines finite state machines, see the FSM module, that provides additional tools on top of the generic machines defined here

State machines:

  • Receive Events
  • Modify State
  • Take further actions based on new state, possibly generating more events

Usage

A state machine is defined in terms of a Planner.

It has the following signature:

type Planner func(events []Event, user interface{}) (nextActions interface{}, eventsProcessed uint64, err error)

A planner receives a series of events and a pointer to the current state (represented by user)

The planner generally:

  • processes one or more events that mutate state
  • constructs a function that will perform additional actions based on the new state

It returns:

  1. The next actions handler-- should have the signature func(ctx Context, st ) error), where is the typeOf(user) param
  2. The number of events processed
  3. An error if occured

As a general rule, you mutate inside the planner function, while you perform side effects outside the planner in the return handler, which only receives a value for state and cannot mutate it (but can dispatch more events).

Interaction with statestore

The go-statemachine is designed to be used with a list of data structures, persisted to a datastore through the go-statestore module. When working with statemachines this way, you define a StateHandler with a Plan function that works like a Planner.

You initialize a new set of statemachines for a given type of state as follows:

var ds datastore.Batching
var stateHandler StateHandler

var stateMachines = statemachine.New(ds, stateHandler, StateType{})

This creates a machine for the given data store that will process data of type StateType with the given stateHandler.

You can now dispatch events to a state machine with:

var id interface{} // some identifier of a tracked state
var evt Event // some event type
stateMachines.Send(id, evt)

The state machine group will initialize a new statemachine if it is not already tracking data for the given identifier

License

Dual-licensed under MIT + Apache 2.0

Documentation

Index

Constants

This section is empty.

Variables

View Source
var ErrTerminated = xerrors.New("normal shutdown of state machine")

Functions

This section is empty.

Types

type Context

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

func (*Context) Context

func (ctx *Context) Context() context.Context

func (*Context) Send

func (ctx *Context) Send(evt interface{}) error

type Event

type Event struct {
	User interface{}
}

type Planner

type Planner func(events []Event, user interface{}) (interface{}, uint64, error)

Planner processes in queue events It returns: 1. a handler of type -- func(ctx Context, st <T>) (func(*<T>), error), where <T> is the typeOf(User) param 2. the number of events processed 3. an error if occured

type StateGroup

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

StateGroup manages a group of state machines sharing the same logic

func New

func New(ds datastore.Datastore, hnd StateHandler, stateType interface{}) *StateGroup

stateType: T - (MyStateStruct{})

func (*StateGroup) Begin

func (s *StateGroup) Begin(id interface{}, userState interface{}) error

Begin initiates tracking with a specific value for a given identifier

func (*StateGroup) Get

func (s *StateGroup) Get(id interface{}) *statestore.StoredState

Get gets state for a single state machine

func (*StateGroup) Has

func (s *StateGroup) Has(id interface{}) (bool, error)

Has indicates whether there is data for the given state machine

func (*StateGroup) List

func (s *StateGroup) List(out interface{}) error

List outputs states of all state machines in this group out: *[]StateT

func (*StateGroup) Send

func (s *StateGroup) Send(id interface{}, evt interface{}) (err error)

Send sends an event to machine identified by `id`. `evt` is going to be passed into StateHandler.Planner, in the events[].User param

If a state machine with the specified id doesn't exits, it's created, and it's state is set to zero-value of stateType provided in group constructor

func (*StateGroup) Stop

func (s *StateGroup) Stop(ctx context.Context) error

Stop stops all state machines in this group

type StateHandler

type StateHandler interface {
	// returns
	Plan(events []Event, user interface{}) (interface{}, uint64, error)
}

type StateHandlerWithInit

type StateHandlerWithInit interface {
	StateHandler
	Init(<-chan struct{})
}

type StateMachine

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

type TestEvent

type TestEvent struct {
	A   string
	Val uint64
}

func (*TestEvent) MarshalCBOR

func (t *TestEvent) MarshalCBOR(w io.Writer) error

func (*TestEvent) UnmarshalCBOR

func (t *TestEvent) UnmarshalCBOR(r io.Reader) error

type TestState

type TestState struct {
	A uint64
	B uint64
	C []uint64
}

func (*TestState) MarshalCBOR

func (t *TestState) MarshalCBOR(w io.Writer) error

func (*TestState) UnmarshalCBOR

func (t *TestState) UnmarshalCBOR(r io.Reader) error

Directories

Path Synopsis
fsm

Jump to

Keyboard shortcuts

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