File Coverage

blib/lib/Cache/Escalate.pm
Criterion Covered Total %
statement 52 52 100.0
branch 13 14 92.8
condition 6 6 100.0
subroutine 9 9 100.0
pod 0 4 0.0
total 80 85 94.1


line stmt bran cond sub pod time code
1             package Cache::Escalate;
2 2     2   29222 use 5.008001;
  2         8  
3 2     2   13 use strict;
  2         4  
  2         62  
4 2     2   20 use warnings;
  2         5  
  2         107  
5              
6             use Class::Accessor::Lite (
7 2         17 ro => [qw{caches sync_level sync_expiration}],
8 2     2   1653 );
  2         2635  
9              
10             our $VERSION = "0.02";
11              
12             our $SYNC_LEVEL_NONE = 1;
13             our $SYNC_LEVEL_MISSED = 2;
14             our $SYNC_LEVEL_FULL = 3;
15              
16             sub new {
17 11     11 0 12627 my $class = shift;
18 11         38 my %args = @_;
19              
20 11 100 100     93 if (! $args{caches} || ref $args{caches} ne "ARRAY" || ! scalar @{$args{caches}}) {
  9   100     46  
21 3         42 die "One more caches required.";
22             }
23              
24 8         10 for my $cache (@{$args{caches}}) {
  8         20  
25 18 100       31 if (! _looks_like_cache($cache)) {
26 3         38 die "`caches` contains invalid object.";
27             }
28             }
29              
30             return bless {
31             caches => $args{caches},
32             sync_level => $args{sync_level},
33             }
34 5         24 }
35              
36             sub _looks_like_cache {
37 18     18   20 my ($cache) = @_;
38              
39 18         24 for my $method (qw{get set delete}) {
40 48 100       168 return if ! $cache->can($method);
41             }
42              
43 15         36 return 1;
44             }
45              
46             sub get {
47 3     3 0 37 my ($self, $key) = @_;
48              
49 3         6 my $value;
50 3         6 my @caches = @{$self->caches};
  3         9  
51 3         21 my @missed;
52             my @rest;
53              
54 3         11 while (my $cache = shift @caches) {
55 6         15 $value = $cache->get($key);
56              
57 6 100       44 if (defined $value) {
58 3         6 @rest = @caches;
59 3         6 last;
60             }
61              
62 3         10 push @missed, $cache;
63             }
64              
65 3 50       7 return if ! defined $value;
66 3 100       10 return $value if $self->sync_level == $SYNC_LEVEL_NONE;
67              
68 2 100       13 my @sync_targets = $self->sync_level == $SYNC_LEVEL_MISSED
69             ? @missed
70             : (@missed, @rest);
71              
72 2         14 for my $cache (@sync_targets) {
73 3         13 $cache->set($key, $value, $self->sync_expiration);
74             }
75              
76 2         21 return $value;
77             }
78              
79             sub set {
80 1     1 0 10 my ($self, $key, $value, $expiration) = @_;
81              
82 1         3 for my $cache (@{$self->caches}) {
  1         7  
83 2         34 $cache->set($key, $value, $expiration);
84             }
85              
86 1         9 return;
87             }
88              
89             sub delete {
90 1     1 0 21 my ($self, $key) = @_;
91              
92 1         1 for my $cache (@{$self->caches}) {
  1         20  
93 3         18 $cache->delete($key);
94             }
95              
96 1         4 return;
97             }
98              
99             1;
100             __END__