I’ve been using Memcached
for a few weeks, trying to offload some VERY heavy database load. It’s nice and blazing fast, but the implementation is sort of clunky. If I have this simple bit of code:
$key = "foobar"; $val = calculate_val($key);
It turns into this:
$key = "foobar"; $val = $memd->get($key); if(! defined($val)) { $val = calculate_val($key); $memd->set($key, $val); }
Repeatedly I came back to the idea of a get_or_set
method that would handle this stuff, but until the obvious solution hit me, I couldn’t get it:
$key = "foobar"; $val = $memd->get_or_set($key, sub { calculate_val($key) });
A simple closure around the actual calculation block which is then passed to the get_or_set
method as a callback. If the lookup finds a value the method returns it, otherwise it returns the result of calling the callback function.
The only change to Cache::Memcached is adding the get_or_set function. The easiest way is to just subclass Cache::Memcached:
package My::Memcached use base qw(Cache::Memcached); sub get_or_set { my $self = shift; my($key, $callback) = @_; my $val = $self->get($key); unless(defined $val) { $val = &$callback; $self->set($key, $val); } return $val; } 1;
Now you have this simple interface:
use My::Memcached; my $memd = new My::Memcached { servers => [...] }; my $foo = $memd->get_or_set("bar", sub { get_val("bar") });