| 983 | } |
| 984 | |
| 985 | func (c *sentinelFailover) replicaAddrs(ctx context.Context, useDisconnected bool) ([]string, error) { |
| 986 | c.mu.RLock() |
| 987 | sentinel := c.sentinel |
| 988 | c.mu.RUnlock() |
| 989 | |
| 990 | if sentinel != nil { |
| 991 | addrs, err := c.getReplicaAddrs(ctx, sentinel) |
| 992 | if err != nil { |
| 993 | if isContextError(ctx.Err()) { |
| 994 | return nil, err |
| 995 | } |
| 996 | // Continue on other errors |
| 997 | internal.Logger.Printf(ctx, "sentinel: Replicas name=%q failed: %s", |
| 998 | c.opt.MasterName, err) |
| 999 | } else if len(addrs) > 0 { |
| 1000 | return addrs, nil |
| 1001 | } |
| 1002 | } |
| 1003 | |
| 1004 | c.mu.Lock() |
| 1005 | defer c.mu.Unlock() |
| 1006 | |
| 1007 | if c.sentinel != nil { |
| 1008 | addrs, err := c.getReplicaAddrs(ctx, c.sentinel) |
| 1009 | if err != nil { |
| 1010 | _ = c.closeSentinel() |
| 1011 | if isContextError(ctx.Err()) { |
| 1012 | return nil, err |
| 1013 | } |
| 1014 | // Continue on other errors |
| 1015 | internal.Logger.Printf(ctx, "sentinel: Replicas name=%q failed: %s", |
| 1016 | c.opt.MasterName, err) |
| 1017 | } else if len(addrs) > 0 { |
| 1018 | return addrs, nil |
| 1019 | } else if !useDisconnected { |
| 1020 | // No error and no replicas — valid steady state for master-only setups. |
| 1021 | // Preserve the sentinel connection for master discovery and failover |
| 1022 | // pub/sub monitoring. Only return early when useDisconnected is false; |
| 1023 | // when true, fall through to the discovery loop which passes |
| 1024 | // useDisconnected to parseReplicaAddrs (getReplicaAddrs hardcodes false). |
| 1025 | return []string{}, nil |
| 1026 | } else { |
| 1027 | // useDisconnected=true: close sentinel so the discovery loop can call |
| 1028 | // setSentinel if it finds disconnected replicas. |
| 1029 | _ = c.closeSentinel() |
| 1030 | } |
| 1031 | } |
| 1032 | |
| 1033 | var sentinelReachable bool |
| 1034 | |
| 1035 | for i, sentinelAddr := range c.sentinelAddrs { |
| 1036 | sentinel := NewSentinelClient(c.opt.sentinelOptions(sentinelAddr)) |
| 1037 | |
| 1038 | replicas, err := sentinel.Replicas(ctx, c.opt.MasterName).Result() |
| 1039 | if err != nil { |
| 1040 | _ = sentinel.Close() |
| 1041 | if isContextError(ctx.Err()) { |
| 1042 | return nil, err |