File Coverage

blib/lib/Tie/Redis.pm
Criterion Covered Total %
statement 39 97 40.2
branch 4 32 12.5
condition 2 5 40.0
subroutine 11 25 44.0
pod n/a
total 56 159 35.2


line stmt bran cond sub pod time code
1             package Tie::Redis;
2             BEGIN {
3 6     6   60218 $Tie::Redis::VERSION = '0.22_1';
4             }
5             # ABSTRACT: Connect perl data structures to Redis
6 6     6   72 use strict;
  6         10  
  6         169  
7 6     6   1897 use parent qw(AnyEvent::Redis);
  6         1129  
  6         31  
8 6     6   227350 use Carp ();
  6         8  
  6         119  
9              
10 6     6   2403 use Tie::Redis::Hash;
  6         27  
  6         187  
11 6     6   2151 use Tie::Redis::List;
  6         14  
  6         159  
12 6     6   2106 use Tie::Redis::Scalar;
  6         11  
  6         5960  
13              
14             sub TIEHASH {
15 1     1   12 my($class, %args) = @_;
16 1         3 my $serialize = delete $args{serialize};
17              
18 1         12 my $self = $class->SUPER::new(%args);
19 1         17 $self->{serialize} = $self->_serializer($serialize);
20              
21 1         3 return $self;
22             }
23              
24             sub _serializer {
25 1     1   2 my($self, $serialize) = @_;
26              
27             my %serializers = (
28             json => [
29 0     0   0 sub { require JSON },
30             \&JSON::to_json,
31             \&JSON::from_json
32             ],
33             storable => [
34 0     0   0 sub { require Storable },
35             \&Storable::nfreeze,
36             \&Storaable::thaw
37             ],
38             msgpack => [
39 0     0   0 sub { require Data::MessagePack },
40 0     0   0 sub { unshift @_, "Data::MessagePack"; goto &Data::MessagePack::pack },
  0         0  
41 0     0   0 sub { unshift @_, "Data::MessagePack"; goto &Data::MessagePack::unpack }
  0         0  
42 1         22 ],
43             );
44              
45             my $serializer = $serializers{$serialize || ''} || [undef, (sub {
46 0     0   0 Carp::croak("No serializer specified for Tie::Redis; unable to handle nested structures");
47 1   50     13 }) x 2];
48              
49             # Load; will error if required module isn't present
50 1 50       3 $serializer->[0] && $serializer->[0]->();
51              
52 1         14 return $serializer;
53             }
54              
55             sub _cmd {
56 1     1   2 my($self, $cmd, @args) = @_;
57              
58 1 50 33     5 if($self->{prefix} && defined $args[0]) {
59 0         0 $args[0] = "$self->{prefix}$args[0]";
60             }
61              
62 1 50       4 if($self->{use_recv}) {
63 0         0 $self->$cmd(@args)->recv;
64             } else {
65 1         1 my($ret, $error, $done);
66              
67 1         2 $done = 0;
68 1         14 my $cv = $self->$cmd(@args);
69             $cv->cb(sub {
70 0     0   0 $done = 1;
71 0         0 $ret = eval { $_[0]->recv };
  0         0  
72 0 0       0 if($@) {
73 0         0 $error = $@;
74             }
75 1         4325 });
76              
77             # We need to block, but using ->recv won't work if the program is using
78             # ->recv at a higher level, so we do this slight hack.
79 1         37 AnyEvent->one_event until $done;
80 0 0       0 die $error if defined $error;
81 0         0 $ret;
82             }
83             }
84              
85             sub STORE {
86 0     0   0 my($self, $key, $value) = @_;
87              
88 0 0       0 if(!ref $value) {
    0          
    0          
    0          
89 0         0 $self->_cmd(set => $key, $value);
90              
91             } elsif(ref $value eq 'HASH') {
92             # TODO: Should pipeline somehow
93 0         0 $self->_cmd("multi");
94 0         0 $self->_cmd(del => $key);
95             $self->_cmd(hmset => $key,
96 0         0 map +($_ => $value->{$_}), keys %$value);
97 0         0 $self->_cmd("exec");
98 0         0 $self->{_type_cache}->{$key} = 'hash';
99              
100             } elsif(ref $value eq 'ARRAY') {
101 0         0 $self->_cmd("multi");
102 0         0 $self->_cmd(del => $key);
103 0         0 for my $v(@$value) {
104 0         0 $self->_cmd(rpush => $key, $v);
105             }
106 0         0 $self->_cmd("exec");
107 0         0 $self->{_type_cache}->{$key} = 'list';
108              
109             } elsif(ref $value) {
110 0         0 $self->_cmd(set => $key, $self->{serialize}->[1]->($value));
111             }
112             }
113              
114             sub FETCH {
115 1     1   9 my($self, $key) = @_;
116             my $type = exists $self->{_type_cache}->{$key}
117 1 50       7 ? $self->{_type_cache}->{$key}
118             : $self->_cmd(type => $key);
119              
120 0 0         if($type eq 'hash') {
    0          
    0          
    0          
    0          
121 0           tie my %h, "Tie::Redis::Hash", redis => $self, key => $key;
122 0           return \%h;
123             } elsif($type eq 'list') {
124 0           tie my @l, "Tie::Redis::List", redis => $self, key => $key;
125 0           return \@l;
126             } elsif($type eq 'set') {
127 0           die "Sets yet to be implemented...";
128             } elsif($type eq 'zset') {
129 0           die "Zsets yet to be implemented...";
130             } elsif($type eq 'string') {
131 0           $self->_cmd(get => $key);
132             } else {
133 0           return undef;
134             }
135             }
136              
137             sub FIRSTKEY {
138 0     0     my($self) = @_;
139 0           my $keys = $self->_cmd(keys => "*");
140 0           $self->{keys} = $keys;
141 0           $self->NEXTKEY;
142             }
143              
144             sub NEXTKEY {
145 0     0     my($self) = @_;
146 0           shift @{$self->{keys}};
  0            
147             }
148              
149             sub EXISTS {
150 0     0     my($self, $key) = @_;
151 0           $self->_cmd(exists => $key);
152             }
153              
154             sub DELETE {
155 0     0     my($self, $key) = @_;
156 0           $self->_cmd(del => $key);
157             }
158              
159             sub CLEAR {
160 0     0     my($self, $key) = @_;
161 0 0         if($self->{prefix}) {
162 0           $self->_cmd(del => $self->_cmd(keys => "*"));
163             } else {
164 0           $self->_cmd("flushdb");
165             }
166             }
167              
168             sub SCALAR {
169 0     0     my($self) = @_;
170 0           $self->_cmd("dbsize");
171             }
172              
173             1;
174              
175              
176              
177             __END__