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

pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy