Giter Site home page Giter Site logo

ffsm's Introduction

FFSM

CI Status Go Report Card codecov

Finite State Machine (or FSM) written in Go. It is a low-level primitive for more complex solutions. Supported (optional) transition handler for advanced logic.

What is a finite state machine (or FSM)? TODO

Features

Quickstart

Install or update ffsm package.

go get -u github.com/gebv/ffsm

Simple example:

// enum of states
var (
	OpenDoor  = "open"
	CloseDoor = "close"
)

// setup of state transition diagram
wf := make(ffsm.Stack).Add(OpenDoor, CloseDoor).Add(CloseDoor, OpenDoor)

// init FSM with initial state CloseDoor
fsm := ffsm.NewFSM(wf, CloseDoor)

// to opens the door
err := fsm.Dispatch(context.Background(), OpenDoor)

if err != nil {
  // handler errors
}

fsm.State() // end state

Examples

Finite state machine example

Simple FSM

Can open door and close door. Opened door can not open. And closed door can not close.

Follow state transition diagram in image

On the playground https://play.golang.org/p/J8Cej99Rp-J

Listing code
package main

import (
	"context"
	"fmt"

	"github.com/gebv/ffsm"
)

func main() {
	// setup state transition diagram
	wf := make(ffsm.Stack).Add(OpenDoor, CloseDoor).Add(CloseDoor, OpenDoor)

	// init FSM with initial state CloseDoor
	fsm := ffsm.NewFSM(wf, CloseDoor)
	fmt.Println("initial state:", fsm.State())
	fmt.Println()

	fmt.Println("to open door")
	fmt.Println("----------------------------")
	fmt.Println("before:", fsm.State())
	err := fsm.Dispatch(context.Background(), OpenDoor)
	if err != nil {
		fmt.Println("failed:", err)
	}
	fmt.Println("after:", fsm.State())
	fmt.Println()

	fmt.Println("to open door for opened door")
	fmt.Println("----------------------------")
	fmt.Println("before:", fsm.State())
	err = fsm.Dispatch(context.Background(), OpenDoor)
	if err != nil {
		fmt.Println("failed:", err)
	}
	fmt.Println("after:", fsm.State())
	fmt.Println()

	fmt.Println("to close door")
	fmt.Println("----------------------------")
	fmt.Println("before:", fsm.State())
	err = fsm.Dispatch(context.Background(), CloseDoor)
	if err != nil {
		fmt.Println("failed:", err)
	}
	fmt.Println("after:", fsm.State())
}

const (
	OpenDoor  = "open"
	CloseDoor = "close"
)

FSM with transition handlers

Only Bob can open door. Anyone can close the door. And also opened door can not open and closed door can not close.

Follow state transition diagram in image

On the playground https://play.golang.org/p/M5JiBwUycnx

Listing code
package main

import (
	"context"
	"fmt"
	"errors"

	"github.com/gebv/ffsm"
)

func main() {
	// handler for CloseDoor to OpenDoor transition
	onlyBobHandler := func(ctx context.Context) (context.Context, error) {
		name, ok := ctx.Value("__name").(string)
		if !ok {
			return ctx, errors.New("forbidden - only for Bob")
		}
		if name != "bob" {
			return ctx, errors.New("forbidden - only for Bob")
		}
		return ctx, nil
	}
	// setup state transition diagram
	wf := make(ffsm.Stack).Add(OpenDoor, CloseDoor).Add(CloseDoor, OpenDoor, onlyBobHandler)

	// init FSM with initial state CloseDoor
	fsm := ffsm.NewFSM(wf, CloseDoor)
	fmt.Println("initial state:", fsm.State())
	fmt.Println()

	fmt.Println("anonymous opens door")
	fmt.Println("----------------------------")
	fmt.Println("before:", fsm.State())
	err := fsm.Dispatch(context.Background(), OpenDoor)
	if err != nil {
		fmt.Println("failed:", err)
	}
	fmt.Println("after:", fsm.State())
	fmt.Println()

	fmt.Println("Bob opens door")
	fmt.Println("----------------------------")
	fmt.Println("before:", fsm.State())
	bobCtx := context.WithValue(context.Background(), "__name", "bob")
	err = fsm.Dispatch(bobCtx, OpenDoor)
	if err != nil {
		fmt.Println("failed:", err)
	}
	fmt.Println("after:", fsm.State())
	fmt.Println()

	fmt.Println("to open door for opened door")
	fmt.Println("----------------------------")
	fmt.Println("before:", fsm.State())
	err = fsm.Dispatch(context.Background(), OpenDoor)
	if err != nil {
		fmt.Println("failed:", err)
	}
	fmt.Println("after:", fsm.State())
	fmt.Println()

	fmt.Println("to close door")
	fmt.Println("----------------------------")
	fmt.Println("before:", fsm.State())
	err = fsm.Dispatch(context.Background(), CloseDoor)
	if err != nil {
		fmt.Println("failed:", err)
	}
	fmt.Println("after:", fsm.State())
}

const (
	OpenDoor  = "open"
	CloseDoor = "close"
)

More examples

See more in tests

Additional packages

Version Policy

ffsm follows semantic versioning for the documented public API on stable releases. v1.2 is the latest stable version. Follows changelog.

License

MIT, see LICENSE.

ffsm's People

Contributors

gebv avatar

Watchers

 avatar  avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.