Merge lp:~abentley/launchpad/celery-everywhere-6 into lp:launchpad

Proposed by Aaron Bentley on 2012-04-24
Status: Merged
Approved by: Aaron Bentley on 2012-04-24
Approved revision: no longer in the source branch.
Merged at revision: 15147
Proposed branch: lp:~abentley/launchpad/celery-everywhere-6
Merge into: lp:launchpad
Prerequisite: lp:~abentley/launchpad/celery-everywhere-5
Diff against target: 215 lines (+112/-3)
5 files modified
lib/lp/services/job/model/job.py (+6/-1)
lib/lp/services/job/tests/__init__.py (+2/-0)
lib/lp/translations/model/translationpackagingjob.py (+7/-0)
lib/lp/translations/model/translationsharingjob.py (+6/-1)
lib/lp/translations/tests/test_translationpackagingjob.py (+91/-1)
To merge this branch: bzr merge lp:~abentley/launchpad/celery-everywhere-6
Reviewer Review Type Date Requested Status
Deryck Hodge (community) 2012-04-24 Approve on 2012-04-24
Review via email: mp+103346@code.launchpad.net

Commit Message

Support running translation sharing jobs via Celery.

Description of the Change

= Summary =
Support running TranslationSharingJob via Celery

== Pre-implementation notes ==
None

== LOC Rationale ==
Part of a resourced arc that will ultimately reduce LOC.

== Implementation details ==
TranslationSharingJobDerived.create now schedules jobs to run via celery.

All TranslationSharingJobDerived subclasses now have a config member. (These are currently the same, but should eventually be different.)

UniversalJobSource can now return TranslationSharingJob jobs.

Better error handling in block_on_job.

== Tests ==
bin/test test_translationpackagingjob --layer=CeleryJobLayer

== Demo and Q/A ==
None

= Launchpad lint =

Checking for conflicts and issues in changed files.

Linting changed files:
  lib/lp/soyuz/model/distroseriesdifferencejob.py
  lib/lp/soyuz/model/distributionjob.py
  lib/lp/bugs/model/apportjob.py
  lib/lp/translations/model/translationsharingjob.py
  lib/lp/soyuz/tests/test_initializedistroseriesjob.py
  lib/lp/testing/factory.py
  lib/lp/services/job/tests/test_job.py
  lib/lp/translations/model/translationpackagingjob.py
  lib/lp/soyuz/model/initializedistroseriesjob.py
  lib/lp/translations/tests/test_translationpackagingjob.py
  lib/lp/soyuz/tests/test_distroseriesdifferencejob.py
  lib/lp/bugs/tests/test_apportjob.py
  lib/lp/services/job/model/job.py
  lib/lp/services/job/tests/__init__.py

To post a comment you must log in.
Deryck Hodge (deryck) wrote :

Looks good to me! Thanks! Another job type ready for the new hotness. :)

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'lib/lp/services/job/model/job.py'
2--- lib/lp/services/job/model/job.py 2012-04-24 18:49:01 +0000
3+++ lib/lp/services/job/model/job.py 2012-04-24 18:49:29 +0000
4@@ -277,11 +277,16 @@
5 BranchMergeProposalJob,
6 )
7 from lp.soyuz.model.distributionjob import DistributionJob
8+ from lp.translations.model.translationsharingjob import (
9+ TranslationSharingJob,
10+ )
11 dbconfig.override(
12 dbuser=config.launchpad.dbuser, isolation_level='read_committed')
13
14 for baseclass in [
15- ApportJob, BranchJob, BranchMergeProposalJob, DistributionJob]:
16+ ApportJob, BranchJob, BranchMergeProposalJob, DistributionJob,
17+ TranslationSharingJob,
18+ ]:
19 derived, base_class, store = cls._getDerived(job_id, baseclass)
20 if derived is not None:
21 cls.clearStore(store)
22
23=== modified file 'lib/lp/services/job/tests/__init__.py'
24--- lib/lp/services/job/tests/__init__.py 2012-04-24 18:49:01 +0000
25+++ lib/lp/services/job/tests/__init__.py 2012-04-24 18:49:29 +0000
26@@ -58,6 +58,8 @@
27 with CaptureOops() as capture:
28 with monitor_celery() as responses:
29 yield
30+ if len(responses) == 0:
31+ raise Exception('No Job was requested to run via Celery.')
32 try:
33 responses[-1].wait(30)
34 finally:
35
36=== modified file 'lib/lp/translations/model/translationpackagingjob.py'
37--- lib/lp/translations/model/translationpackagingjob.py 2011-11-07 11:21:05 +0000
38+++ lib/lp/translations/model/translationpackagingjob.py 2012-04-24 18:49:29 +0000
39@@ -26,6 +26,7 @@
40 implements,
41 )
42
43+from lp.services.config import config
44 from lp.services.job.interfaces.job import IRunnableJob
45 from lp.services.job.runner import BaseRunnableJob
46 from lp.translations.interfaces.translationpackagingjob import (
47@@ -88,6 +89,8 @@
48
49 create_on_event = IObjectCreatedEvent
50
51+ config = config.packaging_translations
52+
53 def run(self):
54 """See `IRunnableJob`."""
55 logger = logging.getLogger()
56@@ -113,6 +116,8 @@
57
58 create_on_event = IObjectDeletedEvent
59
60+ config = config.packaging_translations
61+
62 def run(self):
63 """See `IRunnableJob`."""
64 logger = logging.getLogger()
65@@ -131,6 +136,8 @@
66
67 create_on_event = IObjectModifiedEvent
68
69+ config = config.packaging_translations
70+
71 @classmethod
72 def forPOTemplate(cls, potemplate):
73 """Create a TranslationTemplateChangeJob for a POTemplate.
74
75=== modified file 'lib/lp/translations/model/translationsharingjob.py'
76--- lib/lp/translations/model/translationsharingjob.py 2012-03-22 19:17:45 +0000
77+++ lib/lp/translations/model/translationsharingjob.py 2012-04-24 18:49:29 +0000
78@@ -110,6 +110,9 @@
79 self.productseries = productseries
80 self.potemplate = potemplate
81
82+ def makeDerived(self):
83+ return TranslationSharingJobDerived.makeSubclass(self)
84+
85
86 class TranslationSharingJobDerived:
87 """Base class for specialized TranslationTemplate Job types."""
88@@ -154,7 +157,9 @@
89 context = TranslationSharingJob(
90 Job(), cls.class_job_type, productseries,
91 distroseries, sourcepackagename, potemplate)
92- return cls(context)
93+ derived = cls(context)
94+ derived.celeryRunOnCommit()
95+ return derived
96
97 @classmethod
98 def schedulePackagingJob(cls, packaging, event):
99
100=== modified file 'lib/lp/translations/tests/test_translationpackagingjob.py'
101--- lib/lp/translations/tests/test_translationpackagingjob.py 2012-03-26 13:09:30 +0000
102+++ lib/lp/translations/tests/test_translationpackagingjob.py 2012-04-24 18:49:29 +0000
103@@ -13,17 +13,23 @@
104 from zope.event import notify
105
106 from lp.registry.interfaces.packaging import IPackagingUtil
107+from lp.services.features.testing import FeatureFixture
108 from lp.services.job.interfaces.job import (
109 IRunnableJob,
110 JobStatus,
111 )
112+from lp.services.job.tests import block_on_job
113 from lp.services.webapp.testing import verifyObject
114 from lp.testing import (
115+ celebrity_logged_in,
116 EventRecorder,
117 person_logged_in,
118 TestCaseWithFactory,
119 )
120-from lp.testing.layers import LaunchpadZopelessLayer
121+from lp.testing.layers import (
122+ CeleryJobLayer,
123+ LaunchpadZopelessLayer,
124+ )
125 from lp.translations.interfaces.potemplate import IPOTemplate
126 from lp.translations.interfaces.side import TranslationSide
127 from lp.translations.interfaces.translationpackagingjob import (
128@@ -349,3 +355,87 @@
129 [tm.translations for tm in potmsgset.getAllTranslationMessages()],
130 [tm.translations
131 for tm in new_potmsgset.getAllTranslationMessages()])
132+
133+
134+class TestViaCelery(TestCaseWithFactory):
135+
136+ layer = CeleryJobLayer
137+
138+ def test_TranslationMergeJob(self):
139+ """TranslationMergeJob runs under Celery."""
140+ self.useFixture(FeatureFixture({
141+ 'jobs.celery.enabled_classes': 'TranslationMergeJob',
142+ }))
143+ job = make_translation_merge_job(self.factory)
144+ product_msg = get_msg_sets(productseries=job.productseries)
145+ package_msg = get_msg_sets(
146+ sourcepackagename=job.sourcepackagename,
147+ distroseries=job.distroseries)
148+ with block_on_job(self):
149+ transaction.commit()
150+ product_msg = get_msg_sets(productseries=job.productseries)
151+ package_msg = get_msg_sets(
152+ sourcepackagename=job.sourcepackagename,
153+ distroseries=job.distroseries)
154+ self.assertEqual(package_msg, product_msg)
155+
156+ def test_TranslationSplitJob(self):
157+ """Ensure TranslationSplitJob runs under Celery."""
158+ self.useFixture(FeatureFixture({
159+ 'jobs.celery.enabled_classes': 'TranslationSplitJob',
160+ }))
161+ upstream_item, ubuntu_item = make_shared_potmsgset(self.factory)
162+ TranslationSplitJob.create(
163+ upstream_item.potemplate.productseries,
164+ ubuntu_item.potemplate.distroseries,
165+ ubuntu_item.potemplate.sourcepackagename,
166+ )
167+ self.assertEqual(upstream_item.potmsgset, ubuntu_item.potmsgset)
168+ with block_on_job(self):
169+ transaction.commit()
170+ self.assertNotEqual(upstream_item.potmsgset, ubuntu_item.potmsgset)
171+
172+ def test_TranslationTemplateChangeJob(self):
173+ """Ensure TranslationTemplateChangeJob runs under Celery."""
174+ self.useFixture(FeatureFixture({
175+ 'jobs.celery.enabled_classes': 'TranslationTemplateChangeJob',
176+ }))
177+ potemplate = self.factory.makePOTemplate(name='template')
178+ other_ps = self.factory.makeProductSeries(
179+ product=potemplate.productseries.product)
180+ old_shared = self.factory.makePOTemplate(name='template',
181+ productseries=other_ps)
182+ new_shared = self.factory.makePOTemplate(name='renamed',
183+ productseries=other_ps)
184+
185+ # Set up shared POTMsgSets and translations.
186+ potmsgset = self.factory.makePOTMsgSet(potemplate, sequence=1)
187+ potmsgset.setSequence(old_shared, 1)
188+ self.factory.makeCurrentTranslationMessage(potmsgset=potmsgset)
189+
190+ # This is the identical English message in the new_shared template.
191+ target_potmsgset = self.factory.makePOTMsgSet(
192+ new_shared, sequence=1, singular=potmsgset.singular_text)
193+
194+ # Rename the template and confirm that messages are now shared
195+ # with new_shared instead of old_shared.
196+ with celebrity_logged_in('admin'):
197+ potemplate.name = 'renamed'
198+ TranslationTemplateChangeJob.create(potemplate=potemplate)
199+
200+ with block_on_job(self):
201+ transaction.commit()
202+
203+ # New POTMsgSet is now different from the old one (it's been split),
204+ # but matches the target potmsgset (it's been merged into it).
205+ new_potmsgset = potemplate.getPOTMsgSets()[0]
206+ old_potmsgset = old_shared.getPOTMsgSets()[0]
207+ target_potmsgset = new_shared.getPOTMsgSets()[0]
208+ self.assertNotEqual(old_potmsgset, new_potmsgset)
209+ self.assertEqual(target_potmsgset, new_potmsgset)
210+
211+ # Translations have been merged as well.
212+ self.assertContentEqual(
213+ [tm.translations for tm in potmsgset.getAllTranslationMessages()],
214+ [tm.translations
215+ for tm in new_potmsgset.getAllTranslationMessages()])