diff options
Diffstat (limited to '')
-rw-r--r-- | dependencies/pkg/mod/github.com/go-redis/redis/v8@v8.11.5/error.go | 144 |
1 files changed, 144 insertions, 0 deletions
diff --git a/dependencies/pkg/mod/github.com/go-redis/redis/v8@v8.11.5/error.go b/dependencies/pkg/mod/github.com/go-redis/redis/v8@v8.11.5/error.go new file mode 100644 index 0000000..521594b --- /dev/null +++ b/dependencies/pkg/mod/github.com/go-redis/redis/v8@v8.11.5/error.go @@ -0,0 +1,144 @@ +package redis + +import ( + "context" + "io" + "net" + "strings" + + "github.com/go-redis/redis/v8/internal/pool" + "github.com/go-redis/redis/v8/internal/proto" +) + +// ErrClosed performs any operation on the closed client will return this error. +var ErrClosed = pool.ErrClosed + +type Error interface { + error + + // RedisError is a no-op function but + // serves to distinguish types that are Redis + // errors from ordinary errors: a type is a + // Redis error if it has a RedisError method. + RedisError() +} + +var _ Error = proto.RedisError("") + +func shouldRetry(err error, retryTimeout bool) bool { + switch err { + case io.EOF, io.ErrUnexpectedEOF: + return true + case nil, context.Canceled, context.DeadlineExceeded: + return false + } + + if v, ok := err.(timeoutError); ok { + if v.Timeout() { + return retryTimeout + } + return true + } + + s := err.Error() + if s == "ERR max number of clients reached" { + return true + } + if strings.HasPrefix(s, "LOADING ") { + return true + } + if strings.HasPrefix(s, "READONLY ") { + return true + } + if strings.HasPrefix(s, "CLUSTERDOWN ") { + return true + } + if strings.HasPrefix(s, "TRYAGAIN ") { + return true + } + + return false +} + +func isRedisError(err error) bool { + _, ok := err.(proto.RedisError) + return ok +} + +func isBadConn(err error, allowTimeout bool, addr string) bool { + switch err { + case nil: + return false + case context.Canceled, context.DeadlineExceeded: + return true + } + + if isRedisError(err) { + switch { + 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 + case isMovedSameConnAddr(err, addr): + // Close connections when we are asked to move to the same addr + // of the connection. Force a DNS resolution when all connections + // of the pool are recycled + return true + default: + return false + } + } + + if allowTimeout { + if netErr, ok := err.(net.Error); ok && netErr.Timeout() { + return !netErr.Temporary() + } + } + + return true +} + +func isMovedError(err error) (moved bool, ask bool, addr string) { + if !isRedisError(err) { + return + } + + s := err.Error() + switch { + case strings.HasPrefix(s, "MOVED "): + moved = true + case strings.HasPrefix(s, "ASK "): + ask = true + default: + return + } + + ind := strings.LastIndex(s, " ") + if ind == -1 { + return false, false, "" + } + addr = s[ind+1:] + return +} + +func isLoadingError(err error) bool { + return strings.HasPrefix(err.Error(), "LOADING ") +} + +func isReadOnlyError(err error) bool { + return strings.HasPrefix(err.Error(), "READONLY ") +} + +func isMovedSameConnAddr(err error, addr string) bool { + redisError := err.Error() + if !strings.HasPrefix(redisError, "MOVED ") { + return false + } + return strings.HasSuffix(redisError, " "+addr) +} + +//------------------------------------------------------------------------------ + +type timeoutError interface { + Timeout() bool +} |