]> git.evergreen-ils.org Git - OpenSRF.git/blob - src/perlmods/OpenSRF/Utils/Cache.pm
now magically does both memcache and persist caching if the persist option
[OpenSRF.git] / src / perlmods / OpenSRF / Utils / Cache.pm
1 package OpenSRF::Utils::Cache;
2 use strict; use warnings;
3 use base qw/Cache::Memcached OpenSRF/;
4 use Cache::Memcached;
5 use OpenSRF::Utils::Config;
6 use OpenSRF::EX qw(:try);
7
8
9 =head OpenSRF::Utils::Cache
10
11 This class just subclasses Cache::Memcached.
12 see Cache::Memcached for more options.
13
14 The value passed to the call to current is the cache type
15 you wish to access.  The below example sets/gets data
16 from the 'user' cache.
17
18 my $cache = OpenSRF::Utils::Cache->current("user");
19 $cache->set( "key1", "value1" [, $expire_secs ] );
20 my $val = $cache->get( "key1" );
21
22
23 =cut
24
25 sub DESTROY {}
26
27 my %caches;
28
29 # ------------------------------------------------------
30 # Persist methods and method names
31 # ------------------------------------------------------
32 my $persist_add_slot; 
33 my $persist_push_stack;
34 my $persist_peek_stack;
35 my $persist_destroy_slot;
36 my $persist_slot_get_expire;
37 my $persist_slot_find;
38
39 my $max_persist_time                                    = 86400;
40 my $persist_add_slot_name                       = "opensrf.persist.slot.create_expirable";
41 my $persist_push_stack_name             = "opensrf.persist.stack.push";
42 my $persist_peek_stack_name             = "opensrf.persist.stack.peek";
43 my $persist_destroy_slot_name           = "opensrf.persist.slot.destroy";
44 my $persist_slot_get_expire_name = "opensrf.persist.slot.get_expire";
45 my $persist_slot_find_name                      = "opensrf.persist.slot.find";;
46
47 # ------------------------------------------------------
48
49
50 # return a named cache if it exists
51 sub current { 
52         my ( $class, $c_type )  = @_;
53         return undef unless $c_type;
54         return $caches{$c_type} if exists $caches{$c_type};
55         return $caches{$c_type} = $class->new( $c_type );
56 }
57
58
59 # create a new named memcache object.
60 sub new {
61
62         my( $class, $cache_type, $persist, $servers ) = @_;
63         return undef unless $cache_type;
64         return $caches{$cache_type} 
65                 if exists $caches{$cache_type};
66
67
68         $class = ref( $class ) || $class;
69         my $self = {};
70         $self->{persist} = $persist || 0;
71         $self->{memcache} = Cache::Memcached->new( { servers => $servers } ); 
72         if(!$self->{memcache}) {
73                 throw OpenSRF::EX::PANIC ("Unable to create a new memcache object for $cache_type");
74         }
75
76         bless($self, $class);
77         $caches{$cache_type} = $self;
78         return $self;
79 }
80
81
82
83 sub put_cache {
84         my($self, $key, $value, $expiretime ) = @_;
85         return undef unless( $key and $value );
86
87         _load_methods();
88
89         $expiretime ||= $max_persist_time;
90
91         $self->{memcache}->set( $key, $value, $expiretime );
92
93         if($self->{"persist"}) {
94
95                 my ($slot) = $persist_add_slot->run($key, $expiretime . "s");
96
97                 if(!$slot) {
98                         # slot may already exist
99                         ($slot) = $persist_slot_find->run($key);
100                         if(!defined($slot)) {
101                                 throw OpenSRF::EX::ERROR ("Unable to create cache slot $key in persist server" );
102                         }
103                 }
104
105                 ($slot) = $persist_push_stack->run($slot, $value);
106
107                 if(!$slot) {
108                         throw OpenSRF::EX::ERROR ("Unable to push data onto stack in persist slot $key" );
109                 }
110         }
111
112         return $key;
113 }
114
115 sub delete_cache {
116         my( $self, $key ) = @_;
117         if(!$key) { return undef; }
118         _load_methods();
119         $self->{memcache}->delete($key);
120         if( $self->{persist} ) {
121                 $persist_destroy_slot->run($key);
122         }
123         return $key; 
124 }
125
126 sub get_cache {
127         my($self, $key ) = @_;
128
129         my $val = $self->{memcache}->get( $key );
130         return $val if defined($val);
131
132         _load_methods();
133
134         # if not in memcache but we are persisting, the put it into memcache
135         if( $self->{"persist"} ) {
136                 $val = $persist_peek_stack->( $key );
137                 if(defined($val)) {
138                         my ($expire) = $persist_slot_get_expire->run($key);
139                         if($expire)     {
140                                 $self->{memcache}->set( $key, $val, $expire);
141                         } else {
142                                 $self->{memcache}->set( $key, $val, $max_persist_time);
143                         }
144                         return $val;
145                 } 
146         }
147         return undef;
148
149
150
151
152
153 sub _load_methods {
154
155         if(!$persist_add_slot) {
156                 $persist_add_slot = 
157                         OpenSRF::Application->method_lookup($persist_add_slot_name);
158                 if(!ref($persist_add_slot)) {
159                         throw OpenSRF::EX::PANIC ("Unable to retrieve method $persist_add_slot_name");
160                 }
161         }
162
163         if(!$persist_push_stack) {
164                 $persist_push_stack = 
165                         OpenSRF::Application->method_lookup($persist_push_stack_name);
166                 if(!ref($persist_push_stack)) {
167                         throw OpenSRF::EX::PANIC ("Unable to retrieve method $persist_push_stack_name");
168                 }
169         }
170
171         if(!$persist_peek_stack) {
172                 $persist_peek_stack = 
173                         OpenSRF::Application->method_lookup($persist_peek_stack_name);
174                 if(!ref($persist_peek_stack)) {
175                         throw OpenSRF::EX::PANIC ("Unable to retrieve method $persist_peek_stack_name");
176                 }
177         }
178
179         if(!$persist_destroy_slot) {
180                 $persist_destroy_slot = 
181                         OpenSRF::Application->method_lookup($persist_destroy_slot_name);
182                 if(!ref($persist_destroy_slot)) {
183                         throw OpenSRF::EX::PANIC ("Unable to retrieve method $persist_destroy_slot_name");
184                 }
185         }
186         if(!$persist_slot_get_expire) {
187                 $persist_slot_get_expire = 
188                         OpenSRF::Application->method_lookup($persist_slot_get_expire_name);
189                 if(!ref($persist_slot_get_expire)) {
190                         throw OpenSRF::EX::PANIC ("Unable to retrieve method $persist_slot_get_expire_name");
191                 }
192         }
193         if(!$persist_slot_find) {
194                 $persist_slot_find = 
195                         OpenSRF::Application->method_lookup($persist_slot_find_name);
196                 if(!ref($persist_slot_find)) {
197                         throw OpenSRF::EX::PANIC ("Unable to retrieve method $persist_slot_find_name");
198                 }
199         }
200 }
201
202
203
204
205
206
207
208 1;
209