123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100 |
- 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
- }
- )
|