File Coverage

blib/lib/Plack/Session/Store/Transparent.pm
Criterion Covered Total %
statement 60 61 98.3
branch 11 18 61.1
condition 1 3 33.3
subroutine 14 14 100.0
pod 4 4 100.0
total 90 100 90.0


line stmt bran cond sub pod time code
1             package Plack::Session::Store::Transparent;
2 5     5   499576 use 5.008005;
  5         23  
  5         206  
3 5     5   30 use strict;
  5         9  
  5         182  
4 5     5   38 use warnings;
  5         18  
  5         130  
5 5     5   26 use Carp;
  5         11  
  5         723  
6 5     5   30 use Scalar::Util qw(blessed);
  5         9  
  5         1202  
7              
8             our $VERSION = "0.03";
9              
10 5     5   4652 use parent 'Plack::Session::Store';
  5         3675  
  5         38  
11              
12 5         26 use Plack::Util::Accessor qw(
13             origin
14             cache
15 5     5   26780 );
  5         15  
16              
17             sub _check_interface {
18 21     21   38 my ($class, $obj) = @_;
19 21   33     495 return blessed $obj
20             && $obj->can('fetch')
21             && $obj->can('store')
22             && $obj->can('remove');
23             }
24              
25             sub new {
26 7     7 1 12575 my ($class, %args) = @_;
27              
28 7 50       58 unless ($args{origin}) {
29 0         0 croak "missing mandatory parameter 'origin'";
30             }
31              
32            
33             {
34             # check origin
35 7 50       15 croak 'origin requires fetch, store and remove method'
  7         33  
36             unless $class->_check_interface($args{origin});
37              
38             # check cache
39 7 50       40 my @caches = ( ref($args{cache}) eq 'ARRAY' ? @{ $args{cache} } : $args{cache} );
  7         24  
40 7         19 for (@caches) {
41 14 50       38 next unless $_;
42 14 50       37 croak 'cache requires fetch, store and remove method'
43             unless $class->_check_interface($_);
44             }
45             }
46              
47 7         57 return bless { %args }, $class;
48             }
49              
50             sub fetch {
51 15     15 1 7045 my ($self, $session_id) = @_;
52              
53 15         70 my @uppers;
54 15         120 for my $layer ($self->_layers) {
55 28 100       256 if (my $session = $layer->fetch($session_id)) {
56             # ignore exceptions for availability
57 11         85 eval {
58 11         38 $_->store($session_id, $session) for @uppers;
59             };
60 11         89 return $session;
61             }
62 17         237 unshift(@uppers, $layer);
63             }
64              
65 4         22 return;
66             }
67              
68             sub store {
69 13     13 1 38856 my ($self, $session_id, $session) = @_;
70              
71 13         27 my @uppers;
72 13         51 for my $layer ($self->_layers) {
73 38         309 eval {
74 38         115 $layer->store($session_id, $session);
75             };
76 38 100       374 if (my $e = $@) {
77 1         13 $_->remove($session_id) for @uppers;
78 1         33 croak $e;
79             }
80              
81 37         108 push(@uppers, $layer);
82             }
83             }
84              
85             sub remove {
86 3     3 1 1147 my ($self, $session_id) = @_;
87              
88 3         12 for my $layer ($self->_layers) {
89 8         114 $layer->remove($session_id);
90             }
91             }
92              
93             sub _caches {
94 31     31   42 my ($self) = @_;
95 31 50       130 return [] unless $self->cache;
96 31 50       265 return ref($self->cache) eq 'ARRAY' ? $self->cache : [ $self->cache ];
97             }
98              
99             sub _layers {
100 31     31   44 my ($self) = @_;
101 31         38 return (@{ $self->_caches }, $self->origin);
  31         72  
102             }
103              
104             1;
105             __END__