File Coverage

blib/lib/Articulate/Caching/Native.pm
Criterion Covered Total %
statement 34 49 69.3
branch 4 12 33.3
condition n/a
subroutine 9 11 81.8
pod 5 5 100.0
total 52 77 67.5


line stmt bran cond sub pod time code
1             package Articulate::Caching::Native;
2 6     6   3913 use strict;
  6         12  
  6         213  
3 6     6   27 use warnings;
  6         9  
  6         133  
4              
5 6     6   25 use Moo;
  6         9  
  6         34  
6 6     6   5266 use DateTime;
  6         384172  
  6         2617  
7             with 'Articulate::Role::Component';
8              
9             =head1 NAME
10              
11             Articulate::Caching::Native - cache content in memory
12              
13             =head1 DESCRIPTION
14              
15             This implements caching by keeping an hash of the content you wish to
16             cache in memory.
17              
18             No attempt is made to monitor the memory size of the hash directly, but
19             a maximum number of locations under which content may be stored is set.
20             Once this maximum is reached or exceeded, a quarter of the keys are
21             removed (preserving those which have most recently been accessed).
22              
23             Consequently, it is unsuitable for cases where large documents are to
24             be stored alongside small ones, or where you have a very large number
25             of locations you want to cache.
26              
27             =cut
28              
29 0     0   0 sub _now { DateTime->now . '' }
30              
31             =head1 ATTRIBUTES
32              
33             =cut
34              
35             =head3 cache
36              
37             This is the contents of the cache. Don't set this.
38              
39             =cut
40              
41             has cache => (
42             is => 'rw',
43             default => sub { {} },
44             );
45              
46             =head3 max_keys
47              
48             The maximum number of keys in the hash (locations for which either meta
49             or content or both is stored).
50              
51             Be warned that each time this is exceeded, a sort is performed on the
52             values (to find the entries least recently accessed). The larger
53             max_keys is, the longer this sort will take.
54              
55             =cut
56              
57             has max_keys => (
58             is => 'rw',
59             default => sub { 255 },
60             );
61              
62             =head1 METHODS
63              
64             =head3 is_cached
65              
66             $caching->is_cached( $what, $location )
67              
68             =cut
69              
70             sub is_cached {
71 4     4 1 9 my $self = shift;
72 4         17 my $what = shift;
73 4         9 my $location = shift;
74 4 100       25 return undef unless exists $self->cache->{$location};
75 1 50       7 return undef unless exists $self->cache->{$location}->{$what};
76 0         0 return 1;
77             }
78              
79             =head3 get_cached
80              
81             $caching->get_cached( $what, $location )
82              
83             =cut
84              
85             sub get_cached {
86 0     0 1 0 my $self = shift;
87 0         0 my $what = shift;
88 0         0 my $location = shift;
89 0 0       0 return undef unless exists $self->cache->{$location};
90 0 0       0 return undef unless exists $self->cache->{$location}->{$what};
91 0         0 $self->cache->{$location}->{last_retrieved} = _now;
92 0         0 return $self->cache->{$location}->{$what}->{value};
93             }
94              
95             =head3 set_cache
96              
97             $caching->set_cache( $what, $location, $value )
98              
99             =cut
100              
101             sub set_cache {
102 4     4 1 7 my $self = shift;
103 4         7 my $what = shift;
104 4         8 my $location = shift;
105 4         8 my $value = shift;
106 4         19 $self->_prune;
107 4         44 return $self->cache->{$location}->{$what}->{value} = $value;
108             }
109              
110             =head3 clear_cache
111              
112             $caching->clear_cache( $what, $location )
113              
114             =cut
115              
116             sub clear_cache {
117 4     4 1 7 my $self = shift;
118 4         7 my $what = shift;
119 4         13 my $location = shift;
120 4         22 return delete $self->cache->{$location}->{$what};
121             }
122              
123             =head3 empty_cache
124              
125             $caching->empty_cache( $what, $location )
126              
127             =cut
128              
129             sub empty_cache {
130 6     6 1 16 my $self = shift;
131 6         10 delete $self->cache->{$_} for keys %{ $self->cache };
  6         63  
132             }
133              
134             sub _prune {
135 4     4   6 my $self = shift;
136 4         63 my $to_remove = ( keys %{ $self->cache } ) - $self->max_keys;
  4         30  
137 4 50       18 if ( $to_remove > 1 ) {
138 0           $to_remove = $to_remove +
139             int( $self->max_keys / 4 ); # so we don't have to do this too often
140 0           foreach my $location (
  0            
141             sort {
142 0           $self->cached->{$a}->{last_retrieved}
143             cmp $self->cached->{$b}->{last_retrieved}
144             } keys %{ $self->cached }
145             )
146             {
147 0           delete $self->cached->{$location};
148 0 0         last unless --$to_remove;
149             }
150             }
151             }
152              
153             1;