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 }