Skip to content

Commit

Permalink
runtime/jitter: naming improvements and other nits
Browse files Browse the repository at this point in the history
Signed-off-by: Hidde Beydals <[email protected]>
  • Loading branch information
hiddeco committed Aug 2, 2023
1 parent 521d800 commit 148f2a1
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 32 deletions.
33 changes: 16 additions & 17 deletions runtime/jitter/interval.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,11 @@ package jitter

import (
"errors"
"github.com/spf13/pflag"
"math/rand"
"sync"
"time"

"github.com/spf13/pflag"
ctrl "sigs.k8s.io/controller-runtime"
)

Expand All @@ -46,33 +46,32 @@ func SetGlobalIntervalJitter(p float64, rand *rand.Rand) {
})
}

// RequeueAfterResult returns a result with a requeue-after interval that has
// JitteredRequeueInterval returns a result with a requeue-after interval that has
// been jittered. It will not modify the result if it is zero or is marked
// to requeue immediately.
//
// To use this function, you must first initialize the global jitter with
// SetGlobalIntervalJitter.
func RequeueAfterResult(res ctrl.Result) ctrl.Result {
if res.IsZero() || res.Requeue == true {
return res
}
if after := res.RequeueAfter; after > 0 {
res.RequeueAfter = globalIntervalJitter(after)
func JitteredRequeueInterval(res ctrl.Result) ctrl.Result {
if !res.IsZero() && res.RequeueAfter > 0 {
res.RequeueAfter = globalIntervalJitter(res.RequeueAfter)
}
return res
}

// IntervalDuration returns a jittered duration based on the given interval.
// JitteredIntervalDuration returns a jittered duration based on the given
// duration.
//
// To use this function, you must first initialize the global jitter with
// SetGlobalIntervalJitter.
func IntervalDuration(d time.Duration) time.Duration {
func JitteredIntervalDuration(d time.Duration) time.Duration {
return globalIntervalJitter(d)
}

// Interval is used to configure the interval jitter for a controller using
// command line flags. To use it, create an Interval and call BindFlags, then
// call SetGlobalJitter with a rand.Rand (or nil to use the default).
// IntervalOptions is used to configure the interval jitter for a controller
// using command line flags. To use it, create an IntervalOptions and call
// BindFlags, then call SetGlobalJitter with a rand.Rand (or nil to use the
// default).
//
// Applying jitter to the interval duration can be useful to mitigate spikes in
// memory and CPU usage caused by many resources being configured with the same
Expand All @@ -95,7 +94,7 @@ func IntervalDuration(d time.Duration) time.Duration {
// distribution also translates into benefits for the Go garbage collector.
// Notably, the garbage collector experiences reduced GC bursts and more
// frequent collections, leading to improved overall performance.
type Interval struct {
type IntervalOptions struct {
// Percentage of jitter to apply to interval durations. A value of 10
// will apply a jitter of +/-10% to the interval duration. It can not be negative,
// and must be less than 100.
Expand All @@ -104,15 +103,15 @@ type Interval struct {

// BindFlags will parse the given pflag.FlagSet and load the interval jitter
// with the default value of 10%.
func (o *Interval) BindFlags(fs *pflag.FlagSet) {
func (o *IntervalOptions) BindFlags(fs *pflag.FlagSet) {
o.BindFlagsWithDefault(fs, -1)
}

// BindFlagsWithDefault will parse the given pflag.FlagSet and load the interval
// jitter. The defaultPercentage is used to set the default value for the
// interval jitter percentage. If the defaultPercentage is negative, then the
// default value (of 10%) will be used.
func (o *Interval) BindFlagsWithDefault(fs *pflag.FlagSet, defaultPercentage int) {
func (o *IntervalOptions) BindFlagsWithDefault(fs *pflag.FlagSet, defaultPercentage int) {
if defaultPercentage < 0 {
defaultPercentage = defaultIntervalJitterPercentage
}
Expand All @@ -124,7 +123,7 @@ func (o *Interval) BindFlagsWithDefault(fs *pflag.FlagSet, defaultPercentage int

// SetGlobalJitter sets the global interval jitter. It is safe to call this
// method multiple times, but only the first call will have an effect.
func (o *Interval) SetGlobalJitter(rand *rand.Rand) error {
func (o *IntervalOptions) SetGlobalJitter(rand *rand.Rand) error {
if o.Percentage >= 100 {
return errInvalidIntervalJitter
}
Expand Down
29 changes: 14 additions & 15 deletions runtime/jitter/interval_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,16 @@ limitations under the License.
package jitter

import (
"github.com/spf13/pflag"
"math/rand"
"testing"
"time"

. "github.com/onsi/gomega"
"github.com/spf13/pflag"
ctrl "sigs.k8s.io/controller-runtime"
)

func TestRequeueAfterResult(t *testing.T) {
func TestJitteredRequeueInterval(t *testing.T) {
r := rand.New(rand.NewSource(int64(12345)))
p := 0.2
SetGlobalIntervalJitter(p, r)
Expand All @@ -50,21 +50,20 @@ func TestRequeueAfterResult(t *testing.T) {
upperBound := float64(tt.res.RequeueAfter) * (1 + p)

for i := 0; i < 100; i++ {
res := RequeueAfterResult(tt.res)
res := JitteredRequeueInterval(tt.res)

g.Expect(res.RequeueAfter).To(BeNumerically(">=", lowerBound))
g.Expect(res.RequeueAfter).To(BeNumerically("<=", upperBound))
g.Expect(res.RequeueAfter).ToNot(Equal(tt.res.RequeueAfter))
}
} else {
res := RequeueAfterResult(tt.res)
g.Expect(res).To(Equal(tt.res))
g.Expect(JitteredRequeueInterval(tt.res)).To(Equal(tt.res))
}
})
}
}

func TestIntervalDuration(t *testing.T) {
func TestJitteredIntervalDuration(t *testing.T) {
g := NewWithT(t)

r := rand.New(rand.NewSource(int64(12345)))
Expand All @@ -76,30 +75,30 @@ func TestIntervalDuration(t *testing.T) {
upperBound := float64(interval) * (1 + p)

for i := 0; i < 100; i++ {
d := IntervalDuration(interval)
d := JitteredIntervalDuration(interval)

g.Expect(d).To(BeNumerically(">=", lowerBound))
g.Expect(d).To(BeNumerically("<=", upperBound))
g.Expect(d).ToNot(Equal(interval))
}
}

func TestInterval_BindFlags(t *testing.T) {
func TestIntervalOptions_BindFlags(t *testing.T) {
g := NewWithT(t)

interval := &Interval{}
interval := &IntervalOptions{}

fs := pflag.NewFlagSet("test", pflag.ContinueOnError)
interval.BindFlags(fs)

g.Expect(interval.Percentage).To(Equal(uint8(defaultIntervalJitterPercentage)))
}

func TestInterval_BindFlagsWithDefault(t *testing.T) {
func TestIntervalOptions_BindFlagsWithDefault(t *testing.T) {
g := NewWithT(t)

t.Run("with default fallback", func(t *testing.T) {
interval := &Interval{}
interval := &IntervalOptions{}

fs := pflag.NewFlagSet("test", pflag.ContinueOnError)
interval.BindFlagsWithDefault(fs, -1)
Expand All @@ -108,7 +107,7 @@ func TestInterval_BindFlagsWithDefault(t *testing.T) {
})

t.Run("with custom default", func(t *testing.T) {
interval := &Interval{}
interval := &IntervalOptions{}

fs := pflag.NewFlagSet("test", pflag.ContinueOnError)
interval.BindFlagsWithDefault(fs, 50)
Expand All @@ -117,7 +116,7 @@ func TestInterval_BindFlagsWithDefault(t *testing.T) {
})

t.Run("with flag override", func(t *testing.T) {
interval := &Interval{}
interval := &IntervalOptions{}

fs := pflag.NewFlagSet("test", pflag.ContinueOnError)
interval.BindFlagsWithDefault(fs, 0)
Expand All @@ -128,11 +127,11 @@ func TestInterval_BindFlagsWithDefault(t *testing.T) {
})
}

func TestInterval_SetGlobalJitter(t *testing.T) {
func TestIntervalOptions_SetGlobalJitter(t *testing.T) {
t.Run("invalid percentage >=100", func(t *testing.T) {
g := NewWithT(t)

interval := &Interval{Percentage: uint8(100)}
interval := &IntervalOptions{Percentage: uint8(100)}
err := interval.SetGlobalJitter(nil)
g.Expect(err).To(MatchError(errInvalidIntervalJitter))
})
Expand Down

0 comments on commit 148f2a1

Please sign in to comment.