Howdy,

Here's the second (and hopefully final!) RFC for CGI::Application::Plugin::Cache. I received a LOT of good feedback, both on and off list, and a whole bunch more at YAPC. I wish I could say a lot of ideas were mine - I have to give Cees, hide, and Perrin a lot of props for helping me out with it.

The one thing I am not sure what to do with it remove(). Should it behave like Perl's delete and return the value of the key it's deleting, or should it return the number of items that it's deleting?

Looking forward to 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().
        #

        # Create an unnamed cache with a Cache::FastMmap backend
        $self->cache->config({
            driver     => 'CacheFastMmap',
            share_file => '/home/webapp/cache/mmapcache',
            cache_size => '1m',
        });

        # The cache in action!
        $self->cache->set( $key, $value );
        my $value = $self->cache->get( $key );
        my $value = $self->cache->remove( $key );

        # Remove any expired objects
        my $count = $self->cache->purge_expired;

        # Clear the entire cache
        $self->cache->clear;

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" );

    Named caches, while handy, add a great deal of complexity to your
    application. As such, developers need to understand how
    "CGI::Application::Plugin::Cache" deals with named caches.

The best and most clear way of dealing with named caches is to provide "cache()" with a list of caches to operate on. Caches are used in the
    order provided. For example:

        $self->cache( 'memory', 'disk' )->set( "mykey", "thisvalue" );

    adds the key "mykey" to the memory cache first and sets it to
"thisvalue". "set()" then adds the key/value combination to the disk
    cache.

    Likewise:

my ($value1, $value2) = $self->cache( 'memory', 'network')- >get( 'thiskey', 'thatkey' );

looks first in the memory cache for the key "thiskey". If it's found, $value1 is populated with the value in the memory cache, regardless of whether or not "thiskey" exists in the network cache. If the key is not
    found in memory, the network cache is searched. If neither cache
contains "thiskey", $value1 is set to "undef". $value2 is populated in
    this same manner.

If this is too much typing for you, you can pass an additional argument
    to "config()" called "default":

        $self->cache->config({ default => ['memory', 'network'] });

    You can now write the above "get()" operation as such:

my ($value1, $value2) = $self->cache->get( 'thiskey', 'thatkey' );

and get the result in the same manner. Note that you can define many caches in your application, but you do not have to make all of them part
    of the default list.

    More specific examples are provided throughout this documentation.

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 a cache name (or list of
    cache names) to be used by "cache()":

$self->cache( 'memory', 'disk' )->set( "yourkey", "yourvalue" );
        my $value = $self->cache( 'network', 'disk' )->get( "mykey" );

The desired operation will be performed on each of the specified caches. If a cache is not expressly stated, "CGI::Application::Plugin::Cache"
    uses the methodology described in "Named Caches" to determine which
    caches to operate on.

    "CGI::Application::Plugin::Cache" uses lazy-loading to prevent the
unnecessary use of caching resources by your application. This means that if you configure a cache but never end up using it, the caching backend is never instantiated. The potential savings offered by lazy loading are huge, as many caching backends are somewhat on the heavy
    side.

METHODS
  config()
Configures the caching module. It can be called as an object method or a
    class method. It should be called in either your application's
    "cgiapp_init()" or "setup()" events.

"config()" can take one or more hash arguments that define which caches are being defined, and what drivers are implementing that cache. It also takes a "default" argument which specifies which caches to use (and in
    what order) when a cache is not explicitly stated.

    Let's look at some sample configurations:

        # The simplest config call possible!
        $self->cache->config;

This example implements a simple Cache::FileCache-based cache. A simple cache is created in your system's temporary directory (determined with File::Temp) using reasonable defaults. While not the most advanced or
    efficient caching option, it will work for most circumstances.

# Another 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',
        });

This creates a single cache using Cache::FastMmap. This also illustrates how to pass additional arguments to your underlying driver mechanism.

# 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( 'network' )->config({
            driver => 'CacheMemcached',
servers => [ '192.168.0.10:11211', '192.168.0.20:11211' ],
            debug     => 0,
            namespace => 'myapp',
        });

This example shows us how to create multiple, named caches within our web application. We can access each one of these caches individually within our application by specifying the name of the cache we'd like to
    use as an argument to "cache()".

        # Specify the default cache for cache operations
        $self->cache->config({ default => ['memory'] });

When using multiple caches, this specifies which cache (or caches) to
    use as the default for caching operations.

        # Or, as a single method call. . .
        $self->cache->config({
            {
                name       => 'memory',
                driver     => 'CacheFastMmap',
                share_file => '/home/webapp/cache/mmapcache',
                cache_size => '1m',
            },
            {
                name       => 'disk',
                driver     => 'CacheFileCache',
                namespace  => 'Default',
                cache_root => '/home/webapp/cache/filecache',
            }],
            default        => [ 'memory' ],
        });

    This is a convenient way to do all of the above in one call to
    "config()".

   Driver Notes
When configuring a driver, you must specify two parameters: "name" and "driver". "name" is the name of the cache you are configuring a driver for, and can be provided as an argument to "cache()". It can also be specified as a key to the driver's configuration hash. See the examples
    above for more details.

    "driver" is the name of the driver module being used to power your
    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 these as additional key/value combinations in
    the configuration hash. See the examples above for more details.

  set()
        $self->cache()->set( $key, $value, [ $expiry, { %options } ]);
$self->cache( 'memory' )->set( $key, $value, [ $expiry, { % options } ]); $self->cache( 'disk', '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
    default 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 ($value1, $value2, $value3) = $self->cache( 'network' )- >get([ "key1", "key2", "key3" ]); my ($value1, $value2) = $self->cache( 'network', 'disk' )- >get([ "key1", "key2" ]);

Returns a list of values for the key or keys provided as arguments from the specified cache. If a cache is not specified, values are retrieved from the default cache. If multiple caches are provided (or there are multiple default caches), caches are searched in the order provided. The value returned comes from the first cache in the list that contains the
    desired key.

    If a key is not found, "get()" returns "undef".

  remove()
        my ($value) = $self->cache->remove( $key );
my ($value1, $value2, $value3) = $self->cache( 'disk' )- >remove([ "key1", "key2", "key3" ]); my ($value1, $value2) = $self->cache( 'disk', 'memory' )- >remove([ "key1", "key2" ]);

    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 default cache. "remove()" returns the list of values
    that were deleted.

  purge_expired()
        my $count = $self->cache->purge_expired;
        my $count = $self->cache( 'memory' )->purge_expired;
        my $count = $self->cache( 'disk', 'memory' )->purge_expired;

Removes all expired objects from the specified cache. If no cache is specified, all expired items are purged from the default cache. Returns
    the number of items that were expired and removed.

  clear()
        $self->cache->clear;
        $self->cache( 'network' )->clear;
        $self->cache( 'memory', 'network' )->clear;

Removes all objects from the specified cache. If no cache was specified,
    all objects are removed from the default 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.

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.

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,
Perrin Harkins for sharing some of his caching expertise with me, and,
    as always, thanks to the usual crowd in #cgiapp on irc.perl.org for
    keeping me company and making these projects worthwhile.

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.

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]

Reply via email to