File Coverage

blib/lib/Async/Redis/Error/Redis.pm
Criterion Covered Total %
statement 27 33 81.8
branch 3 6 50.0
condition 7 20 35.0
subroutine 13 16 81.2
pod 12 12 100.0
total 62 87 71.2


line stmt bran cond sub pod time code
1             package Async::Redis::Error::Redis;
2              
3 74     74   1077 use strict;
  74         192  
  74         3363  
4 74     74   383 use warnings;
  74         136  
  74         4175  
5 74     74   1276 use 5.018;
  74         253  
6              
7             our $VERSION = '0.001';
8              
9 74     74   484 use parent 'Async::Redis::Error';
  74         173  
  74         546  
10              
11 3     3 1 756 sub type { shift->{type} }
12              
13             # Parse error type from Redis error message
14             # Redis errors are formatted as: "ERRORTYPE message text"
15             sub from_message {
16 2     2 1 8059 my ($class, $message) = @_;
17              
18 2         4 my $type = 'ERR'; # default
19 2 50       14 if ($message =~ /^([A-Z]+)\s/) {
20 2         45 $type = $1;
21             }
22              
23 2         12 return $class->new(
24             message => $message,
25             type => $type,
26             );
27             }
28              
29             # Predicate methods for common error types
30 7   50 7 1 107 sub is_wrongtype { uc(shift->{type} // '') eq 'WRONGTYPE' }
31 7   50 7 1 3313 sub is_oom { uc(shift->{type} // '') eq 'OOM' }
32 7   50 7 1 3116 sub is_busy { uc(shift->{type} // '') eq 'BUSY' }
33 6   50 6 1 3020 sub is_noscript { uc(shift->{type} // '') eq 'NOSCRIPT' }
34 6   50 6 1 3091 sub is_readonly { uc(shift->{type} // '') eq 'READONLY' }
35 7   50 7 1 3135 sub is_loading { uc(shift->{type} // '') eq 'LOADING' }
36 0   0 0 1 0 sub is_noauth { uc(shift->{type} // '') eq 'NOAUTH' }
37 0   0 0 1 0 sub is_noperm { uc(shift->{type} // '') eq 'NOPERM' }
38              
39             # Fatal errors should not be retried
40             sub is_fatal {
41 7     7 1 3030 my $self = shift;
42 7   50     32 my $type = uc($self->{type} // '');
43              
44             # These are deterministic failures - retrying won't help
45 7 100       60 return 1 if $type =~ /^(WRONGTYPE|OOM|NOSCRIPT|NOAUTH|NOPERM|ERR)$/;
46              
47 3         22 return 0;
48             }
49              
50             # Transient errors may succeed on retry
51             sub is_transient {
52 0     0 1   my $self = shift;
53 0   0       my $type = uc($self->{type} // '');
54              
55             # These may succeed if retried after a delay
56 0 0         return 1 if $type =~ /^(BUSY|LOADING|READONLY|CLUSTERDOWN)$/;
57              
58 0           return 0;
59             }
60              
61             1;
62              
63             __END__