File Coverage

blib/lib/Plack/Debugger/Storage.pm
Criterion Covered Total %
statement 56 57 98.2
branch 13 24 54.1
condition 5 13 38.4
subroutine 16 16 100.0
pod 11 11 100.0
total 101 121 83.4


line stmt bran cond sub pod time code
1             package Plack::Debugger::Storage;
2              
3             # ABSTRACT: The storage manager for debugging data
4              
5 1     1   69693 use strict;
  1         2  
  1         30  
6 1     1   4 use warnings;
  1         1  
  1         38  
7              
8             our $VERSION = '0.03';
9             our $AUTHORITY = 'cpan:STEVAN';
10              
11 1     1   8 use File::Spec;
  1         2  
  1         1011  
12              
13             sub new {
14 1     1 1 645 my $class = shift;
15 1 50 33     11 my %args = @_ == 1 && ref $_[0] eq 'HASH' ? %{ $_[0] } : @_;
  0         0  
16              
17 1 50       4 die "You must specify a data directory for collecting debugging data"
18             unless defined $args{'data_dir'};
19              
20 1 50 33     7 die "You must specify a valid & writable data directory"
21             unless -d $args{'data_dir'} && -w $args{'data_dir'};
22              
23 1         85 foreach (qw[ serializer deserializer ]) {
24 2 50       4 die "You must provide a $_ callback"
25             unless defined $args{ $_ };
26              
27 2 50 33     12 die "The $_ callback must be a CODE reference"
28             unless ref $args{ $_ }
29             && ref $args{ $_ } eq 'CODE';
30             }
31              
32             bless {
33 1   50     9 data_dir => $args{'data_dir'},
34             serializer => $args{'serializer'},
35             deserializer => $args{'deserializer'},
36             filename_fmt => $args{'filename_fmt'} || '%s',
37             } => $class;
38             }
39              
40             # accessors
41              
42 8     8 1 91 sub data_dir { (shift)->{'data_dir'} } # directory where collected debugging data is stored
43 4     4 1 20 sub serializer { (shift)->{'serializer'} } # CODE ref serializer for data into data-dir
44 5     5 1 20 sub deserializer { (shift)->{'deserializer'} } # CODE ref deserializer for data into data-dir
45 8     8 1 249 sub filename_fmt { (shift)->{'filename_fmt'} } # format string for filename, takes the request UID (optional)
46              
47             # ...
48              
49             sub store_request_results {
50 1     1 1 1029 my ($self, $request_uid, $results) = @_;
51 1         3 $self->_store_results( $self->data_dir, (sprintf $self->filename_fmt => $request_uid), $results );
52             }
53              
54             sub store_subrequest_results {
55 2     2 1 1003148 my ($self, $request_uid, $subrequest_uid, $results) = @_;
56 2         10 my $dir = File::Spec->catfile( $self->data_dir, $request_uid );
57 2 100 50     161 mkdir $dir or die "Could not create $dir because $!"
58             unless -e $dir;
59 2         8 $self->_store_results( $dir, (sprintf $self->filename_fmt => $subrequest_uid), $results );
60             }
61              
62             sub load_request_results {
63 1     1 1 987 my ($self, $request_uid) = @_;
64 1         4 return $self->_load_results( $self->data_dir, (sprintf $self->filename_fmt => $request_uid) );
65             }
66              
67             sub load_subrequest_results {
68 1     1 1 2183 my ($self, $request_uid, $subrequest_uid) = @_;
69 1         3 my $dir = File::Spec->catfile( $self->data_dir, $request_uid );
70 1 50       30 die "Could not find $dir" unless -e $dir;
71 1         2 return $self->_load_results( $dir, (sprintf $self->filename_fmt => $subrequest_uid) );
72             }
73              
74             sub load_all_subrequest_results {
75 1     1 1 901 my ($self, $request_uid) = @_;
76 1         3 my $dir = File::Spec->catfile( $self->data_dir, $request_uid );
77 1 50       30 return [] unless -e $dir;
78             return [
79 1         16 map {
80 1         4 $self->_load_results( $dir, (File::Spec->splitpath($_))[2] )
81             } glob( File::Spec->catfile( $dir, sprintf $self->filename_fmt => '*' ) )
82             ];
83             }
84              
85             sub load_all_subrequest_results_modified_since {
86 1     1 1 2817 my ($self, $request_uid, $epoch) = @_;
87 1 50       5 die "You must specify an epoch to check modification date against"
88             unless $epoch;
89 1         2 my $dir = File::Spec->catfile( $self->data_dir, $request_uid );
90 1 50       76 return [] unless -e $dir;
91             return [
92 1         26 map {
93 2         52 $self->_load_results( $dir, (File::Spec->splitpath($_))[2] )
94             } grep {
95 1         7 (stat( $_ ))[9] > $epoch
96             } glob( File::Spec->catfile( $dir, sprintf $self->filename_fmt => '*' ) )
97             ];
98             }
99              
100             # private utils ...
101              
102             sub _store_results {
103 3     3   4 my ($self, $dir, $filename, $results) = @_;
104 3         23 my $file = File::Spec->catfile( $dir, $filename );
105 3 50       38 my $fh = IO::File->new( $file, '>' ) or die "Could not open file($file) for writing because: $!";
106 3         478 $fh->print( $self->serializer->( $results ) );
107 3         121 $fh->close;
108             }
109              
110             sub _load_results {
111 4     4   7 my ($self, $dir, $filename) = @_;
112 4         32 my $file = File::Spec->catfile( $dir, $filename );
113 4 50       39 my $fh = IO::File->new( $file, '<' ) or die "Could not open file($file) for reading because: $!";
114 4         376 my $results = $self->deserializer->( join '' => <$fh> ) ;
115 4         110 $fh->close;
116 4         60 $results;
117             }
118              
119              
120             1;
121              
122             __END__