diff --git a/cluster.go b/cluster.go index 941838dd..6c47dccc 100644 --- a/cluster.go +++ b/cluster.go @@ -936,7 +936,7 @@ func (c *ClusterClient) process(ctx context.Context, cmd Cmder) error { if lastErr == nil { return nil } - if isReadOnly := isReadOnlyError(lastErr); isReadOnly || lastErr == pool.ErrClosed { + if isReadOnly := IsReadOnlyError(lastErr); isReadOnly || lastErr == pool.ErrClosed { if isReadOnly { c.state.LazyReload() } @@ -1620,7 +1620,7 @@ func (c *ClusterClient) Watch(ctx context.Context, fn func(*Tx) error, keys ...s continue } - if isReadOnly := isReadOnlyError(err); isReadOnly || err == pool.ErrClosed { + if isReadOnly := IsReadOnlyError(err); isReadOnly || err == pool.ErrClosed { if isReadOnly { c.state.LazyReload() } diff --git a/error.go b/error.go index d5ebad60..91163814 100644 --- a/error.go +++ b/error.go @@ -58,7 +58,7 @@ func shouldRetry(err error, retryTimeout bool) bool { if strings.HasPrefix(s, "LOADING ") { return true } - if strings.HasPrefix(s, "READONLY ") { + if IsReadOnlyError(err) { return true } if strings.HasPrefix(s, "CLUSTERDOWN ") { @@ -86,7 +86,7 @@ func isBadConn(err error, allowTimeout bool, addr string) bool { if isRedisError(err) { switch { - case isReadOnlyError(err): + case IsReadOnlyError(err): // Close connections in read only state in case domain addr is used // and domain resolves to a different Redis Server. See #790. return true @@ -136,8 +136,15 @@ func isLoadingError(err error) bool { return strings.HasPrefix(err.Error(), "LOADING ") } -func isReadOnlyError(err error) bool { - return strings.HasPrefix(err.Error(), "READONLY ") +func IsReadOnlyError(err error) bool { + redisError := err.Error() + if strings.HasPrefix(redisError, "READONLY ") { + return true + } + + // For a Lua script that includes write commands, the read-only error string + // contains "-READONLY" rather than beginning with "READONLY " + return strings.Contains(redisError, "-READONLY") } func isMovedSameConnAddr(err error, addr string) bool {