statemachine

package module
v1.0.0 Latest Latest
Warning

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

Go to latest
Published: Mar 29, 2021 License: Apache-2.0, MIT Imports: 11 Imported by: 1

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