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 76     76   735 use strict;
  76         115  
  76         2593  
4 76     76   288 use warnings;
  76         109  
  76         3076  
5 76     76   884 use 5.018;
  76         203  
6              
7             our $VERSION = '0.001';
8              
9 76     76   344 use parent 'Async::Redis::Error';
  76         152  
  76         385  
10              
11 3     3 1 377 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 4250 my ($class, $message) = @_;
17              
18 2         3 my $type = 'ERR'; # default
19 2 50       11 if ($message =~ /^([A-Z]+)\s/) {
20 2         4 $type = $1;
21             }
22              
23 2         6 return $class->new(
24             message => $message,
25             type => $type,
26             );
27             }
28              
29             # Predicate methods for common error types
30 7   50 7 1 64 sub is_wrongtype { uc(shift->{type} // '') eq 'WRONGTYPE' }
31 7   50 7 1 1621 sub is_oom { uc(shift->{type} // '') eq 'OOM' }
32 7   50 7 1 1586 sub is_busy { uc(shift->{type} // '') eq 'BUSY' }
33 6   50 6 1 1607 sub is_noscript { uc(shift->{type} // '') eq 'NOSCRIPT' }
34 6   50 6 1 1532 sub is_readonly { uc(shift->{type} // '') eq 'READONLY' }
35 7   50 7 1 1633 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 1591 my $self = shift;
42 7   50     18 my $type = uc($self->{type} // '');
43              
44             # These are deterministic failures - retrying won't help
45 7 100       43 return 1 if $type =~ /^(WRONGTYPE|OOM|NOSCRIPT|NOAUTH|NOPERM|ERR)$/;
46              
47 3         14 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__