Commit | Line | Data |
c28ee69c |
1 | #!/usr/bin/perl |
2 | |
3 | package Catalyst::Plugin::Cache; |
5662d9dc |
4 | use Moose; |
c28ee69c |
5 | |
5662d9dc |
6 | with 'Catalyst::ClassData'; |
c28ee69c |
7 | |
d1cb9db3 |
8 | our $VERSION = "0.12"; |
d6861a7f |
9 | |
c28ee69c |
10 | use Scalar::Util (); |
23b2d59b |
11 | use Catalyst::Utils (); |
c28ee69c |
12 | use Carp (); |
ab8e499f |
13 | use MRO::Compat; |
a78b4047 |
14 | use Scalar::Util qw/ blessed /; |
2e4bde89 |
15 | use Catalyst::Plugin::Cache::Curried; |
16 | |
c28ee69c |
17 | __PACKAGE__->mk_classdata( "_cache_backends" ); |
5662d9dc |
18 | has _default_curried_cache => ( |
19 | is => 'rw', |
20 | ); |
21 | no Moose; |
c28ee69c |
22 | |
23 | sub setup { |
24 | my $app = shift; |
25 | |
26 | # set it once per app, not once per plugin, |
27 | # and don't overwrite if some plugin was wicked |
28 | $app->_cache_backends({}) unless $app->_cache_backends; |
29 | |
ab8e499f |
30 | my $ret = $app->maybe::next::method( @_ ); |
c28ee69c |
31 | |
32 | $app->setup_cache_backends; |
33 | |
34 | $ret; |
35 | } |
4d098922 |
36 | { |
37 | my %has_warned_for; |
38 | sub _get_cache_plugin_config { |
39 | my ($app) = @_; |
40 | my $config = $app->config->{'Plugin::Cache'}; |
41 | if (!$config) { |
42 | $config = $app->config->{cache}; |
43 | my $appname = ref($app); |
44 | if (! $has_warned_for{$appname}++ ) { |
45 | $app->log->warn($config ? |
46 | 'Catalyst::Plugin::Cache config found in deprecated $c->config->{cache}, please move to $c->config->{"Plugin::Cache"}.' |
47 | : 'Catalyst::Plugin::Cache config not found, using empty config!' |
48 | ); |
49 | } |
50 | } |
51 | return $config || {}; |
52 | } |
0ba5145c |
53 | } |
54 | |
23b2d59b |
55 | sub get_default_cache_backend_config { |
56 | my ( $app, $name ) = @_; |
0ba5145c |
57 | $app->_get_cache_plugin_config->{backend} || $app->get_cache_backend_config("default"); |
23b2d59b |
58 | } |
59 | |
60 | sub get_cache_backend_config { |
61 | my ( $app, $name ) = @_; |
0ba5145c |
62 | $app->_get_cache_plugin_config->{backends}{$name}; |
23b2d59b |
63 | } |
64 | |
65 | sub setup_cache_backends { |
66 | my $app = shift; |
67 | |
68 | # give plugins a chance to find things for themselves |
ab8e499f |
69 | $app->maybe::next::method; |
23b2d59b |
70 | |
0ba5145c |
71 | # FIXME - Don't know why the _get_cache_plugin_config method doesn't work here! |
4d098922 |
72 | my $conf = $app->_get_cache_plugin_config->{backends}; |
0ba5145c |
73 | foreach my $name ( keys %$conf ) { |
23b2d59b |
74 | next if $app->get_cache_backend( $name ); |
75 | $app->setup_generic_cache_backend( $name, $app->get_cache_backend_config( $name ) || {} ); |
76 | } |
77 | |
33002c69 |
78 | if ( !$app->get_cache_backend("default") ) { |
fba82fef |
79 | ### XXX currently we dont have a fallback scenario |
80 | ### so die here with the error message. Once we have |
81 | ### an in memory fallback, we may consider silently |
82 | ### logging the error and falling back to that. |
83 | ### If we dont die here, the app will silently start |
84 | ### up and then explode at the first cache->get or |
85 | ### cache->set request with a FIXME error |
86 | #local $@; |
87 | #eval { |
88 | $app->setup_generic_cache_backend( default => $app->get_default_cache_backend_config || {} ); |
89 | #}; |
90 | |
85a748b9 |
91 | } |
23b2d59b |
92 | } |
93 | |
94 | sub default_cache_store { |
95 | my $app = shift; |
0ba5145c |
96 | $app->_get_cache_plugin_config->{default_store} || $app->guess_default_cache_store; |
23b2d59b |
97 | } |
98 | |
99 | sub guess_default_cache_store { |
100 | my $app = shift; |
101 | |
102 | my @stores = map { /Cache::Store::(.*)$/ ? $1 : () } $app->registered_plugins; |
103 | |
104 | if ( @stores == 1 ) { |
105 | return $stores[0]; |
106 | } else { |
107 | Carp::croak "You must configure a default store type unless you use exactly one store plugin."; |
108 | } |
109 | } |
110 | |
111 | sub setup_generic_cache_backend { |
112 | my ( $app, $name, $config ) = @_; |
113 | my %config = %$config; |
114 | |
115 | if ( my $class = delete $config{class} ) { |
fba82fef |
116 | |
117 | ### try as list and as hashref, collect the |
118 | ### error if things go wrong |
119 | ### if all goes well, exit the loop |
120 | my @errors; |
121 | for my $aref ( [%config], [\%config] ) { |
122 | eval { $app->setup_cache_backend_by_class( |
123 | $name, $class, @$aref |
124 | ); |
125 | } ? do { @errors = (); last } |
126 | : push @errors, "\t$@"; |
127 | } |
128 | |
129 | ### and die with the errors if we have any |
130 | die "Couldn't construct $class with either list style or hash ref style param passing:\n @errors" if @errors; |
131 | |
23b2d59b |
132 | } elsif ( my $store = delete $config->{store} || $app->default_cache_store ) { |
133 | my $method = lc("setup_${store}_cache_backend"); |
134 | |
135 | Carp::croak "You must load the $store cache store plugin (if it exists). ". |
136 | "Please consult the Catalyst::Plugin::Cache documentation on how to configure hetrogeneous stores." |
137 | unless $app->can($method); |
138 | |
887cc08f |
139 | $app->$method( $name, \%config ); |
23b2d59b |
140 | } else { |
141 | $app->log->warn("Couldn't setup the cache backend named '$name'"); |
142 | } |
143 | } |
144 | |
145 | sub setup_cache_backend_by_class { |
146 | my ( $app, $name, $class, @args ) = @_; |
147 | Catalyst::Utils::ensure_class_loaded( $class ); |
148 | $app->register_cache_backend( $name => $class->new( @args ) ); |
149 | } |
150 | |
151 | # end of spaghetti setup DWIM |
c28ee69c |
152 | |
153 | sub cache { |
2e4bde89 |
154 | my ( $c, @meta ) = @_; |
155 | |
156 | if ( @meta == 1 ) { |
157 | my $name = $meta[0]; |
158 | return ( $c->get_preset_curried($name) || $c->get_cache_backend($name) ); |
a78b4047 |
159 | } elsif ( !@meta && blessed $c ) { |
2e4bde89 |
160 | # be nice and always return the same one for the simplest case |
161 | return ( $c->_default_curried_cache || $c->_default_curried_cache( $c->curry_cache( @meta ) ) ); |
c28ee69c |
162 | } else { |
2e4bde89 |
163 | return $c->curry_cache( @meta ); |
c28ee69c |
164 | } |
165 | } |
166 | |
5a00a29b |
167 | sub construct_curried_cache { |
168 | my ( $c, @meta ) = @_; |
169 | return $c->curried_cache_class( @meta )->new( @meta ); |
170 | } |
171 | |
172 | sub curried_cache_class { |
173 | my ( $c, @meta ) = @_; |
0ba5145c |
174 | $c->_get_cache_plugin_config->{curried_class} || "Catalyst::Plugin::Cache::Curried"; |
5a00a29b |
175 | } |
176 | |
2e4bde89 |
177 | sub curry_cache { |
178 | my ( $c, @meta ) = @_; |
5a00a29b |
179 | return $c->construct_curried_cache( $c, $c->_cache_caller_meta, @meta ); |
2e4bde89 |
180 | } |
181 | |
182 | sub get_preset_curried { |
183 | my ( $c, $name ) = @_; |
184 | |
0ba5145c |
185 | if ( ref( my $preset = $c->_get_cache_plugin_config->{profiles}{$name} ) ) { |
2e4bde89 |
186 | return $preset if Scalar::Util::blessed($preset); |
187 | |
188 | my @meta = ( ( ref $preset eq "HASH" ) ? %$preset : @$preset ); |
189 | return $c->curry_cache( @meta ); |
190 | } |
191 | |
192 | return; |
193 | } |
194 | |
c28ee69c |
195 | sub get_cache_backend { |
196 | my ( $c, $name ) = @_; |
197 | $c->_cache_backends->{$name}; |
198 | } |
199 | |
200 | sub register_cache_backend { |
201 | my ( $c, $name, $backend ) = @_; |
202 | |
203 | no warnings 'uninitialized'; |
204 | Carp::croak("$backend does not look like a cache backend - " |
aed484da |
205 | . "it must be an object supporting get, set and remove") |
206 | unless eval { $backend->can("get") && $backend->can("set") && $backend->can("remove") }; |
c28ee69c |
207 | |
208 | $c->_cache_backends->{$name} = $backend; |
209 | } |
210 | |
211 | sub unregister_cache_backend { |
212 | my ( $c, $name ) = @_; |
213 | delete $c->_cache_backends->{$name}; |
214 | } |
215 | |
216 | sub default_cache_backend { |
217 | my $c = shift; |
218 | $c->get_cache_backend( "default" ) || $c->temporary_cache_backend; |
219 | } |
220 | |
221 | sub temporary_cache_backend { |
222 | my $c = shift; |
223 | die "FIXME - make up an in memory cache backend, that hopefully works well for the current engine"; |
224 | } |
225 | |
5a00a29b |
226 | sub _cache_caller_meta { |
227 | my $c = shift; |
228 | |
229 | my ( $caller, $component, $controller ); |
230 | |
231 | for my $i ( 0 .. 15 ) { # don't look to far |
232 | my @info = caller(2 + $i) or last; |
233 | |
85a748b9 |
234 | $caller ||= \@info unless $info[0] =~ /Plugin::Cache/; |
5a00a29b |
235 | $component ||= \@info if $info[0]->isa("Catalyst::Component"); |
236 | $controller ||= \@info if $info[0]->isa("Catalyst::Controller"); |
237 | |
238 | last if $caller && $component && $controller; |
239 | } |
240 | |
85a748b9 |
241 | my ( $caller_pkg, $component_pkg, $controller_pkg ) = |
242 | map { $_ ? $_->[0] : undef } $caller, $component, $controller; |
243 | |
5a00a29b |
244 | return ( |
85a748b9 |
245 | 'caller' => $caller_pkg, |
246 | component => $component_pkg, |
247 | controller => $controller_pkg, |
248 | caller_frame => $caller, |
249 | component_frame => $component, |
250 | controller_frame => $controller, |
5a00a29b |
251 | ); |
252 | } |
253 | |
c28ee69c |
254 | # this gets a shit name so that the plugins can override a good name |
255 | sub choose_cache_backend_wrapper { |
256 | my ( $c, @meta ) = @_; |
257 | |
c627df81 |
258 | Carp::croak("metadata must be an even sized list") unless @meta % 2 == 0; |
c28ee69c |
259 | |
260 | my %meta = @meta; |
5a00a29b |
261 | |
262 | unless ( exists $meta{'caller'} ) { |
263 | my %caller = $c->_cache_caller_meta; |
264 | @meta{keys %caller} = values %caller; |
265 | } |
c28ee69c |
266 | |
267 | # allow the cache client to specify who it wants to cache with (but loeave room for a hook) |
268 | if ( exists $meta{backend} ) { |
269 | if ( Scalar::Util::blessed($meta{backend}) ) { |
270 | return $meta{backend}; |
271 | } else { |
272 | return $c->get_cache_backend( $meta{backend} ) || $c->default_cache_backend; |
273 | } |
274 | }; |
275 | |
c28ee69c |
276 | if ( my $chosen = $c->choose_cache_backend( %meta ) ) { |
277 | $chosen = $c->get_cache_backend( $chosen ) unless Scalar::Util::blessed($chosen); # if it's a name find it |
278 | return $chosen if Scalar::Util::blessed($chosen); # only return if it was an object or name lookup worked |
279 | |
280 | # FIXME |
281 | # die "no such backend"? |
282 | # currently, we fall back to default |
283 | } |
284 | |
285 | return $c->default_cache_backend; |
286 | } |
287 | |
ab8e499f |
288 | sub choose_cache_backend { shift->maybe::next::method( @_ ) } # a convenient fallback |
c28ee69c |
289 | |
290 | sub cache_set { |
390db05f |
291 | my ( $c, $key, $value, %meta ) = @_; |
292 | $c->choose_cache_backend_wrapper( key => $key, value => $value, %meta ) |
293 | ->set( $key, $value, exists $meta{expires} ? $meta{expires} : () ); |
c28ee69c |
294 | } |
295 | |
296 | sub cache_get { |
297 | my ( $c, $key, @meta ) = @_; |
298 | $c->choose_cache_backend_wrapper( key => $key, @meta )->get( $key ); |
299 | } |
300 | |
aed484da |
301 | sub cache_remove { |
c28ee69c |
302 | my ( $c, $key, @meta ) = @_; |
aed484da |
303 | $c->choose_cache_backend_wrapper( key => $key, @meta )->remove( $key ); |
c28ee69c |
304 | } |
305 | |
26dcff5b |
306 | sub cache_compute { |
307 | my ($c, $key, $code, %meta) = @_; |
308 | |
309 | my $backend = $c->choose_cache_backend_wrapper( key => $key, %meta ); |
310 | if ($backend->can('compute')) { |
311 | return $backend->compute( $key, $code, exists $meta{expires} ? $meta{expires} : () ); |
312 | } |
313 | |
314 | Carp::croak "must specify key and code" unless defined($key) && defined($code); |
315 | |
316 | my $value = $c->cache_get( $key, %meta ); |
317 | if ( !defined $value ) { |
318 | $value = $code->(); |
319 | $c->cache_set( $key, $value, %meta ); |
320 | } |
321 | return $value; |
322 | } |
323 | |
c28ee69c |
324 | __PACKAGE__; |
325 | |
326 | __END__ |
327 | |
328 | =pod |
329 | |
330 | =head1 NAME |
331 | |
85a748b9 |
332 | Catalyst::Plugin::Cache - Flexible caching support for Catalyst. |
c28ee69c |
333 | |
334 | =head1 SYNOPSIS |
335 | |
5a00a29b |
336 | use Catalyst qw/ |
337 | Cache |
338 | /; |
339 | |
340 | # configure a backend or use a store plugin |
0ba5145c |
341 | __PACKAGE__->config->{'Plugin::Cache'}{backend} = { |
85a748b9 |
342 | class => "Cache::Bounded", |
fba82fef |
343 | # ... params for Cache::Bounded... |
85a748b9 |
344 | }; |
5a00a29b |
345 | |
fba82fef |
346 | # typical example for Cache::Memcached::libmemcached |
0ba5145c |
347 | __PACKAGE__->config->{'Plugin::Cache'}{backend} = { |
fba82fef |
348 | class => "Cache::Memcached::libmemcached", |
349 | servers => ['127.0.0.1:11211'], |
350 | debug => 2, |
351 | }; |
352 | |
353 | |
c627df81 |
354 | # In a controller: |
5a00a29b |
355 | |
356 | sub foo : Local { |
357 | my ( $self, $c, $id ) = @_; |
358 | |
359 | my $cache = $c->cache; |
360 | |
361 | my $result; |
362 | |
363 | unless ( $result = $cache->get( $id ) ) { |
c627df81 |
364 | # ... calculate result ... |
5a00a29b |
365 | $c->cache->set( $id, $result ); |
366 | } |
367 | }; |
c28ee69c |
368 | |
369 | =head1 DESCRIPTION |
370 | |
c627df81 |
371 | This plugin gives you access to a variety of systems for caching |
372 | data. It allows you to use a very simple configuration API, while |
373 | maintaining the possibility of flexibility when you need it later. |
5a00a29b |
374 | |
c627df81 |
375 | Among its features are support for multiple backends, segmentation based |
376 | on component or controller, keyspace partitioning, and so more, in |
377 | various subsidiary plugins. |
5a00a29b |
378 | |
85a748b9 |
379 | =head1 METHODS |
380 | |
381 | =over 4 |
382 | |
383 | =item cache $profile_name |
384 | |
385 | =item cache %meta |
386 | |
c627df81 |
387 | Return a curried object with metadata from C<$profile_name> or as |
388 | explicitly specified. |
85a748b9 |
389 | |
c627df81 |
390 | If a profile by the name C<$profile_name> doesn't exist, but a backend |
391 | object by that name does exist, the backend will be returned instead, |
392 | since the interface for curried caches and backends is almost identical. |
85a748b9 |
393 | |
c627df81 |
394 | This method can also be called without arguments, in which case is |
395 | treated as though the C<%meta> hash was empty. |
85a748b9 |
396 | |
c627df81 |
397 | See L</METADATA> for details. |
85a748b9 |
398 | |
399 | =item curry_cache %meta |
400 | |
c627df81 |
401 | Return a L<Catalyst::Plugin::Cache::Curried> object, curried with C<%meta>. |
85a748b9 |
402 | |
c627df81 |
403 | See L</METADATA> for details. |
85a748b9 |
404 | |
405 | =item cache_set $key, $value, %meta |
406 | |
407 | =item cache_get $key, %meta |
408 | |
409 | =item cache_remove $key, %meta |
410 | |
26dcff5b |
411 | =item cache_compute $key, $code, %meta |
412 | |
c627df81 |
413 | These cache operations will call L<choose_cache_backend> with %meta, and |
26dcff5b |
414 | then call C<set>, C<get>, C<remove>, or C<compute> on the resulting backend |
415 | object. |
416 | |
417 | If the backend object does not support C<compute> then we emulate it by |
418 | calling L<cache_get>, and if the returned value is undefined we call the passed |
419 | code reference, stores the returned value with L<cache_set>, and then returns |
420 | the value. Inspired by L<CHI>. |
85a748b9 |
421 | |
422 | =item choose_cache_backend %meta |
423 | |
c627df81 |
424 | Select a backend object. This should return undef if no specific backend |
425 | was selected - its caller will handle getting C<default_cache_backend> |
426 | on its own. |
85a748b9 |
427 | |
428 | This method is typically used by plugins. |
429 | |
430 | =item get_cache_backend $name |
431 | |
432 | Get a backend object by name. |
433 | |
434 | =item default_cache_backend |
435 | |
436 | Return the default backend object. |
437 | |
438 | =item temporary_cache_backend |
439 | |
c627df81 |
440 | When no default cache backend is configured this method might return a |
441 | backend known to work well with the current L<Catalyst::Engine>. This is |
442 | a stub. |
85a748b9 |
443 | |
444 | =item |
445 | |
446 | =back |
447 | |
c627df81 |
448 | =head1 METADATA |
85a748b9 |
449 | |
450 | =head2 Introduction |
451 | |
c627df81 |
452 | Whenever you set or retrieve a key you may specify additional metadata |
453 | that will be used to select a specific backend. |
85a748b9 |
454 | |
455 | This metadata is very freeform, and the only key that has any meaning by |
456 | default is the C<backend> key which can be used to explicitly choose a backend |
457 | by name. |
458 | |
c627df81 |
459 | The C<choose_cache_backend> method can be overridden in order to |
460 | facilitate more intelligent backend selection. For example, |
461 | L<Catalyst::Plugin::Cache::Choose::KeyRegexes> overrides that method to |
462 | select a backend based on key regexes. |
85a748b9 |
463 | |
c627df81 |
464 | Another example is a L<Catalyst::Plugin::Cache::ControllerNamespacing>, |
465 | which wraps backends in objects that perform key mangling, in order to |
466 | keep caches namespaced per controller. |
85a748b9 |
467 | |
468 | However, this is generally left as a hook for larger, more complex |
c627df81 |
469 | applications. Most configurations should make due XXXX |
85a748b9 |
470 | |
c627df81 |
471 | The simplest way to dynamically select a backend is based on the |
472 | L</Cache Profiles> configuration. |
85a748b9 |
473 | |
474 | =head2 Meta Data Keys |
475 | |
476 | C<choose_cache_backend> is called with some default keys. |
477 | |
478 | =over 4 |
479 | |
480 | =item key |
481 | |
c627df81 |
482 | Supplied by C<cache_get>, C<cache_set>, and C<cache_remove>. |
85a748b9 |
483 | |
484 | =item value |
485 | |
c627df81 |
486 | Supplied by C<cache_set>. |
85a748b9 |
487 | |
488 | =item caller |
489 | |
490 | The package name of the innermost caller that doesn't match |
491 | C<qr/Plugin::Cache/>. |
492 | |
493 | =item caller_frame |
494 | |
495 | The entire C<caller($i)> frame of C<caller>. |
496 | |
497 | =item component |
498 | |
c627df81 |
499 | The package name of the innermost caller who C<isa> |
500 | L<Catalyst::Component>. |
85a748b9 |
501 | |
502 | =item component_frame |
503 | |
504 | This entire C<caller($i)> frame of C<component>. |
505 | |
506 | =item controller |
507 | |
c627df81 |
508 | The package name of the innermost caller who C<isa> |
509 | L<Catalyst::Controller>. |
85a748b9 |
510 | |
511 | =item controller_frame |
512 | |
513 | This entire C<caller($i)> frame of C<controller>. |
514 | |
515 | =back |
516 | |
c627df81 |
517 | =head2 Metadata Currying |
85a748b9 |
518 | |
c627df81 |
519 | In order to avoid specifying C<%meta> over and over again you may call |
520 | C<cache> or C<curry_cache> with C<%meta> once, and get back a B<curried |
521 | cache object>. This object responds to the methods C<get>, C<set>, and |
522 | C<remove>, by appending its captured metadata and delegating them to |
523 | C<cache_get>, C<cache_set>, and C<cache_remove>. |
85a748b9 |
524 | |
525 | This is simpler than it sounds. |
526 | |
527 | Here is an example using currying: |
528 | |
529 | my $cache = $c->cache( %meta ); # cache is curried |
530 | |
531 | $cache->set( $key, $value ); |
532 | |
533 | $cache->get( $key ); |
534 | |
535 | And here is an example without using currying: |
536 | |
537 | $c->cache_set( $key, $value, %meta ); |
538 | |
539 | $c->cache_get( $key, %meta ); |
540 | |
541 | See L<Catalyst::Plugin::Cache::Curried> for details. |
542 | |
0f0237aa |
543 | =head1 CONFIGURATION |
544 | |
0ba5145c |
545 | $c->config->{'Plugin::Cache'} = { |
85a748b9 |
546 | ... |
547 | }; |
0f0237aa |
548 | |
c627df81 |
549 | All configuration parameters should be provided in a hash reference |
0ba5145c |
550 | under the C<Plugin::Cache> key in the C<config> hash. |
0f0237aa |
551 | |
85a748b9 |
552 | =head2 Backend Configuration |
553 | |
554 | Configuring backend objects is done by adding hash entries under the |
c627df81 |
555 | C<backends> key in the main config. |
85a748b9 |
556 | |
c627df81 |
557 | A special case is that the hash key under the C<backend> (singular) key |
558 | of the main config is assumed to be the backend named C<default>. |
85a748b9 |
559 | |
0f0237aa |
560 | =over 4 |
561 | |
562 | =item class |
563 | |
85a748b9 |
564 | Instantiate a backend from a L<Cache> compatible class. E.g. |
0f0237aa |
565 | |
0ba5145c |
566 | $c->config->{'Plugin::Cache'}{backends}{small_things} = { |
85a748b9 |
567 | class => "Cache::Bounded", |
568 | interval => 1000, |
569 | size => 10000, |
570 | }; |
571 | |
0ba5145c |
572 | $c->config->{'Plugin::Cache'}{backends}{large_things} = { |
bd2e2f72 |
573 | class => "Cache::Memcached", |
85a748b9 |
574 | data => '1.2.3.4:1234', |
575 | }; |
0f0237aa |
576 | |
85a748b9 |
577 | The options in the hash are passed to the class's C<new> method. |
0f0237aa |
578 | |
85a748b9 |
579 | The class will be C<required> as necessary during setup time. |
0f0237aa |
580 | |
85a748b9 |
581 | =item store |
0f0237aa |
582 | |
c627df81 |
583 | Instantiate a backend using a store plugin, e.g. |
0f0237aa |
584 | |
0ba5145c |
585 | $c->config->{'Plugin::Cache'}{backend} = { |
85a748b9 |
586 | store => "FastMmap", |
587 | }; |
0f0237aa |
588 | |
c627df81 |
589 | Store plugins typically require less configuration because they are |
590 | specialized for L<Catalyst> applications. For example |
85a748b9 |
591 | L<Catalyst::Plugin::Cache::Store::FastMmap> will specify a default |
c627df81 |
592 | C<share_file>, and additionally use a subclass of L<Cache::FastMmap> |
593 | that can also store non reference data. |
85a748b9 |
594 | |
595 | The store plugin must be loaded. |
596 | |
597 | =back |
0f0237aa |
598 | |
85a748b9 |
599 | =head2 Cache Profiles |
600 | |
601 | =over 4 |
0f0237aa |
602 | |
603 | =item profiles |
604 | |
c627df81 |
605 | Supply your own predefined profiles for cache metadata, when using the |
606 | C<cache> method. |
85a748b9 |
607 | |
608 | For example when you specify |
609 | |
0ba5145c |
610 | $c->config->{'Plugin::Cache'}{profiles}{thumbnails} = { |
85a748b9 |
611 | backend => "large_things", |
612 | }; |
613 | |
614 | And then get a cache object like this: |
615 | |
616 | $c->cache("thumbnails"); |
617 | |
618 | It is the same as if you had done: |
619 | |
620 | $c->cache( backend => "large_things" ); |
621 | |
622 | =back |
623 | |
c627df81 |
624 | =head2 Miscellaneous Configuration |
85a748b9 |
625 | |
626 | =over 4 |
627 | |
628 | =item default_store |
629 | |
c627df81 |
630 | When you do not specify a C<store> parameter in the backend |
631 | configuration this one will be used instead. This configuration |
632 | parameter is not necessary if only one store plugin is loaded. |
0f0237aa |
633 | |
634 | =back |
635 | |
636 | =head1 TERMINOLOGY |
23b2d59b |
637 | |
638 | =over 4 |
639 | |
640 | =item backend |
641 | |
642 | An object that responds to the methods detailed in |
643 | L<Catalyst::Plugin::Cache::Backend> (or more). |
644 | |
645 | =item store |
646 | |
c627df81 |
647 | A plugin that provides backends of a certain type. This is a bit like a |
648 | factory. |
23b2d59b |
649 | |
0f0237aa |
650 | =item cache |
651 | |
652 | Stored key/value pairs of data for easy re-access. |
653 | |
c627df81 |
654 | =item metadata |
85a748b9 |
655 | |
c627df81 |
656 | "Extra" information about the item being stored, which can be used to |
657 | locate an appropriate backend. |
85a748b9 |
658 | |
23b2d59b |
659 | =item curried cache |
660 | |
0f0237aa |
661 | my $cache = $c->cache(type => 'thumbnails'); |
662 | $cache->set('pic01', $thumbnaildata); |
663 | |
c627df81 |
664 | A cache which has been pre-configured with a particular set of |
665 | namespacing data. In the example the cache returned could be one |
666 | specifically tuned for storing thumbnails. |
0f0237aa |
667 | |
c627df81 |
668 | An object that responds to C<get>, C<set>, and C<remove>, and will |
669 | automatically add metadata to calls to C<< $c->cache_get >>, etc. |
23b2d59b |
670 | |
671 | =back |
672 | |
772299b1 |
673 | =head1 SEE ALSO |
674 | |
c627df81 |
675 | L<Cache> - the generic cache API on CPAN. |
772299b1 |
676 | |
677 | L<Catalyst::Plugin::Cache::Store> - how to write a store plugin. |
678 | |
679 | L<Catalyst::Plugin::Cache::Curried> - the interface for curried caches. |
680 | |
681 | L<Catalyst::Plugin::Cache::Choose::KeyRegexes> - choose a backend based on |
682 | regex matching on the keys. Can be used to partition the keyspace. |
683 | |
684 | L<Catalyst::Plugin::Cache::ControllerNamespacing> - wrap backend objects in a |
c627df81 |
685 | name mangler so that every controller gets its own keyspace. |
772299b1 |
686 | |
271f5106 |
687 | =head1 AUTHOR |
688 | |
689 | Yuval Kogman, C<nothingmuch@woobling.org> |
690 | |
dc5fda2b |
691 | Jos Boumans, C<kane@cpan.org> |
692 | |
271f5106 |
693 | =head1 COPYRIGHT & LICENSE |
c28ee69c |
694 | |
271f5106 |
695 | Copyright (c) Yuval Kogman, 2006. All rights reserved. |
696 | |
697 | This library is free software, you can redistribute it and/or modify it under |
698 | the same terms as Perl itself, as well as under the terms of the MIT license. |
699 | |
700 | =cut |
c28ee69c |
701 | |