[tools 2/2] testbot: Allow resuming jobs after stopping them.

Francois Gouget fgouget at codeweavers.com
Mon May 30 11:07:29 CDT 2022


This renames the 'cancel' action to 'stop' since it's reversible now.

Signed-off-by: Francois Gouget <fgouget at codeweavers.com>
---
Naming is a bit tricky:
* Cancel implies too much that the job cannot be resumed.
* Pause implies too much that this is a temporary state and that the job 
  is meant to be resumed eventually. That's not the case: once stopped 
  it's considered to be "done" and will be garbage collected after 
  a while.
* So I settled on Stop.

This can be used to let other jobs run for instance, and what's really 
new is that one can then resume the job wherease before one had to 
restart it from scratch (which is still an option).
---
 testbot/bin/Engine.pl           |  6 ++-
 testbot/lib/WineTestBot/Jobs.pm | 65 +++++++++++++++++++++++++++++++--
 testbot/web/JobDetails.pl       | 15 +++++---
 3 files changed, 74 insertions(+), 12 deletions(-)

diff --git a/testbot/bin/Engine.pl b/testbot/bin/Engine.pl
index da72ffb47..88852730e 100755
--- a/testbot/bin/Engine.pl
+++ b/testbot/bin/Engine.pl
@@ -333,7 +333,7 @@ sub HandleJobControl($)
 {
   my ($Action, $JobKey) = @_;
 
-  if ($Action !~ /^(cancel|restart)$/)
+  if ($Action !~ /^(stop|resume|restart)$/)
   {
     LogMsg "Invalid $Action JobControl command\n";
     return "0Invalid $Action JobControl command";
@@ -350,7 +350,9 @@ sub HandleJobControl($)
   $JobKey =~ m/^(.*)$/;
   $JobKey = $1;
 
-  my $ErrMessage = $Action eq "cancel" ? $Job->Cancel() : $Job->Restart();
+  my $ErrMessage = $Action eq "stop" ? $Job->Stop() :
+                   $Action eq "resume" ? $Job->Resume() :
+                   $Job->Restart();
   if (defined($ErrMessage))
   {
     LogMsg "$Action problem: $ErrMessage\n";
diff --git a/testbot/lib/WineTestBot/Jobs.pm b/testbot/lib/WineTestBot/Jobs.pm
index c082a36ab..e4d76d356 100644
--- a/testbot/lib/WineTestBot/Jobs.pm
+++ b/testbot/lib/WineTestBot/Jobs.pm
@@ -75,7 +75,7 @@ Once all the Steps have completed the Job's Status is updated to reflect the
 overall result: completed, badpatch, etc.
 
 =item *
-If the Job is canceled by the user, then the Status field is set to canceled.
+If the Job is stopped by the user, then the Status field is set to canceled.
 
 =back
 
@@ -280,9 +280,9 @@ sub UpdateStatus($)
 =pod
 =over 12
 
-=item C<Cancel()>
+=item C<Stop()>
 
-Cancels the Job, preserving existing results.
+Stops the Job, preserving existing results.
 
 More precisely, goes through all of that Job's 'queued' and 'running' tasks,
 killing all the running ones and marking them, and all the queued tasks, as
@@ -294,7 +294,7 @@ Returns undef if successful, the error message otherwise.
 =back
 =cut
 
-sub Cancel($)
+sub Stop($)
 {
   my ($self) = @_;
   my $ErrMessage;
@@ -339,6 +339,63 @@ sub Cancel($)
 =pod
 =over 12
 
+=item C<Resume()>
+
+Resume running the Job.
+
+More precisely, marks the 'skipped' and 'canceled' tasks as 'queued' 
+again and updates the job status accordingly. This preserves existing 
+results unlike Restart().
+
+Returns undef if successful, the error message otherwise.
+
+=back
+=cut
+
+sub Resume($)
+{
+  my ($self) = @_;
+
+  if ($self->Status ne "canceled")
+  {
+    return "The job has not been stopped and is currently ". $self->Status;
+  }
+
+  my $Steps = $self->Steps;
+  $Steps->AddFilter("Status", ["canceled", "skipped"]);
+  foreach my $Step (@{$Steps->GetSortedItems()})
+  {
+    if ($Step->PreviousNo)
+    {
+      my $PrevStatus = $Steps->GetItem($Step->PreviousNo)->Status;
+      if ($PrevStatus ne "queued" && $PrevStatus ne "running" &&
+          $PrevStatus ne "completed")
+      {
+        # The previous step was supposed to provide binaries but it failed.
+        # So this one cannot resume.
+        continue;
+      }
+    }
+
+    my $Tasks = $Step->Tasks;
+    $Tasks->AddFilter("Status", ["canceled", "skipped"]);
+    foreach my $Task (@{$Tasks->GetItems()})
+    {
+      $Task->Status("queued");
+      $Task->Started(undef);
+    }
+    $Step->Status("queued");
+  }
+  # Mark the job as queued and let UpdateStatus() set it to running if
+  # appropriate.
+  $self->Status("queued");
+  $self->UpdateStatus();
+  return undef;
+}
+
+=pod
+=over 12
+
 =item C<Restart()>
 
 Restarts the Job from scratch.
diff --git a/testbot/web/JobDetails.pl b/testbot/web/JobDetails.pl
index 87a56941e..329ab150c 100644
--- a/testbot/web/JobDetails.pl
+++ b/testbot/web/JobDetails.pl
@@ -173,7 +173,8 @@ sub CanDoJobControl($$)
   }
 
   my %AllowedStatus = (
-    "cancel" => {"queued" => 1, "running" => 1},
+    "stop" => {"queued" => 1, "running" => 1},
+    "resume" => {"canceled" => 1},
     "restart" => {"boterror" => 1, "canceled" => 1},
   );
   return $AllowedStatus{$Action}->{$Job->Status} ? undef :
@@ -210,17 +211,19 @@ sub GetActions($)
 {
   my ($self) = @_;
 
-  # These are mutually exclusive
-  return ["Cancel job"] if (!defined $self->CanDoJobControl("cancel"));
-  return ["Restart job"] if (!defined $self->CanDoJobControl("restart"));
-  return [];
+  my @Actions;
+  push @Actions, "Stop job" if (!$self->CanDoJobControl("stop"));
+  push @Actions, "Resume job" if (!$self->CanDoJobControl("resume"));
+  push @Actions, "Restart job" if (!$self->CanDoJobControl("restart"));
+  return \@Actions;
 }
 
 sub OnAction($$)
 {
   my ($self, $Action) = @_;
 
-  return $Action eq "Cancel job" ? $self->OnJobControl("cancel") :
+  return $Action eq "Stop job" ? $self->OnJobControl("stop") :
+         $Action eq "Resume job" ? $self->OnJobControl("resume") :
          $Action eq "Restart job" ? $self->OnJobControl("restart") :
          $self->SUPER::OnAction($Action);
 }
-- 
2.30.2



More information about the wine-devel mailing list