1+ package util
2+
3+ import (
4+ "context"
5+ "time"
6+ )
7+
8+ // RetryFunc is a function type that will try to be called again if it doesn't work
9+ type RetryFunc func () bool
10+
11+ // RetryCallbackFunc is a function type for callback
12+ type RetryCallbackFunc func ()
13+
14+ // Retry is a wrapper function that is used to try to call external resources that have the potential to fail
15+ func Retry (ctx context.Context , n int , interval time.Duration ,
16+ done chan <- bool , f RetryFunc , onSucceed RetryCallbackFunc , onError RetryCallbackFunc ) {
17+ var i int = 1
18+ go func (ctx context.Context , i int , n int , interval time.Duration ,
19+ done chan <- bool , f RetryFunc , onSucceed RetryCallbackFunc , onError RetryCallbackFunc ) {
20+
21+ for {
22+ select {
23+ case <- ctx .Done ():
24+ done <- true
25+ return
26+ default :
27+ }
28+
29+ succeed := f ()
30+ if succeed {
31+ done <- true
32+
33+ if onSucceed != nil {
34+ onSucceed ()
35+ }
36+ return
37+ }
38+
39+ if i == n {
40+ done <- true
41+
42+ if onError != nil {
43+ onError ()
44+ }
45+ return
46+ }
47+
48+ <- time .After (interval )
49+
50+ i ++
51+
52+ }
53+ }(ctx , i , n , interval , done , f , onSucceed , onError )
54+ }
55+
56+ // Usage
57+
58+ // func main() {
59+ // f := func() bool {
60+ // resp, err := httpPost("not_ok")
61+ // if err != nil {
62+ // fmt.Println(err)
63+ // return true
64+ // }
65+
66+ // statusOK := resp.httpCode >= 200 && resp.httpCode < 300
67+ // if !statusOK {
68+ // fmt.Println("retry")
69+ // return false
70+ // }
71+
72+ // return true
73+ // }
74+
75+ // done := make(chan bool, 1)
76+
77+ // ctx, cancel := context.WithCancel(context.Background())
78+ // //ctx, cancel := context.WithTimeout(context.Background(), time.Millisecond*500)
79+ // defer func() { cancel() }()
80+
81+ // onSucceed := func() {
82+ // fmt.Println("execution succeed")
83+ // }
84+
85+ // onError := func() {
86+ // fmt.Println("execution error")
87+ // }
88+
89+ // Retry(ctx, 5, 3*time.Second, done, f, onSucceed, onError)
90+
91+ // <-done
92+
93+ // //time.Sleep(time.Second * 15)
94+ // }
95+
96+ // type response struct {
97+ // httpCode int
98+ // }
99+
100+ // func httpPost(data string) (*response, error) {
101+ // if data == "fatal" {
102+ // return nil, errors.New("fatal error")
103+ // }
104+
105+ // if data == "not_ok" {
106+ // return &response{httpCode: 400}, nil
107+ // }
108+
109+ // return &response{httpCode: 200}, nil
110+ // }
0 commit comments