Merge lp:~wgrant/launchpad/bug-761439 into lp:launchpad

Proposed by William Grant
Status: Merged
Approved by: William Grant
Approved revision: no longer in the source branch.
Merged at revision: 12938
Proposed branch: lp:~wgrant/launchpad/bug-761439
Merge into: lp:launchpad
Diff against target: 90 lines (+47/-0)
2 files modified
lib/lp/soyuz/scripts/processaccepted.py (+9/-0)
lib/lp/soyuz/tests/test_processaccepted.py (+38/-0)
To merge this branch: bzr merge lp:~wgrant/launchpad/bug-761439
Reviewer Review Type Date Requested Status
Steve Kowalik (community) Approve
Review via email: mp+59317@code.launchpad.net

Commit message

[r=stevenk][bug=761439] process-accepted now commits after processing each upload.

Description of the change

Bug #761439 is caused by process-accepted not committing after each item is processed: sometimes they create library files that later items need to read, which can't happen before the transaction is committed. This branch changes process-accepted to commit after each upload, even on failure.

It seems unintuitive to commit on failure, but process-accepted makes changes to the on-disk archive. We can't roll back filesystem changes, so we need to commit a potentially partial acceptance to the DB too. The test is a bit awkward: a transaction synchronizer keeps track of the number of commits and ensures that only one item is processed per commit.

I've also added some more logging to process-accepted, to ease identification of the current queue item.

To post a comment you must log in.
Revision history for this message
William Grant (wgrant) wrote :

(Note that it already committed on failure anyway, just all in one huge transaction.)

Revision history for this message
Steve Kowalik (stevenk) wrote :

I agree the test is a little awkward, but I welcome the change, and more logging is nice.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'lib/lp/soyuz/scripts/processaccepted.py'
2--- lib/lp/soyuz/scripts/processaccepted.py 2010-09-23 02:12:27 +0000
3+++ lib/lp/soyuz/scripts/processaccepted.py 2011-04-28 05:36:31 +0000
4@@ -268,6 +268,8 @@
5 queue_items = distroseries.getQueueItems(
6 PackageUploadStatus.ACCEPTED, archive=archive)
7 for queue_item in queue_items:
8+ self.logger.debug(
9+ "Processing queue item %d" % queue_item.id)
10 try:
11 queue_item.realiseUpload(self.logger)
12 except Exception:
13@@ -280,7 +282,14 @@
14 self.logger.error('%s (%s)' % (message,
15 request.oopsid))
16 else:
17+ self.logger.debug(
18+ "Successfully processed queue item %d" %
19+ queue_item.id)
20 processed_queue_ids.append(queue_item.id)
21+ # Commit even on error; we may have altered the
22+ # on-disk archive, so the partial state must
23+ # make it to the DB.
24+ self.txn.commit()
25
26 if not self.options.dryrun:
27 self.txn.commit()
28
29=== modified file 'lib/lp/soyuz/tests/test_processaccepted.py'
30--- lib/lp/soyuz/tests/test_processaccepted.py 2011-03-03 00:43:44 +0000
31+++ lib/lp/soyuz/tests/test_processaccepted.py 2011-04-28 05:36:31 +0000
32@@ -6,6 +6,7 @@
33 from cStringIO import StringIO
34
35 from debian.deb822 import Changes
36+from testtools.matchers import LessThan
37
38 from canonical.config import config
39 from canonical.launchpad.webapp.errorlog import ErrorReportingUtility
40@@ -15,6 +16,7 @@
41 from lp.soyuz.enums import (
42 ArchivePurpose,
43 PackagePublishingStatus,
44+ PackageUploadStatus,
45 )
46 from lp.soyuz.scripts.processaccepted import (
47 get_bugs_from_changes_file,
48@@ -131,6 +133,42 @@
49 published_copy.status, PackagePublishingStatus.PENDING)
50 self.assertEqual(copy_source, published_copy.sourcepackagerelease)
51
52+ def test_commits_after_each_item(self):
53+ # Test that the script commits after each item, not just at the end.
54+ uploads = [
55+ self.createWaitingAcceptancePackage(
56+ distroseries=
57+ self.factory.makeDistroSeries(distribution=self.distro),
58+ sourcename='source%d' % i)
59+ for i in range(3)]
60+
61+ class UploadCheckingSynchronizer:
62+
63+ commit_count = 0
64+
65+ def beforeCompletion(inner_self, txn):
66+ pass
67+
68+ def afterCompletion(inner_self, txn):
69+ if txn.status != 'Committed':
70+ return
71+ inner_self.commit_count += 1
72+ done_count = len([
73+ upload for upload in uploads
74+ if upload.package_upload.status ==
75+ PackageUploadStatus.DONE])
76+ self.assertEqual(
77+ min(len(uploads), inner_self.commit_count),
78+ done_count)
79+
80+ script = self.getScript([])
81+ self.layer.txn.commit()
82+ self.layer.switchDbUser(self.dbuser)
83+ synch = UploadCheckingSynchronizer()
84+ script.txn.registerSynch(synch)
85+ script.main()
86+ self.assertThat(len(uploads), LessThan(synch.commit_count))
87+
88
89 class TestBugsFromChangesFile(TestCaseWithFactory):
90 """Test get_bugs_from_changes_file."""