Merge lp:~cjwatson/launchpad/report-pcj-oops-2 into lp:launchpad

Proposed by Colin Watson on 2012-08-10
Status: Merged
Approved by: Colin Watson on 2012-08-13
Approved revision: no longer in the source branch.
Merged at revision: 15803
Proposed branch: lp:~cjwatson/launchpad/report-pcj-oops-2
Merge into: lp:launchpad
Diff against target: 65 lines (+27/-7)
2 files modified
lib/lp/soyuz/model/packagecopyjob.py (+2/-0)
lib/lp/soyuz/tests/test_packagecopyjob.py (+25/-7)
To merge this branch: bzr merge lp:~cjwatson/launchpad/report-pcj-oops-2
Reviewer Review Type Date Requested Status
Benji York (community) code 2012-08-10 Approve on 2012-08-13
Review via email: mp+119209@code.launchpad.net

Commit Message

Commit change to PlainPackageCopyJob.error_message when processing an OOPS.

Description of the Change

== Summary ==

https://code.launchpad.net/~cjwatson/launchpad/report-pcj-oops/+merge/117601 was almost right, but it failed to handle the case of an IntegrityError while committing the results of processing the job, since the transaction that changed PPCJ.error_message was then never committed. This was actually the case encountered by the bug reporter, but I didn't notice it in the test suite because I hadn't managed to write a sufficiently careful test that failed at just the right point and then aborted the transaction.

== Proposed fix ==

If processing an OOPS involves setting PPCJ.error_message, abort before doing so and commit afterwards.

== LOC Rationale ==

+20. Same as https://code.launchpad.net/~cjwatson/launchpad/report-pcj-oops/+merge/117601 (except now I have 4080 lines of credit).

== Tests ==

bin/test -vvct test_packagecopyjob

== Demo and Q/A ==

Same as https://code.launchpad.net/~cjwatson/launchpad/report-pcj-oops/+merge/117601.

To post a comment you must log in.
Benji York (benji) wrote :

Looks good.

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/soyuz/model/packagecopyjob.py'
2--- lib/lp/soyuz/model/packagecopyjob.py 2012-08-08 13:53:44 +0000
3+++ lib/lp/soyuz/model/packagecopyjob.py 2012-08-10 23:28:25 +0000
4@@ -516,10 +516,12 @@
5 def notifyOops(self, oops):
6 """See `IRunnableJob`."""
7 if not self.error_message:
8+ transaction.abort()
9 self.reportFailure(
10 "Launchpad encountered an internal error while copying this"
11 " package. It was logged with id %s. Sorry for the"
12 " inconvenience." % oops["id"])
13+ transaction.commit()
14 super(PlainPackageCopyJob, self).notifyOops(oops)
15
16 def run(self):
17
18=== modified file 'lib/lp/soyuz/tests/test_packagecopyjob.py'
19--- lib/lp/soyuz/tests/test_packagecopyjob.py 2012-08-08 13:53:44 +0000
20+++ lib/lp/soyuz/tests/test_packagecopyjob.py 2012-08-10 23:28:25 +0000
21@@ -420,19 +420,37 @@
22 "Destination pocket must be 'release' for a PPA.",
23 job.error_message)
24
25+ def assertOopsRecorded(self, job):
26+ self.assertEqual(JobStatus.FAILED, job.status)
27+ self.assertThat(
28+ job.error_message, MatchesRegex(
29+ "Launchpad encountered an internal error while copying this"
30+ " package. It was logged with id .*. Sorry for the"
31+ " inconvenience."))
32+
33 def test_target_ppa_message_unexpected_error(self):
34 # When copying to a PPA archive, unexpected errors are stored in the
35 # job's metadata with an apologetic message.
36 job = self.makePPAJob()
37 removeSecurityProxy(job).attemptCopy = FakeMethod(failure=Exception())
38 self.runJob(job)
39- self.assertEqual(JobStatus.FAILED, job.status)
40- self.assertThat(
41- job.error_message,
42- MatchesRegex(
43- "Launchpad encountered an internal error while copying this"
44- " package. It was logged with id .*. Sorry for the"
45- " inconvenience."))
46+ self.assertOopsRecorded(job)
47+
48+ def test_target_ppa_message_integrity_error(self):
49+ # Even database integrity errors (which cause exceptions on commit)
50+ # reliably store an error message in the job's metadata.
51+ job = self.makePPAJob()
52+ spr = self.factory.makeSourcePackageRelease(archive=job.target_archive)
53+
54+ def copy_integrity_error():
55+ """Force an integrity error."""
56+ spr.requestDiffTo(job.requester, spr)
57+
58+ removeSecurityProxy(job).attemptCopy = copy_integrity_error
59+ self.runJob(job)
60+ # Abort the transaction to simulate the job runner script exiting.
61+ transaction.abort()
62+ self.assertOopsRecorded(job)
63
64 def test_run(self):
65 # A proper test run synchronizes packages.