← Back to team overview

launchpad-reviewers team mailing list archive

[Merge] ~twom/launchpad:add-more-stats-to-more-pages into launchpad:master

 

Tom Wardill has proposed merging ~twom/launchpad:add-more-stats-to-more-pages into launchpad:master.

Commit message:
Add code import queue stats to the machine pages

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~twom/launchpad/+git/launchpad/+merge/381106

The builders page has stats about the queue lengths, but the code import machine page doesn't.
This seems a bit weird.

ADD MORE STATS.
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of ~twom/launchpad:add-more-stats-to-more-pages into launchpad:master.
diff --git a/lib/lp/code/browser/codeimportmachine.py b/lib/lp/code/browser/codeimportmachine.py
index db7a13b..1bcb25f 100644
--- a/lib/lp/code/browser/codeimportmachine.py
+++ b/lib/lp/code/browser/codeimportmachine.py
@@ -25,10 +25,12 @@ from lp.app.browser.launchpadform import (
     LaunchpadFormView,
     )
 from lp.code.enums import (
+    CodeImportJobState,
     CodeImportMachineOfflineReason,
     CodeImportMachineState,
     )
 from lp.code.interfaces.codeimportevent import ICodeImportEvent
+from lp.code.interfaces.codeimportjob import ICodeImportJobSet
 from lp.code.interfaces.codeimportmachine import ICodeImportMachineSet
 from lp.services.propertycache import cachedproperty
 from lp.services.webapp import (
@@ -72,6 +74,24 @@ class CodeImportMachineSetView(LaunchpadView):
         """Get the machines, sorted alphabetically by hostname."""
         return getUtility(ICodeImportMachineSet).getAll()
 
+    @property
+    def pending_imports(self):
+        """Get the number of imports that are pending."""
+        return getUtility(ICodeImportJobSet).getJobsInState(
+            CodeImportJobState.PENDING).count()
+
+    @property
+    def scheduled_imports(self):
+        """Get the number of imports that are scheduled."""
+        return getUtility(ICodeImportJobSet).getJobsInState(
+            CodeImportJobState.SCHEDULED).count()
+
+    @property
+    def running_imports(self):
+        """Get the number of imports that are running."""
+        return getUtility(ICodeImportJobSet).getJobsInState(
+            CodeImportJobState.RUNNING).count()
+
 
 class UpdateMachineStateForm(Interface):
     """An interface to allow the user to enter a reason for quiescing."""
diff --git a/lib/lp/code/interfaces/codeimportjob.py b/lib/lp/code/interfaces/codeimportjob.py
index 6102b22..2a99a81 100644
--- a/lib/lp/code/interfaces/codeimportjob.py
+++ b/lib/lp/code/interfaces/codeimportjob.py
@@ -139,6 +139,12 @@ class ICodeImportJobSetPublic(Interface):
         It will return None if there is no such job.
         """
 
+    def getJobsInState(state):
+        """Get the jobs that are in a given state.
+
+        :return: A ResultSet of `CodeImportJob`.
+        """
+
 
 class ICodeImportJobWorkflow(Interface):
     """Utility to manage `CodeImportJob` objects through their life cycle."""
diff --git a/lib/lp/code/model/codeimportjob.py b/lib/lp/code/model/codeimportjob.py
index 702c93c..39d71ee 100644
--- a/lib/lp/code/model/codeimportjob.py
+++ b/lib/lp/code/model/codeimportjob.py
@@ -215,6 +215,11 @@ class CodeImportJobSet(object):
             % sqlvalues(CodeImportJobState.RUNNING, UTC_NOW,
                         config.codeimportworker.maximum_heartbeat_interval))
 
+    def getJobsInState(self, state):
+        return IStore(CodeImportJob).find(
+            CodeImportJob,
+            CodeImportJob.state == state)
+
 
 @implementer(ICodeImportJobWorkflow)
 class CodeImportJobWorkflow:
diff --git a/lib/lp/code/model/tests/test_codeimportjob.py b/lib/lp/code/model/tests/test_codeimportjob.py
index 68499dd..0130d17 100644
--- a/lib/lp/code/model/tests/test_codeimportjob.py
+++ b/lib/lp/code/model/tests/test_codeimportjob.py
@@ -217,6 +217,18 @@ class TestCodeImportJobSet(TestCaseWithFactory):
         no_job = getUtility(ICodeImportJobSet).getById(-1)
         self.assertIs(None, no_job)
 
+    def test_getByJobState(self):
+        self.machine = self.factory.makeCodeImportMachine(set_online=True)
+        made_job = removeSecurityProxy(self.factory.makeCodeImportJob())
+        for _ in range(3):
+            job = self.factory.makeCodeImportJob()
+            getUtility(ICodeImportJobWorkflow).startJob(job, self.machine)
+        found_jobs = getUtility(ICodeImportJobSet).getJobsInState(
+            CodeImportJobState.PENDING).order_by(CodeImportJob.id)
+        # There's a job in the test date, we need the second one.
+        self.assertEqual(found_jobs.count(), 2)
+        self.assertEqual(made_job, found_jobs[1])
+
 
 class TestCodeImportJobSetGetJobForMachine(TestCaseWithFactory):
     """Tests for the CodeImportJobSet.getJobForMachine method.
diff --git a/lib/lp/code/templates/codeimport-machines.pt b/lib/lp/code/templates/codeimport-machines.pt
index c915b1c..eaa60d2 100644
--- a/lib/lp/code/templates/codeimport-machines.pt
+++ b/lib/lp/code/templates/codeimport-machines.pt
@@ -12,7 +12,30 @@
 
 <div metal:fill-slot="main" class="visualPadding">
 
-  <table class="listing" id="code-import-machine-listing">
+  <div style="float:right;">
+    <div id="import-queue-status">
+      <div>
+        <div>
+          <h3>Import queue</h3>
+          <table class="summary">
+            <tr>
+              <td>Pending</td>
+              <td tal:content="view/pending_imports"></td>
+            </tr>
+            <tr>
+              <td>Scheduled</td>
+              <td tal:content="view/scheduled_imports"></td>
+            </tr>
+            <tr>
+              <td>Running</td>
+              <td tal:content="view/running_imports"></td>
+            </tr>
+        </div>
+      </div>
+    </div><!-- portlet -->
+  </div><!-- yui-u -->
+
+  <table style="width:80%" class="listing" id="code-import-machine-listing">
     <thead>
       <tr>
         <th>Machine</th>
@@ -53,6 +76,7 @@
       </tal:machine>
     </tbody>
   </table>
+
 </div>
 
 </body>