Skip to content

Commit

Permalink
redisc: implement SplitBySlot
Browse files Browse the repository at this point in the history
  • Loading branch information
mna committed Mar 22, 2016
1 parent a7a0134 commit e25a089
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 3 deletions.
9 changes: 7 additions & 2 deletions cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -178,15 +178,20 @@ func (c *Cluster) populateNodes() {
// pool, even if Cluster.CreatePool is set. The actual returned
// type is *redisc.Conn, see its documentation for details.
func (c *Cluster) Dial() (redis.Conn, error) {
return nil, nil
return &Conn{
cluster: c,
forceDial: true,
}, nil
}

// Get returns a redis.Conn interface that can be used to call
// redis commands on the cluster. The application must close the
// returned connection. The actual returned type is *redisc.Conn,
// see its documentation for details.
func (c *Cluster) Get() redis.Conn {
return nil
return &Conn{
cluster: c,
}
}

// Close releases the resources used by the cluster. It closes all the
Expand Down
33 changes: 32 additions & 1 deletion hash.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
package redisc

import "strings"
import (
"sort"
"strings"
)

// Slot returns the hash slot for the key.
func Slot(key string) int {
Expand All @@ -12,3 +15,31 @@ func Slot(key string) int {
}
return int(crc16(key) % hashSlots)
}

// SplitBySlot takes a list of keys and returns a list of list of keys,
// separated by cluster slot. For example:
//
// bySlot := SplitBySlot("k1", "k2", "k3")
// for _, keys := range bySlot {
// // keys is a list of keys that belong to the same slot
// }
func SplitBySlot(keys ...string) [][]string {
var slots []int
m := make(map[int][]string)
for _, k := range keys {
slot := Slot(k)
_, ok := m[slot]
m[slot] = append(m[slot], k)

if !ok {
slots = append(slots, slot)
}
}

sort.Ints(slots)
bySlot := make([][]string, 0, len(m))
for _, slot := range slots {
bySlot = append(bySlot, m[slot])
}
return bySlot
}
32 changes: 32 additions & 0 deletions hash_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package redisc

import (
"strings"
"testing"

"github.com/stretchr/testify/assert"
Expand Down Expand Up @@ -41,3 +42,34 @@ func TestSlot(t *testing.T) {
assert.Equal(t, c.out, got, c.in)
}
}

func TestSplitBySlot(t *testing.T) {
cases := []struct {
// join/split by comma, for convenience
in string
out []string
}{
{"", nil},
{"a", []string{"a"}},
{"a,b", []string{"b", "a"}},
{"a,b,cb{a}", []string{"b", "a,cb{a}"}},
{"a,b,cb{a},a{b}", []string{"b,a{b}", "a,cb{a}"}},
{"a,b,cb{a},a{b},abc", []string{"b,a{b}", "abc", "a,cb{a}"}},
}

for _, c := range cases {
args := strings.Split(c.in, ",")
if c.in == "" {
args = nil
}
got := SplitBySlot(args...)

exp := make([][]string, len(c.out))
for i, o := range c.out {
exp[i] = strings.Split(o, ",")
}

assert.Equal(t, exp, got, c.in)
t.Logf("%#v", got)
}
}

0 comments on commit e25a089

Please sign in to comment.