github.com/minio/minio-go/v6@v6.0.57/retry-continous.go (about)

     1  /*
     2   * MinIO Go Library for Amazon S3 Compatible Cloud Storage
     3   * Copyright 2015-2017 MinIO, Inc.
     4   *
     5   * Licensed under the Apache License, Version 2.0 (the "License");
     6   * you may not use this file except in compliance with the License.
     7   * You may obtain a copy of the License at
     8   *
     9   *     http://www.apache.org/licenses/LICENSE-2.0
    10   *
    11   * Unless required by applicable law or agreed to in writing, software
    12   * distributed under the License is distributed on an "AS IS" BASIS,
    13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    14   * See the License for the specific language governing permissions and
    15   * limitations under the License.
    16   */
    17  
    18  package minio
    19  
    20  import "time"
    21  
    22  // newRetryTimerContinous creates a timer with exponentially increasing delays forever.
    23  func (c Client) newRetryTimerContinous(unit time.Duration, cap time.Duration, jitter float64, doneCh chan struct{}) <-chan int {
    24  	attemptCh := make(chan int)
    25  
    26  	// normalize jitter to the range [0, 1.0]
    27  	if jitter < NoJitter {
    28  		jitter = NoJitter
    29  	}
    30  	if jitter > MaxJitter {
    31  		jitter = MaxJitter
    32  	}
    33  
    34  	// computes the exponential backoff duration according to
    35  	// https://www.awsarchitectureblog.com/2015/03/backoff.html
    36  	exponentialBackoffWait := func(attempt int) time.Duration {
    37  		// 1<<uint(attempt) below could overflow, so limit the value of attempt
    38  		maxAttempt := 30
    39  		if attempt > maxAttempt {
    40  			attempt = maxAttempt
    41  		}
    42  		//sleep = random_between(0, min(cap, base * 2 ** attempt))
    43  		sleep := unit * time.Duration(1<<uint(attempt))
    44  		if sleep > cap {
    45  			sleep = cap
    46  		}
    47  		if jitter != NoJitter {
    48  			sleep -= time.Duration(c.random.Float64() * float64(sleep) * jitter)
    49  		}
    50  		return sleep
    51  	}
    52  
    53  	go func() {
    54  		defer close(attemptCh)
    55  		var nextBackoff int
    56  		for {
    57  			select {
    58  			// Attempts starts.
    59  			case attemptCh <- nextBackoff:
    60  				nextBackoff++
    61  			case <-doneCh:
    62  				// Stop the routine.
    63  				return
    64  			}
    65  			time.Sleep(exponentialBackoffWait(nextBackoff))
    66  		}
    67  	}()
    68  	return attemptCh
    69  }