launchpad-reviewers team mailing list archive
-
launchpad-reviewers team
-
Mailing list archive
-
Message #07638
[Merge] lp:~wgrant/launchpad/flag-bugtaskflat-garbo into lp:launchpad
William Grant has proposed merging lp:~wgrant/launchpad/flag-bugtaskflat-garbo into lp:launchpad.
Requested reviews:
Launchpad code reviewers (launchpad-reviewers)
Related bugs:
Bug #989209 in Launchpad itself: "Timeout searching ubuntu patches"
https://bugs.launchpad.net/launchpad/+bug/989209
For more details, see:
https://code.launchpad.net/~wgrant/launchpad/flag-bugtaskflat-garbo/+merge/104875
Teach BugTaskFlattener to generate its watermark memcached key from a feature-flagged generation value. This lets us disable the flattener when we don't need it (most of the time) and easily trigger a full regeneration when we make a schema change.
--
https://code.launchpad.net/~wgrant/launchpad/flag-bugtaskflat-garbo/+merge/104875
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~wgrant/launchpad/flag-bugtaskflat-garbo into lp:launchpad.
=== modified file 'lib/lp/scripts/garbo.py'
--- lib/lp/scripts/garbo.py 2012-05-07 00:21:39 +0000
+++ lib/lp/scripts/garbo.py 2012-05-07 07:45:23 +0000
@@ -1128,11 +1128,19 @@
def __init__(self, log, abort_time=None):
super(BugTaskFlattener, self).__init__(log, abort_time)
- watermark = getUtility(IMemcacheClient).get(
- '%s:bugtask-flattener' % config.instance_name)
- self.start_at = watermark or 0
+ generation = getFeatureFlag('bugs.bugtaskflattener.generation')
+ if generation is None:
+ self.start_at = None
+ else:
+ self.memcache_key = (
+ '%s:bugtask-flattener:%s'
+ % (config.instance_name, generation.encode('utf-8')))
+ watermark = getUtility(IMemcacheClient).get(self.memcache_key)
+ self.start_at = watermark or 0
def findTaskIDs(self):
+ if self.start_at is None:
+ return EmptyResultSet()
return IMasterStore(BugTask).find(
(BugTask.id,), BugTask.id >= self.start_at).order_by(BugTask.id)
@@ -1147,8 +1155,7 @@
self.start_at = ids[-1] + 1
result = getUtility(IMemcacheClient).set(
- '%s:bugtask-flattener' % config.instance_name,
- self.start_at)
+ self.memcache_key, self.start_at)
if not result:
self.log.warning('Failed to set start_at in memcache.')
=== modified file 'lib/lp/scripts/tests/test_garbo.py'
--- lib/lp/scripts/tests/test_garbo.py 2012-05-04 06:24:08 +0000
+++ lib/lp/scripts/tests/test_garbo.py 2012-05-07 07:45:23 +0000
@@ -109,7 +109,10 @@
TestCase,
TestCaseWithFactory,
)
-from lp.testing.dbuser import switch_dbuser
+from lp.testing.dbuser import (
+ dbuser,
+ switch_dbuser,
+ )
from lp.testing.layers import (
DatabaseLayer,
LaunchpadScriptLayer,
@@ -1107,33 +1110,45 @@
self.assertEqual(0, spec.work_items.count())
def test_BugTaskFlattener(self):
- # Private bugs without corresponding data in the access policy
- # schema get mirrored.
- switch_dbuser('testadmin')
- task = self.factory.makeBugTask()
+ # Bugs without a record in BugTaskFlat get mirrored.
# Remove the existing mirrored data.
- IMasterStore(BugTask).execute(
- 'DELETE FROM BugTaskFlat WHERE bugtask = ?', (task.id,))
- transaction.commit()
- self.runHourly()
- # Check that there's a record again, and delete it.
- switch_dbuser('testadmin')
- self.assertEqual(
- (task.id,),
+ with dbuser('testadmin'):
+ task = self.factory.makeBugTask()
IMasterStore(BugTask).execute(
+ 'DELETE FROM BugTaskFlat WHERE bugtask = ?', (task.id,))
+
+ def get_flat():
+ return IMasterStore(BugTask).execute(
'SELECT bugtask FROM BugTaskFlat WHERE bugtask = ?',
- (task.id,)).get_one())
- IMasterStore(BugTask).execute(
- 'DELETE FROM BugTaskFlat WHERE bugtask = ?', (task.id,))
- transaction.commit()
- self.runHourly()
+ (task.id,)).get_one()
+
+ # Nothing is done until the feature flag is set.
+ self.runHourly()
+ self.assertIs(None, get_flat())
+
+ # If we set the generation flag, the bug will be mirrored.
+ with dbuser('testadmin'):
+ IMasterStore(FeatureFlag).add(FeatureFlag(
+ u'default', 0, u'bugs.bugtaskflattener.generation', u'1'))
+ self.runHourly()
+ self.assertEqual((task.id,), get_flat())
+
# A watermark is kept in memcache, so a second run doesn't
# consider the same task.
- self.assertIs(
- None,
+ with dbuser('testadmin'):
IMasterStore(BugTask).execute(
- 'SELECT bugtask FROM BugTaskFlat WHERE bugtask = ?',
- (task.id,)).get_one())
+ 'DELETE FROM BugTaskFlat WHERE bugtask = ?', (task.id,))
+ self.runHourly()
+ self.assertIs(None, get_flat())
+
+ # Incrementing the generation feature flag causes a fresh pass.
+ with dbuser('testadmin'):
+ IMasterStore(FeatureFlag).find(
+ FeatureFlag, flag=u'bugs.bugtaskflattener.generation').remove()
+ IMasterStore(FeatureFlag).add(FeatureFlag(
+ u'default', 1, u'bugs.bugtaskflattener.generation', u'2'))
+ self.runHourly()
+ self.assertEqual((task.id,), get_flat())
def test_BranchInformationTypeMigrator_public(self):
# A non-migrated public branch will have information_type set
=== modified file 'lib/lp/services/features/flags.py'
--- lib/lp/services/features/flags.py 2012-05-01 07:31:48 +0000
+++ lib/lp/services/features/flags.py 2012-05-07 07:45:23 +0000
@@ -63,6 +63,14 @@
'',
'',
'https://bugs.launchpad.net/launchpad/+bug/678090'),
+ ('bugs.bugtaskflattener.generation',
+ 'string',
+ ("Sets the key used to store progress in a BugTaskFlat update pass. "
+ "Normally disabled unless recent schema changes require a full "
+ "update."),
+ 'BugTaskFlattener disabled',
+ '',
+ ''),
('bugs.bugtracker_components.enabled',
'boolean',
('Enables the display of bugtracker components.'),
Follow ups