yfsm

package module
v0.0.0-...-beaaa3b Latest Latest
Warning

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

Go to latest
Published: Oct 3, 2019 License: MIT Imports: 7 Imported by: 0

README

yfsm

Yet (another) Finite State Machine library.

The library was created for one the ecommerce projects in DataInq ecommerce lab.

Main concepts are:

  • state
  • event

The graph of states and transitions can be described by tuples: <state0, event, state1>.

The library has the capability of saving the state change history. You should provide a History implementation.

Usage

  1. Create necessary tables in Postgre database.
  2. Populate tables with states and data.
  3. In your code, create a Machine instance with a Type object. You can use SqlType with table name and state column provided.
  4. You can play with the states:
m := yfsm.NewMachine()

Configuring state machine

state_machine table contains all state machines you want to use. If you have many object types you want to manage state, e.g. orders and warehouse commodity transfer, you probably should create two separate machines: order_state and parcel_state.

INSERT INTO state_machine(id, name) VALUES (1, 'order_states');

You must provide states:

INSERT INTO state_machine_state(id, state_machine_id, name, start, stop) VALUES
(1, 1, 'CREATED', TRUE, FALSE),
(2, 1, 'BUYER_DATA', FALSE, FALSE),
(3, 1, 'PAYMENT', FALSE, FALSE),
(4, 1, 'EXTERNAL_PAYMENT', FALSE, FALSE),
(5, 1, 'WAITING_FOR_ACCEPT', FALSE, FALSE),
(6, 1, 'COLLECT', FALSE, FALSE),
(7, 1, 'SEND', FALSE, FALSE),
(8, 1, 'ON_THE_WAY', FALSE, FALSE),
(9, 1, 'DELIVERED', FALSE, FALSE),
(10, 1, 'DONE', FALSE, TRUE),
(11, 1, 'PAYMENT_FAIL', FALSE, TRUE),
(12, 1, 'FAIL_TO_DELIVER', FALSE, TRUE),
(13, 1, 'DECLINED', FALSE, TRUE),
(14, 1, 'CANCELED', FALSE, TRUE);

Having states (think about them as nodes in graph), one must define transitions between states. We have two concepts around that: event and transition. The first can be though as a name e.g. OK may be an event, whereas transition is a tuple of (fromState, event, toState). There may be multiple transitions defined for same event.

Let's define some events:

INSERT INTO state_machine_event(id, state_machine_id, name)
VALUES
(1, 1, 'OK'),
(2, 1, 'FAIL'),
(3, 1, 'RETRY');

Then we may define exact transitions we want to allow:

INSERT INTO state_machine_transition(
    id,
    state_machine_id,
    state_machine_event_id,
    from_state_id,
    to_state_id
) VALUES
(1, 1, 1, 1, 2),  -- 'CREATED' - on 'OK' change to 'BUYER_DATA'
(12, 1, 3, 11, 4);  -- 'DECLINED' - on 'RETRY' change to 'EXTERNAL_PAYMENT'

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	ErrDuplicate            = errors.New("duplicate object")
	ErrCannotFindInstance   = errors.New("cannot find object")
	ErrCannotFindTransition = errors.New("cannot find transition")
	ErrCannotIdentifyEvent  = errors.New("cannot identify event")
)

Functions

This section is empty.

Types

type Event

type Event interface {
	ID() int
	Transition() int
	Name() string

	Identify() bool
}

Event describes an event to happen.

func EventFromID

func EventFromID(id int) Event

func EventFromName

func EventFromName(name string) Event

func EventFromTransition

func EventFromTransition(id int) Event

type History

type History interface {
	Save()
}

type Machine

type Machine interface {
	ID() int
	Name() string

	// Check if a type's object is in a proper state to handle event.
	Can(id int, event Event) (bool, error)
	ToState(fromState int, event Event) (int, error)
	Fire(id int, event Event) error
}

func LoadMachineForType

func LoadMachineForType(id int, t Type) Machine

Loads a given machine for a given type.

func NewMachine

func NewMachine(rawDB *sql.DB, t Type) Machine

type MapType

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

func NewMapType

func NewMapType() *MapType

func (*MapType) Add

func (m *MapType) Add(id, state int) error

func (*MapType) Get

func (m *MapType) Get(id int) (int, error)

func (*MapType) Transition

func (m *MapType) Transition(id, fromState, toState int) error

type SqlType

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

func NewSqlType

func NewSqlType(db *sql.DB, table string, column string) *SqlType

func (*SqlType) Get

func (s *SqlType) Get(id int) (int, error)

func (*SqlType) Transition

func (s *SqlType) Transition(id, fromState, toState int) error

type State

type State interface {
	ID() int
	Machine() int
	Name() string
}

type Storage

type Storage interface {
	Get()
	Save()
}

type Type

type Type interface {
	Get(id int) (int, error)
	Transition(id, fromState, toState int) error
}

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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