blob: ca57542d35089ddf59736dece941392c7931c9ef [file] [log] [blame]
khenaidoobf6e7bb2018-08-14 22:27:29 -04001/*
2 * Copyright 2018-present Open Networking Foundation
3
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7
8 * http://www.apache.org/licenses/LICENSE-2.0
9
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
khenaidoocfee5f42018-07-19 22:47:38 -040016package kvstore
17
serkant.uluderyac431f2c2021-02-24 17:32:43 +030018import (
yasin sapli5458a1c2021-06-14 22:24:38 +000019 "context"
serkant.uluderyac431f2c2021-02-24 17:32:43 +030020 "fmt"
yasin sapli5458a1c2021-06-14 22:24:38 +000021 "math"
22 "math/rand"
23 "time"
24)
25
26const (
27 minRetryInterval = 100
28 maxRetryInterval = 5000
29 incrementalFactor = 1.2
30 jitter = 0.2
serkant.uluderyac431f2c2021-02-24 17:32:43 +030031)
khenaidoocfee5f42018-07-19 22:47:38 -040032
33// ToString converts an interface value to a string. The interface should either be of
34// a string type or []byte. Otherwise, an error is returned.
35func ToString(value interface{}) (string, error) {
36 switch t := value.(type) {
37 case []byte:
38 return string(value.([]byte)), nil
39 case string:
40 return value.(string), nil
41 default:
42 return "", fmt.Errorf("unexpected-type-%T", t)
43 }
44}
45
46// ToByte converts an interface value to a []byte. The interface should either be of
47// a string type or []byte. Otherwise, an error is returned.
48func ToByte(value interface{}) ([]byte, error) {
49 switch t := value.(type) {
50 case []byte:
51 return value.([]byte), nil
52 case string:
53 return []byte(value.(string)), nil
54 default:
55 return nil, fmt.Errorf("unexpected-type-%T", t)
56 }
57}
serkant.uluderyac431f2c2021-02-24 17:32:43 +030058
yasin sapli5458a1c2021-06-14 22:24:38 +000059// backoff waits an amount of time that is proportional to the attempt value. The wait time in a range of
60// minRetryInterval and maxRetryInterval.
61func backoff(ctx context.Context, attempt int) error {
62 if attempt == 0 {
63 return nil
64 }
65 backoff := int(minRetryInterval + incrementalFactor*math.Exp(float64(attempt)))
66 backoff *= 1 + int(jitter*(rand.Float64()*2-1))
67 if backoff > maxRetryInterval {
68 backoff = maxRetryInterval
69 }
70 ticker := time.NewTicker(time.Duration(backoff) * time.Millisecond)
71 defer ticker.Stop()
72 select {
73 case <-ctx.Done():
74 return ctx.Err()
75 case <-ticker.C:
76 }
77 return nil
78}