File Coverage

blib/lib/OurCal/Provider/Cache.pm
Criterion Covered Total %
statement 15 78 19.2
branch 0 12 0.0
condition 0 10 0.0
subroutine 5 19 26.3
pod 10 10 100.0
total 30 129 23.2


line stmt bran cond sub pod time code
1             package OurCal::Provider::Cache;
2              
3 1     1   2269 use strict;
  1         5  
  1         49  
4 1     1   7 use File::Spec::Functions qw(catfile rel2abs);
  1         3  
  1         66  
5 1     1   8 use File::Path;
  1         2  
  1         59  
6 1     1   1275 use Storable;
  1         10332  
  1         59  
7 1     1   9 use OurCal::Provider;
  1         3  
  1         10  
8              
9             =head1 NAME
10              
11             OurCal::Provider::Cache - a caching provider
12              
13             =head1 SYNOPSIS
14              
15             [a_cache]
16             type = cache
17             dir = .cache
18             child = a_provider
19              
20             =head1 CONFIG OPTIONS
21              
22             =over 4
23              
24             =item dir
25              
26             The directory to cache into. Defaults to '.cache'
27              
28             =item child
29              
30             An optional child to cache stuff from. This will instantiate the
31             provider and feed stuff through to it, caching appropriately.
32              
33             =item cache_expiry
34              
35             How long to cache for in seconds. Defaults to 1800 (30 mins).
36              
37             =back
38              
39             =head1 METHODS
40              
41             =cut
42              
43             =head2 new
44              
45             Requires an C object as config param and a name param.
46              
47             =cut
48              
49             sub new {
50 0     0 1   my $class = shift;
51 0           my %what = @_;
52 0           my $conf = $what{config}->config($what{name});
53 0 0         if (defined $conf->{child}) {
54 0           $what{_provider} = OurCal::Provider->load_provider($conf->{child}, $what{config});
55 0           $what{_provider_name} = $conf->{child};
56             }
57 0   0       $what{_cache_dir} = $conf->{dir} || '.cache';
58 0   0       $what{_cache_expiry} = $conf->{cache_expiry} || 60 * 30;
59 0           return bless \%what, $class;
60             }
61              
62              
63             sub todos {
64 0     0 1   my $self = shift;
65 0           return $self->_do_cached('todos', @_);
66             }
67              
68             sub has_events {
69 0     0 1   my $self = shift;
70 0           return ($self->_do_cached('has_events', @_))[0];
71             }
72              
73             sub events {
74 0     0 1   my $self = shift;
75 0           my %opts = @_;
76 0           my @events = $self->_do_cached('events', %opts);
77 0 0         @events = splice @events, 0, $opts{limit} if defined $opts{limit};
78 0           return @events;
79             }
80              
81             sub users {
82 0     0 1   my $self = shift;
83 0           return $self->_do_cached('users', @_);
84             }
85              
86             sub save_todo {
87 0     0 1   my $self = shift;
88 0           return $self->_do_default('save_todo', @_);
89             }
90              
91             sub del_todo {
92 0     0 1   my $self = shift;
93 0           return $self->_do_default('del_todo', @_);
94             }
95              
96              
97             sub save_event {
98 0     0 1   my $self = shift;
99 0           return $self->_do_default('save_event', @_);
100             }
101              
102             sub del_event {
103 0     0 1   my $self = shift;
104 0           return $self->_do_default('del_event', @_);
105             }
106              
107             sub _do_cached {
108 0     0     my $self = shift;
109 0           my $sub = shift;
110 0           my $thing = shift;
111 0 0         return unless defined $self->{_provider};
112 0           my $file = $self->{_provider_name}."+".$sub."@".$self->_flatten_args($thing, @_);
113 0     0     return $self->cache($file, sub { $self->{_provider}->$sub($thing, @_) });
  0            
114             }
115              
116              
117             =head2 cache
118              
119             Retrieve the cache file and returns a list of objects serialised in it.
120              
121             If the cache has expired then runs the subroutine passed to fetch more
122             data.
123              
124             =cut
125              
126             # TODO perhaps the caching code should be refactored out into
127             # ::Cache::Simple and ::Provider::Cache could take an optional
128             # 'class' parameter. This will do for now though.
129             sub cache {
130 0     0 1   my $self = shift;
131 0           my $file = shift;
132 0           my $sub = shift;
133 0           my $dir = rel2abs($self->{_cache_dir});
134 0 0 0       -d $dir || eval { mkpath($dir) } || die "Couldn't create cache directory $dir: $@\n";
  0            
135 0           my $cache = catfile($dir, $file);
136 0           my $expire = $self->{_cache_expiry};
137 0           my $mtime = (stat($cache))[9];
138 0           my $time = time;
139 0           my @res = ();
140 0 0 0       if (-e $cache && ($time-$mtime < $expire)) {
141 0           @res = @{Storable::retrieve( $cache )};
  0            
142             } else {
143 0           @res = $sub->();
144 0           Storable::store( [@res], $cache );
145             }
146 0           return @res;
147             }
148              
149             sub _flatten_args {
150 0     0     my $self = shift;
151 0           my %opts = @_;
152 0           my $flat = "";
153 0           foreach my $key (sort keys %opts) {
154 0           $flat .= "$key=$opts{$key};"
155             }
156 0           return $flat;
157             }
158              
159             sub _do_default {
160 0     0     my $self = shift;
161 0           my $sub = shift;
162 0           my $thing = shift;
163 0 0         return unless defined $self->{_provider};
164 0           return $self->{_provider}->$sub($thing, @_);
165             }
166              
167             =head2 todos
168              
169             Returns all the todos on the system.
170              
171             =head2 has_events
172              
173             Returns whether there are events given the params.
174              
175             =head2 events
176              
177             Returns all the events for the given params.
178              
179             =head2 users
180              
181             Returns the name of all the users on the system.
182              
183             =head2 save_todo
184              
185             Save a todo.
186              
187             =head2 del_todo
188              
189             Delete a todo.
190              
191              
192             =head2 save_event
193              
194             Save an event.
195              
196             =head2 del_event
197              
198             Delete an event..
199              
200             =cut
201              
202              
203             1;
204