|
package main |
|
|
|
import ( |
|
"errors" |
|
"log" |
|
"math" |
|
"math/rand" |
|
"time" |
|
) |
|
|
|
var ( |
|
RangeMaxRetriesDefault = 10 |
|
RangeQueryMinRetryDelay = 30 * time.Millisecond |
|
RangeQueryMaxRetryDelay = 300 * time.Second |
|
MaxRetriesDefault = 15 |
|
) |
|
|
|
func getReaderSettings() (rangeEnabled bool, retriesCount int, minRetryDelay, maxRetryDelay time.Duration) { |
|
rangeEnabled = true |
|
|
|
retriesCount = RangeMaxRetriesDefault |
|
|
|
if minRetryDelay == 0 { |
|
minRetryDelay = RangeQueryMinRetryDelay |
|
} |
|
if maxRetryDelay == 0 { |
|
maxRetryDelay = RangeQueryMaxRetryDelay |
|
} |
|
|
|
return rangeEnabled, retriesCount, minRetryDelay, maxRetryDelay |
|
} |
|
|
|
func simulateRangeQuery() error { |
|
return errors.New("simulated range query error") |
|
} |
|
|
|
func getJitterDelay(duration time.Duration) time.Duration { |
|
return time.Duration(rand.Int63n(int64(duration)) + int64(duration)) |
|
} |
|
|
|
func getIncrSleep(retryCount int, minDelay time.Duration, maxDelay time.Duration) time.Duration { |
|
var delay time.Duration |
|
|
|
actualRetryCount := int(math.Log2(float64(minDelay))) + 1 |
|
if actualRetryCount < 63-retryCount { |
|
delay = time.Duration(1<<uint64(retryCount)) * getJitterDelay(minDelay) |
|
if delay > maxDelay { |
|
delay = getJitterDelay(maxDelay / 2) |
|
} |
|
} else { |
|
delay = getJitterDelay(maxDelay / 2) |
|
} |
|
return delay |
|
} |
|
|
|
func main() { |
|
rangeEnabled, retriesCount, minRetryDelay, maxRetryDelay := getReaderSettings() |
|
|
|
log.Printf("rangeEnabled: %v, retriesCount: %v, minRetryDelay: %v, maxRetryDelay: %v", rangeEnabled, retriesCount, minRetryDelay, maxRetryDelay) |
|
|
|
for i := 1; i <= retriesCount; i++ { |
|
log.Printf("Retry #%d for range query", i) |
|
|
|
err := simulateRangeQuery() |
|
if err == nil { |
|
log.Println("Range query successful!") |
|
break |
|
} |
|
|
|
if i == retriesCount { |
|
log.Println("Max retries reached, giving up.") |
|
break |
|
} |
|
|
|
// Calculate the retry delay |
|
retryDelay := getIncrSleep(i, minRetryDelay, maxRetryDelay) |
|
|
|
log.Printf("Range query failed. Retrying in %v...", retryDelay) |
|
//time.Sleep(retryDelay) |
|
} |
|
|
|
log.Println("Simulation finished.") |
|
} |