diff options
Diffstat (limited to 'vendor/github.com/go-redis/redis')
53 files changed, 940 insertions, 8344 deletions
diff --git a/vendor/github.com/go-redis/redis/.travis.yml b/vendor/github.com/go-redis/redis/.travis.yml index c95b3e6c6..39ffc2bec 100644 --- a/vendor/github.com/go-redis/redis/.travis.yml +++ b/vendor/github.com/go-redis/redis/.travis.yml @@ -8,6 +8,7 @@ go: - 1.7.x - 1.8.x - 1.9.x + - 1.10.x - tip matrix: diff --git a/vendor/github.com/go-redis/redis/Makefile b/vendor/github.com/go-redis/redis/Makefile index 50fdc55a1..1fbdac91c 100644 --- a/vendor/github.com/go-redis/redis/Makefile +++ b/vendor/github.com/go-redis/redis/Makefile @@ -1,6 +1,7 @@ all: testdeps go test ./... go test ./... -short -race + env GOOS=linux GOARCH=386 go test ./... go vet testdeps: testdata/redis/src/redis-server @@ -15,5 +16,5 @@ testdata/redis: wget -qO- https://github.com/antirez/redis/archive/unstable.tar.gz | tar xvz --strip-components=1 -C $@ testdata/redis/src/redis-server: testdata/redis - sed -i 's/libjemalloc.a/libjemalloc.a -lrt/g' $</src/Makefile + sed -i.bak 's/libjemalloc.a/libjemalloc.a -lrt/g' $</src/Makefile cd $< && make all diff --git a/vendor/github.com/go-redis/redis/bench_test.go b/vendor/github.com/go-redis/redis/bench_test.go deleted file mode 100644 index f6b75c72a..000000000 --- a/vendor/github.com/go-redis/redis/bench_test.go +++ /dev/null @@ -1,216 +0,0 @@ -package redis_test - -import ( - "bytes" - "testing" - "time" - - "github.com/go-redis/redis" -) - -func benchmarkRedisClient(poolSize int) *redis.Client { - client := redis.NewClient(&redis.Options{ - Addr: ":6379", - DialTimeout: time.Second, - ReadTimeout: time.Second, - WriteTimeout: time.Second, - PoolSize: poolSize, - }) - if err := client.FlushDB().Err(); err != nil { - panic(err) - } - return client -} - -func BenchmarkRedisPing(b *testing.B) { - client := benchmarkRedisClient(10) - defer client.Close() - - b.ResetTimer() - - b.RunParallel(func(pb *testing.PB) { - for pb.Next() { - if err := client.Ping().Err(); err != nil { - b.Fatal(err) - } - } - }) -} - -func BenchmarkRedisSetString(b *testing.B) { - client := benchmarkRedisClient(10) - defer client.Close() - - value := string(bytes.Repeat([]byte{'1'}, 10000)) - - b.ResetTimer() - - b.RunParallel(func(pb *testing.PB) { - for pb.Next() { - if err := client.Set("key", value, 0).Err(); err != nil { - b.Fatal(err) - } - } - }) -} - -func BenchmarkRedisGetNil(b *testing.B) { - client := benchmarkRedisClient(10) - defer client.Close() - - b.ResetTimer() - - b.RunParallel(func(pb *testing.PB) { - for pb.Next() { - if err := client.Get("key").Err(); err != redis.Nil { - b.Fatal(err) - } - } - }) -} - -func benchmarkSetRedis(b *testing.B, poolSize, payloadSize int) { - client := benchmarkRedisClient(poolSize) - defer client.Close() - - value := string(bytes.Repeat([]byte{'1'}, payloadSize)) - - b.ResetTimer() - - b.RunParallel(func(pb *testing.PB) { - for pb.Next() { - if err := client.Set("key", value, 0).Err(); err != nil { - b.Fatal(err) - } - } - }) -} - -func BenchmarkSetRedis10Conns64Bytes(b *testing.B) { - benchmarkSetRedis(b, 10, 64) -} - -func BenchmarkSetRedis100Conns64Bytes(b *testing.B) { - benchmarkSetRedis(b, 100, 64) -} - -func BenchmarkSetRedis10Conns1KB(b *testing.B) { - benchmarkSetRedis(b, 10, 1024) -} - -func BenchmarkSetRedis100Conns1KB(b *testing.B) { - benchmarkSetRedis(b, 100, 1024) -} - -func BenchmarkSetRedis10Conns10KB(b *testing.B) { - benchmarkSetRedis(b, 10, 10*1024) -} - -func BenchmarkSetRedis100Conns10KB(b *testing.B) { - benchmarkSetRedis(b, 100, 10*1024) -} - -func BenchmarkSetRedis10Conns1MB(b *testing.B) { - benchmarkSetRedis(b, 10, 1024*1024) -} - -func BenchmarkSetRedis100Conns1MB(b *testing.B) { - benchmarkSetRedis(b, 100, 1024*1024) -} - -func BenchmarkRedisSetGetBytes(b *testing.B) { - client := benchmarkRedisClient(10) - defer client.Close() - - value := bytes.Repeat([]byte{'1'}, 10000) - - b.ResetTimer() - - b.RunParallel(func(pb *testing.PB) { - for pb.Next() { - if err := client.Set("key", value, 0).Err(); err != nil { - b.Fatal(err) - } - - got, err := client.Get("key").Bytes() - if err != nil { - b.Fatal(err) - } - if !bytes.Equal(got, value) { - b.Fatalf("got != value") - } - } - }) -} - -func BenchmarkRedisMGet(b *testing.B) { - client := benchmarkRedisClient(10) - defer client.Close() - - if err := client.MSet("key1", "hello1", "key2", "hello2").Err(); err != nil { - b.Fatal(err) - } - - b.ResetTimer() - - b.RunParallel(func(pb *testing.PB) { - for pb.Next() { - if err := client.MGet("key1", "key2").Err(); err != nil { - b.Fatal(err) - } - } - }) -} - -func BenchmarkSetExpire(b *testing.B) { - client := benchmarkRedisClient(10) - defer client.Close() - - b.ResetTimer() - - b.RunParallel(func(pb *testing.PB) { - for pb.Next() { - if err := client.Set("key", "hello", 0).Err(); err != nil { - b.Fatal(err) - } - if err := client.Expire("key", time.Second).Err(); err != nil { - b.Fatal(err) - } - } - }) -} - -func BenchmarkPipeline(b *testing.B) { - client := benchmarkRedisClient(10) - defer client.Close() - - b.ResetTimer() - - b.RunParallel(func(pb *testing.PB) { - for pb.Next() { - _, err := client.Pipelined(func(pipe redis.Pipeliner) error { - pipe.Set("key", "hello", 0) - pipe.Expire("key", time.Second) - return nil - }) - if err != nil { - b.Fatal(err) - } - } - }) -} - -func BenchmarkZAdd(b *testing.B) { - client := benchmarkRedisClient(10) - defer client.Close() - - b.ResetTimer() - - b.RunParallel(func(pb *testing.PB) { - for pb.Next() { - if err := client.ZAdd("key", redis.Z{float64(1), "hello"}).Err(); err != nil { - b.Fatal(err) - } - } - }) -} diff --git a/vendor/github.com/go-redis/redis/cluster.go b/vendor/github.com/go-redis/redis/cluster.go index a2c18b387..4a2951157 100644 --- a/vendor/github.com/go-redis/redis/cluster.go +++ b/vendor/github.com/go-redis/redis/cluster.go @@ -1,7 +1,10 @@ package redis import ( + "context" + "errors" "fmt" + "math" "math/rand" "net" "sync" @@ -12,10 +15,10 @@ import ( "github.com/go-redis/redis/internal/hashtag" "github.com/go-redis/redis/internal/pool" "github.com/go-redis/redis/internal/proto" + "github.com/go-redis/redis/internal/singleflight" ) var errClusterNoNodes = fmt.Errorf("redis: cluster has no nodes") -var errNilClusterState = fmt.Errorf("redis: cannot load cluster slots") // ClusterOptions are used to configure a cluster client and should be // passed to NewClusterClient. @@ -25,13 +28,15 @@ type ClusterOptions struct { // The maximum number of retries before giving up. Command is retried // on network errors and MOVED/ASK redirects. - // Default is 16. + // Default is 8. MaxRedirects int // Enables read-only commands on slave nodes. ReadOnly bool // Allows routing read-only commands to the closest master or slave node. RouteByLatency bool + // Allows routing read-only commands to the random master or slave node. + RouteRandomly bool // Following options are copied from Options struct. @@ -57,7 +62,7 @@ func (opt *ClusterOptions) init() { if opt.MaxRedirects == -1 { opt.MaxRedirects = 0 } else if opt.MaxRedirects == 0 { - opt.MaxRedirects = 16 + opt.MaxRedirects = 8 } if opt.RouteByLatency { @@ -118,11 +123,11 @@ func (opt *ClusterOptions) clientOptions() *Options { //------------------------------------------------------------------------------ type clusterNode struct { - Client *Client - Latency time.Duration + Client *Client - loading time.Time - generation uint32 + latency uint32 // atomic + generation uint32 // atomic + loading uint32 // atomic } func newClusterNode(clOpt *ClusterOptions, addr string) *clusterNode { @@ -132,36 +137,69 @@ func newClusterNode(clOpt *ClusterOptions, addr string) *clusterNode { Client: NewClient(opt), } + node.latency = math.MaxUint32 if clOpt.RouteByLatency { - node.updateLatency() + go node.updateLatency() } return &node } +func (n *clusterNode) Close() error { + return n.Client.Close() +} + +func (n *clusterNode) Test() error { + return n.Client.ClusterInfo().Err() +} + func (n *clusterNode) updateLatency() { const probes = 10 + + var latency uint32 for i := 0; i < probes; i++ { start := time.Now() n.Client.Ping() - n.Latency += time.Since(start) + probe := uint32(time.Since(start) / time.Microsecond) + latency = (latency + probe) / 2 } - n.Latency = n.Latency / probes + atomic.StoreUint32(&n.latency, latency) +} + +func (n *clusterNode) Latency() time.Duration { + latency := atomic.LoadUint32(&n.latency) + return time.Duration(latency) * time.Microsecond +} + +func (n *clusterNode) MarkAsLoading() { + atomic.StoreUint32(&n.loading, uint32(time.Now().Unix())) } func (n *clusterNode) Loading() bool { - return !n.loading.IsZero() && time.Since(n.loading) < time.Minute + const minute = int64(time.Minute / time.Second) + + loading := atomic.LoadUint32(&n.loading) + if loading == 0 { + return false + } + if time.Now().Unix()-int64(loading) < minute { + return true + } + atomic.StoreUint32(&n.loading, 0) + return false } func (n *clusterNode) Generation() uint32 { - return n.generation + return atomic.LoadUint32(&n.generation) } func (n *clusterNode) SetGeneration(gen uint32) { - if gen < n.generation { - panic("gen < n.generation") + for { + v := atomic.LoadUint32(&n.generation) + if gen < v || atomic.CompareAndSwapUint32(&n.generation, v, gen) { + break + } } - n.generation = gen } //------------------------------------------------------------------------------ @@ -169,18 +207,23 @@ func (n *clusterNode) SetGeneration(gen uint32) { type clusterNodes struct { opt *ClusterOptions - mu sync.RWMutex - addrs []string - nodes map[string]*clusterNode - closed bool + mu sync.RWMutex + allAddrs []string + allNodes map[string]*clusterNode + clusterAddrs []string + closed bool + + nodeCreateGroup singleflight.Group generation uint32 } func newClusterNodes(opt *ClusterOptions) *clusterNodes { return &clusterNodes{ - opt: opt, - nodes: make(map[string]*clusterNode), + opt: opt, + + allAddrs: opt.Addrs, + allNodes: make(map[string]*clusterNode), } } @@ -194,21 +237,29 @@ func (c *clusterNodes) Close() error { c.closed = true var firstErr error - for _, node := range c.nodes { + for _, node := range c.allNodes { if err := node.Client.Close(); err != nil && firstErr == nil { firstErr = err } } - c.addrs = nil - c.nodes = nil + + c.allNodes = nil + c.clusterAddrs = nil return firstErr } func (c *clusterNodes) Addrs() ([]string, error) { + var addrs []string c.mu.RLock() closed := c.closed - addrs := c.addrs + if !closed { + if len(c.clusterAddrs) > 0 { + addrs = c.clusterAddrs + } else { + addrs = c.allAddrs + } + } c.mu.RUnlock() if closed { @@ -229,55 +280,45 @@ func (c *clusterNodes) NextGeneration() uint32 { func (c *clusterNodes) GC(generation uint32) { var collected []*clusterNode c.mu.Lock() - for i := 0; i < len(c.addrs); { - addr := c.addrs[i] - node := c.nodes[addr] + for addr, node := range c.allNodes { if node.Generation() >= generation { - i++ continue } - c.addrs = append(c.addrs[:i], c.addrs[i+1:]...) - delete(c.nodes, addr) + c.clusterAddrs = remove(c.clusterAddrs, addr) + delete(c.allNodes, addr) collected = append(collected, node) } c.mu.Unlock() - time.AfterFunc(time.Minute, func() { - for _, node := range collected { - _ = node.Client.Close() - } - }) -} - -func (c *clusterNodes) All() ([]*clusterNode, error) { - c.mu.RLock() - defer c.mu.RUnlock() - - if c.closed { - return nil, pool.ErrClosed + for _, node := range collected { + _ = node.Client.Close() } - - nodes := make([]*clusterNode, 0, len(c.nodes)) - for _, node := range c.nodes { - nodes = append(nodes, node) - } - return nodes, nil } func (c *clusterNodes) GetOrCreate(addr string) (*clusterNode, error) { var node *clusterNode - var ok bool + var err error c.mu.RLock() - if !c.closed { - node, ok = c.nodes[addr] + if c.closed { + err = pool.ErrClosed + } else { + node = c.allNodes[addr] } c.mu.RUnlock() - if ok { + if err != nil { + return nil, err + } + if node != nil { return node, nil } + v, err := c.nodeCreateGroup.Do(addr, func() (interface{}, error) { + node := newClusterNode(c.opt, addr) + return node, node.Test() + }) + c.mu.Lock() defer c.mu.Unlock() @@ -285,15 +326,35 @@ func (c *clusterNodes) GetOrCreate(addr string) (*clusterNode, error) { return nil, pool.ErrClosed } - node, ok = c.nodes[addr] + node, ok := c.allNodes[addr] if ok { - return node, nil + _ = v.(*clusterNode).Close() + return node, err } + node = v.(*clusterNode) - c.addrs = append(c.addrs, addr) - node = newClusterNode(c.opt, addr) - c.nodes[addr] = node - return node, nil + c.allAddrs = appendIfNotExists(c.allAddrs, addr) + if err == nil { + c.clusterAddrs = append(c.clusterAddrs, addr) + } + c.allNodes[addr] = node + + return node, err +} + +func (c *clusterNodes) All() ([]*clusterNode, error) { + c.mu.RLock() + defer c.mu.RUnlock() + + if c.closed { + return nil, pool.ErrClosed + } + + cp := make([]*clusterNode, 0, len(c.allNodes)) + for _, node := range c.allNodes { + cp = append(cp, node) + } + return cp, nil } func (c *clusterNodes) Random() (*clusterNode, error) { @@ -302,20 +363,8 @@ func (c *clusterNodes) Random() (*clusterNode, error) { return nil, err } - var nodeErr error - for i := 0; i <= c.opt.MaxRedirects; i++ { - n := rand.Intn(len(addrs)) - node, err := c.GetOrCreate(addrs[n]) - if err != nil { - return nil, err - } - - nodeErr = node.Client.ClusterInfo().Err() - if nodeErr == nil { - return node, nil - } - } - return nil, nodeErr + n := rand.Intn(len(addrs)) + return c.GetOrCreate(addrs[n]) } //------------------------------------------------------------------------------ @@ -367,6 +416,10 @@ func newClusterState(nodes *clusterNodes, slots []ClusterSlot, origin string) (* } } + time.AfterFunc(time.Minute, func() { + nodes.GC(c.generation) + }) + return &c, nil } @@ -416,13 +469,19 @@ func (c *clusterState) slotClosestNode(slot int) (*clusterNode, error) { if n.Loading() { continue } - if node == nil || node.Latency-n.Latency > threshold { + if node == nil || node.Latency()-n.Latency() > threshold { node = n } } return node, nil } +func (c *clusterState) slotRandomNode(slot int) *clusterNode { + nodes := c.slotNodes(slot) + n := rand.Intn(len(nodes)) + return nodes[n] +} + func (c *clusterState) slotNodes(slot int) []*clusterNode { if slot >= 0 && slot < len(c.slots) { return c.slots[slot] @@ -432,25 +491,83 @@ func (c *clusterState) slotNodes(slot int) []*clusterNode { //------------------------------------------------------------------------------ +type clusterStateHolder struct { + load func() (*clusterState, error) + + state atomic.Value + + lastErrMu sync.RWMutex + lastErr error + + reloading uint32 // atomic +} + +func newClusterStateHolder(fn func() (*clusterState, error)) *clusterStateHolder { + return &clusterStateHolder{ + load: fn, + } +} + +func (c *clusterStateHolder) Load() (*clusterState, error) { + state, err := c.load() + if err != nil { + c.lastErrMu.Lock() + c.lastErr = err + c.lastErrMu.Unlock() + return nil, err + } + c.state.Store(state) + return state, nil +} + +func (c *clusterStateHolder) LazyReload() { + if !atomic.CompareAndSwapUint32(&c.reloading, 0, 1) { + return + } + go func() { + defer atomic.StoreUint32(&c.reloading, 0) + + _, err := c.Load() + if err == nil { + time.Sleep(time.Second) + } + }() +} + +func (c *clusterStateHolder) Get() (*clusterState, error) { + v := c.state.Load() + if v != nil { + return v.(*clusterState), nil + } + + c.lastErrMu.RLock() + err := c.lastErr + c.lastErrMu.RUnlock() + if err != nil { + return nil, err + } + + return nil, errors.New("redis: cluster has no state") +} + +//------------------------------------------------------------------------------ + // ClusterClient is a Redis Cluster client representing a pool of zero // or more underlying connections. It's safe for concurrent use by // multiple goroutines. type ClusterClient struct { cmdable - opt *ClusterOptions - nodes *clusterNodes - _state atomic.Value + ctx context.Context - cmdsInfoOnce internal.Once - cmdsInfo map[string]*CommandInfo + opt *ClusterOptions + nodes *clusterNodes + state *clusterStateHolder + cmdsInfoCache *cmdsInfoCache process func(Cmder) error processPipeline func([]Cmder) error processTxPipeline func([]Cmder) error - - // Reports whether slots reloading is in progress. - reloading uint32 } // NewClusterClient returns a Redis Cluster client as described in @@ -459,9 +576,11 @@ func NewClusterClient(opt *ClusterOptions) *ClusterClient { opt.init() c := &ClusterClient{ - opt: opt, - nodes: newClusterNodes(opt), + opt: opt, + nodes: newClusterNodes(opt), + cmdsInfoCache: newCmdsInfoCache(), } + c.state = newClusterStateHolder(c.loadState) c.process = c.defaultProcess c.processPipeline = c.defaultProcessPipeline @@ -469,25 +588,33 @@ func NewClusterClient(opt *ClusterOptions) *ClusterClient { c.cmdable.setProcessor(c.Process) - // Add initial nodes. - for _, addr := range opt.Addrs { - _, _ = c.nodes.GetOrCreate(addr) + _, _ = c.state.Load() + if opt.IdleCheckFrequency > 0 { + go c.reaper(opt.IdleCheckFrequency) } - // Preload cluster slots. - for i := 0; i < 10; i++ { - state, err := c.reloadState() - if err == nil { - c._state.Store(state) - break - } + return c +} + +func (c *ClusterClient) Context() context.Context { + if c.ctx != nil { + return c.ctx } + return context.Background() +} - if opt.IdleCheckFrequency > 0 { - go c.reaper(opt.IdleCheckFrequency) +func (c *ClusterClient) WithContext(ctx context.Context) *ClusterClient { + if ctx == nil { + panic("nil context") } + c2 := c.copy() + c2.ctx = ctx + return c2 +} - return c +func (c *ClusterClient) copy() *ClusterClient { + cp := *c + return &cp } // Options returns read-only Options that were used to create the client. @@ -499,40 +626,18 @@ func (c *ClusterClient) retryBackoff(attempt int) time.Duration { return internal.RetryBackoff(attempt, c.opt.MinRetryBackoff, c.opt.MaxRetryBackoff) } -func (c *ClusterClient) state() (*clusterState, error) { - v := c._state.Load() - if v != nil { - return v.(*clusterState), nil - } - - _, err := c.nodes.Addrs() - if err != nil { - return nil, err - } - - c.lazyReloadState() - return nil, errNilClusterState -} - func (c *ClusterClient) cmdInfo(name string) *CommandInfo { - err := c.cmdsInfoOnce.Do(func() error { + cmdsInfo, err := c.cmdsInfoCache.Do(func() (map[string]*CommandInfo, error) { node, err := c.nodes.Random() if err != nil { - return err - } - - cmdsInfo, err := node.Client.Command().Result() - if err != nil { - return err + return nil, err } - - c.cmdsInfo = cmdsInfo - return nil + return node.Client.Command().Result() }) if err != nil { return nil } - info := c.cmdsInfo[name] + info := cmdsInfo[name] if info == nil { internal.Logf("info for cmd=%s not found", name) } @@ -552,7 +657,12 @@ func (c *ClusterClient) cmdSlot(cmd Cmder) int { return cmdSlot(cmd, cmdFirstKeyPos(cmd, cmdInfo)) } -func (c *ClusterClient) cmdSlotAndNode(state *clusterState, cmd Cmder) (int, *clusterNode, error) { +func (c *ClusterClient) cmdSlotAndNode(cmd Cmder) (int, *clusterNode, error) { + state, err := c.state.Get() + if err != nil { + return 0, nil, err + } + cmdInfo := c.cmdInfo(cmd.Name()) slot := cmdSlot(cmd, cmdFirstKeyPos(cmd, cmdInfo)) @@ -562,6 +672,11 @@ func (c *ClusterClient) cmdSlotAndNode(state *clusterState, cmd Cmder) (int, *cl return slot, node, err } + if c.opt.RouteRandomly { + node := state.slotRandomNode(slot) + return slot, node, nil + } + node, err := state.slotSlaveNode(slot) return slot, node, err } @@ -570,16 +685,24 @@ func (c *ClusterClient) cmdSlotAndNode(state *clusterState, cmd Cmder) (int, *cl return slot, node, err } +func (c *ClusterClient) slotMasterNode(slot int) (*clusterNode, error) { + state, err := c.state.Get() + if err != nil { + return nil, err + } + + nodes := state.slotNodes(slot) + if len(nodes) > 0 { + return nodes[0], nil + } + return c.nodes.Random() +} + func (c *ClusterClient) Watch(fn func(*Tx) error, keys ...string) error { if len(keys) == 0 { return fmt.Errorf("redis: keys don't hash to the same slot") } - state, err := c.state() - if err != nil { - return err - } - slot := hashtag.Slot(keys[0]) for _, key := range keys[1:] { if hashtag.Slot(key) != slot { @@ -587,7 +710,7 @@ func (c *ClusterClient) Watch(fn func(*Tx) error, keys ...string) error { } } - node, err := state.slotMasterNode(slot) + node, err := c.slotMasterNode(slot) if err != nil { return err } @@ -608,7 +731,7 @@ func (c *ClusterClient) Watch(fn func(*Tx) error, keys ...string) error { moved, ask, addr := internal.IsMovedError(err) if moved || ask { - c.lazyReloadState() + c.state.LazyReload() node, err = c.nodes.GetOrCreate(addr) if err != nil { return err @@ -617,10 +740,11 @@ func (c *ClusterClient) Watch(fn func(*Tx) error, keys ...string) error { } if err == pool.ErrClosed { - node, err = state.slotMasterNode(slot) + node, err = c.slotMasterNode(slot) if err != nil { return err } + continue } return err @@ -644,31 +768,27 @@ func (c *ClusterClient) WrapProcess( } func (c *ClusterClient) Process(cmd Cmder) error { - if c.process != nil { - return c.process(cmd) - } - return c.defaultProcess(cmd) + return c.process(cmd) } func (c *ClusterClient) defaultProcess(cmd Cmder) error { - state, err := c.state() - if err != nil { - cmd.setErr(err) - return err - } - - _, node, err := c.cmdSlotAndNode(state, cmd) - if err != nil { - cmd.setErr(err) - return err - } - + var node *clusterNode var ask bool for attempt := 0; attempt <= c.opt.MaxRedirects; attempt++ { if attempt > 0 { time.Sleep(c.retryBackoff(attempt)) } + if node == nil { + var err error + _, node, err = c.cmdSlotAndNode(cmd) + if err != nil { + cmd.setErr(err) + break + } + } + + var err error if ask { pipe := node.Client.Pipeline() _ = pipe.Process(NewCmd("ASKING")) @@ -687,15 +807,13 @@ func (c *ClusterClient) defaultProcess(cmd Cmder) error { // If slave is loading - read from master. if c.opt.ReadOnly && internal.IsLoadingError(err) { - // TODO: race - node.loading = time.Now() + node.MarkAsLoading() continue } if internal.IsRetryableError(err, true) { - var nodeErr error - node, nodeErr = c.nodes.Random() - if nodeErr != nil { + node, err = c.nodes.Random() + if err != nil { break } continue @@ -705,22 +823,18 @@ func (c *ClusterClient) defaultProcess(cmd Cmder) error { var addr string moved, ask, addr = internal.IsMovedError(err) if moved || ask { - c.lazyReloadState() + c.state.LazyReload() - var nodeErr error - node, nodeErr = c.nodes.GetOrCreate(addr) - if nodeErr != nil { + node, err = c.nodes.GetOrCreate(addr) + if err != nil { break } continue } if err == pool.ErrClosed { - _, node, err = c.cmdSlotAndNode(state, cmd) - if err != nil { - cmd.setErr(err) - return err - } + node = nil + continue } break @@ -732,7 +846,7 @@ func (c *ClusterClient) defaultProcess(cmd Cmder) error { // ForEachMaster concurrently calls the fn on each master node in the cluster. // It returns the first error if any. func (c *ClusterClient) ForEachMaster(fn func(client *Client) error) error { - state, err := c.state() + state, err := c.state.Get() if err != nil { return err } @@ -765,7 +879,7 @@ func (c *ClusterClient) ForEachMaster(fn func(client *Client) error) error { // ForEachSlave concurrently calls the fn on each slave node in the cluster. // It returns the first error if any. func (c *ClusterClient) ForEachSlave(fn func(client *Client) error) error { - state, err := c.state() + state, err := c.state.Get() if err != nil { return err } @@ -798,7 +912,7 @@ func (c *ClusterClient) ForEachSlave(fn func(client *Client) error) error { // ForEachNode concurrently calls the fn on each known node in the cluster. // It returns the first error if any. func (c *ClusterClient) ForEachNode(fn func(client *Client) error) error { - state, err := c.state() + state, err := c.state.Get() if err != nil { return err } @@ -838,7 +952,7 @@ func (c *ClusterClient) ForEachNode(fn func(client *Client) error) error { func (c *ClusterClient) PoolStats() *PoolStats { var acc PoolStats - state, _ := c.state() + state, _ := c.state.Get() if state == nil { return &acc } @@ -868,46 +982,34 @@ func (c *ClusterClient) PoolStats() *PoolStats { return &acc } -func (c *ClusterClient) lazyReloadState() { - if !atomic.CompareAndSwapUint32(&c.reloading, 0, 1) { - return +func (c *ClusterClient) loadState() (*clusterState, error) { + addrs, err := c.nodes.Addrs() + if err != nil { + return nil, err } - go func() { - defer atomic.StoreUint32(&c.reloading, 0) - - for { - state, err := c.reloadState() - if err == pool.ErrClosed { - return + var firstErr error + for _, addr := range addrs { + node, err := c.nodes.GetOrCreate(addr) + if err != nil { + if firstErr == nil { + firstErr = err } + continue + } - if err != nil { - time.Sleep(time.Millisecond) - continue + slots, err := node.Client.ClusterSlots().Result() + if err != nil { + if firstErr == nil { + firstErr = err } - - c._state.Store(state) - time.Sleep(5 * time.Second) - c.nodes.GC(state.generation) - break + continue } - }() -} -// Not thread-safe. -func (c *ClusterClient) reloadState() (*clusterState, error) { - node, err := c.nodes.Random() - if err != nil { - return nil, err - } - - slots, err := node.Client.ClusterSlots().Result() - if err != nil { - return nil, err + return newClusterState(c.nodes, slots, node.Client.opt.Addr) } - return newClusterState(c.nodes, slots, node.Client.opt.Addr) + return nil, firstErr } // reaper closes idle connections to the cluster. @@ -991,7 +1093,7 @@ func (c *ClusterClient) defaultProcessPipeline(cmds []Cmder) error { } func (c *ClusterClient) mapCmdsByNode(cmds []Cmder) (map[*clusterNode][]Cmder, error) { - state, err := c.state() + state, err := c.state.Get() if err != nil { setCmdsErr(cmds, err) return nil, err @@ -1024,15 +1126,17 @@ func (c *ClusterClient) remapCmds(cmds []Cmder, failedCmds map[*clusterNode][]Cm func (c *ClusterClient) pipelineProcessCmds( node *clusterNode, cn *pool.Conn, cmds []Cmder, failedCmds map[*clusterNode][]Cmder, ) error { - cn.SetWriteTimeout(c.opt.WriteTimeout) - if err := writeCmd(cn, cmds...); err != nil { + _ = cn.SetWriteTimeout(c.opt.WriteTimeout) + + err := writeCmd(cn, cmds...) + if err != nil { setCmdsErr(cmds, err) failedCmds[node] = cmds return err } // Set read timeout for all commands. - cn.SetReadTimeout(c.opt.ReadTimeout) + _ = cn.SetReadTimeout(c.opt.ReadTimeout) return c.pipelineReadCmds(cn, cmds, failedCmds) } @@ -1065,7 +1169,7 @@ func (c *ClusterClient) checkMovedErr( moved, ask, addr := internal.IsMovedError(err) if moved { - c.lazyReloadState() + c.state.LazyReload() node, err := c.nodes.GetOrCreate(addr) if err != nil { @@ -1103,7 +1207,7 @@ func (c *ClusterClient) TxPipelined(fn func(Pipeliner) error) ([]Cmder, error) { } func (c *ClusterClient) defaultProcessTxPipeline(cmds []Cmder) error { - state, err := c.state() + state, err := c.state.Get() if err != nil { return err } @@ -1249,12 +1353,7 @@ func (c *ClusterClient) pubSub(channels []string) *PubSub { slot = -1 } - state, err := c.state() - if err != nil { - return nil, err - } - - masterNode, err := state.slotMasterNode(slot) + masterNode, err := c.slotMasterNode(slot) if err != nil { return nil, err } @@ -1310,3 +1409,31 @@ func appendNode(nodes []*clusterNode, node *clusterNode) []*clusterNode { } return append(nodes, node) } + +func appendIfNotExists(ss []string, es ...string) []string { +loop: + for _, e := range es { + for _, s := range ss { + if s == e { + continue loop + } + } + ss = append(ss, e) + } + return ss +} + +func remove(ss []string, es ...string) []string { + if len(es) == 0 { + return ss[:0] + } + for _, e := range es { + for i, s := range ss { + if s == e { + ss = append(ss[:i], ss[i+1:]...) + break + } + } + } + return ss +} diff --git a/vendor/github.com/go-redis/redis/cluster_test.go b/vendor/github.com/go-redis/redis/cluster_test.go deleted file mode 100644 index 43f3261bc..000000000 --- a/vendor/github.com/go-redis/redis/cluster_test.go +++ /dev/null @@ -1,813 +0,0 @@ -package redis_test - -import ( - "bytes" - "fmt" - "net" - "strconv" - "strings" - "sync" - "testing" - "time" - - "github.com/go-redis/redis" - "github.com/go-redis/redis/internal/hashtag" - - . "github.com/onsi/ginkgo" - . "github.com/onsi/gomega" -) - -type clusterScenario struct { - ports []string - nodeIds []string - processes map[string]*redisProcess - clients map[string]*redis.Client -} - -func (s *clusterScenario) masters() []*redis.Client { - result := make([]*redis.Client, 3) - for pos, port := range s.ports[:3] { - result[pos] = s.clients[port] - } - return result -} - -func (s *clusterScenario) slaves() []*redis.Client { - result := make([]*redis.Client, 3) - for pos, port := range s.ports[3:] { - result[pos] = s.clients[port] - } - return result -} - -func (s *clusterScenario) addrs() []string { - addrs := make([]string, len(s.ports)) - for i, port := range s.ports { - addrs[i] = net.JoinHostPort("127.0.0.1", port) - } - return addrs -} - -func (s *clusterScenario) clusterClient(opt *redis.ClusterOptions) *redis.ClusterClient { - opt.Addrs = s.addrs() - return redis.NewClusterClient(opt) -} - -func startCluster(scenario *clusterScenario) error { - // Start processes and collect node ids - for pos, port := range scenario.ports { - process, err := startRedis(port, "--cluster-enabled", "yes") - if err != nil { - return err - } - - client := redis.NewClient(&redis.Options{ - Addr: ":" + port, - }) - - info, err := client.ClusterNodes().Result() - if err != nil { - return err - } - - scenario.processes[port] = process - scenario.clients[port] = client - scenario.nodeIds[pos] = info[:40] - } - - // Meet cluster nodes. - for _, client := range scenario.clients { - err := client.ClusterMeet("127.0.0.1", scenario.ports[0]).Err() - if err != nil { - return err - } - } - - // Bootstrap masters. - slots := []int{0, 5000, 10000, 16384} - for pos, master := range scenario.masters() { - err := master.ClusterAddSlotsRange(slots[pos], slots[pos+1]-1).Err() - if err != nil { - return err - } - } - - // Bootstrap slaves. - for idx, slave := range scenario.slaves() { - masterId := scenario.nodeIds[idx] - - // Wait until master is available - err := eventually(func() error { - s := slave.ClusterNodes().Val() - wanted := masterId - if !strings.Contains(s, wanted) { - return fmt.Errorf("%q does not contain %q", s, wanted) - } - return nil - }, 10*time.Second) - if err != nil { - return err - } - - err = slave.ClusterReplicate(masterId).Err() - if err != nil { - return err - } - } - - // Wait until all nodes have consistent info. - for _, client := range scenario.clients { - err := eventually(func() error { - res, err := client.ClusterSlots().Result() - if err != nil { - return err - } - wanted := []redis.ClusterSlot{ - {0, 4999, []redis.ClusterNode{{"", "127.0.0.1:8220"}, {"", "127.0.0.1:8223"}}}, - {5000, 9999, []redis.ClusterNode{{"", "127.0.0.1:8221"}, {"", "127.0.0.1:8224"}}}, - {10000, 16383, []redis.ClusterNode{{"", "127.0.0.1:8222"}, {"", "127.0.0.1:8225"}}}, - } - return assertSlotsEqual(res, wanted) - }, 30*time.Second) - if err != nil { - return err - } - } - - return nil -} - -func assertSlotsEqual(slots, wanted []redis.ClusterSlot) error { -outer_loop: - for _, s2 := range wanted { - for _, s1 := range slots { - if slotEqual(s1, s2) { - continue outer_loop - } - } - return fmt.Errorf("%v not found in %v", s2, slots) - } - return nil -} - -func slotEqual(s1, s2 redis.ClusterSlot) bool { - if s1.Start != s2.Start { - return false - } - if s1.End != s2.End { - return false - } - if len(s1.Nodes) != len(s2.Nodes) { - return false - } - for i, n1 := range s1.Nodes { - if n1.Addr != s2.Nodes[i].Addr { - return false - } - } - return true -} - -func stopCluster(scenario *clusterScenario) error { - for _, client := range scenario.clients { - if err := client.Close(); err != nil { - return err - } - } - for _, process := range scenario.processes { - if err := process.Close(); err != nil { - return err - } - } - return nil -} - -//------------------------------------------------------------------------------ - -var _ = Describe("ClusterClient", func() { - var opt *redis.ClusterOptions - var client *redis.ClusterClient - - assertClusterClient := func() { - It("should GET/SET/DEL", func() { - val, err := client.Get("A").Result() - Expect(err).To(Equal(redis.Nil)) - Expect(val).To(Equal("")) - - val, err = client.Set("A", "VALUE", 0).Result() - Expect(err).NotTo(HaveOccurred()) - Expect(val).To(Equal("OK")) - - Eventually(func() string { - return client.Get("A").Val() - }, 30*time.Second).Should(Equal("VALUE")) - - cnt, err := client.Del("A").Result() - Expect(err).NotTo(HaveOccurred()) - Expect(cnt).To(Equal(int64(1))) - }) - - It("follows redirects", func() { - Expect(client.Set("A", "VALUE", 0).Err()).NotTo(HaveOccurred()) - - slot := hashtag.Slot("A") - client.SwapSlotNodes(slot) - - Eventually(func() string { - return client.Get("A").Val() - }, 30*time.Second).Should(Equal("VALUE")) - }) - - It("distributes keys", func() { - for i := 0; i < 100; i++ { - err := client.Set(fmt.Sprintf("key%d", i), "value", 0).Err() - Expect(err).NotTo(HaveOccurred()) - } - - for _, master := range cluster.masters() { - Eventually(func() string { - return master.Info("keyspace").Val() - }, 30*time.Second).Should(Or( - ContainSubstring("keys=31"), - ContainSubstring("keys=29"), - ContainSubstring("keys=40"), - )) - } - }) - - It("distributes keys when using EVAL", func() { - script := redis.NewScript(` - local r = redis.call('SET', KEYS[1], ARGV[1]) - return r - `) - - var key string - for i := 0; i < 100; i++ { - key = fmt.Sprintf("key%d", i) - err := script.Run(client, []string{key}, "value").Err() - Expect(err).NotTo(HaveOccurred()) - } - - for _, master := range cluster.masters() { - Eventually(func() string { - return master.Info("keyspace").Val() - }, 30*time.Second).Should(Or( - ContainSubstring("keys=31"), - ContainSubstring("keys=29"), - ContainSubstring("keys=40"), - )) - } - }) - - It("supports Watch", func() { - var incr func(string) error - - // Transactionally increments key using GET and SET commands. - incr = func(key string) error { - err := client.Watch(func(tx *redis.Tx) error { - n, err := tx.Get(key).Int64() - if err != nil && err != redis.Nil { - return err - } - - _, err = tx.Pipelined(func(pipe redis.Pipeliner) error { - pipe.Set(key, strconv.FormatInt(n+1, 10), 0) - return nil - }) - return err - }, key) - if err == redis.TxFailedErr { - return incr(key) - } - return err - } - - var wg sync.WaitGroup - for i := 0; i < 100; i++ { - wg.Add(1) - go func() { - defer GinkgoRecover() - defer wg.Done() - - err := incr("key") - Expect(err).NotTo(HaveOccurred()) - }() - } - wg.Wait() - - n, err := client.Get("key").Int64() - Expect(err).NotTo(HaveOccurred()) - Expect(n).To(Equal(int64(100))) - }) - - Describe("pipelining", func() { - var pipe *redis.Pipeline - - assertPipeline := func() { - keys := []string{"A", "B", "C", "D", "E", "F", "G"} - - It("follows redirects", func() { - for _, key := range keys { - slot := hashtag.Slot(key) - client.SwapSlotNodes(slot) - } - - for i, key := range keys { - pipe.Set(key, key+"_value", 0) - pipe.Expire(key, time.Duration(i+1)*time.Hour) - } - cmds, err := pipe.Exec() - Expect(err).NotTo(HaveOccurred()) - Expect(cmds).To(HaveLen(14)) - - for _, key := range keys { - slot := hashtag.Slot(key) - client.SwapSlotNodes(slot) - } - - for _, key := range keys { - pipe.Get(key) - pipe.TTL(key) - } - cmds, err = pipe.Exec() - Expect(err).NotTo(HaveOccurred()) - Expect(cmds).To(HaveLen(14)) - - for i, key := range keys { - get := cmds[i*2].(*redis.StringCmd) - Expect(get.Val()).To(Equal(key + "_value")) - - ttl := cmds[(i*2)+1].(*redis.DurationCmd) - dur := time.Duration(i+1) * time.Hour - Expect(ttl.Val()).To(BeNumerically("~", dur, 5*time.Second)) - } - }) - - It("works with missing keys", func() { - pipe.Set("A", "A_value", 0) - pipe.Set("C", "C_value", 0) - _, err := pipe.Exec() - Expect(err).NotTo(HaveOccurred()) - - a := pipe.Get("A") - b := pipe.Get("B") - c := pipe.Get("C") - cmds, err := pipe.Exec() - Expect(err).To(Equal(redis.Nil)) - Expect(cmds).To(HaveLen(3)) - - Expect(a.Err()).NotTo(HaveOccurred()) - Expect(a.Val()).To(Equal("A_value")) - - Expect(b.Err()).To(Equal(redis.Nil)) - Expect(b.Val()).To(Equal("")) - - Expect(c.Err()).NotTo(HaveOccurred()) - Expect(c.Val()).To(Equal("C_value")) - }) - } - - Describe("with Pipeline", func() { - BeforeEach(func() { - pipe = client.Pipeline().(*redis.Pipeline) - }) - - AfterEach(func() { - Expect(pipe.Close()).NotTo(HaveOccurred()) - }) - - assertPipeline() - }) - - Describe("with TxPipeline", func() { - BeforeEach(func() { - pipe = client.TxPipeline().(*redis.Pipeline) - }) - - AfterEach(func() { - Expect(pipe.Close()).NotTo(HaveOccurred()) - }) - - assertPipeline() - }) - }) - - It("supports PubSub", func() { - pubsub := client.Subscribe("mychannel") - defer pubsub.Close() - - Eventually(func() error { - _, err := client.Publish("mychannel", "hello").Result() - if err != nil { - return err - } - - msg, err := pubsub.ReceiveTimeout(time.Second) - if err != nil { - return err - } - - _, ok := msg.(*redis.Message) - if !ok { - return fmt.Errorf("got %T, wanted *redis.Message", msg) - } - - return nil - }, 30*time.Second).ShouldNot(HaveOccurred()) - }) - } - - Describe("ClusterClient", func() { - BeforeEach(func() { - opt = redisClusterOptions() - client = cluster.clusterClient(opt) - - _ = client.ForEachMaster(func(master *redis.Client) error { - return master.FlushDB().Err() - }) - }) - - AfterEach(func() { - _ = client.ForEachMaster(func(master *redis.Client) error { - return master.FlushDB().Err() - }) - Expect(client.Close()).NotTo(HaveOccurred()) - }) - - It("returns pool stats", func() { - Expect(client.PoolStats()).To(BeAssignableToTypeOf(&redis.PoolStats{})) - }) - - It("removes idle connections", func() { - stats := client.PoolStats() - Expect(stats.TotalConns).NotTo(BeZero()) - Expect(stats.FreeConns).NotTo(BeZero()) - - time.Sleep(2 * time.Second) - - stats = client.PoolStats() - Expect(stats.TotalConns).To(BeZero()) - Expect(stats.FreeConns).To(BeZero()) - }) - - It("returns an error when there are no attempts left", func() { - opt := redisClusterOptions() - opt.MaxRedirects = -1 - client := cluster.clusterClient(opt) - - slot := hashtag.Slot("A") - client.SwapSlotNodes(slot) - - err := client.Get("A").Err() - Expect(err).To(HaveOccurred()) - Expect(err.Error()).To(ContainSubstring("MOVED")) - - Expect(client.Close()).NotTo(HaveOccurred()) - }) - - It("calls fn for every master node", func() { - for i := 0; i < 10; i++ { - Expect(client.Set(strconv.Itoa(i), "", 0).Err()).NotTo(HaveOccurred()) - } - - err := client.ForEachMaster(func(master *redis.Client) error { - return master.FlushDB().Err() - }) - Expect(err).NotTo(HaveOccurred()) - - size, err := client.DBSize().Result() - Expect(err).NotTo(HaveOccurred()) - Expect(size).To(Equal(int64(0))) - }) - - It("should CLUSTER SLOTS", func() { - res, err := client.ClusterSlots().Result() - Expect(err).NotTo(HaveOccurred()) - Expect(res).To(HaveLen(3)) - - wanted := []redis.ClusterSlot{ - {0, 4999, []redis.ClusterNode{{"", "127.0.0.1:8220"}, {"", "127.0.0.1:8223"}}}, - {5000, 9999, []redis.ClusterNode{{"", "127.0.0.1:8221"}, {"", "127.0.0.1:8224"}}}, - {10000, 16383, []redis.ClusterNode{{"", "127.0.0.1:8222"}, {"", "127.0.0.1:8225"}}}, - } - Expect(assertSlotsEqual(res, wanted)).NotTo(HaveOccurred()) - }) - - It("should CLUSTER NODES", func() { - res, err := client.ClusterNodes().Result() - Expect(err).NotTo(HaveOccurred()) - Expect(len(res)).To(BeNumerically(">", 400)) - }) - - It("should CLUSTER INFO", func() { - res, err := client.ClusterInfo().Result() - Expect(err).NotTo(HaveOccurred()) - Expect(res).To(ContainSubstring("cluster_known_nodes:6")) - }) - - It("should CLUSTER KEYSLOT", func() { - hashSlot, err := client.ClusterKeySlot("somekey").Result() - Expect(err).NotTo(HaveOccurred()) - Expect(hashSlot).To(Equal(int64(hashtag.Slot("somekey")))) - }) - - It("should CLUSTER COUNT-FAILURE-REPORTS", func() { - n, err := client.ClusterCountFailureReports(cluster.nodeIds[0]).Result() - Expect(err).NotTo(HaveOccurred()) - Expect(n).To(Equal(int64(0))) - }) - - It("should CLUSTER COUNTKEYSINSLOT", func() { - n, err := client.ClusterCountKeysInSlot(10).Result() - Expect(err).NotTo(HaveOccurred()) - Expect(n).To(Equal(int64(0))) - }) - - It("should CLUSTER SAVECONFIG", func() { - res, err := client.ClusterSaveConfig().Result() - Expect(err).NotTo(HaveOccurred()) - Expect(res).To(Equal("OK")) - }) - - It("should CLUSTER SLAVES", func() { - nodesList, err := client.ClusterSlaves(cluster.nodeIds[0]).Result() - Expect(err).NotTo(HaveOccurred()) - Expect(nodesList).Should(ContainElement(ContainSubstring("slave"))) - Expect(nodesList).Should(HaveLen(1)) - }) - - It("should RANDOMKEY", func() { - const nkeys = 100 - - for i := 0; i < nkeys; i++ { - err := client.Set(fmt.Sprintf("key%d", i), "value", 0).Err() - Expect(err).NotTo(HaveOccurred()) - } - - var keys []string - addKey := func(key string) { - for _, k := range keys { - if k == key { - return - } - } - keys = append(keys, key) - } - - for i := 0; i < nkeys*10; i++ { - key := client.RandomKey().Val() - addKey(key) - } - - Expect(len(keys)).To(BeNumerically("~", nkeys, nkeys/10)) - }) - - assertClusterClient() - }) - - Describe("ClusterClient failover", func() { - BeforeEach(func() { - opt = redisClusterOptions() - client = cluster.clusterClient(opt) - - _ = client.ForEachMaster(func(master *redis.Client) error { - return master.FlushDB().Err() - }) - - _ = client.ForEachSlave(func(slave *redis.Client) error { - Eventually(func() int64 { - return client.DBSize().Val() - }, 30*time.Second).Should(Equal(int64(0))) - return slave.ClusterFailover().Err() - }) - }) - - AfterEach(func() { - _ = client.ForEachMaster(func(master *redis.Client) error { - return master.FlushDB().Err() - }) - Expect(client.Close()).NotTo(HaveOccurred()) - }) - - assertClusterClient() - }) - - Describe("ClusterClient with RouteByLatency", func() { - BeforeEach(func() { - opt = redisClusterOptions() - opt.RouteByLatency = true - client = cluster.clusterClient(opt) - - _ = client.ForEachMaster(func(master *redis.Client) error { - return master.FlushDB().Err() - }) - - _ = client.ForEachSlave(func(slave *redis.Client) error { - Eventually(func() int64 { - return client.DBSize().Val() - }, 30*time.Second).Should(Equal(int64(0))) - return nil - }) - }) - - AfterEach(func() { - _ = client.ForEachMaster(func(master *redis.Client) error { - return master.FlushDB().Err() - }) - Expect(client.Close()).NotTo(HaveOccurred()) - }) - - assertClusterClient() - }) -}) - -var _ = Describe("ClusterClient without nodes", func() { - var client *redis.ClusterClient - - BeforeEach(func() { - client = redis.NewClusterClient(&redis.ClusterOptions{}) - }) - - AfterEach(func() { - Expect(client.Close()).NotTo(HaveOccurred()) - }) - - It("Ping returns an error", func() { - err := client.Ping().Err() - Expect(err).To(MatchError("redis: cluster has no nodes")) - }) - - It("pipeline returns an error", func() { - _, err := client.Pipelined(func(pipe redis.Pipeliner) error { - pipe.Ping() - return nil - }) - Expect(err).To(MatchError("redis: cluster has no nodes")) - }) -}) - -var _ = Describe("ClusterClient without valid nodes", func() { - var client *redis.ClusterClient - - BeforeEach(func() { - client = redis.NewClusterClient(&redis.ClusterOptions{ - Addrs: []string{redisAddr}, - }) - }) - - AfterEach(func() { - Expect(client.Close()).NotTo(HaveOccurred()) - }) - - It("returns an error", func() { - err := client.Ping().Err() - Expect(err).To(MatchError("redis: cannot load cluster slots")) - }) - - It("pipeline returns an error", func() { - _, err := client.Pipelined(func(pipe redis.Pipeliner) error { - pipe.Ping() - return nil - }) - Expect(err).To(MatchError("redis: cannot load cluster slots")) - }) -}) - -var _ = Describe("ClusterClient timeout", func() { - var client *redis.ClusterClient - - AfterEach(func() { - _ = client.Close() - }) - - testTimeout := func() { - It("Ping timeouts", func() { - err := client.Ping().Err() - Expect(err).To(HaveOccurred()) - Expect(err.(net.Error).Timeout()).To(BeTrue()) - }) - - It("Pipeline timeouts", func() { - _, err := client.Pipelined(func(pipe redis.Pipeliner) error { - pipe.Ping() - return nil - }) - Expect(err).To(HaveOccurred()) - Expect(err.(net.Error).Timeout()).To(BeTrue()) - }) - - It("Tx timeouts", func() { - err := client.Watch(func(tx *redis.Tx) error { - return tx.Ping().Err() - }, "foo") - Expect(err).To(HaveOccurred()) - Expect(err.(net.Error).Timeout()).To(BeTrue()) - }) - - It("Tx Pipeline timeouts", func() { - err := client.Watch(func(tx *redis.Tx) error { - _, err := tx.Pipelined(func(pipe redis.Pipeliner) error { - pipe.Ping() - return nil - }) - return err - }, "foo") - Expect(err).To(HaveOccurred()) - Expect(err.(net.Error).Timeout()).To(BeTrue()) - }) - } - - const pause = time.Second - - Context("read/write timeout", func() { - BeforeEach(func() { - opt := redisClusterOptions() - opt.ReadTimeout = 100 * time.Millisecond - opt.WriteTimeout = 100 * time.Millisecond - opt.MaxRedirects = 1 - client = cluster.clusterClient(opt) - - err := client.ForEachNode(func(client *redis.Client) error { - return client.ClientPause(pause).Err() - }) - Expect(err).NotTo(HaveOccurred()) - }) - - AfterEach(func() { - client.ForEachNode(func(client *redis.Client) error { - Eventually(func() error { - return client.Ping().Err() - }, 2*pause).ShouldNot(HaveOccurred()) - return nil - }) - }) - - testTimeout() - }) -}) - -//------------------------------------------------------------------------------ - -func BenchmarkRedisClusterPing(b *testing.B) { - if testing.Short() { - b.Skip("skipping in short mode") - } - - cluster := &clusterScenario{ - ports: []string{"8220", "8221", "8222", "8223", "8224", "8225"}, - nodeIds: make([]string, 6), - processes: make(map[string]*redisProcess, 6), - clients: make(map[string]*redis.Client, 6), - } - - if err := startCluster(cluster); err != nil { - b.Fatal(err) - } - defer stopCluster(cluster) - - client := cluster.clusterClient(redisClusterOptions()) - defer client.Close() - - b.ResetTimer() - - b.RunParallel(func(pb *testing.PB) { - for pb.Next() { - if err := client.Ping().Err(); err != nil { - b.Fatal(err) - } - } - }) -} - -func BenchmarkRedisClusterSetString(b *testing.B) { - if testing.Short() { - b.Skip("skipping in short mode") - } - - cluster := &clusterScenario{ - ports: []string{"8220", "8221", "8222", "8223", "8224", "8225"}, - nodeIds: make([]string, 6), - processes: make(map[string]*redisProcess, 6), - clients: make(map[string]*redis.Client, 6), - } - - if err := startCluster(cluster); err != nil { - b.Fatal(err) - } - defer stopCluster(cluster) - - client := cluster.clusterClient(redisClusterOptions()) - defer client.Close() - - value := string(bytes.Repeat([]byte{'1'}, 10000)) - - b.ResetTimer() - - b.RunParallel(func(pb *testing.PB) { - for pb.Next() { - if err := client.Set("key", value, 0).Err(); err != nil { - b.Fatal(err) - } - } - }) -} diff --git a/vendor/github.com/go-redis/redis/command.go b/vendor/github.com/go-redis/redis/command.go index 480a5ce19..1588ca251 100644 --- a/vendor/github.com/go-redis/redis/command.go +++ b/vendor/github.com/go-redis/redis/command.go @@ -10,6 +10,7 @@ import ( "github.com/go-redis/redis/internal" "github.com/go-redis/redis/internal/pool" "github.com/go-redis/redis/internal/proto" + "github.com/go-redis/redis/internal/util" ) type Cmder interface { @@ -436,7 +437,7 @@ func NewStringCmd(args ...interface{}) *StringCmd { } func (cmd *StringCmd) Val() string { - return internal.BytesToString(cmd.val) + return util.BytesToString(cmd.val) } func (cmd *StringCmd) Result() (string, error) { @@ -1022,3 +1023,26 @@ func (cmd *CommandsInfoCmd) readReply(cn *pool.Conn) error { cmd.val = v.(map[string]*CommandInfo) return nil } + +//------------------------------------------------------------------------------ + +type cmdsInfoCache struct { + once internal.Once + cmds map[string]*CommandInfo +} + +func newCmdsInfoCache() *cmdsInfoCache { + return &cmdsInfoCache{} +} + +func (c *cmdsInfoCache) Do(fn func() (map[string]*CommandInfo, error)) (map[string]*CommandInfo, error) { + err := c.once.Do(func() error { + cmds, err := fn() + if err != nil { + return err + } + c.cmds = cmds + return nil + }) + return c.cmds, err +} diff --git a/vendor/github.com/go-redis/redis/command_test.go b/vendor/github.com/go-redis/redis/command_test.go deleted file mode 100644 index e42375eda..000000000 --- a/vendor/github.com/go-redis/redis/command_test.go +++ /dev/null @@ -1,60 +0,0 @@ -package redis_test - -import ( - "github.com/go-redis/redis" - - . "github.com/onsi/ginkgo" - . "github.com/onsi/gomega" -) - -var _ = Describe("Cmd", func() { - var client *redis.Client - - BeforeEach(func() { - client = redis.NewClient(redisOptions()) - Expect(client.FlushDB().Err()).NotTo(HaveOccurred()) - }) - - AfterEach(func() { - Expect(client.Close()).NotTo(HaveOccurred()) - }) - - It("implements Stringer", func() { - set := client.Set("foo", "bar", 0) - Expect(set.String()).To(Equal("set foo bar: OK")) - - get := client.Get("foo") - Expect(get.String()).To(Equal("get foo: bar")) - }) - - It("has val/err", func() { - set := client.Set("key", "hello", 0) - Expect(set.Err()).NotTo(HaveOccurred()) - Expect(set.Val()).To(Equal("OK")) - - get := client.Get("key") - Expect(get.Err()).NotTo(HaveOccurred()) - Expect(get.Val()).To(Equal("hello")) - - Expect(set.Err()).NotTo(HaveOccurred()) - Expect(set.Val()).To(Equal("OK")) - }) - - It("has helpers", func() { - set := client.Set("key", "10", 0) - Expect(set.Err()).NotTo(HaveOccurred()) - - n, err := client.Get("key").Int64() - Expect(err).NotTo(HaveOccurred()) - Expect(n).To(Equal(int64(10))) - - un, err := client.Get("key").Uint64() - Expect(err).NotTo(HaveOccurred()) - Expect(un).To(Equal(uint64(10))) - - f, err := client.Get("key").Float64() - Expect(err).NotTo(HaveOccurred()) - Expect(f).To(Equal(float64(10))) - }) - -}) diff --git a/vendor/github.com/go-redis/redis/commands.go b/vendor/github.com/go-redis/redis/commands.go index 569342cfa..a3dacacd2 100644 --- a/vendor/github.com/go-redis/redis/commands.go +++ b/vendor/github.com/go-redis/redis/commands.go @@ -1,6 +1,7 @@ package redis import ( + "errors" "io" "time" @@ -38,6 +39,22 @@ func formatSec(dur time.Duration) int64 { return int64(dur / time.Second) } +func appendArgs(dst, src []interface{}) []interface{} { + if len(src) == 1 { + if ss, ok := src[0].([]string); ok { + for _, s := range ss { + dst = append(dst, s) + } + return dst + } + } + + for _, v := range src { + dst = append(dst, v) + } + return dst +} + type Cmdable interface { Pipeline() Pipeliner Pipelined(fn func(Pipeliner) error) ([]Cmder, error) @@ -70,8 +87,10 @@ type Cmdable interface { RenameNX(key, newkey string) *BoolCmd Restore(key string, ttl time.Duration, value string) *StatusCmd RestoreReplace(key string, ttl time.Duration, value string) *StatusCmd - Sort(key string, sort Sort) *StringSliceCmd - SortInterfaces(key string, sort Sort) *SliceCmd + Sort(key string, sort *Sort) *StringSliceCmd + SortStore(key, store string, sort *Sort) *IntCmd + SortInterfaces(key string, sort *Sort) *SliceCmd + Touch(keys ...string) *IntCmd TTL(key string) *DurationCmd Type(key string) *StatusCmd Scan(cursor uint64, match string, count int64) *ScanCmd @@ -195,6 +214,7 @@ type Cmdable interface { ConfigGet(parameter string) *SliceCmd ConfigResetStat() *StatusCmd ConfigSet(parameter, value string) *StatusCmd + ConfigRewrite() *StatusCmd DBSize() *IntCmd FlushAll() *StatusCmd FlushAllAsync() *StatusCmd @@ -210,7 +230,7 @@ type Cmdable interface { Time() *TimeCmd Eval(script string, keys []string, args ...interface{}) *Cmd EvalSha(sha1 string, keys []string, args ...interface{}) *Cmd - ScriptExists(scripts ...string) *BoolSliceCmd + ScriptExists(hashes ...string) *BoolSliceCmd ScriptFlush() *StatusCmd ScriptKill() *StatusCmd ScriptLoad(script string) *StringCmd @@ -252,6 +272,7 @@ type StatefulCmdable interface { Cmdable Auth(password string) *StatusCmd Select(index int) *StatusCmd + SwapDB(index1, index2 int) *StatusCmd ClientSetName(name string) *BoolCmd ReadOnly() *StatusCmd ReadWrite() *StatusCmd @@ -316,6 +337,12 @@ func (c *statefulCmdable) Select(index int) *StatusCmd { return cmd } +func (c *statefulCmdable) SwapDB(index1, index2 int) *StatusCmd { + cmd := NewStatusCmd("swapdb", index1, index2) + c.process(cmd) + return cmd +} + //------------------------------------------------------------------------------ func (c *cmdable) Del(keys ...string) *IntCmd { @@ -484,11 +511,10 @@ func (c *cmdable) RestoreReplace(key string, ttl time.Duration, value string) *S type Sort struct { By string - Offset, Count float64 + Offset, Count int64 Get []string Order string - IsAlpha bool - Store string + Alpha bool } func (sort *Sort) args(key string) []interface{} { @@ -505,27 +531,45 @@ func (sort *Sort) args(key string) []interface{} { if sort.Order != "" { args = append(args, sort.Order) } - if sort.IsAlpha { + if sort.Alpha { args = append(args, "alpha") } - if sort.Store != "" { - args = append(args, "store", sort.Store) - } return args } -func (c *cmdable) Sort(key string, sort Sort) *StringSliceCmd { +func (c *cmdable) Sort(key string, sort *Sort) *StringSliceCmd { cmd := NewStringSliceCmd(sort.args(key)...) c.process(cmd) return cmd } -func (c *cmdable) SortInterfaces(key string, sort Sort) *SliceCmd { +func (c *cmdable) SortStore(key, store string, sort *Sort) *IntCmd { + args := sort.args(key) + if store != "" { + args = append(args, "store", store) + } + cmd := NewIntCmd(args...) + c.process(cmd) + return cmd +} + +func (c *cmdable) SortInterfaces(key string, sort *Sort) *SliceCmd { cmd := NewSliceCmd(sort.args(key)...) c.process(cmd) return cmd } +func (c *cmdable) Touch(keys ...string) *IntCmd { + args := make([]interface{}, len(keys)+1) + args[0] = "touch" + for i, key := range keys { + args[i+1] = key + } + cmd := NewIntCmd(args...) + c.process(cmd) + return cmd +} + func (c *cmdable) TTL(key string) *DurationCmd { cmd := NewDurationCmd(time.Second, "ttl", key) c.process(cmd) @@ -732,22 +776,18 @@ func (c *cmdable) MGet(keys ...string) *SliceCmd { } func (c *cmdable) MSet(pairs ...interface{}) *StatusCmd { - args := make([]interface{}, 1+len(pairs)) + args := make([]interface{}, 1, 1+len(pairs)) args[0] = "mset" - for i, pair := range pairs { - args[1+i] = pair - } + args = appendArgs(args, pairs) cmd := NewStatusCmd(args...) c.process(cmd) return cmd } func (c *cmdable) MSetNX(pairs ...interface{}) *BoolCmd { - args := make([]interface{}, 1+len(pairs)) + args := make([]interface{}, 1, 1+len(pairs)) args[0] = "msetnx" - for i, pair := range pairs { - args[1+i] = pair - } + args = appendArgs(args, pairs) cmd := NewBoolCmd(args...) c.process(cmd) return cmd @@ -1012,12 +1052,10 @@ func (c *cmdable) LPop(key string) *StringCmd { } func (c *cmdable) LPush(key string, values ...interface{}) *IntCmd { - args := make([]interface{}, 2+len(values)) + args := make([]interface{}, 2, 2+len(values)) args[0] = "lpush" args[1] = key - for i, value := range values { - args[2+i] = value - } + args = appendArgs(args, values) cmd := NewIntCmd(args...) c.process(cmd) return cmd @@ -1076,12 +1114,10 @@ func (c *cmdable) RPopLPush(source, destination string) *StringCmd { } func (c *cmdable) RPush(key string, values ...interface{}) *IntCmd { - args := make([]interface{}, 2+len(values)) + args := make([]interface{}, 2, 2+len(values)) args[0] = "rpush" args[1] = key - for i, value := range values { - args[2+i] = value - } + args = appendArgs(args, values) cmd := NewIntCmd(args...) c.process(cmd) return cmd @@ -1096,12 +1132,10 @@ func (c *cmdable) RPushX(key string, value interface{}) *IntCmd { //------------------------------------------------------------------------------ func (c *cmdable) SAdd(key string, members ...interface{}) *IntCmd { - args := make([]interface{}, 2+len(members)) + args := make([]interface{}, 2, 2+len(members)) args[0] = "sadd" args[1] = key - for i, member := range members { - args[2+i] = member - } + args = appendArgs(args, members) cmd := NewIntCmd(args...) c.process(cmd) return cmd @@ -1214,12 +1248,10 @@ func (c *cmdable) SRandMemberN(key string, count int64) *StringSliceCmd { } func (c *cmdable) SRem(key string, members ...interface{}) *IntCmd { - args := make([]interface{}, 2+len(members)) + args := make([]interface{}, 2, 2+len(members)) args[0] = "srem" args[1] = key - for i, member := range members { - args[2+i] = member - } + args = appendArgs(args, members) cmd := NewIntCmd(args...) c.process(cmd) return cmd @@ -1479,12 +1511,10 @@ func (c *cmdable) ZRank(key, member string) *IntCmd { } func (c *cmdable) ZRem(key string, members ...interface{}) *IntCmd { - args := make([]interface{}, 2+len(members)) + args := make([]interface{}, 2, 2+len(members)) args[0] = "zrem" args[1] = key - for i, member := range members { - args[2+i] = member - } + args = appendArgs(args, members) cmd := NewIntCmd(args...) c.process(cmd) return cmd @@ -1600,12 +1630,10 @@ func (c *cmdable) ZUnionStore(dest string, store ZStore, keys ...string) *IntCmd //------------------------------------------------------------------------------ func (c *cmdable) PFAdd(key string, els ...interface{}) *IntCmd { - args := make([]interface{}, 2+len(els)) + args := make([]interface{}, 2, 2+len(els)) args[0] = "pfadd" args[1] = key - for i, el := range els { - args[2+i] = el - } + args = appendArgs(args, els) cmd := NewIntCmd(args...) c.process(cmd) return cmd @@ -1698,6 +1726,12 @@ func (c *cmdable) ConfigSet(parameter, value string) *StatusCmd { return cmd } +func (c *cmdable) ConfigRewrite() *StatusCmd { + cmd := NewStatusCmd("config", "rewrite") + c.process(cmd) + return cmd +} + // Deperecated. Use DBSize instead. func (c *cmdable) DbSize() *IntCmd { return c.DBSize() @@ -1776,7 +1810,7 @@ func (c *cmdable) shutdown(modifier string) *StatusCmd { } } else { // Server did not quit. String reply contains the reason. - cmd.err = internal.RedisError(cmd.val) + cmd.err = errors.New(cmd.val) cmd.val = "" } return cmd @@ -1817,45 +1851,39 @@ func (c *cmdable) Time() *TimeCmd { //------------------------------------------------------------------------------ func (c *cmdable) Eval(script string, keys []string, args ...interface{}) *Cmd { - cmdArgs := make([]interface{}, 3+len(keys)+len(args)) + cmdArgs := make([]interface{}, 3+len(keys), 3+len(keys)+len(args)) cmdArgs[0] = "eval" cmdArgs[1] = script cmdArgs[2] = len(keys) for i, key := range keys { cmdArgs[3+i] = key } - pos := 3 + len(keys) - for i, arg := range args { - cmdArgs[pos+i] = arg - } + cmdArgs = appendArgs(cmdArgs, args) cmd := NewCmd(cmdArgs...) c.process(cmd) return cmd } func (c *cmdable) EvalSha(sha1 string, keys []string, args ...interface{}) *Cmd { - cmdArgs := make([]interface{}, 3+len(keys)+len(args)) + cmdArgs := make([]interface{}, 3+len(keys), 3+len(keys)+len(args)) cmdArgs[0] = "evalsha" cmdArgs[1] = sha1 cmdArgs[2] = len(keys) for i, key := range keys { cmdArgs[3+i] = key } - pos := 3 + len(keys) - for i, arg := range args { - cmdArgs[pos+i] = arg - } + cmdArgs = appendArgs(cmdArgs, args) cmd := NewCmd(cmdArgs...) c.process(cmd) return cmd } -func (c *cmdable) ScriptExists(scripts ...string) *BoolSliceCmd { - args := make([]interface{}, 2+len(scripts)) +func (c *cmdable) ScriptExists(hashes ...string) *BoolSliceCmd { + args := make([]interface{}, 2+len(hashes)) args[0] = "script" args[1] = "exists" - for i, script := range scripts { - args[2+i] = script + for i, hash := range hashes { + args[2+i] = hash } cmd := NewBoolSliceCmd(args...) c.process(cmd) diff --git a/vendor/github.com/go-redis/redis/commands_test.go b/vendor/github.com/go-redis/redis/commands_test.go deleted file mode 100644 index 715379556..000000000 --- a/vendor/github.com/go-redis/redis/commands_test.go +++ /dev/null @@ -1,2968 +0,0 @@ -package redis_test - -import ( - "encoding/json" - "fmt" - "reflect" - "time" - - . "github.com/onsi/ginkgo" - . "github.com/onsi/gomega" - - "github.com/go-redis/redis" -) - -var _ = Describe("Commands", func() { - var client *redis.Client - - BeforeEach(func() { - client = redis.NewClient(redisOptions()) - Expect(client.FlushDB().Err()).NotTo(HaveOccurred()) - }) - - AfterEach(func() { - Expect(client.Close()).NotTo(HaveOccurred()) - }) - - Describe("server", func() { - - It("should Auth", func() { - cmds, err := client.Pipelined(func(pipe redis.Pipeliner) error { - pipe.Auth("password") - pipe.Auth("") - return nil - }) - Expect(err).To(MatchError("ERR Client sent AUTH, but no password is set")) - Expect(cmds[0].Err()).To(MatchError("ERR Client sent AUTH, but no password is set")) - Expect(cmds[1].Err()).To(MatchError("ERR Client sent AUTH, but no password is set")) - - stats := client.PoolStats() - Expect(stats.Hits).To(Equal(uint32(1))) - Expect(stats.Misses).To(Equal(uint32(1))) - Expect(stats.Timeouts).To(Equal(uint32(0))) - Expect(stats.TotalConns).To(Equal(uint32(1))) - Expect(stats.FreeConns).To(Equal(uint32(1))) - }) - - It("should Echo", func() { - pipe := client.Pipeline() - echo := pipe.Echo("hello") - _, err := pipe.Exec() - Expect(err).NotTo(HaveOccurred()) - - Expect(echo.Err()).NotTo(HaveOccurred()) - Expect(echo.Val()).To(Equal("hello")) - }) - - It("should Ping", func() { - ping := client.Ping() - Expect(ping.Err()).NotTo(HaveOccurred()) - Expect(ping.Val()).To(Equal("PONG")) - }) - - It("should Wait", func() { - // assume testing on single redis instance - start := time.Now() - wait := client.Wait(1, time.Second) - Expect(wait.Err()).NotTo(HaveOccurred()) - Expect(wait.Val()).To(Equal(int64(0))) - Expect(time.Now()).To(BeTemporally("~", start.Add(time.Second), 800*time.Millisecond)) - }) - - It("should Select", func() { - pipe := client.Pipeline() - sel := pipe.Select(1) - _, err := pipe.Exec() - Expect(err).NotTo(HaveOccurred()) - - Expect(sel.Err()).NotTo(HaveOccurred()) - Expect(sel.Val()).To(Equal("OK")) - }) - - It("should BgRewriteAOF", func() { - Skip("flaky test") - - val, err := client.BgRewriteAOF().Result() - Expect(err).NotTo(HaveOccurred()) - Expect(val).To(ContainSubstring("Background append only file rewriting")) - }) - - It("should BgSave", func() { - Skip("flaky test") - - // workaround for "ERR Can't BGSAVE while AOF log rewriting is in progress" - Eventually(func() string { - return client.BgSave().Val() - }, "30s").Should(Equal("Background saving started")) - }) - - It("should ClientKill", func() { - r := client.ClientKill("1.1.1.1:1111") - Expect(r.Err()).To(MatchError("ERR No such client")) - Expect(r.Val()).To(Equal("")) - }) - - It("should ClientPause", func() { - err := client.ClientPause(time.Second).Err() - Expect(err).NotTo(HaveOccurred()) - - start := time.Now() - err = client.Ping().Err() - Expect(err).NotTo(HaveOccurred()) - Expect(time.Now()).To(BeTemporally("~", start.Add(time.Second), 800*time.Millisecond)) - }) - - It("should ClientSetName and ClientGetName", func() { - pipe := client.Pipeline() - set := pipe.ClientSetName("theclientname") - get := pipe.ClientGetName() - _, err := pipe.Exec() - Expect(err).NotTo(HaveOccurred()) - - Expect(set.Err()).NotTo(HaveOccurred()) - Expect(set.Val()).To(BeTrue()) - - Expect(get.Err()).NotTo(HaveOccurred()) - Expect(get.Val()).To(Equal("theclientname")) - }) - - It("should ConfigGet", func() { - val, err := client.ConfigGet("*").Result() - Expect(err).NotTo(HaveOccurred()) - Expect(val).NotTo(BeEmpty()) - }) - - It("should ConfigResetStat", func() { - r := client.ConfigResetStat() - Expect(r.Err()).NotTo(HaveOccurred()) - Expect(r.Val()).To(Equal("OK")) - }) - - It("should ConfigSet", func() { - configGet := client.ConfigGet("maxmemory") - Expect(configGet.Err()).NotTo(HaveOccurred()) - Expect(configGet.Val()).To(HaveLen(2)) - Expect(configGet.Val()[0]).To(Equal("maxmemory")) - - configSet := client.ConfigSet("maxmemory", configGet.Val()[1].(string)) - Expect(configSet.Err()).NotTo(HaveOccurred()) - Expect(configSet.Val()).To(Equal("OK")) - }) - - It("should DBSize", func() { - size, err := client.DBSize().Result() - Expect(err).NotTo(HaveOccurred()) - Expect(size).To(Equal(int64(0))) - }) - - It("should Info", func() { - info := client.Info() - Expect(info.Err()).NotTo(HaveOccurred()) - Expect(info.Val()).NotTo(Equal("")) - }) - - It("should Info cpu", func() { - info := client.Info("cpu") - Expect(info.Err()).NotTo(HaveOccurred()) - Expect(info.Val()).NotTo(Equal("")) - Expect(info.Val()).To(ContainSubstring(`used_cpu_sys`)) - }) - - It("should LastSave", func() { - lastSave := client.LastSave() - Expect(lastSave.Err()).NotTo(HaveOccurred()) - Expect(lastSave.Val()).NotTo(Equal(0)) - }) - - It("should Save", func() { - // workaround for "ERR Background save already in progress" - Eventually(func() string { - return client.Save().Val() - }, "10s").Should(Equal("OK")) - }) - - It("should SlaveOf", func() { - slaveOf := client.SlaveOf("localhost", "8888") - Expect(slaveOf.Err()).NotTo(HaveOccurred()) - Expect(slaveOf.Val()).To(Equal("OK")) - - slaveOf = client.SlaveOf("NO", "ONE") - Expect(slaveOf.Err()).NotTo(HaveOccurred()) - Expect(slaveOf.Val()).To(Equal("OK")) - }) - - It("should Time", func() { - tm, err := client.Time().Result() - Expect(err).NotTo(HaveOccurred()) - Expect(tm).To(BeTemporally("~", time.Now(), 3*time.Second)) - }) - - It("Should Command", func() { - cmds, err := client.Command().Result() - Expect(err).NotTo(HaveOccurred()) - Expect(len(cmds)).To(BeNumerically("~", 180, 10)) - - cmd := cmds["mget"] - Expect(cmd.Name).To(Equal("mget")) - Expect(cmd.Arity).To(Equal(int8(-2))) - Expect(cmd.Flags).To(ContainElement("readonly")) - Expect(cmd.FirstKeyPos).To(Equal(int8(1))) - Expect(cmd.LastKeyPos).To(Equal(int8(-1))) - Expect(cmd.StepCount).To(Equal(int8(1))) - - cmd = cmds["ping"] - Expect(cmd.Name).To(Equal("ping")) - Expect(cmd.Arity).To(Equal(int8(-1))) - Expect(cmd.Flags).To(ContainElement("stale")) - Expect(cmd.Flags).To(ContainElement("fast")) - Expect(cmd.FirstKeyPos).To(Equal(int8(0))) - Expect(cmd.LastKeyPos).To(Equal(int8(0))) - Expect(cmd.StepCount).To(Equal(int8(0))) - }) - - }) - - Describe("debugging", func() { - - It("should DebugObject", func() { - debug := client.DebugObject("foo") - Expect(debug.Err()).To(HaveOccurred()) - Expect(debug.Err().Error()).To(Equal("ERR no such key")) - - client.Set("foo", "bar", 0) - debug = client.DebugObject("foo") - Expect(debug.Err()).NotTo(HaveOccurred()) - Expect(debug.Val()).To(ContainSubstring(`serializedlength:4`)) - }) - - }) - - Describe("keys", func() { - - It("should Del", func() { - err := client.Set("key1", "Hello", 0).Err() - Expect(err).NotTo(HaveOccurred()) - err = client.Set("key2", "World", 0).Err() - Expect(err).NotTo(HaveOccurred()) - - n, err := client.Del("key1", "key2", "key3").Result() - Expect(err).NotTo(HaveOccurred()) - Expect(n).To(Equal(int64(2))) - }) - - It("should Unlink", func() { - err := client.Set("key1", "Hello", 0).Err() - Expect(err).NotTo(HaveOccurred()) - err = client.Set("key2", "World", 0).Err() - Expect(err).NotTo(HaveOccurred()) - - n, err := client.Unlink("key1", "key2", "key3").Result() - Expect(err).NotTo(HaveOccurred()) - Expect(n).To(Equal(int64(2))) - }) - - It("should Dump", func() { - set := client.Set("key", "hello", 0) - Expect(set.Err()).NotTo(HaveOccurred()) - Expect(set.Val()).To(Equal("OK")) - - dump := client.Dump("key") - Expect(dump.Err()).NotTo(HaveOccurred()) - Expect(dump.Val()).NotTo(BeEmpty()) - }) - - It("should Exists", func() { - set := client.Set("key1", "Hello", 0) - Expect(set.Err()).NotTo(HaveOccurred()) - Expect(set.Val()).To(Equal("OK")) - - n, err := client.Exists("key1").Result() - Expect(err).NotTo(HaveOccurred()) - Expect(n).To(Equal(int64(1))) - - n, err = client.Exists("key2").Result() - Expect(err).NotTo(HaveOccurred()) - Expect(n).To(Equal(int64(0))) - - n, err = client.Exists("key1", "key2").Result() - Expect(err).NotTo(HaveOccurred()) - Expect(n).To(Equal(int64(1))) - - n, err = client.Exists("key1", "key1").Result() - Expect(err).NotTo(HaveOccurred()) - Expect(n).To(Equal(int64(2))) - }) - - It("should Expire", func() { - set := client.Set("key", "Hello", 0) - Expect(set.Err()).NotTo(HaveOccurred()) - Expect(set.Val()).To(Equal("OK")) - - expire := client.Expire("key", 10*time.Second) - Expect(expire.Err()).NotTo(HaveOccurred()) - Expect(expire.Val()).To(Equal(true)) - - ttl := client.TTL("key") - Expect(ttl.Err()).NotTo(HaveOccurred()) - Expect(ttl.Val()).To(Equal(10 * time.Second)) - - set = client.Set("key", "Hello World", 0) - Expect(set.Err()).NotTo(HaveOccurred()) - Expect(set.Val()).To(Equal("OK")) - - ttl = client.TTL("key") - Expect(ttl.Err()).NotTo(HaveOccurred()) - Expect(ttl.Val() < 0).To(Equal(true)) - }) - - It("should ExpireAt", func() { - set := client.Set("key", "Hello", 0) - Expect(set.Err()).NotTo(HaveOccurred()) - Expect(set.Val()).To(Equal("OK")) - - n, err := client.Exists("key").Result() - Expect(err).NotTo(HaveOccurred()) - Expect(n).To(Equal(int64(1))) - - expireAt := client.ExpireAt("key", time.Now().Add(-time.Hour)) - Expect(expireAt.Err()).NotTo(HaveOccurred()) - Expect(expireAt.Val()).To(Equal(true)) - - n, err = client.Exists("key").Result() - Expect(err).NotTo(HaveOccurred()) - Expect(n).To(Equal(int64(0))) - }) - - It("should Keys", func() { - mset := client.MSet("one", "1", "two", "2", "three", "3", "four", "4") - Expect(mset.Err()).NotTo(HaveOccurred()) - Expect(mset.Val()).To(Equal("OK")) - - keys := client.Keys("*o*") - Expect(keys.Err()).NotTo(HaveOccurred()) - Expect(keys.Val()).To(ConsistOf([]string{"four", "one", "two"})) - - keys = client.Keys("t??") - Expect(keys.Err()).NotTo(HaveOccurred()) - Expect(keys.Val()).To(Equal([]string{"two"})) - - keys = client.Keys("*") - Expect(keys.Err()).NotTo(HaveOccurred()) - Expect(keys.Val()).To(ConsistOf([]string{"four", "one", "three", "two"})) - }) - - It("should Migrate", func() { - migrate := client.Migrate("localhost", redisSecondaryPort, "key", 0, 0) - Expect(migrate.Err()).NotTo(HaveOccurred()) - Expect(migrate.Val()).To(Equal("NOKEY")) - - set := client.Set("key", "hello", 0) - Expect(set.Err()).NotTo(HaveOccurred()) - Expect(set.Val()).To(Equal("OK")) - - migrate = client.Migrate("localhost", redisSecondaryPort, "key", 0, 0) - Expect(migrate.Err()).To(MatchError("IOERR error or timeout writing to target instance")) - Expect(migrate.Val()).To(Equal("")) - }) - - It("should Move", func() { - move := client.Move("key", 2) - Expect(move.Err()).NotTo(HaveOccurred()) - Expect(move.Val()).To(Equal(false)) - - set := client.Set("key", "hello", 0) - Expect(set.Err()).NotTo(HaveOccurred()) - Expect(set.Val()).To(Equal("OK")) - - move = client.Move("key", 2) - Expect(move.Err()).NotTo(HaveOccurred()) - Expect(move.Val()).To(Equal(true)) - - get := client.Get("key") - Expect(get.Err()).To(Equal(redis.Nil)) - Expect(get.Val()).To(Equal("")) - - pipe := client.Pipeline() - pipe.Select(2) - get = pipe.Get("key") - pipe.FlushDB() - - _, err := pipe.Exec() - Expect(err).NotTo(HaveOccurred()) - Expect(get.Val()).To(Equal("hello")) - }) - - It("should Object", func() { - set := client.Set("key", "hello", 0) - Expect(set.Err()).NotTo(HaveOccurred()) - Expect(set.Val()).To(Equal("OK")) - - refCount := client.ObjectRefCount("key") - Expect(refCount.Err()).NotTo(HaveOccurred()) - Expect(refCount.Val()).To(Equal(int64(1))) - - err := client.ObjectEncoding("key").Err() - Expect(err).NotTo(HaveOccurred()) - - idleTime := client.ObjectIdleTime("key") - Expect(idleTime.Err()).NotTo(HaveOccurred()) - Expect(idleTime.Val()).To(Equal(time.Duration(0))) - }) - - It("should Persist", func() { - set := client.Set("key", "Hello", 0) - Expect(set.Err()).NotTo(HaveOccurred()) - Expect(set.Val()).To(Equal("OK")) - - expire := client.Expire("key", 10*time.Second) - Expect(expire.Err()).NotTo(HaveOccurred()) - Expect(expire.Val()).To(Equal(true)) - - ttl := client.TTL("key") - Expect(ttl.Err()).NotTo(HaveOccurred()) - Expect(ttl.Val()).To(Equal(10 * time.Second)) - - persist := client.Persist("key") - Expect(persist.Err()).NotTo(HaveOccurred()) - Expect(persist.Val()).To(Equal(true)) - - ttl = client.TTL("key") - Expect(ttl.Err()).NotTo(HaveOccurred()) - Expect(ttl.Val() < 0).To(Equal(true)) - }) - - It("should PExpire", func() { - set := client.Set("key", "Hello", 0) - Expect(set.Err()).NotTo(HaveOccurred()) - Expect(set.Val()).To(Equal("OK")) - - expiration := 900 * time.Millisecond - pexpire := client.PExpire("key", expiration) - Expect(pexpire.Err()).NotTo(HaveOccurred()) - Expect(pexpire.Val()).To(Equal(true)) - - ttl := client.TTL("key") - Expect(ttl.Err()).NotTo(HaveOccurred()) - Expect(ttl.Val()).To(Equal(time.Second)) - - pttl := client.PTTL("key") - Expect(pttl.Err()).NotTo(HaveOccurred()) - Expect(pttl.Val()).To(BeNumerically("~", expiration, 10*time.Millisecond)) - }) - - It("should PExpireAt", func() { - set := client.Set("key", "Hello", 0) - Expect(set.Err()).NotTo(HaveOccurred()) - Expect(set.Val()).To(Equal("OK")) - - expiration := 900 * time.Millisecond - pexpireat := client.PExpireAt("key", time.Now().Add(expiration)) - Expect(pexpireat.Err()).NotTo(HaveOccurred()) - Expect(pexpireat.Val()).To(Equal(true)) - - ttl := client.TTL("key") - Expect(ttl.Err()).NotTo(HaveOccurred()) - Expect(ttl.Val()).To(Equal(time.Second)) - - pttl := client.PTTL("key") - Expect(pttl.Err()).NotTo(HaveOccurred()) - Expect(pttl.Val()).To(BeNumerically("~", expiration, 10*time.Millisecond)) - }) - - It("should PTTL", func() { - set := client.Set("key", "Hello", 0) - Expect(set.Err()).NotTo(HaveOccurred()) - Expect(set.Val()).To(Equal("OK")) - - expiration := time.Second - expire := client.Expire("key", expiration) - Expect(expire.Err()).NotTo(HaveOccurred()) - Expect(set.Val()).To(Equal("OK")) - - pttl := client.PTTL("key") - Expect(pttl.Err()).NotTo(HaveOccurred()) - Expect(pttl.Val()).To(BeNumerically("~", expiration, 10*time.Millisecond)) - }) - - It("should RandomKey", func() { - randomKey := client.RandomKey() - Expect(randomKey.Err()).To(Equal(redis.Nil)) - Expect(randomKey.Val()).To(Equal("")) - - set := client.Set("key", "hello", 0) - Expect(set.Err()).NotTo(HaveOccurred()) - Expect(set.Val()).To(Equal("OK")) - - randomKey = client.RandomKey() - Expect(randomKey.Err()).NotTo(HaveOccurred()) - Expect(randomKey.Val()).To(Equal("key")) - }) - - It("should Rename", func() { - set := client.Set("key", "hello", 0) - Expect(set.Err()).NotTo(HaveOccurred()) - Expect(set.Val()).To(Equal("OK")) - - status := client.Rename("key", "key1") - Expect(status.Err()).NotTo(HaveOccurred()) - Expect(status.Val()).To(Equal("OK")) - - get := client.Get("key1") - Expect(get.Err()).NotTo(HaveOccurred()) - Expect(get.Val()).To(Equal("hello")) - }) - - It("should RenameNX", func() { - set := client.Set("key", "hello", 0) - Expect(set.Err()).NotTo(HaveOccurred()) - Expect(set.Val()).To(Equal("OK")) - - renameNX := client.RenameNX("key", "key1") - Expect(renameNX.Err()).NotTo(HaveOccurred()) - Expect(renameNX.Val()).To(Equal(true)) - - get := client.Get("key1") - Expect(get.Err()).NotTo(HaveOccurred()) - Expect(get.Val()).To(Equal("hello")) - }) - - It("should Restore", func() { - err := client.Set("key", "hello", 0).Err() - Expect(err).NotTo(HaveOccurred()) - - dump := client.Dump("key") - Expect(dump.Err()).NotTo(HaveOccurred()) - - err = client.Del("key").Err() - Expect(err).NotTo(HaveOccurred()) - - restore, err := client.Restore("key", 0, dump.Val()).Result() - Expect(err).NotTo(HaveOccurred()) - Expect(restore).To(Equal("OK")) - - type_, err := client.Type("key").Result() - Expect(err).NotTo(HaveOccurred()) - Expect(type_).To(Equal("string")) - - val, err := client.Get("key").Result() - Expect(err).NotTo(HaveOccurred()) - Expect(val).To(Equal("hello")) - }) - - It("should RestoreReplace", func() { - err := client.Set("key", "hello", 0).Err() - Expect(err).NotTo(HaveOccurred()) - - dump := client.Dump("key") - Expect(dump.Err()).NotTo(HaveOccurred()) - - restore, err := client.RestoreReplace("key", 0, dump.Val()).Result() - Expect(err).NotTo(HaveOccurred()) - Expect(restore).To(Equal("OK")) - - type_, err := client.Type("key").Result() - Expect(err).NotTo(HaveOccurred()) - Expect(type_).To(Equal("string")) - - val, err := client.Get("key").Result() - Expect(err).NotTo(HaveOccurred()) - Expect(val).To(Equal("hello")) - }) - - It("should Sort", func() { - size, err := client.LPush("list", "1").Result() - Expect(err).NotTo(HaveOccurred()) - Expect(size).To(Equal(int64(1))) - - size, err = client.LPush("list", "3").Result() - Expect(err).NotTo(HaveOccurred()) - Expect(size).To(Equal(int64(2))) - - size, err = client.LPush("list", "2").Result() - Expect(err).NotTo(HaveOccurred()) - Expect(size).To(Equal(int64(3))) - - els, err := client.Sort("list", redis.Sort{ - Offset: 0, - Count: 2, - Order: "ASC", - }).Result() - Expect(err).NotTo(HaveOccurred()) - Expect(els).To(Equal([]string{"1", "2"})) - }) - - It("should Sort and Get", func() { - size, err := client.LPush("list", "1").Result() - Expect(err).NotTo(HaveOccurred()) - Expect(size).To(Equal(int64(1))) - - size, err = client.LPush("list", "3").Result() - Expect(err).NotTo(HaveOccurred()) - Expect(size).To(Equal(int64(2))) - - size, err = client.LPush("list", "2").Result() - Expect(err).NotTo(HaveOccurred()) - Expect(size).To(Equal(int64(3))) - - err = client.Set("object_2", "value2", 0).Err() - Expect(err).NotTo(HaveOccurred()) - - { - els, err := client.Sort("list", redis.Sort{ - Get: []string{"object_*"}, - }).Result() - Expect(err).NotTo(HaveOccurred()) - Expect(els).To(Equal([]string{"", "value2", ""})) - } - - { - els, err := client.SortInterfaces("list", redis.Sort{ - Get: []string{"object_*"}, - }).Result() - Expect(err).NotTo(HaveOccurred()) - Expect(els).To(Equal([]interface{}{nil, "value2", nil})) - } - }) - - It("should TTL", func() { - ttl := client.TTL("key") - Expect(ttl.Err()).NotTo(HaveOccurred()) - Expect(ttl.Val() < 0).To(Equal(true)) - - set := client.Set("key", "hello", 0) - Expect(set.Err()).NotTo(HaveOccurred()) - Expect(set.Val()).To(Equal("OK")) - - expire := client.Expire("key", 60*time.Second) - Expect(expire.Err()).NotTo(HaveOccurred()) - Expect(expire.Val()).To(Equal(true)) - - ttl = client.TTL("key") - Expect(ttl.Err()).NotTo(HaveOccurred()) - Expect(ttl.Val()).To(Equal(60 * time.Second)) - }) - - It("should Type", func() { - set := client.Set("key", "hello", 0) - Expect(set.Err()).NotTo(HaveOccurred()) - Expect(set.Val()).To(Equal("OK")) - - type_ := client.Type("key") - Expect(type_.Err()).NotTo(HaveOccurred()) - Expect(type_.Val()).To(Equal("string")) - }) - - }) - - Describe("scanning", func() { - - It("should Scan", func() { - for i := 0; i < 1000; i++ { - set := client.Set(fmt.Sprintf("key%d", i), "hello", 0) - Expect(set.Err()).NotTo(HaveOccurred()) - } - - keys, cursor, err := client.Scan(0, "", 0).Result() - Expect(err).NotTo(HaveOccurred()) - Expect(keys).NotTo(BeEmpty()) - Expect(cursor).NotTo(BeZero()) - }) - - It("should SScan", func() { - for i := 0; i < 1000; i++ { - sadd := client.SAdd("myset", fmt.Sprintf("member%d", i)) - Expect(sadd.Err()).NotTo(HaveOccurred()) - } - - keys, cursor, err := client.SScan("myset", 0, "", 0).Result() - Expect(err).NotTo(HaveOccurred()) - Expect(keys).NotTo(BeEmpty()) - Expect(cursor).NotTo(BeZero()) - }) - - It("should HScan", func() { - for i := 0; i < 1000; i++ { - sadd := client.HSet("myhash", fmt.Sprintf("key%d", i), "hello") - Expect(sadd.Err()).NotTo(HaveOccurred()) - } - - keys, cursor, err := client.HScan("myhash", 0, "", 0).Result() - Expect(err).NotTo(HaveOccurred()) - Expect(keys).NotTo(BeEmpty()) - Expect(cursor).NotTo(BeZero()) - }) - - It("should ZScan", func() { - for i := 0; i < 1000; i++ { - sadd := client.ZAdd("myset", redis.Z{float64(i), fmt.Sprintf("member%d", i)}) - Expect(sadd.Err()).NotTo(HaveOccurred()) - } - - keys, cursor, err := client.ZScan("myset", 0, "", 0).Result() - Expect(err).NotTo(HaveOccurred()) - Expect(keys).NotTo(BeEmpty()) - Expect(cursor).NotTo(BeZero()) - }) - - }) - - Describe("strings", func() { - - It("should Append", func() { - n, err := client.Exists("key").Result() - Expect(err).NotTo(HaveOccurred()) - Expect(n).To(Equal(int64(0))) - - append := client.Append("key", "Hello") - Expect(append.Err()).NotTo(HaveOccurred()) - Expect(append.Val()).To(Equal(int64(5))) - - append = client.Append("key", " World") - Expect(append.Err()).NotTo(HaveOccurred()) - Expect(append.Val()).To(Equal(int64(11))) - - get := client.Get("key") - Expect(get.Err()).NotTo(HaveOccurred()) - Expect(get.Val()).To(Equal("Hello World")) - }) - - It("should BitCount", func() { - set := client.Set("key", "foobar", 0) - Expect(set.Err()).NotTo(HaveOccurred()) - Expect(set.Val()).To(Equal("OK")) - - bitCount := client.BitCount("key", nil) - Expect(bitCount.Err()).NotTo(HaveOccurred()) - Expect(bitCount.Val()).To(Equal(int64(26))) - - bitCount = client.BitCount("key", &redis.BitCount{0, 0}) - Expect(bitCount.Err()).NotTo(HaveOccurred()) - Expect(bitCount.Val()).To(Equal(int64(4))) - - bitCount = client.BitCount("key", &redis.BitCount{1, 1}) - Expect(bitCount.Err()).NotTo(HaveOccurred()) - Expect(bitCount.Val()).To(Equal(int64(6))) - }) - - It("should BitOpAnd", func() { - set := client.Set("key1", "1", 0) - Expect(set.Err()).NotTo(HaveOccurred()) - Expect(set.Val()).To(Equal("OK")) - - set = client.Set("key2", "0", 0) - Expect(set.Err()).NotTo(HaveOccurred()) - Expect(set.Val()).To(Equal("OK")) - - bitOpAnd := client.BitOpAnd("dest", "key1", "key2") - Expect(bitOpAnd.Err()).NotTo(HaveOccurred()) - Expect(bitOpAnd.Val()).To(Equal(int64(1))) - - get := client.Get("dest") - Expect(get.Err()).NotTo(HaveOccurred()) - Expect(get.Val()).To(Equal("0")) - }) - - It("should BitOpOr", func() { - set := client.Set("key1", "1", 0) - Expect(set.Err()).NotTo(HaveOccurred()) - Expect(set.Val()).To(Equal("OK")) - - set = client.Set("key2", "0", 0) - Expect(set.Err()).NotTo(HaveOccurred()) - Expect(set.Val()).To(Equal("OK")) - - bitOpOr := client.BitOpOr("dest", "key1", "key2") - Expect(bitOpOr.Err()).NotTo(HaveOccurred()) - Expect(bitOpOr.Val()).To(Equal(int64(1))) - - get := client.Get("dest") - Expect(get.Err()).NotTo(HaveOccurred()) - Expect(get.Val()).To(Equal("1")) - }) - - It("should BitOpXor", func() { - set := client.Set("key1", "\xff", 0) - Expect(set.Err()).NotTo(HaveOccurred()) - Expect(set.Val()).To(Equal("OK")) - - set = client.Set("key2", "\x0f", 0) - Expect(set.Err()).NotTo(HaveOccurred()) - Expect(set.Val()).To(Equal("OK")) - - bitOpXor := client.BitOpXor("dest", "key1", "key2") - Expect(bitOpXor.Err()).NotTo(HaveOccurred()) - Expect(bitOpXor.Val()).To(Equal(int64(1))) - - get := client.Get("dest") - Expect(get.Err()).NotTo(HaveOccurred()) - Expect(get.Val()).To(Equal("\xf0")) - }) - - It("should BitOpNot", func() { - set := client.Set("key1", "\x00", 0) - Expect(set.Err()).NotTo(HaveOccurred()) - Expect(set.Val()).To(Equal("OK")) - - bitOpNot := client.BitOpNot("dest", "key1") - Expect(bitOpNot.Err()).NotTo(HaveOccurred()) - Expect(bitOpNot.Val()).To(Equal(int64(1))) - - get := client.Get("dest") - Expect(get.Err()).NotTo(HaveOccurred()) - Expect(get.Val()).To(Equal("\xff")) - }) - - It("should BitPos", func() { - err := client.Set("mykey", "\xff\xf0\x00", 0).Err() - Expect(err).NotTo(HaveOccurred()) - - pos, err := client.BitPos("mykey", 0).Result() - Expect(err).NotTo(HaveOccurred()) - Expect(pos).To(Equal(int64(12))) - - pos, err = client.BitPos("mykey", 1).Result() - Expect(err).NotTo(HaveOccurred()) - Expect(pos).To(Equal(int64(0))) - - pos, err = client.BitPos("mykey", 0, 2).Result() - Expect(err).NotTo(HaveOccurred()) - Expect(pos).To(Equal(int64(16))) - - pos, err = client.BitPos("mykey", 1, 2).Result() - Expect(err).NotTo(HaveOccurred()) - Expect(pos).To(Equal(int64(-1))) - - pos, err = client.BitPos("mykey", 0, -1).Result() - Expect(err).NotTo(HaveOccurred()) - Expect(pos).To(Equal(int64(16))) - - pos, err = client.BitPos("mykey", 1, -1).Result() - Expect(err).NotTo(HaveOccurred()) - Expect(pos).To(Equal(int64(-1))) - - pos, err = client.BitPos("mykey", 0, 2, 1).Result() - Expect(err).NotTo(HaveOccurred()) - Expect(pos).To(Equal(int64(-1))) - - pos, err = client.BitPos("mykey", 0, 0, -3).Result() - Expect(err).NotTo(HaveOccurred()) - Expect(pos).To(Equal(int64(-1))) - - pos, err = client.BitPos("mykey", 0, 0, 0).Result() - Expect(err).NotTo(HaveOccurred()) - Expect(pos).To(Equal(int64(-1))) - }) - - It("should Decr", func() { - set := client.Set("key", "10", 0) - Expect(set.Err()).NotTo(HaveOccurred()) - Expect(set.Val()).To(Equal("OK")) - - decr := client.Decr("key") - Expect(decr.Err()).NotTo(HaveOccurred()) - Expect(decr.Val()).To(Equal(int64(9))) - - set = client.Set("key", "234293482390480948029348230948", 0) - Expect(set.Err()).NotTo(HaveOccurred()) - Expect(set.Val()).To(Equal("OK")) - - decr = client.Decr("key") - Expect(decr.Err()).To(MatchError("ERR value is not an integer or out of range")) - Expect(decr.Val()).To(Equal(int64(0))) - }) - - It("should DecrBy", func() { - set := client.Set("key", "10", 0) - Expect(set.Err()).NotTo(HaveOccurred()) - Expect(set.Val()).To(Equal("OK")) - - decrBy := client.DecrBy("key", 5) - Expect(decrBy.Err()).NotTo(HaveOccurred()) - Expect(decrBy.Val()).To(Equal(int64(5))) - }) - - It("should Get", func() { - get := client.Get("_") - Expect(get.Err()).To(Equal(redis.Nil)) - Expect(get.Val()).To(Equal("")) - - set := client.Set("key", "hello", 0) - Expect(set.Err()).NotTo(HaveOccurred()) - Expect(set.Val()).To(Equal("OK")) - - get = client.Get("key") - Expect(get.Err()).NotTo(HaveOccurred()) - Expect(get.Val()).To(Equal("hello")) - }) - - It("should GetBit", func() { - setBit := client.SetBit("key", 7, 1) - Expect(setBit.Err()).NotTo(HaveOccurred()) - Expect(setBit.Val()).To(Equal(int64(0))) - - getBit := client.GetBit("key", 0) - Expect(getBit.Err()).NotTo(HaveOccurred()) - Expect(getBit.Val()).To(Equal(int64(0))) - - getBit = client.GetBit("key", 7) - Expect(getBit.Err()).NotTo(HaveOccurred()) - Expect(getBit.Val()).To(Equal(int64(1))) - - getBit = client.GetBit("key", 100) - Expect(getBit.Err()).NotTo(HaveOccurred()) - Expect(getBit.Val()).To(Equal(int64(0))) - }) - - It("should GetRange", func() { - set := client.Set("key", "This is a string", 0) - Expect(set.Err()).NotTo(HaveOccurred()) - Expect(set.Val()).To(Equal("OK")) - - getRange := client.GetRange("key", 0, 3) - Expect(getRange.Err()).NotTo(HaveOccurred()) - Expect(getRange.Val()).To(Equal("This")) - - getRange = client.GetRange("key", -3, -1) - Expect(getRange.Err()).NotTo(HaveOccurred()) - Expect(getRange.Val()).To(Equal("ing")) - - getRange = client.GetRange("key", 0, -1) - Expect(getRange.Err()).NotTo(HaveOccurred()) - Expect(getRange.Val()).To(Equal("This is a string")) - - getRange = client.GetRange("key", 10, 100) - Expect(getRange.Err()).NotTo(HaveOccurred()) - Expect(getRange.Val()).To(Equal("string")) - }) - - It("should GetSet", func() { - incr := client.Incr("key") - Expect(incr.Err()).NotTo(HaveOccurred()) - Expect(incr.Val()).To(Equal(int64(1))) - - getSet := client.GetSet("key", "0") - Expect(getSet.Err()).NotTo(HaveOccurred()) - Expect(getSet.Val()).To(Equal("1")) - - get := client.Get("key") - Expect(get.Err()).NotTo(HaveOccurred()) - Expect(get.Val()).To(Equal("0")) - }) - - It("should Incr", func() { - set := client.Set("key", "10", 0) - Expect(set.Err()).NotTo(HaveOccurred()) - Expect(set.Val()).To(Equal("OK")) - - incr := client.Incr("key") - Expect(incr.Err()).NotTo(HaveOccurred()) - Expect(incr.Val()).To(Equal(int64(11))) - - get := client.Get("key") - Expect(get.Err()).NotTo(HaveOccurred()) - Expect(get.Val()).To(Equal("11")) - }) - - It("should IncrBy", func() { - set := client.Set("key", "10", 0) - Expect(set.Err()).NotTo(HaveOccurred()) - Expect(set.Val()).To(Equal("OK")) - - incrBy := client.IncrBy("key", 5) - Expect(incrBy.Err()).NotTo(HaveOccurred()) - Expect(incrBy.Val()).To(Equal(int64(15))) - }) - - It("should IncrByFloat", func() { - set := client.Set("key", "10.50", 0) - Expect(set.Err()).NotTo(HaveOccurred()) - Expect(set.Val()).To(Equal("OK")) - - incrByFloat := client.IncrByFloat("key", 0.1) - Expect(incrByFloat.Err()).NotTo(HaveOccurred()) - Expect(incrByFloat.Val()).To(Equal(10.6)) - - set = client.Set("key", "5.0e3", 0) - Expect(set.Err()).NotTo(HaveOccurred()) - Expect(set.Val()).To(Equal("OK")) - - incrByFloat = client.IncrByFloat("key", 2.0e2) - Expect(incrByFloat.Err()).NotTo(HaveOccurred()) - Expect(incrByFloat.Val()).To(Equal(float64(5200))) - }) - - It("should IncrByFloatOverflow", func() { - incrByFloat := client.IncrByFloat("key", 996945661) - Expect(incrByFloat.Err()).NotTo(HaveOccurred()) - Expect(incrByFloat.Val()).To(Equal(float64(996945661))) - }) - - It("should MSetMGet", func() { - mSet := client.MSet("key1", "hello1", "key2", "hello2") - Expect(mSet.Err()).NotTo(HaveOccurred()) - Expect(mSet.Val()).To(Equal("OK")) - - mGet := client.MGet("key1", "key2", "_") - Expect(mGet.Err()).NotTo(HaveOccurred()) - Expect(mGet.Val()).To(Equal([]interface{}{"hello1", "hello2", nil})) - }) - - It("should MSetNX", func() { - mSetNX := client.MSetNX("key1", "hello1", "key2", "hello2") - Expect(mSetNX.Err()).NotTo(HaveOccurred()) - Expect(mSetNX.Val()).To(Equal(true)) - - mSetNX = client.MSetNX("key2", "hello1", "key3", "hello2") - Expect(mSetNX.Err()).NotTo(HaveOccurred()) - Expect(mSetNX.Val()).To(Equal(false)) - }) - - It("should Set with expiration", func() { - err := client.Set("key", "hello", 100*time.Millisecond).Err() - Expect(err).NotTo(HaveOccurred()) - - val, err := client.Get("key").Result() - Expect(err).NotTo(HaveOccurred()) - Expect(val).To(Equal("hello")) - - Eventually(func() error { - return client.Get("foo").Err() - }, "1s", "100ms").Should(Equal(redis.Nil)) - }) - - It("should SetGet", func() { - set := client.Set("key", "hello", 0) - Expect(set.Err()).NotTo(HaveOccurred()) - Expect(set.Val()).To(Equal("OK")) - - get := client.Get("key") - Expect(get.Err()).NotTo(HaveOccurred()) - Expect(get.Val()).To(Equal("hello")) - }) - - It("should SetNX", func() { - setNX := client.SetNX("key", "hello", 0) - Expect(setNX.Err()).NotTo(HaveOccurred()) - Expect(setNX.Val()).To(Equal(true)) - - setNX = client.SetNX("key", "hello2", 0) - Expect(setNX.Err()).NotTo(HaveOccurred()) - Expect(setNX.Val()).To(Equal(false)) - - get := client.Get("key") - Expect(get.Err()).NotTo(HaveOccurred()) - Expect(get.Val()).To(Equal("hello")) - }) - - It("should SetNX with expiration", func() { - isSet, err := client.SetNX("key", "hello", time.Second).Result() - Expect(err).NotTo(HaveOccurred()) - Expect(isSet).To(Equal(true)) - - isSet, err = client.SetNX("key", "hello2", time.Second).Result() - Expect(err).NotTo(HaveOccurred()) - Expect(isSet).To(Equal(false)) - - val, err := client.Get("key").Result() - Expect(err).NotTo(HaveOccurred()) - Expect(val).To(Equal("hello")) - }) - - It("should SetXX", func() { - isSet, err := client.SetXX("key", "hello2", 0).Result() - Expect(err).NotTo(HaveOccurred()) - Expect(isSet).To(Equal(false)) - - err = client.Set("key", "hello", 0).Err() - Expect(err).NotTo(HaveOccurred()) - - isSet, err = client.SetXX("key", "hello2", 0).Result() - Expect(err).NotTo(HaveOccurred()) - Expect(isSet).To(Equal(true)) - - val, err := client.Get("key").Result() - Expect(err).NotTo(HaveOccurred()) - Expect(val).To(Equal("hello2")) - }) - - It("should SetXX with expiration", func() { - isSet, err := client.SetXX("key", "hello2", time.Second).Result() - Expect(err).NotTo(HaveOccurred()) - Expect(isSet).To(Equal(false)) - - err = client.Set("key", "hello", time.Second).Err() - Expect(err).NotTo(HaveOccurred()) - - isSet, err = client.SetXX("key", "hello2", time.Second).Result() - Expect(err).NotTo(HaveOccurred()) - Expect(isSet).To(Equal(true)) - - val, err := client.Get("key").Result() - Expect(err).NotTo(HaveOccurred()) - Expect(val).To(Equal("hello2")) - }) - - It("should SetRange", func() { - set := client.Set("key", "Hello World", 0) - Expect(set.Err()).NotTo(HaveOccurred()) - Expect(set.Val()).To(Equal("OK")) - - range_ := client.SetRange("key", 6, "Redis") - Expect(range_.Err()).NotTo(HaveOccurred()) - Expect(range_.Val()).To(Equal(int64(11))) - - get := client.Get("key") - Expect(get.Err()).NotTo(HaveOccurred()) - Expect(get.Val()).To(Equal("Hello Redis")) - }) - - It("should StrLen", func() { - set := client.Set("key", "hello", 0) - Expect(set.Err()).NotTo(HaveOccurred()) - Expect(set.Val()).To(Equal("OK")) - - strLen := client.StrLen("key") - Expect(strLen.Err()).NotTo(HaveOccurred()) - Expect(strLen.Val()).To(Equal(int64(5))) - - strLen = client.StrLen("_") - Expect(strLen.Err()).NotTo(HaveOccurred()) - Expect(strLen.Val()).To(Equal(int64(0))) - }) - - }) - - Describe("hashes", func() { - - It("should HDel", func() { - hSet := client.HSet("hash", "key", "hello") - Expect(hSet.Err()).NotTo(HaveOccurred()) - - hDel := client.HDel("hash", "key") - Expect(hDel.Err()).NotTo(HaveOccurred()) - Expect(hDel.Val()).To(Equal(int64(1))) - - hDel = client.HDel("hash", "key") - Expect(hDel.Err()).NotTo(HaveOccurred()) - Expect(hDel.Val()).To(Equal(int64(0))) - }) - - It("should HExists", func() { - hSet := client.HSet("hash", "key", "hello") - Expect(hSet.Err()).NotTo(HaveOccurred()) - - hExists := client.HExists("hash", "key") - Expect(hExists.Err()).NotTo(HaveOccurred()) - Expect(hExists.Val()).To(Equal(true)) - - hExists = client.HExists("hash", "key1") - Expect(hExists.Err()).NotTo(HaveOccurred()) - Expect(hExists.Val()).To(Equal(false)) - }) - - It("should HGet", func() { - hSet := client.HSet("hash", "key", "hello") - Expect(hSet.Err()).NotTo(HaveOccurred()) - - hGet := client.HGet("hash", "key") - Expect(hGet.Err()).NotTo(HaveOccurred()) - Expect(hGet.Val()).To(Equal("hello")) - - hGet = client.HGet("hash", "key1") - Expect(hGet.Err()).To(Equal(redis.Nil)) - Expect(hGet.Val()).To(Equal("")) - }) - - It("should HGetAll", func() { - err := client.HSet("hash", "key1", "hello1").Err() - Expect(err).NotTo(HaveOccurred()) - err = client.HSet("hash", "key2", "hello2").Err() - Expect(err).NotTo(HaveOccurred()) - - m, err := client.HGetAll("hash").Result() - Expect(err).NotTo(HaveOccurred()) - Expect(m).To(Equal(map[string]string{"key1": "hello1", "key2": "hello2"})) - }) - - It("should HIncrBy", func() { - hSet := client.HSet("hash", "key", "5") - Expect(hSet.Err()).NotTo(HaveOccurred()) - - hIncrBy := client.HIncrBy("hash", "key", 1) - Expect(hIncrBy.Err()).NotTo(HaveOccurred()) - Expect(hIncrBy.Val()).To(Equal(int64(6))) - - hIncrBy = client.HIncrBy("hash", "key", -1) - Expect(hIncrBy.Err()).NotTo(HaveOccurred()) - Expect(hIncrBy.Val()).To(Equal(int64(5))) - - hIncrBy = client.HIncrBy("hash", "key", -10) - Expect(hIncrBy.Err()).NotTo(HaveOccurred()) - Expect(hIncrBy.Val()).To(Equal(int64(-5))) - }) - - It("should HIncrByFloat", func() { - hSet := client.HSet("hash", "field", "10.50") - Expect(hSet.Err()).NotTo(HaveOccurred()) - Expect(hSet.Val()).To(Equal(true)) - - hIncrByFloat := client.HIncrByFloat("hash", "field", 0.1) - Expect(hIncrByFloat.Err()).NotTo(HaveOccurred()) - Expect(hIncrByFloat.Val()).To(Equal(10.6)) - - hSet = client.HSet("hash", "field", "5.0e3") - Expect(hSet.Err()).NotTo(HaveOccurred()) - Expect(hSet.Val()).To(Equal(false)) - - hIncrByFloat = client.HIncrByFloat("hash", "field", 2.0e2) - Expect(hIncrByFloat.Err()).NotTo(HaveOccurred()) - Expect(hIncrByFloat.Val()).To(Equal(float64(5200))) - }) - - It("should HKeys", func() { - hkeys := client.HKeys("hash") - Expect(hkeys.Err()).NotTo(HaveOccurred()) - Expect(hkeys.Val()).To(Equal([]string{})) - - hset := client.HSet("hash", "key1", "hello1") - Expect(hset.Err()).NotTo(HaveOccurred()) - hset = client.HSet("hash", "key2", "hello2") - Expect(hset.Err()).NotTo(HaveOccurred()) - - hkeys = client.HKeys("hash") - Expect(hkeys.Err()).NotTo(HaveOccurred()) - Expect(hkeys.Val()).To(Equal([]string{"key1", "key2"})) - }) - - It("should HLen", func() { - hSet := client.HSet("hash", "key1", "hello1") - Expect(hSet.Err()).NotTo(HaveOccurred()) - hSet = client.HSet("hash", "key2", "hello2") - Expect(hSet.Err()).NotTo(HaveOccurred()) - - hLen := client.HLen("hash") - Expect(hLen.Err()).NotTo(HaveOccurred()) - Expect(hLen.Val()).To(Equal(int64(2))) - }) - - It("should HMGet", func() { - err := client.HSet("hash", "key1", "hello1").Err() - Expect(err).NotTo(HaveOccurred()) - err = client.HSet("hash", "key2", "hello2").Err() - Expect(err).NotTo(HaveOccurred()) - - vals, err := client.HMGet("hash", "key1", "key2", "_").Result() - Expect(err).NotTo(HaveOccurred()) - Expect(vals).To(Equal([]interface{}{"hello1", "hello2", nil})) - }) - - It("should HMSet", func() { - ok, err := client.HMSet("hash", map[string]interface{}{ - "key1": "hello1", - "key2": "hello2", - }).Result() - Expect(err).NotTo(HaveOccurred()) - Expect(ok).To(Equal("OK")) - - v, err := client.HGet("hash", "key1").Result() - Expect(err).NotTo(HaveOccurred()) - Expect(v).To(Equal("hello1")) - - v, err = client.HGet("hash", "key2").Result() - Expect(err).NotTo(HaveOccurred()) - Expect(v).To(Equal("hello2")) - }) - - It("should HSet", func() { - hSet := client.HSet("hash", "key", "hello") - Expect(hSet.Err()).NotTo(HaveOccurred()) - Expect(hSet.Val()).To(Equal(true)) - - hGet := client.HGet("hash", "key") - Expect(hGet.Err()).NotTo(HaveOccurred()) - Expect(hGet.Val()).To(Equal("hello")) - }) - - It("should HSetNX", func() { - hSetNX := client.HSetNX("hash", "key", "hello") - Expect(hSetNX.Err()).NotTo(HaveOccurred()) - Expect(hSetNX.Val()).To(Equal(true)) - - hSetNX = client.HSetNX("hash", "key", "hello") - Expect(hSetNX.Err()).NotTo(HaveOccurred()) - Expect(hSetNX.Val()).To(Equal(false)) - - hGet := client.HGet("hash", "key") - Expect(hGet.Err()).NotTo(HaveOccurred()) - Expect(hGet.Val()).To(Equal("hello")) - }) - - It("should HVals", func() { - err := client.HSet("hash", "key1", "hello1").Err() - Expect(err).NotTo(HaveOccurred()) - err = client.HSet("hash", "key2", "hello2").Err() - Expect(err).NotTo(HaveOccurred()) - - v, err := client.HVals("hash").Result() - Expect(err).NotTo(HaveOccurred()) - Expect(v).To(Equal([]string{"hello1", "hello2"})) - - var slice []string - err = client.HVals("hash").ScanSlice(&slice) - Expect(err).NotTo(HaveOccurred()) - Expect(slice).To(Equal([]string{"hello1", "hello2"})) - }) - - }) - - Describe("hyperloglog", func() { - It("should PFMerge", func() { - pfAdd := client.PFAdd("hll1", "1", "2", "3", "4", "5") - Expect(pfAdd.Err()).NotTo(HaveOccurred()) - - pfCount := client.PFCount("hll1") - Expect(pfCount.Err()).NotTo(HaveOccurred()) - Expect(pfCount.Val()).To(Equal(int64(5))) - - pfAdd = client.PFAdd("hll2", "a", "b", "c", "d", "e") - Expect(pfAdd.Err()).NotTo(HaveOccurred()) - - pfMerge := client.PFMerge("hllMerged", "hll1", "hll2") - Expect(pfMerge.Err()).NotTo(HaveOccurred()) - - pfCount = client.PFCount("hllMerged") - Expect(pfCount.Err()).NotTo(HaveOccurred()) - Expect(pfCount.Val()).To(Equal(int64(10))) - - pfCount = client.PFCount("hll1", "hll2") - Expect(pfCount.Err()).NotTo(HaveOccurred()) - Expect(pfCount.Val()).To(Equal(int64(10))) - }) - }) - - Describe("lists", func() { - - It("should BLPop", func() { - rPush := client.RPush("list1", "a", "b", "c") - Expect(rPush.Err()).NotTo(HaveOccurred()) - - bLPop := client.BLPop(0, "list1", "list2") - Expect(bLPop.Err()).NotTo(HaveOccurred()) - Expect(bLPop.Val()).To(Equal([]string{"list1", "a"})) - }) - - It("should BLPopBlocks", func() { - started := make(chan bool) - done := make(chan bool) - go func() { - defer GinkgoRecover() - - started <- true - bLPop := client.BLPop(0, "list") - Expect(bLPop.Err()).NotTo(HaveOccurred()) - Expect(bLPop.Val()).To(Equal([]string{"list", "a"})) - done <- true - }() - <-started - - select { - case <-done: - Fail("BLPop is not blocked") - case <-time.After(time.Second): - // ok - } - - rPush := client.RPush("list", "a") - Expect(rPush.Err()).NotTo(HaveOccurred()) - - select { - case <-done: - // ok - case <-time.After(time.Second): - Fail("BLPop is still blocked") - } - }) - - It("should BLPop timeout", func() { - val, err := client.BLPop(time.Second, "list1").Result() - Expect(err).To(Equal(redis.Nil)) - Expect(val).To(BeNil()) - - Expect(client.Ping().Err()).NotTo(HaveOccurred()) - - stats := client.PoolStats() - Expect(stats.Hits).To(Equal(uint32(1))) - Expect(stats.Misses).To(Equal(uint32(2))) - Expect(stats.Timeouts).To(Equal(uint32(0))) - }) - - It("should BRPop", func() { - rPush := client.RPush("list1", "a", "b", "c") - Expect(rPush.Err()).NotTo(HaveOccurred()) - - bRPop := client.BRPop(0, "list1", "list2") - Expect(bRPop.Err()).NotTo(HaveOccurred()) - Expect(bRPop.Val()).To(Equal([]string{"list1", "c"})) - }) - - It("should BRPop blocks", func() { - started := make(chan bool) - done := make(chan bool) - go func() { - defer GinkgoRecover() - - started <- true - brpop := client.BRPop(0, "list") - Expect(brpop.Err()).NotTo(HaveOccurred()) - Expect(brpop.Val()).To(Equal([]string{"list", "a"})) - done <- true - }() - <-started - - select { - case <-done: - Fail("BRPop is not blocked") - case <-time.After(time.Second): - // ok - } - - rPush := client.RPush("list", "a") - Expect(rPush.Err()).NotTo(HaveOccurred()) - - select { - case <-done: - // ok - case <-time.After(time.Second): - Fail("BRPop is still blocked") - // ok - } - }) - - It("should BRPopLPush", func() { - _, err := client.BRPopLPush("list1", "list2", time.Second).Result() - Expect(err).To(Equal(redis.Nil)) - - err = client.RPush("list1", "a", "b", "c").Err() - Expect(err).NotTo(HaveOccurred()) - - v, err := client.BRPopLPush("list1", "list2", 0).Result() - Expect(err).NotTo(HaveOccurred()) - Expect(v).To(Equal("c")) - }) - - It("should LIndex", func() { - lPush := client.LPush("list", "World") - Expect(lPush.Err()).NotTo(HaveOccurred()) - lPush = client.LPush("list", "Hello") - Expect(lPush.Err()).NotTo(HaveOccurred()) - - lIndex := client.LIndex("list", 0) - Expect(lIndex.Err()).NotTo(HaveOccurred()) - Expect(lIndex.Val()).To(Equal("Hello")) - - lIndex = client.LIndex("list", -1) - Expect(lIndex.Err()).NotTo(HaveOccurred()) - Expect(lIndex.Val()).To(Equal("World")) - - lIndex = client.LIndex("list", 3) - Expect(lIndex.Err()).To(Equal(redis.Nil)) - Expect(lIndex.Val()).To(Equal("")) - }) - - It("should LInsert", func() { - rPush := client.RPush("list", "Hello") - Expect(rPush.Err()).NotTo(HaveOccurred()) - rPush = client.RPush("list", "World") - Expect(rPush.Err()).NotTo(HaveOccurred()) - - lInsert := client.LInsert("list", "BEFORE", "World", "There") - Expect(lInsert.Err()).NotTo(HaveOccurred()) - Expect(lInsert.Val()).To(Equal(int64(3))) - - lRange := client.LRange("list", 0, -1) - Expect(lRange.Err()).NotTo(HaveOccurred()) - Expect(lRange.Val()).To(Equal([]string{"Hello", "There", "World"})) - }) - - It("should LLen", func() { - lPush := client.LPush("list", "World") - Expect(lPush.Err()).NotTo(HaveOccurred()) - lPush = client.LPush("list", "Hello") - Expect(lPush.Err()).NotTo(HaveOccurred()) - - lLen := client.LLen("list") - Expect(lLen.Err()).NotTo(HaveOccurred()) - Expect(lLen.Val()).To(Equal(int64(2))) - }) - - It("should LPop", func() { - rPush := client.RPush("list", "one") - Expect(rPush.Err()).NotTo(HaveOccurred()) - rPush = client.RPush("list", "two") - Expect(rPush.Err()).NotTo(HaveOccurred()) - rPush = client.RPush("list", "three") - Expect(rPush.Err()).NotTo(HaveOccurred()) - - lPop := client.LPop("list") - Expect(lPop.Err()).NotTo(HaveOccurred()) - Expect(lPop.Val()).To(Equal("one")) - - lRange := client.LRange("list", 0, -1) - Expect(lRange.Err()).NotTo(HaveOccurred()) - Expect(lRange.Val()).To(Equal([]string{"two", "three"})) - }) - - It("should LPush", func() { - lPush := client.LPush("list", "World") - Expect(lPush.Err()).NotTo(HaveOccurred()) - lPush = client.LPush("list", "Hello") - Expect(lPush.Err()).NotTo(HaveOccurred()) - - lRange := client.LRange("list", 0, -1) - Expect(lRange.Err()).NotTo(HaveOccurred()) - Expect(lRange.Val()).To(Equal([]string{"Hello", "World"})) - }) - - It("should LPushX", func() { - lPush := client.LPush("list", "World") - Expect(lPush.Err()).NotTo(HaveOccurred()) - - lPushX := client.LPushX("list", "Hello") - Expect(lPushX.Err()).NotTo(HaveOccurred()) - Expect(lPushX.Val()).To(Equal(int64(2))) - - lPushX = client.LPushX("list2", "Hello") - Expect(lPushX.Err()).NotTo(HaveOccurred()) - Expect(lPushX.Val()).To(Equal(int64(0))) - - lRange := client.LRange("list", 0, -1) - Expect(lRange.Err()).NotTo(HaveOccurred()) - Expect(lRange.Val()).To(Equal([]string{"Hello", "World"})) - - lRange = client.LRange("list2", 0, -1) - Expect(lRange.Err()).NotTo(HaveOccurred()) - Expect(lRange.Val()).To(Equal([]string{})) - }) - - It("should LRange", func() { - rPush := client.RPush("list", "one") - Expect(rPush.Err()).NotTo(HaveOccurred()) - rPush = client.RPush("list", "two") - Expect(rPush.Err()).NotTo(HaveOccurred()) - rPush = client.RPush("list", "three") - Expect(rPush.Err()).NotTo(HaveOccurred()) - - lRange := client.LRange("list", 0, 0) - Expect(lRange.Err()).NotTo(HaveOccurred()) - Expect(lRange.Val()).To(Equal([]string{"one"})) - - lRange = client.LRange("list", -3, 2) - Expect(lRange.Err()).NotTo(HaveOccurred()) - Expect(lRange.Val()).To(Equal([]string{"one", "two", "three"})) - - lRange = client.LRange("list", -100, 100) - Expect(lRange.Err()).NotTo(HaveOccurred()) - Expect(lRange.Val()).To(Equal([]string{"one", "two", "three"})) - - lRange = client.LRange("list", 5, 10) - Expect(lRange.Err()).NotTo(HaveOccurred()) - Expect(lRange.Val()).To(Equal([]string{})) - }) - - It("should LRem", func() { - rPush := client.RPush("list", "hello") - Expect(rPush.Err()).NotTo(HaveOccurred()) - rPush = client.RPush("list", "hello") - Expect(rPush.Err()).NotTo(HaveOccurred()) - rPush = client.RPush("list", "key") - Expect(rPush.Err()).NotTo(HaveOccurred()) - rPush = client.RPush("list", "hello") - Expect(rPush.Err()).NotTo(HaveOccurred()) - - lRem := client.LRem("list", -2, "hello") - Expect(lRem.Err()).NotTo(HaveOccurred()) - Expect(lRem.Val()).To(Equal(int64(2))) - - lRange := client.LRange("list", 0, -1) - Expect(lRange.Err()).NotTo(HaveOccurred()) - Expect(lRange.Val()).To(Equal([]string{"hello", "key"})) - }) - - It("should LSet", func() { - rPush := client.RPush("list", "one") - Expect(rPush.Err()).NotTo(HaveOccurred()) - rPush = client.RPush("list", "two") - Expect(rPush.Err()).NotTo(HaveOccurred()) - rPush = client.RPush("list", "three") - Expect(rPush.Err()).NotTo(HaveOccurred()) - - lSet := client.LSet("list", 0, "four") - Expect(lSet.Err()).NotTo(HaveOccurred()) - Expect(lSet.Val()).To(Equal("OK")) - - lSet = client.LSet("list", -2, "five") - Expect(lSet.Err()).NotTo(HaveOccurred()) - Expect(lSet.Val()).To(Equal("OK")) - - lRange := client.LRange("list", 0, -1) - Expect(lRange.Err()).NotTo(HaveOccurred()) - Expect(lRange.Val()).To(Equal([]string{"four", "five", "three"})) - }) - - It("should LTrim", func() { - rPush := client.RPush("list", "one") - Expect(rPush.Err()).NotTo(HaveOccurred()) - rPush = client.RPush("list", "two") - Expect(rPush.Err()).NotTo(HaveOccurred()) - rPush = client.RPush("list", "three") - Expect(rPush.Err()).NotTo(HaveOccurred()) - - lTrim := client.LTrim("list", 1, -1) - Expect(lTrim.Err()).NotTo(HaveOccurred()) - Expect(lTrim.Val()).To(Equal("OK")) - - lRange := client.LRange("list", 0, -1) - Expect(lRange.Err()).NotTo(HaveOccurred()) - Expect(lRange.Val()).To(Equal([]string{"two", "three"})) - }) - - It("should RPop", func() { - rPush := client.RPush("list", "one") - Expect(rPush.Err()).NotTo(HaveOccurred()) - rPush = client.RPush("list", "two") - Expect(rPush.Err()).NotTo(HaveOccurred()) - rPush = client.RPush("list", "three") - Expect(rPush.Err()).NotTo(HaveOccurred()) - - rPop := client.RPop("list") - Expect(rPop.Err()).NotTo(HaveOccurred()) - Expect(rPop.Val()).To(Equal("three")) - - lRange := client.LRange("list", 0, -1) - Expect(lRange.Err()).NotTo(HaveOccurred()) - Expect(lRange.Val()).To(Equal([]string{"one", "two"})) - }) - - It("should RPopLPush", func() { - rPush := client.RPush("list", "one") - Expect(rPush.Err()).NotTo(HaveOccurred()) - rPush = client.RPush("list", "two") - Expect(rPush.Err()).NotTo(HaveOccurred()) - rPush = client.RPush("list", "three") - Expect(rPush.Err()).NotTo(HaveOccurred()) - - rPopLPush := client.RPopLPush("list", "list2") - Expect(rPopLPush.Err()).NotTo(HaveOccurred()) - Expect(rPopLPush.Val()).To(Equal("three")) - - lRange := client.LRange("list", 0, -1) - Expect(lRange.Err()).NotTo(HaveOccurred()) - Expect(lRange.Val()).To(Equal([]string{"one", "two"})) - - lRange = client.LRange("list2", 0, -1) - Expect(lRange.Err()).NotTo(HaveOccurred()) - Expect(lRange.Val()).To(Equal([]string{"three"})) - }) - - It("should RPush", func() { - rPush := client.RPush("list", "Hello") - Expect(rPush.Err()).NotTo(HaveOccurred()) - Expect(rPush.Val()).To(Equal(int64(1))) - - rPush = client.RPush("list", "World") - Expect(rPush.Err()).NotTo(HaveOccurred()) - Expect(rPush.Val()).To(Equal(int64(2))) - - lRange := client.LRange("list", 0, -1) - Expect(lRange.Err()).NotTo(HaveOccurred()) - Expect(lRange.Val()).To(Equal([]string{"Hello", "World"})) - }) - - It("should RPushX", func() { - rPush := client.RPush("list", "Hello") - Expect(rPush.Err()).NotTo(HaveOccurred()) - Expect(rPush.Val()).To(Equal(int64(1))) - - rPushX := client.RPushX("list", "World") - Expect(rPushX.Err()).NotTo(HaveOccurred()) - Expect(rPushX.Val()).To(Equal(int64(2))) - - rPushX = client.RPushX("list2", "World") - Expect(rPushX.Err()).NotTo(HaveOccurred()) - Expect(rPushX.Val()).To(Equal(int64(0))) - - lRange := client.LRange("list", 0, -1) - Expect(lRange.Err()).NotTo(HaveOccurred()) - Expect(lRange.Val()).To(Equal([]string{"Hello", "World"})) - - lRange = client.LRange("list2", 0, -1) - Expect(lRange.Err()).NotTo(HaveOccurred()) - Expect(lRange.Val()).To(Equal([]string{})) - }) - - }) - - Describe("sets", func() { - - It("should SAdd", func() { - sAdd := client.SAdd("set", "Hello") - Expect(sAdd.Err()).NotTo(HaveOccurred()) - Expect(sAdd.Val()).To(Equal(int64(1))) - - sAdd = client.SAdd("set", "World") - Expect(sAdd.Err()).NotTo(HaveOccurred()) - Expect(sAdd.Val()).To(Equal(int64(1))) - - sAdd = client.SAdd("set", "World") - Expect(sAdd.Err()).NotTo(HaveOccurred()) - Expect(sAdd.Val()).To(Equal(int64(0))) - - sMembers := client.SMembers("set") - Expect(sMembers.Err()).NotTo(HaveOccurred()) - Expect(sMembers.Val()).To(ConsistOf([]string{"Hello", "World"})) - }) - - It("should SCard", func() { - sAdd := client.SAdd("set", "Hello") - Expect(sAdd.Err()).NotTo(HaveOccurred()) - Expect(sAdd.Val()).To(Equal(int64(1))) - - sAdd = client.SAdd("set", "World") - Expect(sAdd.Err()).NotTo(HaveOccurred()) - Expect(sAdd.Val()).To(Equal(int64(1))) - - sCard := client.SCard("set") - Expect(sCard.Err()).NotTo(HaveOccurred()) - Expect(sCard.Val()).To(Equal(int64(2))) - }) - - It("should SDiff", func() { - sAdd := client.SAdd("set1", "a") - Expect(sAdd.Err()).NotTo(HaveOccurred()) - sAdd = client.SAdd("set1", "b") - Expect(sAdd.Err()).NotTo(HaveOccurred()) - sAdd = client.SAdd("set1", "c") - Expect(sAdd.Err()).NotTo(HaveOccurred()) - - sAdd = client.SAdd("set2", "c") - Expect(sAdd.Err()).NotTo(HaveOccurred()) - sAdd = client.SAdd("set2", "d") - Expect(sAdd.Err()).NotTo(HaveOccurred()) - sAdd = client.SAdd("set2", "e") - Expect(sAdd.Err()).NotTo(HaveOccurred()) - - sDiff := client.SDiff("set1", "set2") - Expect(sDiff.Err()).NotTo(HaveOccurred()) - Expect(sDiff.Val()).To(ConsistOf([]string{"a", "b"})) - }) - - It("should SDiffStore", func() { - sAdd := client.SAdd("set1", "a") - Expect(sAdd.Err()).NotTo(HaveOccurred()) - sAdd = client.SAdd("set1", "b") - Expect(sAdd.Err()).NotTo(HaveOccurred()) - sAdd = client.SAdd("set1", "c") - Expect(sAdd.Err()).NotTo(HaveOccurred()) - - sAdd = client.SAdd("set2", "c") - Expect(sAdd.Err()).NotTo(HaveOccurred()) - sAdd = client.SAdd("set2", "d") - Expect(sAdd.Err()).NotTo(HaveOccurred()) - sAdd = client.SAdd("set2", "e") - Expect(sAdd.Err()).NotTo(HaveOccurred()) - - sDiffStore := client.SDiffStore("set", "set1", "set2") - Expect(sDiffStore.Err()).NotTo(HaveOccurred()) - Expect(sDiffStore.Val()).To(Equal(int64(2))) - - sMembers := client.SMembers("set") - Expect(sMembers.Err()).NotTo(HaveOccurred()) - Expect(sMembers.Val()).To(ConsistOf([]string{"a", "b"})) - }) - - It("should SInter", func() { - sAdd := client.SAdd("set1", "a") - Expect(sAdd.Err()).NotTo(HaveOccurred()) - sAdd = client.SAdd("set1", "b") - Expect(sAdd.Err()).NotTo(HaveOccurred()) - sAdd = client.SAdd("set1", "c") - Expect(sAdd.Err()).NotTo(HaveOccurred()) - - sAdd = client.SAdd("set2", "c") - Expect(sAdd.Err()).NotTo(HaveOccurred()) - sAdd = client.SAdd("set2", "d") - Expect(sAdd.Err()).NotTo(HaveOccurred()) - sAdd = client.SAdd("set2", "e") - Expect(sAdd.Err()).NotTo(HaveOccurred()) - - sInter := client.SInter("set1", "set2") - Expect(sInter.Err()).NotTo(HaveOccurred()) - Expect(sInter.Val()).To(Equal([]string{"c"})) - }) - - It("should SInterStore", func() { - sAdd := client.SAdd("set1", "a") - Expect(sAdd.Err()).NotTo(HaveOccurred()) - sAdd = client.SAdd("set1", "b") - Expect(sAdd.Err()).NotTo(HaveOccurred()) - sAdd = client.SAdd("set1", "c") - Expect(sAdd.Err()).NotTo(HaveOccurred()) - - sAdd = client.SAdd("set2", "c") - Expect(sAdd.Err()).NotTo(HaveOccurred()) - sAdd = client.SAdd("set2", "d") - Expect(sAdd.Err()).NotTo(HaveOccurred()) - sAdd = client.SAdd("set2", "e") - Expect(sAdd.Err()).NotTo(HaveOccurred()) - - sInterStore := client.SInterStore("set", "set1", "set2") - Expect(sInterStore.Err()).NotTo(HaveOccurred()) - Expect(sInterStore.Val()).To(Equal(int64(1))) - - sMembers := client.SMembers("set") - Expect(sMembers.Err()).NotTo(HaveOccurred()) - Expect(sMembers.Val()).To(Equal([]string{"c"})) - }) - - It("should IsMember", func() { - sAdd := client.SAdd("set", "one") - Expect(sAdd.Err()).NotTo(HaveOccurred()) - - sIsMember := client.SIsMember("set", "one") - Expect(sIsMember.Err()).NotTo(HaveOccurred()) - Expect(sIsMember.Val()).To(Equal(true)) - - sIsMember = client.SIsMember("set", "two") - Expect(sIsMember.Err()).NotTo(HaveOccurred()) - Expect(sIsMember.Val()).To(Equal(false)) - }) - - It("should SMembers", func() { - sAdd := client.SAdd("set", "Hello") - Expect(sAdd.Err()).NotTo(HaveOccurred()) - sAdd = client.SAdd("set", "World") - Expect(sAdd.Err()).NotTo(HaveOccurred()) - - sMembers := client.SMembers("set") - Expect(sMembers.Err()).NotTo(HaveOccurred()) - Expect(sMembers.Val()).To(ConsistOf([]string{"Hello", "World"})) - }) - - It("should SMembersMap", func() { - sAdd := client.SAdd("set", "Hello") - Expect(sAdd.Err()).NotTo(HaveOccurred()) - sAdd = client.SAdd("set", "World") - Expect(sAdd.Err()).NotTo(HaveOccurred()) - - sMembersMap := client.SMembersMap("set") - Expect(sMembersMap.Err()).NotTo(HaveOccurred()) - Expect(sMembersMap.Val()).To(Equal(map[string]struct{}{"Hello": struct{}{}, "World": struct{}{}})) - }) - - It("should SMove", func() { - sAdd := client.SAdd("set1", "one") - Expect(sAdd.Err()).NotTo(HaveOccurred()) - sAdd = client.SAdd("set1", "two") - Expect(sAdd.Err()).NotTo(HaveOccurred()) - - sAdd = client.SAdd("set2", "three") - Expect(sAdd.Err()).NotTo(HaveOccurred()) - - sMove := client.SMove("set1", "set2", "two") - Expect(sMove.Err()).NotTo(HaveOccurred()) - Expect(sMove.Val()).To(Equal(true)) - - sMembers := client.SMembers("set1") - Expect(sMembers.Err()).NotTo(HaveOccurred()) - Expect(sMembers.Val()).To(Equal([]string{"one"})) - - sMembers = client.SMembers("set2") - Expect(sMembers.Err()).NotTo(HaveOccurred()) - Expect(sMembers.Val()).To(ConsistOf([]string{"three", "two"})) - }) - - It("should SPop", func() { - sAdd := client.SAdd("set", "one") - Expect(sAdd.Err()).NotTo(HaveOccurred()) - sAdd = client.SAdd("set", "two") - Expect(sAdd.Err()).NotTo(HaveOccurred()) - sAdd = client.SAdd("set", "three") - Expect(sAdd.Err()).NotTo(HaveOccurred()) - - sPop := client.SPop("set") - Expect(sPop.Err()).NotTo(HaveOccurred()) - Expect(sPop.Val()).NotTo(Equal("")) - - sMembers := client.SMembers("set") - Expect(sMembers.Err()).NotTo(HaveOccurred()) - Expect(sMembers.Val()).To(HaveLen(2)) - - }) - - It("should SPopN", func() { - sAdd := client.SAdd("set", "one") - Expect(sAdd.Err()).NotTo(HaveOccurred()) - sAdd = client.SAdd("set", "two") - Expect(sAdd.Err()).NotTo(HaveOccurred()) - sAdd = client.SAdd("set", "three") - Expect(sAdd.Err()).NotTo(HaveOccurred()) - sAdd = client.SAdd("set", "four") - Expect(sAdd.Err()).NotTo(HaveOccurred()) - - sPopN := client.SPopN("set", 1) - Expect(sPopN.Err()).NotTo(HaveOccurred()) - Expect(sPopN.Val()).NotTo(Equal([]string{""})) - - sMembers := client.SMembers("set") - Expect(sMembers.Err()).NotTo(HaveOccurred()) - Expect(sMembers.Val()).To(HaveLen(3)) - - sPopN = client.SPopN("set", 4) - Expect(sPopN.Err()).NotTo(HaveOccurred()) - Expect(sPopN.Val()).To(HaveLen(3)) - - sMembers = client.SMembers("set") - Expect(sMembers.Err()).NotTo(HaveOccurred()) - Expect(sMembers.Val()).To(HaveLen(0)) - }) - - It("should SRandMember and SRandMemberN", func() { - err := client.SAdd("set", "one").Err() - Expect(err).NotTo(HaveOccurred()) - err = client.SAdd("set", "two").Err() - Expect(err).NotTo(HaveOccurred()) - err = client.SAdd("set", "three").Err() - Expect(err).NotTo(HaveOccurred()) - - members, err := client.SMembers("set").Result() - Expect(err).NotTo(HaveOccurred()) - Expect(members).To(HaveLen(3)) - - member, err := client.SRandMember("set").Result() - Expect(err).NotTo(HaveOccurred()) - Expect(member).NotTo(Equal("")) - - members, err = client.SRandMemberN("set", 2).Result() - Expect(err).NotTo(HaveOccurred()) - Expect(members).To(HaveLen(2)) - }) - - It("should SRem", func() { - sAdd := client.SAdd("set", "one") - Expect(sAdd.Err()).NotTo(HaveOccurred()) - sAdd = client.SAdd("set", "two") - Expect(sAdd.Err()).NotTo(HaveOccurred()) - sAdd = client.SAdd("set", "three") - Expect(sAdd.Err()).NotTo(HaveOccurred()) - - sRem := client.SRem("set", "one") - Expect(sRem.Err()).NotTo(HaveOccurred()) - Expect(sRem.Val()).To(Equal(int64(1))) - - sRem = client.SRem("set", "four") - Expect(sRem.Err()).NotTo(HaveOccurred()) - Expect(sRem.Val()).To(Equal(int64(0))) - - sMembers := client.SMembers("set") - Expect(sMembers.Err()).NotTo(HaveOccurred()) - Expect(sMembers.Val()).To(ConsistOf([]string{"three", "two"})) - }) - - It("should SUnion", func() { - sAdd := client.SAdd("set1", "a") - Expect(sAdd.Err()).NotTo(HaveOccurred()) - sAdd = client.SAdd("set1", "b") - Expect(sAdd.Err()).NotTo(HaveOccurred()) - sAdd = client.SAdd("set1", "c") - Expect(sAdd.Err()).NotTo(HaveOccurred()) - - sAdd = client.SAdd("set2", "c") - Expect(sAdd.Err()).NotTo(HaveOccurred()) - sAdd = client.SAdd("set2", "d") - Expect(sAdd.Err()).NotTo(HaveOccurred()) - sAdd = client.SAdd("set2", "e") - Expect(sAdd.Err()).NotTo(HaveOccurred()) - - sUnion := client.SUnion("set1", "set2") - Expect(sUnion.Err()).NotTo(HaveOccurred()) - Expect(sUnion.Val()).To(HaveLen(5)) - }) - - It("should SUnionStore", func() { - sAdd := client.SAdd("set1", "a") - Expect(sAdd.Err()).NotTo(HaveOccurred()) - sAdd = client.SAdd("set1", "b") - Expect(sAdd.Err()).NotTo(HaveOccurred()) - sAdd = client.SAdd("set1", "c") - Expect(sAdd.Err()).NotTo(HaveOccurred()) - - sAdd = client.SAdd("set2", "c") - Expect(sAdd.Err()).NotTo(HaveOccurred()) - sAdd = client.SAdd("set2", "d") - Expect(sAdd.Err()).NotTo(HaveOccurred()) - sAdd = client.SAdd("set2", "e") - Expect(sAdd.Err()).NotTo(HaveOccurred()) - - sUnionStore := client.SUnionStore("set", "set1", "set2") - Expect(sUnionStore.Err()).NotTo(HaveOccurred()) - Expect(sUnionStore.Val()).To(Equal(int64(5))) - - sMembers := client.SMembers("set") - Expect(sMembers.Err()).NotTo(HaveOccurred()) - Expect(sMembers.Val()).To(HaveLen(5)) - }) - - }) - - Describe("sorted sets", func() { - - It("should ZAdd", func() { - added, err := client.ZAdd("zset", redis.Z{1, "one"}).Result() - Expect(err).NotTo(HaveOccurred()) - Expect(added).To(Equal(int64(1))) - - added, err = client.ZAdd("zset", redis.Z{1, "uno"}).Result() - Expect(err).NotTo(HaveOccurred()) - Expect(added).To(Equal(int64(1))) - - added, err = client.ZAdd("zset", redis.Z{2, "two"}).Result() - Expect(err).NotTo(HaveOccurred()) - Expect(added).To(Equal(int64(1))) - - added, err = client.ZAdd("zset", redis.Z{3, "two"}).Result() - Expect(err).NotTo(HaveOccurred()) - Expect(added).To(Equal(int64(0))) - - vals, err := client.ZRangeWithScores("zset", 0, -1).Result() - Expect(err).NotTo(HaveOccurred()) - Expect(vals).To(Equal([]redis.Z{{1, "one"}, {1, "uno"}, {3, "two"}})) - }) - - It("should ZAdd bytes", func() { - added, err := client.ZAdd("zset", redis.Z{1, []byte("one")}).Result() - Expect(err).NotTo(HaveOccurred()) - Expect(added).To(Equal(int64(1))) - - added, err = client.ZAdd("zset", redis.Z{1, []byte("uno")}).Result() - Expect(err).NotTo(HaveOccurred()) - Expect(added).To(Equal(int64(1))) - - added, err = client.ZAdd("zset", redis.Z{2, []byte("two")}).Result() - Expect(err).NotTo(HaveOccurred()) - Expect(added).To(Equal(int64(1))) - - added, err = client.ZAdd("zset", redis.Z{3, []byte("two")}).Result() - Expect(err).NotTo(HaveOccurred()) - Expect(added).To(Equal(int64(0))) - - val, err := client.ZRangeWithScores("zset", 0, -1).Result() - Expect(err).NotTo(HaveOccurred()) - Expect(val).To(Equal([]redis.Z{{1, "one"}, {1, "uno"}, {3, "two"}})) - }) - - It("should ZAddNX", func() { - added, err := client.ZAddNX("zset", redis.Z{1, "one"}).Result() - Expect(err).NotTo(HaveOccurred()) - Expect(added).To(Equal(int64(1))) - - vals, err := client.ZRangeWithScores("zset", 0, -1).Result() - Expect(err).NotTo(HaveOccurred()) - Expect(vals).To(Equal([]redis.Z{{1, "one"}})) - - added, err = client.ZAddNX("zset", redis.Z{2, "one"}).Result() - Expect(err).NotTo(HaveOccurred()) - Expect(added).To(Equal(int64(0))) - - vals, err = client.ZRangeWithScores("zset", 0, -1).Result() - Expect(err).NotTo(HaveOccurred()) - Expect(vals).To(Equal([]redis.Z{{1, "one"}})) - }) - - It("should ZAddXX", func() { - added, err := client.ZAddXX("zset", redis.Z{1, "one"}).Result() - Expect(err).NotTo(HaveOccurred()) - Expect(added).To(Equal(int64(0))) - - vals, err := client.ZRangeWithScores("zset", 0, -1).Result() - Expect(err).NotTo(HaveOccurred()) - Expect(vals).To(BeEmpty()) - - added, err = client.ZAdd("zset", redis.Z{1, "one"}).Result() - Expect(err).NotTo(HaveOccurred()) - Expect(added).To(Equal(int64(1))) - - added, err = client.ZAddXX("zset", redis.Z{2, "one"}).Result() - Expect(err).NotTo(HaveOccurred()) - Expect(added).To(Equal(int64(0))) - - vals, err = client.ZRangeWithScores("zset", 0, -1).Result() - Expect(err).NotTo(HaveOccurred()) - Expect(vals).To(Equal([]redis.Z{{2, "one"}})) - }) - - It("should ZAddCh", func() { - changed, err := client.ZAddCh("zset", redis.Z{1, "one"}).Result() - Expect(err).NotTo(HaveOccurred()) - Expect(changed).To(Equal(int64(1))) - - changed, err = client.ZAddCh("zset", redis.Z{1, "one"}).Result() - Expect(err).NotTo(HaveOccurred()) - Expect(changed).To(Equal(int64(0))) - }) - - It("should ZAddNXCh", func() { - changed, err := client.ZAddNXCh("zset", redis.Z{1, "one"}).Result() - Expect(err).NotTo(HaveOccurred()) - Expect(changed).To(Equal(int64(1))) - - vals, err := client.ZRangeWithScores("zset", 0, -1).Result() - Expect(err).NotTo(HaveOccurred()) - Expect(vals).To(Equal([]redis.Z{{1, "one"}})) - - changed, err = client.ZAddNXCh("zset", redis.Z{2, "one"}).Result() - Expect(err).NotTo(HaveOccurred()) - Expect(changed).To(Equal(int64(0))) - - vals, err = client.ZRangeWithScores("zset", 0, -1).Result() - Expect(err).NotTo(HaveOccurred()) - Expect(vals).To(Equal([]redis.Z{{1, "one"}})) - }) - - It("should ZAddXXCh", func() { - changed, err := client.ZAddXXCh("zset", redis.Z{1, "one"}).Result() - Expect(err).NotTo(HaveOccurred()) - Expect(changed).To(Equal(int64(0))) - - vals, err := client.ZRangeWithScores("zset", 0, -1).Result() - Expect(err).NotTo(HaveOccurred()) - Expect(vals).To(BeEmpty()) - - added, err := client.ZAdd("zset", redis.Z{1, "one"}).Result() - Expect(err).NotTo(HaveOccurred()) - Expect(added).To(Equal(int64(1))) - - changed, err = client.ZAddXXCh("zset", redis.Z{2, "one"}).Result() - Expect(err).NotTo(HaveOccurred()) - Expect(changed).To(Equal(int64(1))) - - vals, err = client.ZRangeWithScores("zset", 0, -1).Result() - Expect(err).NotTo(HaveOccurred()) - Expect(vals).To(Equal([]redis.Z{{2, "one"}})) - }) - - It("should ZIncr", func() { - score, err := client.ZIncr("zset", redis.Z{1, "one"}).Result() - Expect(err).NotTo(HaveOccurred()) - Expect(score).To(Equal(float64(1))) - - vals, err := client.ZRangeWithScores("zset", 0, -1).Result() - Expect(err).NotTo(HaveOccurred()) - Expect(vals).To(Equal([]redis.Z{{1, "one"}})) - - score, err = client.ZIncr("zset", redis.Z{1, "one"}).Result() - Expect(err).NotTo(HaveOccurred()) - Expect(score).To(Equal(float64(2))) - - vals, err = client.ZRangeWithScores("zset", 0, -1).Result() - Expect(err).NotTo(HaveOccurred()) - Expect(vals).To(Equal([]redis.Z{{2, "one"}})) - }) - - It("should ZIncrNX", func() { - score, err := client.ZIncrNX("zset", redis.Z{1, "one"}).Result() - Expect(err).NotTo(HaveOccurred()) - Expect(score).To(Equal(float64(1))) - - vals, err := client.ZRangeWithScores("zset", 0, -1).Result() - Expect(err).NotTo(HaveOccurred()) - Expect(vals).To(Equal([]redis.Z{{1, "one"}})) - - score, err = client.ZIncrNX("zset", redis.Z{1, "one"}).Result() - Expect(err).To(Equal(redis.Nil)) - Expect(score).To(Equal(float64(0))) - - vals, err = client.ZRangeWithScores("zset", 0, -1).Result() - Expect(err).NotTo(HaveOccurred()) - Expect(vals).To(Equal([]redis.Z{{1, "one"}})) - }) - - It("should ZIncrXX", func() { - score, err := client.ZIncrXX("zset", redis.Z{1, "one"}).Result() - Expect(err).To(Equal(redis.Nil)) - Expect(score).To(Equal(float64(0))) - - vals, err := client.ZRangeWithScores("zset", 0, -1).Result() - Expect(err).NotTo(HaveOccurred()) - Expect(vals).To(BeEmpty()) - - added, err := client.ZAdd("zset", redis.Z{1, "one"}).Result() - Expect(err).NotTo(HaveOccurred()) - Expect(added).To(Equal(int64(1))) - - score, err = client.ZIncrXX("zset", redis.Z{1, "one"}).Result() - Expect(err).NotTo(HaveOccurred()) - Expect(score).To(Equal(float64(2))) - - vals, err = client.ZRangeWithScores("zset", 0, -1).Result() - Expect(err).NotTo(HaveOccurred()) - Expect(vals).To(Equal([]redis.Z{{2, "one"}})) - }) - - It("should ZCard", func() { - zAdd := client.ZAdd("zset", redis.Z{1, "one"}) - Expect(zAdd.Err()).NotTo(HaveOccurred()) - zAdd = client.ZAdd("zset", redis.Z{2, "two"}) - Expect(zAdd.Err()).NotTo(HaveOccurred()) - - zCard := client.ZCard("zset") - Expect(zCard.Err()).NotTo(HaveOccurred()) - Expect(zCard.Val()).To(Equal(int64(2))) - }) - - It("should ZCount", func() { - err := client.ZAdd("zset", redis.Z{1, "one"}).Err() - Expect(err).NotTo(HaveOccurred()) - err = client.ZAdd("zset", redis.Z{2, "two"}).Err() - Expect(err).NotTo(HaveOccurred()) - err = client.ZAdd("zset", redis.Z{3, "three"}).Err() - Expect(err).NotTo(HaveOccurred()) - - count, err := client.ZCount("zset", "-inf", "+inf").Result() - Expect(err).NotTo(HaveOccurred()) - Expect(count).To(Equal(int64(3))) - - count, err = client.ZCount("zset", "(1", "3").Result() - Expect(err).NotTo(HaveOccurred()) - Expect(count).To(Equal(int64(2))) - - count, err = client.ZLexCount("zset", "-", "+").Result() - Expect(err).NotTo(HaveOccurred()) - Expect(count).To(Equal(int64(3))) - }) - - It("should ZIncrBy", func() { - zAdd := client.ZAdd("zset", redis.Z{1, "one"}) - Expect(zAdd.Err()).NotTo(HaveOccurred()) - zAdd = client.ZAdd("zset", redis.Z{2, "two"}) - Expect(zAdd.Err()).NotTo(HaveOccurred()) - - zIncrBy := client.ZIncrBy("zset", 2, "one") - Expect(zIncrBy.Err()).NotTo(HaveOccurred()) - Expect(zIncrBy.Val()).To(Equal(float64(3))) - - val, err := client.ZRangeWithScores("zset", 0, -1).Result() - Expect(err).NotTo(HaveOccurred()) - Expect(val).To(Equal([]redis.Z{{2, "two"}, {3, "one"}})) - }) - - It("should ZInterStore", func() { - zAdd := client.ZAdd("zset1", redis.Z{1, "one"}) - Expect(zAdd.Err()).NotTo(HaveOccurred()) - zAdd = client.ZAdd("zset1", redis.Z{2, "two"}) - Expect(zAdd.Err()).NotTo(HaveOccurred()) - - zAdd = client.ZAdd("zset2", redis.Z{1, "one"}) - Expect(zAdd.Err()).NotTo(HaveOccurred()) - zAdd = client.ZAdd("zset2", redis.Z{2, "two"}) - Expect(zAdd.Err()).NotTo(HaveOccurred()) - zAdd = client.ZAdd("zset3", redis.Z{3, "two"}) - Expect(zAdd.Err()).NotTo(HaveOccurred()) - - zInterStore := client.ZInterStore( - "out", redis.ZStore{Weights: []float64{2, 3}}, "zset1", "zset2") - Expect(zInterStore.Err()).NotTo(HaveOccurred()) - Expect(zInterStore.Val()).To(Equal(int64(2))) - - val, err := client.ZRangeWithScores("out", 0, -1).Result() - Expect(err).NotTo(HaveOccurred()) - Expect(val).To(Equal([]redis.Z{{5, "one"}, {10, "two"}})) - }) - - It("should ZRange", func() { - zAdd := client.ZAdd("zset", redis.Z{1, "one"}) - Expect(zAdd.Err()).NotTo(HaveOccurred()) - zAdd = client.ZAdd("zset", redis.Z{2, "two"}) - Expect(zAdd.Err()).NotTo(HaveOccurred()) - zAdd = client.ZAdd("zset", redis.Z{3, "three"}) - Expect(zAdd.Err()).NotTo(HaveOccurred()) - - zRange := client.ZRange("zset", 0, -1) - Expect(zRange.Err()).NotTo(HaveOccurred()) - Expect(zRange.Val()).To(Equal([]string{"one", "two", "three"})) - - zRange = client.ZRange("zset", 2, 3) - Expect(zRange.Err()).NotTo(HaveOccurred()) - Expect(zRange.Val()).To(Equal([]string{"three"})) - - zRange = client.ZRange("zset", -2, -1) - Expect(zRange.Err()).NotTo(HaveOccurred()) - Expect(zRange.Val()).To(Equal([]string{"two", "three"})) - }) - - It("should ZRangeWithScores", func() { - zAdd := client.ZAdd("zset", redis.Z{1, "one"}) - Expect(zAdd.Err()).NotTo(HaveOccurred()) - zAdd = client.ZAdd("zset", redis.Z{2, "two"}) - Expect(zAdd.Err()).NotTo(HaveOccurred()) - zAdd = client.ZAdd("zset", redis.Z{3, "three"}) - Expect(zAdd.Err()).NotTo(HaveOccurred()) - - val, err := client.ZRangeWithScores("zset", 0, -1).Result() - Expect(err).NotTo(HaveOccurred()) - Expect(val).To(Equal([]redis.Z{{1, "one"}, {2, "two"}, {3, "three"}})) - - val, err = client.ZRangeWithScores("zset", 2, 3).Result() - Expect(err).NotTo(HaveOccurred()) - Expect(val).To(Equal([]redis.Z{{3, "three"}})) - - val, err = client.ZRangeWithScores("zset", -2, -1).Result() - Expect(err).NotTo(HaveOccurred()) - Expect(val).To(Equal([]redis.Z{{2, "two"}, {3, "three"}})) - }) - - It("should ZRangeByScore", func() { - zAdd := client.ZAdd("zset", redis.Z{1, "one"}) - Expect(zAdd.Err()).NotTo(HaveOccurred()) - zAdd = client.ZAdd("zset", redis.Z{2, "two"}) - Expect(zAdd.Err()).NotTo(HaveOccurred()) - zAdd = client.ZAdd("zset", redis.Z{3, "three"}) - Expect(zAdd.Err()).NotTo(HaveOccurred()) - - zRangeByScore := client.ZRangeByScore("zset", redis.ZRangeBy{ - Min: "-inf", - Max: "+inf", - }) - Expect(zRangeByScore.Err()).NotTo(HaveOccurred()) - Expect(zRangeByScore.Val()).To(Equal([]string{"one", "two", "three"})) - - zRangeByScore = client.ZRangeByScore("zset", redis.ZRangeBy{ - Min: "1", - Max: "2", - }) - Expect(zRangeByScore.Err()).NotTo(HaveOccurred()) - Expect(zRangeByScore.Val()).To(Equal([]string{"one", "two"})) - - zRangeByScore = client.ZRangeByScore("zset", redis.ZRangeBy{ - Min: "(1", - Max: "2", - }) - Expect(zRangeByScore.Err()).NotTo(HaveOccurred()) - Expect(zRangeByScore.Val()).To(Equal([]string{"two"})) - - zRangeByScore = client.ZRangeByScore("zset", redis.ZRangeBy{ - Min: "(1", - Max: "(2", - }) - Expect(zRangeByScore.Err()).NotTo(HaveOccurred()) - Expect(zRangeByScore.Val()).To(Equal([]string{})) - }) - - It("should ZRangeByLex", func() { - zAdd := client.ZAdd("zset", redis.Z{0, "a"}) - Expect(zAdd.Err()).NotTo(HaveOccurred()) - zAdd = client.ZAdd("zset", redis.Z{0, "b"}) - Expect(zAdd.Err()).NotTo(HaveOccurred()) - zAdd = client.ZAdd("zset", redis.Z{0, "c"}) - Expect(zAdd.Err()).NotTo(HaveOccurred()) - - zRangeByLex := client.ZRangeByLex("zset", redis.ZRangeBy{ - Min: "-", - Max: "+", - }) - Expect(zRangeByLex.Err()).NotTo(HaveOccurred()) - Expect(zRangeByLex.Val()).To(Equal([]string{"a", "b", "c"})) - - zRangeByLex = client.ZRangeByLex("zset", redis.ZRangeBy{ - Min: "[a", - Max: "[b", - }) - Expect(zRangeByLex.Err()).NotTo(HaveOccurred()) - Expect(zRangeByLex.Val()).To(Equal([]string{"a", "b"})) - - zRangeByLex = client.ZRangeByLex("zset", redis.ZRangeBy{ - Min: "(a", - Max: "[b", - }) - Expect(zRangeByLex.Err()).NotTo(HaveOccurred()) - Expect(zRangeByLex.Val()).To(Equal([]string{"b"})) - - zRangeByLex = client.ZRangeByLex("zset", redis.ZRangeBy{ - Min: "(a", - Max: "(b", - }) - Expect(zRangeByLex.Err()).NotTo(HaveOccurred()) - Expect(zRangeByLex.Val()).To(Equal([]string{})) - }) - - It("should ZRangeByScoreWithScoresMap", func() { - zAdd := client.ZAdd("zset", redis.Z{1, "one"}) - Expect(zAdd.Err()).NotTo(HaveOccurred()) - zAdd = client.ZAdd("zset", redis.Z{2, "two"}) - Expect(zAdd.Err()).NotTo(HaveOccurred()) - zAdd = client.ZAdd("zset", redis.Z{3, "three"}) - Expect(zAdd.Err()).NotTo(HaveOccurred()) - - val, err := client.ZRangeByScoreWithScores("zset", redis.ZRangeBy{ - Min: "-inf", - Max: "+inf", - }).Result() - Expect(err).NotTo(HaveOccurred()) - Expect(val).To(Equal([]redis.Z{{1, "one"}, {2, "two"}, {3, "three"}})) - - val, err = client.ZRangeByScoreWithScores("zset", redis.ZRangeBy{ - Min: "1", - Max: "2", - }).Result() - Expect(err).NotTo(HaveOccurred()) - Expect(val).To(Equal([]redis.Z{{1, "one"}, {2, "two"}})) - - val, err = client.ZRangeByScoreWithScores("zset", redis.ZRangeBy{ - Min: "(1", - Max: "2", - }).Result() - Expect(err).NotTo(HaveOccurred()) - Expect(val).To(Equal([]redis.Z{{2, "two"}})) - - val, err = client.ZRangeByScoreWithScores("zset", redis.ZRangeBy{ - Min: "(1", - Max: "(2", - }).Result() - Expect(err).NotTo(HaveOccurred()) - Expect(val).To(Equal([]redis.Z{})) - }) - - It("should ZRank", func() { - zAdd := client.ZAdd("zset", redis.Z{1, "one"}) - Expect(zAdd.Err()).NotTo(HaveOccurred()) - zAdd = client.ZAdd("zset", redis.Z{2, "two"}) - Expect(zAdd.Err()).NotTo(HaveOccurred()) - zAdd = client.ZAdd("zset", redis.Z{3, "three"}) - Expect(zAdd.Err()).NotTo(HaveOccurred()) - - zRank := client.ZRank("zset", "three") - Expect(zRank.Err()).NotTo(HaveOccurred()) - Expect(zRank.Val()).To(Equal(int64(2))) - - zRank = client.ZRank("zset", "four") - Expect(zRank.Err()).To(Equal(redis.Nil)) - Expect(zRank.Val()).To(Equal(int64(0))) - }) - - It("should ZRem", func() { - zAdd := client.ZAdd("zset", redis.Z{1, "one"}) - Expect(zAdd.Err()).NotTo(HaveOccurred()) - zAdd = client.ZAdd("zset", redis.Z{2, "two"}) - Expect(zAdd.Err()).NotTo(HaveOccurred()) - zAdd = client.ZAdd("zset", redis.Z{3, "three"}) - Expect(zAdd.Err()).NotTo(HaveOccurred()) - - zRem := client.ZRem("zset", "two") - Expect(zRem.Err()).NotTo(HaveOccurred()) - Expect(zRem.Val()).To(Equal(int64(1))) - - val, err := client.ZRangeWithScores("zset", 0, -1).Result() - Expect(err).NotTo(HaveOccurred()) - Expect(val).To(Equal([]redis.Z{{1, "one"}, {3, "three"}})) - }) - - It("should ZRemRangeByRank", func() { - zAdd := client.ZAdd("zset", redis.Z{1, "one"}) - Expect(zAdd.Err()).NotTo(HaveOccurred()) - zAdd = client.ZAdd("zset", redis.Z{2, "two"}) - Expect(zAdd.Err()).NotTo(HaveOccurred()) - zAdd = client.ZAdd("zset", redis.Z{3, "three"}) - Expect(zAdd.Err()).NotTo(HaveOccurred()) - - zRemRangeByRank := client.ZRemRangeByRank("zset", 0, 1) - Expect(zRemRangeByRank.Err()).NotTo(HaveOccurred()) - Expect(zRemRangeByRank.Val()).To(Equal(int64(2))) - - val, err := client.ZRangeWithScores("zset", 0, -1).Result() - Expect(err).NotTo(HaveOccurred()) - Expect(val).To(Equal([]redis.Z{{3, "three"}})) - }) - - It("should ZRemRangeByScore", func() { - zAdd := client.ZAdd("zset", redis.Z{1, "one"}) - Expect(zAdd.Err()).NotTo(HaveOccurred()) - zAdd = client.ZAdd("zset", redis.Z{2, "two"}) - Expect(zAdd.Err()).NotTo(HaveOccurred()) - zAdd = client.ZAdd("zset", redis.Z{3, "three"}) - Expect(zAdd.Err()).NotTo(HaveOccurred()) - - zRemRangeByScore := client.ZRemRangeByScore("zset", "-inf", "(2") - Expect(zRemRangeByScore.Err()).NotTo(HaveOccurred()) - Expect(zRemRangeByScore.Val()).To(Equal(int64(1))) - - val, err := client.ZRangeWithScores("zset", 0, -1).Result() - Expect(err).NotTo(HaveOccurred()) - Expect(val).To(Equal([]redis.Z{{2, "two"}, {3, "three"}})) - }) - - It("should ZRemRangeByLex", func() { - zz := []redis.Z{ - {0, "aaaa"}, - {0, "b"}, - {0, "c"}, - {0, "d"}, - {0, "e"}, - {0, "foo"}, - {0, "zap"}, - {0, "zip"}, - {0, "ALPHA"}, - {0, "alpha"}, - } - for _, z := range zz { - err := client.ZAdd("zset", z).Err() - Expect(err).NotTo(HaveOccurred()) - } - - n, err := client.ZRemRangeByLex("zset", "[alpha", "[omega").Result() - Expect(err).NotTo(HaveOccurred()) - Expect(n).To(Equal(int64(6))) - - vals, err := client.ZRange("zset", 0, -1).Result() - Expect(err).NotTo(HaveOccurred()) - Expect(vals).To(Equal([]string{"ALPHA", "aaaa", "zap", "zip"})) - }) - - It("should ZRevRange", func() { - zAdd := client.ZAdd("zset", redis.Z{1, "one"}) - Expect(zAdd.Err()).NotTo(HaveOccurred()) - zAdd = client.ZAdd("zset", redis.Z{2, "two"}) - Expect(zAdd.Err()).NotTo(HaveOccurred()) - zAdd = client.ZAdd("zset", redis.Z{3, "three"}) - Expect(zAdd.Err()).NotTo(HaveOccurred()) - - zRevRange := client.ZRevRange("zset", 0, -1) - Expect(zRevRange.Err()).NotTo(HaveOccurred()) - Expect(zRevRange.Val()).To(Equal([]string{"three", "two", "one"})) - - zRevRange = client.ZRevRange("zset", 2, 3) - Expect(zRevRange.Err()).NotTo(HaveOccurred()) - Expect(zRevRange.Val()).To(Equal([]string{"one"})) - - zRevRange = client.ZRevRange("zset", -2, -1) - Expect(zRevRange.Err()).NotTo(HaveOccurred()) - Expect(zRevRange.Val()).To(Equal([]string{"two", "one"})) - }) - - It("should ZRevRangeWithScoresMap", func() { - zAdd := client.ZAdd("zset", redis.Z{1, "one"}) - Expect(zAdd.Err()).NotTo(HaveOccurred()) - zAdd = client.ZAdd("zset", redis.Z{2, "two"}) - Expect(zAdd.Err()).NotTo(HaveOccurred()) - zAdd = client.ZAdd("zset", redis.Z{3, "three"}) - Expect(zAdd.Err()).NotTo(HaveOccurred()) - - val, err := client.ZRevRangeWithScores("zset", 0, -1).Result() - Expect(err).NotTo(HaveOccurred()) - Expect(val).To(Equal([]redis.Z{{3, "three"}, {2, "two"}, {1, "one"}})) - - val, err = client.ZRevRangeWithScores("zset", 2, 3).Result() - Expect(err).NotTo(HaveOccurred()) - Expect(val).To(Equal([]redis.Z{{1, "one"}})) - - val, err = client.ZRevRangeWithScores("zset", -2, -1).Result() - Expect(err).NotTo(HaveOccurred()) - Expect(val).To(Equal([]redis.Z{{2, "two"}, {1, "one"}})) - }) - - It("should ZRevRangeByScore", func() { - zadd := client.ZAdd("zset", redis.Z{1, "one"}) - Expect(zadd.Err()).NotTo(HaveOccurred()) - zadd = client.ZAdd("zset", redis.Z{2, "two"}) - Expect(zadd.Err()).NotTo(HaveOccurred()) - zadd = client.ZAdd("zset", redis.Z{3, "three"}) - Expect(zadd.Err()).NotTo(HaveOccurred()) - - vals, err := client.ZRevRangeByScore( - "zset", redis.ZRangeBy{Max: "+inf", Min: "-inf"}).Result() - Expect(err).NotTo(HaveOccurred()) - Expect(vals).To(Equal([]string{"three", "two", "one"})) - - vals, err = client.ZRevRangeByScore( - "zset", redis.ZRangeBy{Max: "2", Min: "(1"}).Result() - Expect(err).NotTo(HaveOccurred()) - Expect(vals).To(Equal([]string{"two"})) - - vals, err = client.ZRevRangeByScore( - "zset", redis.ZRangeBy{Max: "(2", Min: "(1"}).Result() - Expect(err).NotTo(HaveOccurred()) - Expect(vals).To(Equal([]string{})) - }) - - It("should ZRevRangeByLex", func() { - zadd := client.ZAdd("zset", redis.Z{0, "a"}) - Expect(zadd.Err()).NotTo(HaveOccurred()) - zadd = client.ZAdd("zset", redis.Z{0, "b"}) - Expect(zadd.Err()).NotTo(HaveOccurred()) - zadd = client.ZAdd("zset", redis.Z{0, "c"}) - Expect(zadd.Err()).NotTo(HaveOccurred()) - - vals, err := client.ZRevRangeByLex( - "zset", redis.ZRangeBy{Max: "+", Min: "-"}).Result() - Expect(err).NotTo(HaveOccurred()) - Expect(vals).To(Equal([]string{"c", "b", "a"})) - - vals, err = client.ZRevRangeByLex( - "zset", redis.ZRangeBy{Max: "[b", Min: "(a"}).Result() - Expect(err).NotTo(HaveOccurred()) - Expect(vals).To(Equal([]string{"b"})) - - vals, err = client.ZRevRangeByLex( - "zset", redis.ZRangeBy{Max: "(b", Min: "(a"}).Result() - Expect(err).NotTo(HaveOccurred()) - Expect(vals).To(Equal([]string{})) - }) - - It("should ZRevRangeByScoreWithScores", func() { - zadd := client.ZAdd("zset", redis.Z{1, "one"}) - Expect(zadd.Err()).NotTo(HaveOccurred()) - zadd = client.ZAdd("zset", redis.Z{2, "two"}) - Expect(zadd.Err()).NotTo(HaveOccurred()) - zadd = client.ZAdd("zset", redis.Z{3, "three"}) - Expect(zadd.Err()).NotTo(HaveOccurred()) - - vals, err := client.ZRevRangeByScoreWithScores( - "zset", redis.ZRangeBy{Max: "+inf", Min: "-inf"}).Result() - Expect(err).NotTo(HaveOccurred()) - Expect(vals).To(Equal([]redis.Z{{3, "three"}, {2, "two"}, {1, "one"}})) - }) - - It("should ZRevRangeByScoreWithScoresMap", func() { - zAdd := client.ZAdd("zset", redis.Z{1, "one"}) - Expect(zAdd.Err()).NotTo(HaveOccurred()) - zAdd = client.ZAdd("zset", redis.Z{2, "two"}) - Expect(zAdd.Err()).NotTo(HaveOccurred()) - zAdd = client.ZAdd("zset", redis.Z{3, "three"}) - Expect(zAdd.Err()).NotTo(HaveOccurred()) - - val, err := client.ZRevRangeByScoreWithScores( - "zset", redis.ZRangeBy{Max: "+inf", Min: "-inf"}).Result() - Expect(err).NotTo(HaveOccurred()) - Expect(val).To(Equal([]redis.Z{{3, "three"}, {2, "two"}, {1, "one"}})) - - val, err = client.ZRevRangeByScoreWithScores( - "zset", redis.ZRangeBy{Max: "2", Min: "(1"}).Result() - Expect(err).NotTo(HaveOccurred()) - Expect(val).To(Equal([]redis.Z{{2, "two"}})) - - val, err = client.ZRevRangeByScoreWithScores( - "zset", redis.ZRangeBy{Max: "(2", Min: "(1"}).Result() - Expect(err).NotTo(HaveOccurred()) - Expect(val).To(Equal([]redis.Z{})) - }) - - It("should ZRevRank", func() { - zAdd := client.ZAdd("zset", redis.Z{1, "one"}) - Expect(zAdd.Err()).NotTo(HaveOccurred()) - zAdd = client.ZAdd("zset", redis.Z{2, "two"}) - Expect(zAdd.Err()).NotTo(HaveOccurred()) - zAdd = client.ZAdd("zset", redis.Z{3, "three"}) - Expect(zAdd.Err()).NotTo(HaveOccurred()) - - zRevRank := client.ZRevRank("zset", "one") - Expect(zRevRank.Err()).NotTo(HaveOccurred()) - Expect(zRevRank.Val()).To(Equal(int64(2))) - - zRevRank = client.ZRevRank("zset", "four") - Expect(zRevRank.Err()).To(Equal(redis.Nil)) - Expect(zRevRank.Val()).To(Equal(int64(0))) - }) - - It("should ZScore", func() { - zAdd := client.ZAdd("zset", redis.Z{1.001, "one"}) - Expect(zAdd.Err()).NotTo(HaveOccurred()) - - zScore := client.ZScore("zset", "one") - Expect(zScore.Err()).NotTo(HaveOccurred()) - Expect(zScore.Val()).To(Equal(float64(1.001))) - }) - - It("should ZUnionStore", func() { - zAdd := client.ZAdd("zset1", redis.Z{1, "one"}) - Expect(zAdd.Err()).NotTo(HaveOccurred()) - zAdd = client.ZAdd("zset1", redis.Z{2, "two"}) - Expect(zAdd.Err()).NotTo(HaveOccurred()) - - zAdd = client.ZAdd("zset2", redis.Z{1, "one"}) - Expect(zAdd.Err()).NotTo(HaveOccurred()) - zAdd = client.ZAdd("zset2", redis.Z{2, "two"}) - Expect(zAdd.Err()).NotTo(HaveOccurred()) - zAdd = client.ZAdd("zset2", redis.Z{3, "three"}) - Expect(zAdd.Err()).NotTo(HaveOccurred()) - - zUnionStore := client.ZUnionStore( - "out", redis.ZStore{Weights: []float64{2, 3}}, "zset1", "zset2") - Expect(zUnionStore.Err()).NotTo(HaveOccurred()) - Expect(zUnionStore.Val()).To(Equal(int64(3))) - - val, err := client.ZRangeWithScores("out", 0, -1).Result() - Expect(err).NotTo(HaveOccurred()) - Expect(val).To(Equal([]redis.Z{{5, "one"}, {9, "three"}, {10, "two"}})) - }) - - }) - - Describe("Geo add and radius search", func() { - BeforeEach(func() { - geoAdd := client.GeoAdd( - "Sicily", - &redis.GeoLocation{Longitude: 13.361389, Latitude: 38.115556, Name: "Palermo"}, - &redis.GeoLocation{Longitude: 15.087269, Latitude: 37.502669, Name: "Catania"}, - ) - Expect(geoAdd.Err()).NotTo(HaveOccurred()) - Expect(geoAdd.Val()).To(Equal(int64(2))) - }) - - It("should not add same geo location", func() { - geoAdd := client.GeoAdd( - "Sicily", - &redis.GeoLocation{Longitude: 13.361389, Latitude: 38.115556, Name: "Palermo"}, - ) - Expect(geoAdd.Err()).NotTo(HaveOccurred()) - Expect(geoAdd.Val()).To(Equal(int64(0))) - }) - - It("should search geo radius", func() { - res, err := client.GeoRadius("Sicily", 15, 37, &redis.GeoRadiusQuery{ - Radius: 200, - }).Result() - Expect(err).NotTo(HaveOccurred()) - Expect(res).To(HaveLen(2)) - Expect(res[0].Name).To(Equal("Palermo")) - Expect(res[1].Name).To(Equal("Catania")) - }) - - It("should search geo radius with options", func() { - res, err := client.GeoRadius("Sicily", 15, 37, &redis.GeoRadiusQuery{ - Radius: 200, - Unit: "km", - WithGeoHash: true, - WithCoord: true, - WithDist: true, - Count: 2, - Sort: "ASC", - }).Result() - Expect(err).NotTo(HaveOccurred()) - Expect(res).To(HaveLen(2)) - Expect(res[1].Name).To(Equal("Palermo")) - Expect(res[1].Dist).To(Equal(190.4424)) - Expect(res[1].GeoHash).To(Equal(int64(3479099956230698))) - Expect(res[1].Longitude).To(Equal(13.361389338970184)) - Expect(res[1].Latitude).To(Equal(38.115556395496299)) - Expect(res[0].Name).To(Equal("Catania")) - Expect(res[0].Dist).To(Equal(56.4413)) - Expect(res[0].GeoHash).To(Equal(int64(3479447370796909))) - Expect(res[0].Longitude).To(Equal(15.087267458438873)) - Expect(res[0].Latitude).To(Equal(37.50266842333162)) - }) - - It("should search geo radius with WithDist=false", func() { - res, err := client.GeoRadius("Sicily", 15, 37, &redis.GeoRadiusQuery{ - Radius: 200, - Unit: "km", - WithGeoHash: true, - WithCoord: true, - Count: 2, - Sort: "ASC", - }).Result() - Expect(err).NotTo(HaveOccurred()) - Expect(res).To(HaveLen(2)) - Expect(res[1].Name).To(Equal("Palermo")) - Expect(res[1].Dist).To(Equal(float64(0))) - Expect(res[1].GeoHash).To(Equal(int64(3479099956230698))) - Expect(res[1].Longitude).To(Equal(13.361389338970184)) - Expect(res[1].Latitude).To(Equal(38.115556395496299)) - Expect(res[0].Name).To(Equal("Catania")) - Expect(res[0].Dist).To(Equal(float64(0))) - Expect(res[0].GeoHash).To(Equal(int64(3479447370796909))) - Expect(res[0].Longitude).To(Equal(15.087267458438873)) - Expect(res[0].Latitude).To(Equal(37.50266842333162)) - }) - - It("should search geo radius by member with options", func() { - res, err := client.GeoRadiusByMember("Sicily", "Catania", &redis.GeoRadiusQuery{ - Radius: 200, - Unit: "km", - WithGeoHash: true, - WithCoord: true, - WithDist: true, - Count: 2, - Sort: "ASC", - }).Result() - Expect(err).NotTo(HaveOccurred()) - Expect(res).To(HaveLen(2)) - Expect(res[0].Name).To(Equal("Catania")) - Expect(res[0].Dist).To(Equal(0.0)) - Expect(res[0].GeoHash).To(Equal(int64(3479447370796909))) - Expect(res[0].Longitude).To(Equal(15.087267458438873)) - Expect(res[0].Latitude).To(Equal(37.50266842333162)) - Expect(res[1].Name).To(Equal("Palermo")) - Expect(res[1].Dist).To(Equal(166.2742)) - Expect(res[1].GeoHash).To(Equal(int64(3479099956230698))) - Expect(res[1].Longitude).To(Equal(13.361389338970184)) - Expect(res[1].Latitude).To(Equal(38.115556395496299)) - }) - - It("should search geo radius with no results", func() { - res, err := client.GeoRadius("Sicily", 99, 37, &redis.GeoRadiusQuery{ - Radius: 200, - Unit: "km", - WithGeoHash: true, - WithCoord: true, - WithDist: true, - }).Result() - Expect(err).NotTo(HaveOccurred()) - Expect(res).To(HaveLen(0)) - }) - - It("should get geo distance with unit options", func() { - // From Redis CLI, note the difference in rounding in m vs - // km on Redis itself. - // - // GEOADD Sicily 13.361389 38.115556 "Palermo" 15.087269 37.502669 "Catania" - // GEODIST Sicily Palermo Catania m - // "166274.15156960033" - // GEODIST Sicily Palermo Catania km - // "166.27415156960032" - dist, err := client.GeoDist("Sicily", "Palermo", "Catania", "km").Result() - Expect(err).NotTo(HaveOccurred()) - Expect(dist).To(BeNumerically("~", 166.27, 0.01)) - - dist, err = client.GeoDist("Sicily", "Palermo", "Catania", "m").Result() - Expect(err).NotTo(HaveOccurred()) - Expect(dist).To(BeNumerically("~", 166274.15, 0.01)) - }) - - It("should get geo hash in string representation", func() { - hashes, err := client.GeoHash("Sicily", "Palermo", "Catania").Result() - Expect(err).NotTo(HaveOccurred()) - Expect(hashes).To(ConsistOf([]string{"sqc8b49rny0", "sqdtr74hyu0"})) - }) - - It("should return geo position", func() { - pos, err := client.GeoPos("Sicily", "Palermo", "Catania", "NonExisting").Result() - Expect(err).NotTo(HaveOccurred()) - Expect(pos).To(ConsistOf([]*redis.GeoPos{ - { - Longitude: 13.361389338970184, - Latitude: 38.1155563954963, - }, - { - Longitude: 15.087267458438873, - Latitude: 37.50266842333162, - }, - nil, - })) - }) - }) - - Describe("marshaling/unmarshaling", func() { - - type convTest struct { - value interface{} - wanted string - dest interface{} - } - - convTests := []convTest{ - {nil, "", nil}, - {"hello", "hello", new(string)}, - {[]byte("hello"), "hello", new([]byte)}, - {int(1), "1", new(int)}, - {int8(1), "1", new(int8)}, - {int16(1), "1", new(int16)}, - {int32(1), "1", new(int32)}, - {int64(1), "1", new(int64)}, - {uint(1), "1", new(uint)}, - {uint8(1), "1", new(uint8)}, - {uint16(1), "1", new(uint16)}, - {uint32(1), "1", new(uint32)}, - {uint64(1), "1", new(uint64)}, - {float32(1.0), "1", new(float32)}, - {float64(1.0), "1", new(float64)}, - {true, "1", new(bool)}, - {false, "0", new(bool)}, - } - - It("should convert to string", func() { - for _, test := range convTests { - err := client.Set("key", test.value, 0).Err() - Expect(err).NotTo(HaveOccurred()) - - s, err := client.Get("key").Result() - Expect(err).NotTo(HaveOccurred()) - Expect(s).To(Equal(test.wanted)) - - if test.dest == nil { - continue - } - - err = client.Get("key").Scan(test.dest) - Expect(err).NotTo(HaveOccurred()) - Expect(deref(test.dest)).To(Equal(test.value)) - } - }) - - }) - - Describe("json marshaling/unmarshaling", func() { - - BeforeEach(func() { - value := &numberStruct{Number: 42} - err := client.Set("key", value, 0).Err() - Expect(err).NotTo(HaveOccurred()) - }) - - It("should marshal custom values using json", func() { - s, err := client.Get("key").Result() - Expect(err).NotTo(HaveOccurred()) - Expect(s).To(Equal(`{"Number":42}`)) - }) - - It("should scan custom values using json", func() { - value := &numberStruct{} - err := client.Get("key").Scan(value) - Expect(err).NotTo(HaveOccurred()) - Expect(value.Number).To(Equal(42)) - }) - - }) - - Describe("Eval", func() { - - It("returns keys and values", func() { - vals, err := client.Eval( - "return {KEYS[1],ARGV[1]}", - []string{"key"}, - "hello", - ).Result() - Expect(err).NotTo(HaveOccurred()) - Expect(vals).To(Equal([]interface{}{"key", "hello"})) - }) - - }) - -}) - -type numberStruct struct { - Number int -} - -func (s *numberStruct) MarshalBinary() ([]byte, error) { - return json.Marshal(s) -} - -func (s *numberStruct) UnmarshalBinary(b []byte) error { - return json.Unmarshal(b, s) -} - -func deref(viface interface{}) interface{} { - v := reflect.ValueOf(viface) - for v.Kind() == reflect.Ptr { - v = v.Elem() - } - return v.Interface() -} diff --git a/vendor/github.com/go-redis/redis/example_instrumentation_test.go b/vendor/github.com/go-redis/redis/example_instrumentation_test.go deleted file mode 100644 index 85abbd744..000000000 --- a/vendor/github.com/go-redis/redis/example_instrumentation_test.go +++ /dev/null @@ -1,48 +0,0 @@ -package redis_test - -import ( - "fmt" - - "github.com/go-redis/redis" -) - -func Example_instrumentation() { - cl := redis.NewClient(&redis.Options{ - Addr: ":6379", - }) - cl.WrapProcess(func(old func(cmd redis.Cmder) error) func(cmd redis.Cmder) error { - return func(cmd redis.Cmder) error { - fmt.Printf("starting processing: <%s>\n", cmd) - err := old(cmd) - fmt.Printf("finished processing: <%s>\n", cmd) - return err - } - }) - - cl.Ping() - // Output: starting processing: <ping: > - // finished processing: <ping: PONG> -} - -func Example_Pipeline_instrumentation() { - client := redis.NewClient(&redis.Options{ - Addr: ":6379", - }) - - client.WrapProcessPipeline(func(old func([]redis.Cmder) error) func([]redis.Cmder) error { - return func(cmds []redis.Cmder) error { - fmt.Printf("pipeline starting processing: %v\n", cmds) - err := old(cmds) - fmt.Printf("pipeline finished processing: %v\n", cmds) - return err - } - }) - - client.Pipelined(func(pipe redis.Pipeliner) error { - pipe.Ping() - pipe.Ping() - return nil - }) - // Output: pipeline starting processing: [ping: ping: ] - // pipeline finished processing: [ping: PONG ping: PONG] -} diff --git a/vendor/github.com/go-redis/redis/example_test.go b/vendor/github.com/go-redis/redis/example_test.go deleted file mode 100644 index 4d18ddb94..000000000 --- a/vendor/github.com/go-redis/redis/example_test.go +++ /dev/null @@ -1,414 +0,0 @@ -package redis_test - -import ( - "fmt" - "strconv" - "sync" - "time" - - "github.com/go-redis/redis" -) - -var client *redis.Client - -func init() { - client = redis.NewClient(&redis.Options{ - Addr: ":6379", - DialTimeout: 10 * time.Second, - ReadTimeout: 30 * time.Second, - WriteTimeout: 30 * time.Second, - PoolSize: 10, - PoolTimeout: 30 * time.Second, - }) - client.FlushDB() -} - -func ExampleNewClient() { - client := redis.NewClient(&redis.Options{ - Addr: "localhost:6379", - Password: "", // no password set - DB: 0, // use default DB - }) - - pong, err := client.Ping().Result() - fmt.Println(pong, err) - // Output: PONG <nil> -} - -func ExampleParseURL() { - opt, err := redis.ParseURL("redis://:qwerty@localhost:6379/1") - if err != nil { - panic(err) - } - fmt.Println("addr is", opt.Addr) - fmt.Println("db is", opt.DB) - fmt.Println("password is", opt.Password) - - // Create client as usually. - _ = redis.NewClient(opt) - - // Output: addr is localhost:6379 - // db is 1 - // password is qwerty -} - -func ExampleNewFailoverClient() { - // See http://redis.io/topics/sentinel for instructions how to - // setup Redis Sentinel. - client := redis.NewFailoverClient(&redis.FailoverOptions{ - MasterName: "master", - SentinelAddrs: []string{":26379"}, - }) - client.Ping() -} - -func ExampleNewClusterClient() { - // See http://redis.io/topics/cluster-tutorial for instructions - // how to setup Redis Cluster. - client := redis.NewClusterClient(&redis.ClusterOptions{ - Addrs: []string{":7000", ":7001", ":7002", ":7003", ":7004", ":7005"}, - }) - client.Ping() -} - -func ExampleNewRing() { - client := redis.NewRing(&redis.RingOptions{ - Addrs: map[string]string{ - "shard1": ":7000", - "shard2": ":7001", - "shard3": ":7002", - }, - }) - client.Ping() -} - -func ExampleClient() { - err := client.Set("key", "value", 0).Err() - if err != nil { - panic(err) - } - - val, err := client.Get("key").Result() - if err != nil { - panic(err) - } - fmt.Println("key", val) - - val2, err := client.Get("key2").Result() - if err == redis.Nil { - fmt.Println("key2 does not exist") - } else if err != nil { - panic(err) - } else { - fmt.Println("key2", val2) - } - // Output: key value - // key2 does not exist -} - -func ExampleClient_Set() { - // Last argument is expiration. Zero means the key has no - // expiration time. - err := client.Set("key", "value", 0).Err() - if err != nil { - panic(err) - } - - // key2 will expire in an hour. - err = client.Set("key2", "value", time.Hour).Err() - if err != nil { - panic(err) - } -} - -func ExampleClient_Incr() { - result, err := client.Incr("counter").Result() - if err != nil { - panic(err) - } - - fmt.Println(result) - // Output: 1 -} - -func ExampleClient_BLPop() { - if err := client.RPush("queue", "message").Err(); err != nil { - panic(err) - } - - // use `client.BLPop(0, "queue")` for infinite waiting time - result, err := client.BLPop(1*time.Second, "queue").Result() - if err != nil { - panic(err) - } - - fmt.Println(result[0], result[1]) - // Output: queue message -} - -func ExampleClient_Scan() { - client.FlushDB() - for i := 0; i < 33; i++ { - err := client.Set(fmt.Sprintf("key%d", i), "value", 0).Err() - if err != nil { - panic(err) - } - } - - var cursor uint64 - var n int - for { - var keys []string - var err error - keys, cursor, err = client.Scan(cursor, "", 10).Result() - if err != nil { - panic(err) - } - n += len(keys) - if cursor == 0 { - break - } - } - - fmt.Printf("found %d keys\n", n) - // Output: found 33 keys -} - -func ExampleClient_Pipelined() { - var incr *redis.IntCmd - _, err := client.Pipelined(func(pipe redis.Pipeliner) error { - incr = pipe.Incr("pipelined_counter") - pipe.Expire("pipelined_counter", time.Hour) - return nil - }) - fmt.Println(incr.Val(), err) - // Output: 1 <nil> -} - -func ExampleClient_Pipeline() { - pipe := client.Pipeline() - - incr := pipe.Incr("pipeline_counter") - pipe.Expire("pipeline_counter", time.Hour) - - // Execute - // - // INCR pipeline_counter - // EXPIRE pipeline_counts 3600 - // - // using one client-server roundtrip. - _, err := pipe.Exec() - fmt.Println(incr.Val(), err) - // Output: 1 <nil> -} - -func ExampleClient_TxPipelined() { - var incr *redis.IntCmd - _, err := client.TxPipelined(func(pipe redis.Pipeliner) error { - incr = pipe.Incr("tx_pipelined_counter") - pipe.Expire("tx_pipelined_counter", time.Hour) - return nil - }) - fmt.Println(incr.Val(), err) - // Output: 1 <nil> -} - -func ExampleClient_TxPipeline() { - pipe := client.TxPipeline() - - incr := pipe.Incr("tx_pipeline_counter") - pipe.Expire("tx_pipeline_counter", time.Hour) - - // Execute - // - // MULTI - // INCR pipeline_counter - // EXPIRE pipeline_counts 3600 - // EXEC - // - // using one client-server roundtrip. - _, err := pipe.Exec() - fmt.Println(incr.Val(), err) - // Output: 1 <nil> -} - -func ExampleClient_Watch() { - var incr func(string) error - - // Transactionally increments key using GET and SET commands. - incr = func(key string) error { - err := client.Watch(func(tx *redis.Tx) error { - n, err := tx.Get(key).Int64() - if err != nil && err != redis.Nil { - return err - } - - _, err = tx.Pipelined(func(pipe redis.Pipeliner) error { - pipe.Set(key, strconv.FormatInt(n+1, 10), 0) - return nil - }) - return err - }, key) - if err == redis.TxFailedErr { - return incr(key) - } - return err - } - - var wg sync.WaitGroup - for i := 0; i < 100; i++ { - wg.Add(1) - go func() { - defer wg.Done() - - err := incr("counter3") - if err != nil { - panic(err) - } - }() - } - wg.Wait() - - n, err := client.Get("counter3").Int64() - fmt.Println(n, err) - // Output: 100 <nil> -} - -func ExamplePubSub() { - pubsub := client.Subscribe("mychannel1") - defer pubsub.Close() - - // Wait for subscription to be created before publishing message. - subscr, err := pubsub.ReceiveTimeout(time.Second) - if err != nil { - panic(err) - } - fmt.Println(subscr) - - err = client.Publish("mychannel1", "hello").Err() - if err != nil { - panic(err) - } - - msg, err := pubsub.ReceiveMessage() - if err != nil { - panic(err) - } - - fmt.Println(msg.Channel, msg.Payload) - // Output: subscribe: mychannel1 - // mychannel1 hello -} - -func ExamplePubSub_Receive() { - pubsub := client.Subscribe("mychannel2") - defer pubsub.Close() - - for i := 0; i < 2; i++ { - // ReceiveTimeout is a low level API. Use ReceiveMessage instead. - msgi, err := pubsub.ReceiveTimeout(time.Second) - if err != nil { - break - } - - switch msg := msgi.(type) { - case *redis.Subscription: - fmt.Println("subscribed to", msg.Channel) - - _, err := client.Publish("mychannel2", "hello").Result() - if err != nil { - panic(err) - } - case *redis.Message: - fmt.Println("received", msg.Payload, "from", msg.Channel) - default: - panic("unreached") - } - } - - // sent message to 1 client - // received hello from mychannel2 -} - -func ExampleScript() { - IncrByXX := redis.NewScript(` - if redis.call("GET", KEYS[1]) ~= false then - return redis.call("INCRBY", KEYS[1], ARGV[1]) - end - return false - `) - - n, err := IncrByXX.Run(client, []string{"xx_counter"}, 2).Result() - fmt.Println(n, err) - - err = client.Set("xx_counter", "40", 0).Err() - if err != nil { - panic(err) - } - - n, err = IncrByXX.Run(client, []string{"xx_counter"}, 2).Result() - fmt.Println(n, err) - - // Output: <nil> redis: nil - // 42 <nil> -} - -func Example_customCommand() { - Get := func(client *redis.Client, key string) *redis.StringCmd { - cmd := redis.NewStringCmd("get", key) - client.Process(cmd) - return cmd - } - - v, err := Get(client, "key_does_not_exist").Result() - fmt.Printf("%q %s", v, err) - // Output: "" redis: nil -} - -func ExampleScanIterator() { - iter := client.Scan(0, "", 0).Iterator() - for iter.Next() { - fmt.Println(iter.Val()) - } - if err := iter.Err(); err != nil { - panic(err) - } -} - -func ExampleScanCmd_Iterator() { - iter := client.Scan(0, "", 0).Iterator() - for iter.Next() { - fmt.Println(iter.Val()) - } - if err := iter.Err(); err != nil { - panic(err) - } -} - -func ExampleNewUniversalClient_simple() { - client := redis.NewUniversalClient(&redis.UniversalOptions{ - Addrs: []string{":6379"}, - }) - defer client.Close() - - client.Ping() -} - -func ExampleNewUniversalClient_failover() { - client := redis.NewUniversalClient(&redis.UniversalOptions{ - MasterName: "master", - Addrs: []string{":26379"}, - }) - defer client.Close() - - client.Ping() -} - -func ExampleNewUniversalClient_cluster() { - client := redis.NewUniversalClient(&redis.UniversalOptions{ - Addrs: []string{":7000", ":7001", ":7002", ":7003", ":7004", ":7005"}, - }) - defer client.Close() - - client.Ping() -} diff --git a/vendor/github.com/go-redis/redis/export_test.go b/vendor/github.com/go-redis/redis/export_test.go deleted file mode 100644 index bcc18c457..000000000 --- a/vendor/github.com/go-redis/redis/export_test.go +++ /dev/null @@ -1,46 +0,0 @@ -package redis - -import ( - "net" - "time" - - "github.com/go-redis/redis/internal/pool" -) - -func (c *baseClient) Pool() pool.Pooler { - return c.connPool -} - -func (c *PubSub) SetNetConn(netConn net.Conn) { - c.cn = pool.NewConn(netConn) -} - -func (c *PubSub) ReceiveMessageTimeout(timeout time.Duration) (*Message, error) { - return c.receiveMessage(timeout) -} - -func (c *ClusterClient) SlotAddrs(slot int) []string { - state, err := c.state() - if err != nil { - panic(err) - } - - var addrs []string - for _, n := range state.slotNodes(slot) { - addrs = append(addrs, n.Client.getAddr()) - } - return addrs -} - -// SwapSlot swaps a slot's master/slave address for testing MOVED redirects. -func (c *ClusterClient) SwapSlotNodes(slot int) { - state, err := c.state() - if err != nil { - panic(err) - } - - nodes := state.slots[slot] - if len(nodes) == 2 { - nodes[0], nodes[1] = nodes[1], nodes[0] - } -} diff --git a/vendor/github.com/go-redis/redis/internal/consistenthash/consistenthash_test.go b/vendor/github.com/go-redis/redis/internal/consistenthash/consistenthash_test.go deleted file mode 100644 index 1a37fd7ff..000000000 --- a/vendor/github.com/go-redis/redis/internal/consistenthash/consistenthash_test.go +++ /dev/null @@ -1,110 +0,0 @@ -/* -Copyright 2013 Google Inc. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package consistenthash - -import ( - "fmt" - "strconv" - "testing" -) - -func TestHashing(t *testing.T) { - - // Override the hash function to return easier to reason about values. Assumes - // the keys can be converted to an integer. - hash := New(3, func(key []byte) uint32 { - i, err := strconv.Atoi(string(key)) - if err != nil { - panic(err) - } - return uint32(i) - }) - - // Given the above hash function, this will give replicas with "hashes": - // 2, 4, 6, 12, 14, 16, 22, 24, 26 - hash.Add("6", "4", "2") - - testCases := map[string]string{ - "2": "2", - "11": "2", - "23": "4", - "27": "2", - } - - for k, v := range testCases { - if hash.Get(k) != v { - t.Errorf("Asking for %s, should have yielded %s", k, v) - } - } - - // Adds 8, 18, 28 - hash.Add("8") - - // 27 should now map to 8. - testCases["27"] = "8" - - for k, v := range testCases { - if hash.Get(k) != v { - t.Errorf("Asking for %s, should have yielded %s", k, v) - } - } - -} - -func TestConsistency(t *testing.T) { - hash1 := New(1, nil) - hash2 := New(1, nil) - - hash1.Add("Bill", "Bob", "Bonny") - hash2.Add("Bob", "Bonny", "Bill") - - if hash1.Get("Ben") != hash2.Get("Ben") { - t.Errorf("Fetching 'Ben' from both hashes should be the same") - } - - hash2.Add("Becky", "Ben", "Bobby") - - if hash1.Get("Ben") != hash2.Get("Ben") || - hash1.Get("Bob") != hash2.Get("Bob") || - hash1.Get("Bonny") != hash2.Get("Bonny") { - t.Errorf("Direct matches should always return the same entry") - } - -} - -func BenchmarkGet8(b *testing.B) { benchmarkGet(b, 8) } -func BenchmarkGet32(b *testing.B) { benchmarkGet(b, 32) } -func BenchmarkGet128(b *testing.B) { benchmarkGet(b, 128) } -func BenchmarkGet512(b *testing.B) { benchmarkGet(b, 512) } - -func benchmarkGet(b *testing.B, shards int) { - - hash := New(50, nil) - - var buckets []string - for i := 0; i < shards; i++ { - buckets = append(buckets, fmt.Sprintf("shard-%d", i)) - } - - hash.Add(buckets...) - - b.ResetTimer() - - for i := 0; i < b.N; i++ { - hash.Get(buckets[i&(shards-1)]) - } -} diff --git a/vendor/github.com/go-redis/redis/internal/error.go b/vendor/github.com/go-redis/redis/internal/error.go index 0898eeb62..7b419577e 100644 --- a/vendor/github.com/go-redis/redis/internal/error.go +++ b/vendor/github.com/go-redis/redis/internal/error.go @@ -4,13 +4,9 @@ import ( "io" "net" "strings" -) - -const Nil = RedisError("redis: nil") - -type RedisError string -func (e RedisError) Error() string { return string(e) } + "github.com/go-redis/redis/internal/proto" +) func IsRetryableError(err error, retryNetError bool) bool { if IsNetworkError(err) { @@ -30,7 +26,7 @@ func IsRetryableError(err error, retryNetError bool) bool { } func IsRedisError(err error) bool { - _, ok := err.(RedisError) + _, ok := err.(proto.RedisError) return ok } @@ -42,6 +38,10 @@ func IsNetworkError(err error) bool { return ok } +func IsReadOnlyError(err error) bool { + return strings.HasPrefix(err.Error(), "READONLY ") +} + func IsBadConn(err error, allowTimeout bool) bool { if err == nil { return false diff --git a/vendor/github.com/go-redis/redis/internal/hashtag/hashtag_test.go b/vendor/github.com/go-redis/redis/internal/hashtag/hashtag_test.go deleted file mode 100644 index 7f0fedf31..000000000 --- a/vendor/github.com/go-redis/redis/internal/hashtag/hashtag_test.go +++ /dev/null @@ -1,74 +0,0 @@ -package hashtag - -import ( - "math/rand" - "testing" - - . "github.com/onsi/ginkgo" - . "github.com/onsi/gomega" -) - -func TestGinkgoSuite(t *testing.T) { - RegisterFailHandler(Fail) - RunSpecs(t, "hashtag") -} - -var _ = Describe("CRC16", func() { - - // http://redis.io/topics/cluster-spec#keys-distribution-model - It("should calculate CRC16", func() { - tests := []struct { - s string - n uint16 - }{ - {"123456789", 0x31C3}, - {string([]byte{83, 153, 134, 118, 229, 214, 244, 75, 140, 37, 215, 215}), 21847}, - } - - for _, test := range tests { - Expect(crc16sum(test.s)).To(Equal(test.n), "for %s", test.s) - } - }) - -}) - -var _ = Describe("HashSlot", func() { - - It("should calculate hash slots", func() { - tests := []struct { - key string - slot int - }{ - {"123456789", 12739}, - {"{}foo", 9500}, - {"foo{}", 5542}, - {"foo{}{bar}", 8363}, - {"", 10503}, - {"", 5176}, - {string([]byte{83, 153, 134, 118, 229, 214, 244, 75, 140, 37, 215, 215}), 5463}, - } - // Empty keys receive random slot. - rand.Seed(100) - - for _, test := range tests { - Expect(Slot(test.key)).To(Equal(test.slot), "for %s", test.key) - } - }) - - It("should extract keys from tags", func() { - tests := []struct { - one, two string - }{ - {"foo{bar}", "bar"}, - {"{foo}bar", "foo"}, - {"{user1000}.following", "{user1000}.followers"}, - {"foo{{bar}}zap", "{bar"}, - {"foo{bar}{zap}", "bar"}, - } - - for _, test := range tests { - Expect(Slot(test.one)).To(Equal(Slot(test.two)), "for %s <-> %s", test.one, test.two) - } - }) - -}) diff --git a/vendor/github.com/go-redis/redis/internal/internal_test.go b/vendor/github.com/go-redis/redis/internal/internal_test.go deleted file mode 100644 index 56ff611e1..000000000 --- a/vendor/github.com/go-redis/redis/internal/internal_test.go +++ /dev/null @@ -1,18 +0,0 @@ -package internal - -import ( - "testing" - "time" - - . "github.com/onsi/gomega" -) - -func TestRetryBackoff(t *testing.T) { - RegisterTestingT(t) - - for i := -1; i <= 16; i++ { - backoff := RetryBackoff(i, time.Millisecond, 512*time.Millisecond) - Expect(backoff >= 0).To(BeTrue()) - Expect(backoff <= 512*time.Millisecond).To(BeTrue()) - } -} diff --git a/vendor/github.com/go-redis/redis/internal/pool/bench_test.go b/vendor/github.com/go-redis/redis/internal/pool/bench_test.go deleted file mode 100644 index e0bb52446..000000000 --- a/vendor/github.com/go-redis/redis/internal/pool/bench_test.go +++ /dev/null @@ -1,80 +0,0 @@ -package pool_test - -import ( - "testing" - "time" - - "github.com/go-redis/redis/internal/pool" -) - -func benchmarkPoolGetPut(b *testing.B, poolSize int) { - connPool := pool.NewConnPool(&pool.Options{ - Dialer: dummyDialer, - PoolSize: poolSize, - PoolTimeout: time.Second, - IdleTimeout: time.Hour, - IdleCheckFrequency: time.Hour, - }) - - b.ResetTimer() - - b.RunParallel(func(pb *testing.PB) { - for pb.Next() { - cn, _, err := connPool.Get() - if err != nil { - b.Fatal(err) - } - if err = connPool.Put(cn); err != nil { - b.Fatal(err) - } - } - }) -} - -func BenchmarkPoolGetPut10Conns(b *testing.B) { - benchmarkPoolGetPut(b, 10) -} - -func BenchmarkPoolGetPut100Conns(b *testing.B) { - benchmarkPoolGetPut(b, 100) -} - -func BenchmarkPoolGetPut1000Conns(b *testing.B) { - benchmarkPoolGetPut(b, 1000) -} - -func benchmarkPoolGetRemove(b *testing.B, poolSize int) { - connPool := pool.NewConnPool(&pool.Options{ - Dialer: dummyDialer, - PoolSize: poolSize, - PoolTimeout: time.Second, - IdleTimeout: time.Hour, - IdleCheckFrequency: time.Hour, - }) - - b.ResetTimer() - - b.RunParallel(func(pb *testing.PB) { - for pb.Next() { - cn, _, err := connPool.Get() - if err != nil { - b.Fatal(err) - } - if err := connPool.Remove(cn); err != nil { - b.Fatal(err) - } - } - }) -} - -func BenchmarkPoolGetRemove10Conns(b *testing.B) { - benchmarkPoolGetRemove(b, 10) -} - -func BenchmarkPoolGetRemove100Conns(b *testing.B) { - benchmarkPoolGetRemove(b, 100) -} - -func BenchmarkPoolGetRemove1000Conns(b *testing.B) { - benchmarkPoolGetRemove(b, 1000) -} diff --git a/vendor/github.com/go-redis/redis/internal/pool/main_test.go b/vendor/github.com/go-redis/redis/internal/pool/main_test.go deleted file mode 100644 index 43afe3fa9..000000000 --- a/vendor/github.com/go-redis/redis/internal/pool/main_test.go +++ /dev/null @@ -1,35 +0,0 @@ -package pool_test - -import ( - "net" - "sync" - "testing" - - . "github.com/onsi/ginkgo" - . "github.com/onsi/gomega" -) - -func TestGinkgoSuite(t *testing.T) { - RegisterFailHandler(Fail) - RunSpecs(t, "pool") -} - -func perform(n int, cbs ...func(int)) { - var wg sync.WaitGroup - for _, cb := range cbs { - for i := 0; i < n; i++ { - wg.Add(1) - go func(cb func(int), i int) { - defer GinkgoRecover() - defer wg.Done() - - cb(i) - }(cb, i) - } - } - wg.Wait() -} - -func dummyDialer() (net.Conn, error) { - return &net.TCPConn{}, nil -} diff --git a/vendor/github.com/go-redis/redis/internal/pool/pool_test.go b/vendor/github.com/go-redis/redis/internal/pool/pool_test.go deleted file mode 100644 index 68c9a1bef..000000000 --- a/vendor/github.com/go-redis/redis/internal/pool/pool_test.go +++ /dev/null @@ -1,241 +0,0 @@ -package pool_test - -import ( - "testing" - "time" - - "github.com/go-redis/redis/internal/pool" - - . "github.com/onsi/ginkgo" - . "github.com/onsi/gomega" -) - -var _ = Describe("ConnPool", func() { - var connPool *pool.ConnPool - - BeforeEach(func() { - connPool = pool.NewConnPool(&pool.Options{ - Dialer: dummyDialer, - PoolSize: 10, - PoolTimeout: time.Hour, - IdleTimeout: time.Millisecond, - IdleCheckFrequency: time.Millisecond, - }) - }) - - AfterEach(func() { - connPool.Close() - }) - - It("should unblock client when conn is removed", func() { - // Reserve one connection. - cn, _, err := connPool.Get() - Expect(err).NotTo(HaveOccurred()) - - // Reserve all other connections. - var cns []*pool.Conn - for i := 0; i < 9; i++ { - cn, _, err := connPool.Get() - Expect(err).NotTo(HaveOccurred()) - cns = append(cns, cn) - } - - started := make(chan bool, 1) - done := make(chan bool, 1) - go func() { - defer GinkgoRecover() - - started <- true - _, _, err := connPool.Get() - Expect(err).NotTo(HaveOccurred()) - done <- true - - err = connPool.Put(cn) - Expect(err).NotTo(HaveOccurred()) - }() - <-started - - // Check that Get is blocked. - select { - case <-done: - Fail("Get is not blocked") - default: - // ok - } - - err = connPool.Remove(cn) - Expect(err).NotTo(HaveOccurred()) - - // Check that Ping is unblocked. - select { - case <-done: - // ok - case <-time.After(time.Second): - Fail("Get is not unblocked") - } - - for _, cn := range cns { - err = connPool.Put(cn) - Expect(err).NotTo(HaveOccurred()) - } - }) -}) - -var _ = Describe("conns reaper", func() { - const idleTimeout = time.Minute - - var connPool *pool.ConnPool - var conns, idleConns, closedConns []*pool.Conn - - BeforeEach(func() { - conns = nil - closedConns = nil - - connPool = pool.NewConnPool(&pool.Options{ - Dialer: dummyDialer, - PoolSize: 10, - PoolTimeout: time.Second, - IdleTimeout: idleTimeout, - IdleCheckFrequency: time.Hour, - - OnClose: func(cn *pool.Conn) error { - closedConns = append(closedConns, cn) - return nil - }, - }) - - // add stale connections - idleConns = nil - for i := 0; i < 3; i++ { - cn, _, err := connPool.Get() - Expect(err).NotTo(HaveOccurred()) - cn.SetUsedAt(time.Now().Add(-2 * idleTimeout)) - conns = append(conns, cn) - idleConns = append(idleConns, cn) - } - - // add fresh connections - for i := 0; i < 3; i++ { - cn, _, err := connPool.Get() - Expect(err).NotTo(HaveOccurred()) - conns = append(conns, cn) - } - - for _, cn := range conns { - Expect(connPool.Put(cn)).NotTo(HaveOccurred()) - } - - Expect(connPool.Len()).To(Equal(6)) - Expect(connPool.FreeLen()).To(Equal(6)) - - n, err := connPool.ReapStaleConns() - Expect(err).NotTo(HaveOccurred()) - Expect(n).To(Equal(3)) - }) - - AfterEach(func() { - _ = connPool.Close() - Expect(connPool.Len()).To(Equal(0)) - Expect(connPool.FreeLen()).To(Equal(0)) - Expect(len(closedConns)).To(Equal(len(conns))) - Expect(closedConns).To(ConsistOf(conns)) - }) - - It("reaps stale connections", func() { - Expect(connPool.Len()).To(Equal(3)) - Expect(connPool.FreeLen()).To(Equal(3)) - }) - - It("does not reap fresh connections", func() { - n, err := connPool.ReapStaleConns() - Expect(err).NotTo(HaveOccurred()) - Expect(n).To(Equal(0)) - }) - - It("stale connections are closed", func() { - Expect(len(closedConns)).To(Equal(len(idleConns))) - Expect(closedConns).To(ConsistOf(idleConns)) - }) - - It("pool is functional", func() { - for j := 0; j < 3; j++ { - var freeCns []*pool.Conn - for i := 0; i < 3; i++ { - cn, _, err := connPool.Get() - Expect(err).NotTo(HaveOccurred()) - Expect(cn).NotTo(BeNil()) - freeCns = append(freeCns, cn) - } - - Expect(connPool.Len()).To(Equal(3)) - Expect(connPool.FreeLen()).To(Equal(0)) - - cn, _, err := connPool.Get() - Expect(err).NotTo(HaveOccurred()) - Expect(cn).NotTo(BeNil()) - conns = append(conns, cn) - - Expect(connPool.Len()).To(Equal(4)) - Expect(connPool.FreeLen()).To(Equal(0)) - - err = connPool.Remove(cn) - Expect(err).NotTo(HaveOccurred()) - - Expect(connPool.Len()).To(Equal(3)) - Expect(connPool.FreeLen()).To(Equal(0)) - - for _, cn := range freeCns { - err := connPool.Put(cn) - Expect(err).NotTo(HaveOccurred()) - } - - Expect(connPool.Len()).To(Equal(3)) - Expect(connPool.FreeLen()).To(Equal(3)) - } - }) -}) - -var _ = Describe("race", func() { - var connPool *pool.ConnPool - var C, N int - - BeforeEach(func() { - C, N = 10, 1000 - if testing.Short() { - C = 4 - N = 100 - } - }) - - AfterEach(func() { - connPool.Close() - }) - - It("does not happen on Get, Put, and Remove", func() { - connPool = pool.NewConnPool(&pool.Options{ - Dialer: dummyDialer, - PoolSize: 10, - PoolTimeout: time.Minute, - IdleTimeout: time.Millisecond, - IdleCheckFrequency: time.Millisecond, - }) - - perform(C, func(id int) { - for i := 0; i < N; i++ { - cn, _, err := connPool.Get() - Expect(err).NotTo(HaveOccurred()) - if err == nil { - Expect(connPool.Put(cn)).NotTo(HaveOccurred()) - } - } - }, func(id int) { - for i := 0; i < N; i++ { - cn, _, err := connPool.Get() - Expect(err).NotTo(HaveOccurred()) - if err == nil { - Expect(connPool.Remove(cn)).NotTo(HaveOccurred()) - } - } - }) - }) -}) diff --git a/vendor/github.com/go-redis/redis/internal/proto/proto_test.go b/vendor/github.com/go-redis/redis/internal/proto/proto_test.go deleted file mode 100644 index c9a820eb1..000000000 --- a/vendor/github.com/go-redis/redis/internal/proto/proto_test.go +++ /dev/null @@ -1,13 +0,0 @@ -package proto_test - -import ( - "testing" - - . "github.com/onsi/ginkgo" - . "github.com/onsi/gomega" -) - -func TestGinkgoSuite(t *testing.T) { - RegisterFailHandler(Fail) - RunSpecs(t, "proto") -} diff --git a/vendor/github.com/go-redis/redis/internal/proto/reader.go b/vendor/github.com/go-redis/redis/internal/proto/reader.go index e5ae8a03e..d5d695358 100644 --- a/vendor/github.com/go-redis/redis/internal/proto/reader.go +++ b/vendor/github.com/go-redis/redis/internal/proto/reader.go @@ -6,7 +6,7 @@ import ( "io" "strconv" - "github.com/go-redis/redis/internal" + "github.com/go-redis/redis/internal/util" ) const bytesAllocLimit = 1024 * 1024 // 1mb @@ -19,6 +19,16 @@ const ( ArrayReply = '*' ) +//------------------------------------------------------------------------------ + +const Nil = RedisError("redis: nil") + +type RedisError string + +func (e RedisError) Error() string { return string(e) } + +//------------------------------------------------------------------------------ + type MultiBulkParse func(*Reader, int64) (interface{}, error) type Reader struct { @@ -66,7 +76,7 @@ func (r *Reader) ReadLine() ([]byte, error) { return nil, fmt.Errorf("redis: reply is empty") } if isNilReply(line) { - return nil, internal.Nil + return nil, Nil } return line, nil } @@ -83,7 +93,7 @@ func (r *Reader) ReadReply(m MultiBulkParse) (interface{}, error) { case StatusReply: return parseStatusValue(line), nil case IntReply: - return parseInt(line[1:], 10, 64) + return util.ParseInt(line[1:], 10, 64) case StringReply: return r.readTmpBytesValue(line) case ArrayReply: @@ -105,7 +115,7 @@ func (r *Reader) ReadIntReply() (int64, error) { case ErrorReply: return 0, ParseErrorReply(line) case IntReply: - return parseInt(line[1:], 10, 64) + return util.ParseInt(line[1:], 10, 64) default: return 0, fmt.Errorf("redis: can't parse int reply: %.100q", line) } @@ -151,7 +161,7 @@ func (r *Reader) ReadFloatReply() (float64, error) { if err != nil { return 0, err } - return parseFloat(b, 64) + return util.ParseFloat(b, 64) } func (r *Reader) ReadArrayReply(m MultiBulkParse) (interface{}, error) { @@ -221,7 +231,7 @@ func (r *Reader) ReadScanReply() ([]string, uint64, error) { func (r *Reader) readTmpBytesValue(line []byte) ([]byte, error) { if isNilReply(line) { - return nil, internal.Nil + return nil, Nil } replyLen, err := strconv.Atoi(string(line[1:])) @@ -241,7 +251,7 @@ func (r *Reader) ReadInt() (int64, error) { if err != nil { return 0, err } - return parseInt(b, 10, 64) + return util.ParseInt(b, 10, 64) } func (r *Reader) ReadUint() (uint64, error) { @@ -249,7 +259,7 @@ func (r *Reader) ReadUint() (uint64, error) { if err != nil { return 0, err } - return parseUint(b, 10, 64) + return util.ParseUint(b, 10, 64) } // -------------------------------------------------------------------- @@ -303,7 +313,7 @@ func isNilReply(b []byte) bool { } func ParseErrorReply(line []byte) error { - return internal.RedisError(string(line[1:])) + return RedisError(string(line[1:])) } func parseStatusValue(line []byte) []byte { @@ -312,23 +322,7 @@ func parseStatusValue(line []byte) []byte { func parseArrayLen(line []byte) (int64, error) { if isNilReply(line) { - return 0, internal.Nil + return 0, Nil } - return parseInt(line[1:], 10, 64) -} - -func atoi(b []byte) (int, error) { - return strconv.Atoi(internal.BytesToString(b)) -} - -func parseInt(b []byte, base int, bitSize int) (int64, error) { - return strconv.ParseInt(internal.BytesToString(b), base, bitSize) -} - -func parseUint(b []byte, base int, bitSize int) (uint64, error) { - return strconv.ParseUint(internal.BytesToString(b), base, bitSize) -} - -func parseFloat(b []byte, bitSize int) (float64, error) { - return strconv.ParseFloat(internal.BytesToString(b), bitSize) + return util.ParseInt(line[1:], 10, 64) } diff --git a/vendor/github.com/go-redis/redis/internal/proto/reader_test.go b/vendor/github.com/go-redis/redis/internal/proto/reader_test.go deleted file mode 100644 index 8d2d71be9..000000000 --- a/vendor/github.com/go-redis/redis/internal/proto/reader_test.go +++ /dev/null @@ -1,87 +0,0 @@ -package proto_test - -import ( - "bytes" - "strings" - "testing" - - "github.com/go-redis/redis/internal/proto" - - . "github.com/onsi/ginkgo" - . "github.com/onsi/gomega" -) - -var _ = Describe("Reader", func() { - - It("should read n bytes", func() { - data, err := proto.NewReader(strings.NewReader("ABCDEFGHIJKLMNO")).ReadN(10) - Expect(err).NotTo(HaveOccurred()) - Expect(len(data)).To(Equal(10)) - Expect(string(data)).To(Equal("ABCDEFGHIJ")) - - data, err = proto.NewReader(strings.NewReader(strings.Repeat("x", 8192))).ReadN(6000) - Expect(err).NotTo(HaveOccurred()) - Expect(len(data)).To(Equal(6000)) - }) - - It("should read lines", func() { - p := proto.NewReader(strings.NewReader("$5\r\nhello\r\n")) - - data, err := p.ReadLine() - Expect(err).NotTo(HaveOccurred()) - Expect(string(data)).To(Equal("$5")) - - data, err = p.ReadLine() - Expect(err).NotTo(HaveOccurred()) - Expect(string(data)).To(Equal("hello")) - }) - -}) - -func BenchmarkReader_ParseReply_Status(b *testing.B) { - benchmarkParseReply(b, "+OK\r\n", nil, false) -} - -func BenchmarkReader_ParseReply_Int(b *testing.B) { - benchmarkParseReply(b, ":1\r\n", nil, false) -} - -func BenchmarkReader_ParseReply_Error(b *testing.B) { - benchmarkParseReply(b, "-Error message\r\n", nil, true) -} - -func BenchmarkReader_ParseReply_String(b *testing.B) { - benchmarkParseReply(b, "$5\r\nhello\r\n", nil, false) -} - -func BenchmarkReader_ParseReply_Slice(b *testing.B) { - benchmarkParseReply(b, "*2\r\n$5\r\nhello\r\n$5\r\nworld\r\n", multiBulkParse, false) -} - -func benchmarkParseReply(b *testing.B, reply string, m proto.MultiBulkParse, wanterr bool) { - buf := new(bytes.Buffer) - for i := 0; i < b.N; i++ { - buf.WriteString(reply) - } - p := proto.NewReader(buf) - b.ResetTimer() - - for i := 0; i < b.N; i++ { - _, err := p.ReadReply(m) - if !wanterr && err != nil { - b.Fatal(err) - } - } -} - -func multiBulkParse(p *proto.Reader, n int64) (interface{}, error) { - vv := make([]interface{}, 0, n) - for i := int64(0); i < n; i++ { - v, err := p.ReadReply(multiBulkParse) - if err != nil { - return nil, err - } - vv = append(vv, v) - } - return vv, nil -} diff --git a/vendor/github.com/go-redis/redis/internal/proto/scan.go b/vendor/github.com/go-redis/redis/internal/proto/scan.go index 0329ffd99..3bdb33f9d 100644 --- a/vendor/github.com/go-redis/redis/internal/proto/scan.go +++ b/vendor/github.com/go-redis/redis/internal/proto/scan.go @@ -5,7 +5,7 @@ import ( "fmt" "reflect" - "github.com/go-redis/redis/internal" + "github.com/go-redis/redis/internal/util" ) func Scan(b []byte, v interface{}) error { @@ -13,80 +13,80 @@ func Scan(b []byte, v interface{}) error { case nil: return fmt.Errorf("redis: Scan(nil)") case *string: - *v = internal.BytesToString(b) + *v = util.BytesToString(b) return nil case *[]byte: *v = b return nil case *int: var err error - *v, err = atoi(b) + *v, err = util.Atoi(b) return err case *int8: - n, err := parseInt(b, 10, 8) + n, err := util.ParseInt(b, 10, 8) if err != nil { return err } *v = int8(n) return nil case *int16: - n, err := parseInt(b, 10, 16) + n, err := util.ParseInt(b, 10, 16) if err != nil { return err } *v = int16(n) return nil case *int32: - n, err := parseInt(b, 10, 32) + n, err := util.ParseInt(b, 10, 32) if err != nil { return err } *v = int32(n) return nil case *int64: - n, err := parseInt(b, 10, 64) + n, err := util.ParseInt(b, 10, 64) if err != nil { return err } *v = n return nil case *uint: - n, err := parseUint(b, 10, 64) + n, err := util.ParseUint(b, 10, 64) if err != nil { return err } *v = uint(n) return nil case *uint8: - n, err := parseUint(b, 10, 8) + n, err := util.ParseUint(b, 10, 8) if err != nil { return err } *v = uint8(n) return nil case *uint16: - n, err := parseUint(b, 10, 16) + n, err := util.ParseUint(b, 10, 16) if err != nil { return err } *v = uint16(n) return nil case *uint32: - n, err := parseUint(b, 10, 32) + n, err := util.ParseUint(b, 10, 32) if err != nil { return err } *v = uint32(n) return nil case *uint64: - n, err := parseUint(b, 10, 64) + n, err := util.ParseUint(b, 10, 64) if err != nil { return err } *v = n return nil case *float32: - n, err := parseFloat(b, 32) + n, err := util.ParseFloat(b, 32) if err != nil { return err } @@ -94,7 +94,7 @@ func Scan(b []byte, v interface{}) error { return err case *float64: var err error - *v, err = parseFloat(b, 64) + *v, err = util.ParseFloat(b, 64) return err case *bool: *v = len(b) == 1 && b[0] == '1' @@ -120,7 +120,7 @@ func ScanSlice(data []string, slice interface{}) error { return fmt.Errorf("redis: ScanSlice(non-slice %T)", slice) } - next := internal.MakeSliceNextElemFunc(v) + next := makeSliceNextElemFunc(v) for i, s := range data { elem := next() if err := Scan([]byte(s), elem.Addr().Interface()); err != nil { @@ -131,3 +131,36 @@ func ScanSlice(data []string, slice interface{}) error { return nil } + +func makeSliceNextElemFunc(v reflect.Value) func() reflect.Value { + elemType := v.Type().Elem() + + if elemType.Kind() == reflect.Ptr { + elemType = elemType.Elem() + return func() reflect.Value { + if v.Len() < v.Cap() { + v.Set(v.Slice(0, v.Len()+1)) + elem := v.Index(v.Len() - 1) + if elem.IsNil() { + elem.Set(reflect.New(elemType)) + } + return elem.Elem() + } + + elem := reflect.New(elemType) + v.Set(reflect.Append(v, elem)) + return elem.Elem() + } + } + + zero := reflect.Zero(elemType) + return func() reflect.Value { + if v.Len() < v.Cap() { + v.Set(v.Slice(0, v.Len()+1)) + return v.Index(v.Len() - 1) + } + + v.Set(reflect.Append(v, zero)) + return v.Index(v.Len() - 1) + } +} diff --git a/vendor/github.com/go-redis/redis/internal/proto/scan_test.go b/vendor/github.com/go-redis/redis/internal/proto/scan_test.go deleted file mode 100644 index fadcd0561..000000000 --- a/vendor/github.com/go-redis/redis/internal/proto/scan_test.go +++ /dev/null @@ -1,48 +0,0 @@ -package proto - -import ( - "encoding/json" - - . "github.com/onsi/ginkgo" - . "github.com/onsi/gomega" -) - -type testScanSliceStruct struct { - ID int - Name string -} - -func (s *testScanSliceStruct) MarshalBinary() ([]byte, error) { - return json.Marshal(s) -} - -func (s *testScanSliceStruct) UnmarshalBinary(b []byte) error { - return json.Unmarshal(b, s) -} - -var _ = Describe("ScanSlice", func() { - data := []string{ - `{"ID":-1,"Name":"Back Yu"}`, - `{"ID":1,"Name":"szyhf"}`, - } - - It("[]testScanSliceStruct", func() { - var slice []testScanSliceStruct - err := ScanSlice(data, &slice) - Expect(err).NotTo(HaveOccurred()) - Expect(slice).To(Equal([]testScanSliceStruct{ - {-1, "Back Yu"}, - {1, "szyhf"}, - })) - }) - - It("var testContainer []*testScanSliceStruct", func() { - var slice []*testScanSliceStruct - err := ScanSlice(data, &slice) - Expect(err).NotTo(HaveOccurred()) - Expect(slice).To(Equal([]*testScanSliceStruct{ - {-1, "Back Yu"}, - {1, "szyhf"}, - })) - }) -}) diff --git a/vendor/github.com/go-redis/redis/internal/proto/write_buffer.go b/vendor/github.com/go-redis/redis/internal/proto/write_buffer.go index 096b6d76a..cc4014fb4 100644 --- a/vendor/github.com/go-redis/redis/internal/proto/write_buffer.go +++ b/vendor/github.com/go-redis/redis/internal/proto/write_buffer.go @@ -71,17 +71,15 @@ func (w *WriteBuffer) append(val interface{}) error { } else { w.AppendString("0") } - default: - if bm, ok := val.(encoding.BinaryMarshaler); ok { - bb, err := bm.MarshalBinary() - if err != nil { - return err - } - w.AppendBytes(bb) - } else { - return fmt.Errorf( - "redis: can't marshal %T (consider implementing encoding.BinaryMarshaler)", val) + case encoding.BinaryMarshaler: + b, err := v.MarshalBinary() + if err != nil { + return err } + w.AppendBytes(b) + default: + return fmt.Errorf( + "redis: can't marshal %T (consider implementing encoding.BinaryMarshaler)", val) } return nil } diff --git a/vendor/github.com/go-redis/redis/internal/proto/write_buffer_test.go b/vendor/github.com/go-redis/redis/internal/proto/write_buffer_test.go deleted file mode 100644 index 84799ff3b..000000000 --- a/vendor/github.com/go-redis/redis/internal/proto/write_buffer_test.go +++ /dev/null @@ -1,63 +0,0 @@ -package proto_test - -import ( - "testing" - "time" - - "github.com/go-redis/redis/internal/proto" - - . "github.com/onsi/ginkgo" - . "github.com/onsi/gomega" -) - -var _ = Describe("WriteBuffer", func() { - var buf *proto.WriteBuffer - - BeforeEach(func() { - buf = proto.NewWriteBuffer() - }) - - It("should reset", func() { - buf.AppendString("string") - Expect(buf.Len()).To(Equal(12)) - buf.Reset() - Expect(buf.Len()).To(Equal(0)) - }) - - It("should append args", func() { - err := buf.Append([]interface{}{ - "string", - 12, - 34.56, - []byte{'b', 'y', 't', 'e', 's'}, - true, - nil, - }) - Expect(err).NotTo(HaveOccurred()) - Expect(buf.Bytes()).To(Equal([]byte("*6\r\n" + - "$6\r\nstring\r\n" + - "$2\r\n12\r\n" + - "$5\r\n34.56\r\n" + - "$5\r\nbytes\r\n" + - "$1\r\n1\r\n" + - "$0\r\n" + - "\r\n"))) - }) - - It("should append marshalable args", func() { - err := buf.Append([]interface{}{time.Unix(1414141414, 0)}) - Expect(err).NotTo(HaveOccurred()) - Expect(buf.Len()).To(Equal(26)) - }) - -}) - -func BenchmarkWriteBuffer_Append(b *testing.B) { - buf := proto.NewWriteBuffer() - args := []interface{}{"hello", "world", "foo", "bar"} - - for i := 0; i < b.N; i++ { - buf.Append(args) - buf.Reset() - } -} diff --git a/vendor/github.com/go-redis/redis/internal/singleflight/singleflight.go b/vendor/github.com/go-redis/redis/internal/singleflight/singleflight.go new file mode 100644 index 000000000..3b1741724 --- /dev/null +++ b/vendor/github.com/go-redis/redis/internal/singleflight/singleflight.go @@ -0,0 +1,64 @@ +/* +Copyright 2013 Google Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Package singleflight provides a duplicate function call suppression +// mechanism. +package singleflight + +import "sync" + +// call is an in-flight or completed Do call +type call struct { + wg sync.WaitGroup + val interface{} + err error +} + +// Group represents a class of work and forms a namespace in which +// units of work can be executed with duplicate suppression. +type Group struct { + mu sync.Mutex // protects m + m map[string]*call // lazily initialized +} + +// Do executes and returns the results of the given function, making +// sure that only one execution is in-flight for a given key at a +// time. If a duplicate comes in, the duplicate caller waits for the +// original to complete and receives the same results. +func (g *Group) Do(key string, fn func() (interface{}, error)) (interface{}, error) { + g.mu.Lock() + if g.m == nil { + g.m = make(map[string]*call) + } + if c, ok := g.m[key]; ok { + g.mu.Unlock() + c.wg.Wait() + return c.val, c.err + } + c := new(call) + c.wg.Add(1) + g.m[key] = c + g.mu.Unlock() + + c.val, c.err = fn() + c.wg.Done() + + g.mu.Lock() + delete(g.m, key) + g.mu.Unlock() + + return c.val, c.err +} diff --git a/vendor/github.com/go-redis/redis/internal/util.go b/vendor/github.com/go-redis/redis/internal/util.go index 1ba9805fe..ffd2353e0 100644 --- a/vendor/github.com/go-redis/redis/internal/util.go +++ b/vendor/github.com/go-redis/redis/internal/util.go @@ -1,6 +1,6 @@ package internal -import "reflect" +import "github.com/go-redis/redis/internal/util" func ToLower(s string) string { if isLower(s) { @@ -15,7 +15,7 @@ func ToLower(s string) string { } b[i] = c } - return BytesToString(b) + return util.BytesToString(b) } func isLower(s string) bool { @@ -27,36 +27,3 @@ func isLower(s string) bool { } return true } - -func MakeSliceNextElemFunc(v reflect.Value) func() reflect.Value { - elemType := v.Type().Elem() - - if elemType.Kind() == reflect.Ptr { - elemType = elemType.Elem() - return func() reflect.Value { - if v.Len() < v.Cap() { - v.Set(v.Slice(0, v.Len()+1)) - elem := v.Index(v.Len() - 1) - if elem.IsNil() { - elem.Set(reflect.New(elemType)) - } - return elem.Elem() - } - - elem := reflect.New(elemType) - v.Set(reflect.Append(v, elem)) - return elem.Elem() - } - } - - zero := reflect.Zero(elemType) - return func() reflect.Value { - if v.Len() < v.Cap() { - v.Set(v.Slice(0, v.Len()+1)) - return v.Index(v.Len() - 1) - } - - v.Set(reflect.Append(v, zero)) - return v.Index(v.Len() - 1) - } -} diff --git a/vendor/github.com/go-redis/redis/internal/safe.go b/vendor/github.com/go-redis/redis/internal/util/safe.go index dc5f4cc8a..cd8918330 100644 --- a/vendor/github.com/go-redis/redis/internal/safe.go +++ b/vendor/github.com/go-redis/redis/internal/util/safe.go @@ -1,6 +1,6 @@ // +build appengine -package internal +package util func BytesToString(b []byte) string { return string(b) diff --git a/vendor/github.com/go-redis/redis/internal/util/strconv.go b/vendor/github.com/go-redis/redis/internal/util/strconv.go new file mode 100644 index 000000000..db5033802 --- /dev/null +++ b/vendor/github.com/go-redis/redis/internal/util/strconv.go @@ -0,0 +1,19 @@ +package util + +import "strconv" + +func Atoi(b []byte) (int, error) { + return strconv.Atoi(BytesToString(b)) +} + +func ParseInt(b []byte, base int, bitSize int) (int64, error) { + return strconv.ParseInt(BytesToString(b), base, bitSize) +} + +func ParseUint(b []byte, base int, bitSize int) (uint64, error) { + return strconv.ParseUint(BytesToString(b), base, bitSize) +} + +func ParseFloat(b []byte, bitSize int) (float64, error) { + return strconv.ParseFloat(BytesToString(b), bitSize) +} diff --git a/vendor/github.com/go-redis/redis/internal/unsafe.go b/vendor/github.com/go-redis/redis/internal/util/unsafe.go index 3ae48c14b..93a89c55c 100644 --- a/vendor/github.com/go-redis/redis/internal/unsafe.go +++ b/vendor/github.com/go-redis/redis/internal/util/unsafe.go @@ -1,6 +1,6 @@ // +build !appengine -package internal +package util import ( "unsafe" diff --git a/vendor/github.com/go-redis/redis/iterator_test.go b/vendor/github.com/go-redis/redis/iterator_test.go deleted file mode 100644 index a2e623813..000000000 --- a/vendor/github.com/go-redis/redis/iterator_test.go +++ /dev/null @@ -1,136 +0,0 @@ -package redis_test - -import ( - "fmt" - - "github.com/go-redis/redis" - - . "github.com/onsi/ginkgo" - . "github.com/onsi/gomega" -) - -var _ = Describe("ScanIterator", func() { - var client *redis.Client - - var seed = func(n int) error { - pipe := client.Pipeline() - for i := 1; i <= n; i++ { - pipe.Set(fmt.Sprintf("K%02d", i), "x", 0).Err() - } - _, err := pipe.Exec() - return err - } - - var extraSeed = func(n int, m int) error { - pipe := client.Pipeline() - for i := 1; i <= m; i++ { - pipe.Set(fmt.Sprintf("A%02d", i), "x", 0).Err() - } - for i := 1; i <= n; i++ { - pipe.Set(fmt.Sprintf("K%02d", i), "x", 0).Err() - } - _, err := pipe.Exec() - return err - } - - var hashKey = "K_HASHTEST" - var hashSeed = func(n int) error { - pipe := client.Pipeline() - for i := 1; i <= n; i++ { - pipe.HSet(hashKey, fmt.Sprintf("K%02d", i), "x").Err() - } - _, err := pipe.Exec() - return err - } - - BeforeEach(func() { - client = redis.NewClient(redisOptions()) - Expect(client.FlushDB().Err()).NotTo(HaveOccurred()) - }) - - AfterEach(func() { - Expect(client.Close()).NotTo(HaveOccurred()) - }) - - It("should scan across empty DBs", func() { - iter := client.Scan(0, "", 10).Iterator() - Expect(iter.Next()).To(BeFalse()) - Expect(iter.Err()).NotTo(HaveOccurred()) - }) - - It("should scan across one page", func() { - Expect(seed(7)).NotTo(HaveOccurred()) - - var vals []string - iter := client.Scan(0, "", 0).Iterator() - for iter.Next() { - vals = append(vals, iter.Val()) - } - Expect(iter.Err()).NotTo(HaveOccurred()) - Expect(vals).To(ConsistOf([]string{"K01", "K02", "K03", "K04", "K05", "K06", "K07"})) - }) - - It("should scan across multiple pages", func() { - Expect(seed(71)).NotTo(HaveOccurred()) - - var vals []string - iter := client.Scan(0, "", 10).Iterator() - for iter.Next() { - vals = append(vals, iter.Val()) - } - Expect(iter.Err()).NotTo(HaveOccurred()) - Expect(vals).To(HaveLen(71)) - Expect(vals).To(ContainElement("K01")) - Expect(vals).To(ContainElement("K71")) - }) - - It("should hscan across multiple pages", func() { - Expect(hashSeed(71)).NotTo(HaveOccurred()) - - var vals []string - iter := client.HScan(hashKey, 0, "", 10).Iterator() - for iter.Next() { - vals = append(vals, iter.Val()) - } - Expect(iter.Err()).NotTo(HaveOccurred()) - Expect(vals).To(HaveLen(71 * 2)) - Expect(vals).To(ContainElement("K01")) - Expect(vals).To(ContainElement("K71")) - }) - - It("should scan to page borders", func() { - Expect(seed(20)).NotTo(HaveOccurred()) - - var vals []string - iter := client.Scan(0, "", 10).Iterator() - for iter.Next() { - vals = append(vals, iter.Val()) - } - Expect(iter.Err()).NotTo(HaveOccurred()) - Expect(vals).To(HaveLen(20)) - }) - - It("should scan with match", func() { - Expect(seed(33)).NotTo(HaveOccurred()) - - var vals []string - iter := client.Scan(0, "K*2*", 10).Iterator() - for iter.Next() { - vals = append(vals, iter.Val()) - } - Expect(iter.Err()).NotTo(HaveOccurred()) - Expect(vals).To(HaveLen(13)) - }) - - It("should scan with match across empty pages", func() { - Expect(extraSeed(2, 10)).NotTo(HaveOccurred()) - - var vals []string - iter := client.Scan(0, "K*", 1).Iterator() - for iter.Next() { - vals = append(vals, iter.Val()) - } - Expect(iter.Err()).NotTo(HaveOccurred()) - Expect(vals).To(HaveLen(2)) - }) -}) diff --git a/vendor/github.com/go-redis/redis/main_test.go b/vendor/github.com/go-redis/redis/main_test.go deleted file mode 100644 index 7c5a6a969..000000000 --- a/vendor/github.com/go-redis/redis/main_test.go +++ /dev/null @@ -1,351 +0,0 @@ -package redis_test - -import ( - "errors" - "fmt" - "net" - "os" - "os/exec" - "path/filepath" - "sync" - "sync/atomic" - "testing" - "time" - - "github.com/go-redis/redis" - - . "github.com/onsi/ginkgo" - . "github.com/onsi/gomega" -) - -const ( - redisPort = "6380" - redisAddr = ":" + redisPort - redisSecondaryPort = "6381" -) - -const ( - ringShard1Port = "6390" - ringShard2Port = "6391" -) - -const ( - sentinelName = "mymaster" - sentinelMasterPort = "8123" - sentinelSlave1Port = "8124" - sentinelSlave2Port = "8125" - sentinelPort = "8126" -) - -var ( - redisMain *redisProcess - ringShard1, ringShard2 *redisProcess - sentinelMaster, sentinelSlave1, sentinelSlave2, sentinel *redisProcess -) - -var cluster = &clusterScenario{ - ports: []string{"8220", "8221", "8222", "8223", "8224", "8225"}, - nodeIds: make([]string, 6), - processes: make(map[string]*redisProcess, 6), - clients: make(map[string]*redis.Client, 6), -} - -var _ = BeforeSuite(func() { - var err error - - redisMain, err = startRedis(redisPort) - Expect(err).NotTo(HaveOccurred()) - - ringShard1, err = startRedis(ringShard1Port) - Expect(err).NotTo(HaveOccurred()) - - ringShard2, err = startRedis(ringShard2Port) - Expect(err).NotTo(HaveOccurred()) - - sentinelMaster, err = startRedis(sentinelMasterPort) - Expect(err).NotTo(HaveOccurred()) - - sentinel, err = startSentinel(sentinelPort, sentinelName, sentinelMasterPort) - Expect(err).NotTo(HaveOccurred()) - - sentinelSlave1, err = startRedis( - sentinelSlave1Port, "--slaveof", "127.0.0.1", sentinelMasterPort) - Expect(err).NotTo(HaveOccurred()) - - sentinelSlave2, err = startRedis( - sentinelSlave2Port, "--slaveof", "127.0.0.1", sentinelMasterPort) - Expect(err).NotTo(HaveOccurred()) - - Expect(startCluster(cluster)).NotTo(HaveOccurred()) -}) - -var _ = AfterSuite(func() { - Expect(redisMain.Close()).NotTo(HaveOccurred()) - - Expect(ringShard1.Close()).NotTo(HaveOccurred()) - Expect(ringShard2.Close()).NotTo(HaveOccurred()) - - Expect(sentinel.Close()).NotTo(HaveOccurred()) - Expect(sentinelSlave1.Close()).NotTo(HaveOccurred()) - Expect(sentinelSlave2.Close()).NotTo(HaveOccurred()) - Expect(sentinelMaster.Close()).NotTo(HaveOccurred()) - - Expect(stopCluster(cluster)).NotTo(HaveOccurred()) -}) - -func TestGinkgoSuite(t *testing.T) { - RegisterFailHandler(Fail) - RunSpecs(t, "go-redis") -} - -//------------------------------------------------------------------------------ - -func redisOptions() *redis.Options { - return &redis.Options{ - Addr: redisAddr, - DB: 15, - DialTimeout: 10 * time.Second, - ReadTimeout: 30 * time.Second, - WriteTimeout: 30 * time.Second, - PoolSize: 10, - PoolTimeout: 30 * time.Second, - IdleTimeout: 500 * time.Millisecond, - IdleCheckFrequency: 500 * time.Millisecond, - } -} - -func redisClusterOptions() *redis.ClusterOptions { - return &redis.ClusterOptions{ - DialTimeout: 10 * time.Second, - ReadTimeout: 30 * time.Second, - WriteTimeout: 30 * time.Second, - PoolSize: 10, - PoolTimeout: 30 * time.Second, - IdleTimeout: 500 * time.Millisecond, - IdleCheckFrequency: 500 * time.Millisecond, - } -} - -func redisRingOptions() *redis.RingOptions { - return &redis.RingOptions{ - Addrs: map[string]string{ - "ringShardOne": ":" + ringShard1Port, - "ringShardTwo": ":" + ringShard2Port, - }, - DialTimeout: 10 * time.Second, - ReadTimeout: 30 * time.Second, - WriteTimeout: 30 * time.Second, - PoolSize: 10, - PoolTimeout: 30 * time.Second, - IdleTimeout: 500 * time.Millisecond, - IdleCheckFrequency: 500 * time.Millisecond, - } -} - -func perform(n int, cbs ...func(int)) { - var wg sync.WaitGroup - for _, cb := range cbs { - for i := 0; i < n; i++ { - wg.Add(1) - go func(cb func(int), i int) { - defer GinkgoRecover() - defer wg.Done() - - cb(i) - }(cb, i) - } - } - wg.Wait() -} - -func eventually(fn func() error, timeout time.Duration) error { - var exit int32 - errCh := make(chan error) - done := make(chan struct{}) - - go func() { - defer GinkgoRecover() - - for atomic.LoadInt32(&exit) == 0 { - err := fn() - if err == nil { - close(done) - return - } - select { - case errCh <- err: - default: - } - time.Sleep(timeout / 100) - } - }() - - select { - case <-done: - return nil - case <-time.After(timeout): - atomic.StoreInt32(&exit, 1) - select { - case err := <-errCh: - return err - default: - return fmt.Errorf("timeout after %s", timeout) - } - } -} - -func execCmd(name string, args ...string) (*os.Process, error) { - cmd := exec.Command(name, args...) - if testing.Verbose() { - cmd.Stdout = os.Stdout - cmd.Stderr = os.Stderr - } - return cmd.Process, cmd.Start() -} - -func connectTo(port string) (*redis.Client, error) { - client := redis.NewClient(&redis.Options{ - Addr: ":" + port, - }) - - err := eventually(func() error { - return client.Ping().Err() - }, 30*time.Second) - if err != nil { - return nil, err - } - - return client, nil -} - -type redisProcess struct { - *os.Process - *redis.Client -} - -func (p *redisProcess) Close() error { - if err := p.Kill(); err != nil { - return err - } - - err := eventually(func() error { - if err := p.Client.Ping().Err(); err != nil { - return nil - } - return errors.New("client is not shutdown") - }, 10*time.Second) - if err != nil { - return err - } - - p.Client.Close() - return nil -} - -var ( - redisServerBin, _ = filepath.Abs(filepath.Join("testdata", "redis", "src", "redis-server")) - redisServerConf, _ = filepath.Abs(filepath.Join("testdata", "redis.conf")) -) - -func redisDir(port string) (string, error) { - dir, err := filepath.Abs(filepath.Join("testdata", "instances", port)) - if err != nil { - return "", err - } - if err := os.RemoveAll(dir); err != nil { - return "", err - } - if err := os.MkdirAll(dir, 0775); err != nil { - return "", err - } - return dir, nil -} - -func startRedis(port string, args ...string) (*redisProcess, error) { - dir, err := redisDir(port) - if err != nil { - return nil, err - } - if err = exec.Command("cp", "-f", redisServerConf, dir).Run(); err != nil { - return nil, err - } - - baseArgs := []string{filepath.Join(dir, "redis.conf"), "--port", port, "--dir", dir} - process, err := execCmd(redisServerBin, append(baseArgs, args...)...) - if err != nil { - return nil, err - } - - client, err := connectTo(port) - if err != nil { - process.Kill() - return nil, err - } - return &redisProcess{process, client}, err -} - -func startSentinel(port, masterName, masterPort string) (*redisProcess, error) { - dir, err := redisDir(port) - if err != nil { - return nil, err - } - process, err := execCmd(redisServerBin, os.DevNull, "--sentinel", "--port", port, "--dir", dir) - if err != nil { - return nil, err - } - client, err := connectTo(port) - if err != nil { - process.Kill() - return nil, err - } - for _, cmd := range []*redis.StatusCmd{ - redis.NewStatusCmd("SENTINEL", "MONITOR", masterName, "127.0.0.1", masterPort, "1"), - redis.NewStatusCmd("SENTINEL", "SET", masterName, "down-after-milliseconds", "500"), - redis.NewStatusCmd("SENTINEL", "SET", masterName, "failover-timeout", "1000"), - redis.NewStatusCmd("SENTINEL", "SET", masterName, "parallel-syncs", "1"), - } { - client.Process(cmd) - if err := cmd.Err(); err != nil { - process.Kill() - return nil, err - } - } - return &redisProcess{process, client}, nil -} - -//------------------------------------------------------------------------------ - -type badConnError string - -func (e badConnError) Error() string { return string(e) } -func (e badConnError) Timeout() bool { return false } -func (e badConnError) Temporary() bool { return false } - -type badConn struct { - net.TCPConn - - readDelay, writeDelay time.Duration - readErr, writeErr error -} - -var _ net.Conn = &badConn{} - -func (cn *badConn) Read([]byte) (int, error) { - if cn.readDelay != 0 { - time.Sleep(cn.readDelay) - } - if cn.readErr != nil { - return 0, cn.readErr - } - return 0, badConnError("bad connection") -} - -func (cn *badConn) Write([]byte) (int, error) { - if cn.writeDelay != 0 { - time.Sleep(cn.writeDelay) - } - if cn.writeErr != nil { - return 0, cn.writeErr - } - return 0, badConnError("bad connection") -} diff --git a/vendor/github.com/go-redis/redis/options_test.go b/vendor/github.com/go-redis/redis/options_test.go deleted file mode 100644 index 211f6b195..000000000 --- a/vendor/github.com/go-redis/redis/options_test.go +++ /dev/null @@ -1,94 +0,0 @@ -// +build go1.7 - -package redis - -import ( - "errors" - "testing" -) - -func TestParseURL(t *testing.T) { - cases := []struct { - u string - addr string - db int - tls bool - err error - }{ - { - "redis://localhost:123/1", - "localhost:123", - 1, false, nil, - }, - { - "redis://localhost:123", - "localhost:123", - 0, false, nil, - }, - { - "redis://localhost/1", - "localhost:6379", - 1, false, nil, - }, - { - "redis://12345", - "12345:6379", - 0, false, nil, - }, - { - "rediss://localhost:123", - "localhost:123", - 0, true, nil, - }, - { - "redis://localhost/?abc=123", - "", - 0, false, errors.New("no options supported"), - }, - { - "http://google.com", - "", - 0, false, errors.New("invalid redis URL scheme: http"), - }, - { - "redis://localhost/1/2/3/4", - "", - 0, false, errors.New("invalid redis URL path: /1/2/3/4"), - }, - { - "12345", - "", - 0, false, errors.New("invalid redis URL scheme: "), - }, - { - "redis://localhost/iamadatabase", - "", - 0, false, errors.New(`invalid redis database number: "iamadatabase"`), - }, - } - - for _, c := range cases { - t.Run(c.u, func(t *testing.T) { - o, err := ParseURL(c.u) - if c.err == nil && err != nil { - t.Fatalf("unexpected error: %q", err) - return - } - if c.err != nil && err != nil { - if c.err.Error() != err.Error() { - t.Fatalf("got %q, expected %q", err, c.err) - } - return - } - if o.Addr != c.addr { - t.Errorf("got %q, want %q", o.Addr, c.addr) - } - if o.DB != c.db { - t.Errorf("got %q, expected %q", o.DB, c.db) - } - if c.tls && o.TLSConfig == nil { - t.Errorf("got nil TLSConfig, expected a TLSConfig") - } - }) - } -} diff --git a/vendor/github.com/go-redis/redis/parser.go b/vendor/github.com/go-redis/redis/parser.go index b378abc4e..f0dc67f0e 100644 --- a/vendor/github.com/go-redis/redis/parser.go +++ b/vendor/github.com/go-redis/redis/parser.go @@ -14,17 +14,23 @@ func sliceParser(rd *proto.Reader, n int64) (interface{}, error) { vals := make([]interface{}, 0, n) for i := int64(0); i < n; i++ { v, err := rd.ReadReply(sliceParser) - if err == Nil { - vals = append(vals, nil) - } else if err != nil { - return nil, err - } else { - switch vv := v.(type) { - case []byte: - vals = append(vals, string(vv)) - default: - vals = append(vals, v) + if err != nil { + if err == Nil { + vals = append(vals, nil) + continue + } + if err, ok := err.(proto.RedisError); ok { + vals = append(vals, err) + continue } + return nil, err + } + + switch v := v.(type) { + case []byte: + vals = append(vals, string(v)) + default: + vals = append(vals, v) } } return vals, nil diff --git a/vendor/github.com/go-redis/redis/pipeline_test.go b/vendor/github.com/go-redis/redis/pipeline_test.go deleted file mode 100644 index 11896c6bb..000000000 --- a/vendor/github.com/go-redis/redis/pipeline_test.go +++ /dev/null @@ -1,80 +0,0 @@ -package redis_test - -import ( - "github.com/go-redis/redis" - - . "github.com/onsi/ginkgo" - . "github.com/onsi/gomega" -) - -var _ = Describe("pipelining", func() { - var client *redis.Client - var pipe *redis.Pipeline - - BeforeEach(func() { - client = redis.NewClient(redisOptions()) - Expect(client.FlushDB().Err()).NotTo(HaveOccurred()) - }) - - AfterEach(func() { - Expect(client.Close()).NotTo(HaveOccurred()) - }) - - It("supports block style", func() { - var get *redis.StringCmd - cmds, err := client.Pipelined(func(pipe redis.Pipeliner) error { - get = pipe.Get("foo") - return nil - }) - Expect(err).To(Equal(redis.Nil)) - Expect(cmds).To(HaveLen(1)) - Expect(cmds[0]).To(Equal(get)) - Expect(get.Err()).To(Equal(redis.Nil)) - Expect(get.Val()).To(Equal("")) - }) - - assertPipeline := func() { - It("returns no errors when there are no commands", func() { - _, err := pipe.Exec() - Expect(err).NotTo(HaveOccurred()) - }) - - It("discards queued commands", func() { - pipe.Get("key") - pipe.Discard() - cmds, err := pipe.Exec() - Expect(err).NotTo(HaveOccurred()) - Expect(cmds).To(BeNil()) - }) - - It("handles val/err", func() { - err := client.Set("key", "value", 0).Err() - Expect(err).NotTo(HaveOccurred()) - - get := pipe.Get("key") - cmds, err := pipe.Exec() - Expect(err).NotTo(HaveOccurred()) - Expect(cmds).To(HaveLen(1)) - - val, err := get.Result() - Expect(err).NotTo(HaveOccurred()) - Expect(val).To(Equal("value")) - }) - } - - Describe("Pipeline", func() { - BeforeEach(func() { - pipe = client.Pipeline().(*redis.Pipeline) - }) - - assertPipeline() - }) - - Describe("TxPipeline", func() { - BeforeEach(func() { - pipe = client.TxPipeline().(*redis.Pipeline) - }) - - assertPipeline() - }) -}) diff --git a/vendor/github.com/go-redis/redis/pool_test.go b/vendor/github.com/go-redis/redis/pool_test.go deleted file mode 100644 index 0ca09adc7..000000000 --- a/vendor/github.com/go-redis/redis/pool_test.go +++ /dev/null @@ -1,143 +0,0 @@ -package redis_test - -import ( - "time" - - "github.com/go-redis/redis" - - . "github.com/onsi/ginkgo" - . "github.com/onsi/gomega" -) - -var _ = Describe("pool", func() { - var client *redis.Client - - BeforeEach(func() { - client = redis.NewClient(redisOptions()) - Expect(client.FlushDB().Err()).NotTo(HaveOccurred()) - }) - - AfterEach(func() { - Expect(client.Close()).NotTo(HaveOccurred()) - }) - - It("respects max size", func() { - perform(1000, func(id int) { - val, err := client.Ping().Result() - Expect(err).NotTo(HaveOccurred()) - Expect(val).To(Equal("PONG")) - }) - - pool := client.Pool() - Expect(pool.Len()).To(BeNumerically("<=", 10)) - Expect(pool.FreeLen()).To(BeNumerically("<=", 10)) - Expect(pool.Len()).To(Equal(pool.FreeLen())) - }) - - It("respects max size on multi", func() { - perform(1000, func(id int) { - var ping *redis.StatusCmd - - err := client.Watch(func(tx *redis.Tx) error { - cmds, err := tx.Pipelined(func(pipe redis.Pipeliner) error { - ping = pipe.Ping() - return nil - }) - Expect(err).NotTo(HaveOccurred()) - Expect(cmds).To(HaveLen(1)) - return err - }) - Expect(err).NotTo(HaveOccurred()) - - Expect(ping.Err()).NotTo(HaveOccurred()) - Expect(ping.Val()).To(Equal("PONG")) - }) - - pool := client.Pool() - Expect(pool.Len()).To(BeNumerically("<=", 10)) - Expect(pool.FreeLen()).To(BeNumerically("<=", 10)) - Expect(pool.Len()).To(Equal(pool.FreeLen())) - }) - - It("respects max size on pipelines", func() { - perform(1000, func(id int) { - pipe := client.Pipeline() - ping := pipe.Ping() - cmds, err := pipe.Exec() - Expect(err).NotTo(HaveOccurred()) - Expect(cmds).To(HaveLen(1)) - Expect(ping.Err()).NotTo(HaveOccurred()) - Expect(ping.Val()).To(Equal("PONG")) - Expect(pipe.Close()).NotTo(HaveOccurred()) - }) - - pool := client.Pool() - Expect(pool.Len()).To(BeNumerically("<=", 10)) - Expect(pool.FreeLen()).To(BeNumerically("<=", 10)) - Expect(pool.Len()).To(Equal(pool.FreeLen())) - }) - - It("removes broken connections", func() { - cn, _, err := client.Pool().Get() - Expect(err).NotTo(HaveOccurred()) - cn.SetNetConn(&badConn{}) - Expect(client.Pool().Put(cn)).NotTo(HaveOccurred()) - - err = client.Ping().Err() - Expect(err).To(MatchError("bad connection")) - - val, err := client.Ping().Result() - Expect(err).NotTo(HaveOccurred()) - Expect(val).To(Equal("PONG")) - - pool := client.Pool() - Expect(pool.Len()).To(Equal(1)) - Expect(pool.FreeLen()).To(Equal(1)) - - stats := pool.Stats() - Expect(stats.Hits).To(Equal(uint32(2))) - Expect(stats.Misses).To(Equal(uint32(2))) - Expect(stats.Timeouts).To(Equal(uint32(0))) - }) - - It("reuses connections", func() { - for i := 0; i < 100; i++ { - val, err := client.Ping().Result() - Expect(err).NotTo(HaveOccurred()) - Expect(val).To(Equal("PONG")) - } - - pool := client.Pool() - Expect(pool.Len()).To(Equal(1)) - Expect(pool.FreeLen()).To(Equal(1)) - - stats := pool.Stats() - Expect(stats.Hits).To(Equal(uint32(100))) - Expect(stats.Misses).To(Equal(uint32(1))) - Expect(stats.Timeouts).To(Equal(uint32(0))) - }) - - It("removes idle connections", func() { - stats := client.PoolStats() - Expect(stats).To(Equal(&redis.PoolStats{ - Hits: 0, - Misses: 1, - Timeouts: 0, - TotalConns: 1, - FreeConns: 1, - StaleConns: 0, - })) - - time.Sleep(2 * time.Second) - - stats = client.PoolStats() - Expect(stats).To(Equal(&redis.PoolStats{ - Hits: 0, - Misses: 1, - Timeouts: 0, - TotalConns: 0, - FreeConns: 0, - StaleConns: 1, - })) - }) -}) diff --git a/vendor/github.com/go-redis/redis/pubsub.go b/vendor/github.com/go-redis/redis/pubsub.go index 3ee4ea9d0..b56728f3e 100644 --- a/vendor/github.com/go-redis/redis/pubsub.go +++ b/vendor/github.com/go-redis/redis/pubsub.go @@ -24,8 +24,8 @@ type PubSub struct { mu sync.Mutex cn *pool.Conn - channels []string - patterns []string + channels map[string]struct{} + patterns map[string]struct{} closed bool cmd *Cmd @@ -67,12 +67,24 @@ func (c *PubSub) _conn(channels []string) (*pool.Conn, error) { func (c *PubSub) resubscribe(cn *pool.Conn) error { var firstErr error if len(c.channels) > 0 { - if err := c._subscribe(cn, "subscribe", c.channels...); err != nil && firstErr == nil { + channels := make([]string, len(c.channels)) + i := 0 + for channel := range c.channels { + channels[i] = channel + i++ + } + if err := c._subscribe(cn, "subscribe", channels...); err != nil && firstErr == nil { firstErr = err } } if len(c.patterns) > 0 { - if err := c._subscribe(cn, "psubscribe", c.patterns...); err != nil && firstErr == nil { + patterns := make([]string, len(c.patterns)) + i := 0 + for pattern := range c.patterns { + patterns[i] = pattern + i++ + } + if err := c._subscribe(cn, "psubscribe", patterns...); err != nil && firstErr == nil { firstErr = err } } @@ -132,7 +144,12 @@ func (c *PubSub) Close() error { func (c *PubSub) Subscribe(channels ...string) error { c.mu.Lock() err := c.subscribe("subscribe", channels...) - c.channels = appendIfNotExists(c.channels, channels...) + if c.channels == nil { + c.channels = make(map[string]struct{}) + } + for _, channel := range channels { + c.channels[channel] = struct{}{} + } c.mu.Unlock() return err } @@ -142,7 +159,12 @@ func (c *PubSub) Subscribe(channels ...string) error { func (c *PubSub) PSubscribe(patterns ...string) error { c.mu.Lock() err := c.subscribe("psubscribe", patterns...) - c.patterns = appendIfNotExists(c.patterns, patterns...) + if c.patterns == nil { + c.patterns = make(map[string]struct{}) + } + for _, pattern := range patterns { + c.patterns[pattern] = struct{}{} + } c.mu.Unlock() return err } @@ -152,7 +174,9 @@ func (c *PubSub) PSubscribe(patterns ...string) error { func (c *PubSub) Unsubscribe(channels ...string) error { c.mu.Lock() err := c.subscribe("unsubscribe", channels...) - c.channels = remove(c.channels, channels...) + for _, channel := range channels { + delete(c.channels, channel) + } c.mu.Unlock() return err } @@ -162,7 +186,9 @@ func (c *PubSub) Unsubscribe(channels ...string) error { func (c *PubSub) PUnsubscribe(patterns ...string) error { c.mu.Lock() err := c.subscribe("punsubscribe", patterns...) - c.patterns = remove(c.patterns, patterns...) + for _, pattern := range patterns { + delete(c.patterns, pattern) + } c.mu.Unlock() return err } @@ -371,31 +397,3 @@ func (c *PubSub) Channel() <-chan *Message { }) return c.ch } - -func appendIfNotExists(ss []string, es ...string) []string { -loop: - for _, e := range es { - for _, s := range ss { - if s == e { - continue loop - } - } - ss = append(ss, e) - } - return ss -} - -func remove(ss []string, es ...string) []string { - if len(es) == 0 { - return ss[:0] - } - for _, e := range es { - for i, s := range ss { - if s == e { - ss = append(ss[:i], ss[i+1:]...) - break - } - } - } - return ss -} diff --git a/vendor/github.com/go-redis/redis/pubsub_test.go b/vendor/github.com/go-redis/redis/pubsub_test.go deleted file mode 100644 index 6a85bd038..000000000 --- a/vendor/github.com/go-redis/redis/pubsub_test.go +++ /dev/null @@ -1,443 +0,0 @@ -package redis_test - -import ( - "io" - "net" - "sync" - "time" - - "github.com/go-redis/redis" - - . "github.com/onsi/ginkgo" - . "github.com/onsi/gomega" -) - -var _ = Describe("PubSub", func() { - var client *redis.Client - - BeforeEach(func() { - client = redis.NewClient(redisOptions()) - Expect(client.FlushDB().Err()).NotTo(HaveOccurred()) - }) - - AfterEach(func() { - Expect(client.Close()).NotTo(HaveOccurred()) - }) - - It("should support pattern matching", func() { - pubsub := client.PSubscribe("mychannel*") - defer pubsub.Close() - - { - msgi, err := pubsub.ReceiveTimeout(time.Second) - Expect(err).NotTo(HaveOccurred()) - subscr := msgi.(*redis.Subscription) - Expect(subscr.Kind).To(Equal("psubscribe")) - Expect(subscr.Channel).To(Equal("mychannel*")) - Expect(subscr.Count).To(Equal(1)) - } - - { - msgi, err := pubsub.ReceiveTimeout(time.Second) - Expect(err.(net.Error).Timeout()).To(Equal(true)) - Expect(msgi).To(BeNil()) - } - - n, err := client.Publish("mychannel1", "hello").Result() - Expect(err).NotTo(HaveOccurred()) - Expect(n).To(Equal(int64(1))) - - Expect(pubsub.PUnsubscribe("mychannel*")).NotTo(HaveOccurred()) - - { - msgi, err := pubsub.ReceiveTimeout(time.Second) - Expect(err).NotTo(HaveOccurred()) - subscr := msgi.(*redis.Message) - Expect(subscr.Channel).To(Equal("mychannel1")) - Expect(subscr.Pattern).To(Equal("mychannel*")) - Expect(subscr.Payload).To(Equal("hello")) - } - - { - msgi, err := pubsub.ReceiveTimeout(time.Second) - Expect(err).NotTo(HaveOccurred()) - subscr := msgi.(*redis.Subscription) - Expect(subscr.Kind).To(Equal("punsubscribe")) - Expect(subscr.Channel).To(Equal("mychannel*")) - Expect(subscr.Count).To(Equal(0)) - } - - stats := client.PoolStats() - Expect(stats.Misses).To(Equal(uint32(2))) - }) - - It("should pub/sub channels", func() { - channels, err := client.PubSubChannels("mychannel*").Result() - Expect(err).NotTo(HaveOccurred()) - Expect(channels).To(BeEmpty()) - - pubsub := client.Subscribe("mychannel", "mychannel2") - defer pubsub.Close() - - channels, err = client.PubSubChannels("mychannel*").Result() - Expect(err).NotTo(HaveOccurred()) - Expect(channels).To(ConsistOf([]string{"mychannel", "mychannel2"})) - - channels, err = client.PubSubChannels("").Result() - Expect(err).NotTo(HaveOccurred()) - Expect(channels).To(BeEmpty()) - - channels, err = client.PubSubChannels("*").Result() - Expect(err).NotTo(HaveOccurred()) - Expect(len(channels)).To(BeNumerically(">=", 2)) - }) - - It("should return the numbers of subscribers", func() { - pubsub := client.Subscribe("mychannel", "mychannel2") - defer pubsub.Close() - - channels, err := client.PubSubNumSub("mychannel", "mychannel2", "mychannel3").Result() - Expect(err).NotTo(HaveOccurred()) - Expect(channels).To(Equal(map[string]int64{ - "mychannel": 1, - "mychannel2": 1, - "mychannel3": 0, - })) - }) - - It("should return the numbers of subscribers by pattern", func() { - num, err := client.PubSubNumPat().Result() - Expect(err).NotTo(HaveOccurred()) - Expect(num).To(Equal(int64(0))) - - pubsub := client.PSubscribe("*") - defer pubsub.Close() - - num, err = client.PubSubNumPat().Result() - Expect(err).NotTo(HaveOccurred()) - Expect(num).To(Equal(int64(1))) - }) - - It("should pub/sub", func() { - pubsub := client.Subscribe("mychannel", "mychannel2") - defer pubsub.Close() - - { - msgi, err := pubsub.ReceiveTimeout(time.Second) - Expect(err).NotTo(HaveOccurred()) - subscr := msgi.(*redis.Subscription) - Expect(subscr.Kind).To(Equal("subscribe")) - Expect(subscr.Channel).To(Equal("mychannel")) - Expect(subscr.Count).To(Equal(1)) - } - - { - msgi, err := pubsub.ReceiveTimeout(time.Second) - Expect(err).NotTo(HaveOccurred()) - subscr := msgi.(*redis.Subscription) - Expect(subscr.Kind).To(Equal("subscribe")) - Expect(subscr.Channel).To(Equal("mychannel2")) - Expect(subscr.Count).To(Equal(2)) - } - - { - msgi, err := pubsub.ReceiveTimeout(time.Second) - Expect(err.(net.Error).Timeout()).To(Equal(true)) - Expect(msgi).NotTo(HaveOccurred()) - } - - n, err := client.Publish("mychannel", "hello").Result() - Expect(err).NotTo(HaveOccurred()) - Expect(n).To(Equal(int64(1))) - - n, err = client.Publish("mychannel2", "hello2").Result() - Expect(err).NotTo(HaveOccurred()) - Expect(n).To(Equal(int64(1))) - - Expect(pubsub.Unsubscribe("mychannel", "mychannel2")).NotTo(HaveOccurred()) - - { - msgi, err := pubsub.ReceiveTimeout(time.Second) - Expect(err).NotTo(HaveOccurred()) - msg := msgi.(*redis.Message) - Expect(msg.Channel).To(Equal("mychannel")) - Expect(msg.Payload).To(Equal("hello")) - } - - { - msgi, err := pubsub.ReceiveTimeout(time.Second) - Expect(err).NotTo(HaveOccurred()) - msg := msgi.(*redis.Message) - Expect(msg.Channel).To(Equal("mychannel2")) - Expect(msg.Payload).To(Equal("hello2")) - } - - { - msgi, err := pubsub.ReceiveTimeout(time.Second) - Expect(err).NotTo(HaveOccurred()) - subscr := msgi.(*redis.Subscription) - Expect(subscr.Kind).To(Equal("unsubscribe")) - Expect(subscr.Channel).To(Equal("mychannel")) - Expect(subscr.Count).To(Equal(1)) - } - - { - msgi, err := pubsub.ReceiveTimeout(time.Second) - Expect(err).NotTo(HaveOccurred()) - subscr := msgi.(*redis.Subscription) - Expect(subscr.Kind).To(Equal("unsubscribe")) - Expect(subscr.Channel).To(Equal("mychannel2")) - Expect(subscr.Count).To(Equal(0)) - } - - stats := client.PoolStats() - Expect(stats.Misses).To(Equal(uint32(2))) - }) - - It("should ping/pong", func() { - pubsub := client.Subscribe("mychannel") - defer pubsub.Close() - - _, err := pubsub.ReceiveTimeout(time.Second) - Expect(err).NotTo(HaveOccurred()) - - err = pubsub.Ping("") - Expect(err).NotTo(HaveOccurred()) - - msgi, err := pubsub.ReceiveTimeout(time.Second) - Expect(err).NotTo(HaveOccurred()) - pong := msgi.(*redis.Pong) - Expect(pong.Payload).To(Equal("")) - }) - - It("should ping/pong with payload", func() { - pubsub := client.Subscribe("mychannel") - defer pubsub.Close() - - _, err := pubsub.ReceiveTimeout(time.Second) - Expect(err).NotTo(HaveOccurred()) - - err = pubsub.Ping("hello") - Expect(err).NotTo(HaveOccurred()) - - msgi, err := pubsub.ReceiveTimeout(time.Second) - Expect(err).NotTo(HaveOccurred()) - pong := msgi.(*redis.Pong) - Expect(pong.Payload).To(Equal("hello")) - }) - - It("should multi-ReceiveMessage", func() { - pubsub := client.Subscribe("mychannel") - defer pubsub.Close() - - subscr, err := pubsub.ReceiveTimeout(time.Second) - Expect(err).NotTo(HaveOccurred()) - Expect(subscr).To(Equal(&redis.Subscription{ - Kind: "subscribe", - Channel: "mychannel", - Count: 1, - })) - - err = client.Publish("mychannel", "hello").Err() - Expect(err).NotTo(HaveOccurred()) - - err = client.Publish("mychannel", "world").Err() - Expect(err).NotTo(HaveOccurred()) - - msg, err := pubsub.ReceiveMessage() - Expect(err).NotTo(HaveOccurred()) - Expect(msg.Channel).To(Equal("mychannel")) - Expect(msg.Payload).To(Equal("hello")) - - msg, err = pubsub.ReceiveMessage() - Expect(err).NotTo(HaveOccurred()) - Expect(msg.Channel).To(Equal("mychannel")) - Expect(msg.Payload).To(Equal("world")) - }) - - It("should ReceiveMessage after timeout", func() { - timeout := 100 * time.Millisecond - - pubsub := client.Subscribe("mychannel") - defer pubsub.Close() - - subscr, err := pubsub.ReceiveTimeout(time.Second) - Expect(err).NotTo(HaveOccurred()) - Expect(subscr).To(Equal(&redis.Subscription{ - Kind: "subscribe", - Channel: "mychannel", - Count: 1, - })) - - done := make(chan bool, 1) - go func() { - defer GinkgoRecover() - defer func() { - done <- true - }() - - time.Sleep(timeout + 100*time.Millisecond) - n, err := client.Publish("mychannel", "hello").Result() - Expect(err).NotTo(HaveOccurred()) - Expect(n).To(Equal(int64(1))) - }() - - msg, err := pubsub.ReceiveMessageTimeout(timeout) - Expect(err).NotTo(HaveOccurred()) - Expect(msg.Channel).To(Equal("mychannel")) - Expect(msg.Payload).To(Equal("hello")) - - Eventually(done).Should(Receive()) - - stats := client.PoolStats() - Expect(stats.Hits).To(Equal(uint32(1))) - Expect(stats.Misses).To(Equal(uint32(1))) - }) - - It("returns an error when subscribe fails", func() { - pubsub := client.Subscribe() - defer pubsub.Close() - - pubsub.SetNetConn(&badConn{ - readErr: io.EOF, - writeErr: io.EOF, - }) - - err := pubsub.Subscribe("mychannel") - Expect(err).To(MatchError("EOF")) - - err = pubsub.Subscribe("mychannel") - Expect(err).NotTo(HaveOccurred()) - }) - - expectReceiveMessageOnError := func(pubsub *redis.PubSub) { - pubsub.SetNetConn(&badConn{ - readErr: io.EOF, - writeErr: io.EOF, - }) - - done := make(chan bool, 1) - go func() { - defer GinkgoRecover() - defer func() { - done <- true - }() - - time.Sleep(100 * time.Millisecond) - err := client.Publish("mychannel", "hello").Err() - Expect(err).NotTo(HaveOccurred()) - }() - - msg, err := pubsub.ReceiveMessage() - Expect(err).NotTo(HaveOccurred()) - Expect(msg.Channel).To(Equal("mychannel")) - Expect(msg.Payload).To(Equal("hello")) - - Eventually(done).Should(Receive()) - } - - It("Subscribe should reconnect on ReceiveMessage error", func() { - pubsub := client.Subscribe("mychannel") - defer pubsub.Close() - - subscr, err := pubsub.ReceiveTimeout(time.Second) - Expect(err).NotTo(HaveOccurred()) - Expect(subscr).To(Equal(&redis.Subscription{ - Kind: "subscribe", - Channel: "mychannel", - Count: 1, - })) - - expectReceiveMessageOnError(pubsub) - }) - - It("PSubscribe should reconnect on ReceiveMessage error", func() { - pubsub := client.PSubscribe("mychannel") - defer pubsub.Close() - - subscr, err := pubsub.ReceiveTimeout(time.Second) - Expect(err).NotTo(HaveOccurred()) - Expect(subscr).To(Equal(&redis.Subscription{ - Kind: "psubscribe", - Channel: "mychannel", - Count: 1, - })) - - expectReceiveMessageOnError(pubsub) - }) - - It("should return on Close", func() { - pubsub := client.Subscribe("mychannel") - defer pubsub.Close() - - var wg sync.WaitGroup - wg.Add(1) - go func() { - defer GinkgoRecover() - - wg.Done() - defer wg.Done() - - _, err := pubsub.ReceiveMessage() - Expect(err).To(HaveOccurred()) - Expect(err).To(SatisfyAny( - MatchError("redis: client is closed"), - MatchError("use of closed network connection"), // Go 1.4 - )) - }() - - wg.Wait() - wg.Add(1) - - Expect(pubsub.Close()).NotTo(HaveOccurred()) - - wg.Wait() - }) - - It("should ReceiveMessage without a subscription", func() { - timeout := 100 * time.Millisecond - - pubsub := client.Subscribe() - defer pubsub.Close() - - var wg sync.WaitGroup - wg.Add(1) - go func() { - defer GinkgoRecover() - defer wg.Done() - - time.Sleep(2 * timeout) - - err := pubsub.Subscribe("mychannel") - Expect(err).NotTo(HaveOccurred()) - - time.Sleep(timeout) - - err = client.Publish("mychannel", "hello").Err() - Expect(err).NotTo(HaveOccurred()) - }() - - msg, err := pubsub.ReceiveMessageTimeout(timeout) - Expect(err).NotTo(HaveOccurred()) - Expect(msg.Channel).To(Equal("mychannel")) - Expect(msg.Payload).To(Equal("hello")) - - wg.Wait() - }) - - It("handles big message payload", func() { - pubsub := client.Subscribe("mychannel") - defer pubsub.Close() - - ch := pubsub.Channel() - - bigVal := bigVal() - err := client.Publish("mychannel", bigVal).Err() - Expect(err).NotTo(HaveOccurred()) - - var msg *redis.Message - Eventually(ch).Should(Receive(&msg)) - Expect(msg.Channel).To(Equal("mychannel")) - Expect(msg.Payload).To(Equal(string(bigVal))) - }) -}) diff --git a/vendor/github.com/go-redis/redis/race_test.go b/vendor/github.com/go-redis/redis/race_test.go deleted file mode 100644 index 14264086c..000000000 --- a/vendor/github.com/go-redis/redis/race_test.go +++ /dev/null @@ -1,250 +0,0 @@ -package redis_test - -import ( - "bytes" - "fmt" - "net" - "strconv" - "testing" - "time" - - "github.com/go-redis/redis" - - . "github.com/onsi/ginkgo" - . "github.com/onsi/gomega" -) - -var _ = Describe("races", func() { - var client *redis.Client - var C, N int - - BeforeEach(func() { - client = redis.NewClient(redisOptions()) - Expect(client.FlushDB().Err()).To(BeNil()) - - C, N = 10, 1000 - if testing.Short() { - C = 4 - N = 100 - } - }) - - AfterEach(func() { - err := client.Close() - Expect(err).NotTo(HaveOccurred()) - }) - - It("should echo", func() { - perform(C, func(id int) { - for i := 0; i < N; i++ { - msg := fmt.Sprintf("echo %d %d", id, i) - echo, err := client.Echo(msg).Result() - Expect(err).NotTo(HaveOccurred()) - Expect(echo).To(Equal(msg)) - } - }) - }) - - It("should incr", func() { - key := "TestIncrFromGoroutines" - - perform(C, func(id int) { - for i := 0; i < N; i++ { - err := client.Incr(key).Err() - Expect(err).NotTo(HaveOccurred()) - } - }) - - val, err := client.Get(key).Int64() - Expect(err).NotTo(HaveOccurred()) - Expect(val).To(Equal(int64(C * N))) - }) - - It("should handle many keys", func() { - perform(C, func(id int) { - for i := 0; i < N; i++ { - err := client.Set( - fmt.Sprintf("keys.key-%d-%d", id, i), - fmt.Sprintf("hello-%d-%d", id, i), - 0, - ).Err() - Expect(err).NotTo(HaveOccurred()) - } - }) - - keys := client.Keys("keys.*") - Expect(keys.Err()).NotTo(HaveOccurred()) - Expect(len(keys.Val())).To(Equal(C * N)) - }) - - It("should handle many keys 2", func() { - perform(C, func(id int) { - keys := []string{"non-existent-key"} - for i := 0; i < N; i++ { - key := fmt.Sprintf("keys.key-%d", i) - keys = append(keys, key) - - err := client.Set(key, fmt.Sprintf("hello-%d", i), 0).Err() - Expect(err).NotTo(HaveOccurred()) - } - keys = append(keys, "non-existent-key") - - vals, err := client.MGet(keys...).Result() - Expect(err).NotTo(HaveOccurred()) - Expect(len(vals)).To(Equal(N + 2)) - - for i := 0; i < N; i++ { - Expect(vals[i+1]).To(Equal(fmt.Sprintf("hello-%d", i))) - } - - Expect(vals[0]).To(BeNil()) - Expect(vals[N+1]).To(BeNil()) - }) - }) - - It("should handle big vals in Get", func() { - C, N = 4, 100 - - bigVal := bigVal() - - err := client.Set("key", bigVal, 0).Err() - Expect(err).NotTo(HaveOccurred()) - - // Reconnect to get new connection. - Expect(client.Close()).To(BeNil()) - client = redis.NewClient(redisOptions()) - - perform(C, func(id int) { - for i := 0; i < N; i++ { - got, err := client.Get("key").Bytes() - Expect(err).NotTo(HaveOccurred()) - Expect(got).To(Equal(bigVal)) - } - }) - }) - - It("should handle big vals in Set", func() { - C, N = 4, 100 - - bigVal := bigVal() - perform(C, func(id int) { - for i := 0; i < N; i++ { - err := client.Set("key", bigVal, 0).Err() - Expect(err).NotTo(HaveOccurred()) - } - }) - }) - - It("should select db", func() { - err := client.Set("db", 1, 0).Err() - Expect(err).NotTo(HaveOccurred()) - - perform(C, func(id int) { - opt := redisOptions() - opt.DB = id - client := redis.NewClient(opt) - for i := 0; i < N; i++ { - err := client.Set("db", id, 0).Err() - Expect(err).NotTo(HaveOccurred()) - - n, err := client.Get("db").Int64() - Expect(err).NotTo(HaveOccurred()) - Expect(n).To(Equal(int64(id))) - } - err := client.Close() - Expect(err).NotTo(HaveOccurred()) - }) - - n, err := client.Get("db").Int64() - Expect(err).NotTo(HaveOccurred()) - Expect(n).To(Equal(int64(1))) - }) - - It("should select DB with read timeout", func() { - perform(C, func(id int) { - opt := redisOptions() - opt.DB = id - opt.ReadTimeout = time.Nanosecond - client := redis.NewClient(opt) - - perform(C, func(id int) { - err := client.Ping().Err() - Expect(err).To(HaveOccurred()) - Expect(err.(net.Error).Timeout()).To(BeTrue()) - }) - - err := client.Close() - Expect(err).NotTo(HaveOccurred()) - }) - }) - - It("should Watch/Unwatch", func() { - err := client.Set("key", "0", 0).Err() - Expect(err).NotTo(HaveOccurred()) - - perform(C, func(id int) { - for i := 0; i < N; i++ { - err := client.Watch(func(tx *redis.Tx) error { - val, err := tx.Get("key").Result() - Expect(err).NotTo(HaveOccurred()) - Expect(val).NotTo(Equal(redis.Nil)) - - num, err := strconv.ParseInt(val, 10, 64) - Expect(err).NotTo(HaveOccurred()) - - cmds, err := tx.Pipelined(func(pipe redis.Pipeliner) error { - pipe.Set("key", strconv.FormatInt(num+1, 10), 0) - return nil - }) - Expect(cmds).To(HaveLen(1)) - return err - }, "key") - if err == redis.TxFailedErr { - i-- - continue - } - Expect(err).NotTo(HaveOccurred()) - } - }) - - val, err := client.Get("key").Int64() - Expect(err).NotTo(HaveOccurred()) - Expect(val).To(Equal(int64(C * N))) - }) - - It("should Pipeline", func() { - perform(C, func(id int) { - pipe := client.Pipeline() - for i := 0; i < N; i++ { - pipe.Echo(fmt.Sprint(i)) - } - - cmds, err := pipe.Exec() - Expect(err).NotTo(HaveOccurred()) - Expect(cmds).To(HaveLen(N)) - - for i := 0; i < N; i++ { - Expect(cmds[i].(*redis.StringCmd).Val()).To(Equal(fmt.Sprint(i))) - } - }) - }) - - It("should Pipeline", func() { - pipe := client.Pipeline() - perform(N, func(id int) { - pipe.Incr("key") - }) - - cmds, err := pipe.Exec() - Expect(err).NotTo(HaveOccurred()) - Expect(cmds).To(HaveLen(N)) - - n, err := client.Get("key").Int64() - Expect(err).NotTo(HaveOccurred()) - Expect(n).To(Equal(int64(N))) - }) -}) - -func bigVal() []byte { - return bytes.Repeat([]byte{'*'}, 1<<17) // 128kb -} diff --git a/vendor/github.com/go-redis/redis/redis.go b/vendor/github.com/go-redis/redis/redis.go index cf402986d..7a606b70e 100644 --- a/vendor/github.com/go-redis/redis/redis.go +++ b/vendor/github.com/go-redis/redis/redis.go @@ -1,6 +1,7 @@ package redis import ( + "context" "fmt" "log" "os" @@ -11,8 +12,8 @@ import ( "github.com/go-redis/redis/internal/proto" ) -// Nil reply redis returned when key does not exist. -const Nil = internal.Nil +// Nil reply Redis returns when key does not exist. +const Nil = proto.Nil func init() { SetLogger(log.New(os.Stderr, "redis: ", log.LstdFlags|log.Lshortfile)) @@ -22,6 +23,17 @@ func SetLogger(logger *log.Logger) { internal.Logger = logger } +type baseClient struct { + opt *Options + connPool pool.Pooler + + process func(Cmder) error + processPipeline func([]Cmder) error + processTxPipeline func([]Cmder) error + + onClose func() error // hook called when client is closed +} + func (c *baseClient) init() { c.process = c.defaultProcess c.processPipeline = c.defaultProcessPipeline @@ -84,16 +96,7 @@ func (c *baseClient) initConn(cn *pool.Conn) error { return nil } - // Temp client to initialize connection. - conn := &Conn{ - baseClient: baseClient{ - opt: c.opt, - connPool: pool.NewSingleConnPool(cn), - }, - } - conn.baseClient.init() - conn.statefulCmdable.setProcessor(conn.Process) - + conn := newConn(c.opt, cn) _, err := conn.Pipelined(func(pipe Pipeliner) error { if c.opt.Password != "" { pipe.Auth(c.opt.Password) @@ -119,10 +122,7 @@ func (c *baseClient) initConn(cn *pool.Conn) error { return nil } -// WrapProcess replaces the process func. It takes a function createWrapper -// which is supplied by the user. createWrapper takes the old process func as -// an input and returns the new wrapper process func. createWrapper should -// use call the old process func within the new process func. +// WrapProcess wraps function that processes Redis commands. func (c *baseClient) WrapProcess(fn func(oldProcess func(cmd Cmder) error) func(cmd Cmder) error) { c.process = fn(c.process) } @@ -338,33 +338,52 @@ func (c *baseClient) txPipelineReadQueued(cn *pool.Conn, cmds []Cmder) error { type Client struct { baseClient cmdable + + ctx context.Context } -func newClient(opt *Options, pool pool.Pooler) *Client { +// NewClient returns a client to the Redis Server specified by Options. +func NewClient(opt *Options) *Client { + opt.init() + c := Client{ baseClient: baseClient{ opt: opt, - connPool: pool, + connPool: newConnPool(opt), }, } c.baseClient.init() - c.cmdable.setProcessor(c.Process) + c.init() + return &c } -// NewClient returns a client to the Redis Server specified by Options. -func NewClient(opt *Options) *Client { - opt.init() - return newClient(opt, newConnPool(opt)) +func (c *Client) init() { + c.cmdable.setProcessor(c.Process) } -func (c *Client) copy() *Client { - c2 := new(Client) - *c2 = *c - c2.cmdable.setProcessor(c2.Process) +func (c *Client) Context() context.Context { + if c.ctx != nil { + return c.ctx + } + return context.Background() +} + +func (c *Client) WithContext(ctx context.Context) *Client { + if ctx == nil { + panic("nil context") + } + c2 := c.copy() + c2.ctx = ctx return c2 } +func (c *Client) copy() *Client { + cp := *c + cp.init() + return &cp +} + // Options returns read-only Options that were used to create the client. func (c *Client) Options() *Options { return c.opt @@ -442,6 +461,18 @@ type Conn struct { statefulCmdable } +func newConn(opt *Options, cn *pool.Conn) *Conn { + c := Conn{ + baseClient: baseClient{ + opt: opt, + connPool: pool.NewSingleConnPool(cn), + }, + } + c.baseClient.init() + c.statefulCmdable.setProcessor(c.Process) + return &c +} + func (c *Conn) Pipelined(fn func(Pipeliner) error) ([]Cmder, error) { return c.Pipeline().Pipelined(fn) } diff --git a/vendor/github.com/go-redis/redis/redis_context.go b/vendor/github.com/go-redis/redis/redis_context.go deleted file mode 100644 index c00e505f6..000000000 --- a/vendor/github.com/go-redis/redis/redis_context.go +++ /dev/null @@ -1,38 +0,0 @@ -// +build go1.7 - -package redis - -import ( - "context" - - "github.com/go-redis/redis/internal/pool" -) - -type baseClient struct { - connPool pool.Pooler - opt *Options - - process func(Cmder) error - processPipeline func([]Cmder) error - processTxPipeline func([]Cmder) error - - onClose func() error // hook called when client is closed - - ctx context.Context -} - -func (c *Client) Context() context.Context { - if c.ctx != nil { - return c.ctx - } - return context.Background() -} - -func (c *Client) WithContext(ctx context.Context) *Client { - if ctx == nil { - panic("nil context") - } - c2 := c.copy() - c2.ctx = ctx - return c2 -} diff --git a/vendor/github.com/go-redis/redis/redis_no_context.go b/vendor/github.com/go-redis/redis/redis_no_context.go deleted file mode 100644 index 8555c5c09..000000000 --- a/vendor/github.com/go-redis/redis/redis_no_context.go +++ /dev/null @@ -1,18 +0,0 @@ -// +build !go1.7 - -package redis - -import ( - "github.com/go-redis/redis/internal/pool" -) - -type baseClient struct { - connPool pool.Pooler - opt *Options - - process func(Cmder) error - processPipeline func([]Cmder) error - processTxPipeline func([]Cmder) error - - onClose func() error // hook called when client is closed -} diff --git a/vendor/github.com/go-redis/redis/redis_test.go b/vendor/github.com/go-redis/redis/redis_test.go deleted file mode 100644 index 49d3fb329..000000000 --- a/vendor/github.com/go-redis/redis/redis_test.go +++ /dev/null @@ -1,364 +0,0 @@ -package redis_test - -import ( - "bytes" - "net" - "time" - - "github.com/go-redis/redis" - - . "github.com/onsi/ginkgo" - . "github.com/onsi/gomega" -) - -var _ = Describe("Client", func() { - var client *redis.Client - - BeforeEach(func() { - client = redis.NewClient(redisOptions()) - Expect(client.FlushDB().Err()).NotTo(HaveOccurred()) - }) - - AfterEach(func() { - client.Close() - }) - - It("should Stringer", func() { - Expect(client.String()).To(Equal("Redis<:6380 db:15>")) - }) - - It("should ping", func() { - val, err := client.Ping().Result() - Expect(err).NotTo(HaveOccurred()) - Expect(val).To(Equal("PONG")) - }) - - It("should return pool stats", func() { - Expect(client.PoolStats()).To(BeAssignableToTypeOf(&redis.PoolStats{})) - }) - - It("should support custom dialers", func() { - custom := redis.NewClient(&redis.Options{ - Addr: ":1234", - Dialer: func() (net.Conn, error) { - return net.Dial("tcp", redisAddr) - }, - }) - - val, err := custom.Ping().Result() - Expect(err).NotTo(HaveOccurred()) - Expect(val).To(Equal("PONG")) - Expect(custom.Close()).NotTo(HaveOccurred()) - }) - - It("should close", func() { - Expect(client.Close()).NotTo(HaveOccurred()) - err := client.Ping().Err() - Expect(err).To(MatchError("redis: client is closed")) - }) - - It("should close pubsub without closing the client", func() { - pubsub := client.Subscribe() - Expect(pubsub.Close()).NotTo(HaveOccurred()) - - _, err := pubsub.Receive() - Expect(err).To(MatchError("redis: client is closed")) - Expect(client.Ping().Err()).NotTo(HaveOccurred()) - }) - - It("should close Tx without closing the client", func() { - err := client.Watch(func(tx *redis.Tx) error { - _, err := tx.Pipelined(func(pipe redis.Pipeliner) error { - pipe.Ping() - return nil - }) - return err - }) - Expect(err).NotTo(HaveOccurred()) - - Expect(client.Ping().Err()).NotTo(HaveOccurred()) - }) - - It("should close pipeline without closing the client", func() { - pipeline := client.Pipeline() - Expect(pipeline.Close()).NotTo(HaveOccurred()) - - pipeline.Ping() - _, err := pipeline.Exec() - Expect(err).To(MatchError("redis: client is closed")) - - Expect(client.Ping().Err()).NotTo(HaveOccurred()) - }) - - It("should close pubsub when client is closed", func() { - pubsub := client.Subscribe() - Expect(client.Close()).NotTo(HaveOccurred()) - - _, err := pubsub.Receive() - Expect(err).To(MatchError("redis: client is closed")) - - Expect(pubsub.Close()).NotTo(HaveOccurred()) - }) - - It("should close pipeline when client is closed", func() { - pipeline := client.Pipeline() - Expect(client.Close()).NotTo(HaveOccurred()) - Expect(pipeline.Close()).NotTo(HaveOccurred()) - }) - - It("should select DB", func() { - db2 := redis.NewClient(&redis.Options{ - Addr: redisAddr, - DB: 2, - }) - Expect(db2.FlushDB().Err()).NotTo(HaveOccurred()) - Expect(db2.Get("db").Err()).To(Equal(redis.Nil)) - Expect(db2.Set("db", 2, 0).Err()).NotTo(HaveOccurred()) - - n, err := db2.Get("db").Int64() - Expect(err).NotTo(HaveOccurred()) - Expect(n).To(Equal(int64(2))) - - Expect(client.Get("db").Err()).To(Equal(redis.Nil)) - - Expect(db2.FlushDB().Err()).NotTo(HaveOccurred()) - Expect(db2.Close()).NotTo(HaveOccurred()) - }) - - It("processes custom commands", func() { - cmd := redis.NewCmd("PING") - client.Process(cmd) - - // Flush buffers. - Expect(client.Echo("hello").Err()).NotTo(HaveOccurred()) - - Expect(cmd.Err()).NotTo(HaveOccurred()) - Expect(cmd.Val()).To(Equal("PONG")) - }) - - It("should retry command on network error", func() { - Expect(client.Close()).NotTo(HaveOccurred()) - - client = redis.NewClient(&redis.Options{ - Addr: redisAddr, - MaxRetries: 1, - }) - - // Put bad connection in the pool. - cn, _, err := client.Pool().Get() - Expect(err).NotTo(HaveOccurred()) - - cn.SetNetConn(&badConn{}) - err = client.Pool().Put(cn) - Expect(err).NotTo(HaveOccurred()) - - err = client.Ping().Err() - Expect(err).NotTo(HaveOccurred()) - }) - - It("should retry with backoff", func() { - Expect(client.Close()).NotTo(HaveOccurred()) - - // use up all the available connections to force a fail - connectionHogClient := redis.NewClient(&redis.Options{ - Addr: redisAddr, - MaxRetries: 1, - }) - defer connectionHogClient.Close() - - for i := 0; i <= 1002; i++ { - connectionHogClient.Pool().NewConn() - } - - clientNoRetry := redis.NewClient(&redis.Options{ - Addr: redisAddr, - PoolSize: 1, - MaxRetryBackoff: -1, - }) - defer clientNoRetry.Close() - - clientRetry := redis.NewClient(&redis.Options{ - Addr: redisAddr, - MaxRetries: 5, - PoolSize: 1, - MaxRetryBackoff: 128 * time.Millisecond, - }) - defer clientRetry.Close() - - startNoRetry := time.Now() - err := clientNoRetry.Ping().Err() - Expect(err).To(HaveOccurred()) - elapseNoRetry := time.Since(startNoRetry) - - startRetry := time.Now() - err = clientRetry.Ping().Err() - Expect(err).To(HaveOccurred()) - elapseRetry := time.Since(startRetry) - - Expect(elapseRetry > elapseNoRetry).To(BeTrue()) - }) - - It("should update conn.UsedAt on read/write", func() { - cn, _, err := client.Pool().Get() - Expect(err).NotTo(HaveOccurred()) - Expect(cn.UsedAt).NotTo(BeZero()) - createdAt := cn.UsedAt() - - err = client.Pool().Put(cn) - Expect(err).NotTo(HaveOccurred()) - Expect(cn.UsedAt().Equal(createdAt)).To(BeTrue()) - - err = client.Ping().Err() - Expect(err).NotTo(HaveOccurred()) - - cn, _, err = client.Pool().Get() - Expect(err).NotTo(HaveOccurred()) - Expect(cn).NotTo(BeNil()) - Expect(cn.UsedAt().After(createdAt)).To(BeTrue()) - }) - - It("should process command with special chars", func() { - set := client.Set("key", "hello1\r\nhello2\r\n", 0) - Expect(set.Err()).NotTo(HaveOccurred()) - Expect(set.Val()).To(Equal("OK")) - - get := client.Get("key") - Expect(get.Err()).NotTo(HaveOccurred()) - Expect(get.Val()).To(Equal("hello1\r\nhello2\r\n")) - }) - - It("should handle big vals", func() { - bigVal := bytes.Repeat([]byte{'*'}, 2e6) - - err := client.Set("key", bigVal, 0).Err() - Expect(err).NotTo(HaveOccurred()) - - // Reconnect to get new connection. - Expect(client.Close()).NotTo(HaveOccurred()) - client = redis.NewClient(redisOptions()) - - got, err := client.Get("key").Bytes() - Expect(err).NotTo(HaveOccurred()) - Expect(got).To(Equal(bigVal)) - }) - - It("should call WrapProcess", func() { - var wrapperFnCalled bool - - client.WrapProcess(func(oldProcess func(redis.Cmder) error) func(redis.Cmder) error { - return func(cmd redis.Cmder) error { - wrapperFnCalled = true - return oldProcess(cmd) - } - }) - - Expect(client.Ping().Err()).NotTo(HaveOccurred()) - - Expect(wrapperFnCalled).To(BeTrue()) - }) -}) - -var _ = Describe("Client timeout", func() { - var opt *redis.Options - var client *redis.Client - - AfterEach(func() { - Expect(client.Close()).NotTo(HaveOccurred()) - }) - - testTimeout := func() { - It("Ping timeouts", func() { - err := client.Ping().Err() - Expect(err).To(HaveOccurred()) - Expect(err.(net.Error).Timeout()).To(BeTrue()) - }) - - It("Pipeline timeouts", func() { - _, err := client.Pipelined(func(pipe redis.Pipeliner) error { - pipe.Ping() - return nil - }) - Expect(err).To(HaveOccurred()) - Expect(err.(net.Error).Timeout()).To(BeTrue()) - }) - - It("Subscribe timeouts", func() { - if opt.WriteTimeout == 0 { - return - } - - pubsub := client.Subscribe() - defer pubsub.Close() - - err := pubsub.Subscribe("_") - Expect(err).To(HaveOccurred()) - Expect(err.(net.Error).Timeout()).To(BeTrue()) - }) - - It("Tx timeouts", func() { - err := client.Watch(func(tx *redis.Tx) error { - return tx.Ping().Err() - }) - Expect(err).To(HaveOccurred()) - Expect(err.(net.Error).Timeout()).To(BeTrue()) - }) - - It("Tx Pipeline timeouts", func() { - err := client.Watch(func(tx *redis.Tx) error { - _, err := tx.Pipelined(func(pipe redis.Pipeliner) error { - pipe.Ping() - return nil - }) - return err - }) - Expect(err).To(HaveOccurred()) - Expect(err.(net.Error).Timeout()).To(BeTrue()) - }) - } - - Context("read timeout", func() { - BeforeEach(func() { - opt = redisOptions() - opt.ReadTimeout = time.Nanosecond - opt.WriteTimeout = -1 - client = redis.NewClient(opt) - }) - - testTimeout() - }) - - Context("write timeout", func() { - BeforeEach(func() { - opt = redisOptions() - opt.ReadTimeout = -1 - opt.WriteTimeout = time.Nanosecond - client = redis.NewClient(opt) - }) - - testTimeout() - }) -}) - -var _ = Describe("Client OnConnect", func() { - var client *redis.Client - - BeforeEach(func() { - opt := redisOptions() - opt.DB = 0 - opt.OnConnect = func(cn *redis.Conn) error { - return cn.ClientSetName("on_connect").Err() - } - - client = redis.NewClient(opt) - }) - - AfterEach(func() { - Expect(client.Close()).NotTo(HaveOccurred()) - }) - - It("calls OnConnect", func() { - name, err := client.ClientGetName().Result() - Expect(err).NotTo(HaveOccurred()) - Expect(name).To(Equal("on_connect")) - }) -}) diff --git a/vendor/github.com/go-redis/redis/ring.go b/vendor/github.com/go-redis/redis/ring.go index 10f33ed00..6d2877413 100644 --- a/vendor/github.com/go-redis/redis/ring.go +++ b/vendor/github.com/go-redis/redis/ring.go @@ -1,6 +1,7 @@ package redis import ( + "context" "errors" "fmt" "math/rand" @@ -15,6 +16,8 @@ import ( "github.com/go-redis/redis/internal/pool" ) +const nreplicas = 100 + var errRingShardsDown = errors.New("redis: all ring shards are down") // RingOptions are used to configure a ring client and should be @@ -85,6 +88,8 @@ func (opt *RingOptions) clientOptions() *Options { } } +//------------------------------------------------------------------------------ + type ringShard struct { Client *Client down int32 @@ -125,6 +130,150 @@ func (shard *ringShard) Vote(up bool) bool { return shard.IsDown() } +//------------------------------------------------------------------------------ + +type ringShards struct { + mu sync.RWMutex + hash *consistenthash.Map + shards map[string]*ringShard // read only + list []*ringShard // read only + closed bool +} + +func newRingShards() *ringShards { + return &ringShards{ + hash: consistenthash.New(nreplicas, nil), + shards: make(map[string]*ringShard), + } +} + +func (c *ringShards) Add(name string, cl *Client) { + shard := &ringShard{Client: cl} + c.hash.Add(name) + c.shards[name] = shard + c.list = append(c.list, shard) +} + +func (c *ringShards) List() []*ringShard { + c.mu.RLock() + list := c.list + c.mu.RUnlock() + return list +} + +func (c *ringShards) Hash(key string) string { + c.mu.RLock() + hash := c.hash.Get(key) + c.mu.RUnlock() + return hash +} + +func (c *ringShards) GetByKey(key string) (*ringShard, error) { + key = hashtag.Key(key) + + c.mu.RLock() + + if c.closed { + c.mu.RUnlock() + return nil, pool.ErrClosed + } + + hash := c.hash.Get(key) + if hash == "" { + c.mu.RUnlock() + return nil, errRingShardsDown + } + + shard := c.shards[hash] + c.mu.RUnlock() + + return shard, nil +} + +func (c *ringShards) GetByHash(name string) (*ringShard, error) { + if name == "" { + return c.Random() + } + + c.mu.RLock() + shard := c.shards[name] + c.mu.RUnlock() + return shard, nil +} + +func (c *ringShards) Random() (*ringShard, error) { + return c.GetByKey(strconv.Itoa(rand.Int())) +} + +// heartbeat monitors state of each shard in the ring. +func (c *ringShards) Heartbeat(frequency time.Duration) { + ticker := time.NewTicker(frequency) + defer ticker.Stop() + for range ticker.C { + var rebalance bool + + c.mu.RLock() + + if c.closed { + c.mu.RUnlock() + break + } + + shards := c.list + c.mu.RUnlock() + + for _, shard := range shards { + err := shard.Client.Ping().Err() + if shard.Vote(err == nil || err == pool.ErrPoolTimeout) { + internal.Logf("ring shard state changed: %s", shard) + rebalance = true + } + } + + if rebalance { + c.rebalance() + } + } +} + +// rebalance removes dead shards from the Ring. +func (c *ringShards) rebalance() { + hash := consistenthash.New(nreplicas, nil) + for name, shard := range c.shards { + if shard.IsUp() { + hash.Add(name) + } + } + + c.mu.Lock() + c.hash = hash + c.mu.Unlock() +} + +func (c *ringShards) Close() error { + c.mu.Lock() + defer c.mu.Unlock() + + if c.closed { + return nil + } + c.closed = true + + var firstErr error + for _, shard := range c.shards { + if err := shard.Client.Close(); err != nil && firstErr == nil { + firstErr = err + } + } + c.hash = nil + c.shards = nil + c.list = nil + + return firstErr +} + +//------------------------------------------------------------------------------ + // Ring is a Redis client that uses constistent hashing to distribute // keys across multiple Redis servers (shards). It's safe for // concurrent use by multiple goroutines. @@ -142,33 +291,22 @@ func (shard *ringShard) Vote(up bool) bool { type Ring struct { cmdable - opt *RingOptions - nreplicas int + ctx context.Context - mu sync.RWMutex - hash *consistenthash.Map - shards map[string]*ringShard - shardsList []*ringShard + opt *RingOptions + shards *ringShards + cmdsInfoCache *cmdsInfoCache processPipeline func([]Cmder) error - - cmdsInfoOnce internal.Once - cmdsInfo map[string]*CommandInfo - - closed bool } func NewRing(opt *RingOptions) *Ring { - const nreplicas = 100 - opt.init() ring := &Ring{ - opt: opt, - nreplicas: nreplicas, - - hash: consistenthash.New(nreplicas, nil), - shards: make(map[string]*ringShard), + opt: opt, + shards: newRingShards(), + cmdsInfoCache: newCmdsInfoCache(), } ring.processPipeline = ring.defaultProcessPipeline ring.cmdable.setProcessor(ring.Process) @@ -176,21 +314,33 @@ func NewRing(opt *RingOptions) *Ring { for name, addr := range opt.Addrs { clopt := opt.clientOptions() clopt.Addr = addr - ring.addShard(name, NewClient(clopt)) + ring.shards.Add(name, NewClient(clopt)) } - go ring.heartbeat() + go ring.shards.Heartbeat(opt.HeartbeatFrequency) return ring } -func (c *Ring) addShard(name string, cl *Client) { - shard := &ringShard{Client: cl} - c.mu.Lock() - c.hash.Add(name) - c.shards[name] = shard - c.shardsList = append(c.shardsList, shard) - c.mu.Unlock() +func (c *Ring) Context() context.Context { + if c.ctx != nil { + return c.ctx + } + return context.Background() +} + +func (c *Ring) WithContext(ctx context.Context) *Ring { + if ctx == nil { + panic("nil context") + } + c2 := c.copy() + c2.ctx = ctx + return c2 +} + +func (c *Ring) copy() *Ring { + cp := *c + return &cp } // Options returns read-only Options that were used to create the client. @@ -204,10 +354,7 @@ func (c *Ring) retryBackoff(attempt int) time.Duration { // PoolStats returns accumulated connection pool stats. func (c *Ring) PoolStats() *PoolStats { - c.mu.RLock() - shards := c.shardsList - c.mu.RUnlock() - + shards := c.shards.List() var acc PoolStats for _, shard := range shards { s := shard.Client.connPool.Stats() @@ -226,7 +373,7 @@ func (c *Ring) Subscribe(channels ...string) *PubSub { panic("at least one channel is required") } - shard, err := c.shardByKey(channels[0]) + shard, err := c.shards.GetByKey(channels[0]) if err != nil { // TODO: return PubSub with sticky error panic(err) @@ -240,7 +387,7 @@ func (c *Ring) PSubscribe(channels ...string) *PubSub { panic("at least one channel is required") } - shard, err := c.shardByKey(channels[0]) + shard, err := c.shards.GetByKey(channels[0]) if err != nil { // TODO: return PubSub with sticky error panic(err) @@ -251,10 +398,7 @@ func (c *Ring) PSubscribe(channels ...string) *PubSub { // ForEachShard concurrently calls the fn on each live shard in the ring. // It returns the first error if any. func (c *Ring) ForEachShard(fn func(client *Client) error) error { - c.mu.RLock() - shards := c.shardsList - c.mu.RUnlock() - + shards := c.shards.List() var wg sync.WaitGroup errCh := make(chan error, 1) for _, shard := range shards { @@ -285,81 +429,38 @@ func (c *Ring) ForEachShard(fn func(client *Client) error) error { } func (c *Ring) cmdInfo(name string) *CommandInfo { - err := c.cmdsInfoOnce.Do(func() error { - c.mu.RLock() - shards := c.shardsList - c.mu.RUnlock() - - var firstErr error + cmdsInfo, err := c.cmdsInfoCache.Do(func() (map[string]*CommandInfo, error) { + shards := c.shards.List() + firstErr := errRingShardsDown for _, shard := range shards { cmdsInfo, err := shard.Client.Command().Result() if err == nil { - c.cmdsInfo = cmdsInfo - return nil + return cmdsInfo, nil } if firstErr == nil { firstErr = err } } - return firstErr + return nil, firstErr }) if err != nil { return nil } - if c.cmdsInfo == nil { - return nil - } - info := c.cmdsInfo[name] + info := cmdsInfo[name] if info == nil { internal.Logf("info for cmd=%s not found", name) } return info } -func (c *Ring) shardByKey(key string) (*ringShard, error) { - key = hashtag.Key(key) - - c.mu.RLock() - - if c.closed { - c.mu.RUnlock() - return nil, pool.ErrClosed - } - - name := c.hash.Get(key) - if name == "" { - c.mu.RUnlock() - return nil, errRingShardsDown - } - - shard := c.shards[name] - c.mu.RUnlock() - return shard, nil -} - -func (c *Ring) randomShard() (*ringShard, error) { - return c.shardByKey(strconv.Itoa(rand.Int())) -} - -func (c *Ring) shardByName(name string) (*ringShard, error) { - if name == "" { - return c.randomShard() - } - - c.mu.RLock() - shard := c.shards[name] - c.mu.RUnlock() - return shard, nil -} - func (c *Ring) cmdShard(cmd Cmder) (*ringShard, error) { cmdInfo := c.cmdInfo(cmd.Name()) pos := cmdFirstKeyPos(cmd, cmdInfo) if pos == 0 { - return c.randomShard() + return c.shards.Random() } firstKey := cmd.stringArg(pos) - return c.shardByKey(firstKey) + return c.shards.GetByKey(firstKey) } func (c *Ring) WrapProcess(fn func(oldProcess func(cmd Cmder) error) func(cmd Cmder) error) { @@ -378,77 +479,6 @@ func (c *Ring) Process(cmd Cmder) error { return shard.Client.Process(cmd) } -// rebalance removes dead shards from the Ring. -func (c *Ring) rebalance() { - hash := consistenthash.New(c.nreplicas, nil) - for name, shard := range c.shards { - if shard.IsUp() { - hash.Add(name) - } - } - - c.mu.Lock() - c.hash = hash - c.mu.Unlock() -} - -// heartbeat monitors state of each shard in the ring. -func (c *Ring) heartbeat() { - ticker := time.NewTicker(c.opt.HeartbeatFrequency) - defer ticker.Stop() - for range ticker.C { - var rebalance bool - - c.mu.RLock() - - if c.closed { - c.mu.RUnlock() - break - } - - shards := c.shardsList - c.mu.RUnlock() - - for _, shard := range shards { - err := shard.Client.Ping().Err() - if shard.Vote(err == nil || err == pool.ErrPoolTimeout) { - internal.Logf("ring shard state changed: %s", shard) - rebalance = true - } - } - - if rebalance { - c.rebalance() - } - } -} - -// Close closes the ring client, releasing any open resources. -// -// It is rare to Close a Ring, as the Ring is meant to be long-lived -// and shared between many goroutines. -func (c *Ring) Close() error { - c.mu.Lock() - defer c.mu.Unlock() - - if c.closed { - return nil - } - c.closed = true - - var firstErr error - for _, shard := range c.shards { - if err := shard.Client.Close(); err != nil && firstErr == nil { - firstErr = err - } - } - c.hash = nil - c.shards = nil - c.shardsList = nil - - return firstErr -} - func (c *Ring) Pipeline() Pipeliner { pipe := Pipeline{ exec: c.processPipeline, @@ -471,11 +501,11 @@ func (c *Ring) defaultProcessPipeline(cmds []Cmder) error { cmdsMap := make(map[string][]Cmder) for _, cmd := range cmds { cmdInfo := c.cmdInfo(cmd.Name()) - name := cmd.stringArg(cmdFirstKeyPos(cmd, cmdInfo)) - if name != "" { - name = c.hash.Get(hashtag.Key(name)) + hash := cmd.stringArg(cmdFirstKeyPos(cmd, cmdInfo)) + if hash != "" { + hash = c.shards.Hash(hashtag.Key(hash)) } - cmdsMap[name] = append(cmdsMap[name], cmd) + cmdsMap[hash] = append(cmdsMap[hash], cmd) } for attempt := 0; attempt <= c.opt.MaxRetries; attempt++ { @@ -485,8 +515,8 @@ func (c *Ring) defaultProcessPipeline(cmds []Cmder) error { var failedCmdsMap map[string][]Cmder - for name, cmds := range cmdsMap { - shard, err := c.shardByName(name) + for hash, cmds := range cmdsMap { + shard, err := c.shards.GetByHash(hash) if err != nil { setCmdsErr(cmds, err) continue @@ -509,7 +539,7 @@ func (c *Ring) defaultProcessPipeline(cmds []Cmder) error { if failedCmdsMap == nil { failedCmdsMap = make(map[string][]Cmder) } - failedCmdsMap[name] = cmds + failedCmdsMap[hash] = cmds } } @@ -529,3 +559,11 @@ func (c *Ring) TxPipeline() Pipeliner { func (c *Ring) TxPipelined(fn func(Pipeliner) error) ([]Cmder, error) { panic("not implemented") } + +// Close closes the ring client, releasing any open resources. +// +// It is rare to Close a Ring, as the Ring is meant to be long-lived +// and shared between many goroutines. +func (c *Ring) Close() error { + return c.shards.Close() +} diff --git a/vendor/github.com/go-redis/redis/ring_test.go b/vendor/github.com/go-redis/redis/ring_test.go deleted file mode 100644 index 0cad4298b..000000000 --- a/vendor/github.com/go-redis/redis/ring_test.go +++ /dev/null @@ -1,193 +0,0 @@ -package redis_test - -import ( - "crypto/rand" - "fmt" - "time" - - "github.com/go-redis/redis" - - . "github.com/onsi/ginkgo" - . "github.com/onsi/gomega" -) - -var _ = Describe("Redis Ring", func() { - const heartbeat = 100 * time.Millisecond - - var ring *redis.Ring - - setRingKeys := func() { - for i := 0; i < 100; i++ { - err := ring.Set(fmt.Sprintf("key%d", i), "value", 0).Err() - Expect(err).NotTo(HaveOccurred()) - } - } - - BeforeEach(func() { - opt := redisRingOptions() - opt.HeartbeatFrequency = heartbeat - ring = redis.NewRing(opt) - - err := ring.ForEachShard(func(cl *redis.Client) error { - return cl.FlushDB().Err() - }) - Expect(err).NotTo(HaveOccurred()) - }) - - AfterEach(func() { - Expect(ring.Close()).NotTo(HaveOccurred()) - }) - - It("distributes keys", func() { - setRingKeys() - - // Both shards should have some keys now. - Expect(ringShard1.Info().Val()).To(ContainSubstring("keys=57")) - Expect(ringShard2.Info().Val()).To(ContainSubstring("keys=43")) - }) - - It("distributes keys when using EVAL", func() { - script := redis.NewScript(` - local r = redis.call('SET', KEYS[1], ARGV[1]) - return r - `) - - var key string - for i := 0; i < 100; i++ { - key = fmt.Sprintf("key%d", i) - err := script.Run(ring, []string{key}, "value").Err() - Expect(err).NotTo(HaveOccurred()) - } - - Expect(ringShard1.Info().Val()).To(ContainSubstring("keys=57")) - Expect(ringShard2.Info().Val()).To(ContainSubstring("keys=43")) - }) - - It("uses single shard when one of the shards is down", func() { - // Stop ringShard2. - Expect(ringShard2.Close()).NotTo(HaveOccurred()) - - // Ring needs 3 * heartbeat time to detect that node is down. - // Give it more to be sure. - time.Sleep(2 * 3 * heartbeat) - - setRingKeys() - - // RingShard1 should have all keys. - Expect(ringShard1.Info().Val()).To(ContainSubstring("keys=100")) - - // Start ringShard2. - var err error - ringShard2, err = startRedis(ringShard2Port) - Expect(err).NotTo(HaveOccurred()) - - // Wait for ringShard2 to come up. - Eventually(func() error { - return ringShard2.Ping().Err() - }, "1s").ShouldNot(HaveOccurred()) - - // Ring needs heartbeat time to detect that node is up. - // Give it more to be sure. - time.Sleep(heartbeat + heartbeat) - - setRingKeys() - - // RingShard2 should have its keys. - Expect(ringShard2.Info().Val()).To(ContainSubstring("keys=43")) - }) - - It("supports hash tags", func() { - for i := 0; i < 100; i++ { - err := ring.Set(fmt.Sprintf("key%d{tag}", i), "value", 0).Err() - Expect(err).NotTo(HaveOccurred()) - } - - Expect(ringShard1.Info().Val()).ToNot(ContainSubstring("keys=")) - Expect(ringShard2.Info().Val()).To(ContainSubstring("keys=100")) - }) - - Describe("pipeline", func() { - It("distributes keys", func() { - pipe := ring.Pipeline() - for i := 0; i < 100; i++ { - err := pipe.Set(fmt.Sprintf("key%d", i), "value", 0).Err() - Expect(err).NotTo(HaveOccurred()) - } - cmds, err := pipe.Exec() - Expect(err).NotTo(HaveOccurred()) - Expect(cmds).To(HaveLen(100)) - Expect(pipe.Close()).NotTo(HaveOccurred()) - - for _, cmd := range cmds { - Expect(cmd.Err()).NotTo(HaveOccurred()) - Expect(cmd.(*redis.StatusCmd).Val()).To(Equal("OK")) - } - - // Both shards should have some keys now. - Expect(ringShard1.Info().Val()).To(ContainSubstring("keys=57")) - Expect(ringShard2.Info().Val()).To(ContainSubstring("keys=43")) - }) - - It("is consistent with ring", func() { - var keys []string - for i := 0; i < 100; i++ { - key := make([]byte, 64) - _, err := rand.Read(key) - Expect(err).NotTo(HaveOccurred()) - keys = append(keys, string(key)) - } - - _, err := ring.Pipelined(func(pipe redis.Pipeliner) error { - for _, key := range keys { - pipe.Set(key, "value", 0).Err() - } - return nil - }) - Expect(err).NotTo(HaveOccurred()) - - for _, key := range keys { - val, err := ring.Get(key).Result() - Expect(err).NotTo(HaveOccurred()) - Expect(val).To(Equal("value")) - } - }) - - It("supports hash tags", func() { - _, err := ring.Pipelined(func(pipe redis.Pipeliner) error { - for i := 0; i < 100; i++ { - pipe.Set(fmt.Sprintf("key%d{tag}", i), "value", 0).Err() - } - return nil - }) - Expect(err).NotTo(HaveOccurred()) - - Expect(ringShard1.Info().Val()).ToNot(ContainSubstring("keys=")) - Expect(ringShard2.Info().Val()).To(ContainSubstring("keys=100")) - }) - }) -}) - -var _ = Describe("empty Redis Ring", func() { - var ring *redis.Ring - - BeforeEach(func() { - ring = redis.NewRing(&redis.RingOptions{}) - }) - - AfterEach(func() { - Expect(ring.Close()).NotTo(HaveOccurred()) - }) - - It("returns an error", func() { - err := ring.Ping().Err() - Expect(err).To(MatchError("redis: all ring shards are down")) - }) - - It("pipeline returns an error", func() { - _, err := ring.Pipelined(func(pipe redis.Pipeliner) error { - pipe.Ping() - return nil - }) - Expect(err).To(MatchError("redis: all ring shards are down")) - }) -}) diff --git a/vendor/github.com/go-redis/redis/script.go b/vendor/github.com/go-redis/redis/script.go index 74135f5a5..09f36d932 100644 --- a/vendor/github.com/go-redis/redis/script.go +++ b/vendor/github.com/go-redis/redis/script.go @@ -10,7 +10,7 @@ import ( type scripter interface { Eval(script string, keys []string, args ...interface{}) *Cmd EvalSha(sha1 string, keys []string, args ...interface{}) *Cmd - ScriptExists(scripts ...string) *BoolSliceCmd + ScriptExists(hashes ...string) *BoolSliceCmd ScriptLoad(script string) *StringCmd } @@ -40,7 +40,7 @@ func (s *Script) Load(c scripter) *StringCmd { } func (s *Script) Exists(c scripter) *BoolSliceCmd { - return c.ScriptExists(s.src) + return c.ScriptExists(s.hash) } func (s *Script) Eval(c scripter, keys []string, args ...interface{}) *Cmd { diff --git a/vendor/github.com/go-redis/redis/sentinel_test.go b/vendor/github.com/go-redis/redis/sentinel_test.go deleted file mode 100644 index c67713cd0..000000000 --- a/vendor/github.com/go-redis/redis/sentinel_test.go +++ /dev/null @@ -1,88 +0,0 @@ -package redis_test - -import ( - "github.com/go-redis/redis" - - . "github.com/onsi/ginkgo" - . "github.com/onsi/gomega" -) - -var _ = Describe("Sentinel", func() { - var client *redis.Client - - BeforeEach(func() { - client = redis.NewFailoverClient(&redis.FailoverOptions{ - MasterName: sentinelName, - SentinelAddrs: []string{":" + sentinelPort}, - }) - Expect(client.FlushDB().Err()).NotTo(HaveOccurred()) - }) - - AfterEach(func() { - Expect(client.Close()).NotTo(HaveOccurred()) - }) - - It("should facilitate failover", func() { - // Set value on master. - err := client.Set("foo", "master", 0).Err() - Expect(err).NotTo(HaveOccurred()) - - // Verify. - val, err := sentinelMaster.Get("foo").Result() - Expect(err).NotTo(HaveOccurred()) - Expect(val).To(Equal("master")) - - // Create subscription. - ch := client.Subscribe("foo").Channel() - - // Wait until replicated. - Eventually(func() string { - return sentinelSlave1.Get("foo").Val() - }, "1s", "100ms").Should(Equal("master")) - Eventually(func() string { - return sentinelSlave2.Get("foo").Val() - }, "1s", "100ms").Should(Equal("master")) - - // Wait until slaves are picked up by sentinel. - Eventually(func() string { - return sentinel.Info().Val() - }, "10s", "100ms").Should(ContainSubstring("slaves=2")) - - // Kill master. - sentinelMaster.Shutdown() - Eventually(func() error { - return sentinelMaster.Ping().Err() - }, "5s", "100ms").Should(HaveOccurred()) - - // Wait for Redis sentinel to elect new master. - Eventually(func() string { - return sentinelSlave1.Info().Val() + sentinelSlave2.Info().Val() - }, "30s", "1s").Should(ContainSubstring("role:master")) - - // Check that client picked up new master. - Eventually(func() error { - return client.Get("foo").Err() - }, "5s", "100ms").ShouldNot(HaveOccurred()) - - // Publish message to check if subscription is renewed. - err = client.Publish("foo", "hello").Err() - Expect(err).NotTo(HaveOccurred()) - - var msg *redis.Message - Eventually(ch).Should(Receive(&msg)) - Expect(msg.Channel).To(Equal("foo")) - Expect(msg.Payload).To(Equal("hello")) - }) - - It("supports DB selection", func() { - Expect(client.Close()).NotTo(HaveOccurred()) - - client = redis.NewFailoverClient(&redis.FailoverOptions{ - MasterName: sentinelName, - SentinelAddrs: []string{":" + sentinelPort}, - DB: 1, - }) - err := client.Ping().Err() - Expect(err).NotTo(HaveOccurred()) - }) -}) diff --git a/vendor/github.com/go-redis/redis/testdata/redis.conf b/vendor/github.com/go-redis/redis/testdata/redis.conf deleted file mode 100644 index 235b2954a..000000000 --- a/vendor/github.com/go-redis/redis/testdata/redis.conf +++ /dev/null @@ -1,10 +0,0 @@ -# Minimal redis.conf - -port 6379 -daemonize no -dir . -save "" -appendonly yes -cluster-config-file nodes.conf -cluster-node-timeout 30000 -maxclients 1001
\ No newline at end of file diff --git a/vendor/github.com/go-redis/redis/tx.go b/vendor/github.com/go-redis/redis/tx.go index 26c29bef5..6a753b6a0 100644 --- a/vendor/github.com/go-redis/redis/tx.go +++ b/vendor/github.com/go-redis/redis/tx.go @@ -1,12 +1,12 @@ package redis import ( - "github.com/go-redis/redis/internal" "github.com/go-redis/redis/internal/pool" + "github.com/go-redis/redis/internal/proto" ) // TxFailedErr transaction redis failed. -const TxFailedErr = internal.RedisError("redis: transaction failed") +const TxFailedErr = proto.RedisError("redis: transaction failed") // Tx implements Redis transactions as described in // http://redis.io/topics/transactions. It's NOT safe for concurrent use diff --git a/vendor/github.com/go-redis/redis/tx_test.go b/vendor/github.com/go-redis/redis/tx_test.go deleted file mode 100644 index de597ff06..000000000 --- a/vendor/github.com/go-redis/redis/tx_test.go +++ /dev/null @@ -1,151 +0,0 @@ -package redis_test - -import ( - "strconv" - "sync" - - "github.com/go-redis/redis" - - . "github.com/onsi/ginkgo" - . "github.com/onsi/gomega" -) - -var _ = Describe("Tx", func() { - var client *redis.Client - - BeforeEach(func() { - client = redis.NewClient(redisOptions()) - Expect(client.FlushDB().Err()).NotTo(HaveOccurred()) - }) - - AfterEach(func() { - Expect(client.Close()).NotTo(HaveOccurred()) - }) - - It("should Watch", func() { - var incr func(string) error - - // Transactionally increments key using GET and SET commands. - incr = func(key string) error { - err := client.Watch(func(tx *redis.Tx) error { - n, err := tx.Get(key).Int64() - if err != nil && err != redis.Nil { - return err - } - - _, err = tx.Pipelined(func(pipe redis.Pipeliner) error { - pipe.Set(key, strconv.FormatInt(n+1, 10), 0) - return nil - }) - return err - }, key) - if err == redis.TxFailedErr { - return incr(key) - } - return err - } - - var wg sync.WaitGroup - for i := 0; i < 100; i++ { - wg.Add(1) - go func() { - defer GinkgoRecover() - defer wg.Done() - - err := incr("key") - Expect(err).NotTo(HaveOccurred()) - }() - } - wg.Wait() - - n, err := client.Get("key").Int64() - Expect(err).NotTo(HaveOccurred()) - Expect(n).To(Equal(int64(100))) - }) - - It("should discard", func() { - err := client.Watch(func(tx *redis.Tx) error { - cmds, err := tx.Pipelined(func(pipe redis.Pipeliner) error { - pipe.Set("key1", "hello1", 0) - pipe.Discard() - pipe.Set("key2", "hello2", 0) - return nil - }) - Expect(err).NotTo(HaveOccurred()) - Expect(cmds).To(HaveLen(1)) - return err - }, "key1", "key2") - Expect(err).NotTo(HaveOccurred()) - - get := client.Get("key1") - Expect(get.Err()).To(Equal(redis.Nil)) - Expect(get.Val()).To(Equal("")) - - get = client.Get("key2") - Expect(get.Err()).NotTo(HaveOccurred()) - Expect(get.Val()).To(Equal("hello2")) - }) - - It("returns no error when there are no commands", func() { - err := client.Watch(func(tx *redis.Tx) error { - _, err := tx.Pipelined(func(redis.Pipeliner) error { return nil }) - return err - }) - Expect(err).NotTo(HaveOccurred()) - - v, err := client.Ping().Result() - Expect(err).NotTo(HaveOccurred()) - Expect(v).To(Equal("PONG")) - }) - - It("should exec bulks", func() { - const N = 20000 - - err := client.Watch(func(tx *redis.Tx) error { - cmds, err := tx.Pipelined(func(pipe redis.Pipeliner) error { - for i := 0; i < N; i++ { - pipe.Incr("key") - } - return nil - }) - Expect(err).NotTo(HaveOccurred()) - Expect(len(cmds)).To(Equal(N)) - for _, cmd := range cmds { - Expect(cmd.Err()).NotTo(HaveOccurred()) - } - return err - }) - Expect(err).NotTo(HaveOccurred()) - - num, err := client.Get("key").Int64() - Expect(err).NotTo(HaveOccurred()) - Expect(num).To(Equal(int64(N))) - }) - - It("should recover from bad connection", func() { - // Put bad connection in the pool. - cn, _, err := client.Pool().Get() - Expect(err).NotTo(HaveOccurred()) - - cn.SetNetConn(&badConn{}) - err = client.Pool().Put(cn) - Expect(err).NotTo(HaveOccurred()) - - do := func() error { - err := client.Watch(func(tx *redis.Tx) error { - _, err := tx.Pipelined(func(pipe redis.Pipeliner) error { - pipe.Ping() - return nil - }) - return err - }) - return err - } - - err = do() - Expect(err).To(MatchError("bad connection")) - - err = do() - Expect(err).NotTo(HaveOccurred()) - }) -}) diff --git a/vendor/github.com/go-redis/redis/universal.go b/vendor/github.com/go-redis/redis/universal.go index ea42f6984..fde3c4150 100644 --- a/vendor/github.com/go-redis/redis/universal.go +++ b/vendor/github.com/go-redis/redis/universal.go @@ -114,6 +114,7 @@ func (o *UniversalOptions) simple() *Options { type UniversalClient interface { Cmdable Process(cmd Cmder) error + WrapProcess(fn func(oldProcess func(cmd Cmder) error) func(cmd Cmder) error) Subscribe(channels ...string) *PubSub PSubscribe(channels ...string) *PubSub Close() error diff --git a/vendor/github.com/go-redis/redis/universal_test.go b/vendor/github.com/go-redis/redis/universal_test.go deleted file mode 100644 index 2a0850dea..000000000 --- a/vendor/github.com/go-redis/redis/universal_test.go +++ /dev/null @@ -1,41 +0,0 @@ -package redis_test - -import ( - . "github.com/onsi/ginkgo" - . "github.com/onsi/gomega" - - "github.com/go-redis/redis" -) - -var _ = Describe("UniversalClient", func() { - var client redis.UniversalClient - - AfterEach(func() { - if client != nil { - Expect(client.Close()).To(Succeed()) - } - }) - - It("should connect to failover servers", func() { - client = redis.NewUniversalClient(&redis.UniversalOptions{ - MasterName: sentinelName, - Addrs: []string{":" + sentinelPort}, - }) - Expect(client.Ping().Err()).NotTo(HaveOccurred()) - }) - - It("should connect to simple servers", func() { - client = redis.NewUniversalClient(&redis.UniversalOptions{ - Addrs: []string{redisAddr}, - }) - Expect(client.Ping().Err()).NotTo(HaveOccurred()) - }) - - It("should connect to clusters", func() { - client = redis.NewUniversalClient(&redis.UniversalOptions{ - Addrs: cluster.addrs(), - }) - Expect(client.Ping().Err()).NotTo(HaveOccurred()) - }) - -}) |