@@ -144,9 +144,21 @@ type StateMachine[Event any, Env Environment] struct {
144144 wg sync.WaitGroup
145145}
146146
147+ // ErrorReporter is an interface that's used to report errors that occur during
148+ // state machine execution.
149+ type ErrorReporter interface {
150+ // ReportError is a method that's used to report an error that occurred
151+ // during state machine execution.
152+ ReportError (err error )
153+ }
154+
147155// StateMachineCfg is a configuration struct that's used to create a new state
148156// machine.
149157type StateMachineCfg [Event any , Env Environment ] struct {
158+ // ErrorReporter is used to report errors that occur during state
159+ // transitions.
160+ ErrorReporter ErrorReporter
161+
150162 // Daemon is a set of adapters that will be used to bridge the FSM to
151163 // the daemon.
152164 Daemon DaemonAdapters
@@ -586,6 +598,11 @@ func (s *StateMachine[Event, Env]) applyEvents(currentState State[Event, Env],
586598 return err
587599 }
588600
601+ log .Infof ("FSM(%v): state transition: from_state=%T, " +
602+ "to_state=%T" ,
603+ s .cfg .Env .Name (), currentState ,
604+ transition .NextState )
605+
589606 // With our events processed, we'll now update our
590607 // internal state.
591608 currentState = transition .NextState
@@ -638,9 +655,15 @@ func (s *StateMachine[Event, Env]) driveMachine() {
638655 case newEvent := <- s .events :
639656 newState , err := s .applyEvents (currentState , newEvent )
640657 if err != nil {
641- // TODO(roasbeef): hard error?
658+ s .cfg .ErrorReporter .ReportError (err )
659+
642660 log .Errorf ("unable to apply event: %v" , err )
643- continue
661+
662+ // An error occurred, so we'll tear down the
663+ // entire state machine as we can't proceed.
664+ go s .Stop ()
665+
666+ return
644667 }
645668
646669 currentState = newState
0 commit comments