blob: 27dd50f37a56c8de186c9b57bf9ea1a92a21325a [file] [log] [blame]
Scott Baker2c1c4822019-10-16 11:02:41 -07001/*
Joey Armstrong7f8436c2023-07-09 20:23:27 -04002* Copyright 2018-2023 Open Networking Foundation (ONF) and the ONF Contributors
Scott Baker2c1c4822019-10-16 11:02:41 -07003
Joey Armstrong7f8436c2023-07-09 20:23:27 -04004* 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
Scott Baker2c1c4822019-10-16 11:02:41 -07007
Joey Armstrong7f8436c2023-07-09 20:23:27 -04008* http://www.apache.org/licenses/LICENSE-2.0
Scott Baker2c1c4822019-10-16 11:02:41 -07009
Joey Armstrong7f8436c2023-07-09 20:23:27 -040010* 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.
Scott Baker2c1c4822019-10-16 11:02:41 -070015 */
16package kvstore
17
serkant.uluderya2f2855e2021-01-30 12:43:40 +030018import (
Girish Gowdra248971a2021-06-01 15:14:15 -070019 "context"
serkant.uluderya2f2855e2021-01-30 12:43:40 +030020 "fmt"
Girish Gowdra248971a2021-06-01 15:14:15 -070021 "math"
22 "math/rand"
23 "time"
24)
25
26const (
27 minRetryInterval = 100
28 maxRetryInterval = 5000
29 incrementalFactor = 1.2
30 jitter = 0.2
serkant.uluderya2f2855e2021-01-30 12:43:40 +030031)
Scott Baker2c1c4822019-10-16 11:02:41 -070032
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.uluderya2f2855e2021-01-30 12:43:40 +030058
Girish Gowdra248971a2021-06-01 15:14:15 -070059// 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}