Skip to content

FSM-Go is a lightweight, high-performance, stateless finite state machine implementation in Go, inspired by Alibaba's COLA state machine component.

License

Notifications You must be signed in to change notification settings

lingcoder/fsm-go

Repository files navigation

FSM-Go: A Lightweight Finite State Machine for Go

Go Reference Go Report Card License: MIT

FSM-Go is a lightweight, high-performance, stateless finite state machine implementation in Go, inspired by Alibaba's COLA state machine component.

中文文档

✨ Features

  • 🪶 Lightweight - Minimal, stateless design for high performance
  • 🔒 Type-safe - Built with Go generics for compile-time type checking
  • 🔄 Fluent API - Intuitive builder pattern for defining state machines
  • 🔀 Versatile Transitions - Support for external, internal, and parallel transitions
  • 🧪 Conditional Logic - Flexible conditions to control when transitions occur
  • 🎬 Action Execution - Custom actions that execute during transitions
  • 🔄 Thread-safe - Designed for concurrent use in multi-threaded environments
  • 📊 Visualization - Built-in support for generating state machine diagrams

📦 Installation

go get github.com/lingcoder/fsm-go

🚀 Usage

package main

import (
	"fmt"
	"log"

	"github.com/lingcoder/fsm-go"
)

// Define states
type OrderState string

const (
	OrderCreated   OrderState = "CREATED"
	OrderPaid      OrderState = "PAID"
	OrderShipped   OrderState = "SHIPPED"
	OrderDelivered OrderState = "DELIVERED"
	OrderCancelled OrderState = "CANCELLED"
)

// Define events
type OrderEvent string

const (
	EventPay     OrderEvent = "PAY"
	EventShip    OrderEvent = "SHIP"
	EventDeliver OrderEvent = "DELIVER"
	EventCancel  OrderEvent = "CANCEL"
)

// Define payload
type OrderPayload struct {
	OrderID string
	Amount  float64
}

func main() {
	// Create a builder
	builder := fsm.NewStateMachineBuilder[OrderState, OrderEvent, OrderPayload]()

	// Define the state machine
	builder.ExternalTransition().
		From(OrderCreated).
		To(OrderPaid).
		On(EventPay).
		WhenFunc(func(payload OrderPayload) bool {
			// Check if amount is valid
			return payload.Amount > 0
		}).
		PerformFunc(func(from, to OrderState, event OrderEvent, payload OrderPayload) error {
			fmt.Printf("Order %s transitioning from %s to %s on event %s\n",
				payload.OrderID, from, to, event)
			return nil
		})

	builder.ExternalTransition().
		From(OrderPaid).
		To(OrderShipped).
		On(EventShip).
		WhenFunc(func(payload OrderPayload) bool {
			return true
		}).
		PerformFunc(func(from, to OrderState, event OrderEvent, payload OrderPayload) error {
			fmt.Printf("Order %s is being shipped\n", payload.OrderID)
			return nil
		})

	// Define multiple source transitions
	builder.ExternalTransitions().
		FromAmong(OrderCreated, OrderPaid, OrderShipped).
		To(OrderCancelled).
		On(EventCancel).
		WhenFunc(func(payload OrderPayload) bool {
			return true
		}).
		PerformFunc(func(from, to OrderState, event OrderEvent, payload OrderPayload) error {
			fmt.Printf("Order %s cancelled from %s state\n", payload.OrderID, from)
			return nil
		})

	// Build the state machine
	stateMachine, err := builder.Build("OrderStateMachine")
	if err != nil {
		log.Fatalf("Failed to build state machine: %v", err)
	}

	// Create payload
	payload := OrderPayload{
		OrderID: "ORD-20250425-001",
		Amount:  100.0,
	}

	// Transition from CREATED to PAID
	newState, err := stateMachine.FireEvent(OrderCreated, EventPay, payload)
	if err != nil {
		log.Fatalf("Transition failed: %v", err)
	}

	fmt.Printf("New state: %v\n", newState)
}

🧩 Core Concepts

Concept Description
State Represents a specific state in your business process
Event Triggers state transitions
Transition Defines how states change in response to events
Condition Logic that determines if a transition should occur
Action Logic executed when a transition occurs
StateMachine The core component that manages states and transitions

Types of Transitions

  • External Transition: Transition between different states
  • Internal Transition: Actions within the same state
  • Parallel Transition: Transition to multiple states simultaneously

📚 Examples

Check the examples directory for more detailed examples:

  • examples/order: Order processing workflow
  • examples/workflow: Approval workflow
  • examples/game: Game state management

⚡ Performance

FSM-Go is designed for high performance:

  • Stateless design minimizes memory usage
  • Efficient transition lookup
  • Thread-safe for concurrent use
  • Benchmarks included in the test suite

📊 Visualization

FSM-Go provides a unified way to visualize your state machine with different formats:

// Default format (PlantUML)
plantUML := stateMachine.GenerateDiagram()
fmt.Println(plantUML)

// Generate specific format
table := stateMachine.GenerateDiagram(fsm.MarkdownTable)     // Markdown table format
fmt.Println(table)

flow := stateMachine.GenerateDiagram(fsm.MarkdownFlowchart)  // Markdown flowchart format
fmt.Println(flow)

// Generate multiple formats separately
diagrams := stateMachine.GenerateDiagram(fsm.PlantUML, fsm.MarkdownTable, fsm.MarkdownFlowchart, fsm.MarkdownStateDiagram)
fmt.Println(diagrams)

📄 License

MIT © LingCoder

About

FSM-Go is a lightweight, high-performance, stateless finite state machine implementation in Go, inspired by Alibaba's COLA state machine component.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages