3 package Catalyst::Plugin::Cache;
4 use base qw/Class::Data::Inheritable Class::Accessor::Fast/;
10 use Catalyst::Utils ();
14 use Catalyst::Plugin::Cache::Curried;
16 __PACKAGE__->mk_classdata( "_cache_backends" );
17 __PACKAGE__->mk_accessors( "_default_curried_cache" );
22 # set it once per app, not once per plugin,
23 # and don't overwrite if some plugin was wicked
24 $app->_cache_backends({}) unless $app->_cache_backends;
26 my $ret = $app->NEXT::setup( @_ );
28 $app->setup_cache_backends;
33 sub get_default_cache_backend_config {
34 my ( $app, $name ) = @_;
35 $app->config->{cache}{backend} || $app->get_cache_backend_config("default");
38 sub get_cache_backend_config {
39 my ( $app, $name ) = @_;
40 $app->config->{cache}{backends}{$name};
43 sub setup_cache_backends {
46 # give plugins a chance to find things for themselves
47 $app->NEXT::setup_cache_backends;
49 foreach my $name ( keys %{ $app->config->{cache}{backends} } ) {
50 next if $app->get_cache_backend( $name );
51 $app->setup_generic_cache_backend( $name, $app->get_cache_backend_config( $name ) || {} );
54 if ( !$app->get_cache_backend("default") ) {
56 eval { $app->setup_generic_cache_backend( default => $app->get_default_cache_backend_config || {} ) };
60 sub default_cache_store {
62 $app->config->{cache}{default_store} || $app->guess_default_cache_store;
65 sub guess_default_cache_store {
68 my @stores = map { /Cache::Store::(.*)$/ ? $1 : () } $app->registered_plugins;
73 Carp::croak "You must configure a default store type unless you use exactly one store plugin.";
77 sub setup_generic_cache_backend {
78 my ( $app, $name, $config ) = @_;
79 my %config = %$config;
81 if ( my $class = delete $config{class} ) {
82 $app->setup_cache_backend_by_class( $name, $class, %config );
83 } elsif ( my $store = delete $config->{store} || $app->default_cache_store ) {
84 my $method = lc("setup_${store}_cache_backend");
86 Carp::croak "You must load the $store cache store plugin (if it exists). ".
87 "Please consult the Catalyst::Plugin::Cache documentation on how to configure hetrogeneous stores."
88 unless $app->can($method);
90 $app->$method( $name, %config );
92 $app->log->warn("Couldn't setup the cache backend named '$name'");
96 sub setup_cache_backend_by_class {
97 my ( $app, $name, $class, @args ) = @_;
98 Catalyst::Utils::ensure_class_loaded( $class );
99 $app->register_cache_backend( $name => $class->new( @args ) );
102 # end of spaghetti setup DWIM
105 my ( $c, @meta ) = @_;
109 return ( $c->get_preset_curried($name) || $c->get_cache_backend($name) );
111 # be nice and always return the same one for the simplest case
112 return ( $c->_default_curried_cache || $c->_default_curried_cache( $c->curry_cache( @meta ) ) );
114 return $c->curry_cache( @meta );
119 my ( $c, @meta ) = @_;
120 return Catalyst::Plugin::Cache::Curried->new( $c, @meta );
123 sub get_preset_curried {
124 my ( $c, $name ) = @_;
126 if ( ref( my $preset = $c->config->{cache}{profiles}{$name} ) ) {
127 return $preset if Scalar::Util::blessed($preset);
129 my @meta = ( ( ref $preset eq "HASH" ) ? %$preset : @$preset );
130 return $c->curry_cache( @meta );
136 sub get_cache_backend {
137 my ( $c, $name ) = @_;
138 $c->_cache_backends->{$name};
141 sub register_cache_backend {
142 my ( $c, $name, $backend ) = @_;
144 no warnings 'uninitialized';
145 Carp::croak("$backend does not look like a cache backend - "
146 . "it must be an object supporting get, set and remove")
147 unless eval { $backend->can("get") && $backend->can("set") && $backend->can("remove") };
149 $c->_cache_backends->{$name} = $backend;
152 sub unregister_cache_backend {
153 my ( $c, $name ) = @_;
154 delete $c->_cache_backends->{$name};
157 sub default_cache_backend {
159 $c->get_cache_backend( "default" ) || $c->temporary_cache_backend;
162 sub temporary_cache_backend {
164 die "FIXME - make up an in memory cache backend, that hopefully works well for the current engine";
167 # this gets a shit name so that the plugins can override a good name
168 sub choose_cache_backend_wrapper {
169 my ( $c, @meta ) = @_;
171 Carp::croak("meta data must be an even sized list") unless @meta % 2 == 0;
175 # allow the cache client to specify who it wants to cache with (but loeave room for a hook)
176 if ( exists $meta{backend} ) {
177 if ( Scalar::Util::blessed($meta{backend}) ) {
178 return $meta{backend};
180 return $c->get_cache_backend( $meta{backend} ) || $c->default_cache_backend;
185 $meta{caller} = [ caller(2) ] unless exists $meta{caller}; # might be interesting
187 if ( my $chosen = $c->choose_cache_backend( %meta ) ) {
188 $chosen = $c->get_cache_backend( $chosen ) unless Scalar::Util::blessed($chosen); # if it's a name find it
189 return $chosen if Scalar::Util::blessed($chosen); # only return if it was an object or name lookup worked
192 # die "no such backend"?
193 # currently, we fall back to default
196 return $c->default_cache_backend;
199 sub choose_cache_backend { shift->NEXT::choose_cache_backend( @_ ) } # a convenient fallback
202 my ( $c, $key, $value, @meta ) = @_;
203 $c->choose_cache_backend_wrapper( key => $key, value => $value, @meta )->set( $key, $value );
207 my ( $c, $key, @meta ) = @_;
208 $c->choose_cache_backend_wrapper( key => $key, @meta )->get( $key );
212 my ( $c, $key, @meta ) = @_;
213 $c->choose_cache_backend_wrapper( key => $key, @meta )->remove( $key );
224 Catalyst::Plugin::Cache -
228 use Catalyst::Plugin::Cache;
238 An object that responds to the methods detailed in
239 L<Catalyst::Plugin::Cache::Backend> (or more).
243 A generic "type" of backend. Typically a plugin used to construct backends.
247 An object that responds to C<get>, C<set> and C<remove>, and will automatically
248 add meta data to calls to C<< $c->cache_get >>, etc.