Merge lp:~julian-edwards/launchpad/build-queue-sizes-bug-609904 into lp:launchpad

Proposed by Julian Edwards
Status: Merged
Approved by: Māris Fogels
Approved revision: no longer in the source branch.
Merged at revision: 11289
Proposed branch: lp:~julian-edwards/launchpad/build-queue-sizes-bug-609904
Merge into: lp:launchpad
Diff against target: 75 lines (+28/-5)
2 files modified
lib/lp/buildmaster/doc/builder.txt (+21/-1)
lib/lp/buildmaster/model/builder.py (+7/-4)
To merge this branch: bzr merge lp:~julian-edwards/launchpad/build-queue-sizes-bug-609904
Reviewer Review Type Date Requested Status
Māris Fogels (community) code Approve
Review via email: mp+31647@code.launchpad.net

Description of the change

= Summary =
Put pending builds that have virtualized=False in the virtual build queues on
/builders

== Proposed fix ==
IBuilderSet.getBuildQueueSizes() is horribly broken because
BuildQueue.virtualized can be True, False or None. If it's None then the
query will potentially return three groups instead of the expected two, and
because of the bad code in the following "for" loop it will overwrite the
dictionary entry for "nonvirt" depending on which group it sees first in the
results iteration.

== Implementation details ==
Simple fix in the query to coalesce the result so that if it's NULL we turn it
into a True. Also made the inline "if" more explicit.

== Tests ==
bin/test -cvvt builder.txt

== Demo and Q/A ==
Easy to check on edge, there's about 160 pending translations builds
erroneously showing up in the distro builders queue right now!

= Launchpad lint =

Checking for conflicts and issues in changed files.

To post a comment you must log in.
Revision history for this message
Māris Fogels (mars) wrote :

Hi Julian,

I have a bit of difficulty reviewing this without domain-specific knowledge, so I'll trust you that the code is ok. But I did have a question about the tests.

You see, I'm a bit confused by the doc/ directory and the files within. When I am reading a documentation file I don't care what the 'virtualized' flag does, I just care that it exists. I also don't want to read the gritty details of how it behaves correctly when a certain bug is present (which is what the new doctest code is for). The implementation details and bugfix test should be off in a unit test somewhere.

So, is the doctest the right place to exercise the bugfix? What is the purpose of doc/builder.txt?

I'm marking this as 'Needs Information' for now.

Maris

review: Needs Information (code)
Revision history for this message
Julian Edwards (julian-edwards) wrote :

Thanks for the review Maris.

<bigjools> mars: thank you
<bigjools> mars: so, no, the doctest is absolutely not the right place for
that test but I don't have the time to convert that all to unit tests and I am
loathe to write a new unit test and not include the existing ones.

I'm happy to file a cleanup bug about it.

Revision history for this message
Māris Fogels (mars) wrote :

As discussed on IRC: I'm marking this as able to land now, but on the condition that someone be scheduled to rewrite this doctest section into a buildmaster unit test. I am not willing to let the doctests change in this way.

(We probably want an XXX line for bookkeeping and kanban)

Maris

review: Approve (code)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'lib/lp/buildmaster/doc/builder.txt'
2--- lib/lp/buildmaster/doc/builder.txt 2010-06-25 08:45:00 +0000
3+++ lib/lp/buildmaster/doc/builder.txt 2010-08-03 17:51:03 +0000
4@@ -1,3 +1,8 @@
5+XXX Julian 2010-08-03 bug=613096
6+Most of this doctest is really a unit test in disguise. It should get
7+re-written and unit tests moved to buildmaster/tests/test_builder.py
8+
9+
10 =============
11 Builder Class
12 =============
13@@ -173,12 +178,27 @@
14 >>> from lp.soyuz.interfaces.processor import IProcessorFamilySet
15 >>> i386_family = getUtility(IProcessorFamilySet).getByName('x86')
16 >>> recipe_bq.processor = i386_family.processors[0]
17+ >>> recipe_bq.virtualized = True
18+ >>> transaction.commit()
19
20- >>> transaction.commit()
21 >>> queue_sizes = builderset.getBuildQueueSizes()
22 >>> print queue_sizes['virt']['386']
23 (1L, datetime.timedelta(0, 64))
24
25+Any BuildQueues with a null `virtualized` property are considered virtual
26+by default.
27+
28+ >>> recipe_bq = factory.makeSourcePackageRecipeBuildJob()
29+ >>> recipe_bq.virtualized = None
30+ >>> recipe_bq.processor = i386_family.processors[0]
31+ >>> transaction.commit()
32+ >>> queue_sizes = builderset.getBuildQueueSizes()
33+
34+The virtual queue size has increased accordingly:
35+
36+ >>> print queue_sizes['virt']['386']
37+ (2L, datetime.timedelta(0, 128))
38+
39
40 Resuming buildd slaves
41 ======================
42
43=== modified file 'lib/lp/buildmaster/model/builder.py'
44--- lib/lp/buildmaster/model/builder.py 2010-08-02 02:13:52 +0000
45+++ lib/lp/buildmaster/model/builder.py 2010-08-03 17:51:03 +0000
46@@ -24,7 +24,7 @@
47
48 from sqlobject import (
49 BoolCol, ForeignKey, IntCol, SQLObjectNotFound, StringCol)
50-from storm.expr import Count, Sum
51+from storm.expr import Coalesce, Count, Sum
52 from storm.store import Store
53 from zope.component import getUtility
54 from zope.interface import implements
55@@ -704,15 +704,18 @@
56 Count(),
57 Sum(BuildQueue.estimated_duration),
58 Processor,
59- BuildQueue.virtualized),
60+ Coalesce(BuildQueue.virtualized, True)),
61 Processor.id == BuildQueue.processorID,
62 Job.id == BuildQueue.jobID,
63 Job._status == JobStatus.WAITING).group_by(
64- Processor, BuildQueue.virtualized)
65+ Processor, Coalesce(BuildQueue.virtualized, True))
66
67 result_dict = {'virt': {}, 'nonvirt': {}}
68 for size, duration, processor, virtualized in results:
69- virt_str = 'virt' if virtualized else 'nonvirt'
70+ if virtualized is False:
71+ virt_str = 'nonvirt'
72+ else:
73+ virt_str = 'virt'
74 result_dict[virt_str][processor.name] = (
75 size, duration)
76