Merge lp:~thumper/launchpad/code-import-event-garbo into lp:launchpad

Proposed by Tim Penhey on 2010-10-17
Status: Merged
Approved by: Robert Collins on 2010-10-17
Approved revision: no longer in the source branch.
Merged at revision: 11738
Proposed branch: lp:~thumper/launchpad/code-import-event-garbo
Merge into: lp:launchpad
Prerequisite: lp:~thumper/launchpad/move-garbo-to-lp
Diff against target: 170 lines (+73/-4)
4 files modified
database/schema/security.cfg (+2/-0)
lib/lp/code/model/codeimportevent.py (+5/-3)
lib/lp/scripts/garbo.py (+36/-1)
lib/lp/scripts/tests/test_garbo.py (+30/-0)
To merge this branch: bzr merge lp:~thumper/launchpad/code-import-event-garbo
Reviewer Review Type Date Requested Status
Robert Collins (community) 2010-10-17 Approve on 2010-10-17
Review via email: mp+38675@code.launchpad.net

Commit Message

Prune CodeImportEvents.

Description of the Change

Add a garbo pruner for the CodeImportEvent table.

To post a comment you must log in.
Robert Collins (lifeless) wrote :

Looks fine to me.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'database/schema/security.cfg'
2--- database/schema/security.cfg 2010-10-08 10:06:11 +0000
3+++ database/schema/security.cfg 2010-10-17 22:58:46 +0000
4@@ -1926,6 +1926,8 @@
5 public.bugtag = SELECT
6 public.bugwatch = SELECT, UPDATE
7 public.bugwatchactivity = SELECT, DELETE
8+public.codeimportevent = SELECT, DELETE
9+public.codeimporteventdata = SELECT, DELETE
10 public.codeimportresult = SELECT, DELETE
11 public.emailaddress = SELECT
12 public.oauthnonce = SELECT, DELETE
13
14=== modified file 'lib/lp/code/model/codeimportevent.py'
15--- lib/lp/code/model/codeimportevent.py 2010-08-20 20:31:18 +0000
16+++ lib/lp/code/model/codeimportevent.py 2010-10-17 22:58:46 +0000
17@@ -20,7 +20,7 @@
18 )
19 from zope.interface import implements
20
21-from canonical.database.constants import DEFAULT
22+from canonical.database.constants import DEFAULT, UTC_NOW
23 from canonical.database.datetimecol import UtcDateTimeCol
24 from canonical.database.enumcol import EnumCol
25 from canonical.database.sqlbase import SQLBase
26@@ -144,12 +144,14 @@
27 data_type=CodeImportEventDataType.MESSAGE,
28 data_value=message)
29
30- def newOnline(self, machine, user=None, message=None):
31+ def newOnline(self, machine, user=None, message=None, _date_created=None):
32 """See `ICodeImportEventSet`."""
33 assert machine is not None, "machine must not be None"
34+ if _date_created is None:
35+ _date_created = UTC_NOW
36 event = CodeImportEvent(
37 event_type=CodeImportEventType.ONLINE,
38- machine=machine, person=user)
39+ machine=machine, person=user, date_created=_date_created)
40 self._recordMessage(event, message)
41 return event
42
43
44=== modified file 'lib/lp/scripts/garbo.py'
45--- lib/lp/scripts/garbo.py 2010-10-03 15:30:06 +0000
46+++ lib/lp/scripts/garbo.py 2010-10-17 22:58:46 +0000
47@@ -4,7 +4,10 @@
48 """Database garbage collection."""
49
50 __metaclass__ = type
51-__all__ = ['DailyDatabaseGarbageCollector', 'HourlyDatabaseGarbageCollector']
52+__all__ = [
53+ 'DailyDatabaseGarbageCollector',
54+ 'HourlyDatabaseGarbageCollector',
55+ ]
56
57 from datetime import (
58 datetime,
59@@ -18,6 +21,7 @@
60 In,
61 Max,
62 Min,
63+ Select,
64 SQL,
65 )
66 import transaction
67@@ -58,6 +62,7 @@
68 )
69 from lp.code.interfaces.revision import IRevisionSet
70 from lp.code.model.branchjob import BranchJob
71+from lp.code.model.codeimportevent import CodeImportEvent
72 from lp.code.model.codeimportresult import CodeImportResult
73 from lp.code.model.revision import (
74 RevisionAuthor,
75@@ -195,6 +200,35 @@
76 transaction.commit()
77
78
79+class CodeImportEventPruner(TunableLoop):
80+ """Prune `CodeImportEvent`s that are more than a month old.
81+
82+ Events that happened more than 30 days ago are really of no interest to us.
83+ """
84+
85+ maximum_chunk_size = 10000
86+ minimum_chunk_size = 500
87+
88+ def isDone(self):
89+ store = IMasterStore(CodeImportEvent)
90+ events = store.find(
91+ CodeImportEvent,
92+ CodeImportEvent.date_created < THIRTY_DAYS_AGO)
93+ return events.any() is None
94+
95+ def __call__(self, chunk_size):
96+ chunk_size = int(chunk_size)
97+ store = IMasterStore(CodeImportEvent)
98+ event_ids = Select(
99+ [CodeImportEvent.id],
100+ CodeImportEvent.date_created < THIRTY_DAYS_AGO,
101+ limit=chunk_size)
102+ num_removed = store.find(
103+ CodeImportEvent, CodeImportEvent.id.is_in(event_ids)).remove()
104+ transaction.commit()
105+ self.log.debug("Removed %d old CodeImportEvents" % num_removed)
106+
107+
108 class CodeImportResultPruner(TunableLoop):
109 """A TunableLoop to prune unwanted CodeImportResult rows.
110
111@@ -850,6 +884,7 @@
112 BranchJobPruner,
113 BugNotificationPruner,
114 BugWatchActivityPruner,
115+ CodeImportEventPruner,
116 CodeImportResultPruner,
117 HWSubmissionEmailLinker,
118 ObsoleteBugAttachmentDeleter,
119
120=== modified file 'lib/lp/scripts/tests/test_garbo.py'
121--- lib/lp/scripts/tests/test_garbo.py 2010-10-17 22:58:44 +0000
122+++ lib/lp/scripts/tests/test_garbo.py 2010-10-17 22:58:46 +0000
123@@ -60,10 +60,12 @@
124 RepositoryFormat,
125 )
126 from lp.code.enums import CodeImportResultStatus
127+from lp.code.interfaces.codeimportevent import ICodeImportEventSet
128 from lp.code.model.branchjob import (
129 BranchJob,
130 BranchUpgradeJob,
131 )
132+from lp.code.model.codeimportevent import CodeImportEvent
133 from lp.code.model.codeimportresult import CodeImportResult
134 from lp.registry.interfaces.person import (
135 IPersonSet,
136@@ -257,6 +259,34 @@
137 Min(CodeImportResult.date_created)).one().replace(tzinfo=UTC)
138 >= now - timedelta(days=30))
139
140+ def test_CodeImportEventPruner(self):
141+ now = datetime.utcnow().replace(tzinfo=UTC)
142+ store = IMasterStore(CodeImportResult)
143+
144+ LaunchpadZopelessLayer.switchDbUser('testadmin')
145+ machine = self.factory.makeCodeImportMachine()
146+ requester = self.factory.makePerson()
147+ # Create 6 code import events for this machine, 3 on each side of 30
148+ # days. Use the event set to the extra event data rows get created too.
149+ event_set = getUtility(ICodeImportEventSet)
150+ for age in (35, 33, 31, 29, 27, 15):
151+ event_set.newOnline(
152+ machine, user=requester, message='Hello',
153+ _date_created=(now - timedelta(days=age)))
154+ transaction.commit()
155+
156+ # Run the garbage collector
157+ self.runDaily()
158+
159+ # Only the three most recent results are left.
160+ events = list(machine.events)
161+ self.assertEqual(3, len(events))
162+ # We now have no CodeImportEvents older than 30 days
163+ self.failUnless(
164+ store.find(
165+ Min(CodeImportEvent.date_created)).one().replace(tzinfo=UTC)
166+ >= now - timedelta(days=30))
167+
168 def test_OpenIDConsumerAssociationPruner(self):
169 pruner = OpenIDConsumerAssociationPruner
170 table_name = pruner.table_name