@@ -23,35 +23,37 @@ const maxRetries = 250
23
23
//
24
24
// This should by typically used to wrap transactions.
25
25
func Retry (ctx context.Context , f func (ctx context.Context ) error ) error {
26
- // TODO: the retry loop should be configurable.
27
26
var err error
28
27
for i := 0 ; i < maxRetries ; i ++ {
29
28
err = f (ctx )
30
- if err != nil {
31
- if errors .Is (err , context .Canceled ) {
32
- break
33
- }
34
-
35
- // No point in re-trying or logging a no-row or not found error.
36
- if errors .Is (err , sql .ErrNoRows ) || api .StatusErrorCheck (err , http .StatusNotFound ) {
37
- break
38
- }
39
-
40
- // Process actual errors.
41
- if IsRetriableError (err ) {
42
- if i == maxRetries {
43
- logger .Warn ("Database error, giving up" , logger.Ctx {"attempt" : i , "err" : err })
44
- break
45
- }
46
-
47
- logger .Debug ("Database error, retrying" , logger.Ctx {"attempt" : i , "err" : err })
48
- time .Sleep (jitter .Deviation (nil , 0.8 )(100 * time .Millisecond ))
49
- continue
50
- } else {
51
- logger .Debug ("Database error" , logger.Ctx {"err" : err })
52
- }
29
+ if err == nil {
30
+ // The function succeeded, we're done here.
31
+ break
53
32
}
54
- break
33
+
34
+ if errors .Is (err , context .Canceled ) {
35
+ // The function was canceled, don't retry.
36
+ break
37
+ }
38
+
39
+ // No point in re-trying or logging a no-row or not found error.
40
+ if errors .Is (err , sql .ErrNoRows ) || api .StatusErrorCheck (err , http .StatusNotFound ) {
41
+ break
42
+ }
43
+
44
+ // Process actual errors.
45
+ if ! IsRetriableError (err ) {
46
+ logger .Debug ("Database error" , logger.Ctx {"err" : err })
47
+ break
48
+ }
49
+
50
+ if i == maxRetries {
51
+ logger .Warn ("Database error, giving up" , logger.Ctx {"attempt" : i , "err" : err })
52
+ break
53
+ }
54
+
55
+ logger .Debug ("Database error, retrying" , logger.Ctx {"attempt" : i , "err" : err })
56
+ time .Sleep (jitter .Deviation (nil , 0.8 )(100 * time .Millisecond ))
55
57
}
56
58
57
59
return err
0 commit comments