NAME¶
CHI::Driver::Development -- Manual for developing new CHI drivers
VERSION¶
version 0.54
SYNOPSIS¶
package CHI::Driver::MyDriver;
use Moose;
use strict;
use warnings;
extends 'CHI::Driver';
has ...;
__PACKAGE__->meta->make_immutable();
sub fetch {
my ( $self, $key ) = @_;
}
sub store {
my ( $self, $key, $data[, $expires_in] ) = @_;
}
sub remove {
my ( $self, $key ) = @_;
}
sub clear {
my ($self) = @_;
}
sub get_keys {
my ($self) = @_;
}
sub get_namespaces {
my ($self) = @_;
}
DESCRIPTION¶
This document describes how to implement a new CHI driver.
The easiest way to start is to look at existing drivers, such as
CHI::Driver::Memory and CHI::Driver::FastMmap.
NAMING¶
If you are going to publicly release your driver, call it 'CHI::Driver::
something' so that users can create it with
CHI->new(driver => 'I<something>');
If it's an internal driver, you can call it whatever you like and create it like
CHI->new(driver => '+My::Internal::CHI::Driver');
MOOSE¶
CHI driver classes must be Moose based to be fully functional, since we use
Moose roles to implement various features. For backward compatibility,
non-Moose drivers will still work at a basic level, but you will see an error
if using any feature requiring a role.
All drivers must directly or indirectly extend CHI::Driver.
NAMESPACE¶
All cache handles have an assigned namespace that you can access with
"$self->namespace". You should use the namespace to partition
your data store. That is, two cache objects with different namespaces should
be able to access the same key without any collision.
Examples:
- •
- The Memory driver uses a separate sub-hash inside its main
memory hash for each namespace.
- •
- The File driver uses a separate top-level directory for
each namespace.
- •
- The FastMmap driver uses a separate Cache::FastMmap file
for each namespace.
METHODS¶
Required methods¶
The following methods have no default implementation, and MUST be defined by
your subclass:
- store ( $self, $key, $data[, $expires_in] )
- Associate $data with
$key in the namespace, overwriting any existing
entry. Called by "set". $data will contain
any necessary metadata, including expiration options, so you can just
store it as a single block.
$expires_in is optionally the number of seconds from
now when the entry will expire. This will only be passed if
"expires_on_backend" in CHI is set. If your driver does not
support expiration, or if you'd rather just let CHI manage expiration, you
can ignore this.
- fetch ( $self, $key )
- Returns the data associated with $key
in the namespace. Called by "get". The main CHI::Driver
superclass will take care of extracting out metadata like expiration
options and determining if the value has expired.
- remove ( $self, $key )
- Remove the data associated with the
$key in the namespace.
- clear ( $self )
- Remove all data associated with the namespace. (Technically
not required, but the default implementation, which iterates over all keys
and calls "remove" for each, is very inefficient).
Overridable methods¶
The following methods have a default implementation, but MAY be overridden by
your subclass:
- BUILD ( $self, $options )
- Define the Moose BUILD method if you want to process any
options specific to your driver.
- fetch_multi_hashref ( $keys )
- Override this if you want to efficiently process multiple
fetches. Return a hash reference from keys to fetched data. If a key is
not available, it may be left out of the hash or paired with undef. The
default method will iterate over $keys and call fetch
for each.
This method is called by get_multi_arrayref and get_multi_hashref.
- store_multi ( $key_data, $options )
- Override this if you want to efficiently process multiple
stores. $key_data is a hash of keys and data that
should be stored. The default will iterate over
$key_data and call store for each pair.
This method is called by set_multi.
Optional methods¶
The following methods have no default implementation, and MAY be defined by your
subclass, but are not required for basic cache operations.
- get_keys ( $self )
- Return all keys in the namespace. It is acceptable to
either include or omit expired keys.
- get_namespaces ( $self )
- Return namespaces associated with the cache. It is
acceptable to either include or omit namespaces with no valid keys.
DISCARD POLICIES¶
You can create new discard policies for CHI/SIZE AWARENESS caches, to choose
items to discard when the cache gets full. For example, the Memory driver
implements an LRU policy.
To implement a discard policy
foo, define a subroutine
discard_policy_foo, which takes a driver object and returns a closure
that returns one key each time it is called. The closure should maintain state
so that each key is only returned once.
For example, here's the Memory driver's LRU implementation. It utilizes a hash
containing the last used time for each key.
sub discard_policy_lru {
my ($self) = @_;
my $last_used_time = $self->{metadata_for_namespace}->{last_used_time};
my @keys_in_lru_order =
sort { $last_used_time->{$a} <=> $last_used_time->{$b} } $self->get_keys;
return sub {
shift(@keys_in_lru_order);
};
}
You can set the default discard policy for your driver by overriding
default_discard_policy; otherwise the default is 'arbitrary'.
sub default_discard_policy { 'lru' }
TESTING¶
CHI has a standard set of unit tests that should be used to ensure your driver
is fully implementing the CHI API.
To use CHI's tests (replacing
MyDriver with the name of your driver):
- •
- Install Test::Class, and add Test::Class to the build
dependencies for your distribution.
- •
- Add a module called
CHI::Driver::MyDriver::t::CHIDriverTests to your distribution
containing:
package CHI::Driver::MyDriver::t::CHIDriverTests;
use strict;
use warnings;
use CHI::Test;
use base qw(CHI::t::Driver);
sub new_cache_options {
my $self = shift;
return (
$self->SUPER::new_cache_options(),
driver => '+CHI::Driver::MyDriver',
# Any other CHI->new parameters for your test driver
);
}
1;
- •
- Add a test script called t/CHI-driver-tests.t to
your distribution containing:
#!perl -w
use strict;
use warnings;
use CHI::Driver::MyDriver::t::CHIDriverTests;
CHI::Driver::MyDriver::t::CHIDriverTests->runtests;
- •
- You may need to override other methods in
CHI::Driver::MyDriver::t::CHIDriverTests, e.g. to skip tests that
do not apply to your driver. See CHI::t::Driver::Memory and
CHI::t::Driver::File in this distribution for examples.
AUTHOR¶
Jonathan Swartz
SEE ALSO¶
CHI, CHI::Driver
COPYRIGHT & LICENSE¶
Copyright (C) 2007 Jonathan Swartz.
CHI is provided "as is" and without any express or implied warranties,
including, without limitation, the implied warranties of merchantibility and
fitness for a particular purpose.
This program is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.
AUTHOR¶
Jonathan Swartz <swartz@pobox.com>
COPYRIGHT AND LICENSE¶
This software is copyright (c) 2011 by Jonathan Swartz.
This is free software; you can redistribute it and/or modify it under the same
terms as the Perl 5 programming language system itself.