-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathretry_test.go
79 lines (70 loc) · 1.75 KB
/
retry_test.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
69
70
71
72
73
74
75
76
77
78
79
package retry_test
import (
"context"
"encoding/json"
"net/http"
"net/http/httptest"
"reflect"
"testing"
"time"
"github.com/cenkalti/backoff/v3"
"github.com/izumin5210/hx"
"github.com/izumin5210/hx/plugins/retry"
)
func TestRetry(t *testing.T) {
type Message struct {
UserID int `json:"user_id"`
Body string `json:"body"`
}
var (
failCount = 2
gotMessages []Message
)
idempotencyKeys := map[string]interface{}{}
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
switch {
case r.Method == http.MethodPost && r.URL.Path == "/messages":
if failCount > 0 {
failCount--
w.WriteHeader(http.StatusBadGateway)
return
}
failCount--
if _, ok := idempotencyKeys[r.Header.Get("Idempotency-Key")]; ok {
w.WriteHeader(http.StatusNoContent)
return
}
var msg Message
json.NewDecoder(r.Body).Decode(&msg)
gotMessages = append(gotMessages, msg)
w.WriteHeader(http.StatusCreated)
json.NewEncoder(w).Encode(&msg)
default:
w.WriteHeader(http.StatusNotFound)
}
}))
defer ts.Close()
bo := backoff.NewExponentialBackOff()
bo.InitialInterval = 50 * time.Millisecond
bo.MaxInterval = 500 * time.Millisecond
in := Message{
UserID: 123,
Body: "Hello!",
}
var out Message
err := hx.Post(context.Background(), ts.URL+"/messages",
retry.When(hx.Any(hx.IsServerError, hx.IsTemporaryError), bo),
hx.JSON(&in),
hx.WhenSuccess(hx.AsJSON(&out)),
hx.WhenFailure(hx.AsError()),
)
if err != nil {
t.Errorf("returned %v, want nil", err)
}
if got, want := in, out; !reflect.DeepEqual(got, want) {
t.Errorf("returned %v, want %v", got, want)
}
if got, want := gotMessages, []Message{in}; !reflect.DeepEqual(got, want) {
t.Errorf("got %v, want %v", got, want)
}
}