Merge lp:~jtv/launchpad/bug-872646 into lp:launchpad

Proposed by Jeroen T. Vermeulen
Status: Merged
Approved by: Данило Шеган
Approved revision: no longer in the source branch.
Merged at revision: 14146
Proposed branch: lp:~jtv/launchpad/bug-872646
Merge into: lp:launchpad
Diff against target: 80 lines (+21/-26)
2 files modified
lib/lp/translations/interfaces/translationimportqueue.py (+2/-1)
lib/lp/translations/tests/test_autoapproval.py (+19/-25)
To merge this branch: bzr merge lp:~jtv/launchpad/bug-872646
Reviewer Review Type Date Requested Status
Данило Шеган (community) Approve
Review via email: mp+79053@code.launchpad.net

Commit message

Purge Approved translations uploads after half a year.

Description of the change

= Summary =

Hardy's translations import queue still has a few hundred 8-month-old uploads sitting in its Approved queue, because imports for Hardy have long been disabled. They're just noise in the operational graphs, making it look as if there's something wrong with the importer.

== Proposed fix ==

Set an expiry age of half a year for Approved queue entries. See bug 872646 for my reasoning.

Note that expiry counts from last status change (tests recommended below also cover this) so if for whatever reason an ancient upload suddenly gets approved after a long time of sitting in the needs-review queue, it still gets that full half-year period.

== Pre-implementation notes ==

The code change is easy, since expiry policy is data-driven. All I need now is consensus on the policy change, but I'll need to wait for Europe to wake up. My frank expectation is that people will agree in principle, but may want a different expiry age. If so, I don't see a change in the parameter value affecting review.

== Implementation details ==

The tests for expiry policy hard-coded some statuses. Fully generalized this so that (1) it's more robust against future change and (2) you don't need to read through the repetition to recognize that it does the same thing for multiple statuses.

== Tests ==

{{{
./bin/test -vvc lp.translations.tests.test_autoapproval -t cleanUpObsoleteEntries
}}}

== Demo and Q/A ==

Run the translations import queue gardener (cronscripts/rosetta-approve-imports.py) and see all Approved uploads for Hardy that are more than half a year old disappear. Also watch total counts to verify that nothing else disappears.

= Launchpad lint =

Checking for conflicts and issues in changed files.

Linting changed files:
  lib/lp/translations/interfaces/translationimportqueue.py

To post a comment you must log in.
Revision history for this message
Данило Шеган (danilo) wrote :

Your lint doesn't include all the files, so please run it over the test to ensure it's fine as well. :)
As for the change, it's good, and I don't mind the expiry time you selected: this should affect only unsupported distributions nowadays, so six months is probably as good as any other period.

review: Approve
Revision history for this message
Jeroen T. Vermeulen (jtv) wrote :

Thanks. I realized at the last moment (while writing the MP) that the tests needed some love; I did run “make lint” on those changes, as well as the copyright updater and the imports formatter. :) (Okay, none of them needed any changes. But I ran them.)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'lib/lp/translations/interfaces/translationimportqueue.py'
--- lib/lp/translations/interfaces/translationimportqueue.py 2011-06-16 20:12:00 +0000
+++ lib/lp/translations/interfaces/translationimportqueue.py 2011-10-12 04:13:28 +0000
@@ -1,4 +1,4 @@
1# Copyright 2009-2010 Canonical Ltd. This software is licensed under the1# Copyright 2009-2011 Canonical Ltd. This software is licensed under the
2# GNU Affero General Public License version 3 (see the file LICENSE).2# GNU Affero General Public License version 3 (see the file LICENSE).
33
4# pylint: disable-msg=E0211,E02134# pylint: disable-msg=E0211,E0213
@@ -97,6 +97,7 @@
97# Period after which entries with certain statuses are culled from the97# Period after which entries with certain statuses are culled from the
98# queue.98# queue.
99translation_import_queue_entry_age = {99translation_import_queue_entry_age = {
100 RosettaImportStatus.APPROVED: timedelta(days=DAYS_IN_HALF_YEAR),
100 RosettaImportStatus.DELETED: timedelta(days=3),101 RosettaImportStatus.DELETED: timedelta(days=3),
101 RosettaImportStatus.FAILED: timedelta(days=DAYS_IN_MONTH),102 RosettaImportStatus.FAILED: timedelta(days=DAYS_IN_MONTH),
102 RosettaImportStatus.IMPORTED: timedelta(days=3),103 RosettaImportStatus.IMPORTED: timedelta(days=3),
103104
=== modified file 'lib/lp/translations/tests/test_autoapproval.py'
--- lib/lp/translations/tests/test_autoapproval.py 2011-09-15 11:35:28 +0000
+++ lib/lp/translations/tests/test_autoapproval.py 2011-10-12 04:13:28 +0000
@@ -931,39 +931,33 @@
931 entry.syncUpdate()931 entry.syncUpdate()
932932
933 def test_cleanUpObsoleteEntries_unaffected_statuses(self):933 def test_cleanUpObsoleteEntries_unaffected_statuses(self):
934 # _cleanUpObsoleteEntries leaves entries in some states (i.e.934 # _cleanUpObsoleteEntries leaves entries in states without
935 # Approved and Blocked) alone no matter how old they are.935 # expiry age (currently only Blocked) alone no matter how old
936 one_year_ago = datetime.now(UTC) - timedelta(days=366)936 # they are.
937 unaffected_statuses = (
938 set(RosettaImportStatus.items) -
939 set(translation_import_queue_entry_age.keys()))
940 self.assertNotEqual(
941 0, len(unaffected_statuses),
942 "This test is no longer needed; "
943 "there are no statuses without expiry ages.")
944
945 years_ago = datetime.now(UTC) - timedelta(days=2000)
937 entry = self._makeProductEntry()946 entry = self._makeProductEntry()
938 entry.potemplate = (947 entry.potemplate = self.factory.makePOTemplate(
939 self.factory.makePOTemplate(productseries=entry.productseries))948 productseries=entry.productseries)
940 entry_id = entry.id949 entry_id = entry.id
941950 for status in unaffected_statuses:
942 self._setStatus(entry, RosettaImportStatus.APPROVED, one_year_ago)951 self._setStatus(entry, status, years_ago)
943 # No write or delete action expected, so no reason to switch the952 self.queue._cleanUpObsoleteEntries(self.store)
944 # database user. If it writes or deletes, the test has failed anyway.953 self.assertTrue(self._exists(entry_id))
945 self.queue._cleanUpObsoleteEntries(self.store)
946 self.assertTrue(self._exists(entry_id))
947
948 self._setStatus(entry, RosettaImportStatus.BLOCKED, one_year_ago)
949 # No write or delete action expected, so no reason to switch the
950 # database user. If it writes or deletes, the test has failed anyway.
951 self.queue._cleanUpObsoleteEntries(self.store)
952 self.assertTrue(self._exists(entry_id))
953954
954 def test_cleanUpObsoleteEntries_affected_statuses(self):955 def test_cleanUpObsoleteEntries_affected_statuses(self):
955 # _cleanUpObsoleteEntries deletes entries in terminal states956 # _cleanUpObsoleteEntries deletes entries in terminal states
956 # (Imported, Failed, Deleted) after a few days. The exact957 # (Imported, Failed, Deleted) after a few days. The exact
957 # period depends on the state. Entries in certain other states958 # period depends on the state. Entries in certain other states
958 # get cleaned up after longer periods.959 # get cleaned up after longer periods.
959 affected_statuses = [960 for status in translation_import_queue_entry_age.keys():
960 RosettaImportStatus.DELETED,
961 RosettaImportStatus.FAILED,
962 RosettaImportStatus.IMPORTED,
963 RosettaImportStatus.NEEDS_INFORMATION,
964 RosettaImportStatus.NEEDS_REVIEW,
965 ]
966 for status in affected_statuses:
967 entry = self._makeProductEntry()961 entry = self._makeProductEntry()
968 entry.potemplate = self.factory.makePOTemplate()962 entry.potemplate = self.factory.makePOTemplate()
969 maximum_age = translation_import_queue_entry_age[status]963 maximum_age = translation_import_queue_entry_age[status]