github.com/chenbh/concourse/v6@v6.4.2/atc/lidar/check_rate_calculator.go (about)

     1  package lidar
     2  
     3  import (
     4  	"context"
     5  	"time"
     6  
     7  	"golang.org/x/time/rate"
     8  )
     9  
    10  //go:generate counterfeiter . Limiter
    11  
    12  type Limiter interface {
    13  	Wait(context.Context) error
    14  }
    15  
    16  //go:generate counterfeiter . CheckableCounter
    17  
    18  type CheckableCounter interface {
    19  	CheckableCount() (int, error)
    20  }
    21  
    22  type CheckRateCalculator struct {
    23  	MaxChecksPerSecond       int
    24  	ResourceCheckingInterval time.Duration
    25  
    26  	CheckableCounter CheckableCounter
    27  }
    28  
    29  // RateLimiter determines the rate at which the checks should be limited to per
    30  // second.
    31  //
    32  // It is dependent on the max checks per second configuration, where if it is
    33  // configured to -1 then it there is no limit, if it is > 0 then it is set to
    34  // its configured value and if it is 0 (which is default) then it is calculated
    35  // using the number of checkables and the resource checking interval.
    36  //
    37  // The calculated limit is determined by finding the ideal number of checks to
    38  // run per second in order to check all the checkables in the database within
    39  // the resource checking interval. By enforcing that ideal rate of checks, it
    40  // will help spread out the number of checks that are started within the same
    41  // interval.
    42  func (c CheckRateCalculator) RateLimiter() (Limiter, error) {
    43  	var rateOfChecks rate.Limit
    44  	if c.MaxChecksPerSecond == -1 {
    45  		// UNLIMITED POWER
    46  		rateOfChecks = rate.Inf
    47  	} else if c.MaxChecksPerSecond == 0 {
    48  		// Fetch the number of checkables (resource config scopes) in the database
    49  		checkableCount, err := c.CheckableCounter.CheckableCount()
    50  		if err != nil {
    51  			return nil, err
    52  		}
    53  
    54  		// Calculate the number of checks that need to be run per second in order
    55  		// to check all the checkables within the resource checking interval
    56  		everythingRate := float64(checkableCount) / c.ResourceCheckingInterval.Seconds()
    57  
    58  		rateOfChecks = rate.Limit(everythingRate)
    59  	} else {
    60  		rateOfChecks = rate.Limit(c.MaxChecksPerSecond)
    61  	}
    62  
    63  	return rate.NewLimiter(rateOfChecks, 1), nil
    64  }