From 6de0615cd57d5eb417389c9c02147c03cbc2f69d Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Mon, 4 Mar 2024 23:49:11 -0600 Subject: [PATCH] protofsm: allow multiple internal events to be emitted In this commit, we update the execution logic to allow multiple internal events to be emitted. This is useful to handle potential out of order state transitions, as they can be cached, then emitted once the relevant pre-conditions have been met. --- protofsm/log.go | 2 +- protofsm/state_machine.go | 44 ++++++++++++++++------------------ protofsm/state_machine_test.go | 4 +++- 3 files changed, 25 insertions(+), 25 deletions(-) diff --git a/protofsm/log.go b/protofsm/log.go index ea1728ab8..8ff9c1b62 100644 --- a/protofsm/log.go +++ b/protofsm/log.go @@ -12,7 +12,7 @@ var log btclog.Logger // The default amount of logging is none. func init() { - UseLogger(build.NewSubLogger("PRCL", nil)) + UseLogger(build.NewSubLogger("PFSM", nil)) } // DisableLog disables all library log output. Logging output is disabled diff --git a/protofsm/state_machine.go b/protofsm/state_machine.go index eb967f2a2..b583d4a8d 100644 --- a/protofsm/state_machine.go +++ b/protofsm/state_machine.go @@ -8,7 +8,6 @@ import ( "github.com/btcsuite/btcd/btcec/v2" "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/wire" - "github.com/davecgh/go-spew/spew" "github.com/lightningnetwork/lnd/chainntnfs" "github.com/lightningnetwork/lnd/fn" "github.com/lightningnetwork/lnd/lnutils" @@ -28,7 +27,7 @@ type EmittedEvent[Event any] struct { // InternalEvent is an optional internal event that is to be routed // back to the target state. This enables state to trigger one or many // state transitions without a new external event. - InternalEvent fn.Option[Event] + InternalEvent fn.Option[[]Event] // ExternalEvent is an optional external event that is to be sent to // the daemon for dispatch. Usually, this is some form of I/O. @@ -329,7 +328,7 @@ func (s *StateMachine[Event, Env]) executeDaemonEvent( //nolint:funlen // any preconditions as well as post-send events. case *SendMsgEvent[Event]: sendAndCleanUp := func() error { - log.Debugf("FSM(%v): sending message to target(%v): "+ + log.Debugf("FSM(%v): sending message to target(%x): "+ "%v", s.cfg.Env.Name(), daemonEvent.TargetPeer.SerializeCompressed(), lnutils.SpewLogClosure(daemonEvent.Msgs), @@ -451,7 +450,11 @@ func (s *StateMachine[Event, Env]) executeDaemonEvent( //nolint:funlen defer s.wg.Done() for { select { - case spend := <-spendEvent.Spend: + case spend, ok := <-spendEvent.Spend: + if !ok { + return + } + // If there's a post-send event, then // we'll send that into the current // state now. @@ -522,11 +525,8 @@ func (s *StateMachine[Event, Env]) applyEvents(currentState State[Event, Env], newEvent Event) (State[Event, Env], error) { log.Debugf("FSM(%v): applying new event", s.cfg.Env.Name(), - lnutils.NewLogClosure(func() string { - return spew.Sdump(newEvent) - }), + lnutils.SpewLogClosure(newEvent), ) - eventQueue := fn.NewQueue(newEvent) // Given the next event to handle, we'll process the event, then add @@ -539,9 +539,7 @@ func (s *StateMachine[Event, Env]) applyEvents(currentState State[Event, Env], err := fn.MapOptionZ(nextEvent, func(event Event) error { log.Debugf("FSM(%v): processing event: %v", s.cfg.Env.Name(), - lnutils.NewLogClosure(func() string { - return spew.Sdump(event) - }), + lnutils.SpewLogClosure(event), ) // Apply the state transition function of the current @@ -584,19 +582,19 @@ func (s *StateMachine[Event, Env]) applyEvents(currentState State[Event, Env], // our event queue. // //nolint:lll - events.InternalEvent.WhenSome(func(es Event) { - log.Debugf("FSM(%v): adding "+ - "new internal event "+ - "to queue: %v", - s.cfg.Env.Name(), - lnutils.NewLogClosure(func() string { //nolint:lll - return spew.Sdump( //nolint:lll - es, - ) - }), - ) + events.InternalEvent.WhenSome(func(es []Event) { + for _, inEvent := range es { + log.Debugf("FSM(%v): adding "+ + "new internal event "+ + "to queue: %v", + s.cfg.Env.Name(), + lnutils.SpewLogClosure( + inEvent, + ), + ) - eventQueue.Enqueue(es) + eventQueue.Enqueue(inEvent) + } }) return nil diff --git a/protofsm/state_machine_test.go b/protofsm/state_machine_test.go index 0a09af60b..0432f386b 100644 --- a/protofsm/state_machine_test.go +++ b/protofsm/state_machine_test.go @@ -80,7 +80,9 @@ func (d *dummyStateStart) ProcessEvent(event dummyEvents, env *dummyEnv, return &StateTransition[dummyEvents, *dummyEnv]{ NextState: &dummyStateStart{}, NewEvents: fn.Some(EmittedEvent[dummyEvents]{ - InternalEvent: fn.Some(dummyEvents(&goToFin{})), + InternalEvent: fn.Some( + []dummyEvents{&goToFin{}}, + ), }), }, nil