File Coverage

blib/lib/Mail/MtPolicyd/SessionCache/Redis.pm
Criterion Covered Total %
statement 9 41 21.9
branch 0 10 0.0
condition 0 3 0.0
subroutine 3 7 42.8
pod 0 2 0.0
total 12 63 19.0


line stmt bran cond sub pod time code
1             package Mail::MtPolicyd::SessionCache::Redis;
2              
3 1     1   1331 use Moose;
  1         2  
  1         7  
4              
5             our $VERSION = '2.02'; # VERSION
6             # ABSTRACT: a session cache adapter for redis
7              
8 1     1   4284 use Time::HiRes qw(usleep);
  1         1  
  1         10  
9 1     1   119 use Storable;
  1         2  
  1         438  
10              
11             extends 'Mail::MtPolicyd::SessionCache::Base';
12              
13             with 'Mail::MtPolicyd::Role::Connection' => {
14             name => 'redis',
15             type => 'Redis',
16             };
17              
18              
19             has 'expire' => ( is => 'ro', isa => 'Int', default => 5 * 60 );
20              
21             has 'lock_wait' => ( is => 'rw', isa => 'Int', default => 50 );
22             has 'lock_max_retry' => ( is => 'rw', isa => 'Int', default => 50 );
23             has 'lock_timeout' => ( is => 'rw', isa => 'Int', default => 10 );
24              
25             sub _acquire_session_lock {
26 0     0     my ( $self, $instance ) = @_;
27 0           my $lock = 'lock_'.$instance;
28              
29 0           for( my $try = 1 ; $try < $self->lock_max_retry ; $try++ ) {
30 0 0         if( $self->_redis_handle->set($lock, 1, 'EX', $self->lock_timeout, 'NX' ) ) {
31 0           return; # lock created
32             }
33 0           usleep( $self->lock_wait * $try );
34             }
35              
36 0           die('could not acquire lock for session '.$instance);
37 0           return;
38             }
39              
40             sub _release_session_lock {
41 0     0     my ( $self, $instance ) = @_;
42 0           my $lock = 'lock_'.$instance;
43              
44 0           $self->_redis_handle->del($lock);
45              
46 0           return;
47             }
48              
49             sub retrieve_session {
50 0     0 0   my ($self, $instance ) = @_;
51              
52 0 0         if( ! defined $instance ) {
53 0           return;
54             }
55              
56 0           $self->_acquire_session_lock( $instance );
57              
58 0 0         if( my $blob = $self->_redis_handle->get($instance) ) {
59 0           my $session;
60 0           eval { $session = Storable::thaw( $blob ) };
  0            
61 0 0         if( $@ ) {
62 0           die("could not restore session $instance: $@");
63             }
64 0           return($session);
65             }
66            
67 0           return( { '_instance' => $instance } );
68             }
69              
70             sub store_session {
71 0     0 0   my ($self, $session ) = @_;
72 0           my $instance = $session->{'_instance'};
73              
74 0 0 0       if( ! defined $session || ! defined $instance ) {
75 0           return;
76             }
77            
78 0           my $data = Storable::freeze( $session );
79 0           $self->_redis_handle->set($instance, $data, 'EX', $self->expire);
80              
81 0           $self->_release_session_lock($instance);
82              
83 0           return;
84             }
85              
86             1;
87              
88             __END__
89              
90             =pod
91              
92             =encoding UTF-8
93              
94             =head1 NAME
95              
96             Mail::MtPolicyd::SessionCache::Redis - a session cache adapter for redis
97              
98             =head1 VERSION
99              
100             version 2.02
101              
102             =head1 SYNOPSIS
103              
104             <SessionCache>
105             module = "Redis"
106             #redis = "redis"
107             # expire session cache entries
108             expire = "300"
109             # wait timeout will be increased each time 50,100,150,... (usec)
110             lock_wait=50
111             # abort after n retries
112             lock_max_retry=50
113             # session lock times out after (sec)
114             lock_timeout=10
115             </SessionCache>
116              
117             =head1 PARAMETERS
118              
119             =over
120              
121             =item redis (default: redis)
122              
123             Name of the database connection to use.
124              
125             You have to define this connection first.
126              
127             see L<Mail::MtPolicyd::Connection::Redis>
128              
129             =item expire (default: 5*60)
130              
131             Timeout in seconds for sessions.
132              
133             =item lock_wait (default: 50)
134              
135             Timeout for retry when session is locked in milliseconds.
136              
137             The retry will be done in multiples of this timeout.
138              
139             When set to 50 retry will be done in 50, 100, 150ms...
140              
141             =item lock_max_retry (default: 50)
142              
143             Maximum number of retries before giving up to obtain lock on a
144             session.
145              
146             =item lock_timeout (default: 10)
147              
148             Timeout of session locks in seconds.
149              
150             =back
151              
152             =head1 AUTHOR
153              
154             Markus Benning <ich@markusbenning.de>
155              
156             =head1 COPYRIGHT AND LICENSE
157              
158             This software is Copyright (c) 2014 by Markus Benning <ich@markusbenning.de>.
159              
160             This is free software, licensed under:
161              
162             The GNU General Public License, Version 2, June 1991
163              
164             =cut