File Coverage

blib/lib/POE/Component/DirWatch/WithCaller.pm
Criterion Covered Total %
statement 15 15 100.0
branch n/a
condition n/a
subroutine 5 5 100.0
pod n/a
total 20 20 100.0


line stmt bran cond sub pod time code
1             package POE::Component::DirWatch::WithCaller;
2              
3             our $VERSION = "1.00";
4              
5 1     1   15574 use 5.006;
  1         3  
  1         41  
6 1     1   5 use strict;
  1         0  
  1         34  
7 1     1   4 use warnings;
  1         5  
  1         29  
8 1     1   580 use Moose;
  1         350988  
  1         7  
9 1     1   6262 use POE;
  1         32297  
  1         6  
10              
11             extends 'POE::Component::DirWatch';
12              
13             has ignore_seen => (
14             is => 'ro',
15             isa => 'Int',
16             required => 1,
17             default => 0,
18             );
19             has ensure_seen => (
20             is => 'ro',
21             isa => 'Int',
22             required => 0,
23             default => 0,
24             );
25             has seen_files => (
26             is => 'rw',
27             isa => 'HashRef',
28             default => sub{{}},
29             );
30              
31             override '_poll' => sub {
32             # the vast majority of this is copied from POE::Component::DirWatch's _poll subroutine by virtue of not being able to call super
33             my ($self, $kernel) = @_[OBJECT, KERNEL];
34             $self->clear_next_poll;
35              
36             # seen_files portions borrowed from POE::Component::DirWatch::Object::NewFile
37             %{ $self->seen_files } = map {$_ => $self->seen_files->{$_} } grep {-e $_ } keys %{ $self->seen_files };
38             my $filter = $self->has_filter ? $self->filter : undef;
39             my $has_dir_cb = $self->has_dir_callback;
40             my $has_file_cb = $self->has_file_callback;
41              
42             while (my $child = $self->directory->next) {
43             if($child->is_dir) {
44             next unless $has_dir_cb;
45             next if ref $filter && !$filter->($self->alias, $child);
46             $kernel->yield(dir_callback => $child);
47             } else {
48             next unless $has_file_cb;
49             next if $child->basename =~ /^\.+$/;
50             $self->seen_files->{"$child"} = 0 if not defined $self->seen_files->{"$child"};
51             next unless $self->seen_files->{"$child"} == 0 or $self->seen_files->{"$child"} > 120 or not $self->ignore_seen;
52             $self->seen_files->{"$child"}++ unless ($self->seen_files->{"$child"}*$self->interval) > 120 and $self->seen_files->{"$child"} = -1;
53             $self->seen_files->{"$child"} = 1 if $self->ignore_seen and not $self->ensure_seen;
54             next if ref $filter && !$filter->($self->alias, $child);
55             $kernel->yield(file_callback => $child);
56             }
57             }
58             $self->next_poll( $kernel->delay_set(poll => $self->interval) );
59             };
60              
61             override '_file_callback' => sub {
62             my ($self, $kernel, $file) = @_[OBJECT, KERNEL, ARG0];
63             $self->file_callback->($self->alias, $file);
64             };
65              
66             override '_dir_callback' => sub {
67             my ($self, $kernel, $dir) = @_[OBJECT, KERNEL, ARG0];
68             $self->dir_callback->($self->alias, $dir);
69             };
70              
71             1;
72             __END__
73              
74             =pod
75              
76             =encoding UTF-8
77              
78             =head1 NAME
79              
80             POE::Component::DirWatch::WithCaller - An extension to POE::Component::DirWatch to pass through the name of the calling DirWatch instance, useful for cases where DirWatch sessions may be dynamically created while sharing callback functions whose behaviour may differ in small ways depending on the caller.
81              
82             =head1 VERSION
83              
84             Version 1.00
85              
86             =head1 SYNOPSIS
87              
88             Somewhat simple extension to L<POE::Component::DirWatch> that passes the name of the calling DirWatch session to callback functions.
89              
90             sub filter { my ($caller,$file) = @_; return 1; }
91             sub file { my ($caller,$file) = @_; }
92             my $monitor = POE::Component::DirWatch::WithCaller->new(
93             alias => 'mymonitor',
94             directory => '/my/path',
95             filter => \&filter,
96             file_callback => \&file,
97             interval => 5,
98             );
99              
100             Filtering already-seen files can be achieved as such:
101              
102             sub filter { my ($caller,$file) = @_; return 1; }
103             sub file { my ($caller,$file) = @_; }
104             my $monitor = POE::Component::DirWatch::WithCaller->new(
105             alias => 'mymonitor',
106             directory => '/my/path',
107             filter => \&filter,
108             file_callback => \&file,
109             interval => 5,
110             ignore_seen => 1,
111             );
112              
113             In some instances, using C<ignore_seen> may result in some files being internally marked as 'seen' without being filtered or sent through callbacks, see below.
114              
115             =head1 FILTERING PREVIOUSLY-SEEN FILES
116              
117             Depending on use case, it may be beneficial or necessary to filter out previously-seen files, either for performance reasons when monitoring highly populous directories for specific files, or for avoiding reprocessing files in the event that they are left in the directory after initial processing.
118             In this case, simply specifying C<ignore_seen =E<gt> 1> as a named argument when creating the DirWatch::WithCaller object will enable this behaviour.
119             While testing this feature, however, it was observed that some edge cases exist in which a file will be considered 'seen' when it has not been processed despite matching a defined monitor. To account for this, each file that has been considered 'seen' will be reprocessed once around 120 seconds after it was first 'seen'. This behaviour may not be desirable, and as such is disabled by default, and can be enabled by specifying C<ensure_seen =E<gt> 1> when creating the object.
120              
121              
122             =head1 AUTHOR
123              
124             Matthew Connelly, C<< <maff at cpan.org> >>
125              
126             =head1 BUGS
127              
128             Please report any bugs or feature requests to C<bug-poe-component-dirwatch-withcaller at rt.cpan.org>, or through
129             the web interface at L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=POE-Component-DirWatch-WithCaller>. I will be notified, and then you'll
130             automatically be notified of progress on your bug as I make changes.
131              
132             =head1 SUPPORT
133              
134             You can find documentation for this module with the perldoc command.
135              
136             perldoc POE::Component::DirWatch::WithCaller
137              
138              
139             You can also look for information at:
140              
141             =over 4
142              
143             =item * RT: CPAN's request tracker (report bugs here)
144              
145             L<http://rt.cpan.org/NoAuth/Bugs.html?Dist=POE-Component-DirWatch-WithCaller>
146              
147             =item * AnnoCPAN: Annotated CPAN documentation
148              
149             L<http://annocpan.org/dist/POE-Component-DirWatch-WithCaller>
150              
151             =item * CPAN Ratings
152              
153             L<http://cpanratings.perl.org/d/POE-Component-DirWatch-WithCaller>
154              
155             =item * Search CPAN
156              
157             L<http://search.cpan.org/dist/POE-Component-DirWatch-WithCaller/>
158              
159             =back
160              
161              
162             =head1 ACKNOWLEDGEMENTS
163              
164             Guillermo Roditi, <groditi@cpan.org>
165             Robert Rothenberg, <rrwo@cpan.org>
166              
167             =head1 SEE ALSO
168              
169             L<POE::Component::DirWatch>, L<POE::Component::DirWatch::Object::NewFile>
170              
171             =head1 LICENSE AND COPYRIGHT
172              
173             Copyright 2015 Matthew Connelly.
174              
175             This program is free software; you can redistribute it and/or modify it
176             under the terms of the the Artistic License (2.0). You may obtain a
177             copy of the full license at:
178              
179             L<http://www.perlfoundation.org/artistic_license_2_0>
180              
181             Any use, modification, and distribution of the Standard or Modified
182             Versions is governed by this Artistic License. By using, modifying or
183             distributing the Package, you accept this license. Do not use, modify,
184             or distribute the Package, if you do not accept this license.
185              
186             If your Modified Version has been derived from a Modified Version made
187             by someone other than you, you are nevertheless required to ensure that
188             your Modified Version complies with the requirements of this license.
189              
190             This license does not grant you the right to use any trademark, service
191             mark, tradename, or logo of the Copyright Holder.
192              
193             This license includes the non-exclusive, worldwide, free-of-charge
194             patent license to make, have made, use, offer to sell, sell, import and
195             otherwise transfer the Package with respect to any patent claims
196             licensable by the Copyright Holder that are necessarily infringed by the
197             Package. If you institute patent litigation (including a cross-claim or
198             counterclaim) against any party alleging that the Package constitutes
199             direct or contributory patent infringement, then this Artistic License
200             to you shall terminate on the date that such litigation is filed.
201              
202             Disclaimer of Warranty: THE PACKAGE IS PROVIDED BY THE COPYRIGHT HOLDER
203             AND CONTRIBUTORS "AS IS' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES.
204             THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
205             PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED TO THE EXTENT PERMITTED BY
206             YOUR LOCAL LAW. UNLESS REQUIRED BY LAW, NO COPYRIGHT HOLDER OR
207             CONTRIBUTOR WILL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, OR
208             CONSEQUENTIAL DAMAGES ARISING IN ANY WAY OUT OF THE USE OF THE PACKAGE,
209             EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
210