File Coverage

blib/lib/Code/TidyAll/CacheModel.pm
Criterion Covered Total %
statement 50 54 92.5
branch 4 6 66.6
condition 3 3 100.0
subroutine 16 17 94.1
pod 2 2 100.0
total 75 82 91.4


line stmt bran cond sub pod time code
1             package Code::TidyAll::CacheModel;
2              
3 27     27   721 use strict;
  27         64  
  27         841  
4 27     27   158 use warnings;
  27         73  
  27         783  
5              
6 27     27   660 use Digest::SHA qw(sha1_hex);
  27         3154  
  27         1368  
7 27     27   1033 use Path::Tiny ();
  27         12983  
  27         588  
8 27     27   706 use Specio::Declare;
  27         73478  
  27         254  
9 27     27   6802 use Specio::Library::Builtins;
  27         25980  
  27         368  
10 27     27   261798 use Specio::Library::Path::Tiny;
  27         39821  
  27         234  
11 27     27   394539 use Specio::Library::String;
  27         305152  
  27         277  
12              
13 27     27   59706 use Moo;
  27         106  
  27         314  
14              
15             our $VERSION = '0.83';
16              
17             has base_sig => (
18             is => 'ro',
19             isa => t('Str'),
20             default => q{},
21             );
22              
23             has cache_engine => (
24             is => 'ro',
25             isa => object_can_type(
26             methods => [qw( get set remove )],
27             ),
28             predicate => '_has_cache_engine',
29             );
30              
31             has cache_key => (
32             is => 'lazy',
33             isa => t('NonEmptyStr'),
34             clearer => 1,
35             );
36              
37             has cache_value => (
38             is => 'lazy',
39             isa => t('NonEmptyStr'),
40             clearer => 1,
41             );
42              
43             has file_contents => (
44             is => 'rw',
45             isa => t('Str'),
46             lazy => 1,
47             builder => 1,
48             trigger => 1,
49             clearer => 1,
50             );
51              
52             has full_path => (
53             is => 'ro',
54             isa => t('Path'),
55             required => 1,
56             );
57              
58             has is_cached => (
59             is => 'rw',
60             isa => t('Bool'),
61             lazy => 1,
62             builder => 1,
63             clearer => 1,
64             );
65              
66             has path => (
67             is => 'ro',
68             isa => t('Path'),
69             required => 1,
70             );
71              
72             sub _build_file_contents {
73 67     67   807 my ($self) = @_;
74 67         322 return Path::Tiny::path( $self->full_path )->slurp_raw;
75             }
76              
77             sub _trigger_file_contents {
78 40     40   1812 my $self = shift;
79 40         848 $self->clear_cache_key;
80 40         975 $self->clear_is_cached;
81 40         901 $self->clear_cache_value;
82 40         373 return;
83             }
84              
85             sub _build_cache_key {
86 83     83   830 my ($self) = @_;
87 83         440 return 'sig/' . $self->path;
88             }
89              
90             sub _build_cache_value {
91 35     35   2192 my ($self) = @_;
92              
93             # this stat isn't ideal, but it'll do
94 35         160 my $last_mod = ( stat( $self->full_path ) )[9];
95 35         1658 return $self->_sig( [ $self->base_sig, $last_mod, $self->file_contents ] );
96             }
97              
98             sub _build_is_cached {
99 67     67   714 my ($self) = @_;
100              
101 67 100       518 return unless $self->_has_cache_engine;
102 51         1009 my $cached_value = $self->cache_engine->get( $self->cache_key );
103 51   100     2759 return defined $cached_value && $cached_value eq $self->cache_value;
104             }
105              
106             sub update {
107 53     53 1 129 my ($self) = @_;
108              
109 53 100       271 return unless $self->_has_cache_engine;
110 37         746 $self->cache_engine->set( $self->cache_key, $self->cache_value );
111 37         1061 $self->is_cached(1);
112 37         1662 return;
113             }
114              
115             sub remove {
116 0     0 1 0 my ($self) = @_;
117              
118 0 0       0 return unless $self->_has_cache_engine;
119 0         0 $self->cache_engine->remove( $self->cache_key );
120 0         0 return;
121             }
122              
123             sub _sig {
124 47     47   3836 my ( $self, $data ) = @_;
125 47         1225 return sha1_hex( join( ',', @$data ) );
126             }
127              
128             1;
129              
130             # ABSTRACT: Caching model for Code::TidyAll
131              
132             __END__
133              
134             =pod
135              
136             =encoding UTF-8
137              
138             =head1 NAME
139              
140             Code::TidyAll::CacheModel - Caching model for Code::TidyAll
141              
142             =head1 VERSION
143              
144             version 0.83
145              
146             =head1 SYNOPSIS
147              
148             my $cache_model = Cody::TidyAll::CacheModel->new(
149             cache_engine => Code::TidyAll::Cache->new(...),
150             path => '/path/to/file/to/cache',
151             );
152              
153             # check cache
154             print 'Yes!' if $cache_model->is_cached;
155              
156             # update cache
157             $cache_model->clear_file_contents;
158             $cache_model->update;
159              
160             # update the cache when you know the file contents
161             $cache_model->file_contents($new_content);
162             $cache_model->update;
163              
164             # force removal from cache
165             $cache_model->remove;
166              
167             =head1 DESCRIPTION
168              
169             A cache model for Code::TidyAll. Different subclasses can employ different
170             caching techniques.
171              
172             The basic model implemented here is simple; It stores a hash key of the file
173             contents keyed by a hash key of the file's path.
174              
175             =head1 METHODS
176              
177             This class has the following methods:
178              
179             =head2 Code::TidyAll::CacheModel->new(%params)
180              
181             The constructor accepts the following attributes:
182              
183             =over 4
184              
185             =item * full_path
186              
187             The full path to the cache file on disk. This is required.
188              
189             =item * path
190              
191             The local path to the file (i.e. what the cache system will consider the
192             canonical name of the file).
193              
194             =item * cache_engine
195              
196             A C<Code::TidyAll::Cache> compatible instance. This can be omitted if no
197             caching is actually being done.
198              
199             =item * base_sig
200              
201             A base signature. This defaults to an empty string.
202              
203             =item * file_contents
204              
205             The contents of the file being cached. This can be omitted, in which case it
206             will be loaded as needed.
207              
208             =item * is_cached
209              
210             A boolean indicating if this file is cached. By default this is computed by
211             checking that the cache key and cache value match what is in the cache.
212              
213             =back
214              
215             =head2 $model->full_path
216              
217             The value passed to the constructor.
218              
219             =head2 $model->path
220              
221             The value passed to the constructor.
222              
223             =head2 $model->cache_engine
224              
225             The value passed to the constructor.
226              
227             =head2 $model->base_sig
228              
229             The value passed to the constructor or the default value, an empty string.
230              
231             =head2 $model->file_contents
232              
233             The file contents, which will be loaded from the file system if needed.
234              
235             =head2 $model->is_cached
236              
237             A boolean indicating whether the path is currently in the cache.
238              
239             =head2 $model->cache_key
240              
241             The computed cache key for the file.
242              
243             =head2 $model->cache_value
244              
245             The computed cache value for the file.
246              
247             =head2 $model->update
248              
249             Updates the cache.
250              
251             =head2 $model->remove
252              
253             Attempts to remove the value from the cache.
254              
255             =head1 SUPPORT
256              
257             Bugs may be submitted at L<https://github.com/houseabsolute/perl-code-tidyall/issues>.
258              
259             =head1 SOURCE
260              
261             The source code repository for Code-TidyAll can be found at L<https://github.com/houseabsolute/perl-code-tidyall>.
262              
263             =head1 AUTHORS
264              
265             =over 4
266              
267             =item *
268              
269             Jonathan Swartz <swartz@pobox.com>
270              
271             =item *
272              
273             Dave Rolsky <autarch@urth.org>
274              
275             =back
276              
277             =head1 COPYRIGHT AND LICENSE
278              
279             This software is copyright (c) 2011 - 2022 by Jonathan Swartz.
280              
281             This is free software; you can redistribute it and/or modify it under
282             the same terms as the Perl 5 programming language system itself.
283              
284             The full text of the license can be found in the
285             F<LICENSE> file included with this distribution.
286              
287             =cut