Frédéric G. MARAND 1 miesiąc temu
rodzic
commit
365693a6c7
2 zmienionych plików z 100 dodań i 0 usunięć
  1. 0 0
      docs/classes.mermaid
  2. 100 0
      fsm2.go

+ 0 - 0
docs/classes.mermaid


+ 100 - 0
fsm2.go

@@ -0,0 +1,100 @@
+package fsm
+
+import (
+	"context"
+	"time"
+)
+
+type M2Hook[T any] func(ctx context.Context, event M2Event[T]) error
+
+type M2State[T any] interface {
+	Name() string
+	SetAfterEnter([]M2Hook[T])
+	AfterEnter() []M2Hook[T]
+	SetBeforeLeave([]M2Hook[T])
+	BeforeLeave() []M2Hook[T]
+}
+
+type M2Event[T any] interface {
+	Name() string
+	Data() T
+}
+
+type RetryableError interface {
+	error
+	RetryableError()
+}
+
+type M2Transition[T any] struct {
+	guards, actions []M2Hook[T]
+	next            State
+}
+
+func (mt *M2Transition[T]) SetGuards([]M2Hook[T])  {}
+func (mt *M2Transition[T]) Guards() []M2Hook[T]    { return mt.guards }
+func (mt *M2Transition[T]) SetActions([]M2Hook[T]) {}
+func (mt *M2Transition[T]) Actions() []M2Hook[T]   { return mt.actions }
+func (mt *M2Transition[T]) Next() State            { return mt.next }
+
+type M2Matrix[T any] map[M2State[T]]map[M2Event[T]]M2Transition[T]
+
+// M2BackoffFunc returning <0 means the retry limit has been reached.
+type M2BackoffFunc func() time.Duration
+
+type M2FSM[T any] interface {
+	Name() string
+
+	SetBackoff(fn M2BackoffFunc)
+
+	SetMatrix(mx M2Matrix[T])
+	Matrix() M2Matrix[T]
+
+	StartState() M2State[T]
+	EndState() M2State[T]
+	ErrorState() M2State[T]
+}
+
+type M2PushMachine[T any] interface {
+	M2FSM[T]
+	Handle(context.Context, M2Event[T]) error // If ctx == nil, handling uses the machine context.
+}
+
+type M2PullMachine[T any] interface {
+	M2FSM[T]
+	Start(ctx context.Context, events chan<- M2Event[T]) M2State[T]
+}
+
+type M2VerifiableMachine[T any] interface {
+	M2FSM[T]
+	IsReachable(s1, s2 M2State[T]) bool
+	IsStronglyConnected() bool // Minimal Complexity O(V+E) using DFS (Tarjan or Kosaraju)
+}
+
+var (
+	m2BackoffInitialDelay    = time.Millisecond
+	m2BackoffMaxAttempts     = 10
+	m2DefaultBackoffAttempts = 0
+
+	// M2YoloBackoff retries indefinitely without delay.
+	M2YoloBackoff M2BackoffFunc = func() time.Duration {
+		return 0
+	}
+
+	// M2NoBackoff retries immediately but only up to the maximum number of retries.
+	M2NoBackoff M2BackoffFunc = func() time.Duration {
+		m2DefaultBackoffAttempts++
+		if m2DefaultBackoffAttempts > m2BackoffMaxAttempts {
+			return -1
+		}
+		return M2YoloBackoff()
+	}
+
+	// M2ExponentialBackoff retries with an exponential delay and maximum number of retries.
+	M2ExponentialBackoff M2BackoffFunc = func() time.Duration {
+		d := M2NoBackoff()
+		if d < 0 {
+			return d
+		}
+		return (1 << m2DefaultBackoffAttempts) * m2BackoffInitialDelay
+	}
+)