Last active
March 21, 2023 15:11
-
-
Save wuriyanto48/086c3ba463fca1ec62bb77677bed6b09 to your computer and use it in GitHub Desktop.
Simple retry mechanism in Go
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package main | |
| import ( | |
| "context" | |
| "errors" | |
| "fmt" | |
| "time" | |
| ) | |
| type Func func() bool | |
| type CallbackFunc func() | |
| func Retry(ctx context.Context, n int, interval time.Duration, done chan<- bool, f Func, onSucceed CallbackFunc, onError CallbackFunc) { | |
| var i int = 1 | |
| go func(ctx context.Context, i int, n int, interval time.Duration, done chan<- bool, f Func, onSucceed CallbackFunc, onError CallbackFunc) { | |
| for { | |
| select { | |
| case <-ctx.Done(): | |
| fmt.Printf("worker canceled\n") | |
| done <- true | |
| return | |
| default: | |
| } | |
| succeed := f() | |
| if succeed { | |
| done <- true | |
| if onSucceed != nil { | |
| onSucceed() | |
| } | |
| return | |
| } | |
| if i >= n { | |
| done <- true | |
| if onError != nil { | |
| onError() | |
| } | |
| return | |
| } | |
| <-time.After(interval) | |
| i++ | |
| } | |
| }(ctx, i, n, interval, done, f, onSucceed, onError) | |
| } | |
| func main() { | |
| f := func() bool { | |
| resp, err := httpPost("not_ok") | |
| if err != nil { | |
| fmt.Println(err) | |
| return true | |
| } | |
| statusOK := resp.httpCode >= 200 && resp.httpCode < 300 | |
| if !statusOK { | |
| fmt.Println("retry") | |
| return false | |
| } | |
| return true | |
| } | |
| done := make(chan bool, 1) | |
| ctx, cancel := context.WithCancel(context.Background()) | |
| //ctx, cancel := context.WithTimeout(context.Background(), time.Millisecond*500) | |
| defer func() { cancel() }() | |
| onSucceed := func() { | |
| fmt.Println("execution succeed") | |
| } | |
| onError := func() { | |
| fmt.Println("execution error") | |
| } | |
| Retry(ctx, 5, 3*time.Second, done, f, onSucceed, onError) | |
| <-done | |
| //time.Sleep(time.Second * 15) | |
| } | |
| type response struct { | |
| httpCode int | |
| } | |
| func httpPost(data string) (*response, error) { | |
| if data == "fatal" { | |
| return nil, errors.New("fatal error") | |
| } | |
| if data == "not_ok" { | |
| return &response{httpCode: 400}, nil | |
| } | |
| return &response{httpCode: 200}, nil | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment