74
77
from lp.registry.model.person import Person
75
78
from lp.services.job.model.job import Job
76
79
from lp.services.log.logger import PrefixFilter
80
from lp.services.propertycache import cachedproperty
77
81
from lp.services.scripts.base import (
78
82
LaunchpadCronScript,
82
86
from lp.services.session.model import SessionData
83
87
from lp.translations.interfaces.potemplate import IPOTemplateSet
84
88
from lp.translations.model.potranslation import POTranslation
89
from lp.translations.model.potmsgset import POTMsgSet
90
from lp.translations.model.translationmessage import TranslationMessage
91
from lp.translations.model.translationtemplateitem import (
92
TranslationTemplateItem,
87
96
ONE_DAY_IN_SECONDS = 24*60*60
871
class UnusedPOTMsgSetPruner(TunableLoop):
872
"""Cleans up unused POTMsgSets."""
876
maximum_chunk_size = 50000
879
"""See `TunableLoop`."""
880
return self.offset >= len(self.msgset_ids_to_remove)
883
def msgset_ids_to_remove(self):
884
"""Return the IDs of the POTMsgSets to remove."""
886
-- Get all POTMsgSet IDs which are obsolete (sequence == 0)
887
-- and are not used (sequence != 0) in any other template.
888
SELECT DISTINCT POTMsgSet
889
FROM TranslationTemplateItem tti
893
FROM TranslationTemplateItem
894
WHERE potmsgset = tti.potmsgset AND
897
-- Get all POTMsgSet IDs which are not referenced
898
-- by any of the templates (they must have TTI rows for that).
903
FROM TranslationTemplateItem)
906
store = IMasterStore(POTMsgSet)
907
results = store.execute(query)
908
ids_to_remove = [id for (id,) in results.get_all()]
911
def __call__(self, chunk_size):
912
"""See `TunableLoop`."""
913
# We cast chunk_size to an int to avoid issues with slicing
914
# (DBLoopTuner passes in a float).
915
chunk_size = int(chunk_size)
916
msgset_ids_to_remove = (
917
self.msgset_ids_to_remove[self.offset:][:chunk_size])
918
# Remove related TranslationTemplateItems.
919
store = IMasterStore(POTMsgSet)
920
related_ttis = store.find(
921
TranslationTemplateItem,
922
In(TranslationTemplateItem.potmsgsetID, msgset_ids_to_remove))
923
related_ttis.remove()
924
# Remove related TranslationMessages.
925
related_translation_messages = store.find(
927
In(TranslationMessage.potmsgsetID, msgset_ids_to_remove))
928
related_translation_messages.remove()
930
POTMsgSet, In(POTMsgSet.id, msgset_ids_to_remove)).remove()
931
self.offset = self.offset + chunk_size
862
935
class BaseDatabaseGarbageCollector(LaunchpadCronScript):
863
936
"""Abstract base class to run a collection of TunableLoops."""
864
937
script_name = None # Script name for locking and database user. Override.