NAME

Memoize::Memcached::Attribute - auto-memoize function results using memcached and subroutine attributes

VERSION

version 0.11

SYNOPSIS

If you're running memcache on your local box, with the default port, you can initialize without passing any parameters:

use Memoize::Memcached::Attribute;

This will use the default server list of 127.0.0.1:11211

If you want to specify the constructor parameters for your Cache::Memcached or Cache::Memcached::Fast client object, you can pass them in during import:

use Memoize::Memcached::Attribute (
	servers => [ '192.168.1.2:11211', '192.168.1.3:11211' ],
	_connect_timeout => 0.1,
	max_failures => 5,
);

Alternatively, you can pass in your memcache client object entirely (we use this because we subclass Cache::Memcached::Fast to add some additional methods and default parameters):

use Memoize::Memcached::Attribute (-client => Cache::Memcached::Fast->new(\%some_params));

Or you can specify it at runtime, the only caveat being that you must do this prior to calling any memoized function:

use Memoize::Memcache::Attribute;
Memoize::Memcache::Attribute::reset(Cache::Memcached::Fast->new(\%some_params));

And that's basically it. Now you have a :CacheMemoize subroutine attribute that will memoize subroutine results based on their parameters, storing the memoized data in memcache for a specified duration.

To use the memoization, you just pass your cache duration to the :CacheMemoize subroutine attribute:

# cache the results in memcache for 5 minutes
sub myfunc :CacheMemoize(300) {
	my @params = @_;
	my $total;
	$total += $_ for @params;
	return $total;
}

Sometimes you have an object method that is not dependent on object state, and you want to memoize those results, independent of the object used to generate them. So we provide that option by passing in 'method' as your first parameter with the cache duration as the second:

# cache the results in memcache for 30 seconds
# but don't look at the object as part of the input data
sub mymethod :CacheMemoize(method => 30) {
	my $self = shift;
	my @params = @_;
	return join('.', @params);
}

Really, you can pass anything in as a first parameter and it will be ignored if it isn't case-insensitively equal to 'method'.

While not generally recommended as good design, we do support the ability to invalidate caches. If you find yourself using the invalidation often, this module is probably not really how you want to go about achieving your caching strategy. Here's how you do it:

Memoize::Memcached::Attribute::invalidate('Some::Package::myfunc', @params);

If you're invalidating the cache from inside the same package as the cached function (which is probably the only place you should be), you can omit the package name:

Memoize::Memcached::Attribute::invalidate('mymethod', @params);

DESCRIPTION

Memoization is a process whereby you cache the results of a function, based on its input, in memory so that repeated calls to the same function don't waste cycles recalculating the results. Generally you use it with functions that are somewhat expensive to run (or that you have to run so frequently they become expensive), and that always return the same results based on the same input (i.e. they have no side effects). This module expands that concept to use memcache to provide a shared memory cache, rather than a per-process cache like a lot of other memoization modules, so that multiple processes can reuse the results. It gives you the added benefit that the memoization is not permanent, because you specify a timeout on the cached data. So, if you have a method that has no side effects, but the data it's returning might become stale, you can still get the benefits of memoization while also having it automatically recalculate the results from time to time.

METHODS

reset

Allows you to reset the package global memcache client after forking.

invalidate

Allows you to invalidate cached data.

import

Allows you to specify memcache connection parameters or your own client object to be used.

CacheMemoize

Should not be called directly. This is the subroutine attribute handler exported by this package.

METHODS

OPTIONS

When you import the package, you can pass a few options in:

-noattrimport - By default, we import some methods to make the attribute work properly in subclasses. This flag prevents that behavior. It allows you to avoid cluttering your namespace a little, at the expense of not working with inheritance.
-client - Allows you to specify your own memcache client object. Useful if you subclass Cache::Memcached in your codebase.

Any remaining options will be used to _connect to the Cache::Memcached client object, if passed.

THREADS/FORKING

Because this module internally stores the memcached client as a package global, and the memcached clients have issues with threads and forking, it would be wise to reset the package global after forking or creating a new thread. This can be done like this:

if (my $pid = fork) {
	# parent
}
else {
	# create a new client using the parameters you used to create the original object
	Memoize::Memcached::Attribute::reset();
	# or pass in your own object
	Memoize::Memcached::Attribute::reset($new_memcached_client);
}

ACKNOWLEDGEMENTS

Thanks to Chris Reinhardt and David Dierauer for finding and fixing some issues. And to LiquidWeb for allowing me to contribute this to CPAN.

BUGS

None known. This has been in use in LiquidWeb production code for a few years without any known issues. It was slightly modified to remove some dependence on other LiquidWeb code, so there's an extremely remote chance that something broke in the process.

If you find a bug, or have a feature request, submit it here: https://github.com/jimbobhickville/perl-Memoize-Memcached-Attribute/issues/new

AUTHOR

Greg Hill <jimbobhickville@gmail.com>

COPYRIGHT AND LICENSE

This software is copyright (c) 2012 by Greg Hill.

This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.