File Coverage

blib/lib/CGI/Application/Plugin/Cache/Adaptive.pm
Criterion Covered Total %
statement 33 83 39.7
branch 0 42 0.0
condition 0 11 0.0
subroutine 11 15 73.3
pod 1 2 50.0
total 45 153 29.4


line stmt bran cond sub pod time code
1             package CGI::Application::Plugin::Cache::Adaptive;
2              
3 5     5   63070 use strict;
  5         12  
  5         178  
4 5     5   156 use warnings;
  5         10  
  5         157  
5              
6 5     5   62 use base qw(Exporter);
  5         9  
  5         406  
7 5     5   7779 use Attribute::Handlers;
  5         30163  
  5         31  
8 5     5   5328 use Cache::Adaptive;
  5         41267  
  5         81  
9 5     5   238 use Carp qw(croak);
  5         11  
  5         552  
10 5     5   6078 use Class::Inspector;
  5         20533  
  5         212  
11 5     5   3162 use Storable qw(freeze);
  5         10632  
  5         3074  
12              
13             our @EXPORT = qw(&cache_adaptive);
14              
15             =head1 NAME
16              
17             CGI::Application::Plugin::Cache::Adaptive - Provide cacheable to method using attribute.
18              
19             =head1 VERSION
20              
21             version 0.03
22              
23             =cut
24              
25             our $VERSION = '0.03';
26              
27             =head1 SYNOPSIS
28              
29             package MyApp;
30             use base qw(CGI::Application);
31             use CGI::Application::Plugin::Cache::Adaptive;
32            
33             use Cache::FileCache;
34            
35             sub setup {
36             my $self = shift;
37              
38             $self->start_mode('default');
39             $self->run_modes(
40             'default' => 'do_default'
41             );
42            
43             $self->cache_adaptive({
44             backend => Cache::FileCache->new({
45             namespace => 'html_cache',
46             max_size => 10 * 1024 * 1024,
47             }),
48             expires_min => 3,
49             expires_max => 60,
50             check_load => sub {
51             my $entry = shift;
52             int($entry->{process_time} * 2) - 1;
53             },
54             });
55             }
56            
57             sub do_default : Cacheable(qw/path path_info query/) {
58             sleep 10;
59             return "test";
60             }
61              
62             =head1 DESCRIPTION
63              
64             This module provides adaptive cache to specified method by 'Cacheable' attribute.
65             Cache mechanism depends on L.
66              
67             =head1 USAGE
68              
69             =head2 Cacheable attribute
70              
71             Cacheable attribute is able to accept some arguments.
72             The arguments effects L behavior.
73              
74             The arguments must be array or hash reference.
75             See below the arguments detail.
76              
77             =over 4
78              
79             =item Array arguments
80              
81             Example,
82              
83             sub do_something : Cacheable(qw/path session/) {
84             # process by user
85             }
86              
87             Array arguments accepts 4 items,
88              
89             =over 4
90              
91             =item path
92              
93             Add path(script_name) to cache key salt.
94              
95             =item query
96              
97             Add query string to cache key salt.
98              
99             =item path_info
100              
101             Add path_info to cache key salt.
102              
103             =item session
104              
105             Add session_id to cache key salt.
106              
107             =back
108              
109             =item Hash reference arguments
110              
111             Example,
112              
113             sub do_something : Cacheable({key_from => [qw/path path_info/], label => 'memcached'}) {
114             # some process
115             }
116              
117             Hash reference accepts 2 original key and any key permitted by L's access method.
118              
119             =over 4
120              
121             =item key_from
122              
123             Same as array arguments. See L.
124              
125             =item label
126              
127             Change cache profile to specified labeled cache object.
128             See L.
129              
130             =back
131              
132             =back
133              
134             =head1 METHODS
135              
136             =head2 cache_adaptive()
137              
138             Alias cache_adaptive('default').
139             See L
140              
141             =head2 cache_adaptive($label)
142              
143             Get L object by label.
144              
145             =head2 cache_adaptive($hash_ref)
146              
147             Set L object to 'default' label.
148             The $hash_ref is L's new parameter.
149              
150             =head2 cache_adaptive($cache_obj)
151              
152             Set L or that inheritance object to 'default' label.
153              
154             =head2 cache_adaptive($label, $hash_ref)
155              
156             Set L object to specified label.
157             The $hash_ref is L's new parameter.
158              
159             =head2 cache_adaptive($label, $cache_obj)
160              
161             Set L or that inheritance object to specified label.
162              
163             =cut
164              
165             sub cache_adaptive {
166 0     0 1   my $self = shift;
167              
168 0 0         if (@_ == 2) {
    0          
169 0 0         if (UNIVERSAL::isa($_[1], 'Cache::Adaptive')) {
170 0           $self->{'Cache::Adaptive::cache_adaptive'}{$_[0]} = $_[1];
171             }
172             else {
173 0           $self->{'Cache::Adaptive::cache_adaptive'}{$_[0]} = Cache::Adaptive->new($_[1]);
174             }
175             }
176             elsif (@_ == 1) {
177 0 0         if (UNIVERSAL::isa($_[0], 'Cache::Adaptive')) {
    0          
178 0           return $self->{'Cache::Adaptive::cache_adaptive'}{'default'} = $_[0];
179             }
180             elsif (ref $_[0] eq 'HASH') {
181 0           $self->{'Cache::Adaptive::cache_adaptive'}{'default'} = Cache::Adaptive->new($_[0]);
182             }
183             else {
184 0           return $self->{'Cache::Adaptive::cache_adaptive'}{$_[0]};
185             }
186             }
187             else {
188 0           return $self->{'Cache::Adaptive::cache_adaptive'}{'default'};
189             }
190             }
191              
192             =head2 CGI::Application::Cacheable()
193              
194             Provide cacheable to specified method.
195             See L
196              
197             =cut
198              
199             sub CGI::Application::Cacheable : ATTR(CODE,BEGIN) {
200 0     0 0   my ($package, $symbol, $referent, $attr, $data, $phase) = @_;
201              
202 0           my %key_index = (
203             'path' => 0,
204             'query' => 1,
205             'path_info' => 2,
206             'session' => 3
207             );
208              
209             $package->add_callback('init',
210             sub {
211 0     0     my $self = shift;
212              
213             ### In the next process, runmode will be rededined.
214             ### In CAP::AutoRunmode, it was cached code reference before redefined.
215             ### Therefore now start_mode and error_mode must be static value.
216 0 0         if (Class::Inspector->loaded('CGI::Application::Plugin::AutoRunmode')) {
217 0           $self->start_mode;
218 0           $self->error_mode;
219             }
220             }
221 0           );
222              
223             $package->add_callback('init',
224             sub {
225 0     0     my ($self, @args) = @_;
226              
227 0 0         $data = {} unless ($data);
228 0           my $data_type = ref $data;
229              
230 0 0 0       if ($data_type eq 'ARRAY' || $data_type eq 'HASH') {
231 0 0 0       my $label = ($data_type eq 'HASH') ? delete $data->{label} || 'default' : 'default';
232 0 0         my $key_from = ($data_type eq 'HASH') ? delete $data->{key_from} : $data;
233 0 0 0       $key_from = [qw(path)] if (!$key_from || @$key_from == 0);
234              
235 0 0         my %extra_params = ($data_type eq 'HASH') ? %$data : ();
236              
237 0           my $method = (grep { $package->can($_) == $referent } @{Class::Inspector->methods($package)})[0];
  0            
  0            
238 0 0         return unless ($method);
239              
240             {
241 5     5   37 no strict 'refs';
  5         9  
  5         178  
  0            
242 5     5   26 no warnings 'redefine';
  5         8  
  5         2372  
243              
244 0           *{$package . "::" . $method} = sub {
245 0           my ($self, @args) = @_;
246              
247 0           local $CGI::USE_PARAM_SEMICOLONS = 0;
248 0           my @key_array = (undef, undef, undef, undef);
249              
250 0           for my $key (grep { exists $key_index{$_} } @$key_from) {
  0            
251 0           my $value = undef;
252              
253 0 0         $value = $self->query->script_name if ($key eq 'path');
254 0 0         $value = $self->query->query_string if ($key eq 'query');
255 0 0         $value = $self->query->path_info if ($key eq 'path_info');
256 0 0         $value = ($self->can('session')) ? $self->session->id : undef if ($key eq 'session');
    0          
257              
258 0 0 0       $key_array[$key_index{$key}] = $value if (exists $key_index{$key} && defined $value);
259             }
260              
261             # {
262             # my %debug = ();
263             # $debug{$_} = $key_array[$key_index{$_}] for (keys %key_index);
264             #
265             # $self->cache_adaptive($label)->log->(\%debug);
266             # }
267              
268             return $self->cache_adaptive($label)->access({
269             key => freeze(\@key_array),
270             builder => sub {
271 0           return $referent->($self, @args);
272             },
273 0           %extra_params
274             });
275 0           };
276              
277             ### If using CAP::AutoRunmode, it's code reference cache table must be refleshed.
278 0 0         if (Class::Inspector->loaded('CGI::Application::Plugin::AutoRunmode')) {
279 0 0         if (exists $CGI::Application::Plugin::AutoRunmode::RUNMODES{"$referent"}) {
280 0           delete $CGI::Application::Plugin::AutoRunmode::RUNMODES{"$referent"};
281 0           $CGI::Application::Plugin::AutoRunmode::RUNMODES{$package->can($method)} = 1;
282             }
283             }
284             }
285             }
286             }
287 0           );
288 5     5   31 }
  5         10  
  5         45  
289              
290             =head1 SEE ALSO
291              
292             =over 4
293              
294             =item L
295              
296             =item L
297              
298             =item L
299              
300             =item L
301              
302             =back
303              
304             =head1 AUTHOR
305              
306             Toru Yamaguchi, C<< >>
307              
308             =head1 THANKS
309              
310             Kazuho Oku, C<< >>
311              
312             =head1 BUGS
313              
314             Please report any bugs or feature requests to
315             C, or through the web interface at
316             L. I will be notified, and then you'll automatically be
317             notified of progress on your bug as I make changes.
318              
319             =head1 COPYRIGHT & LICENSE
320              
321             Copyright 2007 Toru Yamaguchi, All Rights Reserved.
322              
323             This program is free software; you can redistribute it and/or modify it
324             under the same terms as Perl itself.
325              
326             =cut
327              
328             1; # End of CGI::Application::Plugin::Cache::Adaptive