← Back to team overview

launchpad-reviewers team mailing list archive

[Merge] lp:~wgrant/launchpad/antibfjo-5-use-more into lp:launchpad

 

William Grant has proposed merging lp:~wgrant/launchpad/antibfjo-5-use-more into lp:launchpad with lp:~wgrant/launchpad/antibfjo-4-use as a prerequisite.

Commit message:
Adjust code using BuildQueue.job to use the new columns on BuildQueue directly.

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~wgrant/launchpad/antibfjo-5-use-more/+merge/195892

IBuildFarmJobOld and its implementations (BuildPackageJob, SourcePackageRecipeBuildJob, TranslationTemplatesBuildJob) are finally being replaced with an FK from BuildQueue to BuildFarmJob. Additionally, the two fields of Job that are used by BuildQueue are being inlined, and the FK to Job dropped, for performance reasons.

This branch adjust the other half of the relevant code to use the new columns rather than the old ones. All the old columns are still set.
-- 
https://code.launchpad.net/~wgrant/launchpad/antibfjo-5-use-more/+merge/195892
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~wgrant/launchpad/antibfjo-5-use-more into lp:launchpad.
=== modified file 'lib/lp/buildmaster/interactor.py'
--- lib/lp/buildmaster/interactor.py	2013-11-12 09:07:01 +0000
+++ lib/lp/buildmaster/interactor.py	2013-11-20 00:23:09 +0000
@@ -21,6 +21,7 @@
     removeSecurityProxy,
     )
 
+from lp.buildmaster.enums import BuildQueueStatus
 from lp.buildmaster.interfaces.builder import (
     BuildDaemonError,
     CannotFetchFile,
@@ -31,7 +32,6 @@
     )
 from lp.services import encoding
 from lp.services.config import config
-from lp.services.job.interfaces.job import JobStatus
 from lp.services.twistedsupport import cancel_on_timeout
 from lp.services.twistedsupport.processmonitor import ProcessWithTimeout
 from lp.services.webapp import urlappend
@@ -452,7 +452,7 @@
         builder_status = slave_status['builder_status']
         if builder_status == 'BuilderStatus.BUILDING':
             # Build still building, collect the logtail.
-            if vitals.build_queue.job.status != JobStatus.RUNNING:
+            if vitals.build_queue.status != BuildQueueStatus.RUNNING:
                 # XXX: This check should be removed once we confirm it's
                 # not regularly hit.
                 raise AssertionError(

=== modified file 'lib/lp/buildmaster/interfaces/buildfarmjob.py'
--- lib/lp/buildmaster/interfaces/buildfarmjob.py	2013-11-15 09:31:08 +0000
+++ lib/lp/buildmaster/interfaces/buildfarmjob.py	2013-11-20 00:23:09 +0000
@@ -288,17 +288,8 @@
 
         Return a sub-query to narrow down the list of candidate jobs.
         The sub-query will become part of an "outer query" and is free to
-        refer to the `BuildQueue` and `Job` tables already utilized in the
-        latter.
-
-        Example (please see the `BuildPackageJob` implementation for a
-        complete example):
-
-            SELECT TRUE
-            FROM Archive, Build, BuildPackageJob, DistroArchSeries
-            WHERE
-            BuildPackageJob.job = Job.id AND
-            ..
+        refer to the `BuildQueue` and `BuildFarmJob` tables already utilized
+        in the latter.
 
         :param processor: the type of processor that the candidate jobs are
             expected to run on.

=== modified file 'lib/lp/buildmaster/model/builder.py'
--- lib/lp/buildmaster/model/builder.py	2013-11-12 09:07:01 +0000
+++ lib/lp/buildmaster/model/builder.py	2013-11-20 00:23:09 +0000
@@ -25,8 +25,10 @@
 import transaction
 from zope.component import getUtility
 from zope.interface import implements
+from zope.security.proxy import removeSecurityProxy
 
 from lp.app.errors import NotFoundError
+from lp.buildmaster.enums import BuildQueueStatus
 from lp.buildmaster.interfaces.builder import (
     IBuilder,
     IBuilderSet,
@@ -46,8 +48,6 @@
     SQLBase,
     sqlvalues,
     )
-from lp.services.job.interfaces.job import JobStatus
-from lp.services.job.model.job import Job
 from lp.services.propertycache import cachedproperty
 # XXX Michael Nelson 2010-01-13 bug=491330
 # These dependencies on soyuz will be removed when getBuildRecords()
@@ -173,7 +173,7 @@
         def qualify_subquery(job_type, sub_query):
             """Put the sub-query into a job type context."""
             qualified_query = """
-                ((BuildQueue.job_type != %s) OR EXISTS(%%s))
+                ((BuildFarmJob.job_type != %s) OR EXISTS(%%s))
             """ % sqlvalues(job_type)
             qualified_query %= sub_query
             return qualified_query
@@ -182,10 +182,10 @@
         candidate = None
 
         general_query = """
-            SELECT buildqueue.id FROM buildqueue, job
+            SELECT buildqueue.id FROM buildqueue, buildfarmjob
             WHERE
-                buildqueue.job = job.id
-                AND job.status = %s
+                buildfarmjob.id = buildqueue.build_farm_job
+                AND buildqueue.status = %s
                 AND (
                     -- The processor values either match or the candidate
                     -- job is processor-independent.
@@ -201,7 +201,7 @@
                     (buildqueue.virtualized IS NULL AND %s = TRUE))
                 AND buildqueue.builder IS NULL
         """ % sqlvalues(
-            JobStatus.WAITING, self.processor, self.virtualized,
+            BuildQueueStatus.WAITING, self.processor, self.virtualized,
             self.virtualized)
         order_clause = " ORDER BY buildqueue.lastscore DESC, buildqueue.id"
 
@@ -224,7 +224,8 @@
 
         for (candidate_id,) in candidate_jobs:
             candidate = getUtility(IBuildQueueSet).get(candidate_id)
-            job_source = job_sources[candidate.job_type]
+            job_source = job_sources[
+                removeSecurityProxy(candidate)._build_farm_job.job_type]
             candidate_approved = job_source.postprocessCandidate(
                 candidate, logger)
             if candidate_approved:
@@ -296,8 +297,7 @@
             Processor,
             Coalesce(BuildQueue.virtualized, True)),
             Processor.id == BuildQueue.processorID,
-            Job.id == BuildQueue.jobID,
-            Job._status == JobStatus.WAITING).group_by(
+            BuildQueue.status == BuildQueueStatus.WAITING).group_by(
                 Processor, Coalesce(BuildQueue.virtualized, True))
 
         result_dict = {'virt': {}, 'nonvirt': {}}

=== modified file 'lib/lp/buildmaster/model/buildfarmjob.py'
--- lib/lp/buildmaster/model/buildfarmjob.py	2013-11-20 00:23:08 +0000
+++ lib/lp/buildmaster/model/buildfarmjob.py	2013-11-20 00:23:09 +0000
@@ -52,13 +52,6 @@
 
     implements(IBuildFarmJobOld)
 
-    @staticmethod
-    def preloadBuildFarmJobs(jobs):
-        """Preload the build farm jobs to which the given jobs will delegate.
-
-        """
-        pass
-
     @classmethod
     def getByJob(cls, job):
         """See `IBuildFarmJobOld`."""

=== modified file 'lib/lp/buildmaster/model/buildqueue.py'
--- lib/lp/buildmaster/model/buildqueue.py	2013-11-20 00:23:08 +0000
+++ lib/lp/buildmaster/model/buildqueue.py	2013-11-20 00:23:09 +0000
@@ -56,7 +56,6 @@
 from lp.services.database.enumcol import EnumCol
 from lp.services.database.sqlbase import SQLBase
 from lp.services.job.interfaces.job import JobStatus
-from lp.services.job.model.job import Job
 from lp.services.propertycache import (
     cachedproperty,
     get_property_cache,
@@ -117,7 +116,7 @@
     _build_farm_job_id = Int(name='build_farm_job')
     _build_farm_job = Reference(_build_farm_job_id, 'BuildFarmJob.id')
     status = EnumCol(enum=BuildQueueStatus, default=BuildQueueStatus.WAITING)
-    _date_started = DateTime(tzinfo=pytz.UTC, name='date_started')
+    date_started = DateTime(tzinfo=pytz.UTC)
 
     job = ForeignKey(dbName='job', foreignKey='Job')
     job_type = EnumCol(
@@ -134,8 +133,9 @@
     @cachedproperty
     def specific_build(self):
         """See `IBuildQueue`."""
-        specific_source = specific_build_farm_job_sources()[self.job_type]
-        return specific_source.getByBuildFarmJob(self._build_farm_job)
+        bfj = self._build_farm_job
+        specific_source = specific_build_farm_job_sources()[bfj.job_type]
+        return specific_source.getByBuildFarmJob(bfj)
 
     def _clear_specific_build_cache(self):
         del get_property_cache(self).specific_build
@@ -143,6 +143,8 @@
     @cachedproperty
     def specific_old_job(self):
         """See `IBuildQueue`."""
+        if self.job is None:
+            return None
         specific_class = specific_job_classes()[self.job_type]
         return specific_class.getByJob(self.job)
 
@@ -153,7 +155,6 @@
     def preloadSpecificBuild(queues):
         from lp.buildmaster.model.buildfarmjob import BuildFarmJob
         load_related(BuildFarmJob, queues, ['_build_farm_job_id'])
-        load_related(Job, queues, ['jobID'])
         bfj_to_bq = dict(
             (removeSecurityProxy(bq)._build_farm_job, bq)
             for bq in queues)
@@ -167,11 +168,6 @@
                 get_property_cache(bq).specific_build = build
 
     @property
-    def date_started(self):
-        """See `IBuildQueue`."""
-        return self.job.date_started
-
-    @property
     def current_build_duration(self):
         """See `IBuildQueue`."""
         date_started = self.date_started
@@ -186,9 +182,11 @@
         specific_old_job = self.specific_old_job
         builder = self.builder
         Store.of(self).remove(self)
-        specific_old_job.cleanUp()
+        if specific_old_job is not None:
+            specific_old_job.cleanUp()
         Store.of(self).flush()
-        job.destroySelf()
+        if job is not None:
+            job.destroySelf()
         if builder is not None:
             del get_property_cache(builder).currentjob
         self._clear_specific_old_job_cache()
@@ -210,19 +208,20 @@
     def markAsBuilding(self, builder):
         """See `IBuildQueue`."""
         self.builder = builder
-        if self.job.status != JobStatus.RUNNING:
+        if self.job is not None and self.job.status != JobStatus.RUNNING:
             self.job.start()
         self.status = BuildQueueStatus.RUNNING
-        self._date_started = UTC_NOW
+        self.date_started = UTC_NOW
         self.specific_build.updateStatus(BuildStatus.BUILDING)
         if builder is not None:
             del get_property_cache(builder).currentjob
 
     def suspend(self):
         """See `IBuildQueue`."""
-        if self.job.status != JobStatus.WAITING:
+        if self.status != BuildQueueStatus.WAITING:
             raise AssertionError("Only waiting jobs can be suspended.")
-        self.job.suspend()
+        if self.job is not None:
+            self.job.suspend()
         self.status = BuildQueueStatus.SUSPENDED
 
     def resume(self):
@@ -237,12 +236,13 @@
         """See `IBuildQueue`."""
         builder = self.builder
         self.builder = None
-        if self.job.status != JobStatus.WAITING:
+        if self.job is not None and self.job.status != JobStatus.WAITING:
             self.job.queue()
         self.status = BuildQueueStatus.WAITING
-        self._date_started = None
-        self.job.date_started = None
-        self.job.date_finished = None
+        self.date_started = None
+        if self.job is not None:
+            self.job.date_started = None
+            self.job.date_finished = None
         self.logtail = None
         self.specific_build.updateStatus(BuildStatus.NEEDSBUILD)
         if builder is not None:

=== modified file 'lib/lp/buildmaster/queuedepth.py'
--- lib/lp/buildmaster/queuedepth.py	2013-11-10 23:56:44 +0000
+++ lib/lp/buildmaster/queuedepth.py	2013-11-20 00:23:09 +0000
@@ -15,10 +15,10 @@
 
 from pytz import utc
 
+from lp.buildmaster.enums import BuildQueueStatus
 from lp.buildmaster.model.buildqueue import BuildQueue
 from lp.services.database.interfaces import IStore
 from lp.services.database.sqlbase import sqlvalues
-from lp.services.job.interfaces.job import JobStatus
 
 
 def get_builder_data():
@@ -89,13 +89,12 @@
         SELECT
             processor,
             virtualized
-        FROM
-            BuildQueue, Job
+        FROM BuildQueue
         WHERE
         """
     query += get_pending_jobs_clauses(bq)
     query += """
-        ORDER BY lastscore DESC, job LIMIT 1
+        ORDER BY lastscore DESC, id LIMIT 1
         """
     result = IStore(BuildQueue).execute(query).get_one()
     return (my_platform if result is None else result)
@@ -134,11 +133,11 @@
             CASE WHEN
             EXTRACT(EPOCH FROM
                 (BuildQueue.estimated_duration -
-                (((%s AT TIME ZONE 'UTC') - Job.date_started))))  >= 0
+                (((%s AT TIME ZONE 'UTC') - BuildQueue.date_started))))  >= 0
             THEN
             EXTRACT(EPOCH FROM
                 (BuildQueue.estimated_duration -
-                (((%s AT TIME ZONE 'UTC') - Job.date_started))))
+                (((%s AT TIME ZONE 'UTC') - BuildQueue.date_started))))
             ELSE
             -- Assume that jobs that have overdrawn their estimated
             -- duration time budget will complete within 2 minutes.
@@ -150,16 +149,15 @@
             120
             END)
         FROM
-            BuildQueue, Job, Builder
+            BuildQueue, Builder
         WHERE
-            BuildQueue.job = Job.id
-            AND BuildQueue.builder = Builder.id
+            BuildQueue.builder = Builder.id
             AND Builder.manual = False
             AND Builder.builderok = True
-            AND Job.status = %s
+            AND BuildQueue.status = %s
             AND Builder.virtualized = %s
         """ % sqlvalues(
-            now, now, JobStatus.RUNNING,
+            now, now, BuildQueueStatus.RUNNING,
             normalize_virtualization(head_job_virtualized))
 
     if head_job_processor is not None:
@@ -178,14 +176,13 @@
     estimation."""
     virtualized = normalize_virtualization(bq.virtualized)
     clauses = """
-        BuildQueue.job = Job.id
-        AND Job.status = %s
+        BuildQueue.status = %s
         AND (
             -- The score must be either above my score or the
             -- job must be older than me in cases where the
             -- score is equal.
             BuildQueue.lastscore > %s OR
-            (BuildQueue.lastscore = %s AND Job.id < %s))
+            (BuildQueue.lastscore = %s AND BuildQueue.id < %s))
         -- The virtualized values either match or the job
         -- does not care about virtualization and the job
         -- of interest (JOI) is to be run on a virtual builder
@@ -193,7 +190,7 @@
         -- on native builders).
         AND COALESCE(buildqueue.virtualized, TRUE) = %s
         """ % sqlvalues(
-            JobStatus.WAITING, bq.lastscore, bq.lastscore, bq.job,
+            BuildQueueStatus.WAITING, bq.lastscore, bq.lastscore, bq,
             virtualized)
     processor_clause = """
         AND (
@@ -246,12 +243,11 @@
         SELECT
             BuildQueue.processor,
             BuildQueue.virtualized,
-            COUNT(BuildQueue.job),
+            COUNT(BuildQueue.id),
             CAST(EXTRACT(
                 EPOCH FROM
                     SUM(BuildQueue.estimated_duration)) AS INTEGER)
-        FROM
-            BuildQueue, Job
+        FROM BuildQueue
         WHERE
         """
     query += get_pending_jobs_clauses(bq)
@@ -317,7 +313,7 @@
             build pool)
     """
     # This method may only be invoked for pending jobs.
-    if bq.job.status != JobStatus.WAITING:
+    if bq.status != BuildQueueStatus.WAITING:
         raise AssertionError(
             "The start time is only estimated for pending jobs.")
 

=== modified file 'lib/lp/buildmaster/templates/buildqueue-current.pt'
--- lib/lp/buildmaster/templates/buildqueue-current.pt	2013-11-15 06:21:55 +0000
+++ lib/lp/buildmaster/templates/buildqueue-current.pt	2013-11-20 00:23:09 +0000
@@ -6,7 +6,7 @@
 
   <p>Started
     <span
-      tal:attributes="title context/job/date_started/fmt:datetime"
+      tal:attributes="title context/date_started/fmt:datetime"
       tal:content="context/current_build_duration/fmt:exactduration" />
     ago.
   </p>

=== modified file 'lib/lp/buildmaster/templates/builds-list.pt'
--- lib/lp/buildmaster/templates/builds-list.pt	2013-11-15 06:36:55 +0000
+++ lib/lp/buildmaster/templates/builds-list.pt	2013-11-20 00:23:09 +0000
@@ -101,8 +101,8 @@
                 <tal:building condition="bq/builder">
                   Build started
                   <span
-                    tal:attributes="title bq/job/date_started/fmt:datetime"
-                    tal:content="bq/job/date_started/fmt:displaydate" />
+                    tal:attributes="title bq/date_started/fmt:datetime"
+                    tal:content="bq/date_started/fmt:displaydate" />
                   on
                   <a tal:content="bq/builder/title"
                      tal:attributes="href bq/builder/fmt:url"/>

=== modified file 'lib/lp/buildmaster/tests/test_buildqueue.py'
--- lib/lp/buildmaster/tests/test_buildqueue.py	2013-11-20 00:23:08 +0000
+++ lib/lp/buildmaster/tests/test_buildqueue.py	2013-11-20 00:23:09 +0000
@@ -5,7 +5,6 @@
 from datetime import timedelta
 
 from storm.sqlobject import SQLObjectNotFound
-from storm.store import Store
 from zope import component
 from zope.component import getGlobalSiteManager
 from zope.security.proxy import removeSecurityProxy
@@ -124,7 +123,7 @@
         now = buildqueue._now()
         buildqueue._now = FakeMethod(result=now)
         age = timedelta(minutes=3)
-        buildqueue.job.date_started = now - age
+        buildqueue.date_started = now - age
 
         self.assertEqual(age, buildqueue.current_build_duration)
 

=== modified file 'lib/lp/buildmaster/tests/test_queuedepth.py'
--- lib/lp/buildmaster/tests/test_queuedepth.py	2013-11-20 00:23:08 +0000
+++ lib/lp/buildmaster/tests/test_queuedepth.py	2013-11-20 00:23:09 +0000
@@ -39,7 +39,7 @@
 
 def check_mintime_to_builder(test, bq, min_time):
     """Test the estimated time until a builder becomes available."""
-    time_stamp = bq.job.date_started or datetime.now(utc)
+    time_stamp = bq.date_started or datetime.now(utc)
     delay = estimate_time_to_next_builder(
         removeSecurityProxy(bq), now=time_stamp)
     test.assertTrue(
@@ -51,7 +51,7 @@
 def set_remaining_time_for_running_job(bq, remainder):
     """Set remaining running time for job."""
     offset = bq.estimated_duration.seconds - remainder
-    removeSecurityProxy(bq.job).date_started = (
+    removeSecurityProxy(bq).date_started = (
         datetime.now(utc) - timedelta(seconds=offset))
 
 
@@ -76,7 +76,7 @@
 
 
 def check_estimate(test, job, delay_in_seconds):
-    time_stamp = job.job.date_started or datetime.now(utc)
+    time_stamp = job.date_started or datetime.now(utc)
     estimate = job.getEstimatedJobStartTime(now=time_stamp)
     if delay_in_seconds is None:
         test.assertEquals(

=== modified file 'lib/lp/code/browser/sourcepackagerecipebuild.py'
--- lib/lp/code/browser/sourcepackagerecipebuild.py	2012-02-28 04:24:19 +0000
+++ lib/lp/code/browser/sourcepackagerecipebuild.py	2013-11-20 00:23:09 +0000
@@ -20,11 +20,13 @@
     action,
     LaunchpadFormView,
     )
-from lp.buildmaster.enums import BuildStatus
+from lp.buildmaster.enums import (
+    BuildQueueStatus,
+    BuildStatus,
+    )
 from lp.code.interfaces.sourcepackagerecipebuild import (
     ISourcePackageRecipeBuild,
     )
-from lp.services.job.interfaces.job import JobStatus
 from lp.services.librarian.browser import FileNavigationMixin
 from lp.services.propertycache import cachedproperty
 from lp.services.webapp import (
@@ -107,12 +109,12 @@
         if self.context.buildqueue_record is None:
             return None
         queue_record = self.context.buildqueue_record
-        if queue_record.job.status == JobStatus.WAITING:
+        if queue_record.status == BuildQueueStatus.WAITING:
             start_time = queue_record.getEstimatedJobStartTime()
             if start_time is None:
                 return None
         else:
-            start_time = queue_record.job.date_started
+            start_time = queue_record.date_started
         duration = queue_record.estimated_duration
         return start_time + duration
 

=== modified file 'lib/lp/code/browser/tests/test_sourcepackagerecipe.py'
--- lib/lp/code/browser/tests/test_sourcepackagerecipe.py	2013-11-14 07:36:26 +0000
+++ lib/lp/code/browser/tests/test_sourcepackagerecipe.py	2013-11-20 00:23:09 +0000
@@ -1646,7 +1646,7 @@
         It should be None if there is no builder or queue entry.
         It should be getEstimatedJobStartTime + estimated duration for jobs
         that have not started.
-        It should be job.date_started + estimated duration for jobs that have
+        It should be bq.date_started + estimated duration for jobs that have
         started.
         """
         build = self.factory.makeSourcePackageRecipeBuild()
@@ -1661,10 +1661,10 @@
         self.assertEqual(
             queue_entry.getEstimatedJobStartTime() +
             queue_entry.estimated_duration, view.eta)
-        queue_entry.job.start()
+        queue_entry.markAsBuilding(None)
         clear_property_cache(view)
         self.assertEqual(
-            queue_entry.job.date_started + queue_entry.estimated_duration,
+            queue_entry.date_started + queue_entry.estimated_duration,
             view.eta)
 
     def getBuildBrowser(self, build, view_name=None):

=== modified file 'lib/lp/code/model/sourcepackagerecipebuild.py'
--- lib/lp/code/model/sourcepackagerecipebuild.py	2013-11-20 00:23:08 +0000
+++ lib/lp/code/model/sourcepackagerecipebuild.py	2013-11-20 00:23:09 +0000
@@ -430,24 +430,6 @@
         self.job = job
         super(SourcePackageRecipeBuildJob, self).__init__()
 
-    @staticmethod
-    def preloadBuildFarmJobs(jobs):
-        from lp.code.model.sourcepackagerecipebuild import (
-            SourcePackageRecipeBuild,
-            )
-        return list(IStore(SourcePackageRecipeBuildJob).find(
-            SourcePackageRecipeBuild,
-            [SourcePackageRecipeBuildJob.job_id.is_in([j.id for j in jobs]),
-             SourcePackageRecipeBuildJob.build_id ==
-                 SourcePackageRecipeBuild.id]))
-
-    @classmethod
-    def preloadJobsData(cls, jobs):
-        load_related(Job, jobs, ['job_id'])
-        builds = load_related(
-            SourcePackageRecipeBuild, jobs, ['build_id'])
-        SourcePackageRecipeBuild.preloadBuildsData(builds)
-
     @classmethod
     def new(cls, build, job):
         """See `ISourcePackageRecipeBuildJobSource`."""

=== modified file 'lib/lp/code/templates/sourcepackagerecipebuild-index.pt'
--- lib/lp/code/templates/sourcepackagerecipebuild-index.pt	2012-03-02 16:17:46 +0000
+++ lib/lp/code/templates/sourcepackagerecipebuild-index.pt	2013-11-20 00:23:09 +0000
@@ -111,7 +111,7 @@
          tal:content="context/dependencies">x, y, z</em>
      </li>
       <tal:reallypending condition="context/buildqueue_record">
-      <tal:pending condition="context/buildqueue_record/job/status/enumvalue:WAITING">
+      <tal:pending condition="context/buildqueue_record/status/enumvalue:WAITING">
         <li tal:define="eta context/buildqueue_record/getEstimatedJobStartTime">
           Start <tal:eta
           replace="eta/fmt:approximatedate">in 3 hours</tal:eta>

=== modified file 'lib/lp/soyuz/browser/build.py'
--- lib/lp/soyuz/browser/build.py	2013-11-20 00:23:08 +0000
+++ lib/lp/soyuz/browser/build.py	2013-11-20 00:23:09 +0000
@@ -45,7 +45,10 @@
     NotFoundError,
     UnexpectedFormData,
     )
-from lp.buildmaster.enums import BuildStatus
+from lp.buildmaster.enums import (
+    BuildQueueStatus,
+    BuildStatus,
+    )
 from lp.buildmaster.interfaces.buildfarmjob import (
     InconsistentBuildFarmJobError,
     ISpecificBuildFarmJobSource,
@@ -54,7 +57,6 @@
 from lp.code.interfaces.sourcepackagerecipebuild import (
     ISourcePackageRecipeBuildSource,
     )
-from lp.services.job.interfaces.job import JobStatus
 from lp.services.librarian.browser import (
     FileNavigationMixin,
     ProxiedLibraryFileAlias,
@@ -321,7 +323,7 @@
         """
         return (
             self.context.status == BuildStatus.NEEDSBUILD and
-            self.context.buildqueue_record.job.status == JobStatus.WAITING)
+            self.context.buildqueue_record.status == BuildQueueStatus.WAITING)
 
     @cachedproperty
     def eta(self):
@@ -333,10 +335,10 @@
         if self.context.buildqueue_record is None:
             return None
         queue_record = self.context.buildqueue_record
-        if queue_record.job.status == JobStatus.WAITING:
+        if queue_record.status == BuildQueueStatus.WAITING:
             start_time = queue_record.getEstimatedJobStartTime()
         else:
-            start_time = queue_record.job.date_started
+            start_time = queue_record.date_started
         if start_time is None:
             return None
         duration = queue_record.estimated_duration

=== modified file 'lib/lp/soyuz/browser/tests/builder-views.txt'
--- lib/lp/soyuz/browser/tests/builder-views.txt	2013-09-02 07:13:24 +0000
+++ lib/lp/soyuz/browser/tests/builder-views.txt	2013-11-20 00:23:09 +0000
@@ -208,7 +208,7 @@
     >>> import datetime
     >>> import pytz
     >>> from zope.security.proxy import removeSecurityProxy
-    >>> removeSecurityProxy(private_job.job).date_started = (
+    >>> removeSecurityProxy(private_job).date_started = (
     ...     datetime.datetime.now(pytz.UTC) - datetime.timedelta(10))
     >>> print admin_view.current_build_duration
     10 days...

=== modified file 'lib/lp/soyuz/browser/tests/test_build_views.py'
--- lib/lp/soyuz/browser/tests/test_build_views.py	2013-08-29 18:34:59 +0000
+++ lib/lp/soyuz/browser/tests/test_build_views.py	2013-11-20 00:23:09 +0000
@@ -15,12 +15,14 @@
     )
 from zope.security.proxy import removeSecurityProxy
 
-from lp.buildmaster.enums import BuildStatus
+from lp.buildmaster.enums import (
+    BuildQueueStatus,
+    BuildStatus,
+    )
 from lp.registry.interfaces.person import IPersonSet
 from lp.registry.interfaces.pocket import PackagePublishingPocket
 from lp.registry.interfaces.series import SeriesStatus
 from lp.services.database.sqlbase import flush_database_caches
-from lp.services.job.interfaces.job import JobStatus
 from lp.services.webapp import canonical_url
 from lp.services.webapp.interfaces import StormRangeFactoryError
 from lp.services.webapp.servers import LaunchpadTestRequest
@@ -358,13 +360,13 @@
         build = self.factory.makeBinaryPackageBuild()
         build.queueBuild()
         view = create_initialized_view(build, name="+index")
-        job = view.context.buildqueue_record.job
+        bq = view.context.buildqueue_record
         self.assertTrue(view.dispatch_time_estimate_available)
         self.assertEquals(view.context.status, BuildStatus.NEEDSBUILD)
-        self.assertEquals(job.status, JobStatus.WAITING)
+        self.assertEquals(bq.status, BuildQueueStatus.WAITING)
         # If we suspend the job, there is no estimate available
-        job.suspend()
-        self.assertEquals(job.status, JobStatus.SUSPENDED)
+        bq.suspend()
+        self.assertEquals(bq.status, BuildQueueStatus.SUSPENDED)
         self.assertFalse(view.dispatch_time_estimate_available)
 
     def test_old_url_redirection(self):

=== modified file 'lib/lp/soyuz/model/archive.py'
--- lib/lp/soyuz/model/archive.py	2013-11-20 00:23:08 +0000
+++ lib/lp/soyuz/model/archive.py	2013-11-20 00:23:09 +0000
@@ -1922,12 +1922,12 @@
 
         query = """
             UPDATE Job SET status = %s
-            FROM BinaryPackageBuild, BuildPackageJob, BuildQueue
+            FROM BinaryPackageBuild, BuildQueue
             WHERE
                 -- insert self.id here
                 BinaryPackageBuild.archive = %s
-                AND BuildPackageJob.build = BinaryPackageBuild.id
-                AND BuildPackageJob.job = BuildQueue.job
+                AND BuildQueue.build_farm_job =
+                    BinaryPackageBuild.build_farm_job
                 AND Job.id = BuildQueue.job
                 -- Build is in state BuildStatus.NEEDSBUILD (0)
                 AND BinaryPackageBuild.status = %s;
@@ -1940,12 +1940,12 @@
         """Update the pending BuildQueues' statuses for this archive."""
         Store.of(self).execute("""
             UPDATE BuildQueue SET status = %s
-            FROM BinaryPackageBuild, BuildPackageJob
+            FROM BinaryPackageBuild
             WHERE
                 -- insert self.id here
                 BinaryPackageBuild.archive = %s
-                AND BuildPackageJob.build = BinaryPackageBuild.id
-                AND BuildPackageJob.job = BuildQueue.job
+                AND BuildQueue.build_farm_job =
+                    BinaryPackageBuild.build_farm_job
                 -- Build is in state BuildStatus.NEEDSBUILD (0)
                 AND BinaryPackageBuild.status = %s;
             """, params=(status.value, self.id, BuildStatus.NEEDSBUILD.value))

=== modified file 'lib/lp/soyuz/model/buildpackagejob.py'
--- lib/lp/soyuz/model/buildpackagejob.py	2013-11-12 00:12:53 +0000
+++ lib/lp/soyuz/model/buildpackagejob.py	2013-11-20 00:23:09 +0000
@@ -12,13 +12,9 @@
     Reference,
     Storm,
     )
-from zope.component import getUtility
 from zope.interface import implements
 
 from lp.buildmaster.model.buildfarmjob import BuildFarmJobOld
-from lp.services.database.bulk import load_related
-from lp.services.database.interfaces import IStore
-from lp.soyuz.interfaces.binarypackagebuild import IBinaryPackageBuildSet
 from lp.soyuz.interfaces.buildpackagejob import IBuildPackageJob
 
 
@@ -38,19 +34,3 @@
     def __init__(self, build, job):
         self.build, self.job = build, job
         super(BuildPackageJob, self).__init__()
-
-    @staticmethod
-    def preloadBuildFarmJobs(jobs):
-        from lp.soyuz.model.binarypackagebuild import BinaryPackageBuild
-        return list(IStore(BinaryPackageBuild).find(
-            BinaryPackageBuild,
-            [BuildPackageJob.job_id.is_in([job.id for job in jobs]),
-             BuildPackageJob.build_id == BinaryPackageBuild.id]))
-
-    @classmethod
-    def preloadJobsData(cls, jobs):
-        from lp.soyuz.model.binarypackagebuild import BinaryPackageBuild
-        from lp.services.job.model.job import Job
-        load_related(Job, jobs, ['job_id'])
-        builds = load_related(BinaryPackageBuild, jobs, ['build_id'])
-        getUtility(IBinaryPackageBuildSet).preloadBuildsData(list(builds))

=== modified file 'lib/lp/soyuz/scripts/tests/test_populatearchive.py'
--- lib/lp/soyuz/scripts/tests/test_populatearchive.py	2013-09-18 06:34:44 +0000
+++ lib/lp/soyuz/scripts/tests/test_populatearchive.py	2013-11-20 00:23:09 +0000
@@ -12,11 +12,13 @@
 from zope.component import getUtility
 from zope.security.proxy import removeSecurityProxy
 
-from lp.buildmaster.enums import BuildStatus
+from lp.buildmaster.enums import (
+    BuildQueueStatus,
+    BuildStatus,
+    )
 from lp.registry.interfaces.distribution import IDistributionSet
 from lp.registry.interfaces.person import IPersonSet
 from lp.services.config import config
-from lp.services.job.interfaces.job import JobStatus
 from lp.services.log.logger import BufferLogger
 from lp.soyuz.adapters.packagelocation import PackageLocationError
 from lp.soyuz.enums import (
@@ -565,7 +567,7 @@
             """True if the given build is not (pending and suspended)."""
             return not (
                 build.status == BuildStatus.NEEDSBUILD and
-                build.buildqueue_record.job.status == JobStatus.SUSPENDED)
+                build.buildqueue_record.status == BuildQueueStatus.SUSPENDED)
         hoary = getUtility(IDistributionSet)['ubuntu']['hoary']
 
         # Verify that we have the right source packages in the sample data.

=== modified file 'lib/lp/soyuz/templates/build-index.pt'
--- lib/lp/soyuz/templates/build-index.pt	2013-04-17 10:54:01 +0000
+++ lib/lp/soyuz/templates/build-index.pt	2013-11-20 00:23:09 +0000
@@ -164,8 +164,8 @@
       <tal:building condition="context/status/enumvalue:BUILDING">
         <li>
           Started
-          <span tal:attributes="title view/buildqueue/job/date_started/fmt:datetime"
-                tal:content="view/buildqueue/job/date_started/fmt:approximatedate"
+          <span tal:attributes="title view/buildqueue/date_started/fmt:datetime"
+                tal:content="view/buildqueue/date_started/fmt:approximatedate"
             >5 minutes ago</span>
         </li>
       </tal:building>

=== modified file 'lib/lp/translations/model/translationtemplatesbuildjob.py'
--- lib/lp/translations/model/translationtemplatesbuildjob.py	2013-11-15 09:31:08 +0000
+++ lib/lp/translations/model/translationtemplatesbuildjob.py	2013-11-20 00:23:09 +0000
@@ -19,7 +19,6 @@
     BranchJobDerived,
     BranchJobType,
     )
-from lp.services.database.bulk import load_related
 from lp.services.database.interfaces import IStore
 from lp.translations.interfaces.translationtemplatesbuild import (
     ITranslationTemplatesBuildSource,
@@ -92,23 +91,6 @@
         return [cls(branch_job) for branch_job in branch_jobs]
 
     @classmethod
-    def preloadJobsData(cls, jobs):
-        # Circular imports.
-        from lp.code.model.branch import Branch
-        from lp.registry.model.product import Product
-        from lp.code.model.branchcollection import GenericBranchCollection
-        from lp.services.job.model.job import Job
-        from lp.translations.model.translationtemplatesbuild import (
-            TranslationTemplatesBuild,
-            )
-        contexts = [job.context for job in jobs]
-        load_related(Job, contexts, ['jobID'])
-        branches = load_related(Branch, contexts, ['branchID'])
-        GenericBranchCollection.preloadDataForBranches(branches)
-        load_related(Product, branches, ['productID'])
-        load_related(TranslationTemplatesBuild, jobs, ['build_id'])
-
-    @classmethod
     def getByBranch(cls, branch):
         """See `ITranslationTemplatesBuildJobSource`."""
         store = IStore(BranchJob)


Follow ups