error.go 1.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. package redis
  2. import (
  3. "context"
  4. "io"
  5. "net"
  6. "strings"
  7. "github.com/go-redis/redis/internal/proto"
  8. )
  9. func isRetryableError(err error, retryTimeout bool) bool {
  10. switch err {
  11. case nil, context.Canceled, context.DeadlineExceeded:
  12. return false
  13. case io.EOF:
  14. return true
  15. }
  16. if netErr, ok := err.(net.Error); ok {
  17. if netErr.Timeout() {
  18. return retryTimeout
  19. }
  20. return true
  21. }
  22. s := err.Error()
  23. if s == "ERR max number of clients reached" {
  24. return true
  25. }
  26. if strings.HasPrefix(s, "LOADING ") {
  27. return true
  28. }
  29. if strings.HasPrefix(s, "READONLY ") {
  30. return true
  31. }
  32. if strings.HasPrefix(s, "CLUSTERDOWN ") {
  33. return true
  34. }
  35. return false
  36. }
  37. func isRedisError(err error) bool {
  38. _, ok := err.(proto.RedisError)
  39. return ok
  40. }
  41. func isBadConn(err error, allowTimeout bool) bool {
  42. if err == nil {
  43. return false
  44. }
  45. if isRedisError(err) {
  46. // Close connections in read only state in case domain addr is used
  47. // and domain resolves to a different Redis Server. See #790.
  48. return isReadOnlyError(err)
  49. }
  50. if allowTimeout {
  51. if netErr, ok := err.(net.Error); ok && netErr.Timeout() {
  52. return false
  53. }
  54. }
  55. return true
  56. }
  57. func isMovedError(err error) (moved bool, ask bool, addr string) {
  58. if !isRedisError(err) {
  59. return
  60. }
  61. s := err.Error()
  62. switch {
  63. case strings.HasPrefix(s, "MOVED "):
  64. moved = true
  65. case strings.HasPrefix(s, "ASK "):
  66. ask = true
  67. default:
  68. return
  69. }
  70. ind := strings.LastIndex(s, " ")
  71. if ind == -1 {
  72. return false, false, ""
  73. }
  74. addr = s[ind+1:]
  75. return
  76. }
  77. func isLoadingError(err error) bool {
  78. return strings.HasPrefix(err.Error(), "LOADING ")
  79. }
  80. func isReadOnlyError(err error) bool {
  81. return strings.HasPrefix(err.Error(), "READONLY ")
  82. }