File Coverage

blib/lib/App/PerlWatcher/Engine.pm
Criterion Covered Total %
statement 96 96 100.0
branch 6 6 100.0
condition n/a
subroutine 23 23 100.0
pod 3 4 75.0
total 128 129 99.2


line stmt bran cond sub pod time code
1             package App::PerlWatcher::Engine;
2             {
3             $App::PerlWatcher::Engine::VERSION = '0.20';
4             }
5             # ABSTRACT: Creates Watchers and lets them notify Frontend with their's Statuses
6              
7 4     4   16807072 use 5.12.0;
  4         15  
  4         180  
8 4     4   20 use strict;
  4         9  
  4         112  
9 4     4   23 use warnings;
  4         7  
  4         116  
10              
11 4     4   1780 use AnyEvent;
  4         6479  
  4         105  
12 4     4   24 use Carp;
  4         7  
  4         313  
13 4     4   4018 use Class::Load ':all';
  4         180141  
  4         683  
14 4     4   912 use Smart::Comments -ENV;
  4         31624  
  4         46  
15 4     4   3570 use File::Spec;
  4         9  
  4         109  
16 4     4   3606 use List::MoreUtils qw/first_index/;
  4         5466  
  4         335  
17 4     4   3795 use Moo;
  4         93682  
  4         29  
18 4     4   11813 use Path::Tiny;
  4         66393  
  4         316  
19              
20 4     4   2513 use App::PerlWatcher::Shelf;
  4         20  
  4         156  
21 4     4   3453 use App::PerlWatcher::Util::Bootstrap qw/get_home_dir/;
  4         16  
  4         291  
22 4     4   3037 use App::PerlWatcher::Util::Storable qw/freeze thaw/;
  4         13  
  4         3793  
23              
24              
25              
26              
27              
28             has 'frontend' => ( is => 'rw');
29              
30              
31             has 'config' => ( is => 'ro', required => 0);
32              
33             has 'backend' => ( is => 'ro', required => 1);
34              
35              
36             has 'statuses_file' => ( is => 'ro', default => sub {
37             return path(File::Spec->catfile(get_home_dir(), "statuses-shelf.data"));
38             });
39              
40              
41             has 'watchers' => ( is => 'lazy');
42              
43              
44             has 'polling_watchers' => ( is => 'ro', default => sub{ [] });
45              
46              
47             has 'watchers_order' => ( is => 'lazy');
48              
49              
50             has 'shelf' => ( is => 'rw');
51              
52             sub _build_watchers {
53 10     10   3620 my $self = shift;
54 10         49 my $config = $self->config;
55 10         18 my @r;
56             my $poll_callback = sub {
57 4     4   12 my $w = shift;
58 4         8 push @{ $self->polling_watchers }, $w;
  4         86  
59 4         43 $self->frontend->poll($w);
60 10         70 };
61             my $engine_callback = sub {
62 2     2   5 my $status = shift;
63 2         30 my $w_idx = first_index { $_->unique_id eq $status->watcher->unique_id }
64 2         13 @{ $self->polling_watchers };
  2         30  
65 2         128 splice( @{ $self->polling_watchers }, $w_idx, 1);
  2         9  
66             AnyEvent::postpone {
67 2         2529 $self->frontend->update($status);
68 2         16 };
69 10         59 };
70 10         20 for my $watcher_definition ( @{ $config -> {watchers} } ) {
  10         41  
71 20         67 my ($class, $watcher_config )
72 20         318 = @{ $watcher_definition }{ qw/class config/ };
73 20         263 my $watcher;
74 20         29 eval {
75 20         99 load_class($class);
76 19         3930 $watcher = $class->new(
77             engine_config => $config,
78             callback => $engine_callback,
79             poll_callback => $poll_callback,
80             %$watcher_config
81             );
82 19         169 $watcher->callback($engine_callback);
83 18         30 push @r, $watcher;
84             };
85 20 100       827 carp "Error creating watcher $class : $@" if $@;
86             }
87 10         74 return \@r;
88             }
89              
90             sub _build_watchers_order {
91 1     1   1060 my $self = shift;
92 1         82 my $watchers = $self->watchers;
93 1         15 my $order = {};
94 1         82 $order->{ $watchers->[$_] } = $_ for 0 .. @$watchers - 1;
95 1         53 return $order;
96             }
97              
98             sub _build_shelf {
99 10     10   28 my $self = shift;
100 10         39 my $statuses_file = $self->statuses_file;
101 10 100       34 if ( -r $statuses_file ) {
102 2         60 my $data = $statuses_file->slurp;
103 2 100       365 thaw($self, $data)
104             and return $self->shelf;
105             }
106 9         524 return App::PerlWatcher::Shelf->new;
107             }
108              
109             sub BUILD {
110 10     10 0 652 my $self = shift;
111 10         35 $self->shelf($self->_build_shelf);
112             }
113              
114              
115             sub start {
116 2     2 1 4708 my $self = shift;
117 2         6 $_->start for ( @{ $self->watchers } );
  2         22  
118             # actually trigger watchers
119 2         42 $self->backend->start_loop;
120             }
121              
122              
123             sub stop {
124 2     2 1 1544 my $self = shift;
125 2         23 $self->backend->stop_loop;
126              
127 2         55 my $data = freeze($self);
128 2         316 $self->statuses_file->spew($data);
129             }
130              
131              
132             sub sort_statuses {
133 1     1 1 3 my ($self, $statuses) = @_;
134 1         9 my $order_of = $self->watchers_order;
135             return [
136 1         11 sort {
137 1         9 $order_of->{ $a->watcher } <=> $order_of->{ $b->watcher };
138             } @$statuses
139             ];
140             }
141              
142              
143             1;
144              
145             __END__