1CHI::Driver::DevelopmenUts(e3r)Contributed Perl DocumentCaHtIi:o:nDriver::Development(3)
2
3
4
6 CHI::Driver::Development -- Manual for developing new CHI drivers
7
9 version 0.44
10
12 package CHI::Driver::MyDriver;
13 use Moose;
14 use strict;
15 use warnings;
16
17 extends 'CHI::Driver';
18
19 has ...;
20
21 __PACKAGE__->meta->make_immutable();
22
23 sub fetch {
24 my ( $self, $key ) = @_;
25
26 }
27
28 sub store {
29 my ( $self, $key, $data ) = @_;
30
31 }
32
33 sub remove {
34 my ( $self, $key ) = @_;
35
36 }
37
38 sub clear {
39 my ($self) = @_;
40
41 }
42
43 sub get_keys {
44 my ($self) = @_;
45
46 }
47
48 sub get_namespaces {
49 my ($self) = @_;
50
51 }
52
54 This document describes how to implement a new CHI driver.
55
56 The easiest way to start is to look at existing drivers, such as
57 CHI::Driver::Memory and CHI::Driver::FastMmap.
58
60 If you are going to publicly release your driver, call it
61 'CHI::Driver::something' so that users can create it with
62
63 CHI->new(driver => 'I<something>');
64
65 If it's an internal driver, you can call it whatever you like and
66 create it like
67
68 CHI->new(driver_class => 'My::Internal::CHI::Driver');
69
71 CHI driver classes must be Moose based to be fully functional, since we
72 use Moose roles to implement various features. For backward
73 compatibility, non-Moose drivers will still work at a basic level, but
74 you will see an error if using any feature requiring a role.
75
76 All drivers must directly or indirectly extend CHI::Driver.
77
79 All cache handles have an assigned namespace that you can access with
80 "$self->namespace". You should use the namespace to partition your data
81 store. That is, two cache objects with different namespaces should be
82 able to access the same key without any collision.
83
84 Examples:
85
86 · The Memory driver uses a separate sub-hash inside its main memory
87 hash for each namespace.
88
89 · The File driver uses a separate top-level directory for each
90 namespace.
91
92 · The FastMmap driver uses a separate Cache::FastMmap file for each
93 namespace.
94
96 Required methods
97 The following methods have no default implementation, and MUST be
98 defined by your subclass:
99
100 store ( $self, $key, $data, $expires_at, $options )
101 Associate $data with $key in the namespace, overwriting any
102 existing entry. Called by "set". $data will contain any necessary
103 metadata, including expiration options, so you can just store it as
104 a single block.
105
106 The $expires_at epoch value is provided in case you are working
107 with an existing cache implementation (like memcached) that also
108 has an interest in storing the expiration time for its own
109 purposes. Normally, you can ignore this.
110
111 <$options> contains the hash of options passed to "set", in case
112 you want to implement driver-specific set options. Normally, you
113 can ignore this.
114
115 fetch ( $self, $key )
116 Returns the data associated with $key in the namespace. Called by
117 "get". The main CHI::Driver superclass will take care of
118 extracting out metadata like expiration options and determining if
119 the value has expired.
120
121 remove ( $self, $key )
122 Remove the data associated with the $key in the namespace.
123
124 clear ( $self )
125 Remove all data associated with the namespace. (Technically not
126 required, but the default implementation, which iterates over all
127 keys and calls "remove" for each, is very inefficient).
128
129 Overridable methods
130 The following methods have a default implementation, but MAY be
131 overriden by your subclass:
132
133 BUILD ( $self, $options )
134 Define the Moose BUILD method if you want to process any options
135 specific to your driver.
136
137 fetch_multi_hashref ( $keys )
138 Override this if you want to efficiently process multiple fetches.
139 Return a hash reference from keys to fetched data. If a key is not
140 available, it may be left out of the hash or paired with undef. The
141 default method will iterate over $keys and call fetch for each.
142
143 This method is called by get_multi_arrayref and get_multi_hashref.
144
145 store_multi ( $key_data, $options )
146 Override this if you want to efficiently process multiple stores.
147 $key_data is a hash of keys and data that should be stored. The
148 default will iterate over $key_data and call store for each pair.
149
150 This method is called by set_multi.
151
152 Optional methods
153 The following methods have no default implementation, and MAY be
154 defined by your subclass, but are not required for basic cache
155 operations.
156
157 get_keys ( $self )
158 Return all keys in the namespace. It is acceptable to either
159 include or omit expired keys.
160
161 get_namespaces ( $self )
162 Return namespaces associated with the cache. It is acceptable to
163 either include or omit namespaces with no valid keys.
164
166 You can create new discard policies for CHI/SIZE AWARENESS caches, to
167 choose items to discard when the cache gets full. For example, the
168 Memory driver implements an LRU policy.
169
170 To implement a discard policy foo, define a subroutine
171 discard_policy_foo, which takes a driver object and returns a closure
172 that returns one key each time it is called. The closure should
173 maintain state so that each key is only returned once.
174
175 For example, here's the Memory driver's LRU implementation. It utilizes
176 a hash containing the last used time for each key.
177
178 sub discard_policy_lru {
179 my ($self) = @_;
180
181 my $last_used_time = $self->{metadata_for_namespace}->{last_used_time};
182 my @keys_in_lru_order =
183 sort { $last_used_time->{$a} <=> $last_used_time->{$b} } $self->get_keys;
184 return sub {
185 shift(@keys_in_lru_order);
186 };
187 }
188
189 You can set the default discard policy for your driver by overriding
190 default_discard_policy; otherwise the default is 'arbitrary'.
191
192 sub default_discard_policy { 'lru' }
193
195 CHI has a standard set of unit tests that should be used to ensure your
196 driver is fully implementing the CHI API.
197
198 To use CHI's tests (replacing MyDriver with the name of your driver):
199
200 · Install Test::Class, and add Test::Class to the build dependencies
201 for your distribution.
202
203 · Add a module called CHI::Driver::MyDriver::t::CHIDriverTests to
204 your distribution containing:
205
206 package CHI::Driver::MyDriver::t::CHIDriverTests;
207 use strict;
208 use warnings;
209 use CHI::Test;
210 use base qw(CHI::t::Driver);
211
212 sub new_cache_options {
213 my $self = shift;
214
215 return (
216 $self->SUPER::new_cache_options(),
217 driver_class => 'CHI::Driver::MyDriver',
218
219 # Any other CHI->new parameters for your test driver
220 );
221 }
222
223 1;
224
225 · Add a test script called t/CHI-driver-tests.t to your distribution
226 containing:
227
228 #!perl -w
229 use strict;
230 use warnings;
231 use CHI::Driver::MyDriver::t::CHIDriverTests;
232 CHI::Driver::MyDriver::t::CHIDriverTests->runtests;
233
234 · You may need to override other methods in
235 CHI::Driver::MyDriver::t::CHIDriverTests, e.g. to skip tests that
236 do not apply to your driver. See CHI::t::Driver::Memory and
237 CHI::t::Driver::File in this distribution for examples.
238
240 Jonathan Swartz
241
243 CHI, CHI::Driver
244
246 Copyright (C) 2007 Jonathan Swartz.
247
248 CHI is provided "as is" and without any express or implied warranties,
249 including, without limitation, the implied warranties of
250 merchantibility and fitness for a particular purpose.
251
252 This program is free software; you can redistribute it and/or modify it
253 under the same terms as Perl itself.
254
256 Jonathan Swartz <swartz@pobox.com>
257
259 This software is copyright (c) 2011 by Jonathan Swartz.
260
261 This is free software; you can redistribute it and/or modify it under
262 the same terms as the Perl 5 programming language system itself.
263
264
265
266perl v5.12.3 2011-03-17 CHI::Driver::Development(3)