File Coverage

lib/CGI/Session/Driver/redis.pm
Criterion Covered Total %
statement 15 58 25.8
branch 0 10 0.0
condition 0 22 0.0
subroutine 5 12 41.6
pod 5 6 83.3
total 25 108 23.1


line stmt bran cond sub pod time code
1             package CGI::Session::Driver::redis;
2              
3 1     1   36399 use strict;
  1         3  
  1         39  
4 1     1   6 use warnings;
  1         2  
  1         35  
5              
6 1     1   6 use Carp qw(croak);
  1         6  
  1         67  
7 1     1   945 use CGI::Session::Driver;
  1         549  
  1         43  
8              
9             @CGI::Session::Driver::redis::ISA = ("CGI::Session::Driver");
10              
11 1     1   7 use vars qw($VERSION);
  1         2  
  1         741  
12             our $VERSION = "0.5";
13              
14              
15             =pod
16            
17             =head1 NAME
18            
19             CGI::Session::Driver::redis - CGI::Session driver for redis
20            
21             =head1 SYNOPSIS
22            
23             use strict;
24             use warnings;
25             use Redis;
26            
27             my $redis = Redis->new();
28            
29             my $session = CGI::Session->new( "driver:redis", $sid, { Redis => $redis,
30             Expire => 60*60*24 } );
31            
32            
33             =head1 DESCRIPTION
34            
35             This backend stores session data in a persistent redis server, with
36             the ability to specify an expiry time in seconds.
37            
38            
39             =head1 DRIVER ARGUMENTS
40            
41             The following options may be passed to the constructor:
42            
43             =over 4
44            
45             =item C<Expiry>
46            
47             Which is the time to expire the sessions, in seconds, in inactivity.
48             Supplying a value of "0" equates to never expiring sessions.
49            
50             =item C<Prefix>
51            
52             A string value to prefix to the session ID prior to redis
53             storage. The default is "session".
54            
55             =item C<Redis>
56            
57             A Redis object which will be used to store the session data within.
58            
59             =back
60            
61             =head1 REQUIREMENTS
62            
63             =over 4
64            
65             =item L<CGI::Session>
66            
67             =item L<Redis>
68            
69             =back
70            
71             =head1 AUTHOR
72            
73             Steve Kemp <steve@steve.org.uk>
74            
75             =head1 COPYRIGHT AND LICENSE
76            
77             Copyright (C) 2010-2014 Steve Kemp <steve@steve.org.uk>.
78            
79             This library is free software. You can modify and or distribute it under
80             the same terms as Perl itself.
81            
82             =cut
83              
84              
85             =head1 METHODS
86            
87             =cut
88              
89              
90              
91              
92             =head2 init
93            
94             Initialise our driver, ensuring we received a 'Redis' attribute.
95            
96             =cut
97              
98             sub init
99             {
100 0     0 1       my $self = shift;
101 0 0             unless ( defined $self->{ Redis } )
102                 {
103 0                   return $self->set_error("init(): 'Redis' attribute is required.");
104                 }
105              
106 0               return 1;
107             }
108              
109              
110              
111             =head2 store
112            
113             Generate a key, by joining a prefix and the session identifier, then
114             store the session underneath that key.
115            
116             =cut
117              
118             sub store
119             {
120 0     0 1       my $self = shift;
121 0               my ( $sid, $datastr ) = @_;
122 0 0 0           croak "store(): usage error" unless $sid && $datastr;
123              
124             #
125             # Get the prefix, and build a key
126             #
127 0   0           my $prefix = $self->{ 'Prefix' } || "session";
128 0               my $key = $prefix . ':' . $sid;
129              
130             #
131             # redis doesn't like to have whitespace in the keys.
132             #
133 0               $key =~ s/[ \t\r\n]//g;
134              
135             #
136             # Store in the server
137             #
138 0               $self->{ 'Redis' }->set( $key, $datastr );
139              
140             #
141             # Add this key to the known list of sessions; required so that
142             # traverse can succeed.
143             #
144 0               $self->{ 'Redis' }->sadd( $prefix . ":members", $key );
145              
146             #
147             # Set the expiry time, in seconds, if present.
148             #
149 0   0           my $expire = $self->{ 'Expire' } || 0;
150 0 0 0           if ( $expire && $expire > 0 )
151                 {
152 0                   $self->{ 'Redis' }->expire( $key, $expire );
153                 }
154 0               return 1;
155             }
156              
157              
158              
159             =head2 retrieve
160            
161             Generate a key, by joining a prefix and the session identifier, then
162             return the session information stored under that key.
163            
164             =cut
165              
166             sub retrieve
167             {
168 0     0 1       my ( $self, $sid ) = @_;
169              
170             #
171             # Get the prefix, and build a key
172             #
173 0   0           my $prefix = $self->{ 'Prefix' } || "session";
174 0               my $key = $prefix . ':' . $sid;
175              
176             #
177             # redis doesn't like to have whitespace in the keys.
178             #
179 0               $key =~ s/[ \t\r\n]//g;
180              
181 0               my $rv = $self->{ 'Redis' }->get($key);
182 0 0             return 0 unless defined($rv);
183 0               return $rv;
184             }
185              
186              
187             =head2 retrieve
188            
189             Generate a key, by joining a prefix and the session identifier, then
190             remove that key from the Redis store.
191            
192             =cut
193              
194             sub remove
195             {
196              
197 0     0 1       my $self = shift;
198 0               my ( $sid, $datastr ) = @_;
199              
200             #
201             # Get the prefix, and build a key
202             #
203 0   0           my $prefix = $self->{ 'Prefix' } || "session";
204 0               my $key = $prefix . ':' . $sid;
205              
206             #
207             # redis doesn't like to have whitespace in the keys.
208             #
209 0               $key =~ s/[ \t\r\n]//g;
210              
211             # remove the data associated with the id
212 0               $self->{ 'Redis' }->del($key);
213              
214             #
215             # Remove this key from the known list of sessions.
216             #
217 0               $self->{ 'Redis' }->srem( $prefix . ":members", $key );
218              
219 0               return 1;
220             }
221              
222              
223             sub teardown
224             {
225 0     0 0       my ( $self, $sid, $options ) = @_;
226              
227             # NOP
228             }
229              
230             sub DESTROY
231             {
232 0     0         my $self = shift;
233              
234             # NOP
235             }
236              
237             =head2 traverse
238            
239             Invoke the specified code reference on each active session.
240            
241             This is required to allow this driver to be used with the L<CGI::Session/find> method.
242            
243             =cut
244              
245             sub traverse
246             {
247 0     0 1       my $self = shift;
248 0               my ($coderef) = @_;
249              
250 0 0 0           unless ( $coderef && ref($coderef) && ( ref $coderef eq 'CODE' ) )
      0        
251                 {
252 0                   croak "traverse(): usage error";
253                 }
254              
255 0   0           my $prefix = $self->{ 'Prefix' } || "session";
256 0               my $key = $prefix . ':members';
257              
258             #
259             # Redis doesn't like to have whitespace in the keys.
260             #
261 0               $key =~ s/[ \t\r\n]//g;
262              
263             #
264             # For each key invoke the callback.
265             #
266 0               foreach my $session ( $self->{ 'Redis' }->smembers($key) )
267                 {
268 0                   $coderef->($session);
269                 }
270 0               return 1;
271             }
272              
273              
274             1;
275              
276              
277             =head1 SEE ALSO
278            
279             =over 4
280            
281             =item *
282            
283             L<CGI::Session|CGI::Session> - CGI::Session manual
284            
285             =item *
286            
287             L<CGI::Session::Tutorial|CGI::Session::Tutorial> - extended CGI::Session manual
288            
289             =item *
290            
291             L<CGI::Session::CookBook|CGI::Session::CookBook> - practical solutions for real life problems
292            
293             =item *
294            
295             L<Redis|Redis> - Redis interface library.
296            
297             =back
298            
299             =cut
300