Retry simulation for https://github.com/wal-g/wal-g/blob/feb60cc7d25056c443b310f99639c6effe32c01c/pkg/storages/s3/folder.go#L51
Copy and paste to https://go.dev/play/
or
place code in file retry_simulation.go
and run go run retry_simulation.go
Retry simulation for https://github.com/wal-g/wal-g/blob/feb60cc7d25056c443b310f99639c6effe32c01c/pkg/storages/s3/folder.go#L51
Copy and paste to https://go.dev/play/
or
place code in file retry_simulation.go
and run go run retry_simulation.go
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.") | |
} |