blob: 946dbf2458a07928dfa22fd9f0f30dcb35d947f1 [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 (
19 "bytes"
yasin sapli5458a1c2021-06-14 22:24:38 +000020 "context"
serkant.uluderyac431f2c2021-02-24 17:32:43 +030021 "fmt"
yasin sapli5458a1c2021-06-14 22:24:38 +000022 "math"
23 "math/rand"
24 "time"
25)
26
27const (
28 minRetryInterval = 100
29 maxRetryInterval = 5000
30 incrementalFactor = 1.2
31 jitter = 0.2
serkant.uluderyac431f2c2021-02-24 17:32:43 +030032)
khenaidoocfee5f42018-07-19 22:47:38 -040033
34// ToString converts an interface value to a string. The interface should either be of
35// a string type or []byte. Otherwise, an error is returned.
36func ToString(value interface{}) (string, error) {
37 switch t := value.(type) {
38 case []byte:
39 return string(value.([]byte)), nil
40 case string:
41 return value.(string), nil
42 default:
43 return "", fmt.Errorf("unexpected-type-%T", t)
44 }
45}
46
47// ToByte converts an interface value to a []byte. The interface should either be of
48// a string type or []byte. Otherwise, an error is returned.
49func ToByte(value interface{}) ([]byte, error) {
50 switch t := value.(type) {
51 case []byte:
52 return value.([]byte), nil
53 case string:
54 return []byte(value.(string)), nil
55 default:
56 return nil, fmt.Errorf("unexpected-type-%T", t)
57 }
58}
serkant.uluderyac431f2c2021-02-24 17:32:43 +030059
60// Helper function to verify mostly whether the content of two interface types are the same. Focus is []byte and
61// string types
62func isEqual(val1 interface{}, val2 interface{}) bool {
63 b1, err := ToByte(val1)
64 b2, er := ToByte(val2)
65 if err == nil && er == nil {
66 return bytes.Equal(b1, b2)
67 }
68 return val1 == val2
69}
yasin sapli5458a1c2021-06-14 22:24:38 +000070
71// backoff waits an amount of time that is proportional to the attempt value. The wait time in a range of
72// minRetryInterval and maxRetryInterval.
73func backoff(ctx context.Context, attempt int) error {
74 if attempt == 0 {
75 return nil
76 }
77 backoff := int(minRetryInterval + incrementalFactor*math.Exp(float64(attempt)))
78 backoff *= 1 + int(jitter*(rand.Float64()*2-1))
79 if backoff > maxRetryInterval {
80 backoff = maxRetryInterval
81 }
82 ticker := time.NewTicker(time.Duration(backoff) * time.Millisecond)
83 defer ticker.Stop()
84 select {
85 case <-ctx.Done():
86 return ctx.Err()
87 case <-ticker.C:
88 }
89 return nil
90}