...
1 package redis_test
2
3 import (
4 "strconv"
5 "sync"
6
7 "github.com/go-redis/redis"
8
9 . "github.com/onsi/ginkgo"
10 . "github.com/onsi/gomega"
11 )
12
13 var _ = Describe("Tx", func() {
14 var client *redis.Client
15
16 BeforeEach(func() {
17 client = redis.NewClient(redisOptions())
18 Expect(client.FlushDB().Err()).NotTo(HaveOccurred())
19 })
20
21 AfterEach(func() {
22 Expect(client.Close()).NotTo(HaveOccurred())
23 })
24
25 It("should Watch", func() {
26 var incr func(string) error
27
28
29 incr = func(key string) error {
30 err := client.Watch(func(tx *redis.Tx) error {
31 n, err := tx.Get(key).Int64()
32 if err != nil && err != redis.Nil {
33 return err
34 }
35
36 _, err = tx.Pipelined(func(pipe redis.Pipeliner) error {
37 pipe.Set(key, strconv.FormatInt(n+1, 10), 0)
38 return nil
39 })
40 return err
41 }, key)
42 if err == redis.TxFailedErr {
43 return incr(key)
44 }
45 return err
46 }
47
48 var wg sync.WaitGroup
49 for i := 0; i < 100; i++ {
50 wg.Add(1)
51 go func() {
52 defer GinkgoRecover()
53 defer wg.Done()
54
55 err := incr("key")
56 Expect(err).NotTo(HaveOccurred())
57 }()
58 }
59 wg.Wait()
60
61 n, err := client.Get("key").Int64()
62 Expect(err).NotTo(HaveOccurred())
63 Expect(n).To(Equal(int64(100)))
64 })
65
66 It("should discard", func() {
67 err := client.Watch(func(tx *redis.Tx) error {
68 cmds, err := tx.Pipelined(func(pipe redis.Pipeliner) error {
69 pipe.Set("key1", "hello1", 0)
70 pipe.Discard()
71 pipe.Set("key2", "hello2", 0)
72 return nil
73 })
74 Expect(err).NotTo(HaveOccurred())
75 Expect(cmds).To(HaveLen(1))
76 return err
77 }, "key1", "key2")
78 Expect(err).NotTo(HaveOccurred())
79
80 get := client.Get("key1")
81 Expect(get.Err()).To(Equal(redis.Nil))
82 Expect(get.Val()).To(Equal(""))
83
84 get = client.Get("key2")
85 Expect(get.Err()).NotTo(HaveOccurred())
86 Expect(get.Val()).To(Equal("hello2"))
87 })
88
89 It("returns no error when there are no commands", func() {
90 err := client.Watch(func(tx *redis.Tx) error {
91 _, err := tx.Pipelined(func(redis.Pipeliner) error { return nil })
92 return err
93 })
94 Expect(err).NotTo(HaveOccurred())
95
96 v, err := client.Ping().Result()
97 Expect(err).NotTo(HaveOccurred())
98 Expect(v).To(Equal("PONG"))
99 })
100
101 It("should exec bulks", func() {
102 const N = 20000
103
104 err := client.Watch(func(tx *redis.Tx) error {
105 cmds, err := tx.Pipelined(func(pipe redis.Pipeliner) error {
106 for i := 0; i < N; i++ {
107 pipe.Incr("key")
108 }
109 return nil
110 })
111 Expect(err).NotTo(HaveOccurred())
112 Expect(len(cmds)).To(Equal(N))
113 for _, cmd := range cmds {
114 Expect(cmd.Err()).NotTo(HaveOccurred())
115 }
116 return err
117 })
118 Expect(err).NotTo(HaveOccurred())
119
120 num, err := client.Get("key").Int64()
121 Expect(err).NotTo(HaveOccurred())
122 Expect(num).To(Equal(int64(N)))
123 })
124
125 It("should recover from bad connection", func() {
126
127 cn, err := client.Pool().Get()
128 Expect(err).NotTo(HaveOccurred())
129
130 cn.SetNetConn(&badConn{})
131 client.Pool().Put(cn)
132
133 do := func() error {
134 err := client.Watch(func(tx *redis.Tx) error {
135 _, err := tx.Pipelined(func(pipe redis.Pipeliner) error {
136 pipe.Ping()
137 return nil
138 })
139 return err
140 })
141 return err
142 }
143
144 err = do()
145 Expect(err).To(MatchError("bad connection"))
146
147 err = do()
148 Expect(err).NotTo(HaveOccurred())
149 })
150 })
151
View as plain text