Skip to content

Commit d9b5379

Browse files
authored
Merge pull request #10 from safedep/develop
Sync Develop with Main
2 parents 927db83 + 515cea6 commit d9b5379

4 files changed

Lines changed: 150 additions & 10 deletions

File tree

services/pkg/common/db/adapters/mysql_adapter.go

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"log"
66
"time"
77

8+
"github.com/safedep/gateway/services/pkg/common/utils"
89
"golang.org/x/net/context"
910
"gorm.io/driver/mysql"
1011
"gorm.io/gorm"
@@ -29,20 +30,23 @@ func NewMySqlAdapter(config MySqlAdapterConfig) (SqlDataAdapter, error) {
2930

3031
log.Printf("Connecting to MySQL database with %s@%s:%d", config.Username, config.Host, config.Port)
3132

32-
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
33-
retry := 5
34-
t := 1
33+
var db *gorm.DB
34+
var err error
3535

36-
// Retry connection to avoid race with DB container init
37-
for err != nil && t <= retry {
38-
log.Printf("[%d/%d] Failed to connect to MySQL server: %v", t, retry, err)
36+
retryN := 5
37+
utils.InvokeWithRetry(utils.RetryConfig{
38+
Count: retryN,
39+
Sleep: 1 * time.Second,
40+
}, func(n int) error {
3941
db, err = gorm.Open(mysql.Open(dsn), &gorm.Config{})
42+
if err != nil {
43+
log.Printf("[%d/%d] Failed to connect to MySQL server: %v",
44+
n, retryN, err)
45+
}
4046

41-
t += 1
42-
time.Sleep(1 * time.Second)
43-
}
47+
return err
48+
})
4449

45-
// Failed after retry
4650
if err != nil {
4751
return nil, err
4852
}

services/pkg/common/utils/retry.go

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
package utils
2+
3+
import (
4+
"errors"
5+
"time"
6+
)
7+
8+
var (
9+
errInvalidRetryCount = errors.New("invalid retry count")
10+
errInvalidSleepDuration = errors.New("must have a valid sleep")
11+
)
12+
13+
type RetriableFunc func(retryN int) error
14+
15+
type RetryConfig struct {
16+
Count int
17+
Sleep time.Duration
18+
}
19+
20+
func InvokeWithRetry(config RetryConfig, f RetriableFunc) error {
21+
if config.Count <= 0 {
22+
return errInvalidRetryCount
23+
}
24+
25+
now := time.Now()
26+
if now.Add(config.Sleep) == now {
27+
return errInvalidSleepDuration
28+
}
29+
30+
var err error
31+
for i := 0; i < config.Count; i += 1 {
32+
err = f(i + 1)
33+
if err == nil {
34+
break
35+
}
36+
37+
time.Sleep(config.Sleep)
38+
}
39+
40+
return err
41+
}
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
package utils
2+
3+
import (
4+
"errors"
5+
"testing"
6+
"time"
7+
8+
"github.com/stretchr/testify/assert"
9+
)
10+
11+
func TestInvokeWithRetry(t *testing.T) {
12+
cases := []struct {
13+
name string
14+
c RetryConfig
15+
f RetriableFunc
16+
err error
17+
}{
18+
{
19+
"Must fail with zero Count",
20+
RetryConfig{
21+
Count: 0,
22+
Sleep: 0,
23+
},
24+
func(n int) error { return nil },
25+
errInvalidRetryCount,
26+
},
27+
{
28+
"Must fail with zero Sleep",
29+
RetryConfig{
30+
Count: 1,
31+
Sleep: 0,
32+
},
33+
func(n int) error { return nil },
34+
errInvalidSleepDuration,
35+
},
36+
{
37+
"Retry is successful immediately",
38+
RetryConfig{
39+
Count: 1,
40+
Sleep: time.Millisecond * 2,
41+
},
42+
func(n int) error {
43+
return nil
44+
},
45+
nil,
46+
},
47+
{
48+
"Retry is successful after 5 attempts",
49+
RetryConfig{
50+
Count: 5,
51+
Sleep: time.Millisecond * 1,
52+
},
53+
func(n int) error {
54+
if n < 5 {
55+
return errors.New("< 5")
56+
}
57+
58+
return nil
59+
},
60+
nil,
61+
},
62+
{
63+
"Retry is never successful",
64+
RetryConfig{
65+
Count: 10,
66+
Sleep: time.Millisecond * 1,
67+
},
68+
func(n int) error {
69+
return errors.New("err")
70+
},
71+
errors.New("err"),
72+
},
73+
}
74+
75+
for _, test := range cases {
76+
t.Run(test.name, func(t *testing.T) {
77+
err := InvokeWithRetry(test.c, test.f)
78+
if test.err == nil {
79+
assert.Nil(t, err)
80+
} else {
81+
assert.Equal(t, test.err.Error(), err.Error())
82+
}
83+
})
84+
}
85+
}

services/pkg/dcs/opensearch.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,16 @@ func (s *opensearchIndexer) buildOpenSearchClient() (*opensearch.Client, error)
121121
}
122122

123123
func (s *opensearchIndexer) initOpenSearchIndex(name string) error {
124+
return utils.InvokeWithRetry(utils.RetryConfig{
125+
Count: 30,
126+
Sleep: time.Second * 1,
127+
}, func(n int) error {
128+
logger.Infof("Attempting to init opensearch index [retry=%d]", n)
129+
return s.initOpenSearchIndexInternal(name)
130+
})
131+
}
132+
133+
func (s *opensearchIndexer) initOpenSearchIndexInternal(name string) error {
124134
if s.client == nil {
125135
return errors.New("client is nil")
126136
}

0 commit comments

Comments
 (0)