storj.io/minio@v0.0.0-20230509071714-0cbc90f649b1/cmd/crypto/retry.go (about) 1 // MinIO Cloud Storage, (C) 2020 MinIO, Inc. 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 15 package crypto 16 17 import ( 18 "math/rand" 19 "time" 20 ) 21 22 // default retry configuration 23 const ( 24 retryWaitMin = 100 * time.Millisecond // minimum retry limit. 25 retryWaitMax = 1500 * time.Millisecond // 1.5 secs worth of max retry. 26 ) 27 28 // LinearJitterBackoff provides the time.Duration for a caller to 29 // perform linear backoff based on the attempt number and with jitter to 30 // prevent a thundering herd. 31 // 32 // min and max here are *not* absolute values. The number to be multiplied by 33 // the attempt number will be chosen at random from between them, thus they are 34 // bounding the jitter. 35 // 36 // For instance: 37 // * To get strictly linear backoff of one second increasing each retry, set 38 // both to one second (1s, 2s, 3s, 4s, ...) 39 // * To get a small amount of jitter centered around one second increasing each 40 // retry, set to around one second, such as a min of 800ms and max of 1200ms 41 // (892ms, 2102ms, 2945ms, 4312ms, ...) 42 // * To get extreme jitter, set to a very wide spread, such as a min of 100ms 43 // and a max of 20s (15382ms, 292ms, 51321ms, 35234ms, ...) 44 func LinearJitterBackoff(min, max time.Duration, attemptNum int) time.Duration { 45 // attemptNum always starts at zero but we want to start at 1 for multiplication 46 attemptNum++ 47 48 if max <= min { 49 // Unclear what to do here, or they are the same, so return min * 50 // attemptNum 51 return min * time.Duration(attemptNum) 52 } 53 54 // Seed rand; doing this every time is fine 55 rand := rand.New(rand.NewSource(int64(time.Now().Nanosecond()))) 56 57 // Pick a random number that lies somewhere between the min and max and 58 // multiply by the attemptNum. attemptNum starts at zero so we always 59 // increment here. We first get a random percentage, then apply that to the 60 // difference between min and max, and add to min. 61 jitter := rand.Float64() * float64(max-min) 62 jitterMin := int64(jitter) + int64(min) 63 return time.Duration(jitterMin * int64(attemptNum)) 64 }