Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package perl-Minion for openSUSE:Factory 
checked in at 2025-10-07 18:25:59
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/perl-Minion (Old)
 and      /work/SRC/openSUSE:Factory/.perl-Minion.new.11973 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "perl-Minion"

Tue Oct  7 18:25:59 2025 rev:79 rq:1309341 version:11.0.0

Changes:
--------
--- /work/SRC/openSUSE:Factory/perl-Minion/perl-Minion.changes  2025-01-01 
23:07:51.936355997 +0100
+++ /work/SRC/openSUSE:Factory/.perl-Minion.new.11973/perl-Minion.changes       
2025-10-07 18:26:23.824456284 +0200
@@ -1,0 +2,14 @@
+Thu Aug 28 10:36:53 UTC 2025 - Tina Müller <[email protected]>
+
+- updated to 11.0.0 (11.0)
+   see /usr/share/doc/packages/perl-Minion/Changes
+
+  11.0 2025-08-21
+    - Minion::Backend::Pg now requires PostgreSQL 13.
+    - Removed experimetnal status from lax dependency support.
+    - Added support for task limits.
+    - Added Minion::Util module.
+    - Added spare remote control command, this allows workers to be paused 
again by combining jobs and spare.
+    - Fixed a problem where remote control commands would not immediately 
update the worker status.
+
+-------------------------------------------------------------------

Old:
----
  Minion-10.31.tar.gz

New:
----
  Minion-11.0.tar.gz
  README.md
  _scmsync.obsinfo
  build.specials.obscpio

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ perl-Minion.spec ++++++
--- /var/tmp/diff_new_pack.xXlk0c/_old  2025-10-07 18:26:24.592488652 +0200
+++ /var/tmp/diff_new_pack.xXlk0c/_new  2025-10-07 18:26:24.592488652 +0200
@@ -1,7 +1,7 @@
 #
 # spec file for package perl-Minion
 #
-# Copyright (c) 2024 SUSE LLC
+# Copyright (c) 2025 SUSE LLC and contributors
 #
 # All modifications and additions to the file contributed by third parties
 # remain the property of their copyright owners, unless otherwise agreed
@@ -18,22 +18,26 @@
 
 %define cpan_name Minion
 Name:           perl-Minion
-Version:        10.310.0
+Version:        11.0.0
 Release:        0
-# 10.31 -> normalize -> 10.310.0
-%define cpan_version 10.31
+# 11.0 -> normalize -> 11.0.0
+%define cpan_version 11.0
 License:        Artistic-2.0
 Summary:        Job queue
 URL:            https://metacpan.org/release/%{cpan_name}
 Source0:        
https://cpan.metacpan.org/authors/id/S/SR/SRI/%{cpan_name}-%{cpan_version}.tar.gz
 Source1:        cpanspec.yml
+Source100:      README.md
 BuildArch:      noarch
 BuildRequires:  perl
 BuildRequires:  perl-macros
 BuildRequires:  perl(Mojolicious) >= 9.0
-BuildRequires:  perl(YAML::XS) >= 0.67
+BuildRequires:  perl(YAML::XS) >= 0.670
 Requires:       perl(Mojolicious) >= 9.0
-Requires:       perl(YAML::XS) >= 0.67
+Requires:       perl(YAML::XS) >= 0.670
+Provides:       perl(LinkCheck)
+Provides:       perl(LinkCheck::Controller::Links)
+Provides:       perl(LinkCheck::Task::CheckLinks)
 Provides:       perl(Minion) = %{version}
 Provides:       perl(Minion::Backend)
 Provides:       perl(Minion::Backend::Pg)
@@ -42,6 +46,7 @@
 Provides:       perl(Minion::Command::minion::worker)
 Provides:       perl(Minion::Iterator)
 Provides:       perl(Minion::Job)
+Provides:       perl(Minion::Util)
 Provides:       perl(Minion::Worker)
 Provides:       perl(Mojolicious::Plugin::Minion)
 Provides:       perl(Mojolicious::Plugin::Minion::Admin)
@@ -66,7 +71,7 @@
 Take a look at our excellent documentation in Minion::Guide!
 
 %prep
-%autosetup  -n %{cpan_name}-%{cpan_version}
+%autosetup -n %{cpan_name}-%{cpan_version} -p1
 
 find . -type f ! -path "*/t/*" ! -name "*.pl" ! -path "*/bin/*" ! -path 
"*/script/*" ! -path "*/scripts/*" ! -name "configure" -print0 | xargs -0 chmod 
644
 

++++++ Minion-10.31.tar.gz -> Minion-11.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Minion-10.31/Changes new/Minion-11.0/Changes
--- old/Minion-10.31/Changes    2024-09-21 15:52:15.000000000 +0200
+++ new/Minion-11.0/Changes     2025-08-22 16:29:56.884570480 +0200
@@ -1,4 +1,12 @@
 
+11.0 2025-08-21
+  - Minion::Backend::Pg now requires PostgreSQL 13.
+  - Removed experimetnal status from lax dependency support.
+  - Added support for task limits.
+  - Added Minion::Util module.
+  - Added spare remote control command, this allows workers to be paused again 
by combining jobs and spare.
+  - Fixed a problem where remote control commands would not immediately update 
the worker status.
+
 10.31 2024-09-21
   - Restore old repair behavior for job dependencies without performance loss. 
(HEM42)
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Minion-10.31/MANIFEST new/Minion-11.0/MANIFEST
--- old/Minion-10.31/MANIFEST   2024-09-21 15:52:57.000000000 +0200
+++ new/Minion-11.0/MANIFEST    2025-08-22 16:31:34.808768201 +0200
@@ -21,6 +21,7 @@
 lib/Minion/Guide.pod
 lib/Minion/Iterator.pm
 lib/Minion/Job.pm
+lib/Minion/Util.pm
 lib/Minion/Worker.pm
 lib/Mojolicious/Plugin/Minion.pm
 lib/Mojolicious/Plugin/Minion/Admin.pm
@@ -63,6 +64,7 @@
 LICENSE
 Makefile.PL
 MANIFEST                       This list of files
+MANIFEST.bak
 MANIFEST.SKIP
 README.md
 t/backend.t
@@ -79,5 +81,6 @@
 t/pg_worker.t
 t/pod.t
 t/pod_coverage.t
+t/util.t
 META.yml                                 Module YAML meta-data (added by 
MakeMaker)
 META.json                                Module JSON meta-data (added by 
MakeMaker)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Minion-10.31/MANIFEST.bak 
new/Minion-11.0/MANIFEST.bak
--- old/Minion-10.31/MANIFEST.bak       1970-01-01 01:00:00.000000000 +0100
+++ new/Minion-11.0/MANIFEST.bak        2024-09-21 15:52:54.000000000 +0200
@@ -0,0 +1,81 @@
+.perltidyrc
+Changes
+examples/admin.png
+examples/linkcheck/lib/LinkCheck.pm
+examples/linkcheck/lib/LinkCheck/Controller/Links.pm
+examples/linkcheck/lib/LinkCheck/Task/CheckLinks.pm
+examples/linkcheck/linkcheck.conf
+examples/linkcheck/script/linkcheck
+examples/linkcheck/t/linkcheck.t
+examples/linkcheck/templates/layouts/linkcheck.html.ep
+examples/linkcheck/templates/links/index.html.ep
+examples/linkcheck/templates/links/result.html.ep
+examples/minion_bench.pl
+lib/Minion.pm
+lib/Minion/Backend.pm
+lib/Minion/Backend/Pg.pm
+lib/Minion/Backend/resources/migrations/pg.sql
+lib/Minion/Command/minion.pm
+lib/Minion/Command/minion/job.pm
+lib/Minion/Command/minion/worker.pm
+lib/Minion/Guide.pod
+lib/Minion/Iterator.pm
+lib/Minion/Job.pm
+lib/Minion/Worker.pm
+lib/Mojolicious/Plugin/Minion.pm
+lib/Mojolicious/Plugin/Minion/Admin.pm
+lib/Mojolicious/Plugin/Minion/resources/public/minion/app.css
+lib/Mojolicious/Plugin/Minion/resources/public/minion/app.js
+lib/Mojolicious/Plugin/Minion/resources/public/minion/bootstrap/bootstrap.css
+lib/Mojolicious/Plugin/Minion/resources/public/minion/bootstrap/bootstrap.js
+lib/Mojolicious/Plugin/Minion/resources/public/minion/d3/d3.js
+lib/Mojolicious/Plugin/Minion/resources/public/minion/epoch/epoch.css
+lib/Mojolicious/Plugin/Minion/resources/public/minion/epoch/epoch.js
+lib/Mojolicious/Plugin/Minion/resources/public/minion/fontawesome/fontawesome.css
+lib/Mojolicious/Plugin/Minion/resources/public/minion/jquery/jquery.js
+lib/Mojolicious/Plugin/Minion/resources/public/minion/logo-black-2x.png
+lib/Mojolicious/Plugin/Minion/resources/public/minion/logo-black.png
+lib/Mojolicious/Plugin/Minion/resources/public/minion/moment/moment.js
+lib/Mojolicious/Plugin/Minion/resources/public/minion/pinstripe-light.png
+lib/Mojolicious/Plugin/Minion/resources/public/minion/webfonts/fa-brands-400.eot
+lib/Mojolicious/Plugin/Minion/resources/public/minion/webfonts/fa-brands-400.svg
+lib/Mojolicious/Plugin/Minion/resources/public/minion/webfonts/fa-brands-400.ttf
+lib/Mojolicious/Plugin/Minion/resources/public/minion/webfonts/fa-brands-400.woff
+lib/Mojolicious/Plugin/Minion/resources/public/minion/webfonts/fa-brands-400.woff2
+lib/Mojolicious/Plugin/Minion/resources/public/minion/webfonts/fa-regular-400.eot
+lib/Mojolicious/Plugin/Minion/resources/public/minion/webfonts/fa-regular-400.svg
+lib/Mojolicious/Plugin/Minion/resources/public/minion/webfonts/fa-regular-400.ttf
+lib/Mojolicious/Plugin/Minion/resources/public/minion/webfonts/fa-regular-400.woff
+lib/Mojolicious/Plugin/Minion/resources/public/minion/webfonts/fa-regular-400.woff2
+lib/Mojolicious/Plugin/Minion/resources/public/minion/webfonts/fa-solid-900.eot
+lib/Mojolicious/Plugin/Minion/resources/public/minion/webfonts/fa-solid-900.svg
+lib/Mojolicious/Plugin/Minion/resources/public/minion/webfonts/fa-solid-900.ttf
+lib/Mojolicious/Plugin/Minion/resources/public/minion/webfonts/fa-solid-900.woff
+lib/Mojolicious/Plugin/Minion/resources/public/minion/webfonts/fa-solid-900.woff2
+lib/Mojolicious/Plugin/Minion/resources/templates/layouts/minion.html.ep
+lib/Mojolicious/Plugin/Minion/resources/templates/minion/_limit.html.ep
+lib/Mojolicious/Plugin/Minion/resources/templates/minion/_notifications.html.ep
+lib/Mojolicious/Plugin/Minion/resources/templates/minion/_pagination.html.ep
+lib/Mojolicious/Plugin/Minion/resources/templates/minion/dashboard.html.ep
+lib/Mojolicious/Plugin/Minion/resources/templates/minion/jobs.html.ep
+lib/Mojolicious/Plugin/Minion/resources/templates/minion/locks.html.ep
+lib/Mojolicious/Plugin/Minion/resources/templates/minion/workers.html.ep
+LICENSE
+Makefile.PL
+MANIFEST                       This list of files
+MANIFEST.SKIP
+README.md
+t/backend.t
+t/commands.t
+t/lib/MinionTest/AddTestTask.pm
+t/lib/MinionTest/BadTestTask.pm
+t/lib/MinionTest/EmptyTestTask.pm
+t/lib/MinionTest/FailTestTask.pm
+t/lib/MinionTest/NoResultTestTask.pm
+t/lib/MinionTest/SyntaxErrorTestTask.pm
+t/pg.t
+t/pg_admin.t
+t/pg_lite_app.t
+t/pg_worker.t
+t/pod.t
+t/pod_coverage.t
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Minion-10.31/META.json new/Minion-11.0/META.json
--- old/Minion-10.31/META.json  2024-09-21 15:52:57.000000000 +0200
+++ new/Minion-11.0/META.json   2025-08-22 16:31:34.784813091 +0200
@@ -4,7 +4,7 @@
       "Sebastian Riedel <[email protected]>"
    ],
    "dynamic_config" : 0,
-   "generated_by" : "ExtUtils::MakeMaker version 7.64, CPAN::Meta::Converter 
version 2.150010",
+   "generated_by" : "ExtUtils::MakeMaker version 7.70, CPAN::Meta::Converter 
version 2.150010",
    "license" : [
       "artistic_2"
    ],
@@ -58,6 +58,6 @@
          "web" : "https://web.libera.chat/#mojo";
       }
    },
-   "version" : "10.31",
-   "x_serialization_backend" : "JSON::PP version 4.07"
+   "version" : "11.0",
+   "x_serialization_backend" : "JSON::PP version 4.16"
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Minion-10.31/META.yml new/Minion-11.0/META.yml
--- old/Minion-10.31/META.yml   2024-09-21 15:52:56.000000000 +0200
+++ new/Minion-11.0/META.yml    2025-08-22 16:31:34.666269415 +0200
@@ -7,7 +7,7 @@
 configure_requires:
   ExtUtils::MakeMaker: '0'
 dynamic_config: 0
-generated_by: 'ExtUtils::MakeMaker version 7.64, CPAN::Meta::Converter version 
2.150010'
+generated_by: 'ExtUtils::MakeMaker version 7.70, CPAN::Meta::Converter version 
2.150010'
 license: artistic_2
 meta-spec:
   url: http://module-build.sourceforge.net/META-spec-v1.4.html
@@ -30,5 +30,5 @@
   homepage: https://mojolicious.org
   license: http://www.opensource.org/licenses/artistic-license-2.0
   repository: https://github.com/mojolicious/minion.git
-version: '10.31'
+version: '11.0'
 x_serialization_backend: 'CPAN::Meta::YAML version 0.018'
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Minion-10.31/examples/linkcheck/t/linkcheck.t 
new/Minion-11.0/examples/linkcheck/t/linkcheck.t
--- old/Minion-10.31/examples/linkcheck/t/linkcheck.t   2023-04-12 
14:32:58.000000000 +0200
+++ new/Minion-11.0/examples/linkcheck/t/linkcheck.t    2025-05-05 
12:02:09.122123095 +0200
@@ -24,11 +24,17 @@
 
 # Enqueue a background job
 $t->get_ok('/')->status_is(200)->text_is('title' => 'Check 
links')->element_exists('form input[type=url]');
-$t->post_ok('/links' => form => {url => 
'https://mojolicious.org'})->status_is(200)->text_is('title' => 'Result')
-  ->text_is('p' => 'Waiting for result...')->element_exists_not('table');
+$t->post_ok('/links' => form => {url => 'https://mojolicious.org'})
+  ->status_is(200)
+  ->text_is('title' => 'Result')
+  ->text_is('p'     => 'Waiting for result...')
+  ->element_exists_not('table');
 
 # Perform the background job
-$t->get_ok('/links/1')->status_is(200)->text_is('title' => 
'Result')->text_is('p' => 'Waiting for result...')
+$t->get_ok('/links/1')
+  ->status_is(200)
+  ->text_is('title' => 'Result')
+  ->text_is('p'     => 'Waiting for result...')
   ->element_exists_not('table');
 $t->app->minion->perform_jobs;
 $t->get_ok('/links/1')->status_is(200)->text_is('title' => 
'Result')->element_exists_not('p')->element_exists('table');
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Minion-10.31/examples/minion_bench.pl 
new/Minion-11.0/examples/minion_bench.pl
--- old/Minion-10.31/examples/minion_bench.pl   2022-07-21 01:39:53.000000000 
+0200
+++ new/Minion-11.0/examples/minion_bench.pl    2025-05-06 14:32:39.493359401 
+0200
@@ -3,18 +3,20 @@
 use Minion;
 use Time::HiRes 'time';
 
-my $ENQUEUE     = 10000;
-my $DEQUEUE     = 1000;
+my $ENQUEUE     = 20000;
+my $BATCHES     = 20;
+my $DEQUEUE     = 50;
+my $PARENTS     = 50;
+my $CHILDREN    = 500;
 my $REPETITIONS = 2;
 my $WORKERS     = 4;
 my $INFO        = 100;
 my $STATS       = 100;
-my $REPAIR      = 100;
+my $REPAIR      = 10;
 my $LOCK        = 1000;
 my $UNLOCK      = 1000;
 
-# A benchmark script for comparing backends and evaluating the performance
-# impact of proposed changes
+# A benchmark script for comparing backends and evaluating the performance 
impact of proposed changes
 my $minion = Minion->new(Pg => 
'postgresql://[email protected]:5432/postgres');
 $minion->add_task(foo => sub { });
 $minion->add_task(bar => sub { });
@@ -22,14 +24,20 @@
 
 # Enqueue
 say "Clean start with $ENQUEUE jobs";
-my @parents = map { $minion->enqueue('foo') } 1 .. 5;
+my @parents = map { $minion->enqueue('foo') } 1 .. $PARENTS;
+my $worker  = $minion->worker->register;
+$worker->dequeue(0.5, {id => $_})->finish for @parents;
+$worker->unregister;
 my $before  = time;
-$minion->enqueue($_ % 2 ? 'foo' : 'bar' => [] => {parents => \@parents}) for 1 
.. $ENQUEUE;
+my @jobs    = map { $minion->enqueue($_ % 2 ? 'foo' : 'bar' => [] => {parents 
=> \@parents}) } 1 .. $ENQUEUE;
 my $elapsed = time - $before;
 my $avg     = sprintf '%.3f', $ENQUEUE / $elapsed;
 say "Enqueued $ENQUEUE jobs in $elapsed seconds ($avg/s)";
+$minion->enqueue('foo' => [] => {parents => \@jobs}) for 1 .. $CHILDREN;
 $minion->backend->pg->db->query('ANALYZE minion_jobs');
 
+my $FINISH = $DEQUEUE * $BATCHES;
+
 # Dequeue
 sub dequeue {
   my @pids;
@@ -37,12 +45,18 @@
     die "Couldn't fork: $!" unless defined(my $pid = fork);
     unless ($pid) {
       my $worker = $minion->repair->worker->register;
-      say "$$ will finish $DEQUEUE jobs";
       my $before = time;
-      $worker->dequeue(0.5)->finish for 1 .. $DEQUEUE;
+      for (1 .. $BATCHES) {
+        my @jobs;
+        while (@jobs < $DEQUEUE) {
+          next unless my $job = $worker->dequeue(0.5);
+          push @jobs, $job;
+        }
+        $_->finish({minion_bench => $_->id}) for @jobs;
+      }
       my $elapsed = time - $before;
-      my $avg     = sprintf '%.3f', $DEQUEUE / $elapsed;
-      say "$$ finished $DEQUEUE jobs in $elapsed seconds ($avg/s)";
+      my $avg     = sprintf '%.3f', $FINISH / $elapsed;
+      say "$$ finished $FINISH jobs in $elapsed seconds ($avg/s)";
       $worker->unregister;
       exit;
     }
@@ -53,8 +67,8 @@
   my $before = time;
   waitpid $_, 0 for @pids;
   my $elapsed = time - $before;
-  my $avg     = sprintf '%.3f', ($DEQUEUE * $WORKERS) / $elapsed;
-  say "$WORKERS workers finished $DEQUEUE jobs each in $elapsed seconds 
($avg/s)";
+  my $avg     = sprintf '%.3f', ($FINISH * $WORKERS) / $elapsed;
+  say "$WORKERS workers finished $FINISH jobs each in $elapsed seconds 
($avg/s)";
 }
 dequeue() for 1 .. $REPETITIONS;
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Minion-10.31/lib/Minion/Backend/Pg.pm 
new/Minion-11.0/lib/Minion/Backend/Pg.pm
--- old/Minion-10.31/lib/Minion/Backend/Pg.pm   2024-09-21 15:49:15.000000000 
+0200
+++ new/Minion-11.0/lib/Minion/Backend/Pg.pm    2025-08-22 16:26:17.752364800 
+0200
@@ -128,7 +128,7 @@
   my $self = shift->SUPER::new(pg => Mojo::Pg->new(@_));
 
   my $db = Mojo::Pg->new(@_)->db;
-  croak 'PostgreSQL 9.5 or later is required' if $db->dbh->{pg_server_version} 
< 90500;
+  croak 'PostgreSQL 12 or later is required' if $db->dbh->{pg_server_version} 
< 130000;
   $db->disconnect;
 
   my $schema = path(__FILE__)->dirname->child('resources', 'migrations', 
'pg.sql');
@@ -267,21 +267,25 @@
   my ($self, $id, $options) = @_;
 
   return $self->pg->db->query(
-    q{UPDATE minion_jobs SET started = NOW(), state = 'active', worker = ?
-      WHERE id = (
+    q{WITH cte AS (
         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 (
+          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())))
+            OR (state = 'inactive' AND (expires IS NULL OR expires > NOW()))
+          )
         )) AND priority >= COALESCE(?, priority) AND queue = ANY (?) AND state 
= 'inactive' AND task = ANY (?)
-          AND (EXPIRES IS NULL OR expires > NOW())
+          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->{min_priority},
-    $options->{queues} || ['default'], [keys %{$self->minion->tasks}]
+      UPDATE minion_jobs
+      SET started = NOW(), state = 'active', worker = ?
+      WHERE id = (SELECT id FROM cte)
+      RETURNING id, args, retries, task}, $options->{id}, 
$options->{min_priority}, $options->{queues} || ['default'],
+    $options->{tasks} || [keys %{$self->minion->tasks}], $id
   )->expand->hash;
 }
 
@@ -370,6 +374,12 @@
 
 One or more queues to dequeue jobs from, defaults to C<default>.
 
+=item tasks
+
+  tasks => ['foo', 'bar']
+
+One or more tasks to dequeue jobs for, defaults to all tasks.
+
 =back
 
 These fields are currently available:
@@ -438,7 +448,7 @@
   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!
+defaults to C<false>.
 
 =item notes
 
@@ -957,7 +967,7 @@
   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!
+defaults to C<false>.
 
 =item parents
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Minion-10.31/lib/Minion/Backend.pm 
new/Minion-11.0/lib/Minion/Backend.pm
--- old/Minion-10.31/lib/Minion/Backend.pm      2024-03-19 17:25:46.000000000 
+0100
+++ new/Minion-11.0/lib/Minion/Backend.pm       2025-08-22 16:25:35.984148164 
+0200
@@ -131,6 +131,12 @@
 
 One or more queues to dequeue jobs from, defaults to C<default>.
 
+=item tasks
+
+  tasks => ['foo', 'bar']
+
+One or more tasks to dequeue jobs for, defaults to all.
+
 =back
 
 These fields are currently available:
@@ -199,7 +205,7 @@
   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!
+defaults to C<false>.
 
 =item notes
 
@@ -714,7 +720,7 @@
   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!
+defaults to C<false>.
 
 =item parents
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Minion-10.31/lib/Minion/Command/minion/worker.pm 
new/Minion-11.0/lib/Minion/Command/minion/worker.pm
--- old/Minion-10.31/lib/Minion/Command/minion/worker.pm        2022-07-21 
01:39:53.000000000 +0200
+++ new/Minion-11.0/lib/Minion/Command/minion/worker.pm 2025-08-22 
14:49:49.998709294 +0200
@@ -16,7 +16,8 @@
     'D|dequeue-timeout=i'    => \$status->{dequeue_timeout},
     'I|heartbeat-interval=i' => \$status->{heartbeat_interval},
     'j|jobs=i'               => \$status->{jobs},
-    'q|queue=s'              => \my @queues,
+    'L|limit=s' => sub { $_[1] =~ /^(\S+)=(\d+)$/ ? ($status->{limits}{$1} = 
$2) : warn "Invalid limit option: $_[1]" },
+    'q|queue=s' => \my @queues,
     'R|repair-interval=i'    => \$status->{repair_interval},
     's|spare=i'              => \$status->{spare},
     'S|spare-min-priority=i' => \$status->{spare_min_priority};
@@ -50,6 +51,7 @@
     ./myapp.pl minion worker
     ./myapp.pl minion worker -m production -I 15 -C 5 -R 3600 -j 10
     ./myapp.pl minion worker -q important -q default
+    ./myapp.pl minion worker -L foo=2 -L bar=5
 
   Options:
     -C, --command-interval <seconds>     Worker remote control command 
interval,
@@ -65,6 +67,8 @@
                                          parallel in forked worker processes
                                          (not including spare processes),
                                          defaults to 4
+    -L, --limit <name>=<number>          Limit number of jobs for a specific
+                                         task
     -m, --mode <name>                    Operating mode for your application,
                                          defaults to the value of
                                          MOJO_MODE/PLACK_ENV or "development"
@@ -122,7 +126,7 @@
 
 Instruct one or more workers to change the number of jobs to perform 
concurrently. Setting this value to C<0> will
 effectively pause the worker. That means all current jobs will be finished, 
but no new ones accepted, until the number
-is increased again.
+is increased again. Note that L</"spare"> might need to be adjusted if high 
priority jobs should be paused as well.
 
 =head2 kill
 
@@ -132,6 +136,15 @@
 Instruct one or more workers to send a signal to a job that is currently being 
performed. This command will be ignored
 by workers that do not have a job matching the id. That means it is safe to 
broadcast this command to all workers.
 
+=head2 spare
+
+  $ ./myapp.pl minion job -b spare -a '[1]'
+  $ ./myapp.pl minion job -b spare -a '[1]' 23
+
+Instruct one or more workers to change the number of spare worker processes to 
reserve for high priority jobs. Setting
+this value to C<0> will effectively disable the feature, this is required to 
pause the worker. That means all current
+high priority jobs will be finished, but no new ones accepted, until the 
number is increased again.
+
 =head2 stop
 
   $ ./myapp.pl minion job -b stop -a '[10025]'
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Minion-10.31/lib/Minion/Job.pm 
new/Minion-11.0/lib/Minion/Job.pm
--- old/Minion-10.31/lib/Minion/Job.pm  2023-11-10 15:51:58.000000000 +0100
+++ new/Minion-11.0/lib/Minion/Job.pm   2025-08-22 16:25:43.890419404 +0200
@@ -528,7 +528,7 @@
   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!
+defaults to C<false>.
 
 =item parents
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Minion-10.31/lib/Minion/Util.pm 
new/Minion-11.0/lib/Minion/Util.pm
--- old/Minion-10.31/lib/Minion/Util.pm 1970-01-01 01:00:00.000000000 +0100
+++ new/Minion-11.0/lib/Minion/Util.pm  2025-08-21 14:16:32.144547014 +0200
@@ -0,0 +1,56 @@
+package Minion::Util;
+use Mojo::Base -strict;
+
+use Exporter qw(import);
+our @EXPORT_OK = qw(desired_tasks);
+
+sub desired_tasks {
+  my ($limits, $available_tasks, $active_tasks) = @_;
+
+  my %count;
+  $count{$_}++ for @$active_tasks;
+
+  my @desired;
+  for my $task (@$available_tasks) {
+    my $count = $count{$task} // 0;
+    my $limit = $limits->{$task};
+    push @desired, $task if !defined($limit) || $count < $limit;
+  }
+
+  return \@desired;
+}
+
+1;
+
+=encoding utf8
+
+=head1 NAME
+
+Minion::Util - Minion utility functions
+
+=head1 SYNOPSIS
+
+  use Minion::Util qw(desired_tasks);
+
+=head1 DESCRIPTION
+
+L<Minion::Util> provides utility functions for L<Minion>.
+
+=head1 FUNCTIONS
+
+L<Minion::Util> implements the following functions, which can be imported 
individually.
+
+=head2 desired_tasks
+
+  my $desired_tasks = desired_trasks $limits, $available_tasks, $active_tasks;
+
+Enforce limits and generate list of currently desired tasks.
+
+  # ['bar']
+  desired_trasks {foo => 2}, ['foo', 'bar'], ['foo', 'foo'];
+
+=head1 SEE ALSO
+
+L<Minion>, L<Minion::Guide>, 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.31/lib/Minion/Worker.pm 
new/Minion-11.0/lib/Minion/Worker.pm
--- old/Minion-10.31/lib/Minion/Worker.pm       2023-02-04 01:44:47.000000000 
+0100
+++ new/Minion-11.0/lib/Minion/Worker.pm        2025-08-22 15:31:35.908372811 
+0200
@@ -1,8 +1,9 @@
 package Minion::Worker;
 use Mojo::Base 'Mojo::EventEmitter';
 
-use Carp       qw(croak);
-use Mojo::Util qw(steady_time);
+use Carp         qw(croak);
+use Minion::Util qw(desired_tasks);
+use Mojo::Util   qw(steady_time);
 
 has [qw(commands status)] => sub { {} };
 has [qw(id minion)];
@@ -34,10 +35,13 @@
 sub process_commands {
   my $self = shift;
 
+  my $called = 0;
   for my $command (@{$self->minion->backend->receive($self->id)}) {
     next unless my $cb = $self->commands->{shift @$command};
     $self->$cb(@$command);
+    $called++;
   }
+  $self->register if $called;
 
   return $self;
 }
@@ -56,6 +60,7 @@
   $status->{dequeue_timeout}    //= 5;
   $status->{heartbeat_interval} //= 300;
   $status->{jobs}               //= 4;
+  $status->{limits}             //= {};
   $status->{queues} ||= ['default'];
   $status->{performed}       //= 0;
   $status->{repair_interval} //= 21600;
@@ -74,9 +79,10 @@
 
   # Remote control commands need to validate arguments carefully
   my $commands = $self->commands;
-  local $commands->{jobs} = sub { $status->{jobs} = $_[1] if ($_[1] // '') =~ 
/^\d+$/ };
-  local $commands->{kill} = \&_kill;
-  local $commands->{stop} = sub { $self->_kill('KILL', $_[1]) };
+  local $commands->{jobs}  = sub { $status->{jobs} = $_[1] if ($_[1] // '') =~ 
/^\d+$/ };
+  local $commands->{kill}  = \&_kill;
+  local $commands->{spare} = sub { $status->{spare} = $_[1] if ($_[1] // '') 
=~ /^\d+$/ };
+  local $commands->{stop}  = sub { $self->_kill('KILL', $_[1]) };
 
   eval { $self->_work until $self->{finished} && !@{$self->{jobs}} };
   my $err = $@;
@@ -127,8 +133,10 @@
   elsif ($status->{jobs} <= @$jobs) { @extra = (min_priority => 
$status->{spare_min_priority}) }
 
   # Try to get more jobs
+  my $tasks = desired_tasks($status->{limits}, [keys %{$self->minion->tasks}], 
[map { $_->task } @$jobs]);
+  return unless @$tasks;
   my ($max, $queues) = @{$status}{qw(dequeue_timeout queues)};
-  my $job = $self->emit('wait')->dequeue($max => {queues => $queues, @extra});
+  my $job = $self->emit('wait')->dequeue($max => {queues => $queues, tasks => 
$tasks, @extra});
   push @$jobs, $job->start if $job;
 }
 
@@ -294,6 +302,12 @@
 
 One or more queues to dequeue jobs from, defaults to C<default>.
 
+=item tasks
+
+  tasks => ['foo', 'bar'] 
+
+One or more tasks to dequeue jobs from, defaults to all tasks.
+
 =back
 
 =head2 info
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Minion-10.31/lib/Minion.pm 
new/Minion-11.0/lib/Minion.pm
--- old/Minion-10.31/lib/Minion.pm      2024-09-21 15:52:34.000000000 +0200
+++ new/Minion-11.0/lib/Minion.pm       2025-08-22 16:30:08.470564259 +0200
@@ -21,7 +21,7 @@
 has [qw(remove_after stuck_after)] => 172800;
 has tasks                          => sub { {} };
 
-our $VERSION = '10.31';
+our $VERSION = '11.0';
 
 sub add_task {
   my ($self, $name, $task) = @_;
@@ -370,6 +370,9 @@
   # Broadcast "jobs" command to pause worker 23
   $minion->broadcast('jobs', [0], [23]);
 
+  # Broadcast "spare" command to disable the feature on all workers
+  $minion->broadcast('spare', [0]);
+
 =head2 class_for_task
 
   my $class = $minion->class_for_task('foo');
@@ -414,7 +417,7 @@
   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!
+defaults to C<false>.
 
 =item notes
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Minion-10.31/t/pg.t new/Minion-11.0/t/pg.t
--- old/Minion-10.31/t/pg.t     2024-09-21 15:49:15.000000000 +0200
+++ new/Minion-11.0/t/pg.t      2025-08-22 14:43:03.416466012 +0200
@@ -750,6 +750,31 @@
   $worker->unregister;
 };
 
+subtest 'Task limits' => sub {
+  my $id     = $minion->enqueue('foo');
+  my $id2    = $minion->enqueue('foo');
+  my $id3    = $minion->enqueue('bar');
+  my $id4    = $minion->enqueue('baz');
+  my $id5    = $minion->enqueue('bar');
+  my $worker = $minion->worker->register;
+  ok my $job = $worker->dequeue(0, {tasks => ['foo', 'bar', 'baz']}), 'job 
dequeued';
+  is $job->id, $id, 'right id';
+  ok $job->finish,                                   'job finished';
+  ok $job = $worker->dequeue(0, {tasks => ['bar']}), 'job dequeued';
+  is $job->id, $id3, 'right id';
+  ok $job->finish,                                          'job finished';
+  ok $job = $worker->dequeue(0, {tasks => ['bar', 'baz']}), 'job dequeued';
+  is $job->id, $id4, 'right id';
+  ok $job->finish,                                          'job finished';
+  ok $job = $worker->dequeue(0, {tasks => ['bar', 'baz']}), 'job dequeued';
+  is $job->id, $id5, 'right id';
+  ok $job->finish,                                                 'job 
finished';
+  ok $job = $worker->dequeue(0, {tasks => ['foo', 'bar', 'baz']}), 'job 
dequeued';
+  is $job->id, $id2, 'right id';
+  ok $job->finish, 'job finished';
+  $worker->unregister;
+};
+
 subtest 'Events' => sub {
   my ($enqueue, $pid_start, $pid_stop);
   my ($failed, $finished) = (0, 0);
@@ -1407,6 +1432,7 @@
   my @commands;
   $_->add_command(test_id => sub { push @commands, shift->id }) for $worker, 
$worker2;
   $worker->add_command(test_args => sub { shift and push @commands, [@_] 
})->register;
+  $worker2->add_command(test_status => sub { $_[0]->status->{test} = $_[1] });
   ok $minion->broadcast('test_id', [], [$worker->id]),               'sent 
command';
   ok $minion->broadcast('test_id', [], [$worker->id, $worker2->id]), 'sent 
command';
   $worker->process_commands->register;
@@ -1417,10 +1443,12 @@
   ok $minion->broadcast('test_whatever'),                                      
'sent command';
   ok $minion->broadcast('test_args', [23], []),                                
'sent command';
   ok $minion->broadcast('test_args', [1, [2], {3 => 'three'}], [$worker->id]), 
'sent command';
+  ok $minion->broadcast('test_status', ['works']),                             
'sent command';
   $_->process_commands for $worker, $worker2;
   is_deeply \@commands, [$worker->id, [23], [1, [2], {3 => 'three'}], 
$worker2->id], 'right structure';
+  is $worker2->status->{test}, 'works', 'right status';
   $_->unregister for $worker, $worker2;
-  ok !$minion->broadcast('test_id', []), 'command not sent';
+  ok !$minion->broadcast('test_id'), 'command not sent';
 };
 
 subtest 'Single process worker' => sub {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Minion-10.31/t/pg_admin.t 
new/Minion-11.0/t/pg_admin.t
--- old/Minion-10.31/t/pg_admin.t       2024-03-19 17:25:46.000000000 +0100
+++ new/Minion-11.0/t/pg_admin.t        2025-05-05 12:02:09.223186419 +0200
@@ -32,23 +32,37 @@
 };
 
 subtest 'Stats' => sub {
-  $t->get_ok('/minion/stats')->status_is(200)->json_is('/active_jobs' => 
0)->json_is('/active_locks' => 0)
-    ->json_is('/active_workers'   => 0)->json_is('/delayed_jobs'  => 
0)->json_is('/enqueued_jobs' => 2)
-    ->json_is('/failed_jobs'      => 0)->json_is('/finished_jobs' => 
1)->json_is('/inactive_jobs' => 1)
-    ->json_is('/inactive_workers' => 0)->json_has('/uptime');
+  $t->get_ok('/minion/stats')
+    ->status_is(200)
+    ->json_is('/active_jobs'      => 0)
+    ->json_is('/active_locks'     => 0)
+    ->json_is('/active_workers'   => 0)
+    ->json_is('/delayed_jobs'     => 0)
+    ->json_is('/enqueued_jobs'    => 2)
+    ->json_is('/failed_jobs'      => 0)
+    ->json_is('/finished_jobs'    => 1)
+    ->json_is('/inactive_jobs'    => 1)
+    ->json_is('/inactive_workers' => 0)
+    ->json_has('/uptime');
 };
 
 subtest 'Jobs' => sub {
-  $t->get_ok('/minion/jobs?state=inactive')->status_is(200)->text_like('tbody 
td a' => qr/$inactive/)
+  $t->get_ok('/minion/jobs?state=inactive')
+    ->status_is(200)
+    ->text_like('tbody td a' => qr/$inactive/)
     ->text_unlike('tbody td a' => qr/$finished/);
-  $t->get_ok('/minion/jobs?state=finished')->status_is(200)->text_like('tbody 
td a' => qr/$finished/)
+  $t->get_ok('/minion/jobs?state=finished')
+    ->status_is(200)
+    ->text_like('tbody td a' => qr/$finished/)
     ->text_unlike('tbody td a' => qr/$inactive/);
 };
 
 subtest 'Workers' => sub {
   $t->get_ok('/minion/workers')->status_is(200)->element_exists_not('tbody td 
a');
   my $worker = app->minion->worker->register;
-  $t->get_ok('/minion/workers')->status_is(200)->element_exists('tbody td a')
+  $t->get_ok('/minion/workers')
+    ->status_is(200)
+    ->element_exists('tbody td a')
     ->text_like('tbody td a' => qr/@{[$worker->id]}/);
   $worker->unregister;
   $t->get_ok('/minion/workers')->status_is(200)->element_exists_not('tbody td 
a');
@@ -64,11 +78,15 @@
   $t->get_ok('/minion/locks')->status_is(200)->text_like('tbody td#lock_id' => 
qr/2/);
   $t->get_ok('/minion/locks?name=foo')->status_is(200)->text_like('tbody td a' 
      => qr/foo/);
   $t->get_ok('/minion/locks?name=foo')->status_is(200)->text_like('tbody 
td#lock_id' => qr/1/);
-  
$t->post_ok('/minion/locks?_method=DELETE&name=bar')->status_is(200)->text_like('tbody
 td a' => qr/foo/)
+  $t->post_ok('/minion/locks?_method=DELETE&name=bar')
+    ->status_is(200)
+    ->text_like('tbody td a' => qr/foo/)
     ->text_like('.alert-success', qr/All selected named locks released/);
   is $t->tx->previous->res->code, 302, 'right status';
   like $t->tx->previous->res->headers->location, qr/locks/, 'right "Location" 
value';
-  
$t->post_ok('/minion/locks?_method=DELETE&name=foo')->status_is(200)->element_exists_not('tbody
 td a')
+  $t->post_ok('/minion/locks?_method=DELETE&name=foo')
+    ->status_is(200)
+    ->element_exists_not('tbody td a')
     ->text_like('.alert-success', qr/All selected named locks released/);
   is $t->tx->previous->res->code, 302, 'right status';
   like $t->tx->previous->res->headers->location, qr/locks/, 'right "Location" 
value';
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Minion-10.31/t/pg_worker.t 
new/Minion-11.0/t/pg_worker.t
--- old/Minion-10.31/t/pg_worker.t      2023-02-04 01:45:23.000000000 +0100
+++ new/Minion-11.0/t/pg_worker.t       2025-08-22 15:34:13.193964919 +0200
@@ -40,6 +40,43 @@
   is_deeply $minion->job($id)->info->{result}, {just => 'works!'}, 'right 
result';
 };
 
+subtest 'Task limit' => sub {
+  $minion->add_task(
+    $_ => sub {
+      my $job = shift;
+      $job->finish({just => 'works!'});
+    }
+  ) for qw(foo bar baz);
+  my $worker = $minion->worker;
+  $worker->status->{dequeue_timeout} = 0;
+  $worker->status->{limits}          = {foo => 0};
+  $worker->status->{jobs}            = 1;
+  $worker->on(
+    dequeue => sub {
+      my ($worker, $job) = @_;
+      return unless $job->task eq 'baz';
+      $job->on(reap => sub { kill 'INT', $$ });
+    }
+  );
+  my $id  = $minion->enqueue('foo');
+  my $id2 = $minion->enqueue('bar');
+  my $id3 = $minion->enqueue('baz');
+  $worker->run;
+  is_deeply $minion->job($id)->info->{state},  'inactive', 'right state';
+  is_deeply $minion->job($id2)->info->{state}, 'finished', 'right state';
+  is_deeply $minion->job($id3)->info->{state}, 'finished', 'right state';
+};
+
+subtest 'Remote control commands (pause before shutdown)' => sub {
+  my $worker = $minion->worker->register;
+  $minion->broadcast('jobs',  [0]);
+  $minion->broadcast('spare', [0]);
+  $worker->on(busy => sub { kill 'INT', $$ });
+  $worker->run;
+  is $worker->status->{jobs},  0, 'jobs updated';
+  is $worker->status->{spare}, 0, 'spare updated';
+};
+
 subtest 'Clean up event loop' => sub {
   my $timer = 0;
   Mojo::IOLoop->recurring(0 => sub { $timer++ });
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Minion-10.31/t/util.t new/Minion-11.0/t/util.t
--- old/Minion-10.31/t/util.t   1970-01-01 01:00:00.000000000 +0100
+++ new/Minion-11.0/t/util.t    2025-08-21 14:13:04.568393590 +0200
@@ -0,0 +1,16 @@
+use Mojo::Base -strict;
+
+use Test::More;
+use Minion::Util qw(desired_tasks);
+
+subtest 'desired_tasks' => sub {
+  is_deeply desired_tasks({},                   [],                    []),    
                [],      'no tasks';
+  is_deeply desired_tasks({foo => 2},           ['foo', 'bar'],        ['foo', 
'foo']),        ['bar'], 'right tasks';
+  is_deeply desired_tasks({foo => 0},           ['foo', 'bar'],        []),    
                ['bar'], 'right tasks';
+  is_deeply desired_tasks({foo => 2},           ['foo', 'bar'],        ['foo', 
'foo', 'foo']), ['bar'], 'right tasks';
+  is_deeply desired_tasks({foo => 2, bar => 1}, ['foo', 'bar', 'baz'], ['foo', 
'bar', 'foo']), ['baz'], 'right tasks';
+  is_deeply desired_tasks({foo => 2, bar => 1}, ['foo', 'bar'],        ['foo', 
'foo', 'bar']), [],      'no tasks';
+  is_deeply desired_tasks({},                   ['foo', 'bar'],        ['foo', 
'foo']), ['foo', 'bar'], 'right tasks';
+};
+
+done_testing();

++++++ README.md ++++++

## Build Results

Current state of perl in openSUSE:Factory is

![Factory build 
results](https://br.opensuse.org/status/openSUSE:Factory/perl-Minion/standard)

The current state of perl in the devel project build (devel:languages:perl)

![Devel project build 
results](https://br.opensuse.org/status/devel:languages:perl/perl-Minion)



++++++ _scmsync.obsinfo ++++++
mtime: 1756377413
commit: 47cbf4af8400b6dcb5bf80919799ef40d9b3b1a4f7e42e2b588e6422b8ecf2c7
url: https://src.opensuse.org/perl/perl-Minion.git
revision: 47cbf4af8400b6dcb5bf80919799ef40d9b3b1a4f7e42e2b588e6422b8ecf2c7
projectscmsync: https://src.opensuse.org/perl/_ObsPrj

++++++ build.specials.obscpio ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/.gitignore new/.gitignore
--- old/.gitignore      1970-01-01 01:00:00.000000000 +0100
+++ new/.gitignore      2025-08-28 17:53:00.000000000 +0200
@@ -0,0 +1 @@
+.osc

Reply via email to