Hello all,
Please see the attached RFC. I know a caching plugin has been
discussed in the past, but recent needs at work (and recent
conversations with Cees) have motivated me to produce this. When you
have an opportunity, please read and give me your feedback.
One thing I have considered adding but have not done so yet is cache
rollover. To explain this a bit... If you look for a parameter in
an unspecified cache, and the parameter doesn't exist there, you
search all caches for a match on that parameter. Which begs the
question, what should a set operation do? Set in one cache or all
caches? What are your thoughts on this?
Thanks in advance for your feedback,
Jason
NAME
CGI::Application::Plugin::Cache - Generic caching framework for
CGI::Application.
VERSION
Version 0.01
SYNOPSIS
use CGI::Application;
use CGI::Application::Plugin::Cache;
# Configure the cache. Do this in setup() or cgiapp_init().
$self->cache->config(
DRIVER => [ 'CacheFastMmap',
share_file => '/home/webapp/cache/mmapcache',
cache_size => '1m',
],
);
# Or, create named caches. . .
$self->cache( 'memory' )->config(
DRIVER => [ 'CacheFastMmap',
share_file => '/home/webapp/cache/mmapcache',
cache_size => '1m',
],
);
$self->cache( 'disk' )->config(
DRIVER => [ 'CacheFileCache',
namespace => 'Default',
cache_root => '/home/webapp/cache/filecache',
],
);
# Examples of using the cache
$self->cache()->set( $key, $value, [ $expiry, { %options } ]);
$self->cache( 'memory' )->set( $key, $value, [ $expiry, { %
options } ]);
my $value = $self->cache->get( $key );
my %values = $self->cache( 'memcached' )->get([ "key1",
"key2", "key3" ]);
my $count = $self->cache->remove( $key );
my $count = $self->cache( 'disk' )->remove([ "key1", "key2",
"key3" ]);
my $count = $self->cache->purge;
my $count = $self->cache( 'memory' )->purge;
$self->cache->clear;
$self->cache( 'memcached' )->clear;
$self->cache->object->some_cache_object_method( $arg1,
$arg2, ...);
$self->cache( 'disk' )->object->some_cache_object_method
( $arg1, $arg2, ...);
DESCRIPTION
CGI::Application::Plugin::Cache provides a generic caching
interface for
CGI::Application-derived web applications. A single method,
"cache",
gives the developer complete control over defining and using a
cache in
their application.
CGI::Application::Plugin::Cache is dependent on one or more
drivers to
provide functionality from various caching backends.
CGI::Application::Plugin::Cache comes with drivers for the
Cache::Cache
suite of caching modules, Cache::FastMmap, Cache::Memcached, and
Tie::Cache::LRU. For information about writing your own drivers,
see
CGI::Application::Plugin::Cache::Driver.
Named Caches
You may wish to provide one or more data caches to your
application, and
you may wish to store those caches in different types of storage
medium
(disk, memory, shared memory, network cache, etc.).
CGI::Application::Plugin::Cache makes it easy to provide this
functionality in your applications through the use of named caches:
$self->cache( 'memory' )->config(
DRIVER => [ 'CacheFastMmap',
share_file => '/home/webapp/cache/mmapcache',
cache_size => '1m',
],
);
$self->cache( 'disk' )->config(
DRIVER => [ 'CacheFileCache',
namespace => 'Default',
cache_root => '/home/webapp/cache/filecache',
],
);
$self->cache( 'memory' )->set( "yourkey", "yourvalue" );
my $value = $self->cache( 'disk' )->get( "mykey" );
MOTIVATIONS
It was originally my intent to create a simple caching plugin
based upon
Cache::Cache. My need was very simple: I had a drop-down list of
items
that was populated from the database on every request to a
particular
page. The data in those lists changed once or twice a year.
Because of
the static nature of this data, it became a great candidate for
caching.
The performance benefits were obvious to me.
Some issues with Cache::Cache were pointed out to me,
particularly the
(lack of) efficency when it came to determining the expiration
time of a
value and purging those expired values. Cache::FastMmap was
recommended
to me as a great alternative. Unfortunately, Cache::FastMmap
doesn't
play nicely with Windows, which is what half of our web
applications run
on. Wanting to implement caching throughout our suite of
applications,
but not wanting to write custom caching code for each platform
we deploy
to, drove me to creating a generic, reusable caching interface.
EXPORTED METHODS
cache()
Everything in CGI::Application::Plugin::Cache is controlled
through this
method. "cache()" returns a CGI::Application::Plugin::Cache object
unless it was called as a class method, in which case it returns
the
name of the class.
When using the cache, always invoke this method in one of the
following
two ways:
$self->cache->method_to_invoke( @args );
- or -
__PACKAGE__->cache->method_to_invoke (@args );
When using multiple caches, you may provide the name of the
cache to use
as an argument to "cache()". If a cache is not explicitly
specified, we
use the last cache that was used. If a cache was never
specified, we use
the first cache that was defined. This is the same rationale
used by
CGI::Application::Plugin::DBH.
METHODS
config()
# Simple configuration when implementing a single caching
mechanism
# in your application.
$self->cache->config(
DRIVER => [ 'CacheFastMmap',
share_file => '/home/webapp/cache/mmapcache',
cache_size => '1m',
],
);
# Using a named configurations to distinguish these from the
above
# configuration.
$self->cache( 'disk' )->config(
DRIVER => [ 'CacheFileCache',
namespace => 'Default',
cache_root => '/home/webapp/cache/filecache',
],
);
$self->cache( 'memory' )->config(
DRIVER => [ 'CacheFastMmap',
share_file => '/home/webapp/cache/mmapcache',
cache_size => '1m',
],
);
$self->cache( 'memcached' )->config(
DRIVER => [ 'CacheMemcached',
servers => [ '192.168.0.10:11211',
'192.168.0.20:11211' ],
debug => 0,
namespace => 'myapp',
],
);
Configures the caching module. It can be called as an object
method or a
class method.
"config()" takes a single argument: "DRIVER". It specifies which
of the
caching drivers you wish to use for this particular cache. For
sake of
simplicity, you can omit
CGI::Application::Plugin::Cache::Driver:: when
specifying which driver to use. If the underlying caching module
requires additional configuration parameters, you may pass
"config()" an
array reference that contains the name of the driver as its first
parameter and the required options as the rest of the array.
"config()" should be called in either your applications
"cgiapp_init()"
or "setup()" events.
set()
$self->cache()->set( $key, $value, [ $expiry, { %options } ]);
$self->cache( 'memory' )->set( $key, $value, [ $expiry, { %
options } ]);
Sets the specified key to the value provided in the specified
cache. If
no cache was specified, the key/value combination is added to
the last
active cache.
Note: not all caching backends support parameter-level
expiration. In
particular, Cache::FastMmap does not provide the ability to expire
different parameters at different times. This functionality may,
at some
point in the future, be added to drivers for backends that do not
provide that functionality.
Any options specified in %options are passed directly to the
underlying
caching mechanism.
get()
my $value = $self->cache->get( $key );
my %values = $self->cache( 'memcached' )->get([ "key1",
"key2", "key3" ]);
Retrieves the value associated with $key from the specified
cache. If a
cache is not specified, $key is retrieved from the last active
cache.
If a list of keys are provided, "get()" returns a hash
containing the
list of keys and their associated values.
If a key is not found, "get()" returns "undef".
remove()
my $count = $self->cache->remove( $key );
my $count = $self->cache( 'disk' )->remove([ "key1", "key2",
"key3" ]);
Removes the specified key(s) (and the associated values) from the
specified cache. If a cache was not specified, the key/value
combination
is removed from the last active cache.
purge()
my $count = $self->cache->purge;
my $count = $self->cache( 'memory' )->purge;
Removes all expired objects from the specified cache. If no
cache is
specified, all expired items are purged from the last active cache.
Returns the number of items that were removed from the cache.
clear()
$self->cache->clear;
$self->cache( 'memcached' )->clear;
Removes all objects from the specified cache. If no cache was
specified,
all objects are removed from the last active cache.
object()
$self->cache->object->some_cache_object_method( $arg1,
$arg2, ...);
$self->cache( 'disk' )->object->some_cache_object_method
( $arg1, $arg2, ...);
Provides direct access to the underlying caching object. This
method
*should* only be rarely used - i.e., for circumstances where
there is
some functionality provided by the underlying caching mechanism
that is
not supported by the standard driver interface. Using "object()"
bypasses many of the benefits provided by
CGI::Application::Plugin::Cache, and as such, it's regular use
is not
endorsed.
BUGS
Please report any bugs or feature requests to
"[EMAIL PROTECTED]", or through the web
interface at
<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=CGI-Application-
Plugin-C
ache>. I will be notified, and then you'll automatically be
notified of
progress on your bug as I make changes.
ACKNOWLEDGEMENTS
A big thanks to Cees Hek for helping me transform my idea for a
simple
Cache::Cache plugin to a fully-featured generic caching
interface. And,
as always, thanks to the usual crowd in #cgiapp on irc.perl.org for
keeping me company and making these projects worthwhile.
SEE ALSO
CGI::Application, Cache::Cache, Cache::FastMmap, Cache::Memcached.
AUTHOR
Jason A. Crome, "<[EMAIL PROTECTED]>"
COPYRIGHT & LICENSE
Copyright 2006 Jason A. Crome, all rights reserved.
This program is free software; you can redistribute it and/or
modify it
under the same terms as Perl itself.
---------------------------------------------------------------------
Web Archive: http://www.mail-archive.com/[email protected]/
http://marc.theaimsgroup.com/?l=cgiapp&r=1&w=2
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]