Hello community, here is the log from the commit of package perl-Minion for openSUSE:Factory checked in at 2015-11-12 19:41:18 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/perl-Minion (Old) and /work/SRC/openSUSE:Factory/.perl-Minion.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "perl-Minion" Changes: -------- --- /work/SRC/openSUSE:Factory/perl-Minion/perl-Minion.changes 2015-11-11 10:36:07.000000000 +0100 +++ /work/SRC/openSUSE:Factory/.perl-Minion.new/perl-Minion.changes 2015-11-12 19:41:27.000000000 +0100 @@ -1,0 +2,13 @@ +Wed Nov 11 10:12:25 UTC 2015 - co...@suse.com + +- updated to 4.0 + see /usr/share/doc/packages/perl-Minion/Changes + + 4.0 2015-11-09 + - Removed attempts attribute from Minion::Job. + - Improved Minion::Backend::Pg to preserve more information across retries for + debugging. + - Fixed bug where jobs could not be retried automatically if a worker went + away. + +------------------------------------------------------------------- Old: ---- Minion-3.03.tar.gz New: ---- Minion-4.0.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ perl-Minion.spec ++++++ --- /var/tmp/diff_new_pack.5Ia9KT/_old 2015-11-12 19:41:28.000000000 +0100 +++ /var/tmp/diff_new_pack.5Ia9KT/_new 2015-11-12 19:41:28.000000000 +0100 @@ -17,7 +17,7 @@ Name: perl-Minion -Version: 3.03 +Version: 4.0 Release: 0 %define cpan_name Minion Summary: Job queue @@ -35,10 +35,10 @@ %{perl_requires} %description -the Minion manpage is a job queue for the http://mojolicio.us real-time web +Minion is a job queue for the Mojolicious|http://mojolicio.us real-time web framework with support for multiple named queues, priorities, delayed jobs, job results, retries with backoff, distributed workers, parallel processing -and multiple backends (such as http://www.postgresql.org). +and multiple backends (such as PostgreSQL|http://www.postgresql.org). A job queue allows you to process time and/or computationally intensive tasks in background processes, outside of the request/response lifecycle. @@ -66,24 +66,22 @@ app->start; -Background worker processes are usually started with the command the -Minion::Command::minion::worker manpage, which becomes automatically -available when an application loads the plugin the -Mojolicious::Plugin::Minion manpage. +Background worker processes are usually started with the command +Minion::Command::minion::worker, which becomes automatically available when +an application loads the plugin Mojolicious::Plugin::Minion. $ ./myapp.pl minion worker -Jobs can be managed right from the command line with the -Minion::Command::minion::job manpage. +Jobs can be managed right from the command line with +Minion::Command::minion::job. $ ./myapp.pl minion job Every job can fail or succeed, but not get lost, the system is eventually consistent and will preserve job results for as long as you like, depending -on the /"remove_after" manpage. While individual workers can fail in the -middle of processing a job, the system will detect this and ensure that no -job is left in an uncertain state, depending on the /"missing_after" -manpage. +on /"remove_after". While individual workers can fail in the middle of +processing a job, the system will detect this and ensure that no job is +left in an uncertain state, depending on /"missing_after". %prep %setup -q -n %{cpan_name}-%{version} ++++++ Minion-3.03.tar.gz -> Minion-4.0.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Minion-3.03/Changes new/Minion-4.0/Changes --- old/Minion-3.03/Changes 2015-11-08 10:45:42.000000000 +0100 +++ new/Minion-4.0/Changes 2015-11-09 13:30:50.000000000 +0100 @@ -1,4 +1,11 @@ +4.0 2015-11-09 + - Removed attempts attribute from Minion::Job. + - Improved Minion::Backend::Pg to preserve more information across retries for + debugging. + - Fixed bug where jobs could not be retried automatically if a worker went + away. + 3.03 2015-11-08 - Added queues option to perform_jobs method in Minion. @@ -6,7 +13,7 @@ - Fixed portability issues in tests. 3.01 2015-10-30 - - Added support retrying failed jobs automatically. + - Added support for retrying failed jobs automatically. - Added backoff attribute to Minion. - Added attempts attribute to Minion::Job. - Added attempts option to enqueue method in Minion and Minion::Backend::Pg. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Minion-3.03/META.json new/Minion-4.0/META.json --- old/Minion-3.03/META.json 2015-11-08 10:46:53.000000000 +0100 +++ new/Minion-4.0/META.json 2015-11-09 18:12:45.000000000 +0100 @@ -54,5 +54,5 @@ }, "x_IRC" : "irc://irc.perl.org/#mojo" }, - "version" : "3.03" + "version" : "4.0" } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Minion-3.03/META.yml new/Minion-4.0/META.yml --- old/Minion-3.03/META.yml 2015-11-08 10:46:53.000000000 +0100 +++ new/Minion-4.0/META.yml 2015-11-09 18:12:45.000000000 +0100 @@ -27,4 +27,4 @@ homepage: http://mojolicio.us license: http://www.opensource.org/licenses/artistic-license-2.0 repository: https://github.com/kraih/minion.git -version: '3.03' +version: '4.0' diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Minion-3.03/lib/Minion/Backend/Pg.pm new/Minion-4.0/lib/Minion/Backend/Pg.pm --- old/Minion-3.03/lib/Minion/Backend/Pg.pm 2015-10-30 21:35:50.000000000 +0100 +++ new/Minion-4.0/lib/Minion/Backend/Pg.pm 2015-11-09 16:16:53.000000000 +0100 @@ -111,13 +111,12 @@ ); # Abandoned jobs - $db->query( - "update minion_jobs as j - set finished = now(), result = to_json('Worker went away'::text), - state = 'failed' + my $fail = $db->query( + "select id, retries from minion_jobs as j where state = 'active' and not exists(select 1 from minion_workers where id = j.worker)" - ); + )->hashes; + $fail->each(sub { $self->fail_job(@$_{qw(id retries)}, 'Worker went away') }); # Old jobs $db->query( @@ -135,9 +134,8 @@ return !!$self->pg->db->query( "update minion_jobs - set finished = null, priority = coalesce(?, priority), - queue = coalesce(?, queue), retried = now(), retries = retries + 1, - started = null, state = 'inactive', worker = null, + set priority = coalesce(?, priority), queue = coalesce(?, queue), + retried = now(), retries = retries + 1, state = 'inactive', delayed = (now() + (interval '1 second' * ?)) where id = ? and retries = ? and state in ('failed', 'finished') returning 1", @$options{qw(priority queue)}, $options->{delay} // 0, $id, @@ -159,12 +157,12 @@ = $db->query($sql)->arrays->reduce(sub { $a->{$b->[0]} = $b->[1]; $a }, {}); return { + active_jobs => $states->{active} || 0, active_workers => $active, - inactive_workers => $all - $active, - active_jobs => $states->{active} || 0, - inactive_jobs => $states->{inactive} || 0, failed_jobs => $states->{failed} || 0, finished_jobs => $states->{finished} || 0, + inactive_jobs => $states->{inactive} || 0, + inactive_workers => $all - $active }; } @@ -197,7 +195,7 @@ limit 1 for update ) - returning id, args, attempts, retries, task", $id, + returning id, args, retries, task", $id, $options->{queues} || ['default'], [keys %{$self->minion->tasks}] )->expand->hash; } @@ -205,13 +203,18 @@ sub _update { my ($self, $fail, $id, $retries, $result) = @_; - return !!$self->pg->db->query( + return undef unless my $row = $self->pg->db->query( "update minion_jobs set finished = now(), result = ?, state = ? where id = ? and retries = ? and state = 'active' - returning 1", {json => $result}, $fail ? 'failed' : 'finished', $id, - $retries - )->rows; + returning attempts", {json => $result}, $fail ? 'failed' : 'finished', + $id, $retries + )->array; + + return 1 if !$fail || (my $attempts = $row->[0]) == 1; + return 1 if $retries >= ($attempts - 1); + my $delay = $self->minion->backoff->($retries); + return $self->retry_job($id, $retries, {delay => $delay}); } 1; @@ -282,12 +285,6 @@ Job arguments. -=item attempts - - attempts => 25 - -Number of times performing this job will be attempted, defaults to C<1>. - =item id id => '10023' @@ -353,7 +350,9 @@ my $bool = $backend->fail_job( $job_id, $retries, {whatever => 'Something went wrong!'}); -Transition from C<active> to C<failed> state. +Transition from C<active> to C<failed> state, and if there are attempts +remaining, transition back to C<inactive> with a delay based on +L<Minion/"backoff">. =head2 finish_job @@ -565,6 +564,48 @@ Get statistics for jobs and workers. +These fields are currently available: + +=over 2 + +=item active_jobs + + active_jobs => 100 + +Number of jobs in C<active> state. + +=item active_workers + + active_workers => 100 + +Number of workers that are currently processing a job. + +=item failed_jobs + + failed_jobs => 100 + +Number of jobs in C<failed> state. + +=item finished_jobs + + finished_jobs => 100 + +Number of jobs in C<finished> state. + +=item inactive_jobs + + inactive_jobs => 100 + +Number of jobs in C<inactive> state. + +=item inactive_workers + + inactive_workers => 100 + +Number of workers that are currently not processing a job. + +=back + =head2 unregister_worker $backend->unregister_worker($worker_id); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Minion-3.03/lib/Minion/Backend.pm new/Minion-4.0/lib/Minion/Backend.pm --- old/Minion-3.03/lib/Minion/Backend.pm 2015-10-30 21:35:50.000000000 +0100 +++ new/Minion-4.0/lib/Minion/Backend.pm 2015-11-09 16:08:23.000000000 +0100 @@ -109,12 +109,6 @@ Job arguments. -=item attempts - - attempts => 25 - -Number of times performing this job will be attempted, defaults to C<1>. - =item id id => '10023' @@ -180,8 +174,9 @@ my $bool = $backend->fail_job( $job_id, $retries, {whatever => 'Something went wrong!'}); -Transition from C<active> to C<failed> state. Meant to be overloaded in a -subclass. +Transition from C<active> to C<failed> state, and if there are attempts +remaining, transition back to C<inactive> with a delay based on +L<Minion/"backoff">. Meant to be overloaded in a subclass. =head2 finish_job @@ -395,6 +390,48 @@ Get statistics for jobs and workers. Meant to be overloaded in a subclass. +These fields are currently available: + +=over 2 + +=item active_jobs + + active_jobs => 100 + +Number of jobs in C<active> state. + +=item active_workers + + active_workers => 100 + +Number of workers that are currently processing a job. + +=item failed_jobs + + failed_jobs => 100 + +Number of jobs in C<failed> state. + +=item finished_jobs + + finished_jobs => 100 + +Number of jobs in C<finished> state. + +=item inactive_jobs + + inactive_jobs => 100 + +Number of jobs in C<inactive> state. + +=item inactive_workers + + inactive_workers => 100 + +Number of workers that are currently not processing a job. + +=back + =head2 unregister_worker $backend->unregister_worker($worker_id); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Minion-3.03/lib/Minion/Job.pm new/Minion-4.0/lib/Minion/Job.pm --- old/Minion-3.03/lib/Minion/Job.pm 2015-10-30 21:35:50.000000000 +0100 +++ new/Minion-4.0/lib/Minion/Job.pm 2015-11-09 13:24:10.000000000 +0100 @@ -4,20 +4,15 @@ use Mojo::IOLoop; use POSIX 'WNOHANG'; -has [qw(args attempts id minion retries task)]; +has [qw(args id minion retries task)]; sub app { shift->minion->app } sub fail { my $self = shift; - my $err = shift // 'Unknown error'; - - return undef - unless $self->minion->backend->fail_job($self->id, $self->retries, $err); - - return 1 if (my $attempts = $self->emit(failed => $err)->attempts) == 1; - return 1 if (my $retries = $self->retries) >= ($attempts - 1); - return $self->retry({delay => $self->minion->backoff->($retries)}); + my $err = shift // 'Unknown error'; + my $ok = $self->minion->backend->fail_job($self->id, $self->retries, $err); + return $ok ? !!$self->emit(failed => $err) : undef; } sub finish { @@ -149,13 +144,6 @@ Arguments passed to task. -=head2 attempts - - my $attempts = $job->attempts; - $job = $job->attempts(25); - -Number of times performing this job will be attempted. - =head2 id my $id = $job->id; @@ -204,9 +192,9 @@ my $bool = $job->fail('Something went wrong!'); my $bool = $job->fail({whatever => 'Something went wrong!'}); -Transition from C<active> to C<failed> state, and if there are L</"attempts"> -remaining, transition back to C<inactive> with an exponentially increasing -delay based on L<Minion/"backoff">. +Transition from C<active> to C<failed> state, and if there are attempts +remaining, transition back to C<inactive> with a delay based on +L<Minion/"backoff">. =head2 finish diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Minion-3.03/lib/Minion/Worker.pm new/Minion-4.0/lib/Minion/Worker.pm --- old/Minion-3.03/lib/Minion/Worker.pm 2015-10-30 21:35:50.000000000 +0100 +++ new/Minion-4.0/lib/Minion/Worker.pm 2015-11-09 01:07:10.000000000 +0100 @@ -12,12 +12,11 @@ my $minion = $self->minion; return undef unless my $job = $minion->backend->dequeue($id, $wait, $options); $job = Minion::Job->new( - args => $job->{args}, - attempts => $job->{attempts}, - id => $job->{id}, - minion => $minion, - retries => $job->{retries}, - task => $job->{task} + args => $job->{args}, + id => $job->{id}, + minion => $minion, + retries => $job->{retries}, + task => $job->{task} ); $self->emit(dequeue => $job); return $job; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Minion-3.03/lib/Minion.pm new/Minion-4.0/lib/Minion.pm --- old/Minion-3.03/lib/Minion.pm 2015-11-08 10:43:36.000000000 +0100 +++ new/Minion-4.0/lib/Minion.pm 2015-11-09 16:21:05.000000000 +0100 @@ -16,7 +16,7 @@ has remove_after => 864000; has tasks => sub { {} }; -our $VERSION = '3.03'; +our $VERSION = '4.0'; sub add_task { ($_[0]->tasks->{$_[1]} = $_[2]) and return $_[0] } @@ -27,12 +27,11 @@ return undef unless my $job = $self->backend->job_info($id); return Minion::Job->new( - args => $job->{args}, - attempts => $job->{attempts}, - id => $job->{id}, - minion => $self, - retries => $job->{retries}, - task => $job->{task} + args => $job->{args}, + id => $job->{id}, + minion => $self, + retries => $job->{retries}, + task => $job->{task} ); } @@ -234,7 +233,8 @@ $minion = $minion->backoff(sub {...}); A callback used to calculate the delay for automatically retried jobs, defaults -to C<(retries ** 4) + 15> (15, 16, 31, 96...). +to C<(retries ** 4) + 15> (15, 16, 31, 96, 271, 640...), which means that +roughly C<25> attempts can be made in C<21> days. $minion->backoff(sub { my $retries = shift; @@ -304,7 +304,8 @@ attempts => 25 -Number of times performing this job will be attempted, defaults to C<1>. +Number of times performing this job will be attempted, with a delay based on +L</"backoff"> after the first attempt, defaults to C<1>. =item delay @@ -382,6 +383,51 @@ Get statistics for jobs and workers. + # Check idle workers + my $idle = $minion->stats->{inactive_workers}; + +These fields are currently available: + +=over 2 + +=item active_jobs + + active_jobs => 100 + +Number of jobs in C<active> state. + +=item active_workers + + active_workers => 100 + +Number of workers that are currently processing a job. + +=item failed_jobs + + failed_jobs => 100 + +Number of jobs in C<failed> state. + +=item finished_jobs + + finished_jobs => 100 + +Number of jobs in C<finished> state. + +=item inactive_jobs + + inactive_jobs => 100 + +Number of jobs in C<inactive> state. + +=item inactive_workers + + inactive_workers => 100 + +Number of workers that are currently not processing a job. + +=back + =head2 worker my $worker = $minion->worker; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Minion-3.03/t/pg.t new/Minion-4.0/t/pg.t --- old/Minion-3.03/t/pg.t 2015-10-30 21:35:50.000000000 +0100 +++ new/Minion-4.0/t/pg.t 2015-11-09 13:30:50.000000000 +0100 @@ -275,9 +275,6 @@ ok $job->fail, 'job failed'; ok $job->retry, 'job retried'; is $job->info->{retries}, 2, 'job has been retried twice'; -ok !$job->info->{finished}, 'no finished timestamp'; -ok !$job->info->{started}, 'no started timestamp'; -ok !$job->info->{worker}, 'no worker'; $job = $worker->dequeue(0); is $job->info->{state}, 'active', 'right state'; ok $job->finish, 'job finished'; @@ -460,7 +457,7 @@ is $job->info->{result}, 'Non-zero exit status (1)', 'right result'; $worker->unregister; -# Multiple attempts +# Multiple attempts while processing is $minion->backoff->(0), 15, 'right result'; is $minion->backoff->(1), 16, 'right result'; is $minion->backoff->(2), 31, 'right result'; @@ -471,8 +468,7 @@ $id = $minion->enqueue(exit => [] => {attempts => 2}); $job = $worker->register->dequeue(0); is $job->id, $id, 'right id'; -is $job->retries, 0, 'job has not been retried'; -is $job->attempts, 2, 'job will be attempted twice'; +is $job->retries, 0, 'job has not been retried'; $job->perform; is $job->info->{attempts}, 2, 'job will be attempted twice'; is $job->info->{state}, 'inactive', 'right state'; @@ -482,14 +478,35 @@ 'update minion_jobs set delayed = now() where id = ?', $id); $job = $worker->register->dequeue(0); is $job->id, $id, 'right id'; -is $job->retries, 1, 'job has been retried once'; -is $job->attempts, 2, 'job will be attempted twice'; +is $job->retries, 1, 'job has been retried once'; $job->perform; is $job->info->{attempts}, 2, 'job will be attempted twice'; is $job->info->{state}, 'failed', 'right state'; is $job->info->{result}, 'Non-zero exit status (1)', 'right result'; $worker->unregister; +# Multiple attempts during maintenance +$id = $minion->enqueue(exit => [] => {attempts => 2}); +$job = $worker->register->dequeue(0); +is $job->id, $id, 'right id'; +is $job->retries, 0, 'job has not been retried'; +is $job->info->{attempts}, 2, 'job will be attempted twice'; +is $job->info->{state}, 'active', 'right state'; +$worker->unregister; +$minion->repair; +is $job->info->{state}, 'inactive', 'right state'; +is $job->info->{result}, 'Worker went away', 'right result'; +ok $job->info->{retried} < $job->info->{delayed}, 'delayed timestamp'; +$minion->backend->pg->db->query( + 'update minion_jobs set delayed = now() where id = ?', $id); +$job = $worker->register->dequeue(0); +is $job->id, $id, 'right id'; +is $job->retries, 1, 'job has been retried once'; +$worker->unregister; +$minion->repair; +is $job->info->{state}, 'failed', 'right state'; +is $job->info->{result}, 'Worker went away', 'right result'; + # A job needs to be dequeued again after a retry $minion->add_task(restart => sub { }); $id = $minion->enqueue('restart');