...

Source file src/github.com/go-redis/redis/tx_test.go

Documentation: github.com/go-redis/redis

     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  		// Transactionally increments key using GET and SET commands.
    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  		// Put bad connection in the pool.
   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