diff --git a/internal/errors/errors.go b/internal/errors/errors.go index 7e6da13..4736095 100644 --- a/internal/errors/errors.go +++ b/internal/errors/errors.go @@ -213,6 +213,24 @@ func IsTaskAlreadyArchived(err error) bool { return As(err, &target) } +// RedisCommandError indicates that the given redis command returned error. +type RedisCommandError struct { + Command string // redis command (e.g. LRANGE, ZADD, etc) + Err error // underlying error +} + +func (e *RedisCommandError) Error() string { + return fmt.Sprintf("redis command error: %s failed: %v", strings.ToUpper(e.Command), e.Err) +} + +func (e *RedisCommandError) Unwrap() error { return e.Err } + +// IsRedisCommandError reports whether any error in err's chain is of type RedisCommandError. +func IsRedisCommandError(err error) bool { + var target *RedisCommandError + return As(err, &target) +} + /************************************************* Standard Library errors package functions *************************************************/ diff --git a/internal/rdb/inspect.go b/internal/rdb/inspect.go index 26bef61..6430f1a 100644 --- a/internal/rdb/inspect.go +++ b/internal/rdb/inspect.go @@ -183,7 +183,7 @@ func (r *RDB) memoryUsage(qname string) (int64, error) { for { data, cursor, err = r.client.Scan(cursor, fmt.Sprintf("asynq:{%s}*", qname), 100).Result() if err != nil { - return 0, errors.E(op, errors.Unknown, fmt.Sprintf("redis command error: SCAN failed: %v", err)) + return 0, errors.E(op, errors.Unknown, &errors.RedisCommandError{Command: "scan", Err: err}) } keys = append(keys, data...) if cursor == 0 { @@ -194,7 +194,7 @@ func (r *RDB) memoryUsage(qname string) (int64, error) { for _, k := range keys { n, err := r.client.MemoryUsage(k).Result() if err != nil { - return 0, errors.E(op, errors.Unknown, fmt.Sprintf("redis command error: MEMORY USAGE failed: %v", err)) + return 0, errors.E(op, errors.Unknown, &errors.RedisCommandError{Command: "memory usage", Err: err}) } usg += n } @@ -220,7 +220,7 @@ func (r *RDB) HistoricalStats(qname string, n int) ([]*DailyStats, error) { } exists, err := r.client.SIsMember(base.AllQueues, qname).Result() if err != nil { - return nil, errors.E(op, errors.Unknown, fmt.Sprintf("redis command error: SISMEMBER failed: %v", err)) + return nil, errors.E(op, errors.Unknown, &errors.RedisCommandError{Command: "sismember", Err: err}) } if !exists { return nil, errors.E(op, errors.NotFound, &errors.QueueNotFoundError{Queue: qname})