Hello community, here is the log from the commit of package perl-Minion for openSUSE:Factory checked in at 2020-08-04 20:19:06 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/perl-Minion (Old) and /work/SRC/openSUSE:Factory/.perl-Minion.new.3592 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "perl-Minion" Tue Aug 4 20:19:06 2020 rev:61 rq:824126 version:10.13 Changes: -------- --- /work/SRC/openSUSE:Factory/perl-Minion/perl-Minion.changes 2020-07-28 17:29:56.914218575 +0200 +++ /work/SRC/openSUSE:Factory/.perl-Minion.new.3592/perl-Minion.changes 2020-08-04 20:19:38.308963324 +0200 @@ -1,0 +2,18 @@ +Sat Aug 1 03:19:19 UTC 2020 - Tina Müller <timueller+p...@suse.de> + +- updated to 10.13 + see /usr/share/doc/packages/perl-Minion/Changes + + 10.13 2020-07-30 + - Added EXPERIMENTAL support for lax dependencies. + - Added EXPERIMENTAL lax option to enqueue method in Minion, Minion::Backend and Minion::Backend::Pg. + - Removed experimental status from notes option in Minion::Backend and Minion::Backend::Pg. + - Added lax field to list_jobs method in Minion::Backend::Pg. + - Added is_locked method to Minion. + - Added auto_retry_job method to Minion::Backend. + - Added parents method to Minion::Job. + - Added -x option to job command. + - Fixed a bug in Minion::Backend::Pg where manual retries would count towards the attempts limit for automatic + retries. + +------------------------------------------------------------------- Old: ---- Minion-10.12.tar.gz New: ---- Minion-10.13.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ perl-Minion.spec ++++++ --- /var/tmp/diff_new_pack.8Tk88Z/_old 2020-08-04 20:19:40.052963776 +0200 +++ /var/tmp/diff_new_pack.8Tk88Z/_new 2020-08-04 20:19:40.052963776 +0200 @@ -17,7 +17,7 @@ Name: perl-Minion -Version: 10.12 +Version: 10.13 Release: 0 %define cpan_name Minion Summary: Job queue ++++++ Minion-10.12.tar.gz -> Minion-10.13.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Minion-10.12/Changes new/Minion-10.13/Changes --- old/Minion-10.12/Changes 2020-07-25 18:38:19.000000000 +0200 +++ new/Minion-10.13/Changes 2020-07-31 19:54:27.000000000 +0200 @@ -1,4 +1,16 @@ +10.13 2020-07-30 + - Added EXPERIMENTAL support for lax dependencies. + - Added EXPERIMENTAL lax option to enqueue method in Minion, Minion::Backend and Minion::Backend::Pg. + - Removed experimental status from notes option in Minion::Backend and Minion::Backend::Pg. + - Added lax field to list_jobs method in Minion::Backend::Pg. + - Added is_locked method to Minion. + - Added auto_retry_job method to Minion::Backend. + - Added parents method to Minion::Job. + - Added -x option to job command. + - Fixed a bug in Minion::Backend::Pg where manual retries would count towards the attempts limit for automatic + retries. + 10.12 2020-07-25 - Added EXPERIMENTAL support for expiring jobs. - Removed experimental support for job sequences again since use cases turned out to be weaker than expected. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Minion-10.12/META.json new/Minion-10.13/META.json --- old/Minion-10.12/META.json 2020-07-26 16:29:26.000000000 +0200 +++ new/Minion-10.13/META.json 2020-07-31 20:20:55.000000000 +0200 @@ -57,6 +57,6 @@ "web" : "https://webchat.freenode.net/#mojo" } }, - "version" : "10.12", + "version" : "10.13", "x_serialization_backend" : "JSON::PP version 4.05" } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Minion-10.12/META.yml new/Minion-10.13/META.yml --- old/Minion-10.12/META.yml 2020-07-26 16:29:26.000000000 +0200 +++ new/Minion-10.13/META.yml 2020-07-31 20:20:55.000000000 +0200 @@ -29,5 +29,5 @@ homepage: https://mojolicious.org license: http://www.opensource.org/licenses/artistic-license-2.0 repository: https://github.com/mojolicious/minion.git -version: '10.12' +version: '10.13' x_serialization_backend: 'CPAN::Meta::YAML version 0.018' diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Minion-10.12/lib/Minion/Backend/Pg.pm new/Minion-10.13/lib/Minion/Backend/Pg.pm --- old/Minion-10.12/lib/Minion/Backend/Pg.pm 2020-07-26 15:27:18.000000000 +0200 +++ new/Minion-10.13/lib/Minion/Backend/Pg.pm 2020-07-31 00:50:57.000000000 +0200 @@ -36,11 +36,11 @@ my ($self, $task, $args, $options) = (shift, shift, shift || [], shift || {}); return $self->pg->db->query( - q{insert into minion_jobs (args, attempts, delayed, expires, notes, parents, priority, queue, task) + q{insert into minion_jobs (args, attempts, delayed, expires, lax, notes, parents, priority, queue, task) values ($1, $2, (now() + (interval '1 second' * $3)), - case when $4::bigint is not null then now() + (interval '1 second' * $4::bigint) end, $5, $6, $7, $8, $9) + case when $4::bigint is not null then now() + (interval '1 second' * $4::bigint) end, $5, $6, $7, $8, $9, $10) returning id}, {json => $args}, $options->{attempts} // 1, $options->{delay} // 0, $options->{expire}, - {json => $options->{notes} || {}}, $options->{parents} || [], $options->{priority} // 0, + $options->{lax} ? 1 : 0, {json => $options->{notes} || {}}, $options->{parents} || [], $options->{priority} // 0, $options->{queue} // 'default', $task )->hash->{id}; } @@ -78,7 +78,7 @@ q{select id, args, attempts, array(select id from minion_jobs where parents @> ARRAY[j.id]) as children, extract(epoch from created) as created, extract(epoch from delayed) as delayed, - extract(epoch from finished) as finished, notes, parents, priority, queue, result, + extract(epoch from finished) as finished, lax, notes, parents, priority, queue, result, extract(epoch from retried) as retried, retries, extract(epoch from started) as started, state, task, extract(epoch from now()) as time, count(*) over() as total, extract(epoch from expires) as expires, worker from minion_jobs as j @@ -213,11 +213,11 @@ return !!$self->pg->db->query( q{update minion_jobs set attempts = coalesce($1, attempts), delayed = (now() + (interval '1 second' * $2)), expires = case when $3::bigint is not null then now() + (interval '1 second' * $3::bigint) else expires end, - parents = coalesce($4, parents), priority = coalesce($5, priority), queue = coalesce($6, queue), - retried = now(), retries = retries + 1, state = 'inactive' - where id = $7 and retries = $8 - returning 1}, $options->{attempts}, $options->{delay} // 0, @$options{qw(expire parents priority queue)}, $id, - $retries + lax = coalesce($4, lax), parents = coalesce($5, parents), priority = coalesce($6, priority), + queue = coalesce($7, queue), retried = now(), retries = retries + 1, state = 'inactive' + where id = $8 and retries = $9 + returning 1}, $options->{attempts}, $options->{delay} // 0, $options->{expire}, + exists $options->{lax} ? $options->{lax} ? 1 : 0 : undef, @$options{qw(parents priority queue)}, $id, $retries )->rows; } @@ -262,18 +262,19 @@ my ($self, $id, $options) = @_; return $self->pg->db->query( - "update minion_jobs set started = now(), state = 'active', worker = ? - where id = ( - select id from minion_jobs as j - where delayed <= now() and id = coalesce(?, id) and (parents = '{}' or not exists ( - select 1 from minion_jobs where id = any (j.parents) - and (state in ('active', 'failed') or (state = 'inactive' and (expires is null or expires > now()))) - )) and queue = any (?) and state = 'inactive' and task = any (?) and (expires is null or expires > now()) - order by priority desc, id - limit 1 - for update skip locked - ) - returning id, args, retries, task", $id, $options->{id}, $options->{queues} || ['default'], + q{update minion_jobs set started = now(), state = 'active', worker = ? + where id = ( + select id from minion_jobs as j + where delayed <= now() and id = coalesce(?, id) and (parents = '{}' or not exists ( + select 1 from minion_jobs where id = any (j.parents) and ( + state = 'active' or (state = 'failed' and not j.lax) + or (state = 'inactive' and (expires is null or expires > now()))) + )) and queue = any (?) and state = 'inactive' and task = any (?) and (expires is null or expires > now()) + order by priority desc, id + limit 1 + for update skip locked + ) + returning id, args, retries, task}, $id, $options->{id}, $options->{queues} || ['default'], [keys %{$self->minion->tasks}] )->expand->hash; } @@ -287,10 +288,7 @@ 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}); + return $fail ? $self->auto_retry_job($id, $retries, $row->[0]) : 1; } 1; @@ -424,6 +422,13 @@ Job is valid for this many seconds (from now) before it expires. Note that this option is B<EXPERIMENTAL> and might change without warning! +=item lax + + lax => 1 + +Existing jobs this job depends on may also have transitioned to the C<failed> state to allow for it to be processed, +defaults to C<false>. Note that this option is B<EXPERIMENTAL> and might change without warning! + =item notes notes => {foo => 'bar', baz => [1, 2, 3]} @@ -526,7 +531,7 @@ notes => ['foo', 'bar'] -List only jobs with one of these notes. Note that this option is B<EXPERIMENTAL> and might change without warning! +List only jobs with one of these notes. =item queues @@ -600,6 +605,12 @@ Job id. +=item lax + + lax => 0 + +Existing jobs this job depends on may also have failed to allow for it to be processed. + =item notes notes => {foo => 'bar', baz => [1, 2, 3]} @@ -924,6 +935,13 @@ Job is valid for this many seconds (from now) before it expires. Note that this option is B<EXPERIMENTAL> and might change without warning! +=item lax + + lax => 1 + +Existing jobs this job depends on may also have transitioned to the C<failed> state to allow for it to be processed, +defaults to C<false>. Note that this option is B<EXPERIMENTAL> and might change without warning! + =item parents parents => [$id1, $id2, $id3] @@ -1030,6 +1048,6 @@ =head1 SEE ALSO -L<Minion>, L<Mojolicious::Guides>, L<https://mojolicious.org>. +L<Minion>, L<https://minion.pm>, L<Mojolicious::Guides>, L<https://mojolicious.org>. =cut diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Minion-10.12/lib/Minion/Backend/resources/migrations/pg.sql new/Minion-10.13/lib/Minion/Backend/resources/migrations/pg.sql --- old/Minion-10.12/lib/Minion/Backend/resources/migrations/pg.sql 2020-07-25 18:33:31.000000000 +0200 +++ new/Minion-10.13/lib/Minion/Backend/resources/migrations/pg.sql 2020-07-30 20:42:14.000000000 +0200 @@ -89,3 +89,6 @@ alter table minion_jobs drop column if exists next; alter table minion_jobs add column expires timestamp with time zone; create index on minion_jobs (expires); + +-- 23 up +alter table minion_jobs add column lax bool not null default false; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Minion-10.12/lib/Minion/Backend.pm new/Minion-10.13/lib/Minion/Backend.pm --- old/Minion-10.12/lib/Minion/Backend.pm 2020-07-26 15:27:18.000000000 +0200 +++ new/Minion-10.13/lib/Minion/Backend.pm 2020-07-31 00:50:54.000000000 +0200 @@ -5,6 +5,13 @@ has minion => undef, weak => 1; +sub auto_retry_job { + my ($self, $id, $retries, $attempts) = @_; + return 1 if $attempts <= 1; + my $delay = $self->minion->backoff->($retries); + return $self->retry_job($id, $retries, {attempts => $attempts > 1 ? $attempts - 1 : 1, delay => $delay}); +} + sub broadcast { croak 'Method "broadcast" not implemented by subclass' } sub dequeue { croak 'Method "dequeue" not implemented by subclass' } sub enqueue { croak 'Method "enqueue" not implemented by subclass' } @@ -79,6 +86,13 @@ L<Minion::Backend> inherits all methods from L<Mojo::Base> and implements the following new ones. +=head2 auto_retry_job + + my $bool = $backend->auto_retry_job($job_id, $retries, $attempts); + +Automatically L</"retry"> job with L<Minion/"backoff"> if there are attempts left, used to implement backends like +L<Minion::Backend::Pg>. + =head2 broadcast my $bool = $backend->broadcast('some_command'); @@ -175,6 +189,13 @@ Job is valid for this many seconds (from now) before it expires. Note that this option is B<EXPERIMENTAL> and might change without warning! +=item lax + + lax => 1 + +Existing jobs this job depends on may also have transitioned to the C<failed> state to allow for it to be processed, +defaults to C<false>. Note that this option is B<EXPERIMENTAL> and might change without warning! + =item notes notes => {foo => 'bar', baz => [1, 2, 3]} @@ -277,7 +298,7 @@ notes => ['foo', 'bar'] -List only jobs with one of these notes. Note that this option is B<EXPERIMENTAL> and might change without warning! +List only jobs with one of these notes. =item queues @@ -351,6 +372,12 @@ Job id. +=item lax + + lax => 0 + +Existing jobs this job depends on may also have failed to allow for it to be processed. + =item notes notes => {foo => 'bar', baz => [1, 2, 3]} @@ -671,6 +698,13 @@ Job is valid for this many seconds (from now) before it expires. Note that this option is B<EXPERIMENTAL> and might change without warning! +=item lax + + lax => 1 + +Existing jobs this job depends on may also have transitioned to the C<failed> state to allow for it to be processed, +defaults to C<false>. Note that this option is B<EXPERIMENTAL> and might change without warning! + =item parents parents => [$id1, $id2, $id3] @@ -778,6 +812,6 @@ =head1 SEE ALSO -L<Minion>, L<Mojolicious::Guides>, L<https://mojolicious.org>. +L<Minion>, L<https://minion.pm>, L<Mojolicious::Guides>, L<https://mojolicious.org>. =cut diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Minion-10.12/lib/Minion/Command/minion/job.pm new/Minion-10.13/lib/Minion/Command/minion/job.pm --- old/Minion-10.12/lib/Minion/Command/minion/job.pm 2020-07-25 18:33:52.000000000 +0200 +++ new/Minion-10.13/lib/Minion/Command/minion/job.pm 2020-07-30 23:22:33.000000000 +0200 @@ -34,7 +34,8 @@ 'T|tasks' => \my $tasks, 't|task=s' => sub { push @{$options->{tasks}}, $_[1] }, 'U|unlock=s' => \my $unlock, - 'w|workers' => \my $workers; + 'w|workers' => \my $workers, + 'x|lax=s' => \$options->{lax}; # Worker remote control command my $minion = $self->app->minion; @@ -123,7 +124,7 @@ ./myapp.pl minion job -q important -t foo -t bar -S inactive ./myapp.pl minion job -Q 'host:localhost' -S inactive ./myapp.pl minion job -e foo -a '[23, "bar"]' - ./myapp.pl minion job -e foo -P 10023 -P 10024 -p 5 -q important + ./myapp.pl minion job -e foo -x 1 -P 10023 -P 10024 -p 5 -q important ./myapp.pl minion job -e 'foo' -n '{"test":123}' ./myapp.pl minion job -R -d 10 -E 300 10023 ./myapp.pl minion job --remove 10023 @@ -175,6 +176,8 @@ -U, --unlock <name> Release named lock -w, --workers List workers instead of jobs, or show information for a specific worker + -x, --lax <bool> Jobs this job depends on may also have failed + to allow for it to be processed =head1 DESCRIPTION @@ -212,6 +215,6 @@ =head1 SEE ALSO -L<Minion>, L<Mojolicious::Guides>, L<https://mojolicious.org>. +L<Minion>, L<https://minion.pm>, L<Mojolicious::Guides>, L<https://mojolicious.org>. =cut diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Minion-10.12/lib/Minion/Command/minion/worker.pm new/Minion-10.13/lib/Minion/Command/minion/worker.pm --- old/Minion-10.12/lib/Minion/Command/minion/worker.pm 2020-06-19 22:08:37.000000000 +0200 +++ new/Minion-10.13/lib/Minion/Command/minion/worker.pm 2020-07-29 17:50:25.000000000 +0200 @@ -164,6 +164,6 @@ =head1 SEE ALSO -L<Minion>, L<Mojolicious::Guides>, L<https://mojolicious.org>. +L<Minion>, L<https://minion.pm>, L<Mojolicious::Guides>, L<https://mojolicious.org>. =cut diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Minion-10.12/lib/Minion/Command/minion.pm new/Minion-10.13/lib/Minion/Command/minion.pm --- old/Minion-10.12/lib/Minion/Command/minion.pm 2020-06-19 22:08:37.000000000 +0200 +++ new/Minion-10.13/lib/Minion/Command/minion.pm 2020-07-29 17:50:30.000000000 +0200 @@ -72,6 +72,6 @@ =head1 SEE ALSO -L<Minion>, L<Mojolicious::Guides>, L<https://mojolicious.org>. +L<Minion>, L<https://minion.pm>, L<Mojolicious::Guides>, L<https://mojolicious.org>. =cut diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Minion-10.12/lib/Minion/Iterator.pm new/Minion-10.13/lib/Minion/Iterator.pm --- old/Minion-10.12/lib/Minion/Iterator.pm 2020-06-19 22:08:37.000000000 +0200 +++ new/Minion-10.13/lib/Minion/Iterator.pm 2020-07-29 17:50:53.000000000 +0200 @@ -88,6 +88,6 @@ =head1 SEE ALSO -L<Minion>, L<Mojolicious::Guides>, L<https://mojolicious.org>. +L<Minion>, L<https://minion.pm>, L<Mojolicious::Guides>, L<https://mojolicious.org>. =cut diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Minion-10.12/lib/Minion/Job.pm new/Minion-10.13/lib/Minion/Job.pm --- old/Minion-10.12/lib/Minion/Job.pm 2020-07-25 18:16:27.000000000 +0200 +++ new/Minion-10.13/lib/Minion/Job.pm 2020-07-31 20:16:03.000000000 +0200 @@ -2,6 +2,7 @@ use Mojo::Base 'Mojo::EventEmitter'; use Carp qw(croak); +use Mojo::Collection; use Mojo::IOLoop; use POSIX qw(WNOHANG); @@ -30,7 +31,7 @@ return $ok ? !!$self->emit(finished => $result) : undef; } -sub info { $_[0]->minion->backend->list_jobs(0, 1, {ids => [$_[0]->id]})->{jobs}[0]; } +sub info { $_[0]->minion->backend->list_jobs(0, 1, {ids => [$_[0]->id]})->{jobs}[0] } sub is_finished { my $self = shift; @@ -46,6 +47,12 @@ return $self->minion->backend->note($self->id, {@_}); } +sub parents { + my $self = shift; + my $minion = $self->minion; + return Mojo::Collection->new(map { $minion->job($_) // () } @{($self->info || {})->{parents} || []}); +} + sub perform { my $self = shift; waitpid $self->start->pid, 0; @@ -362,6 +369,12 @@ Epoch time job was finished. +=item lax + + lax => 0 + +Existing jobs this job depends on may also have failed to allow for it to be processed. + =item notes notes => {foo => 'bar', baz => [1, 2, 3]} @@ -463,6 +476,18 @@ # Share stats $job->note(stats => {utime => '0.012628', stime => '0.002429'}); +=head2 parents + + my $parents = $job->parents; + +Return a L<Mojo::Collection> object containing all jobs this job depends on as L<Minion::Job> objects. + + # Check parent state + for my $parent ($job->parents->each) { + my $info = $parent->info; + say "$info->{id}: $info->{state}"; + } + =head2 perform $job->perform; @@ -513,6 +538,13 @@ Job is valid for this many seconds (from now) before it expires. Note that this option is B<EXPERIMENTAL> and might change without warning! +=item lax + + lax => 1 + +Existing jobs this job depends on may also have transitioned to the C<failed> state to allow for it to be processed, +defaults to C<false>. Note that this option is B<EXPERIMENTAL> and might change without warning! + =item parents parents => [$id1, $id2, $id3] @@ -562,6 +594,6 @@ =head1 SEE ALSO -L<Minion>, L<Mojolicious::Guides>, L<https://mojolicious.org>. +L<Minion>, L<https://minion.pm>, L<Mojolicious::Guides>, L<https://mojolicious.org>. =cut diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Minion-10.12/lib/Minion/Worker.pm new/Minion-10.13/lib/Minion/Worker.pm --- old/Minion-10.12/lib/Minion/Worker.pm 2020-06-19 22:08:36.000000000 +0200 +++ new/Minion-10.13/lib/Minion/Worker.pm 2020-07-29 17:51:09.000000000 +0200 @@ -450,6 +450,6 @@ =head1 SEE ALSO -L<Minion>, L<Mojolicious::Guides>, L<https://mojolicious.org>. +L<Minion>, L<https://minion.pm>, L<Mojolicious::Guides>, L<https://mojolicious.org>. =cut diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Minion-10.12/lib/Minion.pm new/Minion-10.13/lib/Minion.pm --- old/Minion-10.12/lib/Minion.pm 2020-07-26 15:18:46.000000000 +0200 +++ new/Minion-10.13/lib/Minion.pm 2020-07-30 23:01:42.000000000 +0200 @@ -20,7 +20,7 @@ has [qw(remove_after stuck_after)] => 172800; has tasks => sub { {} }; -our $VERSION = '10.12'; +our $VERSION = '10.13'; sub add_task { my ($self, $name, $task) = @_; @@ -78,6 +78,8 @@ sub history { shift->backend->history } +sub is_locked { !shift->lock(shift, 0) } + sub job { my ($self, $id) = @_; @@ -524,6 +526,13 @@ Job is valid for this many seconds (from now) before it expires. Note that this option is B<EXPERIMENTAL> and might change without warning! +=item lax + + lax => 1 + +Existing jobs this job depends on may also have transitioned to the C<failed> state to allow for it to be processed, +defaults to C<false>. Note that this option is B<EXPERIMENTAL> and might change without warning! + =item notes notes => {foo => 'bar', baz => [1, 2, 3]} @@ -602,6 +611,12 @@ =back +=head2 is_locked + + my $bool = $minion->is_locked('foo'); + +Check if a lock with that name is currently active. + =head2 job my $job = $minion->job($id); @@ -653,7 +668,7 @@ notes => ['foo', 'bar'] -List only jobs with one of these notes. Note that this option is B<EXPERIMENTAL> and might change without warning! +List only jobs with one of these notes. =item queues @@ -727,6 +742,12 @@ Job id. +=item lax + + lax => 0 + +Existing jobs this job depends on may also have failed to allow for it to be processed. + =item notes notes => {foo => 'bar', baz => [1, 2, 3]} @@ -835,10 +856,12 @@ ... }); -An expiration time of C<0> can be used to check if a named lock already exists without creating one. +An expiration time of C<0> can be used to check if a named lock could have been acquired without creating one. + + # Check if the lock "foo" could have been acquired + say 'Lock could have been acquired' unless $minion->lock('foo', 0); - # Check if the lock "foo" already exists - say 'Lock exists' unless $minion->lock('foo', 0); +Or to simply check if a named lock already exists you can also use L</"is_locked">. These options are currently available: @@ -1256,6 +1279,6 @@ =head1 SEE ALSO -L<https://github.com/mojolicious/minion>, L<Mojolicious::Guides>, L<https://mojolicious.org>. +L<https://github.com/mojolicious/minion>, L<https://minion.pm>, L<Mojolicious::Guides>, L<https://mojolicious.org>. =cut diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Minion-10.12/lib/Mojolicious/Plugin/Minion/Admin.pm new/Minion-10.13/lib/Mojolicious/Plugin/Minion/Admin.pm --- old/Minion-10.12/lib/Mojolicious/Plugin/Minion/Admin.pm 2020-07-25 18:34:19.000000000 +0200 +++ new/Minion-10.13/lib/Mojolicious/Plugin/Minion/Admin.pm 2020-07-29 17:51:27.000000000 +0200 @@ -218,6 +218,6 @@ =head1 SEE ALSO -L<Minion>, L<Mojolicious::Guides>, L<https://mojolicious.org>. +L<Minion>, L<https://minion.pm>, L<Mojolicious::Guides>, L<https://mojolicious.org>. =cut diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Minion-10.12/lib/Mojolicious/Plugin/Minion.pm new/Minion-10.13/lib/Mojolicious/Plugin/Minion.pm --- old/Minion-10.12/lib/Mojolicious/Plugin/Minion.pm 2020-06-19 22:08:38.000000000 +0200 +++ new/Minion-10.13/lib/Mojolicious/Plugin/Minion.pm 2020-07-29 17:51:20.000000000 +0200 @@ -78,6 +78,6 @@ =head1 SEE ALSO -L<Minion>, L<Mojolicious::Guides>, L<https://mojolicious.org>. +L<Minion>, L<https://minion.pm>, L<Mojolicious::Guides>, L<https://mojolicious.org>. =cut diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Minion-10.12/t/pg.t new/Minion-10.13/t/pg.t --- old/Minion-10.12/t/pg.t 2020-07-25 19:24:14.000000000 +0200 +++ new/Minion-10.13/t/pg.t 2020-07-31 20:16:10.000000000 +0200 @@ -28,9 +28,9 @@ }; subtest 'Migrate up and down' => sub { - is $minion->backend->pg->migrations->active, 22, 'active version is 22'; + is $minion->backend->pg->migrations->active, 23, 'active version is 23'; is $minion->backend->pg->migrations->migrate(0)->active, 0, 'active version is 0'; - is $minion->backend->pg->migrations->migrate->active, 22, 'active version is 22'; + is $minion->backend->pg->migrations->migrate->active, 23, 'active version is 23'; }; subtest 'Register and unregister' => sub { @@ -283,7 +283,9 @@ ok !$minion->unlock('foo'), 'not unlocked again'; ok $minion->lock('foo', -3600), 'locked'; ok $minion->lock('foo', 0), 'locked again'; - ok $minion->lock('foo', 3600), 'locked again'; + ok !$minion->is_locked('foo'), 'lock does not exist'; + ok $minion->lock('foo', 3600), 'locked again'; + ok $minion->is_locked('foo'), 'lock exists'; ok !$minion->lock('foo', -3600), 'not locked again'; ok !$minion->lock('foo', 3600), 'not locked again'; ok $minion->unlock('foo'), 'unlocked'; @@ -293,8 +295,9 @@ }; subtest 'Shared lock' => sub { - ok $minion->lock('bar', 3600, {limit => 3}), 'locked'; - ok $minion->lock('bar', 3600, {limit => 3}), 'locked again'; + ok $minion->lock('bar', 3600, {limit => 3}), 'locked'; + ok $minion->lock('bar', 3600, {limit => 3}), 'locked again'; + ok $minion->is_locked('bar'), 'lock exists'; ok $minion->lock('bar', -3600, {limit => 3}), 'locked again'; ok $minion->lock('bar', 3600, {limit => 3}), 'locked again'; ok !$minion->lock('bar', 3600, {limit => 2}), 'not locked again'; @@ -304,7 +307,8 @@ ok $minion->unlock('bar'), 'unlocked again'; ok $minion->unlock('bar'), 'unlocked again'; ok $minion->unlock('bar'), 'unlocked again'; - ok !$minion->unlock('bar'), 'not unlocked again'; + ok !$minion->unlock('bar'), 'not unlocked again'; + ok !$minion->is_locked('bar'), 'lock does not exist'; ok $minion->unlock('baz'), 'unlocked'; ok !$minion->unlock('baz'), 'not unlocked again'; }; @@ -901,34 +905,57 @@ is $minion->backoff->(4), 271, 'right result'; is $minion->backoff->(5), 640, 'right result'; is $minion->backoff->(25), 390640, 'right result'; - my $id = $minion->enqueue(exit => [] => {attempts => 2}); + + my $id = $minion->enqueue(exit => [] => {attempts => 3}); my $worker = $minion->worker->register; ok my $job = $worker->dequeue(0), 'job dequeued'; is $job->id, $id, 'right id'; is $job->retries, 0, 'job has not been retried'; - $job->perform; my $info = $job->info; - is $info->{attempts}, 2, 'job will be attempted twice'; + is $info->{attempts}, 3, 'three attempts'; + is $info->{state}, 'active', 'right state'; + $job->perform; + $info = $job->info; + is $info->{attempts}, 2, 'two attempts'; is $info->{state}, 'inactive', 'right state'; is $info->{result}, 'Job terminated unexpectedly (exit code: 1, signal: 0)', 'right result'; ok $info->{retried} < $job->info->{delayed}, 'delayed timestamp'; + $minion->backend->pg->db->query('update minion_jobs set delayed = now() where id = ?', $id); - ok $job = $worker->register->dequeue(0), 'job dequeued'; + ok $job = $worker->dequeue(0), 'job dequeued'; is $job->id, $id, 'right id'; - is $job->retries, 1, 'job has been retried once'; + is $job->retries, 1, 'job has been retried'; + $info = $job->info; + is $info->{attempts}, 2, 'two attempts'; + is $info->{state}, 'active', 'right state'; $job->perform; $info = $job->info; - is $info->{attempts}, 2, 'job will be attempted twice'; - is $info->{state}, 'failed', 'right state'; - is $info->{result}, 'Job terminated unexpectedly (exit code: 1, signal: 0)', 'right result'; - ok $job->retry({attempts => 3}), 'job retried'; + is $info->{attempts}, 1, 'one attempt'; + is $info->{state}, 'inactive', 'right state'; + + $minion->backend->pg->db->query('update minion_jobs set delayed = now() where id = ?', $id); ok $job = $worker->register->dequeue(0), 'job dequeued'; is $job->id, $id, 'right id'; + is $job->retries, 2, 'two retries'; + $info = $job->info; + is $info->{attempts}, 1, 'one attempt'; + is $info->{state}, 'active', 'right state'; $job->perform; $info = $job->info; - is $info->{attempts}, 3, 'job will be attempted three times'; + is $info->{attempts}, 1, 'one attempt'; is $info->{state}, 'failed', 'right state'; is $info->{result}, 'Job terminated unexpectedly (exit code: 1, signal: 0)', 'right result'; + + ok $job->retry({attempts => 2}), 'job retried'; + ok $job = $worker->register->dequeue(0), 'job dequeued'; + is $job->id, $id, 'right id'; + $job->perform; + is $job->info->{state}, 'inactive', 'right state'; + $minion->backend->pg->db->query('update minion_jobs set delayed = now() where id = ?', $id); + ok $job = $worker->register->dequeue(0), 'job dequeued'; + is $job->id, $id, 'right id'; + $job->perform; + is $job->info->{state}, 'failed', 'right state'; $worker->unregister; }; @@ -1083,6 +1110,67 @@ is $job->id, $id, 'right id'; is_deeply $job->info->{parents}, [-1, -2], 'right parents'; ok $job->finish, 'job finished'; + + my $id4 = $minion->enqueue('test'); + my $id5 = $minion->enqueue('test'); + my $id6 = $minion->enqueue(test => [] => {parents => [$id4, $id5]}); + my $child = $minion->job($id6); + my $parents = $child->parents; + is $parents->size, 2, 'two parents'; + is $parents->[0]->id, $id4, 'first parent'; + is $parents->[1]->id, $id5, 'second parent'; + $_->remove for $parents->each; + is $child->parents->size, 0, 'no parents'; + ok $child->remove, 'job removed'; + $worker->unregister; +}; + +subtest 'Job dependencies (lax)' => sub { + my $worker = $minion->worker->register; + my $id = $minion->enqueue('test'); + my $id2 = $minion->enqueue('test'); + my $id3 = $minion->enqueue(test => [] => {lax => 1, parents => [$id, $id2]}); + ok my $job = $worker->dequeue(0), 'job dequeued'; + is $job->id, $id, 'right id'; + is_deeply $job->info->{children}, [$id3], 'right children'; + is_deeply $job->info->{parents}, [], 'right parents'; + ok my $job2 = $worker->dequeue(0), 'job dequeued'; + is $job2->id, $id2, 'right id'; + is_deeply $job2->info->{children}, [$id3], 'right children'; + is_deeply $job2->info->{parents}, [], 'right parents'; + ok !$worker->dequeue(0), 'parents are not ready yet'; + ok $job->finish, 'job finished'; + ok !$worker->dequeue(0), 'parents are not ready yet'; + ok $job2->fail, 'job failed'; + ok my $job3 = $worker->dequeue(0), 'job dequeued'; + is $job3->id, $id3, 'right id'; + is_deeply $job3->info->{children}, [], 'right children'; + is_deeply $job3->info->{parents}, [$id, $id2], 'right parents'; + ok $job3->finish, 'job finished'; + + my $id4 = $minion->enqueue('test'); + my $id5 = $minion->enqueue(test => [] => {parents => [$id4]}); + ok my $job4 = $worker->dequeue(0), 'job dequeued'; + is $job4->id, $id4, 'right id'; + ok !$worker->dequeue(0), 'parents are not ready yet'; + ok $job4->fail, 'job finished'; + ok !$worker->dequeue(0), 'parents are not ready yet'; + ok $minion->job($id5)->retry({lax => 1}), 'job is now lax'; + ok my $job5 = $worker->dequeue(0), 'job dequeued'; + is $job5->id, $id5, 'right id'; + is_deeply $job5->info->{children}, [], 'right children'; + is_deeply $job5->info->{parents}, [$id4], 'right parents'; + ok $job5->finish, 'job finished'; + ok $job4->remove, 'job removed'; + + is $minion->jobs({ids => [$id5]})->next->{lax}, 1, 'lax'; + ok $minion->job($id5)->retry, 'job is still lax'; + is $minion->jobs({ids => [$id5]})->next->{lax}, 1, 'lax'; + ok $minion->job($id5)->retry({lax => 0}), 'job is not lax anymore'; + is $minion->jobs({ids => [$id5]})->next->{lax}, 0, 'not lax'; + ok $minion->job($id5)->retry, 'job is still not lax'; + is $minion->jobs({ids => [$id5]})->next->{lax}, 0, 'not lax'; + ok $minion->job($id5)->remove, 'job removed'; $worker->unregister; };