File Coverage

blib/lib/Interact/Later.pm
Criterion Covered Total %
statement 56 65 86.1
branch 3 4 75.0
condition n/a
subroutine 15 18 83.3
pod 5 7 71.4
total 79 94 84.0


line stmt bran cond sub pod time code
1             package Interact::Later;
2              
3 2     2   1141068 use 5.020;
  2         15  
4 2     2   13 use strict;
  2         4  
  2         63  
5 2     2   13 use warnings;
  2         6  
  2         62  
6              
7              
8 2     2   12 use Storable qw( store retrieve );
  2         4  
  2         122  
9 2     2   915 use Path::Class qw/dir/;
  2         18392  
  2         140  
10 2     2   1172 use Moose;
  2         923418  
  2         16  
11 2     2   16356 use Data::UUID;
  2         1381  
  2         130  
12 2     2   1069 use File::Find::Rule;
  2         16363  
  2         17  
13 2     2   106 use Data::Printer;
  2         4  
  2         21  
14              
15 2     2   1165 use experimental 'signatures';
  2         7183  
  2         14  
16 2     2   364 no if ( $] >= 5.018 ), 'warnings' => 'experimental';
  2         5  
  2         21  
17              
18             has 'cache_path' => (
19             is => 'ro',
20             isa => 'Str',
21             trigger => sub {
22              
23             # The trigger operate a transformation on the relative path that is passed
24             # as an argument.
25             # $_[0] is the new value
26             # $_[1] is the old value
27             # See https://stackoverflow.com/a/1415884/954777
28             $_[ 0 ]->{ cache_path } = dir( $_[ 1 ] )->absolute->stringify() . '/';
29             }
30             );
31              
32             has 'file_extension' => (
33             is => 'ro',
34             isa => 'Str'
35             );
36              
37 0     0 0 0 sub get_oldest_file_in_cache($self) {
  0         0  
  0         0  
38 0         0 my @files = File::Find::Rule
39             ->file
40             ->name( '*' . $self->file_extension );
41 0         0 p @files;
42              
43             # https://stackoverflow.com/a/7585306/954777
44             }
45              
46 2     2 0 15 sub get_all_cache_files_ordered_by_date ($self) {
  2         5  
  2         4  
47 2         58 my $path_and_pattern = $self->cache_path . '*' . $self->file_extension;
48             my @files
49 2         288 = sort { ( stat $a )[ 10 ] <=> ( stat $b )[ 10 ] } glob $path_and_pattern;
  19         415  
50 2         14 return @files;
51             }
52              
53 0     0 1 0 sub release_cache($id) { }
  0         0  
54              
55 3     3 1 2512 sub clean_cache($self) {
  3         9  
  3         6  
56 3         104 while ( glob $self->cache_path . '*' . $self->file_extension ) {
57 21 50       1696 unlink $_ or warn("Can't remove $_: $!");
58             }
59              
60             }
61              
62             sub generate_uuid {
63 21     21 1 14371 my $uuid = Data::UUID->new->create_str();
64 21         16353 return $uuid;
65             }
66              
67 21     21 1 120573 sub write_data_to_disk ( $self, $data ) {
  21         50  
  21         45  
  21         45  
68 21 100       940 if ( not -d $self->cache_path ) {
69 1         35 mkdir $self->cache_path;
70 1         66 say 'created cache directory';
71             }
72 21         97 my $uuid = generate_uuid();
73 21         1084 store \$data, $self->cache_path . $uuid . $self->file_extension;
74 21         3416 return $uuid;
75             }
76              
77 0     0 1   sub retrieve_data_from_disk($id) {
  0            
78              
79             }
80              
81              
82             =encoding UTF-8
83              
84             =head1 NAME
85              
86             Interact::Later - Delay some tasks for later by dumping their data to disk
87              
88             =head1 VERSION
89              
90             Version 0.05
91              
92             =cut
93              
94             our $VERSION = '0.05';
95              
96              
97             =head1 SYNOPSIS
98              
99             Can be used, for example, when you receive lots of C<POST> requests that you
100             don't want to proceed right now to save database load.
101              
102             This module will fastly store the data content on disk (with L<Storable>) without
103             the need to use a database or a job queue. I believe as Perl is fast at writing
104             files to disk, we can hope good results. This is an experiment...
105              
106              
107             use Interact::Later;
108              
109             my $delayer = Interact::Later->new(
110             cache_path => 'path/to/cache',
111             file_extension => '.dmp'
112             );
113              
114             $delayer->write_data_to_disk($data);
115              
116             # Later...
117             # Do it until there are no more files...
118             $delayer->get_oldest_file_in_cache();
119              
120             # Finally
121             $delayer->clean_cache;
122              
123             =head1 MOTIVATIONS
124              
125             TODO Telling the story of what happened at work and the situation with
126             databases, job queues, etc. that got troubled by the large amount of POST
127             requests.
128              
129             =head1 EXPORT
130              
131             A list of functions that can be exported. You can delete this section
132             if you don't export anything, such as for a purely object-oriented module.
133              
134             =head1 ATTRIBUTES
135              
136             To instantiate a new C<Interacter::Later> delayer, simply pass a hashref
137             containing a key-value couple containing the following:
138              
139             =head2 cache_path
140              
141             C<cache_path> is the relative path to the directory that will contain multiple
142             cache files. It will be expanded to an absolute path by the L<Moose> trigger and
143             L<Path::Class>.
144              
145             Keep it simple, it don't require a C</> in the beginning nor the end, and you
146             will be able to access it through C<$delayer->class_path>.
147              
148             $ pwd
149             /home/smonff/later/
150              
151             my $delayer = Interact::Later->new( cache_path => 'path/to/cache', ... );
152             say $delayer->class_path;
153             # /home/smonff/later/path/to/cache/
154             # Note it add a / in the end
155              
156             =head2 file_extension
157              
158             TODO
159              
160             =head1 SUBROUTINES/METHODS
161              
162             =head2 get_oldest_cache_files_ordered_by_date
163              
164             Retrieve the oldest file in the cache. C<$files[0]> is the oldest,
165             C<$files[-1]>the newest.
166              
167             =head2 clean_cache
168              
169             Flush the cache.
170              
171             =head2 release_cache
172              
173             Retrieve a specific file by ID
174              
175             =head2 generate_uuid
176              
177             =head2 write_data_to_disk
178              
179             Writes the cache files to disk using C<Storable>. It also checks that the cache
180             path exists and if not, it creates it.
181              
182             Returns the UUID so this way, the caller could re-use it (by placing it in a
183             queue for example).
184              
185              
186             =head2 retrieve_data_from_disk
187              
188              
189             =head1 AUTHOR
190              
191             Sébastien Feugère, C<< <smonff at riseup.net> >>
192              
193             =head1 BUGS
194              
195             Please report any bugs or feature requests to C<interact-later at gitlab.com>, or through
196             the web interface at L<https://gitlab.com/smonff/interact-later/issues>. I will be notified, and then you'll
197             automatically be notified of progress on your bug as I make changes.
198              
199              
200              
201              
202             =head1 SUPPORT
203              
204             You can find documentation for this module with the perldoc command.
205              
206             perldoc Interact::Later
207              
208              
209             You can also look for information at:
210              
211             =over 4
212              
213             =item * Gitlab: Gitlab issues tracker (report bugs here)
214              
215             L<http://gitlab.com/smonff/Interact-Later>
216              
217             =item * AnnoCPAN: Annotated CPAN documentation
218              
219             L<http://annocpan.org/dist/Interact-Later>
220              
221             =item * CPAN Ratings
222              
223             L<http://cpanratings.perl.org/d/Interact-Later>
224              
225             =item * Search CPAN
226              
227             L<http://search.cpan.org/dist/Interact-Later/>
228              
229             =back
230              
231              
232             =head1 ACKNOWLEDGEMENTS
233              
234              
235             =head1 LICENSE AND COPYRIGHT
236              
237             Copyright 2019 Sébastien Feugère.
238              
239             This program is free software; you can redistribute it and/or modify it
240             under the terms of the the Artistic License (2.0). You may obtain a
241             copy of the full license at:
242              
243             L<http://www.perlfoundation.org/artistic_license_2_0>
244              
245             Any use, modification, and distribution of the Standard or Modified
246             Versions is governed by this Artistic License. By using, modifying or
247             distributing the Package, you accept this license. Do not use, modify,
248             or distribute the Package, if you do not accept this license.
249              
250             If your Modified Version has been derived from a Modified Version made
251             by someone other than you, you are nevertheless required to ensure that
252             your Modified Version complies with the requirements of this license.
253              
254             This license does not grant you the right to use any trademark, service
255             mark, tradename, or logo of the Copyright Holder.
256              
257             This license includes the non-exclusive, worldwide, free-of-charge
258             patent license to make, have made, use, offer to sell, sell, import and
259             otherwise transfer the Package with respect to any patent claims
260             licensable by the Copyright Holder that are necessarily infringed by the
261             Package. If you institute patent litigation (including a cross-claim or
262             counterclaim) against any party alleging that the Package constitutes
263             direct or contributory patent infringement, then this Artistic License
264             to you shall terminate on the date that such litigation is filed.
265              
266             Disclaimer of Warranty: THE PACKAGE IS PROVIDED BY THE COPYRIGHT HOLDER
267             AND CONTRIBUTORS "AS IS' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES.
268             THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
269             PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED TO THE EXTENT PERMITTED BY
270             YOUR LOCAL LAW. UNLESS REQUIRED BY LAW, NO COPYRIGHT HOLDER OR
271             CONTRIBUTOR WILL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, OR
272             CONSEQUENTIAL DAMAGES ARISING IN ANY WAY OUT OF THE USE OF THE PACKAGE,
273             EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
274              
275              
276             =cut
277              
278             1; # End of Interact::Later