From 2c0d0b3cc7ca207cb24a3b7b88325d07f2af3a0b Mon Sep 17 00:00:00 2001 From: Oliver Gorwits Date: Wed, 31 Jan 2018 14:02:11 +0000 Subject: [PATCH] #228 timeout setting (default 10min) for backend jobs --- Build.PL | 5 +++-- Changes | 5 +++++ lib/App/Netdisco/Worker/Runner.pm | 30 +++++++++++++++++++++++++----- share/config.yml | 1 + 4 files changed, 34 insertions(+), 7 deletions(-) diff --git a/Build.PL b/Build.PL index 94eb60a2..d80d5b32 100644 --- a/Build.PL +++ b/Build.PL @@ -64,7 +64,8 @@ Module::Build->new( 'Sereal' => '0', 'Socket6' => '0.23', 'Starman' => '0.4008', - 'Storable' => 0, + 'Storable' => '0', + 'Sys::SigAction' => '0', 'SNMP::Info' => '3.40', 'SQL::Translator' => '0.11018', 'Template' => '2.24', @@ -75,7 +76,7 @@ Module::Build->new( 'Try::Tiny' => '0', 'URI' => '0', 'URL::Encode' => '0.03', - 'URL::Encode::XS' => 0, + 'URL::Encode::XS' => '0', 'YAML' => '0.84', 'YAML::XS' => '0.41', }, diff --git a/Changes b/Changes index 829845e3..ef70e8a9 100644 --- a/Changes +++ b/Changes @@ -1,5 +1,10 @@ 2.038033 - 2018-01-?? + [NEW FEATURES] + + * #228 timeout setting (default 10min) for backend jobs + * #341 timeout setting for all actions ("_timeout") + [BUG FIXES] * #367 buttons in the neighbourmap have an incorrect height diff --git a/lib/App/Netdisco/Worker/Runner.pm b/lib/App/Netdisco/Worker/Runner.pm index c0f1a770..bf604a15 100644 --- a/lib/App/Netdisco/Worker/Runner.pm +++ b/lib/App/Netdisco/Worker/Runner.pm @@ -6,9 +6,11 @@ use App::Netdisco::Util::Permission qw/check_acl_no check_acl_only/; use aliased 'App::Netdisco::Worker::Status'; use Try::Tiny; +use Time::HiRes (); use Module::Load (); use Scope::Guard 'guard'; use Storable 'dclone'; +use Sys::SigAction 'timeout_call'; use Moo::Role; use namespace::clean; @@ -55,12 +57,30 @@ sub run { my $configguard = guard { set(device_auth => \@userconf) }; set(device_auth => \@newuserconf); - # run check phase and if there are workers then one MUST be successful - $self->run_workers('workers_check'); - return if not $job->check_passed; + my $runner = sub { + my ($self, $job) = @_; - # run other phases - $self->run_workers("workers_${_}") for qw/early main user/; + # run check phase and if there are workers then one MUST be successful + $self->run_workers('workers_check'); + + # run other phases + if ($job->check_passed) { + $self->run_workers("workers_${_}") for qw/early main user/; + } + }; + + my $maxtime = ((defined setting($job->action .'_timeout')) + ? setting($job->action .'_timeout') : setting('timeout')); + if ($maxtime) { + debug sprintf '%s: running with timeout %ss', $job->action, $maxtime; + if (timeout_call($maxtime, $runner, ($self, $job))) { + debug sprintf '%s: timed out!', $job->action; + $job->add_status( Status->error("job timed out after $maxtime sec") ); + } + } + else { + $runner->($self, $job); + } } sub run_workers { diff --git a/share/config.yml b/share/config.yml index fd9e39f6..a639fcf9 100644 --- a/share/config.yml +++ b/share/config.yml @@ -199,6 +199,7 @@ snmptimeout: 3000000 snmpretries: 2 devices_no: [] devices_only: [] +timeout: 600 discover_no: [] discover_only: [] discover_no_type: