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  }