launchpad-reviewers team mailing list archive
-
launchpad-reviewers team
-
Mailing list archive
-
Message #06957
[Merge] lp:~wgrant/launchpad/bugtaskflat-garbo into lp:launchpad
William Grant has proposed merging lp:~wgrant/launchpad/bugtaskflat-garbo into lp:launchpad with lp:launchpad/db-devel as a prerequisite.
Requested reviews:
Launchpad code reviewers (launchpad-reviewers)
For more details, see:
https://code.launchpad.net/~wgrant/launchpad/bugtaskflat-garbo/+merge/100363
BugTaskFlat will soon exist on production, but it needs to be populated. This is a garbo job to do that, pretty much the same as the bug legacy access mirrorer that I removed a couple of weeks back.
--
https://code.launchpad.net/~wgrant/launchpad/bugtaskflat-garbo/+merge/100363
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~wgrant/launchpad/bugtaskflat-garbo into lp:launchpad.
=== modified file 'lib/lp/scripts/garbo.py'
--- lib/lp/scripts/garbo.py 2012-03-26 22:47:47 +0000
+++ lib/lp/scripts/garbo.py 2012-04-02 07:16:34 +0000
@@ -44,6 +44,7 @@
from lp.bugs.model.bug import Bug
from lp.bugs.model.bugattachment import BugAttachment
from lp.bugs.model.bugnotification import BugNotification
+from lp.bugs.model.bugtask import BugTask
from lp.bugs.model.bugwatch import BugWatchActivity
from lp.bugs.scripts.checkwatches.scheduler import (
BugWatchScheduler,
@@ -81,6 +82,7 @@
from lp.services.librarian.model import TimeLimitedToken
from lp.services.log.logger import PrefixFilter
from lp.services.looptuner import TunableLoop
+from lp.services.memcache.interfaces import IMemcacheClient
from lp.services.oauth.model import OAuthNonce
from lp.services.openid.model.openidconsumer import OpenIDConsumerNonce
from lp.services.propertycache import cachedproperty
@@ -1091,6 +1093,40 @@
self.offset += chunk_size
+class BugTaskFlattener(TunableLoop):
+ """A `TunableLoop` to populate BugTaskFlat for all bugtasks."""
+
+ maximum_chunk_size = 5000
+
+ 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
+
+ def findTaskIDs(self):
+ return IMasterStore(BugTask).find(
+ (BugTask.id,), BugTask.id >= self.start_at).order_by(BugTask.id)
+
+ def isDone(self):
+ return self.findTaskIDs().is_empty()
+
+ def __call__(self, chunk_size):
+ ids = [row[0] for row in self.findTaskIDs()[:chunk_size]]
+ list(IMasterStore(BugTask).using(BugTask).find(
+ SQL('bugtask_flatten(BugTask.id, false)'),
+ BugTask.id.is_in(ids)))
+
+ self.start_at = ids[-1] + 1
+ result = getUtility(IMemcacheClient).set(
+ '%s:bugtask-flattener' % config.instance_name,
+ self.start_at)
+ if not result:
+ self.log.warning('Failed to set start_at in memcache.')
+
+ transaction.commit()
+
+
class BaseDatabaseGarbageCollector(LaunchpadCronScript):
"""Abstract base class to run a collection of TunableLoops."""
script_name = None # Script name for locking and database user. Override.
@@ -1342,6 +1378,7 @@
UnusedSessionPruner,
DuplicateSessionPruner,
BugHeatUpdater,
+ BugTaskFlattener,
]
experimental_tunable_loops = []
=== modified file 'lib/lp/scripts/tests/test_garbo.py'
--- lib/lp/scripts/tests/test_garbo.py 2012-03-26 22:47:47 +0000
+++ lib/lp/scripts/tests/test_garbo.py 2012-04-02 07:16:34 +0000
@@ -42,6 +42,7 @@
BugNotification,
BugNotificationRecipient,
)
+from lp.bugs.model.bugtask import BugTask
from lp.code.bzr import (
BranchFormat,
RepositoryFormat,
@@ -1104,6 +1105,35 @@
self.assertEqual(whiteboard, spec.whiteboard)
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()
+ # 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,),
+ 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()
+ # A watermark is kept in memcache, so a second run doesn't
+ # consider the same task.
+ self.assertIs(
+ None,
+ IMasterStore(BugTask).execute(
+ 'SELECT bugtask FROM BugTaskFlat WHERE bugtask = ?',
+ (task.id,)).get_one())
+
class TestGarboTasks(TestCaseWithFactory):
layer = LaunchpadZopelessLayer