github.com/gkstretton/dark/services/goo@v0.0.0-20231114224855-2d1a2074d446/actor/executor/executor.go (about)

     1  package executor
     2  
     3  import (
     4  	"fmt"
     5  
     6  	"github.com/gkstretton/asol-protos/go/machinepb"
     7  	"github.com/gkstretton/dark/services/goo/events"
     8  )
     9  
    10  type Executor interface {
    11  	// Final execution
    12  	Execute(chan *machinepb.StateReport)
    13  	// Get state as expected after execution
    14  	PredictOutcome(state *machinepb.StateReport) *machinepb.StateReport
    15  	// Called during a voting round to issue some preemptive action, e.g. move throughout the vote.
    16  	Preempt()
    17  	// For debug
    18  	String() string
    19  }
    20  
    21  func conditionWaiter(c chan *machinepb.StateReport, cond func(*machinepb.StateReport) bool) chan *machinepb.StateReport {
    22  	filterChan := make(chan *machinepb.StateReport)
    23  	go func() {
    24  		for {
    25  			r := <-c
    26  			if cond(r) {
    27  				filterChan <- r
    28  				close(filterChan)
    29  				return
    30  			}
    31  		}
    32  	}()
    33  	return filterChan
    34  }
    35  
    36  // RunExecutorNonBlocking is a utility function to return an await channel and
    37  // the expected state upon completion of an Executor
    38  func RunExecutorNonBlocking(c chan *machinepb.StateReport, e Executor) (completionCh chan struct{}, predictedState *machinepb.StateReport) {
    39  	predictedState = e.PredictOutcome(events.GetLatestStateReportCopy())
    40  
    41  	completionCh = make(chan struct{})
    42  	go func() {
    43  		fmt.Printf("beginning execution: %s\n", e)
    44  		e.Execute(c)
    45  		fmt.Printf("completed execution: %s\n", e)
    46  
    47  		completionCh <- struct{}{}
    48  		close(completionCh)
    49  	}()
    50  
    51  	return completionCh, predictedState
    52  }