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 92     92   815 use strict;
  92         172  
  92         2794  
4 92     92   313 use warnings;
  92         110  
  92         3568  
5 92     92   1101 use 5.018;
  92         216  
6              
7 92     92   292 use parent 'Async::Redis::Error';
  92         156  
  92         377  
8              
9 3     3 1 410 sub type { shift->{type} }
10              
11             # Parse error type from Redis error message
12             # Redis errors are formatted as: "ERRORTYPE message text"
13             sub from_message {
14 4     4 1 4655 my ($class, $message) = @_;
15              
16 4         6 my $type = 'ERR'; # default
17 4 50       21 if ($message =~ /^([A-Z]+)\s/) {
18 4         8 $type = $1;
19             }
20              
21 4         21 return $class->new(
22             message => $message,
23             type => $type,
24             );
25             }
26              
27             # Predicate methods for common error types
28 7   50 7 1 68 sub is_wrongtype { uc(shift->{type} // '') eq 'WRONGTYPE' }
29 7   50 7 1 1680 sub is_oom { uc(shift->{type} // '') eq 'OOM' }
30 7   50 7 1 1953 sub is_busy { uc(shift->{type} // '') eq 'BUSY' }
31 6   50 6 1 1717 sub is_noscript { uc(shift->{type} // '') eq 'NOSCRIPT' }
32 6   50 6 1 1749 sub is_readonly { uc(shift->{type} // '') eq 'READONLY' }
33 7   50 7 1 1844 sub is_loading { uc(shift->{type} // '') eq 'LOADING' }
34 0   0 0 1 0 sub is_noauth { uc(shift->{type} // '') eq 'NOAUTH' }
35 0   0 0 1 0 sub is_noperm { uc(shift->{type} // '') eq 'NOPERM' }
36              
37             # Fatal errors should not be retried
38             sub is_fatal {
39 7     7 1 2152 my $self = shift;
40 7   50     21 my $type = uc($self->{type} // '');
41              
42             # These are deterministic failures - retrying won't help
43 7 100       47 return 1 if $type =~ /^(WRONGTYPE|OOM|NOSCRIPT|NOAUTH|NOPERM|ERR)$/;
44              
45 3         13 return 0;
46             }
47              
48             # Transient errors may succeed on retry
49             sub is_transient {
50 0     0 1   my $self = shift;
51 0   0       my $type = uc($self->{type} // '');
52              
53             # These may succeed if retried after a delay
54 0 0         return 1 if $type =~ /^(BUSY|LOADING|READONLY|CLUSTERDOWN)$/;
55              
56 0           return 0;
57             }
58              
59             1;
60              
61             __END__