File Coverage

blib/lib/Dancer2/Plugin/ProgressStatus.pm
Criterion Covered Total %
statement 63 76 82.8
branch 16 30 53.3
condition 3 12 25.0
subroutine 14 15 93.3
pod n/a
total 96 133 72.1


line stmt bran cond sub pod time code
1             # ABSTRACT: Keeps track of progress status
2              
3             package Dancer2::Plugin::ProgressStatus;
4             $Dancer2::Plugin::ProgressStatus::VERSION = '0.018';
5 1     1   515795 use strict;
  1         2  
  1         25  
6 1     1   5 use warnings;
  1         2  
  1         27  
7              
8 1     1   5 use Digest::MD5 qw/md5_hex/;
  1         2  
  1         53  
9 1     1   1146 use Path::Tiny;
  1         9134  
  1         53  
10 1     1   7 use File::Path qw//;
  1         2  
  1         17  
11 1     1   5 use Carp;
  1         2  
  1         54  
12 1     1   1020 use JSON qw//;
  1         12472  
  1         25  
13              
14 1     1   744 use Dancer2::Plugin;
  1         2286  
  1         6  
15 1     1   2720 use Dancer2::Plugin::ProgressStatus::Object;
  1         3  
  1         31  
16 1     1   6 use Dancer2::Core::Response;
  1         2  
  1         869  
17              
18             sub _progress_status_file {
19 9     9   25 my ( $dsl, $name ) = @_;
20              
21             my $dir = $dsl->app->config->{'plugins'}{ProgressStatus}{dir}
22 9 50       52 or croak 'No ProgressStatus plugin settings in config';
23 9 50       657 if ( !-d $dir ) {
24 0 0       0 File::Path::make_path($dir) or die "Cannot create path $dir";
25             }
26              
27 9         90 return Path::Tiny::path($dir, md5_hex($name));
28             }
29              
30              
31             on_plugin_import {
32             my $dsl = shift;
33              
34             # determine if there is a prefix?
35              
36             # Register the route for fetching messages
37             # We must specify the content_type and encoding here because this plugin
38             # only works for json, and the D2 config might have other settings
39             $dsl->app->add_route(
40             method => 'get',
41             regexp => '/_progress_status/:name',
42             code => sub {
43             my $context = shift;
44             my $data = _get_progress_status_data($dsl, $context->request->params->{'name'});
45              
46             $context->response->status(200);
47             $context->response->content(JSON->new->utf8->encode($data));
48             $context->response->content_type('application/json');
49             $context->response->is_encoded(1);
50              
51             return $context->response;
52             },
53             );
54             };
55              
56             sub _get_progress_status_data {
57 4     4   46 my ($dsl, $name) = @_;
58              
59 4         17 my $file = $dsl->_progress_status_file($name);
60 4 50       165 if ( !$file->is_file ) {
61             return {
62 0         0 error => "No such progress status $name",
63             status => 'error',
64             };
65             }
66 4         166 my $data = JSON->new->utf8(0)->decode($file->slurp_utf8());
67 4         839 delete $data->{pid};
68              
69 4         14 return $data;
70             }
71              
72              
73             register start_progress_status => sub {
74 5     5   144584 my ($dsl, $args) = @_;
75              
76 5 100       25 if ( !ref($args) ) {
77 3         14 $args = { name => $args };
78             }
79              
80 5         42 my $progress_id = $dsl->params->{progress_id};
81 5         87 my $name = delete $args->{name};
82 5 50 66     20 if ( !$name && !$progress_id ) {
83 0         0 croak 'Must supply name and/or progress_id';
84             }
85 5 100       21 $name .= $progress_id if $progress_id;
86              
87 5         21 my $file = $dsl->_progress_status_file($name);
88 5 100       248 if ( $file->is_file ) {
89 1         43 my $d = JSON->new->utf8(0)->decode($file->slurp_utf8());
90 1         189 my $in_progress = $d->{in_progress};
91              
92 1 50 33     8 if ( $in_progress && $d->{pid} != $$ ) {
    50          
93 0 0       0 if ( kill(0, $d->{pid}) ) {
94 0         0 die "Progress status $name already exists for a running process, cannot create a new one\n";
95             }
96             }
97             elsif ( $in_progress ) {
98 1         41 die "Progress status $name already exists\n";
99             }
100             }
101              
102             my %objargs = (
103             _on_save => sub {
104 20     20   34 my ($obj, $is_finished) = @_;
105 20 100       833 my $data = JSON->new->utf8(0)->encode({
106             start_time => $obj->start_time,
107             current_time => $obj->current_time,
108             total => $obj->total,
109             count => $obj->count,
110             messages => $obj->messages,
111             in_progress => $is_finished ? JSON::false : JSON::true,
112             status => $obj->status,
113             pid => $$,
114             });
115              
116 20         654 $file->spew_utf8($data);
117             },
118 4         222 );
119              
120 4         14 foreach my $key (qw/total count status messages/) {
121 16 100       46 if ( $args->{$key} ) {
122 2         6 $objargs{$key} = $args->{$key};
123             }
124             }
125              
126 4         116 my $obj = Dancer2::Plugin::ProgressStatus::Object->new(%objargs);
127 4         73 $obj->save();
128 4         4815 return $obj;
129             };
130              
131             register is_progress_running => sub {
132 0     0     my ( $dsl, $name ) = @_;
133 0           my $file = $dsl->_progress_status_file($name);
134              
135 0 0         if ( $file->exists ) {
136 0           my $d = JSON->new->utf8(0)->decode($file->slurp_utf8());
137 0           my $in_progress = $d->{in_progress};
138              
139 0 0 0       if ( $in_progress && $d->{pid} != $$ && kill(0, $d->{pid}) ) {
      0        
140 0           return 1;
141             }
142             }
143 0           return 0;
144             };
145              
146              
147             register_plugin;
148              
149              
150             1;
151              
152             __END__