-
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathreplay_test.go
More file actions
112 lines (97 loc) · 3.39 KB
/
Copy pathreplay_test.go
File metadata and controls
112 lines (97 loc) · 3.39 KB
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
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
package babelqueue
import (
"context"
"errors"
"testing"
"time"
)
func TestIsReplayAndBypassExternalEffects(t *testing.T) {
bg := context.Background()
if IsReplay(bg) {
t.Error("a plain context must not be a replay")
}
rp := withReplay(bg)
if !IsReplay(rp) {
t.Error("a withReplay context must be a replay")
}
ran := false
if err := BypassExternalEffects(bg, func() error { ran = true; return nil }); err != nil {
t.Fatal(err)
}
if !ran {
t.Error("fn must run when not a replay")
}
ran = false
if err := BypassExternalEffects(rp, func() error { ran = true; return errors.New("must not run") }); err != nil {
t.Fatalf("a replay must skip fn and return nil, got %v", err)
}
if ran {
t.Error("fn must be skipped on a replay")
}
}
func TestInMemoryTransportHeadersRoundTrip(t *testing.T) {
tr := NewInMemoryTransport()
if err := tr.PublishWithHeaders(context.Background(), "q", "body", map[string]string{HeaderReplayBypass: "1"}); err != nil {
t.Fatal(err)
}
msg, _ := tr.Pop(context.Background(), "q", 0)
if msg == nil || msg.Headers[HeaderReplayBypass] != "1" {
t.Fatalf("headers not carried through Pop: %+v", msg)
}
_ = tr.Publish(context.Background(), "q", "plain")
m2, _ := tr.Pop(context.Background(), "q", 0)
if m2.Headers[HeaderReplayBypass] != "" {
t.Error("a plain Publish must carry no replay header")
}
}
func TestRedriveBypassStampsHeaderAndConsumeSkipsEffects(t *testing.T) {
tr := NewInMemoryTransport()
deadLettered(t, tr, "orders.dlq", "urn:babel:orders:created", "orders", map[string]any{"order_id": 1})
res, err := Redrive(context.Background(), tr, "orders.dlq", RedriveOptions{Bypass: true})
if err != nil {
t.Fatal(err)
}
if res.Redriven != 1 || len(res.Items) != 1 || !res.Items[0].Bypassed {
t.Fatalf("expected one bypassed redrive: %+v", res)
}
msg, _ := tr.Pop(context.Background(), "orders", 0)
if msg == nil || msg.Headers[HeaderReplayBypass] != "1" {
t.Fatalf("redriven message is missing the bypass header: %+v", msg)
}
emailed := false
app := NewApp(tr)
app.Handle("urn:babel:orders:created", func(ctx context.Context, _ Envelope) error {
if !IsReplay(ctx) {
t.Error("the handler should see this delivery as a replay")
}
return BypassExternalEffects(ctx, func() error { emailed = true; return nil })
})
app.dispatch(context.Background(), msg)
if emailed {
t.Error("the external side-effect must be skipped on a bypassed replay")
}
}
func TestRedriveBypassWithoutHeaderSupportFallsBack(t *testing.T) {
base := NewInMemoryTransport()
deadLettered(t, base, "dlq", "urn:babel:orders:created", "orders", nil)
tr := plainTransport{inner: base}
res, err := Redrive(context.Background(), tr, "dlq", RedriveOptions{Bypass: true})
if err != nil {
t.Fatal(err)
}
if res.Redriven != 1 || res.Items[0].Bypassed {
t.Fatalf("Bypass must be a no-op when the transport is not a HeaderPublisher: %+v", res)
}
}
// plainTransport wraps InMemoryTransport but exposes only the base Transport methods, so it is
// deliberately NOT a HeaderPublisher.
type plainTransport struct{ inner *InMemoryTransport }
func (p plainTransport) Publish(ctx context.Context, q, b string) error {
return p.inner.Publish(ctx, q, b)
}
func (p plainTransport) Pop(ctx context.Context, q string, d time.Duration) (*ReceivedMessage, error) {
return p.inner.Pop(ctx, q, d)
}
func (p plainTransport) Ack(ctx context.Context, m *ReceivedMessage) error {
return p.inner.Ack(ctx, m)
}