Merge lp:~jtv/launchpad/bug-286237 into lp:launchpad
Status: | Merged | ||||||||
---|---|---|---|---|---|---|---|---|---|
Approved by: | Jeroen T. Vermeulen | ||||||||
Approved revision: | no longer in the source branch. | ||||||||
Merged at revision: | not available | ||||||||
Proposed branch: | lp:~jtv/launchpad/bug-286237 | ||||||||
Merge into: | lp:launchpad | ||||||||
Diff against target: |
754 lines (+279/-94) 14 files modified
lib/lp/translations/browser/tests/test_baseexportview.py (+3/-2) lib/lp/translations/doc/poexport-queue.txt (+6/-5) lib/lp/translations/doc/poexport-request-productseries.txt (+3/-2) lib/lp/translations/doc/poexport-request.txt (+8/-3) lib/lp/translations/doc/poexportqueue-replication-lag.txt (+89/-0) lib/lp/translations/doc/potmsgset.txt (+12/-8) lib/lp/translations/interfaces/poexportrequest.py (+23/-7) lib/lp/translations/interfaces/potmsgset.py (+14/-8) lib/lp/translations/model/poexportrequest.py (+68/-31) lib/lp/translations/model/potmsgset.py (+8/-1) lib/lp/translations/scripts/po_export_queue.py (+10/-24) lib/lp/translations/tests/test_potmsgset.py (+23/-1) lib/lp/translations/tests/test_suggestions.py (+8/-1) lib/lp/translations/tests/test_translatablemessage.py (+4/-1) |
||||||||
To merge this branch: | bzr merge lp:~jtv/launchpad/bug-286237 | ||||||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Guilherme Salgado (community) | Approve | ||
Canonical Launchpad Engineering | code | Pending | |
Review via email: mp+20767@code.launchpad.net |
Commit message
Use slave store for suggestions search & translations export.
Description of the change
= Bugs 286237, =
We're still getting some timeouts from the +translate page because fetching external suggestions is costly, and we're still occasionally seeing big, slow exports. Load on the master database peaks higher than Stuart would like, whereas the slaves don't have this problem and can scale out if needed.
This branch moves these tasks to the slave store. This is very easy for external suggestions, and not too hard but still a bit of work for the export queue. (Luckily I'm spending a lot of time waiting for make schema etc. today).
Some background about the export queue: it lives in the POExportRequest table. The app server adds requests to this queue. If often adds many at a time to cover multiple files; simultaneous requests from the same user are bundled. The export script takes a bundle of requests off the queue and produces exports for them based on the translations data we have.
(A few years ago we modified the export script to service just one request at a time. That was a desperation measure against load problems we had at the time, mainly because of OpenOffice.org. In the meantime, exporting full translations for an Ubuntu package has been restricted a bit; database servers have been upgraded; many problems have been addressed; and OpenOffice.org is no longer translated in Ubuntu. So I made the script do all exports at once again. Not waiting 10 minutes or whatever between exports will probably do wonders for perceived speed of the exports.)
In order to prevent double exports caused by replication lag, the export script now first checks what the oldest live request on the master is. It then considers only that request and newer ones on the slave; older ones have presumably already been deleted, but the slave hasn't noticed it yet. When it's done, it deletes the requests it's done with from the master, and so they certainly won't be selected again on the next call. An extra little doctest goes through this.
I split the queue method popRequest into getRequest and removeRequest. This means that the script only tries to delete the request records after it's processed them. This doesn't matter functionally (everything only happens at commit anyway), but shortens the timespan during which the script holds a transaction with pending changes on the master. If the script holds uncommitted deletes on the queue while processing a request, it may block out app servers trying to add to the queue. Doing it this way should make things run a little more smoothly.
The SQL has also been Stormicated. Deleting items wasn't such smooth sailing: Storm informed me that deleting based on is_in or other expressions is not supported yet. Therefore I executed some raw SQL on the master store (but again in the Storm way, not using cursor). The tests need a few more real commits to allow the master and slave stores to synchronize.
I haven't bothered to recover after an error. If something goes wrong, backing off a bit and waiting for the next cron run is probably a sensible thing to do. If it really piles up, the export pages will mention it to users.
No lint. To test:
{{{
./bin/test -vv -t 'translations.
}}}
To Q/A, verify that external suggestions still appear on +translate pages. Also, request an export on staging and ask for the export script to be run:
{{{
cronscripts/
}}}
This will print a URL to a Librarian file with the exports. Verify that these are alright, e.g. by comparing to a similar export from production.
Jeroen
Hi Jeroen,
This was not a trivial one but your cover letter did a very good job at
explaining what you did. Thanks for taking the time to write it.
I have a few comments/ suggestions below, but r=me
review approve
On Fri, 2010-03-05 at 17:37 +0000, Jeroen T. Vermeulen wrote:
> Jeroen T. Vermeulen has proposed merging lp:~jtv/launchpad/bug-286237 into lp:launchpad/devel.
> === modified file 'lib/lp/ translations/ browser/ tests/test_ baseexportview. py' translations/ browser/ tests/test_ baseexportview. py 2010-02-19 17:06:01 +0000 translations/ browser/ tests/test_ baseexportview. py 2010-03-05 17:38:34 +0000 launchpad. interfaces. lpstorm import IMasterStore launchpad. webapp. servers import LaunchpadTestRe quest eLayer .browser. sourcepackage import ( anslationsExpor tView) .interfaces. translationfile format import ( Format) .model. poexportrequest import POExportRequest POExportRequest ).execute(
> --- lib/lp/
> +++ lib/lp/
> @@ -7,6 +7,7 @@
> import transaction
> import unittest
>
> +from canonical.
> from canonical.
> from canonical.testing import ZopelessDatabas
> from lp.translations
> @@ -15,13 +16,14 @@
> ProductSeriesTr
> from lp.translations
> TranslationFile
> +from lp.translations
> from lp.testing import TestCaseWithFactory
>
>
> def wipe_queue(queue):
> """Erase all export queue entries."""
> - while queue.entry_count > 0:
> - queue.popRequest()
> + queue_ids = IMasterStore(
You don't need to store the queue ids here, do you?
> + "DELETE FROM POExportRequest") ixin(TestCaseWi thFactory) : translations/ doc/poexport- queue.txt' translations/ doc/poexport- queue.txt 2010-02-19 16:02:16 +0000 translations/ doc/poexport- queue.txt 2010-03-05 17:38:34 +0000 queue(fake_ transaction, logging. getLogger( )) commit( ) queue(transacti on, logging. getLogger( )) .../po_ evolution- 2.2.pot request_ set.entry_ count request_ set.addRequest( TranslationFile Format. PO) queue(fake_ transaction, logging. getLogger( )) commit( ) queue(transacti on, logging. getLogger( )) ...eo.po commit( ) librarian_ file(). read() request_ set.addRequest( TranslationFile Format. POCHANGED) queue(fake_ transaction, logging. getLogger( )) commit( ) queue(transacti on, logging. getLogger( )) ...eo.po commit( ) librarian_ file(). read()
>
>
> class BaseExportViewM
>
> === modified file 'lib/lp/
> --- lib/lp/
> +++ lib/lp/
> @@ -275,7 +275,8 @@
>
> Once the queue is processed, the queue is empty again.
>
> - >>> process_
> + >>> transaction.
> + >>> process_
> INFO:...Stored file at http://
>
> >>> export_
> @@ -333,10 +334,10 @@
>
> >>> export_
> ... carlos, pofiles=[pofile], format=
> - >>> process_
> + >>> transaction.
> + >>> process_
> INFO:root:Stored file at http://
>
> - >>> transaction.
> >>> print get_newest_
> # Esperanto translation for ...
> ...
> @@ -354,10 +355,10 @@
>
> >>> export_
> ... carlos, pofiles=[pofile], format=
> - >>> process_
> + >>> transaction.
> + >>> process_
> INFO:root:Stored file at http://
>
> - >>> transaction.
> >>> print get_newest_
> # IMPORTANT: This file does NOT contain a complete PO file structure.
> # DO NOT attempt to import this file b...