...

Source file src/github.com/linkerd/linkerd2/multicluster/service-mirror/jittered_ticker.go

Documentation: github.com/linkerd/linkerd2/multicluster/service-mirror

     1  // Copyright (c) 2016-2017 Tigera, Inc. All rights reserved.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  //NB: This file was copied from: https://github.com/projectcalico/felix/blob/master/jitter/jittered_ticker.go
    15  
    16  package servicemirror
    17  
    18  import (
    19  	"math/rand"
    20  	"time"
    21  
    22  	log "github.com/sirupsen/logrus"
    23  )
    24  
    25  // Ticker tries to emit events on channel C at minDuration intervals plus up to maxJitter.
    26  type Ticker struct {
    27  	C           <-chan time.Time
    28  	stop        chan bool
    29  	MinDuration time.Duration
    30  	MaxJitter   time.Duration
    31  }
    32  
    33  // NewTicker creates a new Ticker
    34  func NewTicker(minDuration time.Duration, maxJitter time.Duration) *Ticker {
    35  	if minDuration < 0 {
    36  		log.WithField("duration", minDuration).Panic("Negative duration")
    37  	}
    38  	if maxJitter < 0 {
    39  		log.WithField("jitter", minDuration).Panic("Negative jitter")
    40  	}
    41  	c := make(chan time.Time, 1)
    42  	ticker := &Ticker{
    43  		C:           c,
    44  		stop:        make(chan bool),
    45  		MinDuration: minDuration,
    46  		MaxJitter:   maxJitter,
    47  	}
    48  	go ticker.loop(c)
    49  	return ticker
    50  }
    51  
    52  func (t *Ticker) loop(c chan time.Time) {
    53  tickLoop:
    54  	for {
    55  		time.Sleep(t.calculateDelay())
    56  		// Send best-effort then go back to sleep.
    57  		select {
    58  		case <-t.stop:
    59  			log.Info("Stopping jittered ticker")
    60  			close(c)
    61  			break tickLoop
    62  		case c <- time.Now():
    63  		default:
    64  		}
    65  	}
    66  }
    67  
    68  func (t *Ticker) calculateDelay() time.Duration {
    69  	// The weakness of this random number generator is not significant for
    70  	// calculating a delay.
    71  	//nolint:gosec
    72  	jitter := time.Duration(rand.Int63n(int64(t.MaxJitter)))
    73  	delay := t.MinDuration + jitter
    74  	return delay
    75  }
    76  
    77  // Stop the ticker
    78  func (t *Ticker) Stop() {
    79  	t.stop <- true
    80  }
    81  

View as plain text