github.com/onflow/flow-go@v0.35.7-crescendo-preview.23-atree-inlining/engine/execution/checker/engine.go (about) 1 package checker 2 3 import ( 4 "context" 5 "time" 6 7 "github.com/onflow/flow-go/module/component" 8 "github.com/onflow/flow-go/module/irrecoverable" 9 ) 10 11 type Engine struct { 12 *component.ComponentManager 13 core *Core 14 } 15 16 // DefaultTimeInterval triggers the check once every minute, 17 const DefaultTimeInterval = time.Minute * 1 18 19 func NewEngine(core *Core) *Engine { 20 e := &Engine{ 21 core: core, 22 } 23 24 e.ComponentManager = component.NewComponentManagerBuilder(). 25 AddWorker(func(ctx irrecoverable.SignalerContext, ready component.ReadyFunc) { 26 ready() 27 err := e.runLoop(ctx, DefaultTimeInterval) 28 if err != nil { 29 ctx.Throw(err) 30 } 31 }). 32 Build() 33 34 return e 35 } 36 37 // runLoop runs the check every minute. 38 // Why using a timer instead of listening to finalized and executed events? 39 // because it's simpler as it doesn't need to subscribe to those events. 40 // It also runs less checks, note: the checker doesn't need to find the 41 // first mismatched block, as long as it can find a mismatch, it's good enough. 42 // A timer could reduce the number of checks, as it only checks once every minute. 43 func (e *Engine) runLoop(ctx context.Context, tickInterval time.Duration) error { 44 ticker := time.NewTicker(tickInterval) 45 defer ticker.Stop() // critical for ticker to be garbage collected 46 for { 47 select { 48 case <-ticker.C: 49 err := e.core.RunCheck() 50 if err != nil { 51 return err 52 } 53 case <-ctx.Done(): 54 return nil 55 } 56 } 57 }