1
0
mirror of https://github.com/redis/go-redis.git synced 2025-08-07 12:42:55 +03:00

Fix cmd info race. Fixes #578

This commit is contained in:
Vladimir Mihailenco
2017-06-17 12:34:39 +03:00
parent eb066030c0
commit 5132e15c93
3 changed files with 39 additions and 18 deletions

View File

@@ -7,6 +7,8 @@ import (
"sync/atomic"
"time"
"go4.org/syncutil"
"github.com/go-redis/redis/internal"
"github.com/go-redis/redis/internal/hashtag"
"github.com/go-redis/redis/internal/pool"
@@ -335,10 +337,12 @@ type ClusterClient struct {
cmdable
opt *ClusterOptions
cmds map[string]*CommandInfo
nodes *clusterNodes
_state atomic.Value
cmdsInfoOnce syncutil.Once
cmdsInfo map[string]*CommandInfo
// Reports where slots reloading is in progress.
reloading uint32
}
@@ -389,13 +393,34 @@ func (c *ClusterClient) state() *clusterState {
return nil
}
func (c *ClusterClient) cmdInfo(name string) *CommandInfo {
err := c.cmdsInfoOnce.Do(func() error {
node, err := c.nodes.Random()
if err != nil {
return err
}
cmdsInfo, err := node.Client.Command().Result()
if err != nil {
return err
}
c.cmdsInfo = cmdsInfo
return nil
})
if err != nil {
return nil
}
return c.cmdsInfo[name]
}
func (c *ClusterClient) cmdSlotAndNode(state *clusterState, cmd Cmder) (int, *clusterNode, error) {
if state == nil {
node, err := c.nodes.Random()
return 0, node, err
}
cmdInfo := c.cmds[cmd.Name()]
cmdInfo := c.cmdInfo(cmd.Name())
firstKey := cmd.arg(cmdFirstKeyPos(cmd, cmdInfo))
slot := hashtag.Slot(firstKey)
@@ -631,15 +656,6 @@ func (c *ClusterClient) reloadSlots() (*clusterState, error) {
return nil, err
}
// TODO: fix race
if c.cmds == nil {
cmds, err := node.Client.Command().Result()
if err != nil {
return nil, err
}
c.cmds = cmds
}
slots, err := node.Client.ClusterSlots().Result()
if err != nil {
return nil, err