Hello community,

here is the log from the commit of package perl-Minion-Backend-SQLite for 
openSUSE:Factory checked in at 2020-08-05 20:27:09
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/perl-Minion-Backend-SQLite (Old)
 and      /work/SRC/openSUSE:Factory/.perl-Minion-Backend-SQLite.new.3592 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "perl-Minion-Backend-SQLite"

Wed Aug  5 20:27:09 2020 rev:8 rq:824357 version:5.0.3

Changes:
--------
--- 
/work/SRC/openSUSE:Factory/perl-Minion-Backend-SQLite/perl-Minion-Backend-SQLite.changes
    2020-07-28 17:30:07.098230131 +0200
+++ 
/work/SRC/openSUSE:Factory/.perl-Minion-Backend-SQLite.new.3592/perl-Minion-Backend-SQLite.changes
  2020-08-05 20:27:23.935044670 +0200
@@ -1,0 +2,16 @@
+Mon Aug  3 03:10:02 UTC 2020 - Tina Müller <[email protected]>
+
+- updated to 5.0.3
+   see /usr/share/doc/packages/perl-Minion-Backend-SQLite/Changes
+
+  v5.0.3    2020-08-02 18:15:20 EDT
+    - Minion requirement bumped to 10.13.
+    - Removed experimental support for job sequences.
+    - Added EXPERIMENTAL expire option to enqueue method to support expiring 
jobs.
+    - Added EXPERIMENTAL lax option to enqueue method to support lax 
dependencies.
+    - Removed next and previous fields from list_jobs method.
+    - Added expires and lax fields to list_jobs method.
+    - Fixed a bug where manual retries would count towards the attempts limit 
for automatic retries.
+    - Optimized checking parent job state in job dequeue.
+
+-------------------------------------------------------------------

Old:
----
  Minion-Backend-SQLite-v5.0.2.tar.gz

New:
----
  Minion-Backend-SQLite-v5.0.3.tar.gz

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

Other differences:
------------------
++++++ perl-Minion-Backend-SQLite.spec ++++++
--- /var/tmp/diff_new_pack.2pq1eu/_old  2020-08-05 20:27:25.291045100 +0200
+++ /var/tmp/diff_new_pack.2pq1eu/_new  2020-08-05 20:27:25.291045100 +0200
@@ -17,7 +17,7 @@
 
 
 Name:           perl-Minion-Backend-SQLite
-Version:        5.0.2
+Version:        5.0.3
 Release:        0
 %define cpan_name Minion-Backend-SQLite
 Summary:        SQLite backend for Minion job queue
@@ -30,13 +30,13 @@
 BuildRoot:      %{_tmppath}/%{name}-%{version}-build
 BuildRequires:  perl
 BuildRequires:  perl-macros
-BuildRequires:  perl(Minion) >= 10.10
+BuildRequires:  perl(Minion) >= 10.13
 BuildRequires:  perl(Module::Build::Tiny) >= 0.034
 BuildRequires:  perl(Module::Metadata)
 BuildRequires:  perl(Mojo::SQLite) >= 3.000
 BuildRequires:  perl(Mojolicious) >= 7.29
 BuildRequires:  perl(Test::More) >= 0.96
-Requires:       perl(Minion) >= 10.10
+Requires:       perl(Minion) >= 10.13
 Requires:       perl(Mojo::SQLite) >= 3.000
 Requires:       perl(Mojolicious) >= 7.29
 %{perl_requires}

++++++ Minion-Backend-SQLite-v5.0.2.tar.gz -> 
Minion-Backend-SQLite-v5.0.3.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Minion-Backend-SQLite-v5.0.2/Build.PL 
new/Minion-Backend-SQLite-v5.0.3/Build.PL
--- old/Minion-Backend-SQLite-v5.0.2/Build.PL   2020-07-23 06:30:48.000000000 
+0200
+++ new/Minion-Backend-SQLite-v5.0.3/Build.PL   2020-08-03 00:15:22.000000000 
+0200
@@ -84,13 +84,13 @@
         "Dan Book <dbook\@cpan.org>"
       ],
       "dist_name" => "Minion-Backend-SQLite",
-      "dist_version" => "v5.0.2",
+      "dist_version" => "v5.0.3",
       "license" => "artistic_2",
       "module_name" => "Minion::Backend::SQLite",
       "recursive_test_files" => 1,
       "requires" => {
         "List::Util" => 0,
-        "Minion" => "10.10",
+        "Minion" => "10.13",
         "Mojo::SQLite" => "3.000",
         "Mojolicious" => "7.29",
         "Sys::Hostname" => 0,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Minion-Backend-SQLite-v5.0.2/Changes 
new/Minion-Backend-SQLite-v5.0.3/Changes
--- old/Minion-Backend-SQLite-v5.0.2/Changes    2020-07-23 06:30:48.000000000 
+0200
+++ new/Minion-Backend-SQLite-v5.0.3/Changes    2020-08-03 00:15:22.000000000 
+0200
@@ -1,3 +1,13 @@
+v5.0.3    2020-08-02 18:15:20 EDT
+  - Minion requirement bumped to 10.13.
+  - Removed experimental support for job sequences.
+  - Added EXPERIMENTAL expire option to enqueue method to support expiring 
jobs.
+  - Added EXPERIMENTAL lax option to enqueue method to support lax 
dependencies.
+  - Removed next and previous fields from list_jobs method.
+  - Added expires and lax fields to list_jobs method.
+  - Fixed a bug where manual retries would count towards the attempts limit 
for automatic retries.
+  - Optimized checking parent job state in job dequeue.
+
 v5.0.2    2020-07-23 00:30:45 EDT
   - Minion requirement bumped to 10.10.
   - Support removing stuck jobs in repair method.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Minion-Backend-SQLite-v5.0.2/META.json 
new/Minion-Backend-SQLite-v5.0.3/META.json
--- old/Minion-Backend-SQLite-v5.0.2/META.json  2020-07-23 06:30:48.000000000 
+0200
+++ new/Minion-Backend-SQLite-v5.0.3/META.json  2020-08-03 00:15:22.000000000 
+0200
@@ -39,7 +39,7 @@
       "runtime" : {
          "requires" : {
             "List::Util" : "0",
-            "Minion" : "10.10",
+            "Minion" : "10.13",
             "Mojo::SQLite" : "3.000",
             "Mojolicious" : "7.29",
             "Sys::Hostname" : "0",
@@ -64,7 +64,7 @@
    "provides" : {
       "Minion::Backend::SQLite" : {
          "file" : "lib/Minion/Backend/SQLite.pm",
-         "version" : "v5.0.2"
+         "version" : "v5.0.3"
       }
    },
    "release_status" : "stable",
@@ -80,7 +80,7 @@
       },
       "x_IRC" : "irc://irc.freenode.net/#mojo"
    },
-   "version" : "v5.0.2",
+   "version" : "v5.0.3",
    "x_contributors" : [
       "Dan Book <[email protected]>",
       "yrjustice <[email protected]>"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Minion-Backend-SQLite-v5.0.2/META.yml 
new/Minion-Backend-SQLite-v5.0.3/META.yml
--- old/Minion-Backend-SQLite-v5.0.2/META.yml   2020-07-23 06:30:48.000000000 
+0200
+++ new/Minion-Backend-SQLite-v5.0.3/META.yml   2020-08-03 00:15:22.000000000 
+0200
@@ -26,10 +26,10 @@
 provides:
   Minion::Backend::SQLite:
     file: lib/Minion/Backend/SQLite.pm
-    version: v5.0.2
+    version: v5.0.3
 requires:
   List::Util: '0'
-  Minion: '10.10'
+  Minion: '10.13'
   Mojo::SQLite: '3.000'
   Mojolicious: '7.29'
   Sys::Hostname: '0'
@@ -40,7 +40,7 @@
   bugtracker: https://github.com/Grinnz/Minion-Backend-SQLite/issues
   homepage: https://github.com/Grinnz/Minion-Backend-SQLite
   repository: https://github.com/Grinnz/Minion-Backend-SQLite.git
-version: v5.0.2
+version: v5.0.3
 x_contributors:
   - 'Dan Book <[email protected]>'
   - 'yrjustice <[email protected]>'
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Minion-Backend-SQLite-v5.0.2/README 
new/Minion-Backend-SQLite-v5.0.3/README
--- old/Minion-Backend-SQLite-v5.0.2/README     2020-07-23 06:30:48.000000000 
+0200
+++ new/Minion-Backend-SQLite-v5.0.3/README     2020-08-03 00:15:22.000000000 
+0200
@@ -143,6 +143,21 @@
 
       Delay job for this many seconds (from now).
 
+    expire
+
+        expire => 300
+
+      Job is valid for this many seconds (from now) before it expires. Note
+      that this option is EXPERIMENTAL and might change without warning!
+
+    lax
+
+        lax => 1
+
+      Existing jobs this job depends on may also have transitioned to the
+      failed state to allow for it to be processed, defaults to false. Note
+      that this option is EXPERIMENTAL and might change without warning!
+
     notes
 
         notes => {foo => 'bar', baz => [1, 2, 3]}
@@ -169,14 +184,6 @@
 
       Queue to put job in, defaults to default.
 
-    sequence
-
-        sequence => 'host:mojolicious.org'
-
-      Sequence this job belongs to. The previous job from the sequence will
-      be automatically added as a parent to continue the sequence. Note
-      that this option is EXPERIMENTAL and might change without warning!
-
  fail_job
 
       my $bool = $backend->fail_job($job_id, $retries);
@@ -248,13 +255,6 @@
 
       List only jobs in these queues.
 
-    sequences
-
-        sequences => ['host:localhost', 'host:mojolicious.org']
-
-      List only jobs from these sequences. Note that this option is
-      EXPERIMENTAL and might change without warning!
-
     states
 
         states => ['inactive', 'active']
@@ -299,6 +299,12 @@
 
       Epoch time job was delayed to.
 
+    expires
+
+        expires => 784111777
+
+      Epoch time job is valid until before it expires.
+
     finished
 
         finished => 784111777
@@ -311,11 +317,12 @@
 
       Job id.
 
-    next
+    lax
 
-        next => 10024
+        lax => 0
 
-      Next job in sequence.
+      Existing jobs this job depends on may also have failed to allow for
+      it to be processed.
 
     notes
 
@@ -329,12 +336,6 @@
 
       Jobs this job depends on.
 
-    previous
-
-        previous => 10022
-
-      Previous job in sequence.
-
     priority
 
         priority => 3
@@ -365,12 +366,6 @@
 
       Number of times job has been retried.
 
-    sequence
-
-        sequence => 'host:mojolicious.org'
-
-      Sequence name.
-
     started
 
         started => 784111777
@@ -615,6 +610,21 @@
 
       Delay job for this many seconds (from now).
 
+    expire
+
+        expire => 300
+
+      Job is valid for this many seconds (from now) before it expires. Note
+      that this option is EXPERIMENTAL and might change without warning!
+
+    lax
+
+        lax => 1
+
+      Existing jobs this job depends on may also have transitioned to the
+      failed state to allow for it to be processed, defaults to false. Note
+      that this option is EXPERIMENTAL and might change without warning!
+
     parents
 
         parents => [$id1, $id2, $id3]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/Minion-Backend-SQLite-v5.0.2/lib/Minion/Backend/SQLite.pm 
new/Minion-Backend-SQLite-v5.0.3/lib/Minion/Backend/SQLite.pm
--- old/Minion-Backend-SQLite-v5.0.2/lib/Minion/Backend/SQLite.pm       
2020-07-23 06:30:48.000000000 +0200
+++ new/Minion-Backend-SQLite-v5.0.3/lib/Minion/Backend/SQLite.pm       
2020-08-03 00:15:22.000000000 +0200
@@ -8,7 +8,7 @@
 use Sys::Hostname 'hostname';
 use Time::HiRes 'usleep';
 
-our $VERSION = 'v5.0.2';
+our $VERSION = 'v5.0.3';
 
 has dequeue_interval => 0.5;
 has 'sqlite';
@@ -47,18 +47,17 @@
 sub enqueue {
   my ($self, $task, $args, $options) = (shift, shift, shift || [], shift || 
{});
 
-  my $db = $self->sqlite->db;
-  return _enqueue($db, $task, $args, $options) unless my $seq = 
$options->{sequence};
-
-  my $tx = $db->begin('exclusive');
-  my $prev = $db->query(
-    q{select id from minion_jobs where sequence = ? and next is null limit 1}, 
$seq)
-    ->hashes->first;
-  unshift @{$options->{parents}}, $prev->{id} if $prev;
-  my $id = _enqueue($db, $task, $args, $options);
-  $db->query(q{update minion_jobs set next = ? where id = ?}, $id, 
$prev->{id}) if $prev;
-  $tx->commit;
-  return $id;
+  return $self->sqlite->db->query(
+    q{insert into minion_jobs
+       (args, attempts, delayed, expires, lax, notes, parents, priority, 
queue, task)
+      values (?, ?, datetime('now', ? || ' seconds'),
+      case when ? is not null then datetime('now', ? || ' seconds') end,
+      ?, ?, ?, ?, ?, ?)},
+    {json => $args}, $options->{attempts} // 1, $options->{delay} // 0,
+    @$options{qw(expire expire)}, $options->{lax} ? 1 : 0, {json => 
$options->{notes} || {}},
+    {json => ($options->{parents} || [])}, $options->{priority} // 0,
+    $options->{queue} // 'default', $task
+  )->last_insert_id;
 }
 
 sub fail_job   { shift->_update(1, @_) }
@@ -122,11 +121,6 @@
     push @where, @$queues ? "queue in ($queues_in)" : 'queue is null';
     push @where_params, @$queues;
   }
-  if (defined(my $sequences = $options->{sequences})) {
-    my $sequences_in = join ',', ('?')x@$sequences;
-    push @where, @$sequences ? "sequence in ($sequences_in)" : 'sequence is 
null';
-    push @where_params, @$sequences;
-  }
   if (defined(my $states = $options->{states})) {
     my $states_in = join ',', ('?')x@$states;
     push @where, @$states ? "state in ($states_in)" : 'state is null';
@@ -137,6 +131,7 @@
     push @where, @$tasks ? "task in ($tasks_in)" : 'task is null';
     push @where_params, @$tasks;
   }
+  push @where, q{(state != 'inactive' or expires is null or expires > 
datetime('now'))};
 
   my $where_str = @where ? 'where ' . join(' and ', @where) : '';
 
@@ -146,10 +141,10 @@
          from minion_jobs as child, json_each(child.parents) as parent_id
          where j.id = parent_id.value) as children,
        strftime('%s',created) as created, strftime('%s',delayed) as delayed,
-       strftime('%s',finished) as finished, next, notes, parents,
-       (select id from minion_jobs where sequence = j.sequence and next = 
j.id) as previous,
-       priority, queue, result, strftime('%s',retried) as retried, retries,
-       sequence, strftime('%s',started) as started, state, task,
+       strftime('%s',expires) as expires, strftime('%s',finished) as finished,
+       lax, notes, parents, priority, queue, result,
+       strftime('%s',retried) as retried, retries,
+       strftime('%s',started) as started, state, task,
        strftime('%s','now') as time, worker
        from minion_jobs as j
        $where_str order by id desc limit ? offset ?},
@@ -302,6 +297,15 @@
       where notified < datetime('now', '-' || ? || ' seconds')}, 
$minion->missing_after
   );
 
+  # Old jobs with no unresolved dependencies and expired jobs
+  $db->query(
+    q{delete from minion_jobs
+      where (finished <= datetime('now', '-' || ? || ' seconds')
+      and state = 'finished' and id not in (select distinct parent_id.value
+        from minion_jobs as child, json_each(child.parents) as parent_id
+        where child.state <> 'finished'))
+      or (expires <= datetime('now') and state = 'inactive')}, 
$minion->remove_after);
+
   # Jobs with missing worker (can be retried)
   my $fail = $db->query(
     q{select id, retries from minion_jobs as j
@@ -315,14 +319,6 @@
     q{update minion_jobs set state = 'failed', result = json_quote('Job 
appears stuck in queue')
       where state = 'inactive' and delayed < datetime('now', '-' || ? || ' 
seconds')},
     $minion->stuck_after);
-
-  # Old jobs with no unresolved dependencies
-  $db->query(
-    q{delete from minion_jobs
-      where finished <= datetime('now', '-' || ? || ' seconds')
-      and state = 'finished' and id not in (select distinct parent_id.value
-        from minion_jobs as child, json_each(child.parents) as parent_id
-        where child.state <> 'finished')}, $minion->remove_after);
 }
 
 sub reset {
@@ -349,13 +345,15 @@
   return !!$self->sqlite->db->query(
     q{update minion_jobs
       set attempts = coalesce(?, attempts),
-        delayed = (datetime('now', ? || ' seconds')),
-        parents = coalesce(?, parents), priority = coalesce(?, priority),
+        delayed = datetime('now', ? || ' seconds'),
+        expires = case when ? is not null then datetime('now', ? || ' 
seconds') else expires end,
+        lax = coalesce(?, lax), parents = coalesce(?, parents), priority = 
coalesce(?, priority),
         queue = coalesce(?, queue), retried = datetime('now'),
         retries = retries + 1, state = 'inactive'
       where id = ? and retries = ?},
-    $options->{attempts}, $options->{delay} // 0, $parents,
-    @$options{qw(priority queue)}, $id, $retries
+    $options->{attempts}, $options->{delay} // 0, @$options{qw(expire expire)},
+    exists $options->{lax} ? $options->{lax} ? 1 : 0 : undef,
+    $parents, @$options{qw(priority queue)}, $id, $retries
   )->rows;
 }
 
@@ -363,7 +361,8 @@
   my $self = shift;
 
   my $stats = $self->sqlite->db->query(
-    q{select count(case state when 'inactive' then 1 end) as inactive_jobs,
+    q{select count(case when state = 'inactive' and (expires is null or 
expires > datetime('now'))
+        then 1 end) as inactive_jobs,
       count(case state when 'active' then 1 end) as active_jobs,
       count(case state when 'failed' then 1 end) as failed_jobs,
       count(case state when 'finished' then 1 end) as finished_jobs,
@@ -396,20 +395,6 @@
   shift->sqlite->db->query('delete from minion_workers where id = ?', shift);
 }
 
-sub _enqueue {
-  my ($db, $task, $args, $options) = @_;
-
-  return $db->query(
-    q{insert into minion_jobs
-       (args, attempts, delayed, notes, parents, priority, queue, sequence, 
task)
-      values (?, ?, (datetime('now', ? || ' seconds')), ?, ?, ?, ?, ?, ?)},
-    {json => $args}, $options->{attempts} // 1,
-    $options->{delay} // 0, {json => $options->{notes} || {}},
-    {json => ($options->{parents} || [])}, $options->{priority} // 0,
-    $options->{queue} // 'default', $options->{sequence}, $task
-  )->last_insert_id;
-}
-
 sub _try {
   my ($self, $id, $options) = @_;
 
@@ -426,10 +411,13 @@
        where delayed <= datetime('now') and id = coalesce(?, id)
        and (json_array_length(parents) = 0 or not exists (
          select 1 from minion_jobs as parent, json_each(j.parents) as parent_id
-         where parent.id = parent_id.value
-         and parent.state in ('inactive', 'active', 'failed')
-       )) and queue in ($queues_in) and state = 'inactive'
-       and task in ($tasks_in)
+         where parent.id = parent_id.value and case parent.state
+           when 'active' then 1
+           when 'failed' then not j.lax
+           when 'inactive' then (parent.expires is null or parent.expires > 
datetime('now'))
+         end
+       )) and queue in ($queues_in) and state = 'inactive' and task in 
($tasks_in)
+       and (expires is null or expires > datetime('now'))
        order by priority desc, id
        limit 1}, $options->{id}, @$queues, @$tasks
   );
@@ -460,10 +448,7 @@
   )->rows > 0;
   
   my $row = $db->query('select attempts from minion_jobs where id = ?', 
$id)->array;
-  return 1 if !$fail || (my $attempts = $row->[0]) == 1;
-  return 1 if $retries >= ($attempts - 1);
-  my $delay = $self->minion->backoff->($retries);
-  return $self->retry_job($id, $retries, {delay => $delay});
+  return $fail ? $self->auto_retry_job($id, $retries, $row->[0]) : 1;
 }
 
 1;
@@ -625,6 +610,21 @@
 
 Delay job for this many seconds (from now).
 
+=item expire
+
+  expire => 300
+
+Job is valid for this many seconds (from now) before it expires. Note that this
+option is B<EXPERIMENTAL> and might change without warning!
+
+=item lax
+
+  lax => 1
+
+Existing jobs this job depends on may also have transitioned to the C<failed>
+state to allow for it to be processed, defaults to C<false>. Note that this
+option is B<EXPERIMENTAL> and might change without warning!
+
 =item notes
 
   notes => {foo => 'bar', baz => [1, 2, 3]}
@@ -650,14 +650,6 @@
 
 Queue to put job in, defaults to C<default>.
 
-=item sequence
-
-  sequence => 'host:mojolicious.org'
-
-Sequence this job belongs to. The previous job from the sequence will be
-automatically added as a parent to continue the sequence. Note that this option
-is B<EXPERIMENTAL> and might change without warning!
-
 =back
 
 =head2 fail_job
@@ -737,13 +729,6 @@
 
 List only jobs in these queues.
 
-=item sequences
-
-  sequences => ['host:localhost', 'host:mojolicious.org']
-
-List only jobs from these sequences. Note that this option is B<EXPERIMENTAL>
-and might change without warning!
-
 =item states
 
   states => ['inactive', 'active']
@@ -792,6 +777,12 @@
 
 Epoch time job was delayed to.
 
+=item expires
+
+  expires => 784111777
+
+Epoch time job is valid until before it expires.
+
 =item finished
 
   finished => 784111777
@@ -804,11 +795,12 @@
 
 Job id.
 
-=item next
+=item lax
 
-  next => 10024
+  lax => 0
 
-Next job in sequence.
+Existing jobs this job depends on may also have failed to allow for it to be
+processed.
 
 =item notes
 
@@ -822,12 +814,6 @@
 
 Jobs this job depends on.
 
-=item previous
-
-  previous => 10022
-
-Previous job in sequence.
-
 =item priority
 
   priority => 3
@@ -858,12 +844,6 @@
 
 Number of times job has been retried.
 
-=item sequence
-
-  sequence => 'host:mojolicious.org'
-
-Sequence name.
-
 =item started
 
   started => 784111777
@@ -1137,6 +1117,21 @@
 
 Delay job for this many seconds (from now).
 
+=item expire
+
+  expire => 300
+
+Job is valid for this many seconds (from now) before it expires. Note that this
+option is B<EXPERIMENTAL> and might change without warning!
+
+=item lax
+
+  lax => 1
+
+Existing jobs this job depends on may also have transitioned to the C<failed>
+state to allow for it to be processed, defaults to C<false>. Note that this
+option is B<EXPERIMENTAL> and might change without warning!
+
 =item parents
 
   parents => [$id1, $id2, $id3]
@@ -1357,3 +1352,36 @@
 alter table minion_jobs add column next integer;
 create unique index minion_jobs_next on minion_jobs (next);
 create index minion_jobs_sequence_next on minion_jobs (sequence, next);
+
+-- 10 up
+create table minion_jobs_NEW (
+  id       integer not null primary key autoincrement,
+  args     text not null,
+  created  text not null default current_timestamp,
+  delayed  text not null,
+  finished text,
+  priority integer not null,
+  result   text,
+  retried  text,
+  retries  integer not null default 0,
+  started  text,
+  state    text not null default 'inactive',
+  task     text not null,
+  worker   integer,
+  queue    text not null default 'default',
+  attempts integer not null default 1,
+  parents  text not null default '[]',
+  notes    text not null
+    check(json_valid(notes) and json_type(notes) = 'object') default '{}',
+  expires  text,
+  lax      boolean not null default 0
+);
+insert into minion_jobs_NEW
+  (id,args,created,delayed,finished,priority,result,retried,retries,
+  started,state,task,worker,queue,attempts,parents,notes)
+  select id,args,created,delayed,finished,priority,result,retried,retries,
+  started,state,task,worker,queue,attempts,parents,notes from minion_jobs;
+drop table minion_jobs;
+alter table minion_jobs_NEW rename to minion_jobs;
+create index if not exists minion_jobs_state_priority_id on minion_jobs 
(state, priority desc, id);
+create index minion_jobs_expires on minion_jobs (expires);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Minion-Backend-SQLite-v5.0.2/prereqs.yml 
new/Minion-Backend-SQLite-v5.0.3/prereqs.yml
--- old/Minion-Backend-SQLite-v5.0.2/prereqs.yml        2020-07-23 
06:30:48.000000000 +0200
+++ new/Minion-Backend-SQLite-v5.0.3/prereqs.yml        2020-08-03 
00:15:22.000000000 +0200
@@ -2,7 +2,7 @@
   requires:
     perl: '5.010001'
     List::Util: 0
-    Minion: '10.10'
+    Minion: '10.13'
     Mojolicious: '7.29'
     Mojo::SQLite: '3.000'
     Sys::Hostname: 0
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Minion-Backend-SQLite-v5.0.2/t/00-report-prereqs.dd 
new/Minion-Backend-SQLite-v5.0.3/t/00-report-prereqs.dd
--- old/Minion-Backend-SQLite-v5.0.2/t/00-report-prereqs.dd     2020-07-23 
06:30:48.000000000 +0200
+++ new/Minion-Backend-SQLite-v5.0.3/t/00-report-prereqs.dd     2020-08-03 
00:15:22.000000000 +0200
@@ -14,7 +14,7 @@
        'runtime' => {
                       'requires' => {
                                       'List::Util' => '0',
-                                      'Minion' => '10.10',
+                                      'Minion' => '10.13',
                                       'Mojo::SQLite' => '3.000',
                                       'Mojolicious' => '7.29',
                                       'Sys::Hostname' => '0',
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Minion-Backend-SQLite-v5.0.2/t/sqlite.t 
new/Minion-Backend-SQLite-v5.0.3/t/sqlite.t
--- old/Minion-Backend-SQLite-v5.0.2/t/sqlite.t 2020-07-23 06:30:48.000000000 
+0200
+++ new/Minion-Backend-SQLite-v5.0.3/t/sqlite.t 2020-08-03 00:15:22.000000000 
+0200
@@ -21,9 +21,9 @@
 };
 
 subtest 'Migrate up and down' => sub {
-  is $minion->backend->sqlite->migrations->active, 9, 'active version is 9';
+  is $minion->backend->sqlite->migrations->active, 10, 'active version is 10';
   is $minion->backend->sqlite->migrations->migrate(0)->active, 0, 'active 
version is 0';
-  is $minion->backend->sqlite->migrations->migrate->active, 9, 'active version 
is 9';
+  is $minion->backend->sqlite->migrations->migrate->active, 10, 'active 
version is 10';
 };
 
 subtest 'Register and unregister' => sub {
@@ -49,7 +49,7 @@
   my $id     = $minion->enqueue('test');
   my (@finished, @failed);
   my $promise = $minion->result_p($id, {interval => 0})->then(sub { @finished 
= @_ })->catch(sub { @failed = @_ });
-  my $job     = $worker->dequeue(0);
+  ok my $job = $worker->dequeue(0), 'job dequeued';
   is $job->id, $id, 'same id';
   Mojo::IOLoop->one_tick;
   is_deeply \@finished, [], 'not finished';
@@ -65,7 +65,7 @@
   (@finished, @failed) = ();
   my $id2 = $minion->enqueue('test');
   $promise = $minion->result_p($id2, {interval => 0})->then(sub { @finished = 
@_ })->catch(sub { @failed = @_ });
-  $job     = $worker->dequeue(0);
+  ok $job = $worker->dequeue(0), 'job dequeued';
   is $job->id, $id2, 'same id';
   $job->fail({works => 'too!'});
   $promise->wait;
@@ -102,7 +102,7 @@
   my $worker2 = $minion->worker->register;
   isnt $worker2->id, $worker->id, 'new id';
   my $id = $minion->enqueue('test');
-  my $job = $worker2->dequeue(0);
+  ok my $job = $worker2->dequeue(0), 'job dequeued';
   is $job->id, $id, 'right id';
   is $worker2->info->{jobs}[0], $job->id, 'right id';
   $id = $worker2->id;
@@ -125,7 +125,7 @@
   plan skip_all => 'Minion workers do not support fork emulation' if 
HAS_PSEUDOFORK;
   my $worker = $minion->worker->register;
   my $id  = $minion->enqueue('test');
-  my $job = $worker->dequeue(0);
+  ok my $job = $worker->dequeue(1), 'job dequeued';
   is $job->id, $id, 'right id';
   $worker->unregister;
   $minion->repair;
@@ -137,7 +137,7 @@
   plan skip_all => 'Minion workers do not support fork emulation' if 
HAS_PSEUDOFORK;
   my $worker = $minion->worker->register;
   my $id = $minion->enqueue('test', [], {queue => 'minion_foreground'});
-  my $job = $worker->dequeue(0, {queues => ['minion_foreground']});
+  ok my $job = $worker->dequeue(0, {queues => ['minion_foreground']}), 'job 
dequeued';
   is $job->id, $id, 'right id';
   $worker->unregister;
   $minion->repair;
@@ -183,7 +183,7 @@
     $minion->stuck_after + 1, $_)
     for $id, $id2, $id3, $id4;
   ok $worker->dequeue(0, {id => $id4})->finish('Works!'), 'job finished';
-  my $job2 = $worker->dequeue(0, {id => $id2});
+  ok my $job2 = $worker->dequeue(0, {id => $id2}), 'job dequeued';
   $minion->repair;
   is $job2->info->{state}, 'active', 'job is still active';
   ok $job2->finish, 'job finished';
@@ -276,7 +276,10 @@
   ok $minion->unlock('foo'), 'unlocked';
   ok !$minion->unlock('foo'), 'not unlocked again';
   ok $minion->lock('foo', -3600), 'locked';
-  ok $minion->lock('foo', 3600),  'locked again';
+  ok $minion->lock('foo', 0),     'locked again';
+  ok !$minion->is_locked('foo'), 'lock does not exist';
+  ok $minion->lock('foo', 3600), 'locked again';
+  ok $minion->is_locked('foo'), 'lock exists';
   ok !$minion->lock('foo', -3600), 'not locked again';
   ok !$minion->lock('foo', 3600),  'not locked again';
   ok $minion->unlock('foo'), 'unlocked';
@@ -286,8 +289,9 @@
 };
 
 subtest 'Shared lock' => sub {
-  ok $minion->lock('bar', 3600,  {limit => 3}), 'locked';
-  ok $minion->lock('bar', 3600,  {limit => 3}), 'locked again';
+  ok $minion->lock('bar', 3600, {limit => 3}), 'locked';
+  ok $minion->lock('bar', 3600, {limit => 3}), 'locked again';
+  ok $minion->is_locked('bar'), 'lock exists';
   ok $minion->lock('bar', -3600, {limit => 3}), 'locked again';
   ok $minion->lock('bar', 3600,  {limit => 3}), 'locked again';
   ok !$minion->lock('bar', 3600, {limit => 2}), 'not locked again';
@@ -297,7 +301,8 @@
   ok $minion->unlock('bar'), 'unlocked again';
   ok $minion->unlock('bar'), 'unlocked again';
   ok $minion->unlock('bar'), 'unlocked again';
-  ok !$minion->unlock('bar'), 'not unlocked again';
+  ok !$minion->unlock('bar'),    'not unlocked again';
+  ok !$minion->is_locked('bar'), 'lock does not exist';
   ok $minion->unlock('baz'), 'unlocked';
   ok !$minion->unlock('baz'), 'not unlocked again';
 };
@@ -417,8 +422,8 @@
   is $minion->stats->{inactive_jobs}, 2, 'two inactive jobs';
   my $job;
   SKIP: {
-    skip 'Minion workers do not support fork emulation', 3 if HAS_PSEUDOFORK;
-    $job      = $worker->dequeue(0);
+    skip 'Minion workers do not support fork emulation', 4 if HAS_PSEUDOFORK;
+    ok $job = $worker->dequeue(0), 'job dequeued';
     my $stats = $minion->stats;
     is $stats->{active_workers}, 1, 'one active worker';
     is $stats->{active_jobs},    1, 'one active job';
@@ -426,8 +431,8 @@
   }
   $minion->enqueue('fail');
   SKIP: {
-    skip 'Minion workers do not support fork emulation', 18 if HAS_PSEUDOFORK;
-    my $job2 = $worker->dequeue(0);
+    skip 'Minion workers do not support fork emulation', 20 if HAS_PSEUDOFORK;
+    ok my $job2 = $worker->dequeue(0), 'job dequeued';
     my $stats = $minion->stats;
     is $stats->{active_workers}, 1, 'one active worker';
     is $stats->{active_jobs},    2, 'two active jobs';
@@ -435,7 +440,7 @@
     ok $job2->finish, 'job finished';
     ok $job->finish,  'job finished';
     is $minion->stats->{finished_jobs}, 2, 'two finished jobs';
-    my $job = $worker->dequeue(0);
+    ok my $job = $worker->dequeue(0), 'job dequeued';
     ok $job->fail, 'job failed';
     is $minion->stats->{failed_jobs}, 1, 'one failed job';
     ok $job->retry, 'job retried';
@@ -457,7 +462,7 @@
   plan skip_all => 'Minion workers do not support fork emulation' if 
HAS_PSEUDOFORK;
   $minion->enqueue('fail');
   my $worker = $minion->worker->register;
-  my $job    = $worker->dequeue(0);
+  ok my $job = $worker->dequeue(0), 'job dequeued';
   ok $job->fail, 'job failed';
   $worker->unregister;
   my $history = $minion->history;
@@ -628,11 +633,11 @@
   is $info->{priority}, 0,          'right priority';
   is $info->{state},    'inactive', 'right state';
   SKIP: {
-    skip 'Minion workers do not support fork emulation', 19 if HAS_PSEUDOFORK;
+    skip 'Minion workers do not support fork emulation', 20 if HAS_PSEUDOFORK;
     my $worker = $minion->worker;
     is $worker->dequeue(0), undef, 'not registered';
     ok !$minion->job($id)->info->{started}, 'no started timestamp';
-    my $job = $worker->register->dequeue(0);
+    ok my $job = $worker->register->dequeue(0), 'job dequeued';
     is $worker->info->{jobs}[0], $job->id, 'right job';
     like $job->info->{created}, qr/^[\d.]+$/, 'has created timestamp';
     like $job->info->{started}, qr/^[\d.]+$/, 'has started timestamp';
@@ -662,7 +667,7 @@
   plan skip_all => 'Minion workers do not support fork emulation' if 
HAS_PSEUDOFORK;
   my $id = $minion->enqueue(add => [5, 6]);
   my $worker = $minion->worker->register;
-  my $job = $worker->dequeue(0);
+  ok my $job = $worker->dequeue(0), 'job dequeued';
   is $job->info->{attempts}, 1, 'job will be attempted once';
   is $job->info->{retries}, 0, 'job has not been retried';
   is $job->id, $id, 'right id';
@@ -674,12 +679,12 @@
   like $job->info->{retried}, qr/^[\d.]+$/, 'has retried timestamp';
   is $job->info->{state},     'inactive',   'right state';
   is $job->info->{retries},   1,            'job has been retried once';
-  $job = $worker->dequeue(0);
+  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';
   is $job->info->{retries}, 2, 'job has been retried twice';
-  $job = $worker->dequeue(0);
+  ok $job = $worker->dequeue(0), 'job dequeued';
   is $job->info->{state}, 'active', 'right state';
   ok $job->finish, 'job finished';
   ok $job->remove, 'job has been removed';
@@ -692,7 +697,7 @@
   ok $job->retry, 'job retried';
   is $job->info->{state},   'inactive', 'right state';
   is $job->info->{retries}, 1,          'job has been retried once';
-  $job = $worker->dequeue(0);
+  ok $job = $worker->dequeue(0), 'job dequeued';
   is $job->id, $id, 'right id';
   ok $job->fail,   'job failed';
   ok $job->remove, 'job has been removed';
@@ -708,24 +713,24 @@
   $minion->enqueue(add => [1, 2]);
   my $id = $minion->enqueue(add => [2, 4], {priority => 1});
   my $worker = $minion->worker->register;
-  my $job = $worker->dequeue(0);
+  ok my $job = $worker->dequeue(0), 'job dequeued';
   is $job->id, $id, 'right id';
   is $job->info->{priority}, 1, 'right priority';
   ok $job->finish, 'job finished';
   isnt $worker->dequeue(0)->id, $id, 'different id';
   $id = $minion->enqueue(add => [2, 5]);
-  $job = $worker->register->dequeue(0);
+  ok $job = $worker->register->dequeue(0), 'job dequeued';
   is $job->id, $id, 'right id';
   is $job->info->{priority}, 0, 'right priority';
   ok $job->finish, 'job finished';
   ok $job->retry({priority => 100}), 'job retried with higher priority';
-  $job = $worker->dequeue(0);
+  ok $job = $worker->dequeue(0), 'job dequeued';
   is $job->id, $id, 'right id';
   is $job->info->{retries},  1,   'job has been retried once';
   is $job->info->{priority}, 100, 'high priority';
   ok $job->finish, 'job finished';
   ok $job->retry({priority => 0}), 'job retried with lower priority';
-  $job = $worker->dequeue(0);
+  ok $job = $worker->dequeue(0), 'job dequeued';
   is $job->id, $id, 'right id';
   is $job->info->{retries},  2, 'job has been retried twice';
   is $job->info->{priority}, 0, 'low priority';
@@ -737,14 +742,14 @@
   my $id = $minion->enqueue(add => [2, 1] => {delay => 100});
   is $minion->stats->{delayed_jobs}, 1, 'one delayed job';
   SKIP: {
-    skip 'Minion workers do not support fork emulation', 15 if HAS_PSEUDOFORK;
+    skip 'Minion workers do not support fork emulation', 17 if HAS_PSEUDOFORK;
     my $worker = $minion->worker->register;
     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->sqlite->db->query(
       q{update minion_jobs set delayed = datetime('now','-1 day') where id = 
?}, $id);
-    $job = $worker->dequeue(0);
+    ok $job = $worker->dequeue(0), 'job dequeued';
     is $job->id, $id, 'right id';
     like $job->info->{delayed}, qr/^[\d.]+$/, 'has delayed timestamp';
     ok $job->finish, 'job finished';
@@ -754,7 +759,7 @@
     ok $job->remove, 'job removed';
     ok !$job->retry, 'job not retried';
     my $id = $minion->enqueue(add => [6, 9]);
-    $job = $worker->dequeue(0);
+    ok $job = $worker->dequeue(0), 'job dequeued';
     $info = $minion->job($id)->info;
     ok $info->{delayed} <= $info->{created}, 'no delayed timestamp';
     ok $job->fail, 'job failed';
@@ -811,7 +816,7 @@
   my $id     = $minion->enqueue(add => [3, 3]);
   is $enqueue, $id, 'enqueue event has been emitted';
   $minion->enqueue(add => [4, 3]);
-  my $job = $worker->dequeue(0);
+  ok my $job = $worker->dequeue(0), 'job dequeued';
   is $failed,   0, 'failed event has not been emitted';
   is $finished, 0, 'finished event has not been emitted';
   my $result;
@@ -824,7 +829,7 @@
   isnt $pid_start, $$,      'new process id';
   isnt $pid_stop,  $$,      'new process id';
   is $pid_start, $pid_stop, 'same process id';
-  $job = $worker->dequeue(0);
+  ok $job = $worker->dequeue(0), 'job dequeued';
   my $err;
   $job->on(failed => sub { $err = pop });
   $job->fail("test\n");
@@ -834,7 +839,7 @@
   is $finished, 1,        'finished event has been emitted once';
   $minion->add_task(switcheroo => sub { });
   $minion->enqueue(switcheroo => [5, 3] => {notes => {finish_count => 0, 
before => 23}});
-  $job = $worker->dequeue(0);
+  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';
@@ -852,18 +857,18 @@
   my $id = $minion->enqueue(add => [100, 1]);
   my $worker = $minion->worker->register;
   is $worker->dequeue(0 => {queues => ['test1']}), undef, 'wrong queue';
-  my $job = $worker->dequeue(0);
+  ok my $job = $worker->dequeue(0), 'job dequeued';
   is $job->id, $id, 'right id';
   is $job->info->{queue}, 'default', 'right queue';
   ok $job->finish, 'job finished';
   $id = $minion->enqueue(add => [100, 3] => {queue => 'test1'});
   is $worker->dequeue(0), undef, 'wrong queue';
-  $job = $worker->dequeue(0 => {queues => ['test1']});
+  ok $job = $worker->dequeue(0 => {queues => ['test1']}), 'job dequeued';
   is $job->id, $id, 'right id';
   is $job->info->{queue}, 'test1', 'right queue';
   ok $job->finish, 'job finished';
   ok $job->retry({queue => 'test2'}), 'job retried';
-  $job = $worker->dequeue(0 => {queues => ['default', 'test2']});
+  ok $job = $worker->dequeue(0 => {queues => ['default', 'test2']}), 'job 
dequeued';
   is $job->id, $id, 'right id';
   is $job->info->{queue}, 'test2', 'right queue';
   ok $job->finish, 'job finished';
@@ -874,7 +879,7 @@
   plan skip_all => 'Minion workers do not support fork emulation' if 
HAS_PSEUDOFORK;
   my $id = $minion->enqueue(add => [5, 6]);
   my $worker = $minion->worker->register;
-  my $job = $worker->dequeue(0);
+  ok my $job = $worker->dequeue(0), 'job dequeued';
   is $job->id, $id, 'right id';
   is $job->info->{result}, undef, 'no result';
   ok $job->fail, 'job failed';
@@ -882,13 +887,13 @@
   is $job->info->{state},  'failed',        'right state';
   is $job->info->{result}, 'Unknown error', 'right result';
   $id = $minion->enqueue(add => [6, 7]);
-  $job = $worker->dequeue(0);
+  ok $job = $worker->dequeue(0), 'job dequeued';
   is $job->id, $id, 'right id';
   ok $job->fail('Something bad happened!'), 'job failed';
   is $job->info->{state}, 'failed', 'right state';
   is $job->info->{result}, 'Something bad happened!', 'right result';
   $id  = $minion->enqueue('fail');
-  $job = $worker->dequeue(0);
+  ok $job = $worker->dequeue(0), 'job dequeued';
   is $job->id, $id, 'right id';
   $job->perform;
   is $job->info->{state}, 'failed', 'right state';
@@ -908,7 +913,7 @@
   );
   $minion->enqueue('nested', [{first => [{second => 'test'}]}, [[3]]], {notes 
=> {foo => [4, 5, 6]}});
   my $worker = $minion->worker->register;
-  my $job = $worker->dequeue(0);
+  ok my $job = $worker->dequeue(0), 'job dequeued';
   $job->perform;
   is $job->info->{state}, 'finished', 'right state';
   ok $job->note(yada => ['works']), 'added metadata';
@@ -935,7 +940,7 @@
   $minion->add_task(exit => sub { exit 1 });
   my $id  = $minion->enqueue('exit');
   my $worker = $minion->worker->register;
-  my $job = $worker->dequeue(0);
+  ok my $job = $worker->dequeue(0), 'job dequeued';
   is $job->id, $id, 'right id';
   $job->perform;
   is $job->info->{state}, 'failed', 'right state';
@@ -952,36 +957,61 @@
   is $minion->backoff->(5),  640,    'right result';
   is $minion->backoff->(25), 390640, 'right result';
   SKIP: {
-    skip 'Minion workers do not support fork emulation', 16 if HAS_PSEUDOFORK;
-    my $id = $minion->enqueue(exit => [] => {attempts => 2});
+    skip 'Minion workers do not support fork emulation', 31 if HAS_PSEUDOFORK;
+
+    my $id = $minion->enqueue(exit => [] => {attempts => 3});
     my $worker = $minion->worker->register;
-    my $job = $worker->dequeue(0);
+    ok my $job = $worker->dequeue(0), 'job dequeued';
     is $job->id, $id, 'right id';
     is $job->retries, 0, 'job has not been retried';
-    $job->perform;
     my $info = $job->info;
-    is $info->{attempts}, 2,          'job will be attempted twice';
+    is $info->{attempts}, 3,        'three attempts';
+    is $info->{state},    'active', 'right state';
+    $job->perform;
+    $info = $job->info;
+    is $info->{attempts}, 2,          'two attempts';
     is $info->{state},    'inactive', 'right state';
     ok $info->{result},   'error message in result';
     ok $info->{retried} < $info->{delayed}, 'delayed timestamp';
+
     $minion->backend->sqlite->db->query(
       q{update minion_jobs set delayed = datetime('now') where id = ?}, $id);
-    $job = $worker->register->dequeue(0);
+    ok $job = $worker->dequeue(0), 'job dequeued';
     is $job->id, $id, 'right id';
-    is $job->retries, 1, 'job has been retried once';
+    is $job->retries, 1, 'job has been retried';
+    $info = $job->info;
+    is $info->{attempts}, 2,        'two attempts';
+    is $info->{state},    'active', 'right state';
     $job->perform;
     $info = $job->info;
-    is $info->{attempts}, 2,        'job will be attempted twice';
-    is $info->{state},    'failed', 'right state';
-    ok $info->{result},   'error message in result';
-    ok $job->retry({attempts => 3}), 'job retried';
-    $job = $worker->register->dequeue(0);
+    is $info->{attempts}, 1,          'one attempt';
+    is $info->{state},    'inactive', 'right state';
+
+    $minion->backend->sqlite->db->query(
+      q{update minion_jobs set delayed = datetime('now') where id = ?}, $id);
+    ok $job = $worker->register->dequeue(0), 'job dequeued';
     is $job->id, $id, 'right id';
+    is $job->retries, 2, 'two retries';
+    $info = $job->info;
+    is $info->{attempts}, 1,        'one attempt';
+    is $info->{state},    'active', 'right state';
     $job->perform;
     $info = $job->info;
-    is $info->{attempts}, 3,        'job will be attempted three times';
+    is $info->{attempts}, 1,        'one attempt';
     is $info->{state},    'failed', 'right state';
     ok $info->{result},   'error message in result';
+
+    ok $job->retry({attempts => 2}), 'job retried';
+    ok $job = $worker->register->dequeue(0), 'job dequeued';
+    is $job->id, $id, 'right id';
+    $job->perform;
+    is $job->info->{state}, 'inactive', 'right state';
+    $minion->backend->sqlite->db->query(
+      q{update minion_jobs set delayed = datetime('now') where id = ?}, $id);
+    ok $job = $worker->register->dequeue(0), 'job dequeued';
+    is $job->id, $id, 'right id';
+    $job->perform;
+    is $job->info->{state}, 'failed', 'right state';
     $worker->unregister;
   }
 };
@@ -990,7 +1020,7 @@
   plan skip_all => 'Minion workers do not support fork emulation' if 
HAS_PSEUDOFORK;
   my $id = $minion->enqueue(exit => [] => {attempts => 2});
   my $worker = $minion->worker->register;
-  my $job = $worker->dequeue(0);
+  ok my $job = $worker->dequeue(0), 'job dequeued';
   is $job->id, $id, 'right id';
   is $job->retries, 0, 'job has not been retried';
   is $job->info->{attempts}, 2,        'job will be attempted twice';
@@ -1002,7 +1032,7 @@
   ok $job->info->{retried} < $job->info->{delayed}, 'delayed timestamp';
   $minion->backend->sqlite->db->query(
     q{update minion_jobs set delayed = datetime('now') where id = ?}, $id);
-  $job = $worker->register->dequeue(0);
+  ok $job = $worker->register->dequeue(0), 'job dequeued';
   is $job->id, $id, 'right id';
   is $job->retries, 1, 'job has been retried once';
   $worker->unregister;
@@ -1016,13 +1046,13 @@
   $minion->add_task(restart => sub { });
   my $id  = $minion->enqueue('restart');
   my $worker = $minion->worker->register;
-  my $job = $worker->dequeue(0);
+  ok my $job = $worker->dequeue(0), 'job dequeued';
   is $job->id, $id, 'right id';
   ok $job->finish, 'job finished';
   is $job->info->{state}, 'finished', 'right state';
   ok $job->retry, 'job retried';
   is $job->info->{state}, 'inactive', 'right state';
-  my $job2 = $worker->dequeue(0);
+  ok my $job2 = $worker->dequeue(0), 'job dequeued';
   is $job->info->{state}, 'active', 'right state';
   ok !$job->finish, 'job not finished';
   is $job->info->{state}, 'active', 'right state';
@@ -1040,10 +1070,10 @@
   my $id3 = $minion->enqueue('test');
   my $id4 = $minion->enqueue('exit');
   my $worker = $minion->worker->register;
-  my $job    = $worker->dequeue(0);
-  my $job2   = $worker->dequeue(0);
-  my $job3 = $worker->dequeue(0);
-  my $job4 = $worker->dequeue(0);
+  ok my $job  = $worker->dequeue(0), 'job dequeued';
+  ok my $job2 = $worker->dequeue(0), 'job dequeued';
+  ok my $job3 = $worker->dequeue(0), 'job dequeued';
+  ok my $job4 = $worker->dequeue(0), 'job dequeued';
   my $pid = $job->start;
   my $pid2 = $job2->start;
   my $pid3 = $job3->start;
@@ -1075,7 +1105,7 @@
   );
   my $worker = $minion->worker->register;
   $minion->enqueue('long_running');
-  my $job = $worker->dequeue(0);
+  ok my $job = $worker->dequeue(0), 'job dequeued';
   ok $job->start->pid, 'has a process id';
   ok !$job->is_finished, 'job is not finished';
   $job->stop;
@@ -1083,7 +1113,7 @@
   is $job->info->{state},  'failed', 'right state';
   ok $job->info->{result}, 'error message in result';
   $minion->enqueue('long_running');
-  $job = $worker->dequeue(0);
+  ok $job = $worker->dequeue(0), 'job dequeued';
   ok $job->start->pid, 'has a process id';
   ok !$job->is_finished, 'job is not finished';
   usleep 5000 until $job->info->{notes}{started};
@@ -1104,11 +1134,11 @@
   my $id  = $minion->enqueue('test');
   my $id2 = $minion->enqueue('test');
   my $id3 = $minion->enqueue(test => [] => {parents => [$id, $id2]});
-  my $job = $worker->dequeue(0);
+  ok my $job = $worker->dequeue(0), 'job dequeued';
   is $job->id, $id, 'right id';
   is_deeply $job->info->{children}, [$id3], 'right children';
   is_deeply $job->info->{parents}, [], 'right parents';
-  my $job2 = $worker->dequeue(0);
+  ok my $job2 = $worker->dequeue(0), 'job dequeued';
   is $job2->id, $id2, 'right id';
   is_deeply $job2->info->{children}, [$id3], 'right children';
   is_deeply $job2->info->{parents}, [], 'right parents';
@@ -1118,10 +1148,10 @@
   ok $job2->fail, 'job failed';
   ok !$worker->dequeue(0), 'parents are not ready yet';
   ok $job2->retry, 'job retried';
-  $job2 = $worker->dequeue(0);
+  ok $job2 = $worker->dequeue(0), 'job dequeued';
   is $job2->id, $id2, 'right id';
   ok $job2->finish, 'job finished';
-  $job = $worker->dequeue(0);
+  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';
@@ -1129,104 +1159,155 @@
   is $minion->repair->stats->{finished_jobs}, 2, 'two finished jobs';
   ok $job->finish, 'job finished';
   is $minion->stats->{finished_jobs}, 3, 'three finished jobs';
-  is $minion->repair->stats->{finished_jobs}, 0, 'no finished jobs';
+  is $minion->repair->remove_after(172800)->stats->{finished_jobs}, 0, 'no 
finished jobs';
   $id = $minion->enqueue(test => [] => {parents => [-1]});
-  $job = $worker->dequeue(0);
+  ok $job = $worker->dequeue(0), 'job dequeued';
   is $job->id, $id, 'right id';
   ok $job->finish, 'job finished';
   $id = $minion->enqueue(test => [] => {parents => [-1]});
-  $job = $worker->dequeue(0);
+  ok $job = $worker->dequeue(0), 'job dequeued';
   is $job->id, $id, 'right id';
   is_deeply $job->info->{parents}, [-1], 'right parents';
   $job->retry({parents => [-1, -2]});
-  $job = $worker->dequeue(0);
+  ok $job = $worker->dequeue(0), 'job dequeued';
   is $job->id, $id, 'right id';
   is_deeply $job->info->{parents}, [-1, -2], 'right parents';
   ok $job->finish, 'job finished';
+
+  my $id4     = $minion->enqueue('test');
+  my $id5     = $minion->enqueue('test');
+  my $id6     = $minion->enqueue(test => [] => {parents => [$id4, $id5]});
+  my $child   = $minion->job($id6);
+  my $parents = $child->parents;
+  is $parents->size, 2, 'two parents';
+  is $parents->[0]->id, $id4, 'first parent';
+  is $parents->[1]->id, $id5, 'second parent';
+  $_->remove for $parents->each;
+  is $child->parents->size, 0, 'no parents';
+  ok $child->remove, 'job removed';
   $worker->unregister;
 };
 
-subtest 'Sequences' => sub {
+subtest 'Job dependencies (lax)' => sub {
   plan skip_all => 'Minion workers do not support fork emulation' if 
HAS_PSEUDOFORK;
   my $worker = $minion->worker->register;
-  my $id     = $minion->enqueue('test' => [] => {sequence => 
'host:localhost'});
-  is $minion->job($id)->info->{previous}, undef, 'new sequence';
-  is $minion->job($id)->info->{next},     undef, 'new sequence';
-  my $id2 = $minion->enqueue('test' => [] => {sequence => 'host:localhost'});
-  is $minion->job($id2)->info->{previous}, $id,  'sequence in progress';
-  is $minion->job($id)->info->{next},      $id2, 'sequence in progress';
-  my $id3 = $minion->enqueue('test' => [] => {sequence => 'host:localhost', 
priority => 5});
-  is $minion->job($id3)->info->{previous}, $id2, 'sequence in progress';
-  is $minion->job($id)->info->{next},      $id2, 'sequence in progress';
-  my $job = $worker->dequeue(0);
-  is $job->id, $id, 'right id';
-  is $job->info->{sequence}, 'host:localhost', 'right sequence';
-  is $job->info->{priority}, 0,                'right priority';
-  is_deeply $job->info->{children}, [$id2], 'right children';
-  is_deeply $job->info->{parents}, [], 'no parents';
-  ok $job->finish, 'job finished';
-  my $job2 = $worker->dequeue(0);
+  my $id     = $minion->enqueue('test');
+  my $id2    = $minion->enqueue('test');
+  my $id3    = $minion->enqueue(test => [] => {lax => 1, parents => [$id, 
$id2]});
+  ok my $job = $worker->dequeue(0), 'job dequeued';
+  is $job->id, $id, 'right id';
+  is_deeply $job->info->{children}, [$id3], 'right children';
+  is_deeply $job->info->{parents}, [], 'right parents';
+  ok my $job2 = $worker->dequeue(0), 'job dequeued';
   is $job2->id, $id2, 'right id';
-  is $job2->info->{sequence}, 'host:localhost', 'right sequence';
-  is $job2->info->{previous}, $id,  'sequence in progress';
-  is $job2->info->{next},     $id3, 'sequence in progress';
-  is $job2->info->{priority}, 0, 'right priority';
   is_deeply $job2->info->{children}, [$id3], 'right children';
-  is_deeply $job2->info->{parents},  [$id],  'right parents';
-  ok $job2->finish, 'job finished';
-  my $job3 = $worker->dequeue(0);
+  is_deeply $job2->info->{parents}, [], 'right parents';
+  ok !$worker->dequeue(0), 'parents are not ready yet';
+  ok $job->finish, 'job finished';
+  ok !$worker->dequeue(0), 'parents are not ready yet';
+  ok $job2->fail, 'job failed';
+  ok my $job3 = $worker->dequeue(0), 'job dequeued';
   is $job3->id, $id3, 'right id';
-  is $job3->info->{sequence}, 'host:localhost', 'right sequence';
-  is $job3->info->{previous}, $id2, 'sequence in progress';
-  is $job3->info->{next},     undef, 'sequence is ending for now';
-  is $job3->info->{priority}, 5,     'right priority';
-  is_deeply $job3->info->{children}, [], 'no children';
-  is_deeply $job3->info->{parents}, [$id2], 'right parents';
+  is_deeply $job3->info->{children}, [], 'right children';
+  is_deeply $job3->info->{parents}, [$id, $id2], 'right parents';
   ok $job3->finish, 'job finished';
 
-  my $id4 = $minion->enqueue('test' => [] => {sequence => 'host:localhost'});
-  is_deeply $job3->info->{children}, [$id4], 'right children';
-  my $job4 = $worker->dequeue(0);
+  my $id4 = $minion->enqueue('test');
+  my $id5 = $minion->enqueue(test => [] => {parents => [$id4]});
+  ok my $job4 = $worker->dequeue(0), 'job dequeued';
   is $job4->id, $id4, 'right id';
-  is $job4->info->{sequence}, 'host:localhost', 'right sequence';
-  is_deeply $job4->info->{children}, [], 'no children';
-  is_deeply $job4->info->{parents}, [$id3], 'right parents';
-  ok $job4->finish, 'job finished';
-
-  my $id5  = $minion->enqueue('test' => [] => {sequence => 'host:localhost', 
parents => [$id, $id2]});
-  my $job5 = $worker->dequeue(0);
+  ok !$worker->dequeue(0), 'parents are not ready yet';
+  ok $job4->fail, 'job finished';
+  ok !$worker->dequeue(0), 'parents are not ready yet';
+  ok $minion->job($id5)->retry({lax => 1}), 'job is now lax';
+  ok my $job5 = $worker->dequeue(0), 'job dequeued';
   is $job5->id, $id5, 'right id';
-  is $job5->info->{sequence}, 'host:localhost', 'right sequence';
-  is_deeply $job5->info->{children}, [], 'no children';
-  is_deeply $job5->info->{parents}, [$id4, $id, $id2], 'right parents';
+  is_deeply $job5->info->{children}, [], 'right children';
+  is_deeply $job5->info->{parents}, [$id4], 'right parents';
   ok $job5->finish, 'job finished';
+  ok $job4->remove, 'job removed';
+
+  is $minion->jobs({ids => [$id5]})->next->{lax}, 1, 'lax';
+  ok $minion->job($id5)->retry, 'job is still lax';
+  is $minion->jobs({ids => [$id5]})->next->{lax}, 1, 'lax';
+  ok $minion->job($id5)->retry({lax => 0}), 'job is not lax anymore';
+  is $minion->jobs({ids => [$id5]})->next->{lax}, 0, 'not lax';
+  ok $minion->job($id5)->retry, 'job is still not lax';
+  is $minion->jobs({ids => [$id5]})->next->{lax}, 0, 'not lax';
   ok $minion->job($id5)->remove, 'job removed';
+  $worker->unregister;
+};
 
-  my $id6  = $minion->enqueue('test' => [] => {sequence => 'host:localhost'});
-  my $job6 = $worker->dequeue(0);
-  is $job6->id, $id6, 'right id';
-  is $job6->info->{sequence}, 'host:localhost', 'right sequence';
-  is $job6->info->{previous}, undef,            'sequence restarted';
-  is $job6->info->{next},     undef,            'sequence restarted';
-  is $job4->info->{next}, $id5, 'sequence restarted';
-  is_deeply $job6->info->{children}, [], 'no children';
-  is_deeply $job6->info->{parents},  [], 'no parents';
-  ok $job6->finish, 'job finished';
-
-  $id  = $minion->enqueue('test' => [] => {sequence => 
'host:mojolicious.org'});
-  $job = $worker->dequeue(0);
-  is $job->id, $id, 'right id';
-  is $job->info->{sequence}, 'host:mojolicious.org', 'right sequence';
-  is_deeply $job->info->{children}, [], 'no children';
-  is_deeply $job->info->{parents},  [], 'no parents';
-  ok $job->finish, 'job finished';
+subtest 'Expiring jobs' => sub {
+  my $id = $minion->enqueue('test');
+  is $minion->job($id)->info->{expires}, undef, 'no expires timestamp';
+  $minion->job($id)->remove;
 
-  is $minion->jobs({sequences => ['host:mojolicious.org']})->total, 1, 'one 
job';
-  is $minion->jobs({sequences => ['host:mojolicious.org']})->next->{id}, $id, 
'same id';
-  is $minion->jobs({sequences => ['host:metacpan.org']})->total, 0, 'no jobs';
-  is $minion->jobs({sequences => ['host:localhost']})->total,    5, 'five 
jobs';
-  is $minion->jobs({sequences => ['host:localhost', 
'host:mojolicious.org']})->total, 6, 'six jobs';
-  $worker->unregister;
+  $id = $minion->enqueue('test' => [] => {expire => 300});
+  like $minion->job($id)->info->{expires}, qr/^[\d.]+$/, 'has expires 
timestamp';
+  SKIP: {
+    skip 'Minion workers do not support fork emulation', 35 if HAS_PSEUDOFORK;
+    my $worker = $minion->worker->register;
+    ok my $job = $worker->dequeue(0), 'job dequeued';
+    is $job->id, $id, 'right id';
+    my $expires = $job->info->{expires};
+    like $expires, qr/^[\d.]+$/, 'has expires timestamp';
+    ok $job->finish, 'job finished';
+    ok $job->retry({expire => 600}), 'job retried';
+    my $info = $minion->job($id)->info;
+    is $info->{state},     'inactive',   'rigth state';
+    like $info->{expires}, qr/^[\d.]+$/, 'has expires timestamp';
+    isnt $info->{expires}, $expires, 'retried with new expires timestamp';
+    is $minion->repair->jobs({states => ['inactive']})->total, 1, 'job has not 
expired yet';
+    ok $job = $worker->dequeue(0), 'job dequeued';
+    is $job->id, $id, 'right id';
+    ok $job->finish, 'job finished';
+
+    $id = $minion->enqueue('test' => [] => {expire => 300});
+    is $minion->repair->jobs({states => ['inactive']})->total, 1, 'job has not 
expired yet';
+    my $sql = $minion->backend->sqlite;
+    $sql->db->query(q{update minion_jobs set expires = datetime('now', '-1 
day') where id = ?}, $id);
+    is $minion->jobs({states => ['inactive']})->total, 0, 'job has expired';
+    ok !$worker->dequeue(0), 'job has expired';
+    ok $sql->db->select('minion_jobs', '*', {id => $id})->hash, 'job still 
exists in database';
+    $minion->repair;
+    ok !$sql->db->select('minion_jobs', '*', {id => $id})->hash, 'job no 
longer exists in database';
+
+    $id = $minion->enqueue('test' => [] => {expire => 300});
+    ok $job = $worker->dequeue(0), 'job dequeued';
+    is $job->id, $id, 'right id';
+    ok $job->finish, 'job finished';
+    $sql->db->query(q{update minion_jobs set expires = datetime('now', '-1 
day') where id = ?}, $id);
+    $minion->repair;
+    ok $job = $minion->job($id), 'job still exists';
+    is $job->info->{state}, 'finished', 'right state';
+
+    $id = $minion->enqueue('test' => [] => {expire => 300});
+    ok $job = $worker->dequeue(0), 'job dequeued';
+    is $job->id, $id, 'right id';
+    ok $job->fail, 'job failed';
+    $sql->db->query(q{update minion_jobs set expires = datetime('now', '-1 
day') where id = ?}, $id);
+    $minion->repair;
+    ok $job = $minion->job($id), 'job still exists';
+    is $job->info->{state}, 'failed', 'right state';
+
+    $id = $minion->enqueue('test' => [] => {expire => 300});
+    ok $job = $worker->dequeue(0), 'job dequeued';
+    is $job->id, $id, 'right id';
+    $sql->db->query(q{update minion_jobs set expires = datetime('now', '-1 
day') where id = ?}, $id);
+    $minion->repair;
+    ok $job = $minion->job($id), 'job still exists';
+    is $job->info->{state}, 'active', 'right state';
+    ok $job->finish, 'job finished';
+
+    $id = $minion->enqueue('test' => [] => {expire => 300});
+    my $id2 = $minion->enqueue('test' => [] => {parents => [$id]});
+    ok !$worker->dequeue(0, {id => $id2}), 'parent is still inactive';
+    $sql->db->query(q{update minion_jobs set expires = datetime('now', '-1 
day') where id = ?}, $id);
+    ok $job = $worker->dequeue(0, {id => $id2}), 'parent has expired';
+    ok $job->finish, 'job finished';
+    $worker->unregister;
+  }
 };
 
 subtest 'Foreground' => sub {


Reply via email to