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:
38
cluster.go
38
cluster.go
@@ -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
|
||||
|
Reference in New Issue
Block a user