Hello community,

here is the log from the commit of package perl-Minion for openSUSE:Factory 
checked in at 2020-10-27 19:01:36
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/perl-Minion (Old)
 and      /work/SRC/openSUSE:Factory/.perl-Minion.new.3463 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "perl-Minion"

Tue Oct 27 19:01:36 2020 rev:62 rq:844254 version:10.14

Changes:
--------
--- /work/SRC/openSUSE:Factory/perl-Minion/perl-Minion.changes  2020-08-04 
20:19:38.308963324 +0200
+++ /work/SRC/openSUSE:Factory/.perl-Minion.new.3463/perl-Minion.changes        
2020-10-27 19:01:51.390870345 +0100
@@ -1,0 +2,10 @@
+Mon Oct 26 03:07:26 UTC 2020 - Tina Müller <timueller+p...@suse.de>
+
+- updated to 10.14
+   see /usr/share/doc/packages/perl-Minion/Changes
+
+  10.14  2020-10-24
+    - Changed SQL style to use uppercase keywords.
+    - Fixed a bug where Minion::Worker could inherit timers from Mojolicious 
applications.
+
+-------------------------------------------------------------------

Old:
----
  Minion-10.13.tar.gz

New:
----
  Minion-10.14.tar.gz

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

Other differences:
------------------
++++++ perl-Minion.spec ++++++
--- /var/tmp/diff_new_pack.eK4WwT/_old  2020-10-27 19:01:52.342871037 +0100
+++ /var/tmp/diff_new_pack.eK4WwT/_new  2020-10-27 19:01:52.346871041 +0100
@@ -17,7 +17,7 @@
 
 
 Name:           perl-Minion
-Version:        10.13
+Version:        10.14
 Release:        0
 %define cpan_name Minion
 Summary:        Job queue

++++++ Minion-10.13.tar.gz -> Minion-10.14.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Minion-10.13/Changes new/Minion-10.14/Changes
--- old/Minion-10.13/Changes    2020-07-31 19:54:27.000000000 +0200
+++ new/Minion-10.14/Changes    2020-10-24 18:13:26.000000000 +0200
@@ -1,4 +1,8 @@
 
+10.14  2020-10-24
+  - Changed SQL style to use uppercase keywords.
+  - Fixed a bug where Minion::Worker could inherit timers from Mojolicious 
applications.
+
 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.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Minion-10.13/META.json new/Minion-10.14/META.json
--- old/Minion-10.13/META.json  2020-07-31 20:20:55.000000000 +0200
+++ new/Minion-10.14/META.json  2020-10-26 00:10:34.000000000 +0100
@@ -4,7 +4,7 @@
       "Sebastian Riedel <s...@cpan.org>"
    ],
    "dynamic_config" : 0,
-   "generated_by" : "ExtUtils::MakeMaker version 7.46, CPAN::Meta::Converter 
version 2.150010",
+   "generated_by" : "ExtUtils::MakeMaker version 7.50, CPAN::Meta::Converter 
version 2.150010",
    "license" : [
       "artistic_2"
    ],
@@ -57,6 +57,6 @@
          "web" : "https://webchat.freenode.net/#mojo";
       }
    },
-   "version" : "10.13",
+   "version" : "10.14",
    "x_serialization_backend" : "JSON::PP version 4.05"
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Minion-10.13/META.yml new/Minion-10.14/META.yml
--- old/Minion-10.13/META.yml   2020-07-31 20:20:55.000000000 +0200
+++ new/Minion-10.14/META.yml   2020-10-26 00:10:33.000000000 +0100
@@ -7,7 +7,7 @@
 configure_requires:
   ExtUtils::MakeMaker: '0'
 dynamic_config: 0
-generated_by: 'ExtUtils::MakeMaker version 7.46, CPAN::Meta::Converter version 
2.150010'
+generated_by: 'ExtUtils::MakeMaker version 7.50, CPAN::Meta::Converter version 
2.150010'
 license: artistic_2
 meta-spec:
   url: http://module-build.sourceforge.net/META-spec-v1.4.html
@@ -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.13'
+version: '10.14'
 x_serialization_backend: 'CPAN::Meta::YAML version 0.018'
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Minion-10.13/examples/linkcheck/t/linkcheck.t 
new/Minion-10.14/examples/linkcheck/t/linkcheck.t
--- old/Minion-10.13/examples/linkcheck/t/linkcheck.t   2020-05-31 
00:18:13.000000000 +0200
+++ new/Minion-10.14/examples/linkcheck/t/linkcheck.t   2020-10-24 
16:40:51.000000000 +0200
@@ -15,8 +15,8 @@
 # Isolate tests
 my $url = Mojo::URL->new($ENV{TEST_ONLINE})->query([search_path => 
'linkcheck_test']);
 my $pg  = Mojo::Pg->new($url);
-$pg->db->query('drop schema if exists linkcheck_test cascade');
-$pg->db->query('create schema linkcheck_test');
+$pg->db->query('DROP SCHEMA IF EXISTS linkcheck_test CASCADE');
+$pg->db->query('CREATE SCHEMA linkcheck_test');
 
 # Override configuration for testing
 my $t = Test::Mojo->new(LinkCheck => {pg => $url, secrets => ['test_s3cret']});
@@ -34,6 +34,6 @@
 $t->get_ok('/links/1')->status_is(200)->text_is('title' => 
'Result')->element_exists_not('p')->element_exists('table');
 
 # Clean up once we are done
-$pg->db->query('drop schema linkcheck_test cascade');
+$pg->db->query('DROP SCHEMA linkcheck_test CASCADE');
 
 done_testing();
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Minion-10.13/examples/minion_bench.pl 
new/Minion-10.14/examples/minion_bench.pl
--- old/Minion-10.13/examples/minion_bench.pl   2020-07-28 15:03:12.000000000 
+0200
+++ new/Minion-10.14/examples/minion_bench.pl   2020-10-24 16:34:44.000000000 
+0200
@@ -28,7 +28,7 @@
 my $elapsed = time - $before;
 my $avg     = sprintf '%.3f', $ENQUEUE / $elapsed;
 say "Enqueued $ENQUEUE jobs in $elapsed seconds ($avg/s)";
-$minion->backend->pg->db->query('analyze minion_jobs');
+$minion->backend->pg->db->query('ANALYZE minion_jobs');
 
 # Dequeue
 sub dequeue {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Minion-10.13/lib/Minion/Backend/Pg.pm 
new/Minion-10.14/lib/Minion/Backend/Pg.pm
--- old/Minion-10.13/lib/Minion/Backend/Pg.pm   2020-07-31 00:50:57.000000000 
+0200
+++ new/Minion-10.14/lib/Minion/Backend/Pg.pm   2020-10-24 18:15:02.000000000 
+0200
@@ -12,7 +12,7 @@
 sub broadcast {
   my ($self, $command, $args, $ids) = (shift, shift, shift || [], shift || []);
   return !!$self->pg->db->query(
-    q{update minion_workers set inbox = inbox || $1::jsonb where (id = any 
($2) or $2 = '{}')},
+    q{UPDATE minion_workers SET inbox = inbox || $1::JSONB WHERE (id = ANY 
($2) OR $2 = '{}')},
     {json => [[$command, @$args]]}, $ids)->rows;
 }
 
@@ -36,10 +36,10 @@
   my ($self, $task, $args, $options) = (shift, shift, shift || [], shift || 
{});
 
   return $self->pg->db->query(
-    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, $10)
-      returning id}, {json => $args}, $options->{attempts} // 1, 
$options->{delay} // 0, $options->{expire},
+    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, $10)
+      RETURNING id}, {json => $args}, $options->{attempts} // 1, 
$options->{delay} // 0, $options->{expire},
     $options->{lax} ? 1 : 0, {json => $options->{notes} || {}}, 
$options->{parents} || [], $options->{priority} // 0,
     $options->{queue} // 'default', $task
   )->hash->{id};
@@ -52,20 +52,20 @@
   my $self = shift;
 
   my $daily = $self->pg->db->query(
-    "select extract(epoch from ts) as epoch, coalesce(failed_jobs, 0) as 
failed_jobs,
-       coalesce(finished_jobs, 0) as finished_jobs
-     from (
-       select extract (day from finished) as day, extract(hour from finished) 
as hour,
-         count(*) filter (where state = 'failed') as failed_jobs,
-         count(*) filter (where state = 'finished') as finished_jobs
-       from minion_jobs
-       where finished > now() - interval '23 hours'
-       group by day, hour
-     ) as j right outer join (
-       select *
-       from generate_series(now() - interval '23 hour', now(), '1 hour') as ts
-     ) as s on extract(hour from ts) = j.hour and extract(day from ts) = j.day
-     order by epoch asc"
+    "SELECT EXTRACT(EPOCH FROM ts) AS epoch, COALESCE(failed_jobs, 0) AS 
failed_jobs,
+       COALESCE(finished_jobs, 0) AS finished_jobs
+     FROM (
+       SELECT EXTRACT (DAY FROM finished) AS day, EXTRACT(HOUR FROM finished) 
AS hour,
+         COUNT(*) FILTER (WHERE state = 'failed') AS failed_jobs,
+         COUNT(*) FILTER (WHERE state = 'finished') AS finished_jobs
+       FROM minion_jobs
+       WHERE finished > NOW() - INTERVAL '23 hours'
+       GROUP BY day, hour
+     ) AS j RIGHT OUTER JOIN (
+       SELECT *
+       FROM GENERATE_SERIES(NOW() - INTERVAL '23 hour', NOW(), '1 hour') AS ts
+     ) AS s ON EXTRACT(HOUR FROM ts) = j.hour AND EXTRACT(DAY FROM ts) = j.day
+     ORDER BY epoch ASC"
   )->hashes->to_array;
 
   return {daily => $daily};
@@ -75,18 +75,18 @@
   my ($self, $offset, $limit, $options) = @_;
 
   my $jobs = $self->pg->db->query(
-    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, 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
-      where (id < $1 or $1 is null) and (id = any ($2) or $2 is null) and 
(notes \? any ($3) or $3 is null)
-        and (queue = any ($4) or $4 is null) and (state = any ($5) or $5 is 
null) and (task = any ($6) or $6 is null)
-        and (state != 'inactive' or expires is null or expires > now())
-      order by id desc
-      limit $7 offset $8}, @$options{qw(before ids notes queues states 
tasks)}, $limit, $offset
+    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 expires) AS expires, 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, 
worker
+      FROM minion_jobs AS j
+      WHERE (id < $1 OR $1 IS NULL) AND (id = ANY ($2) OR $2 IS NULL) AND 
(notes \? ANY ($3) OR $3 IS NULL)
+        AND (queue = ANY ($4) OR $4 IS null) AND (state = ANY ($5) OR $5 IS 
NULL) AND (task = ANY ($6) OR $6 IS NULL)
+        AND (state != 'inactive' OR expires IS null OR expires > NOW())
+      ORDER BY id DESC
+      LIMIT $7 OFFSET $8}, @$options{qw(before ids notes queues states 
tasks)}, $limit, $offset
   )->expand->hashes->to_array;
 
   return _total('jobs', $jobs);
@@ -96,9 +96,9 @@
   my ($self, $offset, $limit, $options) = @_;
 
   my $locks = $self->pg->db->query(
-    'select name, extract(epoch from expires) as expires, count(*) over() as 
total from minion_locks
-     where expires > now() and (name = any ($1) or $1 is null)
-     order by id desc limit $2 offset $3', $options->{names}, $limit, $offset
+    'SELECT name, EXTRACT(EPOCH FROM expires) AS expires, COUNT(*) OVER() AS 
total FROM minion_locks
+     WHERE expires > NOW() AND (name = ANY ($1) OR $1 IS NULL)
+     ORDER BY id DESC LIMIT $2 OFFSET $3', $options->{names}, $limit, $offset
   )->hashes->to_array;
   return _total('locks', $locks);
 }
@@ -107,20 +107,20 @@
   my ($self, $offset, $limit, $options) = @_;
 
   my $workers = $self->pg->db->query(
-    "select id, extract(epoch from notified) as notified, array(
-        select id from minion_jobs where state = 'active' and worker = 
minion_workers.id
-      ) as jobs, host, pid, status, extract(epoch from started) as started,
-      count(*) over() as total
-     from minion_workers
-     where (id < \$1 or \$1 is null)  and (id = any (\$2) or \$2 is null)
-     order by id desc limit \$3 offset \$4", @$options{qw(before ids)}, 
$limit, $offset
+    "SELECT id, EXTRACT(EPOCH FROM notified) AS notified, ARRAY(
+        SELECT id FROM minion_jobs WHERE state = 'active' AND worker = 
minion_workers.id
+      ) AS jobs, host, pid, status, EXTRACT(EPOCH FROM started) AS started,
+      COUNT(*) OVER() AS total
+     FROM minion_workers
+     WHERE (id < \$1 OR \$1 IS NULL)  AND (id = ANY (\$2) OR \$2 IS NULL)
+     ORDER BY id DESC LIMIT \$3 OFFSET \$4", @$options{qw(before ids)}, 
$limit, $offset
   )->expand->hashes->to_array;
   return _total('workers', $workers);
 }
 
 sub lock {
   my ($self, $name, $duration, $options) = (shift, shift, shift, shift // {});
-  return !!$self->pg->db->query('select * from minion_lock(?, ?, ?)', $name, 
$duration, $options->{limit} || 1)
+  return !!$self->pg->db->query('SELECT * FROM minion_lock(?, ?, ?)', $name, 
$duration, $options->{limit} || 1)
     ->array->[0];
 }
 
@@ -139,16 +139,16 @@
 
 sub note {
   my ($self, $id, $merge) = @_;
-  return !!$self->pg->db->query('update minion_jobs set notes = 
jsonb_strip_nulls(notes || ?) where id = ?',
+  return !!$self->pg->db->query('UPDATE minion_jobs SET notes = 
JSONB_STRIP_NULLS(notes || ?) WHERE id = ?',
     {json => $merge}, $id)->rows;
 }
 
 sub receive {
   my $array = shift->pg->db->query(
-    "update minion_workers as new set inbox = '[]'
-     from (select id, inbox from minion_workers where id = ? for update) as old
-     where new.id = old.id and old.inbox != '[]'
-     returning old.inbox", shift
+    "UPDATE minion_workers AS new SET inbox = '[]'
+     FROM (SELECT id, inbox FROM minion_workers WHERE id = ? FOR UPDATE) AS old
+     WHERE new.id = old.id AND old.inbox != '[]'
+     RETURNING old.inbox", shift
   )->expand->array;
   return $array ? $array->[0] : [];
 }
@@ -157,17 +157,17 @@
   my ($self, $id, $options) = (shift, shift, shift || {});
 
   return $self->pg->db->query(
-    q{insert into minion_workers (id, host, pid, status)
-      values (coalesce($1, nextval('minion_workers_id_seq')), $2, $3, $4)
-      on conflict(id) do update set notified = now(), status = $4
-      returning id}, $id, $self->{host} //= hostname, $$, {json => 
$options->{status} // {}}
+    q{INSERT INTO minion_workers (id, host, pid, status)
+      VALUES (COALESCE($1, NEXTVAL('minion_workers_id_seq')), $2, $3, $4)
+      ON CONFLICT(id) DO UPDATE SET notified = now(), status = $4
+      RETURNING id}, $id, $self->{host} //= hostname, $$, {json => 
$options->{status} // {}}
   )->hash->{id};
 }
 
 sub remove_job {
   my ($self, $id) = @_;
   return !!$self->pg->db->query(
-    "delete from minion_jobs where id = ? and state in ('inactive', 'failed', 
'finished') returning 1", $id)->rows;
+    "DELETE FROM minion_jobs WHERE id = ? AND state IN ('inactive', 'failed', 
'finished') RETURNING 1", $id)->rows;
 }
 
 sub repair {
@@ -176,47 +176,47 @@
   # Workers without heartbeat
   my $db     = $self->pg->db;
   my $minion = $self->minion;
-  $db->query("delete from minion_workers where notified < now() - interval '1 
second' * ?", $minion->missing_after);
+  $db->query("DELETE FROM minion_workers WHERE notified < NOW() - INTERVAL '1 
second' * ?", $minion->missing_after);
 
   # Old jobs with no unresolved dependencies and expired jobs
   $db->query(
-    "delete from minion_jobs as j
-     where (finished <= now() - interval '1 second' * ? and not exists (
-       select 1 from minion_jobs where parents @> ARRAY[j.id] and state != 
'finished'
-     ) and state = 'finished') or (expires <= now() and state = 'inactive')", 
$minion->remove_after
+    "DELETE FROM minion_jobs AS j
+     WHERE (finished <= NOW() - INTERVAL '1 second' * ? AND NOT EXISTS (
+       SELECT 1 FROM minion_jobs WHERE parents @> ARRAY[j.id] AND state != 
'finished'
+     ) AND state = 'finished') OR (expires <= NOW() AND state = 'inactive')", 
$minion->remove_after
   );
 
   # Jobs with missing worker (can be retried)
   $db->query(
-    "select id, retries from minion_jobs as j
-     where state = 'active' and queue != 'minion_foreground'
-       and not exists (select 1 from minion_workers where id = j.worker)"
+    "SELECT id, retries FROM minion_jobs AS j
+     WHERE state = 'active' AND queue != 'minion_foreground'
+       AND NOT EXISTS (SELECT 1 FROM minion_workers WHERE id = j.worker)"
   )->hashes->each(sub { $self->fail_job(@$_{qw(id retries)}, 'Worker went 
away') });
 
   # Jobs in queue without workers or not enough workers (cannot be retried and 
requires admin attention)
   $db->query(
-    q{update minion_jobs set state = 'failed', result = '"Job appears stuck in 
queue"'
-      where state = 'inactive' and delayed + ? * interval '1 second' < now()}, 
$minion->stuck_after
+    q{UPDATE minion_jobs SET state = 'failed', result = '"Job appears stuck in 
queue"'
+      WHERE state = 'inactive' AND delayed + ? * INTERVAL '1 second' < NOW()}, 
$minion->stuck_after
   );
 }
 
 sub reset {
   my ($self, $options) = (shift, shift // {});
 
-  if ($options->{all}) { $self->pg->db->query('truncate minion_jobs, 
minion_locks, minion_workers restart identity') }
-  elsif ($options->{locks}) { $self->pg->db->query('truncate minion_locks') }
+  if ($options->{all}) { $self->pg->db->query('TRUNCATE minion_jobs, 
minion_locks, minion_workers RESTART IDENTITY') }
+  elsif ($options->{locks}) { $self->pg->db->query('TRUNCATE minion_locks') }
 }
 
 sub retry_job {
   my ($self, $id, $retries, $options) = (shift, shift, shift, shift || {});
 
   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,
-        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},
+    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,
+        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;
 }
@@ -225,16 +225,16 @@
   my $self = shift;
 
   my $stats = $self->pg->db->query(
-    "select count(*) filter (where state = 'inactive' and (expires is null or 
expires > now())) as inactive_jobs,
-       count(*) filter (where state = 'active') as active_jobs, count(*) 
filter (where state = 'failed') as failed_jobs,
-       count(*) filter (where state = 'finished') as finished_jobs,
-       count(*) filter (where state = 'inactive' and delayed > now()) as 
delayed_jobs,
-       (select count(*) from minion_locks where expires > now()) as 
active_locks,
-       count(distinct worker) filter (where state = 'active') as 
active_workers,
-       (select case when is_called then last_value else 0 end from 
minion_jobs_id_seq) as enqueued_jobs,
-       (select count(*) from minion_workers) as inactive_workers,
-       extract(epoch from now() - pg_postmaster_start_time()) as uptime
-     from minion_jobs"
+    "SELECT COUNT(*) FILTER (WHERE state = 'inactive' AND (expires IS NULL OR 
expires > NOW())) AS inactive_jobs,
+       COUNT(*) FILTER (WHERE state = 'active') AS active_jobs, COUNT(*) 
FILTER (WHERE state = 'failed') AS failed_jobs,
+       COUNT(*) FILTER (WHERE state = 'finished') AS finished_jobs,
+       COUNT(*) FILTER (WHERE state = 'inactive' AND delayed > NOW()) AS 
delayed_jobs,
+       (SELECT COUNT(*) FROM minion_locks WHERE expires > NOW()) AS 
active_locks,
+       COUNT(DISTINCT worker) FILTER (WHERE state = 'active') AS 
active_workers,
+       (SELECT CASE WHEN is_called THEN last_value ELSE 0 END FROM 
minion_jobs_id_seq) AS enqueued_jobs,
+       (SELECT COUNT(*) FROM minion_workers) AS inactive_workers,
+       EXTRACT(EPOCH FROM NOW() - PG_POSTMASTER_START_TIME()) AS uptime
+     FROM minion_jobs"
   )->hash;
   $stats->{inactive_workers} -= $stats->{active_workers};
 
@@ -243,13 +243,13 @@
 
 sub unlock {
   !!shift->pg->db->query(
-    'delete from minion_locks where id = (
-       select id from minion_locks where expires > now() and name = ? order by 
expires limit 1 for update
-     ) returning 1', shift
+    'DELETE FROM minion_locks WHERE id = (
+       SELECT id FROM minion_locks WHERE expires > NOW() AND name = ? ORDER BY 
expires LIMIT 1 FOR UPDATE
+     ) RETURNING 1', shift
   )->rows;
 }
 
-sub unregister_worker { shift->pg->db->query('delete from minion_workers where 
id = ?', shift) }
+sub unregister_worker { shift->pg->db->query('DELETE FROM minion_workers WHERE 
id = ?', shift) }
 
 sub _total {
   my ($name, $results) = @_;
@@ -262,19 +262,19 @@
   my ($self, $id, $options) = @_;
 
   return $self->pg->db->query(
-    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
+    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'],
+      RETURNING id, args, retries, task}, $id, $options->{id}, 
$options->{queues} || ['default'],
     [keys %{$self->minion->tasks}]
   )->expand->hash;
 }
@@ -283,9 +283,9 @@
   my ($self, $fail, $id, $retries, $result) = @_;
 
   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 attempts", {json => $result}, $fail ? 'failed' : 'finished', 
$id, $retries
+    "UPDATE minion_jobs SET finished = NOW(), result = ?, state = ?
+     WHERE id = ? AND retries = ? AND state = 'active'
+     RETURNING attempts", {json => $result}, $fail ? 'failed' : 'finished', 
$id, $retries
   )->array;
 
   return $fail ? $self->auto_retry_job($id, $retries, $row->[0]) : 1;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/Minion-10.13/lib/Minion/Backend/resources/migrations/pg.sql 
new/Minion-10.14/lib/Minion/Backend/resources/migrations/pg.sql
--- old/Minion-10.13/lib/Minion/Backend/resources/migrations/pg.sql     
2020-07-30 20:42:14.000000000 +0200
+++ new/Minion-10.14/lib/Minion/Backend/resources/migrations/pg.sql     
2020-10-24 19:54:02.000000000 +0200
@@ -3,92 +3,92 @@
 -- Downgrades may be used to clean up the database, but they do not have to 
work with old versions of Minion.
 --
 -- 18 up
-create type minion_state as enum ('inactive', 'active', 'failed', 'finished');
-create table if not exists minion_jobs (
-  id       bigserial not null primary key,
-  args     jsonb not null check(jsonb_typeof(args) = 'array'),
-  attempts int not null default 1,
-  created  timestamp with time zone not null default now(),
-  delayed  timestamp with time zone not null,
-  finished timestamp with time zone,
-  notes    jsonb check(jsonb_typeof(notes) = 'object') not null default '{}',
-  parents  bigint[] not null default '{}',
-  priority int not null,
-  queue    text not null default 'default',
-  result   jsonb,
-  retried  timestamp with time zone,
-  retries  int not null default 0,
-  started  timestamp with time zone,
-  state    minion_state not null default 'inactive'::minion_state,
-  task     text not null,
-  worker   bigint
+CREATE TYPE minion_state AS ENUM ('inactive', 'active', 'failed', 'finished');
+CREATE TABLE IF NOT EXISTS minion_jobs (
+  id       BIGSERIAL NOT NULL PRIMARY KEY,
+  args     JSONB NOT NULL CHECK(JSONB_TYPEOF(args) = 'array'),
+  attempts INT NOT NULL DEFAULT 1,
+  created  TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(),
+  delayed  TIMESTAMP WITH TIME ZONE NOT NULL,
+  finished TIMESTAMP WITH TIME ZONE,
+  notes    JSONB CHECK(JSONB_TYPEOF(notes) = 'object') NOT NULL DEFAULT '{}',
+  parents  BIGINT[] NOT NULL DEFAULT '{}',
+  priority INT NOT NULL,
+  queue    TEXT NOT NULL DEFAULT 'default',
+  result   JSONB,
+  retried  TIMESTAMP WITH TIME ZONE,
+  retries  INT NOT NULL DEFAULT 0,
+  started  TIMESTAMP WITH TIME ZONE,
+  state    minion_state NOT NULL DEFAULT 'inactive'::MINION_STATE,
+  task     TEXT NOT NULL,
+  worker   BIGINT
 );
-create index on minion_jobs (state, priority desc, id);
-create index on minion_jobs using gin (parents);
-create table if not exists minion_workers (
-  id       bigserial not null primary key,
-  host     text not null,
-  inbox    jsonb check(jsonb_typeof(inbox) = 'array') not null default '[]',
-  notified timestamp with time zone not null default now(),
-  pid      int not null,
-  started  timestamp with time zone not null default now(),
-  status   jsonb check(jsonb_typeof(status) = 'object') not null default '{}'
+CREATE INDEX ON minion_jobs (state, priority DESC, id);
+CREATE INDEX ON minion_jobs USING GIN (parents);
+CREATE TABLE IF NOT EXISTS minion_workers (
+  id       BIGSERIAL NOT NULL PRIMARY KEY,
+  host     TEXT NOT NULL,
+  inbox    JSONB CHECK(JSONB_TYPEOF(inbox) = 'array') NOT NULL DEFAULT '[]',
+  notified TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(),
+  pid      INT NOT NULL,
+  started  TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(),
+  status   JSONB CHECK(JSONB_TYPEOF(status) = 'object') NOT NULL DEFAULT '{}'
 );
-create unlogged table if not exists minion_locks (
-  id      bigserial not null primary key,
-  name    text not null,
-  expires timestamp with time zone not null
+CREATE UNLOGGED TABLE IF NOT EXISTS minion_locks (
+  id      BIGSERIAL NOT NULL PRIMARY KEY,
+  name    TEXT NOT NULL,
+  expires TIMESTAMP WITH TIME ZONE NOT NULL
 );
-create index on minion_locks (name, expires);
+CREATE INDEX ON minion_locks (name, expires);
 
-create or replace function minion_jobs_notify_workers() returns trigger as $$
-  begin
-    if new.delayed <= now() then
-      notify "minion.job";
-    end if;
-    return null;
-  end;
-$$ language plpgsql;
-create trigger minion_jobs_notify_workers_trigger
-  after insert or update of retries on minion_jobs
-  for each row execute procedure minion_jobs_notify_workers();
-
-create or replace function minion_lock(text, int, int) returns bool as $$
-declare
-  new_expires timestamp with time zone = now() + (interval '1 second' * $2);
-begin
-  lock table minion_locks in exclusive mode;
-  delete from minion_locks where expires < now();
-  if (select count(*) >= $3 from minion_locks where name = $1) then
-    return false;
-  end if;
-  if new_expires > now() then
-    insert into minion_locks (name, expires) values ($1, new_expires);
-  end if;
-  return true;
-end;
-$$ language plpgsql;
+CREATE OR REPLACE FUNCTION minion_jobs_notify_workers() RETURNS trigger AS $$
+  BEGIN
+    IF new.delayed <= NOW() THEN
+      NOTIFY "minion.job";
+    END IF;
+    RETURN NULL;
+  END;
+$$ LANGUAGE plpgsql;
+CREATE TRIGGER minion_jobs_notify_workers_trigger
+  AFTER INSERT OR UPDATE OF retries ON minion_jobs
+  FOR EACH ROW EXECUTE PROCEDURE minion_jobs_notify_workers();
+
+CREATE OR REPLACE FUNCTION minion_lock(TEXT, INT, INT) RETURNS BOOL AS $$
+DECLARE
+  new_expires TIMESTAMP WITH TIME ZONE = NOW() + (INTERVAL '1 second' * $2);
+BEGIN
+  lock TABLE minion_locks IN exclusive mode;
+  DELETE FROM minion_locks WHERE expires < NOW();
+  IF (SELECT COUNT(*) >= $3 FROM minion_locks WHERE NAME = $1) THEN
+    RETURN false;
+  END IF;
+  IF new_expires > NOW() THEN
+    INSERT INTO minion_locks (name, expires) VALUES ($1, new_expires);
+  END IF;
+  RETURN TRUE;
+END;
+$$ LANGUAGE plpgsql;
 
 -- 18 down
-drop table if exists minion_jobs;
-drop table if exists minion_workers;
-drop table if exists minion_locks;
-drop type if exists minion_state;
-drop trigger if exists minion_jobs_notify_workers_trigger on minion_jobs;
-drop function if exists minion_jobs_notify_workers();
-drop function if exists minion_lock(text, int, int);
+DROP TABLE IF EXISTS minion_jobs;
+DROP TABLE if EXISTS minion_workers;
+DROP TABLE IF EXISTS minion_locks;
+DROP TYPE IF EXISTS minion_state;
+DROP TRIGGER IF EXISTS minion_jobs_notify_workers_trigger ON minion_jobs;
+DROP FUNCTION IF EXISTS minion_jobs_notify_workers();
+DROP FUNCTION IF EXISTS minion_lock(TEXT, INT, INT);
 
 -- 19 up
-create index on minion_jobs using gin (notes);
+CREATE INDEX ON minion_jobs USING GIN (notes);
 
 -- 20 up
-alter table minion_workers set unlogged;
+ALTER TABLE minion_workers SET UNLOGGED;
 
 -- 22 up
-alter table minion_jobs drop column if exists sequence;
-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);
+ALTER TABLE minion_jobs DROP COLUMN IF EXISTS SEQUENCE;
+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;
+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.13/lib/Minion/Command/minion/job.pm 
new/Minion-10.14/lib/Minion/Command/minion/job.pm
--- old/Minion-10.13/lib/Minion/Command/minion/job.pm   2020-07-30 
23:22:33.000000000 +0200
+++ new/Minion-10.14/lib/Minion/Command/minion/job.pm   2020-10-24 
18:15:03.000000000 +0200
@@ -21,9 +21,9 @@
     'f|foreground'  => \my $foreground,
     'H|history'     => \my $history,
     'L|locks'       => \my $locks,
-    'l|limit=i'     => \(my $limit = 100),
+    'l|limit=i'     => \(my $limit             = 100),
     'n|notes=s'     => sub { $options->{notes} = decode_json($_[1]) },
-    'o|offset=i'    => \(my $offset = 0),
+    'o|offset=i'    => \(my $offset            = 0),
     'P|parent=s'    => sub { push @{$options->{parents}}, $_[1] },
     'p|priority=i'  => \$options->{priority},
     'q|queue=s'     => sub { push @{$options->{queues}}, $options->{queue} = 
$_[1] },
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Minion-10.13/lib/Minion/Worker.pm 
new/Minion-10.14/lib/Minion/Worker.pm
--- old/Minion-10.13/lib/Minion/Worker.pm       2020-07-29 17:51:09.000000000 
+0200
+++ new/Minion-10.14/lib/Minion/Worker.pm       2020-10-24 18:15:01.000000000 
+0200
@@ -61,6 +61,8 @@
   $status->{repair_interval} //= 21600;
   $status->{repair_interval} -= int rand $status->{repair_interval} / 2;
 
+  # Reset event loop
+  Mojo::IOLoop->reset;
   local $SIG{CHLD} = sub { };
   local $SIG{INT}  = local $SIG{TERM} = sub { $self->{finished}++ };
   local $SIG{QUIT} = sub {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Minion-10.13/lib/Minion.pm 
new/Minion-10.14/lib/Minion.pm
--- old/Minion-10.13/lib/Minion.pm      2020-07-30 23:01:42.000000000 +0200
+++ new/Minion-10.14/lib/Minion.pm      2020-10-24 18:15:01.000000000 +0200
@@ -20,7 +20,7 @@
 has [qw(remove_after stuck_after)] => 172800;
 has tasks                          => sub { {} };
 
-our $VERSION = '10.13';
+our $VERSION = '10.14';
 
 sub add_task {
   my ($self, $name, $task) = @_;
@@ -1163,7 +1163,7 @@
 
 =back
 
-=head1 REFERENCE
+=head1 API
 
 This is the class hierarchy of the L<Minion> distribution.
 
@@ -1185,6 +1185,8 @@
 
 =item * L<Minion::Command::minion::worker>
 
+=item * L<Minion::Iterator>
+
 =item * L<Minion::Job>
 
 =item * L<Minion::Worker>
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Minion-10.13/lib/Mojolicious/Plugin/Minion/Admin.pm 
new/Minion-10.14/lib/Mojolicious/Plugin/Minion/Admin.pm
--- old/Minion-10.13/lib/Mojolicious/Plugin/Minion/Admin.pm     2020-07-29 
17:51:27.000000000 +0200
+++ new/Minion-10.14/lib/Mojolicious/Plugin/Minion/Admin.pm     2020-10-24 
18:15:03.000000000 +0200
@@ -85,8 +85,8 @@
   $v->optional('id');
   $v->optional('limit')->num;
   $v->optional('offset')->num;
-  my $limit  = $v->param('limit')  || 10;
-  my $offset = $v->param('offset') || 0;
+  my $limit   = $v->param('limit')  || 10;
+  my $offset  = $v->param('offset') || 0;
   my $options = {};
   $options->{ids} = $v->every_param('id') if $v->is_valid('id');
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Minion-10.13/t/commands.t 
new/Minion-10.14/t/commands.t
--- old/Minion-10.13/t/commands.t       2020-06-19 22:08:42.000000000 +0200
+++ new/Minion-10.14/t/commands.t       2020-10-24 18:15:09.000000000 +0200
@@ -7,7 +7,7 @@
   my $minion = Minion::Command::minion->new;
   ok $minion->description, 'has a description';
   like $minion->message,   qr/minion/, 'has a message';
-  like $minion->hint,      qr/help/, 'has a hint';
+  like $minion->hint,      qr/help/,   'has a hint';
 };
 
 subtest 'job' => sub {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Minion-10.13/t/pg.t new/Minion-10.14/t/pg.t
--- old/Minion-10.13/t/pg.t     2020-07-31 20:16:10.000000000 +0200
+++ new/Minion-10.14/t/pg.t     2020-10-24 18:15:08.000000000 +0200
@@ -17,8 +17,8 @@
 # Isolate tests
 require Mojo::Pg;
 my $pg = Mojo::Pg->new($ENV{TEST_ONLINE});
-$pg->db->query('drop schema if exists minion_test cascade');
-$pg->db->query('create schema minion_test');
+$pg->db->query('DROP SCHEMA IF EXISTS minion_test CASCADE');
+$pg->db->query('CREATE SCHEMA minion_test');
 my $minion = Minion->new(Pg => $ENV{TEST_ONLINE});
 $minion->backend->pg->search_path(['minion_test']);
 
@@ -114,10 +114,8 @@
   undef $worker2;
   is $job->info->{state}, 'active', 'job is still active';
   ok !!$minion->backend->list_workers(0, 1, {ids => [$id]})->{workers}[0], 'is 
registered';
-  $minion->backend->pg->db->query(
-    "update minion_workers
-   set notified = now() - interval '1 second' * ? where id = ?", 
$minion->missing_after + 1, $id
-  );
+  $minion->backend->pg->db->query("UPDATE minion_workers SET notified = NOW() 
- INTERVAL '1 second' * ? WHERE id = ?",
+    $minion->missing_after + 1, $id);
   $minion->repair;
   ok !$minion->backend->list_workers(0, 1, {ids => [$id]})->{workers}[0], 'not 
registered';
   like $job->info->{finished}, qr/^[\d.]+$/,       'has finished timestamp';
@@ -155,19 +153,15 @@
   my $id2    = $minion->enqueue('test');
   my $id3    = $minion->enqueue('test');
   $worker->dequeue(0)->perform for 1 .. 3;
-  my $finished = $minion->backend->pg->db->query(
-    'select extract(epoch from finished) as finished
-   from minion_jobs
-   where id = ?', $id2
-  )->hash->{finished};
-  $minion->backend->pg->db->query('update minion_jobs set finished = 
to_timestamp(?) where id = ?',
+  my $finished
+    = $minion->backend->pg->db->query('SELECT EXTRACT(EPOCH FROM finished) AS 
finished FROM minion_jobs WHERE id = ?',
+    $id2)->hash->{finished};
+  $minion->backend->pg->db->query('UPDATE minion_jobs SET finished = 
TO_TIMESTAMP(?) WHERE id = ?',
     $finished - ($minion->remove_after + 1), $id2);
-  $finished = $minion->backend->pg->db->query(
-    'select extract(epoch from finished) as finished
-   from minion_jobs
-   where id = ?', $id3
-  )->hash->{finished};
-  $minion->backend->pg->db->query('update minion_jobs set finished = 
to_timestamp(?) where id = ?',
+  $finished
+    = $minion->backend->pg->db->query('SELECT EXTRACT(EPOCH FROM finished) AS 
finished FROM minion_jobs WHERE id = ?',
+    $id3)->hash->{finished};
+  $minion->backend->pg->db->query('UPDATE minion_jobs SET finished = 
TO_TIMESTAMP(?) WHERE id = ?',
     $finished - ($minion->remove_after + 1), $id3);
   $worker->unregister;
   $minion->repair;
@@ -183,7 +177,7 @@
   my $id2    = $minion->enqueue('test');
   my $id3    = $minion->enqueue('test');
   my $id4    = $minion->enqueue('test');
-  $minion->backend->pg->db->query("update minion_jobs set delayed = now() - ? 
* interval '1 second' where id = ?",
+  $minion->backend->pg->db->query("UPDATE minion_jobs SET delayed = NOW() - ? 
* INTERVAL '1 second' WHERE id = ?",
     $minion->stuck_after + 1, $_)
     for $id, $id2, $id3, $id4;
   ok $worker->dequeue(0, {id => $id4})->finish('Works!'), 'job finished';
@@ -213,10 +207,10 @@
   my $batch = $results->{workers};
   ok $batch->[0]{id},        'has id';
   is $batch->[0]{host},      $host, 'right host';
-  is $batch->[0]{pid},       $$, 'right pid';
+  is $batch->[0]{pid},       $$,    'right pid';
   like $batch->[0]{started}, qr/^[\d.]+$/, 'has timestamp';
   is $batch->[1]{host},      $host, 'right host';
-  is $batch->[1]{pid},       $$, 'right pid';
+  is $batch->[1]{pid},       $$,    'right pid';
   ok !$batch->[2], 'no more results';
 
   $results = $minion->backend->list_workers(0, 1);
@@ -299,7 +293,7 @@
   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 => 3}),  'locked again';
   ok !$minion->lock('bar', 3600, {limit => 2}), 'not locked again';
   ok $minion->lock('baz', 3600, {limit => 3}), 'locked';
   ok $minion->unlock('bar'), 'unlocked';
@@ -338,8 +332,7 @@
   is $results->{locks}[2], undef, 'no more locks';
   is $results->{total}, 2, 'two results';
   $minion->backend->pg->db->query(
-    "update minion_locks set expires = now() - interval '1 second' * 1
-   where name = 'yada'",
+    "UPDATE minion_locks SET expires = NOW() - INTERVAL '1 second' * 1 WHERE 
name = 'yada'",
   );
   is $minion->backend->list_locks(0, 10, {names => ['yada']})->{total}, 0, 'no 
results';
   $minion->unlock('test');
@@ -470,31 +463,31 @@
   my $results = $minion->backend->list_jobs(0, 10);
   my $batch   = $results->{jobs};
   is $results->{total}, 4, 'four jobs total';
-  ok $batch->[0]{id},        'has id';
-  is $batch->[0]{task},      'add', 'right task';
-  is $batch->[0]{state},     'inactive', 'right state';
-  is $batch->[0]{retries},   0, 'job has not been retried';
-  like $batch->[0]{created}, qr/^[\d.]+$/, 'has created timestamp';
-  is $batch->[1]{task},      'fail', 'right task';
+  ok $batch->[0]{id},          'has id';
+  is $batch->[0]{task},        'add',        'right task';
+  is $batch->[0]{state},       'inactive',   'right state';
+  is $batch->[0]{retries},     0,            'job has not been retried';
+  like $batch->[0]{created},   qr/^[\d.]+$/, 'has created timestamp';
+  is $batch->[1]{task},        'fail',       'right task';
   is_deeply $batch->[1]{args}, [], 'right arguments';
   is_deeply $batch->[1]{notes}, {}, 'right metadata';
-  is_deeply $batch->[1]{result}, ['works'], 'right result';
-  is $batch->[1]{state},    'finished', 'right state';
-  is $batch->[1]{priority}, 0,          'right priority';
+  is_deeply $batch->[1]{result},   ['works'], 'right result';
+  is $batch->[1]{state},           'finished', 'right state';
+  is $batch->[1]{priority},        0,          'right priority';
   is_deeply $batch->[1]{parents},  [], 'right parents';
   is_deeply $batch->[1]{children}, [], 'right children';
-  is $batch->[1]{retries},    1,            'job has been retried';
-  like $batch->[1]{created},  qr/^[\d.]+$/, 'has created timestamp';
-  like $batch->[1]{delayed},  qr/^[\d.]+$/, 'has delayed timestamp';
-  like $batch->[1]{finished}, qr/^[\d.]+$/, 'has finished timestamp';
-  like $batch->[1]{retried},  qr/^[\d.]+$/, 'has retried timestamp';
-  like $batch->[1]{started},  qr/^[\d.]+$/, 'has started timestamp';
-  is $batch->[2]{task},       'fail',       'right task';
-  is $batch->[2]{state},      'finished',   'right state';
-  is $batch->[2]{retries},    0,            'job has not been retried';
-  is $batch->[3]{task},       'fail',       'right task';
-  is $batch->[3]{state},      'finished',   'right state';
-  is $batch->[3]{retries},    0,            'job has not been retried';
+  is $batch->[1]{retries},         1,            'job has been retried';
+  like $batch->[1]{created},       qr/^[\d.]+$/, 'has created timestamp';
+  like $batch->[1]{delayed},       qr/^[\d.]+$/, 'has delayed timestamp';
+  like $batch->[1]{finished},      qr/^[\d.]+$/, 'has finished timestamp';
+  like $batch->[1]{retried},       qr/^[\d.]+$/, 'has retried timestamp';
+  like $batch->[1]{started},       qr/^[\d.]+$/, 'has started timestamp';
+  is $batch->[2]{task},            'fail',       'right task';
+  is $batch->[2]{state},           'finished',   'right state';
+  is $batch->[2]{retries},         0,            'job has not been retried';
+  is $batch->[3]{task},            'fail',       'right task';
+  is $batch->[3]{state},           'finished',   'right state';
+  is $batch->[3]{retries},         0,            'job has not been retried';
   ok !$batch->[4], 'no more results';
 
   $batch = $minion->backend->list_jobs(0, 10, {states => 
['inactive']})->{jobs};
@@ -593,8 +586,8 @@
   ok $minion->job($id), 'job does exist';
   my $info = $minion->job($id)->info;
   is_deeply $info->{args}, [2, 2], 'right arguments';
-  is $info->{priority}, 0,          'right priority';
-  is $info->{state},    'inactive', 'right state';
+  is $info->{priority},    0,          'right priority';
+  is $info->{state},       'inactive', 'right state';
   my $worker = $minion->worker;
   is $worker->dequeue(0), undef, 'not registered';
   ok !$minion->job($id)->info->{started}, 'no started timestamp';
@@ -641,8 +634,8 @@
   is $job->info->{retries},   1,            'job has been retried once';
   ok $job = $worker->dequeue(0), 'job dequeued';
   is $job->retries, 1, 'job has been retried once';
-  ok $job->retry, 'job retried';
-  is $job->id, $id, 'right id';
+  ok $job->retry,   'job retried';
+  is $job->id,      $id, 'right id';
   is $job->info->{retries}, 2, 'job has been retried twice';
   ok $job = $worker->dequeue(0), 'job dequeued';
   is $job->info->{state}, 'active', 'right state';
@@ -658,7 +651,7 @@
   is $job->info->{state},   'inactive', 'right state';
   is $job->info->{retries}, 1,          'job has been retried once';
   ok $job = $worker->dequeue(0), 'job dequeued';
-  is $job->id, $id, 'right id';
+  is $job->id,     $id, 'right id';
   ok $job->fail,   'job failed';
   ok $job->remove, 'job has been removed';
   is $job->info,   undef, 'no information';
@@ -704,7 +697,7 @@
   is $worker->dequeue(0), undef, 'too early for job';
   my $job = $minion->job($id);
   ok $job->info->{delayed} > $job->info->{created}, 'delayed timestamp';
-  $minion->backend->pg->db->query("update minion_jobs set delayed = now() - 
interval '1 day' where id = ?", $id);
+  $minion->backend->pg->db->query("UPDATE minion_jobs SET delayed = NOW() - 
INTERVAL '1 day' WHERE id = ?", $id);
   ok $job = $worker->dequeue(0), 'job dequeued';
   is $job->id, $id, 'right id';
   like $job->info->{delayed}, qr/^[\d.]+$/, 'has delayed timestamp';
@@ -740,7 +733,7 @@
           $job->on(failed   => sub { $failed++ });
           $job->on(finished => sub { $finished++ });
           $job->on(spawn    => sub { $pid_start = pop });
-          $job->on(reap     => sub { $pid_stop = pop });
+          $job->on(reap     => sub { $pid_stop  = pop });
           $job->on(
             start => sub {
               my $job = shift;
@@ -777,9 +770,9 @@
   $job->on(finished => sub { $result = pop });
   ok $job->finish('Everything is fine!'), 'job finished';
   $job->perform;
-  is $result,   'Everything is fine!', 'right result';
-  is $failed,   0,                     'failed event has not been emitted';
-  is $finished, 1,                     'finished event has been emitted once';
+  is $result,      'Everything is fine!', 'right result';
+  is $failed,      0,                     'failed event has not been emitted';
+  is $finished,    1,                     'finished event has been emitted 
once';
   isnt $pid_start, $$,        'new process id';
   isnt $pid_stop,  $$,        'new process id';
   is $pid_start,   $pid_stop, 'same process id';
@@ -796,9 +789,9 @@
   ok $job = $worker->dequeue(0), 'job dequeued';
   $job->perform;
   is_deeply $job->info->{result}, {added => 9}, 'right result';
-  is $job->info->{notes}{finish_count}, 1, 'finish event has been emitted 
once';
-  ok $job->info->{notes}{finish_pid}, 'has a process id';
-  isnt $job->info->{notes}{finish_pid}, $$, 'different process id';
+  is $job->info->{notes}{finish_count},  1, 'finish event has been emitted 
once';
+  ok $job->info->{notes}{finish_pid},    'has a process id';
+  isnt $job->info->{notes}{finish_pid},  $$, 'different process id';
   is $job->info->{notes}{before},        23, 'value still exists';
   is $job->info->{notes}{cleanup_count}, 2,  'cleanup event has been emitted 
once';
   ok $job->info->{notes}{cleanup_pid},   'has a process id';
@@ -921,7 +914,7 @@
   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);
+  $minion->backend->pg->db->query('UPDATE minion_jobs SET delayed = NOW() 
WHERE id = ?', $id);
   ok $job = $worker->dequeue(0), 'job dequeued';
   is $job->id, $id, 'right id';
   is $job->retries, 1, 'job has been retried';
@@ -933,7 +926,7 @@
   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);
+  $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';
@@ -951,7 +944,7 @@
   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);
+  $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;
@@ -972,7 +965,7 @@
   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);
+  $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, 1, 'job has been retried once';
@@ -1004,10 +997,10 @@
 };
 
 subtest 'Perform jobs concurrently' => sub {
-  my $id  = $minion->enqueue(add => [10, 11]);
-  my $id2 = $minion->enqueue(add => [12, 13]);
-  my $id3 = $minion->enqueue('test');
-  my $id4 = $minion->enqueue('exit');
+  my $id     = $minion->enqueue(add => [10, 11]);
+  my $id2    = $minion->enqueue(add => [12, 13]);
+  my $id3    = $minion->enqueue('test');
+  my $id4    = $minion->enqueue('exit');
   my $worker = $minion->worker->register;
   ok my $job  = $worker->dequeue(0), 'job dequeued';
   ok my $job2 = $worker->dequeue(0), 'job dequeued';
@@ -1090,8 +1083,8 @@
   ok $job2->finish, 'job finished';
   ok $job = $worker->dequeue(0), 'job dequeued';
   is $job->id, $id3, 'right id';
-  is_deeply $job->info->{children}, [], 'right children';
-  is_deeply $job->info->{parents}, [$id, $id2], 'right parents';
+  is_deeply $job->info->{children},   [], 'right children';
+  is_deeply $job->info->{parents},    [$id, $id2], 'right parents';
   is $minion->stats->{finished_jobs}, 2, 'two finished jobs';
   is $minion->repair->stats->{finished_jobs}, 2, 'two finished jobs';
   ok $job->finish, 'job finished';
@@ -1200,7 +1193,7 @@
   $id = $minion->enqueue('test' => [] => {expire => 300});
   is $minion->repair->jobs({states => ['inactive']})->total, 1, 'job has not 
expired yet';
   my $pg = $minion->backend->pg;
-  $pg->db->query("update minion_jobs set expires = now() - interval '1 day' 
where id = ?", $id);
+  $pg->db->query("UPDATE minion_jobs SET expires = NOW() - INTERVAL '1 day' 
WHERE id = ?", $id);
   is $minion->jobs({states => ['inactive']})->total, 0, 'job has expired';
   ok !$worker->dequeue(0), 'job has expired';
   ok $pg->db->select('minion_jobs', '*', {id => $id})->hash, 'job still exists 
in database';
@@ -1211,7 +1204,7 @@
   ok $job = $worker->dequeue(0), 'job dequeued';
   is $job->id, $id, 'right id';
   ok $job->finish, 'job finished';
-  $pg->db->query("update minion_jobs set expires = now() - interval '1 day' 
where id = ?", $id);
+  $pg->db->query("UPDATE minion_jobs SET expires = NOW() - INTERVAL '1 day' 
WHERE id = ?", $id);
   $minion->repair;
   ok $job = $minion->job($id), 'job still exists';
   is $job->info->{state}, 'finished', 'right state';
@@ -1220,7 +1213,7 @@
   ok $job = $worker->dequeue(0), 'job dequeued';
   is $job->id, $id, 'right id';
   ok $job->fail, 'job failed';
-  $pg->db->query("update minion_jobs set expires = now() - interval '1 day' 
where id = ?", $id);
+  $pg->db->query("UPDATE minion_jobs SET expires = NOW() - INTERVAL '1 day' 
WHERE id = ?", $id);
   $minion->repair;
   ok $job = $minion->job($id), 'job still exists';
   is $job->info->{state}, 'failed', 'right state';
@@ -1228,7 +1221,7 @@
   $id = $minion->enqueue('test' => [] => {expire => 300});
   ok $job = $worker->dequeue(0), 'job dequeued';
   is $job->id, $id, 'right id';
-  $pg->db->query("update minion_jobs set expires = now() - interval '1 day' 
where id = ?", $id);
+  $pg->db->query("UPDATE minion_jobs SET expires = NOW() - INTERVAL '1 day' 
WHERE id = ?", $id);
   $minion->repair;
   ok $job = $minion->job($id), 'job still exists';
   is $job->info->{state}, 'active', 'right state';
@@ -1237,7 +1230,7 @@
   $id = $minion->enqueue('test' => [] => {expire => 300});
   my $id2 = $minion->enqueue('test' => [] => {parents => [$id]});
   ok !$worker->dequeue(0, {id => $id2}), 'parent is still inactive';
-  $pg->db->query("update minion_jobs set expires = now() - interval '1 day' 
where id = ?", $id);
+  $pg->db->query("UPDATE minion_jobs SET expires = NOW() - INTERVAL '1 day' 
WHERE id = ?", $id);
   ok $job = $worker->dequeue(0, {id => $id2}), 'parent has expired';
   ok $job->finish, 'job finished';
   $worker->unregister;
@@ -1396,6 +1389,6 @@
 };
 
 # Clean up once we are done
-$pg->db->query('drop schema minion_test cascade');
+$pg->db->query('DROP SCHEMA minion_test CASCADE');
 
 done_testing();
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Minion-10.13/t/pg_admin.t 
new/Minion-10.14/t/pg_admin.t
--- old/Minion-10.13/t/pg_admin.t       2020-06-19 22:08:42.000000000 +0200
+++ new/Minion-10.14/t/pg_admin.t       2020-10-24 18:15:08.000000000 +0200
@@ -12,8 +12,8 @@
 # Isolate tests
 require Mojo::Pg;
 my $pg = Mojo::Pg->new($ENV{TEST_ONLINE});
-$pg->db->query('drop schema if exists minion_admin_test cascade');
-$pg->db->query('create schema minion_admin_test');
+$pg->db->query('DROP SCHEMA IF EXISTS minion_admin_test CASCADE');
+$pg->db->query('CREATE SCHEMA minion_admin_test');
 plugin Minion => {Pg => $ENV{TEST_ONLINE}};
 app->minion->backend->pg->search_path(['minion_admin_test']);
 
@@ -33,8 +33,8 @@
 
 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('/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');
 };
 
@@ -124,6 +124,6 @@
 };
 
 # Clean up once we are done
-$pg->db->query('drop schema minion_admin_test cascade');
+$pg->db->query('DROP SCHEMA minion_admin_test CASCADE');
 
 done_testing();
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Minion-10.13/t/pg_lite_app.t 
new/Minion-10.14/t/pg_lite_app.t
--- old/Minion-10.13/t/pg_lite_app.t    2020-06-19 22:08:43.000000000 +0200
+++ new/Minion-10.14/t/pg_lite_app.t    2020-10-24 18:15:09.000000000 +0200
@@ -17,8 +17,8 @@
 # Isolate tests
 require Mojo::Pg;
 my $pg = Mojo::Pg->new($ENV{TEST_ONLINE});
-$pg->db->query('drop schema if exists minion_app_test cascade');
-$pg->db->query('create schema minion_app_test');
+$pg->db->query('DROP SCHEMA IF EXISTS minion_app_test CASCADE');
+$pg->db->query('CREATE SCHEMA minion_app_test');
 plugin Minion => {Pg => $pg->search_path(['minion_app_test'])};
 
 app->minion->add_task(
@@ -59,6 +59,6 @@
 };
 
 # Clean up once we are done
-$pg->db->query('drop schema minion_app_test cascade');
+$pg->db->query('DROP SCHEMA minion_app_test CASCADE');
 
 done_testing();
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Minion-10.13/t/pg_worker.t 
new/Minion-10.14/t/pg_worker.t
--- old/Minion-10.13/t/pg_worker.t      2020-06-19 22:08:42.000000000 +0200
+++ new/Minion-10.14/t/pg_worker.t      2020-10-24 18:15:09.000000000 +0200
@@ -7,12 +7,13 @@
 plan skip_all => 'set TEST_ONLINE to enable this test' unless 
$ENV{TEST_ONLINE};
 
 use Minion;
+use Mojo::IOLoop;
 
 # Isolate tests
 require Mojo::Pg;
 my $pg = Mojo::Pg->new($ENV{TEST_ONLINE});
-$pg->db->query('drop schema if exists minion_worker_test cascade');
-$pg->db->query('create schema minion_worker_test');
+$pg->db->query('DROP SCHEMA IF EXISTS minion_worker_test CASCADE');
+$pg->db->query('CREATE SCHEMA minion_worker_test');
 my $minion = Minion->new(Pg => $ENV{TEST_ONLINE});
 $minion->backend->pg->search_path(['minion_worker_test']);
 
@@ -24,6 +25,7 @@
     }
   );
   my $worker = $minion->worker;
+  $worker->status->{dequeue_timeout} = 0;
   $worker->on(
     dequeue => sub {
       my ($worker, $job) = @_;
@@ -38,6 +40,23 @@
   is_deeply $minion->job($id)->info->{result}, {just => 'works!'}, 'right 
result';
 };
 
+subtest 'Clean up event loop' => sub {
+  my $timer = 0;
+  Mojo::IOLoop->recurring(0 => sub { $timer++ });
+  my $worker = $minion->worker;
+  $worker->status->{dequeue_timeout} = 0;
+  $worker->on(
+    dequeue => sub {
+      my ($worker, $job) = @_;
+      $job->on(reap => sub { kill 'INT', $$ });
+    }
+  );
+  my $id = $minion->enqueue('test');
+  $worker->run;
+  is_deeply $minion->job($id)->info->{result}, {just => 'works!'}, 'right 
result';
+  is $timer, 0, 'timer has been cleaned up';
+};
+
 subtest 'Signals' => sub {
   $minion->add_task(
     int => sub {
@@ -69,12 +88,12 @@
   is $status->{dequeue_timeout},    5,   'right value';
   is $status->{heartbeat_interval}, 300, 'right value';
   is $status->{jobs},               4,   'right value';
-  is_deeply $status->{queues}, ['default'], 'right structure';
-  is $status->{performed}, 1, 'right value';
-  ok $status->{repair_interval}, 'has a value';
+  is_deeply $status->{queues},      ['default'], 'right structure';
+  is $status->{performed},          1, 'right value';
+  ok $status->{repair_interval},    'has a value';
 };
 
 # Clean up once we are done
-$pg->db->query('drop schema minion_worker_test cascade');
+$pg->db->query('DROP SCHEMA minion_worker_test CASCADE');
 
 done_testing();


Reply via email to