Skip to content

Commit e3d9f9d

Browse files
authored
Merge pull request #768 from go-redis/fix/for-each-reload-state
cluster: reload state for ForEach functions and every 1 minute
2 parents a8ab4b9 + 471caa3 commit e3d9f9d

File tree

1 file changed

+35
-17
lines changed

1 file changed

+35
-17
lines changed

cluster.go

Lines changed: 35 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -391,16 +391,19 @@ type clusterState struct {
391391
slots [][]*clusterNode
392392

393393
generation uint32
394+
createdAt time.Time
394395
}
395396

396397
func newClusterState(
397398
nodes *clusterNodes, slots []ClusterSlot, origin string,
398399
) (*clusterState, error) {
399400
c := clusterState{
400-
nodes: nodes,
401-
generation: nodes.NextGeneration(),
401+
nodes: nodes,
402402

403403
slots: make([][]*clusterNode, hashtag.SlotNumber),
404+
405+
generation: nodes.NextGeneration(),
406+
createdAt: time.Now(),
404407
}
405408

406409
isLoopbackOrigin := isLoopbackAddr(origin)
@@ -534,8 +537,8 @@ type clusterStateHolder struct {
534537

535538
state atomic.Value
536539

537-
lastErrMu sync.RWMutex
538-
lastErr error
540+
firstErrMu sync.RWMutex
541+
firstErr error
539542

540543
reloading uint32 // atomic
541544
}
@@ -560,9 +563,11 @@ func (c *clusterStateHolder) Reload() (*clusterState, error) {
560563
func (c *clusterStateHolder) reload() (*clusterState, error) {
561564
state, err := c.load()
562565
if err != nil {
563-
c.lastErrMu.Lock()
564-
c.lastErr = err
565-
c.lastErrMu.Unlock()
566+
c.firstErrMu.Lock()
567+
if c.firstErr == nil {
568+
c.firstErr = err
569+
}
570+
c.firstErrMu.Unlock()
566571
return nil, err
567572
}
568573
c.state.Store(state)
@@ -592,12 +597,16 @@ func (c *clusterStateHolder) LazyReload() {
592597
func (c *clusterStateHolder) Get() (*clusterState, error) {
593598
v := c.state.Load()
594599
if v != nil {
595-
return v.(*clusterState), nil
600+
state := v.(*clusterState)
601+
if time.Since(state.createdAt) > time.Minute {
602+
c.LazyReload()
603+
}
604+
return state, nil
596605
}
597606

598-
c.lastErrMu.RLock()
599-
err := c.lastErr
600-
c.lastErrMu.RUnlock()
607+
c.firstErrMu.RLock()
608+
err := c.firstErr
609+
c.firstErrMu.RUnlock()
601610
if err != nil {
602611
return nil, err
603612
}
@@ -930,9 +939,12 @@ func (c *ClusterClient) defaultProcess(cmd Cmder) error {
930939
// ForEachMaster concurrently calls the fn on each master node in the cluster.
931940
// It returns the first error if any.
932941
func (c *ClusterClient) ForEachMaster(fn func(client *Client) error) error {
933-
state, err := c.state.Get()
942+
state, err := c.state.Reload()
934943
if err != nil {
935-
return err
944+
state, err = c.state.Get()
945+
if err != nil {
946+
return err
947+
}
936948
}
937949

938950
var wg sync.WaitGroup
@@ -963,9 +975,12 @@ func (c *ClusterClient) ForEachMaster(fn func(client *Client) error) error {
963975
// ForEachSlave concurrently calls the fn on each slave node in the cluster.
964976
// It returns the first error if any.
965977
func (c *ClusterClient) ForEachSlave(fn func(client *Client) error) error {
966-
state, err := c.state.Get()
978+
state, err := c.state.Reload()
967979
if err != nil {
968-
return err
980+
state, err = c.state.Get()
981+
if err != nil {
982+
return err
983+
}
969984
}
970985

971986
var wg sync.WaitGroup
@@ -996,9 +1011,12 @@ func (c *ClusterClient) ForEachSlave(fn func(client *Client) error) error {
9961011
// ForEachNode concurrently calls the fn on each known node in the cluster.
9971012
// It returns the first error if any.
9981013
func (c *ClusterClient) ForEachNode(fn func(client *Client) error) error {
999-
state, err := c.state.Get()
1014+
state, err := c.state.Reload()
10001015
if err != nil {
1001-
return err
1016+
state, err = c.state.Get()
1017+
if err != nil {
1018+
return err
1019+
}
10021020
}
10031021

10041022
var wg sync.WaitGroup

0 commit comments

Comments
 (0)