-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathrepo.go
68 lines (59 loc) · 1.54 KB
/
repo.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
package main
import (
"context"
"encoding/json"
"errors"
"fmt"
"io"
"net/http"
"sync"
"time"
"github.com/rizanw/go-failsafecall"
)
var (
// use mutex to simulate expensive process during fetching data
mu sync.Mutex
)
// getPost simulates external call to fetch data from upstream (service/server/db/redis/etc)
func getPost(ctx context.Context, fs *failsafecall.Wrapper, postID int) (map[string]interface{}, error) {
var (
url = fmt.Sprintf("https://jsonplaceholder.typicode.com/posts/%d", postID)
callKey = fmt.Sprintf("post:%d", postID)
)
// use callwrapper to wrap fetching data
resp, err := fs.Call(ctx, callKey, func(ctx context.Context) (interface{}, error) {
if postID == 9 {
// trigger cb becomes half-open and then open
return nil, errors.New("post not found")
}
// simulate fetching data inside this func(ctx context.Context) (interface{}, error):
var result map[string]interface{}
req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
if err != nil {
return nil, err
}
resp, err := http.DefaultClient.Do(req)
if err != nil {
return nil, err
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
return nil, err
}
err = json.Unmarshal(body, &result)
if err != nil {
return nil, err
}
// simulating additional wait time
mu.Lock()
time.Sleep(2 * time.Second)
mu.Unlock()
return result, nil
}, failsafecall.WithCacheTTL(30))
if err != nil {
return nil, err
}
// parse response data
return resp.(map[string]interface{}), err
}