Skip to content

Commit 83c92da

Browse files
committed
Avoid opening too many jobs in the collector. Only parse so many at one time.
Most unix systems limit the number of file handles any one process can have open at a time to 1024. When the collector gets behind, it may try to open too many files for completed jobs at once. Limit this with a new collector setting which defaults to 300. They'll be picked up once the ones polled are processed. This commit adds App::Yath::Options::Collector
1 parent 1432c1e commit 83c92da

File tree

4 files changed

+91
-3
lines changed

4 files changed

+91
-3
lines changed

lib/App/Yath/Command/collector.pm

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ our $VERSION = '1.000039';
66

77
use File::Spec;
88

9+
use App::Yath::Options;
910
use App::Yath::Util qw/isolate_stdout/;
1011

1112
use Test2::Harness::Util::JSON qw/decode_json/;
@@ -16,6 +17,12 @@ use Test2::Harness::Run;
1617
use parent 'App::Yath::Command';
1718
use Test2::Harness::Util::HashBase;
1819

20+
include_options(
21+
'App::Yath::Options::Debug',
22+
'App::Yath::Options::PreCommand',
23+
'App::Yath::Options::Collector',
24+
);
25+
1926
sub internal_only { 1 }
2027
sub summary { "For internal use only" }
2128
sub name { 'collector' }
@@ -28,7 +35,7 @@ sub run {
2835

2936
my $fh = isolate_stdout();
3037

31-
my $settings = Test2::Harness::Settings->new(File::Spec->catfile($dir, 'settings.json'));
38+
my $settings = $self->settings;
3239

3340
require(mod2file($collector_class));
3441

lib/App/Yath/Options/Collector.pm

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
package App::Yath::Options::Collector;
2+
use strict;
3+
use warnings;
4+
5+
our $VERSION = '1.000039';
6+
7+
use App::Yath::Options;
8+
9+
option_group {prefix => 'collector', category => "Collector Options"} => sub {
10+
option max_jobs_to_process => (
11+
description => 'The maximum number of jobs that the collector can process each loop (Default: 300)',
12+
default => 300,
13+
);
14+
};
15+
16+
1;
17+
18+
__END__
19+
20+
21+
=pod
22+
23+
=encoding UTF-8
24+
25+
=head1 NAME
26+
27+
App::Yath::Options::Collector - collector options for Yath.
28+
29+
=head1 DESCRIPTION
30+
31+
This is where the command line options for the collector are defined.
32+
33+
=head1 PROVIDED OPTIONS POD IS AUTO-GENERATED
34+
35+
=head1 SOURCE
36+
37+
The source code repository for Test2-Harness can be found at
38+
F<http://github.com/Test-More/Test2-Harness/>.
39+
40+
=head1 MAINTAINERS
41+
42+
=over 4
43+
44+
=item Chad Granum E<lt>[email protected]E<gt>
45+
46+
=back
47+
48+
=head1 AUTHORS
49+
50+
=over 4
51+
52+
=item Chad Granum E<lt>[email protected]E<gt>
53+
54+
=back
55+
56+
=head1 COPYRIGHT
57+
58+
Copyright 2020 Chad Granum E<lt>[email protected]E<gt>.
59+
60+
This program is free software; you can redistribute it and/or
61+
modify it under the same terms as Perl itself.
62+
63+
See F<http://dev.perl.org/licenses/>
64+
65+
=cut

lib/Test2/Harness/Collector.pm

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -221,9 +221,19 @@ sub jobs {
221221

222222
return $jobs if $self->{+JOBS_DONE};
223223

224+
# Don't monitor more than 'max_jobs_to_process' or we might have too many open file handles and crash
225+
# Max open files handles on a process applies. Usually this is 1024 so we can't have everything open at once when we're behind.
226+
my $max_jobs_to_process = $self->settings->collector->max_jobs_to_process // 1024;
227+
my $additional_jobs_to_parse = $max_jobs_to_process - scalar keys %$jobs;
228+
if($additional_jobs_to_parse <= 0) {
229+
# This is an unlikely code path. If we're here, it means the last loop couldn't process any results.
230+
print "WARN: max jobs still exceded. Continuing to process jobs\n";
231+
return $jobs;
232+
}
233+
224234
my $queue = $self->jobs_queue or return $jobs;
225235

226-
for my $item ($queue->poll) {
236+
for my $item ($queue->poll($additional_jobs_to_parse)) {
227237
my ($spos, $epos, $job) = @$item;
228238

229239
unless ($job) {
@@ -271,6 +281,11 @@ sub jobs {
271281
);
272282
}
273283

284+
# The collector didn't read in all the jobs because it'd run out of file handles. We need to let the stream know we're behind.
285+
if( scalar keys %$jobs >= $max_jobs_to_process ) {
286+
print STDERR "WARN: The Yath Collector is running behind. More than $max_jobs_to_process test results have not been processed.\n";
287+
}
288+
274289
return $jobs;
275290
}
276291

lib/Test2/Harness/Util/Queue.pm

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,11 +43,12 @@ sub reset {
4343

4444
sub poll {
4545
my $self = shift;
46+
my $max = shift;
4647

4748
return $self->{+ENDED} if $self->{+ENDED};
4849

4950
$self->{+QH} ||= Test2::Harness::Util::File::JSONL->new(name => $self->{+FILE});
50-
my @out = $self->{+QH}->poll_with_index();
51+
my @out = $self->{+QH}->poll_with_index( $max ? (max => $max) : () );
5152

5253
$self->{+ENDED} = $out[-1] if @out && !defined($out[-1]->[-1]);
5354

0 commit comments

Comments
 (0)